1#[cfg(feature = "trace")]
2mod record;
3#[cfg(feature = "replay")]
4mod replay;
5
6use core::{convert::Infallible, ops::Range};
7
8use alloc::{string::String, vec::Vec};
9use macro_rules_attribute::apply;
10
11use crate::{
12 command::{serde_object_reference_struct, BasePass, Command, ReferenceType, RenderCommand},
13 id::{markers, PointerId},
14 pipeline::GeneralRenderPipelineDescriptor,
15};
16
17#[cfg(feature = "trace")]
18pub use record::*;
19#[cfg(feature = "replay")]
20pub use replay::*;
21
22type FileName = String;
23
24pub const FILE_NAME: &str = "trace.ron";
25
26#[derive(Debug)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum Data {
29 File(FileName),
30 String(DataKind, String),
31 Binary(DataKind, Vec<u8>),
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
35#[cfg_attr(
36 feature = "serde",
37 derive(serde::Serialize, serde::Deserialize),
38 serde(rename_all = "lowercase")
39)]
40pub enum DataKind {
41 Bin,
42 Wgsl,
43
44 Ron,
46 Spv,
47 Dxil,
48 Hlsl,
49 Msl,
50 Glsl,
51}
52
53impl core::fmt::Display for DataKind {
54 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55 let s = match self {
56 DataKind::Bin => "bin",
57 DataKind::Wgsl => "wgsl",
58 DataKind::Ron => "ron",
59 DataKind::Spv => "spv",
60 DataKind::Dxil => "dxil",
61 DataKind::Hlsl => "hlsl",
62 DataKind::Msl => "msl",
63 DataKind::Glsl => "glsl",
64 };
65 write!(f, "{s}")
66 }
67}
68
69impl DataKind {
70 #[cfg(feature = "replay")]
71 fn is_string(&self) -> bool {
72 match *self {
73 DataKind::Wgsl | DataKind::Ron | DataKind::Hlsl | DataKind::Msl | DataKind::Glsl => {
74 true
75 }
76 DataKind::Bin | DataKind::Spv | DataKind::Dxil => false,
77 }
78 }
79}
80
81impl Data {
82 pub fn kind(&self) -> DataKind {
83 match self {
84 Data::File(file) => {
85 if file.ends_with(".bin") {
86 DataKind::Bin
87 } else if file.ends_with(".wgsl") {
88 DataKind::Wgsl
89 } else if file.ends_with(".ron") {
90 DataKind::Ron
91 } else if file.ends_with(".spv") {
92 DataKind::Spv
93 } else if file.ends_with(".dxil") {
94 DataKind::Dxil
95 } else if file.ends_with(".hlsl") {
96 DataKind::Hlsl
97 } else if file.ends_with(".msl") {
98 DataKind::Msl
99 } else if file.ends_with(".glsl") {
100 DataKind::Glsl
101 } else {
102 panic!("unknown data file extension: {file}");
103 }
104 }
105 Data::String(kind, _) => *kind,
106 Data::Binary(kind, _) => *kind,
107 }
108 }
109}
110
111#[allow(clippy::large_enum_variant)]
112#[derive(Debug)]
113#[apply(serde_object_reference_struct)]
114pub enum Action<'a, R: ReferenceType> {
115 Init {
116 desc: crate::device::DeviceDescriptor<'a>,
117 backend: wgt::Backend,
118 },
119 ConfigureSurface(
120 R::Surface,
121 wgt::SurfaceConfiguration<Vec<wgt::TextureFormat>>,
122 ),
123 CreateBuffer(R::Buffer, crate::resource::BufferDescriptor<'a>),
124 FreeBuffer(R::Buffer),
125 DestroyBuffer(R::Buffer),
126 CreateTexture(R::Texture, crate::resource::TextureDescriptor<'a>),
127 FreeTexture(R::Texture),
128 DestroyTexture(R::Texture),
129 CreateTextureView {
130 id: R::TextureView,
131 parent: R::Texture,
132 desc: crate::resource::TextureViewDescriptor<'a>,
133 },
134 DestroyTextureView(R::TextureView),
135 CreateExternalTexture {
136 id: R::ExternalTexture,
137 desc: crate::resource::ExternalTextureDescriptor<'a>,
138 planes: alloc::boxed::Box<[R::TextureView]>,
139 },
140 FreeExternalTexture(R::ExternalTexture),
141 DestroyExternalTexture(R::ExternalTexture),
142 CreateSampler(
143 PointerId<markers::Sampler>,
144 crate::resource::SamplerDescriptor<'a>,
145 ),
146 DestroySampler(PointerId<markers::Sampler>),
147 GetSurfaceTexture {
148 id: R::Texture,
149 parent: R::Surface,
150 },
151 Present(R::Surface),
152 DiscardSurfaceTexture(R::Surface),
153 CreateBindGroupLayout(
154 PointerId<markers::BindGroupLayout>,
155 crate::binding_model::BindGroupLayoutDescriptor<'a>,
156 ),
157 GetRenderPipelineBindGroupLayout {
158 id: PointerId<markers::BindGroupLayout>,
159 pipeline: PointerId<markers::RenderPipeline>,
160 index: u32,
161 },
162 GetComputePipelineBindGroupLayout {
163 id: PointerId<markers::BindGroupLayout>,
164 pipeline: PointerId<markers::ComputePipeline>,
165 index: u32,
166 },
167 DestroyBindGroupLayout(PointerId<markers::BindGroupLayout>),
168 CreatePipelineLayout(
169 PointerId<markers::PipelineLayout>,
170 crate::binding_model::ResolvedPipelineLayoutDescriptor<
171 'a,
172 PointerId<markers::BindGroupLayout>,
173 >,
174 ),
175 DestroyPipelineLayout(PointerId<markers::PipelineLayout>),
176 CreateBindGroup(PointerId<markers::BindGroup>, TraceBindGroupDescriptor<'a>),
177 DestroyBindGroup(PointerId<markers::BindGroup>),
178 CreateShaderModule {
179 id: PointerId<markers::ShaderModule>,
180 desc: crate::pipeline::ShaderModuleDescriptor<'a>,
181 data: Data,
182 },
183 CreateShaderModulePassthrough {
184 id: PointerId<markers::ShaderModule>,
185 data: Vec<Data>,
186
187 entry_point: String,
188 label: crate::Label<'a>,
189 num_workgroups: (u32, u32, u32),
190 runtime_checks: wgt::ShaderRuntimeChecks,
191 },
192 DestroyShaderModule(PointerId<markers::ShaderModule>),
193 CreateComputePipeline {
194 id: PointerId<markers::ComputePipeline>,
195 desc: TraceComputePipelineDescriptor<'a>,
196 },
197 DestroyComputePipeline(PointerId<markers::ComputePipeline>),
198 CreateGeneralRenderPipeline {
199 id: PointerId<markers::RenderPipeline>,
200 desc: TraceGeneralRenderPipelineDescriptor<'a>,
201 },
202 DestroyRenderPipeline(PointerId<markers::RenderPipeline>),
203 CreatePipelineCache {
204 id: PointerId<markers::PipelineCache>,
205 desc: crate::pipeline::PipelineCacheDescriptor<'a>,
206 },
207 DestroyPipelineCache(PointerId<markers::PipelineCache>),
208 CreateRenderBundle {
209 id: R::RenderBundle,
210 desc: crate::command::RenderBundleEncoderDescriptor<'a>,
211 base: BasePass<RenderCommand<R>, Infallible>,
212 },
213 DestroyRenderBundle(PointerId<markers::RenderBundle>),
214 CreateQuerySet {
215 id: PointerId<markers::QuerySet>,
216 desc: crate::resource::QuerySetDescriptor<'a>,
217 },
218 DestroyQuerySet(PointerId<markers::QuerySet>),
219 WriteBuffer {
220 id: R::Buffer,
221 data: Data,
222 range: Range<wgt::BufferAddress>,
223 queued: bool,
224 },
225 WriteTexture {
226 to: wgt::TexelCopyTextureInfo<R::Texture>,
227 data: Data,
228 layout: wgt::TexelCopyBufferLayout,
229 size: wgt::Extent3d,
230 },
231 Submit(crate::SubmissionIndex, Vec<Command<R>>),
232 FailedCommands {
233 commands: Option<Vec<Command<R>>>,
234 failed_at_submit: Option<crate::SubmissionIndex>,
238 error: String,
239 },
240 CreateBlas {
241 id: R::Blas,
242 desc: crate::resource::BlasDescriptor<'a>,
243 sizes: wgt::BlasGeometrySizeDescriptors,
244 },
245 DestroyBlas(R::Blas),
246 CreateTlas {
247 id: R::Tlas,
248 desc: crate::resource::TlasDescriptor<'a>,
249 },
250 DestroyTlas(R::Tlas),
251}
252
253pub type TraceBindGroupDescriptor<'a> = crate::binding_model::BindGroupDescriptor<
255 'a,
256 PointerId<markers::BindGroupLayout>,
257 PointerId<markers::Buffer>,
258 PointerId<markers::Sampler>,
259 PointerId<markers::TextureView>,
260 PointerId<markers::Tlas>,
261 PointerId<markers::ExternalTexture>,
262>;
263
264#[doc(hidden)]
268pub type TraceGeneralRenderPipelineDescriptor<'a> = GeneralRenderPipelineDescriptor<
269 'a,
270 PointerId<markers::PipelineLayout>,
271 PointerId<markers::ShaderModule>,
272 PointerId<markers::PipelineCache>,
273>;
274
275#[doc(hidden)]
279pub type TraceComputePipelineDescriptor<'a> = crate::pipeline::ComputePipelineDescriptor<
280 'a,
281 PointerId<markers::PipelineLayout>,
282 PointerId<markers::ShaderModule>,
283 PointerId<markers::PipelineCache>,
284>;