1use crate::id;
2use std::ops::Range;
3#[cfg(feature = "trace")]
4use std::{borrow::Cow, io::Write as _};
5
6type 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}