diff --git a/README.md b/README.md index c59a93a37ca..a16a36f7699 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ The implementation consists of the following parts: - `wgpu-core` - internal Rust API for WebGPU implementations to use - `wgpu-types` - Rust types shared between `wgpu-core`, `wgpu-native`, and `wgpu-rs` + - `player` - application for replaying the API traces, uses `winit` This repository is not meant for direct use by applications. If you are looking for the user-facing Rust API, you need [wgpu-rs](https://github.com/gfx-rs/wgpu-rs). diff --git a/player/README.md b/player/README.md new file mode 100644 index 00000000000..bd73b8b71fd --- /dev/null +++ b/player/README.md @@ -0,0 +1,12 @@ +# wgpu player + +This is application that allows replaying the `wgpu` workloads recorded elsewhere. + +Launch as: +```rust +player +``` + +When built with "winit" feature, it's able to replay the workloads that operate on a swapchain. It renders each frame consequently, then waits for the user to close the window. When built without "winit", it launches in console mode and can replay any trace that doesn't use swapchains. + +Note: replaying is currently restricted to the same backend, as one used for recording a trace. It is straightforward, however, to just replace the backend in RON, since it's serialized as plain text. Valid values are: Vulkan, Metal, Dx12, and Dx11. diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 8d35b94934b..bd6d3b4f6c3 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -33,7 +33,7 @@ pub enum ComputeCommand { index: u8, num_dynamic_offsets: u8, bind_group_id: id::BindGroupId, - #[cfg_attr(feature = "serde", serde(skip))] + #[cfg_attr(any(feature = "trace", feature = "replay"), serde(skip))] phantom_offsets: PhantomSlice, }, SetPipeline(id::ComputePipelineId), diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 6c8b0222de0..9d445559ae5 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -63,7 +63,7 @@ pub enum RenderCommand { index: u8, num_dynamic_offsets: u8, bind_group_id: id::BindGroupId, - #[cfg_attr(feature = "serde", serde(skip))] + #[cfg_attr(any(feature = "trace", feature = "replay"), serde(skip))] phantom_offsets: PhantomSlice, }, SetPipeline(id::RenderPipelineId), diff --git a/wgpu-core/src/id.rs b/wgpu-core/src/id.rs index 966d1eb6db4..bdcd434b701 100644 --- a/wgpu-core/src/id.rs +++ b/wgpu-core/src/id.rs @@ -11,9 +11,37 @@ const EPOCH_MASK: u32 = (1 << (32 - BACKEND_BITS)) - 1; type Dummy = crate::backend::Empty; #[repr(transparent)] +#[cfg_attr(feature = "trace", derive(serde::Serialize), serde(into = "SerialId"))] +#[cfg_attr( + feature = "replay", + derive(serde::Deserialize), + serde(from = "SerialId") +)] +pub struct Id(NonZeroU64, PhantomData); + +// This type represents Id in a more readable (and editabble) way. +#[allow(dead_code)] #[cfg_attr(feature = "trace", derive(serde::Serialize))] #[cfg_attr(feature = "replay", derive(serde::Deserialize))] -pub struct Id(NonZeroU64, PhantomData); +enum SerialId { + // The only variant forces RON to not ignore "Id" + Id(Index, Epoch, Backend), +} +#[cfg(feature = "trace")] +impl From> for SerialId { + fn from(id: Id) -> Self { + let (index, epoch, backend) = id.unzip(); + SerialId::Id(index, epoch, backend) + } +} +#[cfg(feature = "replay")] +impl From for Id { + fn from(id: SerialId) -> Self { + match id { + SerialId::Id(index, epoch, backend) => TypedId::zip(index, epoch, backend), + } + } +} // required for PeekPoke impl Default for Id {