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::ExternalTexture(external_texture_id) => {
699 BindingResource::ExternalTexture(external_texture_id.to_trace())
700 }
701 };
702 BindGroupEntry {
703 binding: entry.binding,
704 resource,
705 }
706 })
707 .collect(),
708 ),
709 }
710 }
711}
712
713impl<'a> IntoTrace for crate::pipeline::ResolvedGeneralRenderPipelineDescriptor<'a> {
714 type Output = TraceGeneralRenderPipelineDescriptor<'a>;
715
716 fn into_trace(self) -> Self::Output {
717 TraceGeneralRenderPipelineDescriptor {
718 label: self.label,
719 layout: self.layout.into_trace(),
720 vertex: self.vertex.into_trace(),
721 primitive: self.primitive,
722 depth_stencil: self.depth_stencil,
723 multisample: self.multisample,
724 fragment: self.fragment.map(|f| f.into_trace()),
725 multiview_mask: self.multiview_mask,
726 cache: self.cache.map(|c| c.into_trace()),
727 }
728 }
729}
730
731impl<'a> IntoTrace for crate::pipeline::ResolvedComputePipelineDescriptor<'a> {
732 type Output = TraceComputePipelineDescriptor<'a>;
733
734 fn into_trace(self) -> Self::Output {
735 TraceComputePipelineDescriptor {
736 label: self.label,
737 layout: self.layout.into_trace(),
738 stage: self.stage.into_trace(),
739 cache: self.cache.map(|c| c.into_trace()),
740 }
741 }
742}
743
744impl<'a> IntoTrace for crate::pipeline::ResolvedProgrammableStageDescriptor<'a> {
745 type Output =
746 crate::pipeline::ProgrammableStageDescriptor<'a, PointerId<markers::ShaderModule>>;
747 fn into_trace(self) -> Self::Output {
748 crate::pipeline::ProgrammableStageDescriptor {
749 module: self.module.into_trace(),
750 entry_point: self.entry_point,
751 constants: self.constants,
752 zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
753 }
754 }
755}
756
757impl<'a> IntoTrace
758 for crate::pipeline::RenderPipelineVertexProcessor<'a, Arc<crate::pipeline::ShaderModule>>
759{
760 type Output =
761 crate::pipeline::RenderPipelineVertexProcessor<'a, PointerId<markers::ShaderModule>>;
762 fn into_trace(self) -> Self::Output {
763 match self {
764 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex) => {
765 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex.into_trace())
766 }
767 crate::pipeline::RenderPipelineVertexProcessor::Mesh(task, mesh) => {
768 crate::pipeline::RenderPipelineVertexProcessor::Mesh(
769 task.map(|t| t.into_trace()),
770 mesh.into_trace(),
771 )
772 }
773 }
774 }
775}
776
777impl<'a> IntoTrace for crate::pipeline::ResolvedTaskState<'a> {
778 type Output = crate::pipeline::TaskState<'a, PointerId<markers::ShaderModule>>;
779 fn into_trace(self) -> Self::Output {
780 crate::pipeline::TaskState {
781 stage: self.stage.into_trace(),
782 }
783 }
784}
785
786impl<'a> IntoTrace for crate::pipeline::ResolvedMeshState<'a> {
787 type Output = crate::pipeline::MeshState<'a, PointerId<markers::ShaderModule>>;
788 fn into_trace(self) -> Self::Output {
789 crate::pipeline::MeshState {
790 stage: self.stage.into_trace(),
791 }
792 }
793}
794
795impl<'a> IntoTrace for crate::pipeline::ResolvedVertexState<'a> {
796 type Output = crate::pipeline::VertexState<'a, PointerId<markers::ShaderModule>>;
797 fn into_trace(self) -> Self::Output {
798 crate::pipeline::VertexState {
799 stage: self.stage.into_trace(),
800 buffers: self.buffers,
801 }
802 }
803}
804
805impl<'a> IntoTrace for crate::pipeline::ResolvedFragmentState<'a> {
806 type Output = crate::pipeline::FragmentState<'a, PointerId<markers::ShaderModule>>;
807 fn into_trace(self) -> Self::Output {
808 crate::pipeline::FragmentState {
809 stage: self.stage.into_trace(),
810 targets: self.targets,
811 }
812 }
813}
814
815impl<T: IntoTrace> IntoTrace for Option<T> {
816 type Output = Option<T::Output>;
817 fn into_trace(self) -> Self::Output {
818 self.map(|v| v.into_trace())
819 }
820}
821
822fn action_to_owned(action: Action<'_, PointerReferences>) -> Action<'static, PointerReferences> {
832 use Action as A;
833 match action {
834 A::Init { desc, backend } => A::Init {
835 desc: wgt::DeviceDescriptor {
836 label: desc.label.map(|l| Cow::Owned(l.into_owned())),
837 required_features: desc.required_features,
838 required_limits: desc.required_limits,
839 experimental_features: desc.experimental_features,
840 memory_hints: desc.memory_hints,
841 trace: desc.trace,
842 },
843 backend,
844 },
845 A::ConfigureSurface(surface, config) => A::ConfigureSurface(surface, config),
846 A::CreateBuffer(buffer, desc) => A::CreateBuffer(
847 buffer,
848 wgt::BufferDescriptor {
849 label: desc.label.map(|l| Cow::Owned(l.into_owned())),
850 size: desc.size,
851 usage: desc.usage,
852 mapped_at_creation: desc.mapped_at_creation,
853 },
854 ),
855 A::FreeBuffer(buffer) => A::FreeBuffer(buffer),
856 A::DestroyBuffer(buffer) => A::DestroyBuffer(buffer),
857 A::FreeTexture(texture) => A::FreeTexture(texture),
858 A::DestroyTexture(texture) => A::DestroyTexture(texture),
859 A::DestroyTextureView(texture_view) => A::DestroyTextureView(texture_view),
860 A::FreeExternalTexture(external_texture) => A::FreeExternalTexture(external_texture),
861 A::DestroyExternalTexture(external_texture) => A::DestroyExternalTexture(external_texture),
862 A::DestroySampler(sampler) => A::DestroySampler(sampler),
863 A::GetSurfaceTexture { id, parent } => A::GetSurfaceTexture { id, parent },
864 A::Present(surface) => A::Present(surface),
865 A::DiscardSurfaceTexture(surface) => A::DiscardSurfaceTexture(surface),
866 A::DestroyBindGroupLayout(layout) => A::DestroyBindGroupLayout(layout),
867 A::GetRenderPipelineBindGroupLayout {
868 id,
869 pipeline,
870 index,
871 } => A::GetRenderPipelineBindGroupLayout {
872 id,
873 pipeline,
874 index,
875 },
876 A::GetComputePipelineBindGroupLayout {
877 id,
878 pipeline,
879 index,
880 } => A::GetComputePipelineBindGroupLayout {
881 id,
882 pipeline,
883 index,
884 },
885 A::DestroyPipelineLayout(layout) => A::DestroyPipelineLayout(layout),
886 A::DestroyBindGroup(bind_group) => A::DestroyBindGroup(bind_group),
887 A::DestroyShaderModule(shader_module) => A::DestroyShaderModule(shader_module),
888 A::DestroyComputePipeline(pipeline) => A::DestroyComputePipeline(pipeline),
889 A::DestroyRenderPipeline(pipeline) => A::DestroyRenderPipeline(pipeline),
890 A::DestroyPipelineCache(cache) => A::DestroyPipelineCache(cache),
891 A::DestroyRenderBundle(render_bundle) => A::DestroyRenderBundle(render_bundle),
892 A::DestroyQuerySet(query_set) => A::DestroyQuerySet(query_set),
893 A::WriteBuffer {
894 id,
895 data,
896 range,
897 queued,
898 } => A::WriteBuffer {
899 id,
900 data,
901 range,
902 queued,
903 },
904 A::WriteTexture {
905 to,
906 data,
907 layout,
908 size,
909 } => A::WriteTexture {
910 to,
911 data,
912 layout,
913 size,
914 },
915 A::Submit(index, commands) => A::Submit(index, commands),
916 A::FailedCommands {
917 commands,
918 failed_at_submit,
919 error,
920 } => A::FailedCommands {
921 commands,
922 failed_at_submit,
923 error,
924 },
925 A::DestroyBlas(blas) => A::DestroyBlas(blas),
926 A::DestroyTlas(tlas) => A::DestroyTlas(tlas),
927
928 A::CreateTexture(..)
929 | A::CreateTextureView { .. }
930 | A::CreateExternalTexture { .. }
931 | A::CreateSampler(..)
932 | A::CreateBindGroupLayout(..)
933 | A::CreatePipelineLayout(..)
934 | A::CreateBindGroup(..)
935 | A::CreateShaderModule { .. }
936 | A::CreateShaderModulePassthrough { .. }
937 | A::CreateComputePipeline { .. }
938 | A::CreateGeneralRenderPipeline { .. }
939 | A::CreatePipelineCache { .. }
940 | A::CreateRenderBundle { .. }
941 | A::CreateQuerySet { .. }
942 | A::CreateBlas { .. }
943 | A::CreateTlas { .. } => panic!("Unsupported action for tracing: {action:?}"),
944 }
945}