wgpu_core/device/
trace.rs

1use alloc::{string::String, vec::Vec};
2use core::{convert::Infallible, ops::Range};
3
4#[cfg(feature = "trace")]
5use {alloc::borrow::Cow, std::io::Write as _};
6
7use crate::id;
8
9//TODO: consider a readable Id that doesn't include the backend
10
11type FileName = String;
12
13pub const FILE_NAME: &str = "trace.ron";
14
15#[cfg(feature = "trace")]
16pub(crate) fn new_render_bundle_encoder_descriptor<'a>(
17    label: crate::Label<'a>,
18    context: &'a super::RenderPassContext,
19    depth_read_only: bool,
20    stencil_read_only: bool,
21) -> crate::command::RenderBundleEncoderDescriptor<'a> {
22    crate::command::RenderBundleEncoderDescriptor {
23        label,
24        color_formats: Cow::Borrowed(&context.attachments.colors),
25        depth_stencil: context.attachments.depth_stencil.map(|format| {
26            wgt::RenderBundleDepthStencil {
27                format,
28                depth_read_only,
29                stencil_read_only,
30            }
31        }),
32        sample_count: context.sample_count,
33        multiview: context.multiview,
34    }
35}
36
37#[allow(clippy::large_enum_variant)]
38#[derive(Debug)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40pub enum Action<'a> {
41    Init {
42        desc: crate::device::DeviceDescriptor<'a>,
43        backend: wgt::Backend,
44    },
45    ConfigureSurface(
46        id::SurfaceId,
47        wgt::SurfaceConfiguration<Vec<wgt::TextureFormat>>,
48    ),
49    CreateBuffer(id::BufferId, crate::resource::BufferDescriptor<'a>),
50    FreeBuffer(id::BufferId),
51    DestroyBuffer(id::BufferId),
52    CreateTexture(id::TextureId, crate::resource::TextureDescriptor<'a>),
53    FreeTexture(id::TextureId),
54    DestroyTexture(id::TextureId),
55    CreateTextureView {
56        id: id::TextureViewId,
57        parent_id: id::TextureId,
58        desc: crate::resource::TextureViewDescriptor<'a>,
59    },
60    DestroyTextureView(id::TextureViewId),
61    CreateExternalTexture {
62        id: id::ExternalTextureId,
63        desc: crate::resource::ExternalTextureDescriptor<'a>,
64        planes: alloc::boxed::Box<[id::TextureViewId]>,
65    },
66    FreeExternalTexture(id::ExternalTextureId),
67    DestroyExternalTexture(id::ExternalTextureId),
68    CreateSampler(id::SamplerId, crate::resource::SamplerDescriptor<'a>),
69    DestroySampler(id::SamplerId),
70    GetSurfaceTexture {
71        id: id::TextureId,
72        parent_id: id::SurfaceId,
73    },
74    Present(id::SurfaceId),
75    DiscardSurfaceTexture(id::SurfaceId),
76    CreateBindGroupLayout(
77        id::BindGroupLayoutId,
78        crate::binding_model::BindGroupLayoutDescriptor<'a>,
79    ),
80    DestroyBindGroupLayout(id::BindGroupLayoutId),
81    CreatePipelineLayout(
82        id::PipelineLayoutId,
83        crate::binding_model::PipelineLayoutDescriptor<'a>,
84    ),
85    DestroyPipelineLayout(id::PipelineLayoutId),
86    CreateBindGroup(
87        id::BindGroupId,
88        crate::binding_model::BindGroupDescriptor<'a>,
89    ),
90    DestroyBindGroup(id::BindGroupId),
91    CreateShaderModule {
92        id: id::ShaderModuleId,
93        desc: crate::pipeline::ShaderModuleDescriptor<'a>,
94        data: FileName,
95    },
96    CreateShaderModulePassthrough {
97        id: id::ShaderModuleId,
98        data: Vec<FileName>,
99
100        entry_point: String,
101        label: crate::Label<'a>,
102        num_workgroups: (u32, u32, u32),
103        runtime_checks: wgt::ShaderRuntimeChecks,
104    },
105    DestroyShaderModule(id::ShaderModuleId),
106    CreateComputePipeline {
107        id: id::ComputePipelineId,
108        desc: crate::pipeline::ComputePipelineDescriptor<'a>,
109    },
110    DestroyComputePipeline(id::ComputePipelineId),
111    CreateRenderPipeline {
112        id: id::RenderPipelineId,
113        desc: crate::pipeline::RenderPipelineDescriptor<'a>,
114    },
115    CreateMeshPipeline {
116        id: id::RenderPipelineId,
117        desc: crate::pipeline::MeshPipelineDescriptor<'a>,
118    },
119    DestroyRenderPipeline(id::RenderPipelineId),
120    CreatePipelineCache {
121        id: id::PipelineCacheId,
122        desc: crate::pipeline::PipelineCacheDescriptor<'a>,
123    },
124    DestroyPipelineCache(id::PipelineCacheId),
125    CreateRenderBundle {
126        id: id::RenderBundleId,
127        desc: crate::command::RenderBundleEncoderDescriptor<'a>,
128        base: crate::command::BasePass<crate::command::RenderCommand, Infallible>,
129    },
130    DestroyRenderBundle(id::RenderBundleId),
131    CreateQuerySet {
132        id: id::QuerySetId,
133        desc: crate::resource::QuerySetDescriptor<'a>,
134    },
135    DestroyQuerySet(id::QuerySetId),
136    WriteBuffer {
137        id: id::BufferId,
138        data: FileName,
139        range: Range<wgt::BufferAddress>,
140        queued: bool,
141    },
142    WriteTexture {
143        to: crate::command::TexelCopyTextureInfo,
144        data: FileName,
145        layout: wgt::TexelCopyBufferLayout,
146        size: wgt::Extent3d,
147    },
148    Submit(crate::SubmissionIndex, Vec<Command>),
149    CreateBlas {
150        id: id::BlasId,
151        desc: crate::resource::BlasDescriptor<'a>,
152        sizes: wgt::BlasGeometrySizeDescriptors,
153    },
154    DestroyBlas(id::BlasId),
155    CreateTlas {
156        id: id::TlasId,
157        desc: crate::resource::TlasDescriptor<'a>,
158    },
159    DestroyTlas(id::TlasId),
160}
161
162#[derive(Debug)]
163#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164pub enum Command {
165    CopyBufferToBuffer {
166        src: id::BufferId,
167        src_offset: wgt::BufferAddress,
168        dst: id::BufferId,
169        dst_offset: wgt::BufferAddress,
170        size: Option<wgt::BufferAddress>,
171    },
172    CopyBufferToTexture {
173        src: crate::command::TexelCopyBufferInfo,
174        dst: crate::command::TexelCopyTextureInfo,
175        size: wgt::Extent3d,
176    },
177    CopyTextureToBuffer {
178        src: crate::command::TexelCopyTextureInfo,
179        dst: crate::command::TexelCopyBufferInfo,
180        size: wgt::Extent3d,
181    },
182    CopyTextureToTexture {
183        src: crate::command::TexelCopyTextureInfo,
184        dst: crate::command::TexelCopyTextureInfo,
185        size: wgt::Extent3d,
186    },
187    ClearBuffer {
188        dst: id::BufferId,
189        offset: wgt::BufferAddress,
190        size: Option<wgt::BufferAddress>,
191    },
192    ClearTexture {
193        dst: id::TextureId,
194        subresource_range: wgt::ImageSubresourceRange,
195    },
196    WriteTimestamp {
197        query_set_id: id::QuerySetId,
198        query_index: u32,
199    },
200    ResolveQuerySet {
201        query_set_id: id::QuerySetId,
202        start_query: u32,
203        query_count: u32,
204        destination: id::BufferId,
205        destination_offset: wgt::BufferAddress,
206    },
207    PushDebugGroup(String),
208    PopDebugGroup,
209    InsertDebugMarker(String),
210    RunComputePass {
211        base: crate::command::BasePass<crate::command::ComputeCommand, Infallible>,
212        timestamp_writes: Option<crate::command::PassTimestampWrites>,
213    },
214    RunRenderPass {
215        base: crate::command::BasePass<crate::command::RenderCommand, Infallible>,
216        target_colors: Vec<Option<crate::command::RenderPassColorAttachment>>,
217        target_depth_stencil: Option<crate::command::RenderPassDepthStencilAttachment>,
218        timestamp_writes: Option<crate::command::PassTimestampWrites>,
219        occlusion_query_set_id: Option<id::QuerySetId>,
220    },
221    BuildAccelerationStructures {
222        blas: Vec<crate::ray_tracing::TraceBlasBuildEntry>,
223        tlas: Vec<crate::ray_tracing::TraceTlasPackage>,
224    },
225}
226
227#[cfg(feature = "trace")]
228#[derive(Debug)]
229pub struct Trace {
230    path: std::path::PathBuf,
231    file: std::fs::File,
232    config: ron::ser::PrettyConfig,
233    binary_id: usize,
234}
235
236#[cfg(feature = "trace")]
237impl Trace {
238    pub fn new(path: std::path::PathBuf) -> Result<Self, std::io::Error> {
239        log::info!("Tracing into '{path:?}'");
240        let mut file = std::fs::File::create(path.join(FILE_NAME))?;
241        file.write_all(b"[\n")?;
242        Ok(Self {
243            path,
244            file,
245            config: ron::ser::PrettyConfig::default(),
246            binary_id: 0,
247        })
248    }
249
250    pub fn make_binary(&mut self, kind: &str, data: &[u8]) -> String {
251        self.binary_id += 1;
252        let name = std::format!("data{}.{}", self.binary_id, kind);
253        let _ = std::fs::write(self.path.join(&name), data);
254        name
255    }
256
257    pub(crate) fn add(&mut self, action: Action) {
258        match ron::ser::to_string_pretty(&action, self.config.clone()) {
259            Ok(string) => {
260                let _ = writeln!(self.file, "{string},");
261            }
262            Err(e) => {
263                log::warn!("RON serialization failure: {e:?}");
264            }
265        }
266    }
267}
268
269#[cfg(feature = "trace")]
270impl Drop for Trace {
271    fn drop(&mut self) {
272        let _ = self.file.write_all(b"]");
273    }
274}