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::{borrow::Cow, 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    DestroyBuffer(R::Buffer),
129    DropBuffer(R::Buffer),
130    CreateTexture(R::Texture, crate::resource::TextureDescriptor<'a>),
131    CreateTextureError(R::Texture, crate::resource::TextureDescriptor<'a>),
132    DestroyTexture(R::Texture),
133    DropTexture(R::Texture),
134    CreateTextureView {
135        id: R::TextureView,
136        parent: R::Texture,
137        desc: crate::resource::TextureViewDescriptor<'a>,
138    },
139    DropTextureView(R::TextureView),
140    CreateExternalTexture {
141        id: R::ExternalTexture,
142        desc: crate::resource::ExternalTextureDescriptor<'a>,
143        planes: alloc::boxed::Box<[R::TextureView]>,
144    },
145    DestroyExternalTexture(R::ExternalTexture),
146    DropExternalTexture(R::ExternalTexture),
147    CreateSampler(
148        PointerId<markers::Sampler>,
149        crate::resource::SamplerDescriptor<'a>,
150    ),
151    DropSampler(PointerId<markers::Sampler>),
152    GetSurfaceTexture {
153        id: R::Texture,
154        parent: R::Surface,
155    },
156    Present(R::Surface),
157    DiscardSurfaceTexture(R::Surface),
158    ReleaseSurfaceTexture(R::Surface),
159    CreateBindGroupLayout(
160        PointerId<markers::BindGroupLayout>,
161        crate::binding_model::BindGroupLayoutDescriptor<'a>,
162    ),
163    GetRenderPipelineBindGroupLayout {
164        id: PointerId<markers::BindGroupLayout>,
165        pipeline: PointerId<markers::RenderPipeline>,
166        index: u32,
167    },
168    GetComputePipelineBindGroupLayout {
169        id: PointerId<markers::BindGroupLayout>,
170        pipeline: PointerId<markers::ComputePipeline>,
171        index: u32,
172    },
173    DropBindGroupLayout(PointerId<markers::BindGroupLayout>),
174    CreatePipelineLayout(
175        PointerId<markers::PipelineLayout>,
176        crate::binding_model::PipelineLayoutDescriptor<'a, PointerId<markers::BindGroupLayout>>,
177    ),
178    DropPipelineLayout(PointerId<markers::PipelineLayout>),
179    CreateBindGroup(PointerId<markers::BindGroup>, TraceBindGroupDescriptor<'a>),
180    DropBindGroup(PointerId<markers::BindGroup>),
181    CreateShaderModule {
182        id: PointerId<markers::ShaderModule>,
183        desc: crate::pipeline::ShaderModuleDescriptor<'a>,
184        data: Data,
185    },
186    CreateShaderModulePassthrough {
187        id: PointerId<markers::ShaderModule>,
188        data: Vec<Data>,
189
190        label: crate::Label<'a>,
191        entry_points: Cow<'a, [wgt::PassthroughShaderEntryPoint<'a>]>,
192    },
193    DropShaderModule(PointerId<markers::ShaderModule>),
194    CreateComputePipeline {
195        id: PointerId<markers::ComputePipeline>,
196        desc: TraceComputePipelineDescriptor<'a>,
197    },
198    DropComputePipeline(PointerId<markers::ComputePipeline>),
199    CreateGeneralRenderPipeline {
200        id: PointerId<markers::RenderPipeline>,
201        desc: TraceGeneralRenderPipelineDescriptor<'a>,
202    },
203    DropRenderPipeline(PointerId<markers::RenderPipeline>),
204    CreatePipelineCache {
205        id: PointerId<markers::PipelineCache>,
206        desc: crate::pipeline::PipelineCacheDescriptor<'a>,
207    },
208    DropPipelineCache(PointerId<markers::PipelineCache>),
209    CreateRenderBundle {
210        id: R::RenderBundle,
211        desc: crate::command::RenderBundleEncoderDescriptor<'a>,
212        base: BasePass<RenderCommand<R>, Infallible>,
213    },
214    DropRenderBundle(PointerId<markers::RenderBundle>),
215    CreateQuerySet {
216        id: PointerId<markers::QuerySet>,
217        desc: crate::resource::QuerySetDescriptor<'a>,
218    },
219    DropQuerySet(PointerId<markers::QuerySet>),
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    DropBlas(R::Blas),
249    CreateTlas {
250        id: R::Tlas,
251        desc: crate::resource::TlasDescriptor<'a>,
252    },
253    DropTlas(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>;