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 crate::ray_tracing::OwnedBlasGeometries::AabbGeometries(geos) => {
366 crate::ray_tracing::OwnedBlasGeometries::AabbGeometries(
367 geos.into_iter().map(|g| g.into_trace()).collect(),
368 )
369 }
370 }
371 }
372}
373
374impl IntoTrace for crate::ray_tracing::OwnedBlasTriangleGeometry<ArcReferences> {
375 type Output = crate::ray_tracing::OwnedBlasTriangleGeometry<PointerReferences>;
376 fn into_trace(self) -> Self::Output {
377 crate::ray_tracing::OwnedBlasTriangleGeometry {
378 size: self.size,
379 vertex_buffer: self.vertex_buffer.into_trace(),
380 index_buffer: self.index_buffer.map(|b| b.into_trace()),
381 transform_buffer: self.transform_buffer.map(|b| b.into_trace()),
382 first_vertex: self.first_vertex,
383 vertex_stride: self.vertex_stride,
384 first_index: self.first_index,
385 transform_buffer_offset: self.transform_buffer_offset,
386 }
387 }
388}
389
390impl IntoTrace for crate::ray_tracing::OwnedBlasAabbGeometry<ArcReferences> {
391 type Output = crate::ray_tracing::OwnedBlasAabbGeometry<PointerReferences>;
392 fn into_trace(self) -> Self::Output {
393 crate::ray_tracing::OwnedBlasAabbGeometry {
394 size: self.size,
395 stride: self.stride,
396 aabb_buffer: self.aabb_buffer.into_trace(),
397 primitive_offset: self.primitive_offset,
398 }
399 }
400}
401
402impl IntoTrace for crate::ray_tracing::OwnedTlasPackage<ArcReferences> {
403 type Output = crate::ray_tracing::OwnedTlasPackage<PointerReferences>;
404 fn into_trace(self) -> Self::Output {
405 crate::ray_tracing::OwnedTlasPackage {
406 tlas: self.tlas.into_trace(),
407 instances: self
408 .instances
409 .into_iter()
410 .map(|opt| opt.map(|inst| inst.into_trace()))
411 .collect(),
412 lowest_unmodified: self.lowest_unmodified,
413 }
414 }
415}
416
417impl IntoTrace for crate::ray_tracing::OwnedTlasInstance<ArcReferences> {
418 type Output = crate::ray_tracing::OwnedTlasInstance<PointerReferences>;
419 fn into_trace(self) -> Self::Output {
420 crate::ray_tracing::OwnedTlasInstance {
421 blas: self.blas.into_trace(),
422 transform: self.transform,
423 custom_data: self.custom_data,
424 mask: self.mask,
425 }
426 }
427}
428
429impl<C: IntoTrace> IntoTrace for BasePass<C, Infallible> {
430 type Output = BasePass<C::Output, Infallible>;
431
432 fn into_trace(self) -> Self::Output {
433 BasePass {
434 label: self.label,
435 error: self.error,
436 commands: self
437 .commands
438 .into_iter()
439 .map(|cmd| cmd.into_trace())
440 .collect(),
441 dynamic_offsets: self.dynamic_offsets,
442 string_data: self.string_data,
443 immediates_data: self.immediates_data,
444 }
445 }
446}
447
448impl IntoTrace for ArcComputeCommand {
449 type Output = ComputeCommand<PointerReferences>;
450 fn into_trace(self) -> Self::Output {
451 use ComputeCommand as C;
452 match self {
453 C::SetBindGroup {
454 index,
455 num_dynamic_offsets,
456 bind_group,
457 } => C::SetBindGroup {
458 index,
459 num_dynamic_offsets,
460 bind_group: bind_group.map(|bg| bg.into_trace()),
461 },
462 C::SetPipeline(id) => C::SetPipeline(id.into_trace()),
463 C::SetImmediate {
464 offset,
465 size_bytes,
466 values_offset,
467 } => C::SetImmediate {
468 offset,
469 size_bytes,
470 values_offset,
471 },
472 C::DispatchWorkgroups(groups) => C::DispatchWorkgroups(groups),
473 C::DispatchWorkgroupsIndirect { buffer, offset } => C::DispatchWorkgroupsIndirect {
474 buffer: buffer.into_trace(),
475 offset,
476 },
477 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
478 C::PopDebugGroup => C::PopDebugGroup,
479 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
480 C::WriteTimestamp {
481 query_set,
482 query_index,
483 } => C::WriteTimestamp {
484 query_set: query_set.into_trace(),
485 query_index,
486 },
487 C::BeginPipelineStatisticsQuery {
488 query_set,
489 query_index,
490 } => C::BeginPipelineStatisticsQuery {
491 query_set: query_set.into_trace(),
492 query_index,
493 },
494 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
495 C::TransitionResources {
496 buffer_transitions,
497 texture_transitions,
498 } => C::TransitionResources {
499 buffer_transitions: buffer_transitions
500 .into_iter()
501 .map(|buffer_transition| wgt::BufferTransition {
502 buffer: buffer_transition.buffer.into_trace(),
503 state: buffer_transition.state,
504 })
505 .collect(),
506 texture_transitions: texture_transitions
507 .into_iter()
508 .map(|texture_transition| wgt::TextureTransition {
509 texture: texture_transition.texture.into_trace(),
510 selector: texture_transition.selector,
511 state: texture_transition.state,
512 })
513 .collect(),
514 },
515 }
516 }
517}
518
519impl IntoTrace for ArcRenderCommand {
520 type Output = RenderCommand<PointerReferences>;
521 fn into_trace(self) -> Self::Output {
522 use RenderCommand as C;
523 match self {
524 C::SetBindGroup {
525 index,
526 num_dynamic_offsets,
527 bind_group,
528 } => C::SetBindGroup {
529 index,
530 num_dynamic_offsets,
531 bind_group: bind_group.map(|bg| bg.into_trace()),
532 },
533 C::SetPipeline(id) => C::SetPipeline(id.into_trace()),
534 C::SetIndexBuffer {
535 buffer,
536 index_format,
537 offset,
538 size,
539 } => C::SetIndexBuffer {
540 buffer: buffer.into_trace(),
541 index_format,
542 offset,
543 size,
544 },
545 C::SetVertexBuffer {
546 slot,
547 buffer,
548 offset,
549 size,
550 } => C::SetVertexBuffer {
551 slot,
552 buffer: buffer.into_trace(),
553 offset,
554 size,
555 },
556 C::SetBlendConstant(color) => C::SetBlendConstant(color),
557 C::SetStencilReference(val) => C::SetStencilReference(val),
558 C::SetViewport {
559 rect,
560 depth_min,
561 depth_max,
562 } => C::SetViewport {
563 rect,
564 depth_min,
565 depth_max,
566 },
567 C::SetScissor(rect) => C::SetScissor(rect),
568 C::SetImmediate {
569 offset,
570 size_bytes,
571 values_offset,
572 } => C::SetImmediate {
573 offset,
574 size_bytes,
575 values_offset,
576 },
577 C::Draw {
578 vertex_count,
579 instance_count,
580 first_vertex,
581 first_instance,
582 } => C::Draw {
583 vertex_count,
584 instance_count,
585 first_vertex,
586 first_instance,
587 },
588 C::DrawIndexed {
589 index_count,
590 instance_count,
591 first_index,
592 base_vertex,
593 first_instance,
594 } => C::DrawIndexed {
595 index_count,
596 instance_count,
597 first_index,
598 base_vertex,
599 first_instance,
600 },
601 C::DrawMeshTasks {
602 group_count_x,
603 group_count_y,
604 group_count_z,
605 } => C::DrawMeshTasks {
606 group_count_x,
607 group_count_y,
608 group_count_z,
609 },
610 C::DrawIndirect {
611 buffer,
612 offset,
613 count,
614 family,
615 vertex_or_index_limit,
616 instance_limit,
617 } => C::DrawIndirect {
618 buffer: buffer.into_trace(),
619 offset,
620 count,
621 family,
622 vertex_or_index_limit,
623 instance_limit,
624 },
625 C::MultiDrawIndirectCount {
626 buffer,
627 offset,
628 count_buffer,
629 count_buffer_offset,
630 max_count,
631 family,
632 } => C::MultiDrawIndirectCount {
633 buffer: buffer.into_trace(),
634 offset,
635 count_buffer: count_buffer.into_trace(),
636 count_buffer_offset,
637 max_count,
638 family,
639 },
640 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
641 C::PopDebugGroup => C::PopDebugGroup,
642 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
643 C::WriteTimestamp {
644 query_set,
645 query_index,
646 } => C::WriteTimestamp {
647 query_set: query_set.into_trace(),
648 query_index,
649 },
650 C::BeginOcclusionQuery { query_index } => C::BeginOcclusionQuery { query_index },
651 C::EndOcclusionQuery => C::EndOcclusionQuery,
652 C::BeginPipelineStatisticsQuery {
653 query_set,
654 query_index,
655 } => C::BeginPipelineStatisticsQuery {
656 query_set: query_set.into_trace(),
657 query_index,
658 },
659 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
660 C::ExecuteBundle(bundle) => C::ExecuteBundle(bundle.into_trace()),
661 }
662 }
663}
664
665impl IntoTrace for crate::binding_model::ResolvedPipelineLayoutDescriptor<'_> {
666 type Output = crate::binding_model::PipelineLayoutDescriptor<
667 'static,
668 PointerId<markers::BindGroupLayout>,
669 >;
670 fn into_trace(self) -> Self::Output {
671 crate::binding_model::PipelineLayoutDescriptor {
672 label: self.label.map(|l| Cow::Owned(l.into_owned())),
673 bind_group_layouts: self
674 .bind_group_layouts
675 .iter()
676 .map(|bgl| bgl.to_trace())
677 .collect(),
678 immediate_size: self.immediate_size,
679 }
680 }
681}
682
683impl<'a> IntoTrace for &'_ crate::binding_model::ResolvedBindGroupDescriptor<'a> {
684 type Output = TraceBindGroupDescriptor<'a>;
685
686 fn into_trace(self) -> Self::Output {
687 use crate::binding_model::{
688 BindGroupEntry, BindingResource, BufferBinding, ResolvedBindingResource,
689 };
690 TraceBindGroupDescriptor {
691 label: self.label.clone(),
692 layout: self.layout.to_trace(),
693 entries: Cow::Owned(
694 self.entries
695 .iter()
696 .map(|entry| {
697 let resource = match &entry.resource {
698 ResolvedBindingResource::Buffer(buffer_binding) => {
699 BindingResource::Buffer(BufferBinding {
700 buffer: buffer_binding.buffer.to_trace(),
701 offset: buffer_binding.offset,
702 size: buffer_binding.size,
703 })
704 }
705 ResolvedBindingResource::BufferArray(buffer_bindings) => {
706 let resolved_buffers: Vec<_> = buffer_bindings
707 .iter()
708 .map(|bb| BufferBinding {
709 buffer: bb.buffer.to_trace(),
710 offset: bb.offset,
711 size: bb.size,
712 })
713 .collect();
714 BindingResource::BufferArray(Cow::Owned(resolved_buffers))
715 }
716 ResolvedBindingResource::Sampler(sampler_id) => {
717 BindingResource::Sampler(sampler_id.to_trace())
718 }
719 ResolvedBindingResource::SamplerArray(sampler_ids) => {
720 let resolved: Vec<_> =
721 sampler_ids.iter().map(|id| id.to_trace()).collect();
722 BindingResource::SamplerArray(Cow::Owned(resolved))
723 }
724 ResolvedBindingResource::TextureView(texture_view_id) => {
725 BindingResource::TextureView(texture_view_id.to_trace())
726 }
727 ResolvedBindingResource::TextureViewArray(texture_view_ids) => {
728 let resolved: Vec<_> =
729 texture_view_ids.iter().map(|id| id.to_trace()).collect();
730 BindingResource::TextureViewArray(Cow::Owned(resolved))
731 }
732 ResolvedBindingResource::AccelerationStructure(tlas_id) => {
733 BindingResource::AccelerationStructure(tlas_id.to_trace())
734 }
735 ResolvedBindingResource::AccelerationStructureArray(tlas_ids) => {
736 let resolved: Vec<_> =
737 tlas_ids.iter().map(|id| id.to_trace()).collect();
738 BindingResource::AccelerationStructureArray(Cow::Owned(resolved))
739 }
740 ResolvedBindingResource::ExternalTexture(external_texture_id) => {
741 BindingResource::ExternalTexture(external_texture_id.to_trace())
742 }
743 };
744 BindGroupEntry {
745 binding: entry.binding,
746 resource,
747 }
748 })
749 .collect(),
750 ),
751 }
752 }
753}
754
755impl<'a> IntoTrace for crate::pipeline::ResolvedGeneralRenderPipelineDescriptor<'a> {
756 type Output = TraceGeneralRenderPipelineDescriptor<'a>;
757
758 fn into_trace(self) -> Self::Output {
759 TraceGeneralRenderPipelineDescriptor {
760 label: self.label,
761 layout: self.layout.into_trace(),
762 vertex: self.vertex.into_trace(),
763 primitive: self.primitive,
764 depth_stencil: self.depth_stencil,
765 multisample: self.multisample,
766 fragment: self.fragment.map(|f| f.into_trace()),
767 multiview_mask: self.multiview_mask,
768 cache: self.cache.map(|c| c.into_trace()),
769 }
770 }
771}
772
773impl<'a> IntoTrace for crate::pipeline::ResolvedComputePipelineDescriptor<'a> {
774 type Output = TraceComputePipelineDescriptor<'a>;
775
776 fn into_trace(self) -> Self::Output {
777 TraceComputePipelineDescriptor {
778 label: self.label,
779 layout: self.layout.into_trace(),
780 stage: self.stage.into_trace(),
781 cache: self.cache.map(|c| c.into_trace()),
782 }
783 }
784}
785
786impl<'a> IntoTrace for crate::pipeline::ResolvedProgrammableStageDescriptor<'a> {
787 type Output =
788 crate::pipeline::ProgrammableStageDescriptor<'a, PointerId<markers::ShaderModule>>;
789 fn into_trace(self) -> Self::Output {
790 crate::pipeline::ProgrammableStageDescriptor {
791 module: self.module.into_trace(),
792 entry_point: self.entry_point,
793 constants: self.constants,
794 zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
795 }
796 }
797}
798
799impl<'a> IntoTrace
800 for crate::pipeline::RenderPipelineVertexProcessor<'a, Arc<crate::pipeline::ShaderModule>>
801{
802 type Output =
803 crate::pipeline::RenderPipelineVertexProcessor<'a, PointerId<markers::ShaderModule>>;
804 fn into_trace(self) -> Self::Output {
805 match self {
806 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex) => {
807 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex.into_trace())
808 }
809 crate::pipeline::RenderPipelineVertexProcessor::Mesh(task, mesh) => {
810 crate::pipeline::RenderPipelineVertexProcessor::Mesh(
811 task.map(|t| t.into_trace()),
812 mesh.into_trace(),
813 )
814 }
815 }
816 }
817}
818
819impl<'a> IntoTrace for crate::pipeline::ResolvedTaskState<'a> {
820 type Output = crate::pipeline::TaskState<'a, PointerId<markers::ShaderModule>>;
821 fn into_trace(self) -> Self::Output {
822 crate::pipeline::TaskState {
823 stage: self.stage.into_trace(),
824 }
825 }
826}
827
828impl<'a> IntoTrace for crate::pipeline::ResolvedMeshState<'a> {
829 type Output = crate::pipeline::MeshState<'a, PointerId<markers::ShaderModule>>;
830 fn into_trace(self) -> Self::Output {
831 crate::pipeline::MeshState {
832 stage: self.stage.into_trace(),
833 }
834 }
835}
836
837impl<'a> IntoTrace for crate::pipeline::ResolvedVertexState<'a> {
838 type Output = crate::pipeline::VertexState<'a, PointerId<markers::ShaderModule>>;
839 fn into_trace(self) -> Self::Output {
840 crate::pipeline::VertexState {
841 stage: self.stage.into_trace(),
842 buffers: self.buffers,
843 }
844 }
845}
846
847impl<'a> IntoTrace for crate::pipeline::ResolvedFragmentState<'a> {
848 type Output = crate::pipeline::FragmentState<'a, PointerId<markers::ShaderModule>>;
849 fn into_trace(self) -> Self::Output {
850 crate::pipeline::FragmentState {
851 stage: self.stage.into_trace(),
852 targets: self.targets,
853 }
854 }
855}
856
857impl<T: IntoTrace> IntoTrace for Option<T> {
858 type Output = Option<T::Output>;
859 fn into_trace(self) -> Self::Output {
860 self.map(|v| v.into_trace())
861 }
862}
863
864fn action_to_owned(action: Action<'_, PointerReferences>) -> Action<'static, PointerReferences> {
874 use Action as A;
875 match action {
876 A::Init { desc, backend } => A::Init {
877 desc: wgt::DeviceDescriptor {
878 label: desc.label.map(|l| Cow::Owned(l.into_owned())),
879 required_features: desc.required_features,
880 required_limits: desc.required_limits,
881 experimental_features: desc.experimental_features,
882 memory_hints: desc.memory_hints,
883 trace: desc.trace,
884 },
885 backend,
886 },
887 A::ConfigureSurface(surface, config) => A::ConfigureSurface(surface, config),
888 A::CreateBuffer(buffer, desc) => A::CreateBuffer(
889 buffer,
890 wgt::BufferDescriptor {
891 label: desc.label.map(|l| Cow::Owned(l.into_owned())),
892 size: desc.size,
893 usage: desc.usage,
894 mapped_at_creation: desc.mapped_at_creation,
895 },
896 ),
897 A::FreeBuffer(buffer) => A::FreeBuffer(buffer),
898 A::DestroyBuffer(buffer) => A::DestroyBuffer(buffer),
899 A::FreeTexture(texture) => A::FreeTexture(texture),
900 A::DestroyTexture(texture) => A::DestroyTexture(texture),
901 A::DestroyTextureView(texture_view) => A::DestroyTextureView(texture_view),
902 A::FreeExternalTexture(external_texture) => A::FreeExternalTexture(external_texture),
903 A::DestroyExternalTexture(external_texture) => A::DestroyExternalTexture(external_texture),
904 A::DestroySampler(sampler) => A::DestroySampler(sampler),
905 A::GetSurfaceTexture { id, parent } => A::GetSurfaceTexture { id, parent },
906 A::Present(surface) => A::Present(surface),
907 A::DiscardSurfaceTexture(surface) => A::DiscardSurfaceTexture(surface),
908 A::DestroyBindGroupLayout(layout) => A::DestroyBindGroupLayout(layout),
909 A::GetRenderPipelineBindGroupLayout {
910 id,
911 pipeline,
912 index,
913 } => A::GetRenderPipelineBindGroupLayout {
914 id,
915 pipeline,
916 index,
917 },
918 A::GetComputePipelineBindGroupLayout {
919 id,
920 pipeline,
921 index,
922 } => A::GetComputePipelineBindGroupLayout {
923 id,
924 pipeline,
925 index,
926 },
927 A::DestroyPipelineLayout(layout) => A::DestroyPipelineLayout(layout),
928 A::DestroyBindGroup(bind_group) => A::DestroyBindGroup(bind_group),
929 A::DestroyShaderModule(shader_module) => A::DestroyShaderModule(shader_module),
930 A::DestroyComputePipeline(pipeline) => A::DestroyComputePipeline(pipeline),
931 A::DestroyRenderPipeline(pipeline) => A::DestroyRenderPipeline(pipeline),
932 A::DestroyPipelineCache(cache) => A::DestroyPipelineCache(cache),
933 A::DestroyRenderBundle(render_bundle) => A::DestroyRenderBundle(render_bundle),
934 A::DestroyQuerySet(query_set) => A::DestroyQuerySet(query_set),
935 A::WriteBuffer {
936 id,
937 data,
938 offset,
939 size,
940 queued,
941 } => A::WriteBuffer {
942 id,
943 data,
944 offset,
945 size,
946 queued,
947 },
948 A::WriteTexture {
949 to,
950 data,
951 layout,
952 size,
953 } => A::WriteTexture {
954 to,
955 data,
956 layout,
957 size,
958 },
959 A::Submit(index, commands) => A::Submit(index, commands),
960 A::FailedCommands {
961 commands,
962 failed_at_submit,
963 error,
964 } => A::FailedCommands {
965 commands,
966 failed_at_submit,
967 error,
968 },
969 A::DestroyBlas(blas) => A::DestroyBlas(blas),
970 A::DestroyTlas(tlas) => A::DestroyTlas(tlas),
971
972 A::CreateTexture(..)
973 | A::CreateTextureView { .. }
974 | A::CreateExternalTexture { .. }
975 | A::CreateSampler(..)
976 | A::CreateBindGroupLayout(..)
977 | A::CreatePipelineLayout(..)
978 | A::CreateBindGroup(..)
979 | A::CreateShaderModule { .. }
980 | A::CreateShaderModulePassthrough { .. }
981 | A::CreateComputePipeline { .. }
982 | A::CreateGeneralRenderPipeline { .. }
983 | A::CreatePipelineCache { .. }
984 | A::CreateRenderBundle { .. }
985 | A::CreateQuerySet { .. }
986 | A::CreateBlas { .. }
987 | A::CreateTlas { .. } => panic!("Unsupported action for tracing: {action:?}"),
988 }
989}