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::ResolvedPipelineLayoutDescriptor<
177 'a,
178 PointerId<markers::BindGroupLayout>,
179 >,
180 ),
181 DropPipelineLayout(PointerId<markers::PipelineLayout>),
182 CreateBindGroup(PointerId<markers::BindGroup>, TraceBindGroupDescriptor<'a>),
183 DropBindGroup(PointerId<markers::BindGroup>),
184 CreateShaderModule {
185 id: PointerId<markers::ShaderModule>,
186 desc: crate::pipeline::ShaderModuleDescriptor<'a>,
187 data: Data,
188 },
189 CreateShaderModulePassthrough {
190 id: PointerId<markers::ShaderModule>,
191 data: Vec<Data>,
192
193 label: crate::Label<'a>,
194 entry_points: Cow<'a, [wgt::PassthroughShaderEntryPoint<'a>]>,
195 },
196 DropShaderModule(PointerId<markers::ShaderModule>),
197 CreateComputePipeline {
198 id: PointerId<markers::ComputePipeline>,
199 desc: TraceComputePipelineDescriptor<'a>,
200 },
201 DropComputePipeline(PointerId<markers::ComputePipeline>),
202 CreateGeneralRenderPipeline {
203 id: PointerId<markers::RenderPipeline>,
204 desc: TraceGeneralRenderPipelineDescriptor<'a>,
205 },
206 DropRenderPipeline(PointerId<markers::RenderPipeline>),
207 CreatePipelineCache {
208 id: PointerId<markers::PipelineCache>,
209 desc: crate::pipeline::PipelineCacheDescriptor<'a>,
210 },
211 DropPipelineCache(PointerId<markers::PipelineCache>),
212 CreateRenderBundle {
213 id: R::RenderBundle,
214 desc: crate::command::RenderBundleEncoderDescriptor<'a>,
215 base: BasePass<RenderCommand<R>, Infallible>,
216 },
217 DropRenderBundle(PointerId<markers::RenderBundle>),
218 CreateQuerySet {
219 id: PointerId<markers::QuerySet>,
220 desc: crate::resource::QuerySetDescriptor<'a>,
221 },
222 DropQuerySet(PointerId<markers::QuerySet>),
223 DestroyQuerySet(PointerId<markers::QuerySet>),
224 WriteBuffer {
225 id: R::Buffer,
226 data: Data,
227 offset: wgt::BufferAddress,
228 size: wgt::BufferAddress,
229 queued: bool,
230 },
231 WriteTexture {
232 to: wgt::TexelCopyTextureInfo<R::Texture>,
233 data: Data,
234 layout: wgt::TexelCopyBufferLayout,
235 size: wgt::Extent3d,
236 },
237 Submit(crate::SubmissionIndex, Vec<Command<R>>),
238 FailedCommands {
239 commands: Option<Vec<Command<R>>>,
240 failed_at_submit: Option<crate::SubmissionIndex>,
244 error: String,
245 },
246 CreateBlas {
247 id: R::Blas,
248 desc: crate::resource::BlasDescriptor<'a>,
249 sizes: wgt::BlasGeometrySizeDescriptors,
250 },
251 DropBlas(R::Blas),
252 CreateTlas {
253 id: R::Tlas,
254 desc: crate::resource::TlasDescriptor<'a>,
255 },
256 DropTlas(R::Tlas),
257}
258
259pub type TraceBindGroupDescriptor<'a> = crate::binding_model::BindGroupDescriptor<
261 'a,
262 PointerId<markers::BindGroupLayout>,
263 PointerId<markers::Buffer>,
264 PointerId<markers::Sampler>,
265 PointerId<markers::TextureView>,
266 PointerId<markers::Tlas>,
267 PointerId<markers::ExternalTexture>,
268>;
269
270#[doc(hidden)]
274pub type TraceGeneralRenderPipelineDescriptor<'a> = GeneralRenderPipelineDescriptor<
275 'a,
276 PointerId<markers::PipelineLayout>,
277 PointerId<markers::ShaderModule>,
278 PointerId<markers::PipelineCache>,
279>;
280
281#[doc(hidden)]
285pub type TraceComputePipelineDescriptor<'a> = crate::pipeline::ComputePipelineDescriptor<
286 'a,
287 PointerId<markers::PipelineLayout>,
288 PointerId<markers::ShaderModule>,
289 PointerId<markers::PipelineCache>,
290>;