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::ResolvedPipelineLayoutDescriptor<
177            'a,
178            PointerId<markers::BindGroupLayout>,
179        >,
180    ),
181    DropPipelineLayout(PointerId<markers::PipelineLayout>),
182    CreateBindGroup(PointerId<markers::BindGroup>, TraceBindGroupDescriptor<'a>),
183    DropBindGroup(PointerId<markers::BindGroup>),
184    CreateShaderModule {
185        id: PointerId<markers::ShaderModule>,
186        desc: crate::pipeline::ShaderModuleDescriptor<'a>,
187        data: Data,
188    },
189    CreateShaderModulePassthrough {
190        id: PointerId<markers::ShaderModule>,
191        data: Vec<Data>,
192
193        label: crate::Label<'a>,
194        entry_points: Cow<'a, [wgt::PassthroughShaderEntryPoint<'a>]>,
195    },
196    DropShaderModule(PointerId<markers::ShaderModule>),
197    CreateComputePipeline {
198        id: PointerId<markers::ComputePipeline>,
199        desc: TraceComputePipelineDescriptor<'a>,
200    },
201    DropComputePipeline(PointerId<markers::ComputePipeline>),
202    CreateGeneralRenderPipeline {
203        id: PointerId<markers::RenderPipeline>,
204        desc: TraceGeneralRenderPipelineDescriptor<'a>,
205    },
206    DropRenderPipeline(PointerId<markers::RenderPipeline>),
207    CreatePipelineCache {
208        id: PointerId<markers::PipelineCache>,
209        desc: crate::pipeline::PipelineCacheDescriptor<'a>,
210    },
211    DropPipelineCache(PointerId<markers::PipelineCache>),
212    CreateRenderBundle {
213        id: R::RenderBundle,
214        desc: crate::command::RenderBundleEncoderDescriptor<'a>,
215        base: BasePass<RenderCommand<R>, Infallible>,
216    },
217    DropRenderBundle(PointerId<markers::RenderBundle>),
218    CreateQuerySet {
219        id: PointerId<markers::QuerySet>,
220        desc: crate::resource::QuerySetDescriptor<'a>,
221    },
222    DropQuerySet(PointerId<markers::QuerySet>),
223    DestroyQuerySet(PointerId<markers::QuerySet>),
224    WriteBuffer {
225        id: R::Buffer,
226        data: Data,
227        offset: wgt::BufferAddress,
228        size: wgt::BufferAddress,
229        queued: bool,
230    },
231    WriteTexture {
232        to: wgt::TexelCopyTextureInfo<R::Texture>,
233        data: Data,
234        layout: wgt::TexelCopyBufferLayout,
235        size: wgt::Extent3d,
236    },
237    Submit(crate::SubmissionIndex, Vec<Command<R>>),
238    FailedCommands {
239        commands: Option<Vec<Command<R>>>,
240        /// If `None`, then encoding failed due to a validation error (returned
241        /// from `CommandEncoder::finish`). If `Some`, submission failed due to
242        /// a resource having been destroyed.
243        failed_at_submit: Option<crate::SubmissionIndex>,
244        error: String,
245    },
246    CreateBlas {
247        id: R::Blas,
248        desc: crate::resource::BlasDescriptor<'a>,
249        sizes: wgt::BlasGeometrySizeDescriptors,
250    },
251    DropBlas(R::Blas),
252    CreateTlas {
253        id: R::Tlas,
254        desc: crate::resource::TlasDescriptor<'a>,
255    },
256    DropTlas(R::Tlas),
257}
258
259/// cbindgen:ignore
260pub type TraceBindGroupDescriptor<'a> = crate::binding_model::BindGroupDescriptor<
261    'a,
262    PointerId<markers::BindGroupLayout>,
263    PointerId<markers::Buffer>,
264    PointerId<markers::Sampler>,
265    PointerId<markers::TextureView>,
266    PointerId<markers::Tlas>,
267    PointerId<markers::ExternalTexture>,
268>;
269
270/// Not a public API. For use by `player` only.
271///
272/// cbindgen:ignore
273#[doc(hidden)]
274pub type TraceGeneralRenderPipelineDescriptor<'a> = GeneralRenderPipelineDescriptor<
275    'a,
276    PointerId<markers::PipelineLayout>,
277    PointerId<markers::ShaderModule>,
278    PointerId<markers::PipelineCache>,
279>;
280
281/// Not a public API. For use by `player` only.
282///
283/// cbindgen:ignore
284#[doc(hidden)]
285pub type TraceComputePipelineDescriptor<'a> = crate::pipeline::ComputePipelineDescriptor<
286    'a,
287    PointerId<markers::PipelineLayout>,
288    PointerId<markers::ShaderModule>,
289    PointerId<markers::PipelineCache>,
290>;