wgpu_core/device/
trace.rs

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