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 = "trace", derive(serde::Serialize))]
37#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
38pub enum Action<'a> {
39 Init {
40 desc: crate::device::DeviceDescriptor<'a>,
41 backend: wgt::Backend,
42 },
43 ConfigureSurface(
44 id::SurfaceId,
45 wgt::SurfaceConfiguration<Vec<wgt::TextureFormat>>,
46 ),
47 CreateBuffer(id::BufferId, crate::resource::BufferDescriptor<'a>),
48 FreeBuffer(id::BufferId),
49 DestroyBuffer(id::BufferId),
50 CreateTexture(id::TextureId, crate::resource::TextureDescriptor<'a>),
51 FreeTexture(id::TextureId),
52 DestroyTexture(id::TextureId),
53 CreateTextureView {
54 id: id::TextureViewId,
55 parent_id: id::TextureId,
56 desc: crate::resource::TextureViewDescriptor<'a>,
57 },
58 DestroyTextureView(id::TextureViewId),
59 CreateSampler(id::SamplerId, crate::resource::SamplerDescriptor<'a>),
60 DestroySampler(id::SamplerId),
61 GetSurfaceTexture {
62 id: id::TextureId,
63 parent_id: id::SurfaceId,
64 },
65 Present(id::SurfaceId),
66 DiscardSurfaceTexture(id::SurfaceId),
67 CreateBindGroupLayout(
68 id::BindGroupLayoutId,
69 crate::binding_model::BindGroupLayoutDescriptor<'a>,
70 ),
71 DestroyBindGroupLayout(id::BindGroupLayoutId),
72 CreatePipelineLayout(
73 id::PipelineLayoutId,
74 crate::binding_model::PipelineLayoutDescriptor<'a>,
75 ),
76 DestroyPipelineLayout(id::PipelineLayoutId),
77 CreateBindGroup(
78 id::BindGroupId,
79 crate::binding_model::BindGroupDescriptor<'a>,
80 ),
81 DestroyBindGroup(id::BindGroupId),
82 CreateShaderModule {
83 id: id::ShaderModuleId,
84 desc: crate::pipeline::ShaderModuleDescriptor<'a>,
85 data: FileName,
86 },
87 DestroyShaderModule(id::ShaderModuleId),
88 CreateComputePipeline {
89 id: id::ComputePipelineId,
90 desc: crate::pipeline::ComputePipelineDescriptor<'a>,
91 #[cfg_attr(feature = "replay", serde(default))]
92 implicit_context: Option<super::ImplicitPipelineContext>,
93 },
94 DestroyComputePipeline(id::ComputePipelineId),
95 CreateRenderPipeline {
96 id: id::RenderPipelineId,
97 desc: crate::pipeline::RenderPipelineDescriptor<'a>,
98 #[cfg_attr(feature = "replay", serde(default))]
99 implicit_context: Option<super::ImplicitPipelineContext>,
100 },
101 DestroyRenderPipeline(id::RenderPipelineId),
102 CreateRenderBundle {
103 id: id::RenderBundleId,
104 desc: crate::command::RenderBundleEncoderDescriptor<'a>,
105 base: crate::command::BasePass<crate::command::RenderCommand>,
106 },
107 DestroyRenderBundle(id::RenderBundleId),
108 CreateQuerySet {
109 id: id::QuerySetId,
110 desc: crate::resource::QuerySetDescriptor<'a>,
111 },
112 DestroyQuerySet(id::QuerySetId),
113 WriteBuffer {
114 id: id::BufferId,
115 data: FileName,
116 range: Range<wgt::BufferAddress>,
117 queued: bool,
118 },
119 WriteTexture {
120 to: crate::command::ImageCopyTexture,
121 data: FileName,
122 layout: wgt::ImageDataLayout,
123 size: wgt::Extent3d,
124 },
125 Submit(crate::SubmissionIndex, Vec<Command>),
126}
127
128#[derive(Debug)]
129#[cfg_attr(feature = "trace", derive(serde::Serialize))]
130#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
131pub enum Command {
132 CopyBufferToBuffer {
133 src: id::BufferId,
134 src_offset: wgt::BufferAddress,
135 dst: id::BufferId,
136 dst_offset: wgt::BufferAddress,
137 size: wgt::BufferAddress,
138 },
139 CopyBufferToTexture {
140 src: crate::command::ImageCopyBuffer,
141 dst: crate::command::ImageCopyTexture,
142 size: wgt::Extent3d,
143 },
144 CopyTextureToBuffer {
145 src: crate::command::ImageCopyTexture,
146 dst: crate::command::ImageCopyBuffer,
147 size: wgt::Extent3d,
148 },
149 CopyTextureToTexture {
150 src: crate::command::ImageCopyTexture,
151 dst: crate::command::ImageCopyTexture,
152 size: wgt::Extent3d,
153 },
154 ClearBuffer {
155 dst: id::BufferId,
156 offset: wgt::BufferAddress,
157 size: Option<wgt::BufferSize>,
158 },
159 ClearTexture {
160 dst: id::TextureId,
161 subresource_range: wgt::ImageSubresourceRange,
162 },
163 WriteTimestamp {
164 query_set_id: id::QuerySetId,
165 query_index: u32,
166 },
167 ResolveQuerySet {
168 query_set_id: id::QuerySetId,
169 start_query: u32,
170 query_count: u32,
171 destination: id::BufferId,
172 destination_offset: wgt::BufferAddress,
173 },
174 PushDebugGroup(String),
175 PopDebugGroup,
176 InsertDebugMarker(String),
177 RunComputePass {
178 base: crate::command::BasePass<crate::command::ComputeCommand>,
179 timestamp_writes: Option<crate::command::ComputePassTimestampWrites>,
180 },
181 RunRenderPass {
182 base: crate::command::BasePass<crate::command::RenderCommand>,
183 target_colors: Vec<Option<crate::command::RenderPassColorAttachment>>,
184 target_depth_stencil: Option<crate::command::RenderPassDepthStencilAttachment>,
185 timestamp_writes: Option<crate::command::RenderPassTimestampWrites>,
186 occlusion_query_set_id: Option<id::QuerySetId>,
187 },
188}
189
190#[cfg(feature = "trace")]
191#[derive(Debug)]
192pub struct Trace {
193 path: std::path::PathBuf,
194 file: std::fs::File,
195 config: ron::ser::PrettyConfig,
196 binary_id: usize,
197}
198
199#[cfg(feature = "trace")]
200impl Trace {
201 pub fn new(path: &std::path::Path) -> Result<Self, std::io::Error> {
202 log::info!("Tracing into '{:?}'", path);
203 let mut file = std::fs::File::create(path.join(FILE_NAME))?;
204 file.write_all(b"[\n")?;
205 Ok(Self {
206 path: path.to_path_buf(),
207 file,
208 config: ron::ser::PrettyConfig::default(),
209 binary_id: 0,
210 })
211 }
212
213 pub fn make_binary(&mut self, kind: &str, data: &[u8]) -> String {
214 self.binary_id += 1;
215 let name = format!("data{}.{}", self.binary_id, kind);
216 let _ = std::fs::write(self.path.join(&name), data);
217 name
218 }
219
220 pub(crate) fn add(&mut self, action: Action) {
221 match ron::ser::to_string_pretty(&action, self.config.clone()) {
222 Ok(string) => {
223 let _ = writeln!(self.file, "{},", string);
224 }
225 Err(e) => {
226 log::warn!("RON serialization failure: {:?}", e);
227 }
228 }
229 }
230}
231
232#[cfg(feature = "trace")]
233impl Drop for Trace {
234 fn drop(&mut self) {
235 let _ = self.file.write_all(b"]");
236 }
237}