wgpu_core/device/
trace.rs

1#[cfg(feature = "trace")]
2mod record;
3#[cfg(feature = "replay")]
4mod replay;
5
6use core::convert::Infallible;
7
8use alloc::{string::String, vec::Vec};
9use macro_rules_attribute::apply;
10
11use crate::{
12    command::{serde_object_reference_struct, BasePass, Command, ReferenceType, RenderCommand},
13    id::{markers, PointerId},
14    pipeline::GeneralRenderPipelineDescriptor,
15};
16
17#[cfg(feature = "trace")]
18pub use record::*;
19#[cfg(feature = "replay")]
20pub use replay::*;
21
22type FileName = String;
23
24pub const FILE_NAME: &str = "trace.ron";
25
26#[derive(Debug)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum Data {
29    File(FileName),
30    String(DataKind, String),
31    Binary(DataKind, Vec<u8>),
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35#[cfg_attr(
36    feature = "serde",
37    derive(serde::Serialize, serde::Deserialize),
38    serde(rename_all = "lowercase")
39)]
40pub enum DataKind {
41    Bin,
42    Wgsl,
43
44    /// IR of Naga module, serialized in RON format
45    Ron,
46    Spv,
47    Dxil,
48    Hlsl,
49    MetalLib,
50    Msl,
51    Glsl,
52}
53
54impl core::fmt::Display for DataKind {
55    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
56        let s = match self {
57            DataKind::Bin => "bin",
58            DataKind::Wgsl => "wgsl",
59            DataKind::Ron => "ron",
60            DataKind::Spv => "spv",
61            DataKind::Dxil => "dxil",
62            DataKind::Hlsl => "hlsl",
63            DataKind::MetalLib => "metallib",
64            DataKind::Msl => "metal",
65            DataKind::Glsl => "glsl",
66        };
67        write!(f, "{s}")
68    }
69}
70
71impl DataKind {
72    #[cfg(feature = "replay")]
73    fn is_string(&self) -> bool {
74        match *self {
75            DataKind::Wgsl | DataKind::Ron | DataKind::Hlsl | DataKind::Msl | DataKind::Glsl => {
76                true
77            }
78            DataKind::Bin | DataKind::Spv | DataKind::Dxil | DataKind::MetalLib => false,
79        }
80    }
81}
82
83impl Data {
84    pub fn kind(&self) -> DataKind {
85        match self {
86            Data::File(file) => {
87                if file.ends_with(".bin") {
88                    DataKind::Bin
89                } else if file.ends_with(".wgsl") {
90                    DataKind::Wgsl
91                } else if file.ends_with(".ron") {
92                    DataKind::Ron
93                } else if file.ends_with(".spv") {
94                    DataKind::Spv
95                } else if file.ends_with(".dxil") {
96                    DataKind::Dxil
97                } else if file.ends_with(".hlsl") {
98                    DataKind::Hlsl
99                } else if file.ends_with(".metallib") {
100                    DataKind::MetalLib
101                } else if file.ends_with(".metal") {
102                    DataKind::Msl
103                } else if file.ends_with(".glsl") {
104                    DataKind::Glsl
105                } else {
106                    panic!("unknown data file extension: {file}");
107                }
108            }
109            Data::String(kind, _) => *kind,
110            Data::Binary(kind, _) => *kind,
111        }
112    }
113}
114
115#[allow(clippy::large_enum_variant)]
116#[derive(Debug)]
117#[apply(serde_object_reference_struct)]
118pub enum Action<'a, R: ReferenceType> {
119    Init {
120        desc: crate::device::DeviceDescriptor<'a>,
121        backend: wgt::Backend,
122    },
123    ConfigureSurface(
124        R::Surface,
125        wgt::SurfaceConfiguration<Vec<wgt::TextureFormat>>,
126    ),
127    CreateBuffer(R::Buffer, crate::resource::BufferDescriptor<'a>),
128    FreeBuffer(R::Buffer),
129    DestroyBuffer(R::Buffer),
130    CreateTexture(R::Texture, crate::resource::TextureDescriptor<'a>),
131    FreeTexture(R::Texture),
132    DestroyTexture(R::Texture),
133    CreateTextureView {
134        id: R::TextureView,
135        parent: R::Texture,
136        desc: crate::resource::TextureViewDescriptor<'a>,
137    },
138    DestroyTextureView(R::TextureView),
139    CreateExternalTexture {
140        id: R::ExternalTexture,
141        desc: crate::resource::ExternalTextureDescriptor<'a>,
142        planes: alloc::boxed::Box<[R::TextureView]>,
143    },
144    FreeExternalTexture(R::ExternalTexture),
145    DestroyExternalTexture(R::ExternalTexture),
146    CreateSampler(
147        PointerId<markers::Sampler>,
148        crate::resource::SamplerDescriptor<'a>,
149    ),
150    DestroySampler(PointerId<markers::Sampler>),
151    GetSurfaceTexture {
152        id: R::Texture,
153        parent: R::Surface,
154    },
155    Present(R::Surface),
156    DiscardSurfaceTexture(R::Surface),
157    CreateBindGroupLayout(
158        PointerId<markers::BindGroupLayout>,
159        crate::binding_model::BindGroupLayoutDescriptor<'a>,
160    ),
161    GetRenderPipelineBindGroupLayout {
162        id: PointerId<markers::BindGroupLayout>,
163        pipeline: PointerId<markers::RenderPipeline>,
164        index: u32,
165    },
166    GetComputePipelineBindGroupLayout {
167        id: PointerId<markers::BindGroupLayout>,
168        pipeline: PointerId<markers::ComputePipeline>,
169        index: u32,
170    },
171    DestroyBindGroupLayout(PointerId<markers::BindGroupLayout>),
172    CreatePipelineLayout(
173        PointerId<markers::PipelineLayout>,
174        crate::binding_model::ResolvedPipelineLayoutDescriptor<
175            'a,
176            PointerId<markers::BindGroupLayout>,
177        >,
178    ),
179    DestroyPipelineLayout(PointerId<markers::PipelineLayout>),
180    CreateBindGroup(PointerId<markers::BindGroup>, TraceBindGroupDescriptor<'a>),
181    DestroyBindGroup(PointerId<markers::BindGroup>),
182    CreateShaderModule {
183        id: PointerId<markers::ShaderModule>,
184        desc: crate::pipeline::ShaderModuleDescriptor<'a>,
185        data: Data,
186    },
187    CreateShaderModulePassthrough {
188        id: PointerId<markers::ShaderModule>,
189        data: Vec<Data>,
190
191        label: crate::Label<'a>,
192        num_workgroups: (u32, u32, u32),
193    },
194    DestroyShaderModule(PointerId<markers::ShaderModule>),
195    CreateComputePipeline {
196        id: PointerId<markers::ComputePipeline>,
197        desc: TraceComputePipelineDescriptor<'a>,
198    },
199    DestroyComputePipeline(PointerId<markers::ComputePipeline>),
200    CreateGeneralRenderPipeline {
201        id: PointerId<markers::RenderPipeline>,
202        desc: TraceGeneralRenderPipelineDescriptor<'a>,
203    },
204    DestroyRenderPipeline(PointerId<markers::RenderPipeline>),
205    CreatePipelineCache {
206        id: PointerId<markers::PipelineCache>,
207        desc: crate::pipeline::PipelineCacheDescriptor<'a>,
208    },
209    DestroyPipelineCache(PointerId<markers::PipelineCache>),
210    CreateRenderBundle {
211        id: R::RenderBundle,
212        desc: crate::command::RenderBundleEncoderDescriptor<'a>,
213        base: BasePass<RenderCommand<R>, Infallible>,
214    },
215    DestroyRenderBundle(PointerId<markers::RenderBundle>),
216    CreateQuerySet {
217        id: PointerId<markers::QuerySet>,
218        desc: crate::resource::QuerySetDescriptor<'a>,
219    },
220    DestroyQuerySet(PointerId<markers::QuerySet>),
221    WriteBuffer {
222        id: R::Buffer,
223        data: Data,
224        offset: wgt::BufferAddress,
225        size: wgt::BufferAddress,
226        queued: bool,
227    },
228    WriteTexture {
229        to: wgt::TexelCopyTextureInfo<R::Texture>,
230        data: Data,
231        layout: wgt::TexelCopyBufferLayout,
232        size: wgt::Extent3d,
233    },
234    Submit(crate::SubmissionIndex, Vec<Command<R>>),
235    FailedCommands {
236        commands: Option<Vec<Command<R>>>,
237        /// If `None`, then encoding failed due to a validation error (returned
238        /// from `CommandEncoder::finish`). If `Some`, submission failed due to
239        /// a resource having been destroyed.
240        failed_at_submit: Option<crate::SubmissionIndex>,
241        error: String,
242    },
243    CreateBlas {
244        id: R::Blas,
245        desc: crate::resource::BlasDescriptor<'a>,
246        sizes: wgt::BlasGeometrySizeDescriptors,
247    },
248    DestroyBlas(R::Blas),
249    CreateTlas {
250        id: R::Tlas,
251        desc: crate::resource::TlasDescriptor<'a>,
252    },
253    DestroyTlas(R::Tlas),
254}
255
256/// cbindgen:ignore
257pub type TraceBindGroupDescriptor<'a> = crate::binding_model::BindGroupDescriptor<
258    'a,
259    PointerId<markers::BindGroupLayout>,
260    PointerId<markers::Buffer>,
261    PointerId<markers::Sampler>,
262    PointerId<markers::TextureView>,
263    PointerId<markers::Tlas>,
264    PointerId<markers::ExternalTexture>,
265>;
266
267/// Not a public API. For use by `player` only.
268///
269/// cbindgen:ignore
270#[doc(hidden)]
271pub type TraceGeneralRenderPipelineDescriptor<'a> = GeneralRenderPipelineDescriptor<
272    'a,
273    PointerId<markers::PipelineLayout>,
274    PointerId<markers::ShaderModule>,
275    PointerId<markers::PipelineCache>,
276>;
277
278/// Not a public API. For use by `player` only.
279///
280/// cbindgen:ignore
281#[doc(hidden)]
282pub type TraceComputePipelineDescriptor<'a> = crate::pipeline::ComputePipelineDescriptor<
283    'a,
284    PointerId<markers::PipelineLayout>,
285    PointerId<markers::ShaderModule>,
286    PointerId<markers::PipelineCache>,
287>;