1use alloc::{borrow::Cow, string::ToString, sync::Arc, vec::Vec};
2use core::{any::Any, convert::Infallible};
3use std::io::Write as _;
4
5use crate::{
6 command::{
7 ArcCommand, ArcComputeCommand, ArcPassTimestampWrites, ArcReferences, ArcRenderCommand,
8 BasePass, ColorAttachments, Command, ComputeCommand, PointerReferences, RenderCommand,
9 RenderPassColorAttachment, ResolvedRenderPassDepthStencilAttachment,
10 },
11 device::trace::{Data, DataKind},
12 id::{markers, PointerId},
13 storage::StorageItem,
14};
15
16use super::{
17 Action, TraceBindGroupDescriptor, TraceComputePipelineDescriptor,
18 TraceGeneralRenderPipelineDescriptor, FILE_NAME,
19};
20
21pub(crate) fn new_render_bundle_encoder_descriptor(
22 label: crate::Label<'_>,
23 context: &crate::device::RenderPassContext,
24 depth_read_only: bool,
25 stencil_read_only: bool,
26) -> crate::command::RenderBundleEncoderDescriptor<'static> {
27 crate::command::RenderBundleEncoderDescriptor {
28 label: label.map(|l| Cow::from(l.to_string())),
29 color_formats: Cow::from(context.attachments.colors.to_vec()),
30 depth_stencil: context.attachments.depth_stencil.map(|format| {
31 wgt::RenderBundleDepthStencil {
32 format,
33 depth_read_only,
34 stencil_read_only,
35 }
36 }),
37 sample_count: context.sample_count,
38 multiview: context.multiview_mask,
39 }
40}
41
42pub trait Trace: Any + Send + Sync {
43 fn make_binary(&mut self, kind: DataKind, data: &[u8]) -> Data;
44
45 fn make_string(&mut self, kind: DataKind, data: &str) -> Data;
46
47 fn add(&mut self, action: Action<'_, PointerReferences>)
48 where
49 for<'a> Action<'a, PointerReferences>: serde::Serialize;
50}
51
52#[derive(Debug)]
53pub struct DiskTrace {
54 path: std::path::PathBuf,
55 file: std::fs::File,
56 config: ron::ser::PrettyConfig,
57 data_id: usize,
58}
59
60impl DiskTrace {
61 pub fn new(path: std::path::PathBuf) -> Result<Self, std::io::Error> {
62 log::debug!("Tracing into '{path:?}'");
63 let mut file = std::fs::File::create(path.join(FILE_NAME))?;
64 file.write_all(b"[\n")?;
65 Ok(Self {
66 path,
67 file,
68 config: ron::ser::PrettyConfig::default(),
69 data_id: 0,
70 })
71 }
72}
73
74impl Trace for DiskTrace {
75 fn make_binary(&mut self, kind: DataKind, data: &[u8]) -> Data {
80 self.data_id += 1;
81 let name = std::format!("data{}.{}", self.data_id, kind);
82 let _ = std::fs::write(self.path.join(&name), data);
83 Data::File(name)
84 }
85
86 fn make_string(&mut self, kind: DataKind, data: &str) -> Data {
91 self.make_binary(kind, data.as_bytes())
92 }
93
94 fn add(&mut self, action: Action<'_, PointerReferences>)
95 where
96 for<'a> Action<'a, PointerReferences>: serde::Serialize,
97 {
98 match ron::ser::to_string_pretty(&action, self.config.clone()) {
99 Ok(string) => {
100 let _ = writeln!(self.file, "{string},");
101 }
102 Err(e) => {
103 log::warn!("RON serialization failure: {e:?}");
104 }
105 }
106 }
107}
108
109impl Drop for DiskTrace {
110 fn drop(&mut self) {
111 let _ = self.file.write_all(b"]");
112 }
113}
114
115#[derive(Default)]
116pub struct MemoryTrace {
117 actions: Vec<Action<'static, PointerReferences>>,
118}
119
120impl MemoryTrace {
121 pub fn new() -> Self {
122 Self::default()
123 }
124
125 pub fn actions(&self) -> &[Action<'static, PointerReferences>] {
126 &self.actions
127 }
128}
129
130impl Trace for MemoryTrace {
131 fn make_binary(&mut self, kind: DataKind, data: &[u8]) -> Data {
136 Data::Binary(kind, data.to_vec())
137 }
138
139 fn make_string(&mut self, kind: DataKind, data: &str) -> Data {
144 Data::String(kind, data.to_string())
145 }
146
147 fn add(&mut self, action: Action<'_, PointerReferences>)
148 where
149 for<'a> Action<'a, PointerReferences>: serde::Serialize,
150 {
151 self.actions.push(action_to_owned(action))
152 }
153}
154
155pub(crate) trait IntoTrace {
156 type Output;
157 fn into_trace(self) -> Self::Output;
158
159 fn to_trace(&self) -> Self::Output
160 where
161 Self: Sized + Clone,
162 {
163 self.clone().into_trace()
164 }
165}
166
167impl<T: StorageItem> IntoTrace for Arc<T> {
168 type Output = PointerId<T::Marker>;
169 fn into_trace(self) -> Self::Output {
170 self.to_trace()
171 }
172
173 fn to_trace(&self) -> Self::Output {
174 PointerId::from(self)
175 }
176}
177
178impl IntoTrace for ArcCommand {
179 type Output = Command<PointerReferences>;
180 fn into_trace(self) -> Self::Output {
181 match self {
182 ArcCommand::CopyBufferToBuffer {
183 src,
184 src_offset,
185 dst,
186 dst_offset,
187 size,
188 } => Command::CopyBufferToBuffer {
189 src: src.to_trace(),
190 src_offset,
191 dst: dst.to_trace(),
192 dst_offset,
193 size,
194 },
195 ArcCommand::CopyBufferToTexture { src, dst, size } => Command::CopyBufferToTexture {
196 src: src.into_trace(),
197 dst: dst.into_trace(),
198 size,
199 },
200 ArcCommand::CopyTextureToBuffer { src, dst, size } => Command::CopyTextureToBuffer {
201 src: src.into_trace(),
202 dst: dst.into_trace(),
203 size,
204 },
205 ArcCommand::CopyTextureToTexture { src, dst, size } => Command::CopyTextureToTexture {
206 src: src.into_trace(),
207 dst: dst.into_trace(),
208 size,
209 },
210 ArcCommand::ClearBuffer { dst, offset, size } => Command::ClearBuffer {
211 dst: dst.to_trace(),
212 offset,
213 size,
214 },
215 ArcCommand::ClearTexture {
216 dst,
217 subresource_range,
218 } => Command::ClearTexture {
219 dst: dst.to_trace(),
220 subresource_range,
221 },
222 ArcCommand::WriteTimestamp {
223 query_set,
224 query_index,
225 } => Command::WriteTimestamp {
226 query_set: query_set.to_trace(),
227 query_index,
228 },
229 ArcCommand::ResolveQuerySet {
230 query_set,
231 start_query,
232 query_count,
233 destination,
234 destination_offset,
235 } => Command::ResolveQuerySet {
236 query_set: query_set.to_trace(),
237 start_query,
238 query_count,
239 destination: destination.to_trace(),
240 destination_offset,
241 },
242 ArcCommand::PushDebugGroup(label) => Command::PushDebugGroup(label),
243 ArcCommand::PopDebugGroup => Command::PopDebugGroup,
244 ArcCommand::InsertDebugMarker(label) => Command::InsertDebugMarker(label),
245 ArcCommand::RunComputePass {
246 pass,
247 timestamp_writes,
248 } => Command::RunComputePass {
249 pass: pass.into_trace(),
250 timestamp_writes: timestamp_writes.map(|tw| tw.into_trace()),
251 },
252 ArcCommand::RunRenderPass {
253 pass,
254 color_attachments,
255 depth_stencil_attachment,
256 timestamp_writes,
257 occlusion_query_set,
258 multiview_mask,
259 } => Command::RunRenderPass {
260 pass: pass.into_trace(),
261 color_attachments: color_attachments.into_trace(),
262 depth_stencil_attachment: depth_stencil_attachment.map(|d| d.into_trace()),
263 timestamp_writes: timestamp_writes.map(|tw| tw.into_trace()),
264 occlusion_query_set: occlusion_query_set.map(|q| q.to_trace()),
265 multiview_mask,
266 },
267 ArcCommand::BuildAccelerationStructures { blas, tlas } => {
268 Command::BuildAccelerationStructures {
269 blas: blas.into_iter().map(|b| b.into_trace()).collect(),
270 tlas: tlas.into_iter().map(|b| b.into_trace()).collect(),
271 }
272 }
273 ArcCommand::TransitionResources {
274 buffer_transitions: _,
275 texture_transitions: _,
276 } => {
277 panic!("TransitionResources cannot be converted to Command");
280 }
281 }
282 }
283}
284
285impl<T: IntoTrace> IntoTrace for wgt::TexelCopyBufferInfo<T> {
286 type Output = wgt::TexelCopyBufferInfo<T::Output>;
287 fn into_trace(self) -> Self::Output {
288 wgt::TexelCopyBufferInfo {
289 buffer: self.buffer.into_trace(),
290 layout: self.layout,
291 }
292 }
293}
294
295impl<T: IntoTrace> IntoTrace for wgt::TexelCopyTextureInfo<T> {
296 type Output = wgt::TexelCopyTextureInfo<T::Output>;
297 fn into_trace(self) -> Self::Output {
298 wgt::TexelCopyTextureInfo {
299 texture: self.texture.into_trace(),
300 mip_level: self.mip_level,
301 origin: self.origin,
302 aspect: self.aspect,
303 }
304 }
305}
306
307impl IntoTrace for ArcPassTimestampWrites {
308 type Output = crate::command::PassTimestampWrites<PointerId<markers::QuerySet>>;
309 fn into_trace(self) -> Self::Output {
310 crate::command::PassTimestampWrites {
311 query_set: self.query_set.into_trace(),
312 beginning_of_pass_write_index: self.beginning_of_pass_write_index,
313 end_of_pass_write_index: self.end_of_pass_write_index,
314 }
315 }
316}
317
318impl IntoTrace for ColorAttachments {
319 type Output = ColorAttachments<PointerId<markers::TextureView>>;
320 fn into_trace(self) -> Self::Output {
321 self.into_iter()
322 .map(|opt| {
323 opt.map(|att| RenderPassColorAttachment {
324 view: att.view.into_trace(),
325 depth_slice: att.depth_slice,
326 resolve_target: att.resolve_target.map(|r| r.into_trace()),
327 load_op: att.load_op,
328 store_op: att.store_op,
329 })
330 })
331 .collect()
332 }
333}
334
335impl<TV: IntoTrace> IntoTrace for ResolvedRenderPassDepthStencilAttachment<TV> {
336 type Output = ResolvedRenderPassDepthStencilAttachment<TV::Output>;
337 fn into_trace(self) -> Self::Output {
338 ResolvedRenderPassDepthStencilAttachment {
339 view: self.view.into_trace(),
340 depth: self.depth,
341 stencil: self.stencil,
342 }
343 }
344}
345
346impl IntoTrace for crate::ray_tracing::OwnedBlasBuildEntry<ArcReferences> {
347 type Output = crate::ray_tracing::OwnedBlasBuildEntry<PointerReferences>;
348 fn into_trace(self) -> Self::Output {
349 crate::ray_tracing::OwnedBlasBuildEntry {
350 blas: self.blas.into_trace(),
351 geometries: self.geometries.into_trace(),
352 }
353 }
354}
355
356impl IntoTrace for crate::ray_tracing::OwnedBlasGeometries<ArcReferences> {
357 type Output = crate::ray_tracing::OwnedBlasGeometries<PointerReferences>;
358 fn into_trace(self) -> Self::Output {
359 match self {
360 crate::ray_tracing::OwnedBlasGeometries::TriangleGeometries(geos) => {
361 crate::ray_tracing::OwnedBlasGeometries::TriangleGeometries(
362 geos.into_iter().map(|g| g.into_trace()).collect(),
363 )
364 }
365 }
366 }
367}
368
369impl IntoTrace for crate::ray_tracing::OwnedBlasTriangleGeometry<ArcReferences> {
370 type Output = crate::ray_tracing::OwnedBlasTriangleGeometry<PointerReferences>;
371 fn into_trace(self) -> Self::Output {
372 crate::ray_tracing::OwnedBlasTriangleGeometry {
373 size: self.size,
374 vertex_buffer: self.vertex_buffer.into_trace(),
375 index_buffer: self.index_buffer.map(|b| b.into_trace()),
376 transform_buffer: self.transform_buffer.map(|b| b.into_trace()),
377 first_vertex: self.first_vertex,
378 vertex_stride: self.vertex_stride,
379 first_index: self.first_index,
380 transform_buffer_offset: self.transform_buffer_offset,
381 }
382 }
383}
384
385impl IntoTrace for crate::ray_tracing::OwnedTlasPackage<ArcReferences> {
386 type Output = crate::ray_tracing::OwnedTlasPackage<PointerReferences>;
387 fn into_trace(self) -> Self::Output {
388 crate::ray_tracing::OwnedTlasPackage {
389 tlas: self.tlas.into_trace(),
390 instances: self
391 .instances
392 .into_iter()
393 .map(|opt| opt.map(|inst| inst.into_trace()))
394 .collect(),
395 lowest_unmodified: self.lowest_unmodified,
396 }
397 }
398}
399
400impl IntoTrace for crate::ray_tracing::OwnedTlasInstance<ArcReferences> {
401 type Output = crate::ray_tracing::OwnedTlasInstance<PointerReferences>;
402 fn into_trace(self) -> Self::Output {
403 crate::ray_tracing::OwnedTlasInstance {
404 blas: self.blas.into_trace(),
405 transform: self.transform,
406 custom_data: self.custom_data,
407 mask: self.mask,
408 }
409 }
410}
411
412impl<C: IntoTrace> IntoTrace for BasePass<C, Infallible> {
413 type Output = BasePass<C::Output, Infallible>;
414
415 fn into_trace(self) -> Self::Output {
416 BasePass {
417 label: self.label,
418 error: self.error,
419 commands: self
420 .commands
421 .into_iter()
422 .map(|cmd| cmd.into_trace())
423 .collect(),
424 dynamic_offsets: self.dynamic_offsets,
425 string_data: self.string_data,
426 immediates_data: self.immediates_data,
427 }
428 }
429}
430
431impl IntoTrace for ArcComputeCommand {
432 type Output = ComputeCommand<PointerReferences>;
433 fn into_trace(self) -> Self::Output {
434 use ComputeCommand as C;
435 match self {
436 C::SetBindGroup {
437 index,
438 num_dynamic_offsets,
439 bind_group,
440 } => C::SetBindGroup {
441 index,
442 num_dynamic_offsets,
443 bind_group: bind_group.map(|bg| bg.into_trace()),
444 },
445 C::SetPipeline(id) => C::SetPipeline(id.into_trace()),
446 C::SetImmediate {
447 offset,
448 size_bytes,
449 values_offset,
450 } => C::SetImmediate {
451 offset,
452 size_bytes,
453 values_offset,
454 },
455 C::Dispatch(groups) => C::Dispatch(groups),
456 C::DispatchIndirect { buffer, offset } => C::DispatchIndirect {
457 buffer: buffer.into_trace(),
458 offset,
459 },
460 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
461 C::PopDebugGroup => C::PopDebugGroup,
462 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
463 C::WriteTimestamp {
464 query_set,
465 query_index,
466 } => C::WriteTimestamp {
467 query_set: query_set.into_trace(),
468 query_index,
469 },
470 C::BeginPipelineStatisticsQuery {
471 query_set,
472 query_index,
473 } => C::BeginPipelineStatisticsQuery {
474 query_set: query_set.into_trace(),
475 query_index,
476 },
477 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
478 }
479 }
480}
481
482impl IntoTrace for ArcRenderCommand {
483 type Output = RenderCommand<PointerReferences>;
484 fn into_trace(self) -> Self::Output {
485 use RenderCommand as C;
486 match self {
487 C::SetBindGroup {
488 index,
489 num_dynamic_offsets,
490 bind_group,
491 } => C::SetBindGroup {
492 index,
493 num_dynamic_offsets,
494 bind_group: bind_group.map(|bg| bg.into_trace()),
495 },
496 C::SetPipeline(id) => C::SetPipeline(id.into_trace()),
497 C::SetIndexBuffer {
498 buffer,
499 index_format,
500 offset,
501 size,
502 } => C::SetIndexBuffer {
503 buffer: buffer.into_trace(),
504 index_format,
505 offset,
506 size,
507 },
508 C::SetVertexBuffer {
509 slot,
510 buffer,
511 offset,
512 size,
513 } => C::SetVertexBuffer {
514 slot,
515 buffer: buffer.into_trace(),
516 offset,
517 size,
518 },
519 C::SetBlendConstant(color) => C::SetBlendConstant(color),
520 C::SetStencilReference(val) => C::SetStencilReference(val),
521 C::SetViewport {
522 rect,
523 depth_min,
524 depth_max,
525 } => C::SetViewport {
526 rect,
527 depth_min,
528 depth_max,
529 },
530 C::SetScissor(rect) => C::SetScissor(rect),
531 C::SetImmediate {
532 offset,
533 size_bytes,
534 values_offset,
535 } => C::SetImmediate {
536 offset,
537 size_bytes,
538 values_offset,
539 },
540 C::Draw {
541 vertex_count,
542 instance_count,
543 first_vertex,
544 first_instance,
545 } => C::Draw {
546 vertex_count,
547 instance_count,
548 first_vertex,
549 first_instance,
550 },
551 C::DrawIndexed {
552 index_count,
553 instance_count,
554 first_index,
555 base_vertex,
556 first_instance,
557 } => C::DrawIndexed {
558 index_count,
559 instance_count,
560 first_index,
561 base_vertex,
562 first_instance,
563 },
564 C::DrawMeshTasks {
565 group_count_x,
566 group_count_y,
567 group_count_z,
568 } => C::DrawMeshTasks {
569 group_count_x,
570 group_count_y,
571 group_count_z,
572 },
573 C::DrawIndirect {
574 buffer,
575 offset,
576 count,
577 family,
578 vertex_or_index_limit,
579 instance_limit,
580 } => C::DrawIndirect {
581 buffer: buffer.into_trace(),
582 offset,
583 count,
584 family,
585 vertex_or_index_limit,
586 instance_limit,
587 },
588 C::MultiDrawIndirectCount {
589 buffer,
590 offset,
591 count_buffer,
592 count_buffer_offset,
593 max_count,
594 family,
595 } => C::MultiDrawIndirectCount {
596 buffer: buffer.into_trace(),
597 offset,
598 count_buffer: count_buffer.into_trace(),
599 count_buffer_offset,
600 max_count,
601 family,
602 },
603 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
604 C::PopDebugGroup => C::PopDebugGroup,
605 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
606 C::WriteTimestamp {
607 query_set,
608 query_index,
609 } => C::WriteTimestamp {
610 query_set: query_set.into_trace(),
611 query_index,
612 },
613 C::BeginOcclusionQuery { query_index } => C::BeginOcclusionQuery { query_index },
614 C::EndOcclusionQuery => C::EndOcclusionQuery,
615 C::BeginPipelineStatisticsQuery {
616 query_set,
617 query_index,
618 } => C::BeginPipelineStatisticsQuery {
619 query_set: query_set.into_trace(),
620 query_index,
621 },
622 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
623 C::ExecuteBundle(bundle) => C::ExecuteBundle(bundle.into_trace()),
624 }
625 }
626}
627
628impl IntoTrace for crate::binding_model::ResolvedPipelineLayoutDescriptor<'_> {
629 type Output = crate::binding_model::PipelineLayoutDescriptor<
630 'static,
631 PointerId<markers::BindGroupLayout>,
632 >;
633 fn into_trace(self) -> Self::Output {
634 crate::binding_model::PipelineLayoutDescriptor {
635 label: self.label.map(|l| Cow::Owned(l.into_owned())),
636 bind_group_layouts: self
637 .bind_group_layouts
638 .iter()
639 .map(|bgl| bgl.to_trace())
640 .collect(),
641 immediate_size: self.immediate_size,
642 }
643 }
644}
645
646impl<'a> IntoTrace for &'_ crate::binding_model::ResolvedBindGroupDescriptor<'a> {
647 type Output = TraceBindGroupDescriptor<'a>;
648
649 fn into_trace(self) -> Self::Output {
650 use crate::binding_model::{
651 BindGroupEntry, BindingResource, BufferBinding, ResolvedBindingResource,
652 };
653 TraceBindGroupDescriptor {
654 label: self.label.clone(),
655 layout: self.layout.to_trace(),
656 entries: Cow::Owned(
657 self.entries
658 .iter()
659 .map(|entry| {
660 let resource = match &entry.resource {
661 ResolvedBindingResource::Buffer(buffer_binding) => {
662 BindingResource::Buffer(BufferBinding {
663 buffer: buffer_binding.buffer.to_trace(),
664 offset: buffer_binding.offset,
665 size: buffer_binding.size,
666 })
667 }
668 ResolvedBindingResource::BufferArray(buffer_bindings) => {
669 let resolved_buffers: Vec<_> = buffer_bindings
670 .iter()
671 .map(|bb| BufferBinding {
672 buffer: bb.buffer.to_trace(),
673 offset: bb.offset,
674 size: bb.size,
675 })
676 .collect();
677 BindingResource::BufferArray(Cow::Owned(resolved_buffers))
678 }
679 ResolvedBindingResource::Sampler(sampler_id) => {
680 BindingResource::Sampler(sampler_id.to_trace())
681 }
682 ResolvedBindingResource::SamplerArray(sampler_ids) => {
683 let resolved: Vec<_> =
684 sampler_ids.iter().map(|id| id.to_trace()).collect();
685 BindingResource::SamplerArray(Cow::Owned(resolved))
686 }
687 ResolvedBindingResource::TextureView(texture_view_id) => {
688 BindingResource::TextureView(texture_view_id.to_trace())
689 }
690 ResolvedBindingResource::TextureViewArray(texture_view_ids) => {
691 let resolved: Vec<_> =
692 texture_view_ids.iter().map(|id| id.to_trace()).collect();
693 BindingResource::TextureViewArray(Cow::Owned(resolved))
694 }
695 ResolvedBindingResource::AccelerationStructure(tlas_id) => {
696 BindingResource::AccelerationStructure(tlas_id.to_trace())
697 }
698 ResolvedBindingResource::AccelerationStructureArray(tlas_ids) => {
699 let resolved: Vec<_> =
700 tlas_ids.iter().map(|id| id.to_trace()).collect();
701 BindingResource::AccelerationStructureArray(Cow::Owned(resolved))
702 }
703 ResolvedBindingResource::ExternalTexture(external_texture_id) => {
704 BindingResource::ExternalTexture(external_texture_id.to_trace())
705 }
706 };
707 BindGroupEntry {
708 binding: entry.binding,
709 resource,
710 }
711 })
712 .collect(),
713 ),
714 }
715 }
716}
717
718impl<'a> IntoTrace for crate::pipeline::ResolvedGeneralRenderPipelineDescriptor<'a> {
719 type Output = TraceGeneralRenderPipelineDescriptor<'a>;
720
721 fn into_trace(self) -> Self::Output {
722 TraceGeneralRenderPipelineDescriptor {
723 label: self.label,
724 layout: self.layout.into_trace(),
725 vertex: self.vertex.into_trace(),
726 primitive: self.primitive,
727 depth_stencil: self.depth_stencil,
728 multisample: self.multisample,
729 fragment: self.fragment.map(|f| f.into_trace()),
730 multiview_mask: self.multiview_mask,
731 cache: self.cache.map(|c| c.into_trace()),
732 }
733 }
734}
735
736impl<'a> IntoTrace for crate::pipeline::ResolvedComputePipelineDescriptor<'a> {
737 type Output = TraceComputePipelineDescriptor<'a>;
738
739 fn into_trace(self) -> Self::Output {
740 TraceComputePipelineDescriptor {
741 label: self.label,
742 layout: self.layout.into_trace(),
743 stage: self.stage.into_trace(),
744 cache: self.cache.map(|c| c.into_trace()),
745 }
746 }
747}
748
749impl<'a> IntoTrace for crate::pipeline::ResolvedProgrammableStageDescriptor<'a> {
750 type Output =
751 crate::pipeline::ProgrammableStageDescriptor<'a, PointerId<markers::ShaderModule>>;
752 fn into_trace(self) -> Self::Output {
753 crate::pipeline::ProgrammableStageDescriptor {
754 module: self.module.into_trace(),
755 entry_point: self.entry_point,
756 constants: self.constants,
757 zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
758 }
759 }
760}
761
762impl<'a> IntoTrace
763 for crate::pipeline::RenderPipelineVertexProcessor<'a, Arc<crate::pipeline::ShaderModule>>
764{
765 type Output =
766 crate::pipeline::RenderPipelineVertexProcessor<'a, PointerId<markers::ShaderModule>>;
767 fn into_trace(self) -> Self::Output {
768 match self {
769 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex) => {
770 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex.into_trace())
771 }
772 crate::pipeline::RenderPipelineVertexProcessor::Mesh(task, mesh) => {
773 crate::pipeline::RenderPipelineVertexProcessor::Mesh(
774 task.map(|t| t.into_trace()),
775 mesh.into_trace(),
776 )
777 }
778 }
779 }
780}
781
782impl<'a> IntoTrace for crate::pipeline::ResolvedTaskState<'a> {
783 type Output = crate::pipeline::TaskState<'a, PointerId<markers::ShaderModule>>;
784 fn into_trace(self) -> Self::Output {
785 crate::pipeline::TaskState {
786 stage: self.stage.into_trace(),
787 }
788 }
789}
790
791impl<'a> IntoTrace for crate::pipeline::ResolvedMeshState<'a> {
792 type Output = crate::pipeline::MeshState<'a, PointerId<markers::ShaderModule>>;
793 fn into_trace(self) -> Self::Output {
794 crate::pipeline::MeshState {
795 stage: self.stage.into_trace(),
796 }
797 }
798}
799
800impl<'a> IntoTrace for crate::pipeline::ResolvedVertexState<'a> {
801 type Output = crate::pipeline::VertexState<'a, PointerId<markers::ShaderModule>>;
802 fn into_trace(self) -> Self::Output {
803 crate::pipeline::VertexState {
804 stage: self.stage.into_trace(),
805 buffers: self.buffers,
806 }
807 }
808}
809
810impl<'a> IntoTrace for crate::pipeline::ResolvedFragmentState<'a> {
811 type Output = crate::pipeline::FragmentState<'a, PointerId<markers::ShaderModule>>;
812 fn into_trace(self) -> Self::Output {
813 crate::pipeline::FragmentState {
814 stage: self.stage.into_trace(),
815 targets: self.targets,
816 }
817 }
818}
819
820impl<T: IntoTrace> IntoTrace for Option<T> {
821 type Output = Option<T::Output>;
822 fn into_trace(self) -> Self::Output {
823 self.map(|v| v.into_trace())
824 }
825}
826
827fn action_to_owned(action: Action<'_, PointerReferences>) -> Action<'static, PointerReferences> {
837 use Action as A;
838 match action {
839 A::Init { desc, backend } => A::Init {
840 desc: wgt::DeviceDescriptor {
841 label: desc.label.map(|l| Cow::Owned(l.into_owned())),
842 required_features: desc.required_features,
843 required_limits: desc.required_limits,
844 experimental_features: desc.experimental_features,
845 memory_hints: desc.memory_hints,
846 trace: desc.trace,
847 },
848 backend,
849 },
850 A::ConfigureSurface(surface, config) => A::ConfigureSurface(surface, config),
851 A::CreateBuffer(buffer, desc) => A::CreateBuffer(
852 buffer,
853 wgt::BufferDescriptor {
854 label: desc.label.map(|l| Cow::Owned(l.into_owned())),
855 size: desc.size,
856 usage: desc.usage,
857 mapped_at_creation: desc.mapped_at_creation,
858 },
859 ),
860 A::FreeBuffer(buffer) => A::FreeBuffer(buffer),
861 A::DestroyBuffer(buffer) => A::DestroyBuffer(buffer),
862 A::FreeTexture(texture) => A::FreeTexture(texture),
863 A::DestroyTexture(texture) => A::DestroyTexture(texture),
864 A::DestroyTextureView(texture_view) => A::DestroyTextureView(texture_view),
865 A::FreeExternalTexture(external_texture) => A::FreeExternalTexture(external_texture),
866 A::DestroyExternalTexture(external_texture) => A::DestroyExternalTexture(external_texture),
867 A::DestroySampler(sampler) => A::DestroySampler(sampler),
868 A::GetSurfaceTexture { id, parent } => A::GetSurfaceTexture { id, parent },
869 A::Present(surface) => A::Present(surface),
870 A::DiscardSurfaceTexture(surface) => A::DiscardSurfaceTexture(surface),
871 A::DestroyBindGroupLayout(layout) => A::DestroyBindGroupLayout(layout),
872 A::GetRenderPipelineBindGroupLayout {
873 id,
874 pipeline,
875 index,
876 } => A::GetRenderPipelineBindGroupLayout {
877 id,
878 pipeline,
879 index,
880 },
881 A::GetComputePipelineBindGroupLayout {
882 id,
883 pipeline,
884 index,
885 } => A::GetComputePipelineBindGroupLayout {
886 id,
887 pipeline,
888 index,
889 },
890 A::DestroyPipelineLayout(layout) => A::DestroyPipelineLayout(layout),
891 A::DestroyBindGroup(bind_group) => A::DestroyBindGroup(bind_group),
892 A::DestroyShaderModule(shader_module) => A::DestroyShaderModule(shader_module),
893 A::DestroyComputePipeline(pipeline) => A::DestroyComputePipeline(pipeline),
894 A::DestroyRenderPipeline(pipeline) => A::DestroyRenderPipeline(pipeline),
895 A::DestroyPipelineCache(cache) => A::DestroyPipelineCache(cache),
896 A::DestroyRenderBundle(render_bundle) => A::DestroyRenderBundle(render_bundle),
897 A::DestroyQuerySet(query_set) => A::DestroyQuerySet(query_set),
898 A::WriteBuffer {
899 id,
900 data,
901 offset,
902 size,
903 queued,
904 } => A::WriteBuffer {
905 id,
906 data,
907 offset,
908 size,
909 queued,
910 },
911 A::WriteTexture {
912 to,
913 data,
914 layout,
915 size,
916 } => A::WriteTexture {
917 to,
918 data,
919 layout,
920 size,
921 },
922 A::Submit(index, commands) => A::Submit(index, commands),
923 A::FailedCommands {
924 commands,
925 failed_at_submit,
926 error,
927 } => A::FailedCommands {
928 commands,
929 failed_at_submit,
930 error,
931 },
932 A::DestroyBlas(blas) => A::DestroyBlas(blas),
933 A::DestroyTlas(tlas) => A::DestroyTlas(tlas),
934
935 A::CreateTexture(..)
936 | A::CreateTextureView { .. }
937 | A::CreateExternalTexture { .. }
938 | A::CreateSampler(..)
939 | A::CreateBindGroupLayout(..)
940 | A::CreatePipelineLayout(..)
941 | A::CreateBindGroup(..)
942 | A::CreateShaderModule { .. }
943 | A::CreateShaderModulePassthrough { .. }
944 | A::CreateComputePipeline { .. }
945 | A::CreateGeneralRenderPipeline { .. }
946 | A::CreatePipelineCache { .. }
947 | A::CreateRenderBundle { .. }
948 | A::CreateQuerySet { .. }
949 | A::CreateBlas { .. }
950 | A::CreateTlas { .. } => panic!("Unsupported action for tracing: {action:?}"),
951 }
952}