1#[cfg(feature = "trace")]
2mod record;
3#[cfg(feature = "replay")]
4mod replay;
5
6use core::convert::Infallible;
7
8use alloc::{borrow::Cow, 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 DestroyBuffer(R::Buffer),
129 DropBuffer(R::Buffer),
130 CreateTexture(R::Texture, crate::resource::TextureDescriptor<'a>),
131 CreateTextureError(R::Texture, crate::resource::TextureDescriptor<'a>),
132 DestroyTexture(R::Texture),
133 DropTexture(R::Texture),
134 CreateTextureView {
135 id: R::TextureView,
136 parent: R::Texture,
137 desc: crate::resource::TextureViewDescriptor<'a>,
138 },
139 DropTextureView(R::TextureView),
140 CreateExternalTexture {
141 id: R::ExternalTexture,
142 desc: crate::resource::ExternalTextureDescriptor<'a>,
143 planes: alloc::boxed::Box<[R::TextureView]>,
144 },
145 DestroyExternalTexture(R::ExternalTexture),
146 DropExternalTexture(R::ExternalTexture),
147 CreateSampler(
148 PointerId<markers::Sampler>,
149 crate::resource::SamplerDescriptor<'a>,
150 ),
151 DropSampler(PointerId<markers::Sampler>),
152 GetSurfaceTexture {
153 id: R::Texture,
154 parent: R::Surface,
155 },
156 Present(R::Surface),
157 DiscardSurfaceTexture(R::Surface),
158 ReleaseSurfaceTexture(R::Surface),
159 CreateBindGroupLayout(
160 PointerId<markers::BindGroupLayout>,
161 crate::binding_model::BindGroupLayoutDescriptor<'a>,
162 ),
163 GetRenderPipelineBindGroupLayout {
164 id: PointerId<markers::BindGroupLayout>,
165 pipeline: PointerId<markers::RenderPipeline>,
166 index: u32,
167 },
168 GetComputePipelineBindGroupLayout {
169 id: PointerId<markers::BindGroupLayout>,
170 pipeline: PointerId<markers::ComputePipeline>,
171 index: u32,
172 },
173 DropBindGroupLayout(PointerId<markers::BindGroupLayout>),
174 CreatePipelineLayout(
175 PointerId<markers::PipelineLayout>,
176 crate::binding_model::PipelineLayoutDescriptor<'a, PointerId<markers::BindGroupLayout>>,
177 ),
178 DropPipelineLayout(PointerId<markers::PipelineLayout>),
179 CreateBindGroup(PointerId<markers::BindGroup>, TraceBindGroupDescriptor<'a>),
180 DropBindGroup(PointerId<markers::BindGroup>),
181 CreateShaderModule {
182 id: PointerId<markers::ShaderModule>,
183 desc: crate::pipeline::ShaderModuleDescriptor<'a>,
184 data: Data,
185 },
186 CreateShaderModulePassthrough {
187 id: PointerId<markers::ShaderModule>,
188 data: Vec<Data>,
189
190 label: crate::Label<'a>,
191 entry_points: Cow<'a, [wgt::PassthroughShaderEntryPoint<'a>]>,
192 },
193 DropShaderModule(PointerId<markers::ShaderModule>),
194 CreateComputePipeline {
195 id: PointerId<markers::ComputePipeline>,
196 desc: TraceComputePipelineDescriptor<'a>,
197 },
198 DropComputePipeline(PointerId<markers::ComputePipeline>),
199 CreateGeneralRenderPipeline {
200 id: PointerId<markers::RenderPipeline>,
201 desc: TraceGeneralRenderPipelineDescriptor<'a>,
202 },
203 DropRenderPipeline(PointerId<markers::RenderPipeline>),
204 CreatePipelineCache {
205 id: PointerId<markers::PipelineCache>,
206 desc: crate::pipeline::PipelineCacheDescriptor<'a>,
207 },
208 DropPipelineCache(PointerId<markers::PipelineCache>),
209 CreateRenderBundle {
210 id: R::RenderBundle,
211 desc: crate::command::RenderBundleEncoderDescriptor<'a>,
212 base: BasePass<RenderCommand<R>, Infallible>,
213 },
214 DropRenderBundle(PointerId<markers::RenderBundle>),
215 CreateQuerySet {
216 id: PointerId<markers::QuerySet>,
217 desc: crate::resource::QuerySetDescriptor<'a>,
218 },
219 DropQuerySet(PointerId<markers::QuerySet>),
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 DropBlas(R::Blas),
249 CreateTlas {
250 id: R::Tlas,
251 desc: crate::resource::TlasDescriptor<'a>,
252 },
253 DropTlas(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>;