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