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    DestroyShaderModule(id::ShaderModuleId),
97    CreateComputePipeline {
98        id: id::ComputePipelineId,
99        desc: crate::pipeline::ComputePipelineDescriptor<'a>,
100    },
101    DestroyComputePipeline(id::ComputePipelineId),
102    CreateRenderPipeline {
103        id: id::RenderPipelineId,
104        desc: crate::pipeline::RenderPipelineDescriptor<'a>,
105    },
106    CreateMeshPipeline {
107        id: id::RenderPipelineId,
108        desc: crate::pipeline::MeshPipelineDescriptor<'a>,
109    },
110    DestroyRenderPipeline(id::RenderPipelineId),
111    CreatePipelineCache {
112        id: id::PipelineCacheId,
113        desc: crate::pipeline::PipelineCacheDescriptor<'a>,
114    },
115    DestroyPipelineCache(id::PipelineCacheId),
116    CreateRenderBundle {
117        id: id::RenderBundleId,
118        desc: crate::command::RenderBundleEncoderDescriptor<'a>,
119        base: crate::command::BasePass<crate::command::RenderCommand, Infallible>,
120    },
121    DestroyRenderBundle(id::RenderBundleId),
122    CreateQuerySet {
123        id: id::QuerySetId,
124        desc: crate::resource::QuerySetDescriptor<'a>,
125    },
126    DestroyQuerySet(id::QuerySetId),
127    WriteBuffer {
128        id: id::BufferId,
129        data: FileName,
130        range: Range<wgt::BufferAddress>,
131        queued: bool,
132    },
133    WriteTexture {
134        to: crate::command::TexelCopyTextureInfo,
135        data: FileName,
136        layout: wgt::TexelCopyBufferLayout,
137        size: wgt::Extent3d,
138    },
139    Submit(crate::SubmissionIndex, Vec<Command>),
140    CreateBlas {
141        id: id::BlasId,
142        desc: crate::resource::BlasDescriptor<'a>,
143        sizes: wgt::BlasGeometrySizeDescriptors,
144    },
145    DestroyBlas(id::BlasId),
146    CreateTlas {
147        id: id::TlasId,
148        desc: crate::resource::TlasDescriptor<'a>,
149    },
150    DestroyTlas(id::TlasId),
151}
152
153#[derive(Debug)]
154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155pub enum Command {
156    CopyBufferToBuffer {
157        src: id::BufferId,
158        src_offset: wgt::BufferAddress,
159        dst: id::BufferId,
160        dst_offset: wgt::BufferAddress,
161        size: Option<wgt::BufferAddress>,
162    },
163    CopyBufferToTexture {
164        src: crate::command::TexelCopyBufferInfo,
165        dst: crate::command::TexelCopyTextureInfo,
166        size: wgt::Extent3d,
167    },
168    CopyTextureToBuffer {
169        src: crate::command::TexelCopyTextureInfo,
170        dst: crate::command::TexelCopyBufferInfo,
171        size: wgt::Extent3d,
172    },
173    CopyTextureToTexture {
174        src: crate::command::TexelCopyTextureInfo,
175        dst: crate::command::TexelCopyTextureInfo,
176        size: wgt::Extent3d,
177    },
178    ClearBuffer {
179        dst: id::BufferId,
180        offset: wgt::BufferAddress,
181        size: Option<wgt::BufferAddress>,
182    },
183    ClearTexture {
184        dst: id::TextureId,
185        subresource_range: wgt::ImageSubresourceRange,
186    },
187    WriteTimestamp {
188        query_set_id: id::QuerySetId,
189        query_index: u32,
190    },
191    ResolveQuerySet {
192        query_set_id: id::QuerySetId,
193        start_query: u32,
194        query_count: u32,
195        destination: id::BufferId,
196        destination_offset: wgt::BufferAddress,
197    },
198    PushDebugGroup(String),
199    PopDebugGroup,
200    InsertDebugMarker(String),
201    RunComputePass {
202        base: crate::command::BasePass<crate::command::ComputeCommand, Infallible>,
203        timestamp_writes: Option<crate::command::PassTimestampWrites>,
204    },
205    RunRenderPass {
206        base: crate::command::BasePass<crate::command::RenderCommand, Infallible>,
207        target_colors: Vec<Option<crate::command::RenderPassColorAttachment>>,
208        target_depth_stencil: Option<crate::command::RenderPassDepthStencilAttachment>,
209        timestamp_writes: Option<crate::command::PassTimestampWrites>,
210        occlusion_query_set_id: Option<id::QuerySetId>,
211    },
212    BuildAccelerationStructures {
213        blas: Vec<crate::ray_tracing::TraceBlasBuildEntry>,
214        tlas: Vec<crate::ray_tracing::TraceTlasPackage>,
215    },
216}
217
218#[cfg(feature = "trace")]
219#[derive(Debug)]
220pub struct Trace {
221    path: std::path::PathBuf,
222    file: std::fs::File,
223    config: ron::ser::PrettyConfig,
224    binary_id: usize,
225}
226
227#[cfg(feature = "trace")]
228impl Trace {
229    pub fn new(path: std::path::PathBuf) -> Result<Self, std::io::Error> {
230        log::info!("Tracing into '{path:?}'");
231        let mut file = std::fs::File::create(path.join(FILE_NAME))?;
232        file.write_all(b"[\n")?;
233        Ok(Self {
234            path,
235            file,
236            config: ron::ser::PrettyConfig::default(),
237            binary_id: 0,
238        })
239    }
240
241    pub fn make_binary(&mut self, kind: &str, data: &[u8]) -> String {
242        self.binary_id += 1;
243        let name = std::format!("data{}.{}", self.binary_id, kind);
244        let _ = std::fs::write(self.path.join(&name), data);
245        name
246    }
247
248    pub(crate) fn add(&mut self, action: Action) {
249        match ron::ser::to_string_pretty(&action, self.config.clone()) {
250            Ok(string) => {
251                let _ = writeln!(self.file, "{string},");
252            }
253            Err(e) => {
254                log::warn!("RON serialization failure: {e:?}");
255            }
256        }
257    }
258}
259
260#[cfg(feature = "trace")]
261impl Drop for Trace {
262    fn drop(&mut self) {
263        let _ = self.file.write_all(b"]");
264    }
265}