Skip to main content

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