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