Skip to content

Conversation

@andyleiserson
Copy link
Contributor

@andyleiserson andyleiserson commented Oct 2, 2025

This resolves the duplicate storage of Id and Arc versions of commands when tracing that was introduced by encode-on-finish. It now stores the Arc version only, and uses the pointers from the Arcs as object IDs when tracing. It also overhauls the trace player to play back traces in this format.

This fixes tracing of compute and render passes when encoded using the standard APIs. Tracing of render bundles is still broken.

Testing
TBD. Existing player tests, manual tests, and it would be nice to have an automated test of recording a trace but I don't think we do right now.

Squash or Rebase? Rebase, after squashing fixups.

Checklist

  • Run cargo fmt.
  • Run taplo format.
  • Run cargo clippy --tests. If applicable, add:
    • --target wasm32-unknown-unknown
  • Run cargo xtask test to run tests.
  • If this contains user-facing changes, add a CHANGELOG.md entry.

@andyleiserson
Copy link
Contributor Author

This does have all my latest local changes, but there's still a little work to do to fix the CI failures, and I want to revisit the way that polling and user_closures are handled.

// this check can't go in the body of `create_bind_group_layout` since the closure might not get called
if let Err(e) = device.check_is_valid() {
break 'error e.into();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this check since create_bind_group_layout now contains it as well.

Ok(submit_index)
}

pub fn get_mapped_range(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_mapped_range on the global is not calling this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for catching this, I missed updating it to call the extracted version.

hashbrown.workspace = true
indexmap.workspace = true
log.workspace = true
macro_rules_attribute.workspace = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can gate this dependency behind the serde feature.

Comment on lines 161 to 164
// Unfortunately, because `Arc::as_ptr` returns a pointer to the
// contained data, and `Arc` stores reference counts before the data,
// we are adding an offset to the pointer here.
Self(Arc::as_ptr(arc) as usize, PhantomData)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of date comment?

Copy link
Contributor Author

@andyleiserson andyleiserson Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will clarify it. The issue is that Arc::as_ptr is not doing the equivalent of arc.inner as *const ArcInner<T> (where arc: &Arc<T>), it is doing &arc.inner.data as *const T, which is located at an offset of 16 from the base address of the ArcInner.

Comment on lines 232 to 240
#[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
//#[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
color: u32,
len: usize,
},

PopDebugGroup,

InsertDebugMarker {
#[cfg_attr(not(any(feature = "serde", feature = "replay")), allow(dead_code))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like we kept those guards for the render pass, but not here.

Comment on lines 432 to 449
fn resolve_buffer_id(
&self,
id: wgc::id::PointerId<wgc::id::markers::Buffer>,
) -> Arc<wgc::resource::Buffer> {
self.buffers.get(&id).expect("invalid buffer").clone()
}

pub fn get_buffer(
&self,
id: wgc::id::PointerId<wgc::id::markers::Buffer>,
) -> Arc<wgc::resource::Buffer> {
self.resolve_buffer_id(id)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need both functions?

Comment on lines 157 to 166
let external_texture = self
.external_textures
.remove(&id)
.expect("invalid external texture");
external_texture.destroy();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the free functions should remove the resource from the map since the spec says it's ok to call destroy multiple times.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the naming is confusing because a traced "free" is a destroy, and a traced "destroy" is a drop. I had fixed this for buffers and textures when tracing boat attack, but I missed external textures. I'll also add a comment about the naming mismatch.

@teoxoy
Copy link
Member

teoxoy commented Oct 13, 2025

I wanted to mention that the main difference I noticed between this approach and the previous is that we now effectively only record commands after successful validation. I find that this somewhat limits the usefulness of recording and replaying traces since they won't record invalid commands.

I've mostly used the record/replay functionality to debug overly restrictive or wrong validation in Firefox which will no longer be possible with this PR.

We should probably talk about this at the maintainers meeting.

@teoxoy
Copy link
Member

teoxoy commented Oct 15, 2025

We talked a bit about this at the maintainers meeting. Would it be possible to trace before validation runs (so that invalid commands get included in the trace)?

@teoxoy
Copy link
Member

teoxoy commented Oct 17, 2025

I just realized Fallible::Invalid also has type Arc<String> - we could use that address to be able to record before validation.

@andyleiserson
Copy link
Contributor Author

Since this PR is already quite large, I opened #8429 for the error tracing support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants