1use alloc::{string::String, vec::Vec};
2use core::ops::Range;
3
4#[cfg(feature = "trace")]
5use {alloc::borrow::Cow, std::io::Write as _};
6
7use crate::id;
8
9type 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>,
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: 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>,
196 timestamp_writes: Option<crate::command::PassTimestampWrites>,
197 },
198 RunRenderPass {
199 base: crate::command::BasePass<crate::command::RenderCommand>,
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 BuildAccelerationStructuresUnsafeTlas {
206 blas: Vec<crate::ray_tracing::TraceBlasBuildEntry>,
207 tlas: Vec<crate::ray_tracing::TlasBuildEntry>,
208 },
209 BuildAccelerationStructures {
210 blas: Vec<crate::ray_tracing::TraceBlasBuildEntry>,
211 tlas: Vec<crate::ray_tracing::TraceTlasPackage>,
212 },
213}
214
215#[cfg(feature = "trace")]
216#[derive(Debug)]
217pub struct Trace {
218 path: std::path::PathBuf,
219 file: std::fs::File,
220 config: ron::ser::PrettyConfig,
221 binary_id: usize,
222}
223
224#[cfg(feature = "trace")]
225impl Trace {
226 pub fn new(path: std::path::PathBuf) -> Result<Self, std::io::Error> {
227 log::info!("Tracing into '{:?}'", path);
228 let mut file = std::fs::File::create(path.join(FILE_NAME))?;
229 file.write_all(b"[\n")?;
230 Ok(Self {
231 path,
232 file,
233 config: ron::ser::PrettyConfig::default(),
234 binary_id: 0,
235 })
236 }
237
238 pub fn make_binary(&mut self, kind: &str, data: &[u8]) -> String {
239 self.binary_id += 1;
240 let name = std::format!("data{}.{}", self.binary_id, kind);
241 let _ = std::fs::write(self.path.join(&name), data);
242 name
243 }
244
245 pub(crate) fn add(&mut self, action: Action) {
246 match ron::ser::to_string_pretty(&action, self.config.clone()) {
247 Ok(string) => {
248 let _ = writeln!(self.file, "{},", string);
249 }
250 Err(e) => {
251 log::warn!("RON serialization failure: {:?}", e);
252 }
253 }
254 }
255}
256
257#[cfg(feature = "trace")]
258impl Drop for Trace {
259 fn drop(&mut self) {
260 let _ = self.file.write_all(b"]");
261 }
262}