1use alloc::{borrow::Cow, string::ToString, sync::Arc, vec::Vec};
2use core::{any::Any, convert::Infallible, marker::PhantomData};
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
178pub(crate) unsafe fn to_trace<T: StorageItem>(t: &T) -> PointerId<T::Marker> {
180 PointerId::PointerId(
181 #[expect(trivial_casts)]
182 core::num::NonZeroUsize::new(t as *const T as usize).unwrap(),
183 PhantomData,
184 )
185}
186
187impl IntoTrace for ArcCommand {
188 type Output = Command<PointerReferences>;
189 fn into_trace(self) -> Self::Output {
190 match self {
191 ArcCommand::CopyBufferToBuffer {
192 src,
193 src_offset,
194 dst,
195 dst_offset,
196 size,
197 } => Command::CopyBufferToBuffer {
198 src: src.to_trace(),
199 src_offset,
200 dst: dst.to_trace(),
201 dst_offset,
202 size,
203 },
204 ArcCommand::CopyBufferToTexture { src, dst, size } => Command::CopyBufferToTexture {
205 src: src.into_trace(),
206 dst: dst.into_trace(),
207 size,
208 },
209 ArcCommand::CopyTextureToBuffer { src, dst, size } => Command::CopyTextureToBuffer {
210 src: src.into_trace(),
211 dst: dst.into_trace(),
212 size,
213 },
214 ArcCommand::CopyTextureToTexture { src, dst, size } => Command::CopyTextureToTexture {
215 src: src.into_trace(),
216 dst: dst.into_trace(),
217 size,
218 },
219 ArcCommand::ClearBuffer { dst, offset, size } => Command::ClearBuffer {
220 dst: dst.to_trace(),
221 offset,
222 size,
223 },
224 ArcCommand::ClearTexture {
225 dst,
226 subresource_range,
227 } => Command::ClearTexture {
228 dst: dst.to_trace(),
229 subresource_range,
230 },
231 ArcCommand::WriteTimestamp {
232 query_set,
233 query_index,
234 } => Command::WriteTimestamp {
235 query_set: query_set.to_trace(),
236 query_index,
237 },
238 ArcCommand::ResolveQuerySet {
239 query_set,
240 start_query,
241 query_count,
242 destination,
243 destination_offset,
244 } => Command::ResolveQuerySet {
245 query_set: query_set.to_trace(),
246 start_query,
247 query_count,
248 destination: destination.to_trace(),
249 destination_offset,
250 },
251 ArcCommand::PushDebugGroup(label) => Command::PushDebugGroup(label),
252 ArcCommand::PopDebugGroup => Command::PopDebugGroup,
253 ArcCommand::InsertDebugMarker(label) => Command::InsertDebugMarker(label),
254 ArcCommand::RunComputePass {
255 pass,
256 timestamp_writes,
257 } => Command::RunComputePass {
258 pass: pass.into_trace(),
259 timestamp_writes: timestamp_writes.map(|tw| tw.into_trace()),
260 },
261 ArcCommand::RunRenderPass {
262 pass,
263 color_attachments,
264 depth_stencil_attachment,
265 timestamp_writes,
266 occlusion_query_set,
267 multiview_mask,
268 } => Command::RunRenderPass {
269 pass: pass.into_trace(),
270 color_attachments: color_attachments.into_trace(),
271 depth_stencil_attachment: depth_stencil_attachment.map(|d| d.into_trace()),
272 timestamp_writes: timestamp_writes.map(|tw| tw.into_trace()),
273 occlusion_query_set: occlusion_query_set.map(|q| q.to_trace()),
274 multiview_mask,
275 },
276 ArcCommand::BuildAccelerationStructures { blas, tlas } => {
277 Command::BuildAccelerationStructures {
278 blas: blas.into_iter().map(|b| b.into_trace()).collect(),
279 tlas: tlas.into_iter().map(|b| b.into_trace()).collect(),
280 }
281 }
282 ArcCommand::TransitionResources {
283 buffer_transitions: _,
284 texture_transitions: _,
285 } => {
286 panic!("TransitionResources cannot be converted to Command");
289 }
290 }
291 }
292}
293
294impl<T: IntoTrace> IntoTrace for wgt::TexelCopyBufferInfo<T> {
295 type Output = wgt::TexelCopyBufferInfo<T::Output>;
296 fn into_trace(self) -> Self::Output {
297 wgt::TexelCopyBufferInfo {
298 buffer: self.buffer.into_trace(),
299 layout: self.layout,
300 }
301 }
302}
303
304impl<T: IntoTrace> IntoTrace for wgt::TexelCopyTextureInfo<T> {
305 type Output = wgt::TexelCopyTextureInfo<T::Output>;
306 fn into_trace(self) -> Self::Output {
307 wgt::TexelCopyTextureInfo {
308 texture: self.texture.into_trace(),
309 mip_level: self.mip_level,
310 origin: self.origin,
311 aspect: self.aspect,
312 }
313 }
314}
315
316impl IntoTrace for ArcPassTimestampWrites {
317 type Output = crate::command::PassTimestampWrites<PointerId<markers::QuerySet>>;
318 fn into_trace(self) -> Self::Output {
319 crate::command::PassTimestampWrites {
320 query_set: self.query_set.into_trace(),
321 beginning_of_pass_write_index: self.beginning_of_pass_write_index,
322 end_of_pass_write_index: self.end_of_pass_write_index,
323 }
324 }
325}
326
327impl IntoTrace for ColorAttachments {
328 type Output = ColorAttachments<PointerId<markers::TextureView>>;
329 fn into_trace(self) -> Self::Output {
330 self.into_iter()
331 .map(|opt| {
332 opt.map(|att| RenderPassColorAttachment {
333 view: att.view.into_trace(),
334 depth_slice: att.depth_slice,
335 resolve_target: att.resolve_target.map(|r| r.into_trace()),
336 load_op: att.load_op,
337 store_op: att.store_op,
338 })
339 })
340 .collect()
341 }
342}
343
344impl<TV: IntoTrace> IntoTrace for ResolvedRenderPassDepthStencilAttachment<TV> {
345 type Output = ResolvedRenderPassDepthStencilAttachment<TV::Output>;
346 fn into_trace(self) -> Self::Output {
347 ResolvedRenderPassDepthStencilAttachment {
348 view: self.view.into_trace(),
349 depth: self.depth,
350 stencil: self.stencil,
351 }
352 }
353}
354
355impl IntoTrace for crate::ray_tracing::OwnedBlasBuildEntry<ArcReferences> {
356 type Output = crate::ray_tracing::OwnedBlasBuildEntry<PointerReferences>;
357 fn into_trace(self) -> Self::Output {
358 crate::ray_tracing::OwnedBlasBuildEntry {
359 blas: self.blas.into_trace(),
360 geometries: self.geometries.into_trace(),
361 }
362 }
363}
364
365impl IntoTrace for crate::ray_tracing::OwnedBlasGeometries<ArcReferences> {
366 type Output = crate::ray_tracing::OwnedBlasGeometries<PointerReferences>;
367 fn into_trace(self) -> Self::Output {
368 match self {
369 crate::ray_tracing::OwnedBlasGeometries::TriangleGeometries(geos) => {
370 crate::ray_tracing::OwnedBlasGeometries::TriangleGeometries(
371 geos.into_iter().map(|g| g.into_trace()).collect(),
372 )
373 }
374 crate::ray_tracing::OwnedBlasGeometries::AabbGeometries(geos) => {
375 crate::ray_tracing::OwnedBlasGeometries::AabbGeometries(
376 geos.into_iter().map(|g| g.into_trace()).collect(),
377 )
378 }
379 }
380 }
381}
382
383impl IntoTrace for crate::ray_tracing::OwnedBlasTriangleGeometry<ArcReferences> {
384 type Output = crate::ray_tracing::OwnedBlasTriangleGeometry<PointerReferences>;
385 fn into_trace(self) -> Self::Output {
386 crate::ray_tracing::OwnedBlasTriangleGeometry {
387 size: self.size,
388 vertex_buffer: self.vertex_buffer.into_trace(),
389 index_buffer: self.index_buffer.map(|b| b.into_trace()),
390 transform_buffer: self.transform_buffer.map(|b| b.into_trace()),
391 first_vertex: self.first_vertex,
392 vertex_stride: self.vertex_stride,
393 first_index: self.first_index,
394 transform_buffer_offset: self.transform_buffer_offset,
395 }
396 }
397}
398
399impl IntoTrace for crate::ray_tracing::OwnedBlasAabbGeometry<ArcReferences> {
400 type Output = crate::ray_tracing::OwnedBlasAabbGeometry<PointerReferences>;
401 fn into_trace(self) -> Self::Output {
402 crate::ray_tracing::OwnedBlasAabbGeometry {
403 size: self.size,
404 stride: self.stride,
405 aabb_buffer: self.aabb_buffer.into_trace(),
406 primitive_offset: self.primitive_offset,
407 }
408 }
409}
410
411impl IntoTrace for crate::ray_tracing::OwnedTlasPackage<ArcReferences> {
412 type Output = crate::ray_tracing::OwnedTlasPackage<PointerReferences>;
413 fn into_trace(self) -> Self::Output {
414 crate::ray_tracing::OwnedTlasPackage {
415 tlas: self.tlas.into_trace(),
416 instances: self
417 .instances
418 .into_iter()
419 .map(|opt| opt.map(|inst| inst.into_trace()))
420 .collect(),
421 lowest_unmodified: self.lowest_unmodified,
422 }
423 }
424}
425
426impl IntoTrace for crate::ray_tracing::OwnedTlasInstance<ArcReferences> {
427 type Output = crate::ray_tracing::OwnedTlasInstance<PointerReferences>;
428 fn into_trace(self) -> Self::Output {
429 crate::ray_tracing::OwnedTlasInstance {
430 blas: self.blas.into_trace(),
431 transform: self.transform,
432 custom_data: self.custom_data,
433 mask: self.mask,
434 }
435 }
436}
437
438impl<C: IntoTrace> IntoTrace for BasePass<C, Infallible> {
439 type Output = BasePass<C::Output, Infallible>;
440
441 fn into_trace(self) -> Self::Output {
442 BasePass {
443 label: self.label,
444 error: self.error,
445 commands: self
446 .commands
447 .into_iter()
448 .map(|cmd| cmd.into_trace())
449 .collect(),
450 dynamic_offsets: self.dynamic_offsets,
451 string_data: self.string_data,
452 immediates_data: self.immediates_data,
453 }
454 }
455}
456
457impl IntoTrace for ArcComputeCommand {
458 type Output = ComputeCommand<PointerReferences>;
459 fn into_trace(self) -> Self::Output {
460 use ComputeCommand as C;
461 match self {
462 C::SetBindGroup {
463 index,
464 num_dynamic_offsets,
465 bind_group,
466 } => C::SetBindGroup {
467 index,
468 num_dynamic_offsets,
469 bind_group: bind_group.map(|bg| bg.into_trace()),
470 },
471 C::SetPipeline(id) => C::SetPipeline(id.into_trace()),
472 C::SetImmediate {
473 offset,
474 size_bytes,
475 values_offset,
476 } => C::SetImmediate {
477 offset,
478 size_bytes,
479 values_offset,
480 },
481 C::DispatchWorkgroups(groups) => C::DispatchWorkgroups(groups),
482 C::DispatchWorkgroupsIndirect { buffer, offset } => C::DispatchWorkgroupsIndirect {
483 buffer: buffer.into_trace(),
484 offset,
485 },
486 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
487 C::PopDebugGroup => C::PopDebugGroup,
488 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
489 C::WriteTimestamp {
490 query_set,
491 query_index,
492 } => C::WriteTimestamp {
493 query_set: query_set.into_trace(),
494 query_index,
495 },
496 C::BeginPipelineStatisticsQuery {
497 query_set,
498 query_index,
499 } => C::BeginPipelineStatisticsQuery {
500 query_set: query_set.into_trace(),
501 query_index,
502 },
503 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
504 C::TransitionResources {
505 buffer_transitions,
506 texture_transitions,
507 } => C::TransitionResources {
508 buffer_transitions: buffer_transitions
509 .into_iter()
510 .map(|buffer_transition| wgt::BufferTransition {
511 buffer: buffer_transition.buffer.into_trace(),
512 state: buffer_transition.state,
513 })
514 .collect(),
515 texture_transitions: texture_transitions
516 .into_iter()
517 .map(|texture_transition| wgt::TextureTransition {
518 texture: texture_transition.texture.into_trace(),
519 selector: texture_transition.selector,
520 state: texture_transition.state,
521 })
522 .collect(),
523 },
524 }
525 }
526}
527
528impl IntoTrace for ArcRenderCommand {
529 type Output = RenderCommand<PointerReferences>;
530 fn into_trace(self) -> Self::Output {
531 use RenderCommand as C;
532 match self {
533 C::SetBindGroup {
534 index,
535 num_dynamic_offsets,
536 bind_group,
537 } => C::SetBindGroup {
538 index,
539 num_dynamic_offsets,
540 bind_group: bind_group.map(|bg| bg.into_trace()),
541 },
542 C::SetPipeline(id) => C::SetPipeline(id.into_trace()),
543 C::SetIndexBuffer {
544 buffer,
545 index_format,
546 offset,
547 size,
548 } => C::SetIndexBuffer {
549 buffer: buffer.into_trace(),
550 index_format,
551 offset,
552 size,
553 },
554 C::SetVertexBuffer {
555 slot,
556 buffer,
557 offset,
558 size,
559 } => C::SetVertexBuffer {
560 slot,
561 buffer: buffer.into_trace(),
562 offset,
563 size,
564 },
565 C::SetBlendConstant(color) => C::SetBlendConstant(color),
566 C::SetStencilReference(val) => C::SetStencilReference(val),
567 C::SetViewport {
568 rect,
569 depth_min,
570 depth_max,
571 } => C::SetViewport {
572 rect,
573 depth_min,
574 depth_max,
575 },
576 C::SetScissor(rect) => C::SetScissor(rect),
577 C::SetImmediate {
578 offset,
579 size_bytes,
580 values_offset,
581 } => C::SetImmediate {
582 offset,
583 size_bytes,
584 values_offset,
585 },
586 C::Draw {
587 vertex_count,
588 instance_count,
589 first_vertex,
590 first_instance,
591 } => C::Draw {
592 vertex_count,
593 instance_count,
594 first_vertex,
595 first_instance,
596 },
597 C::DrawIndexed {
598 index_count,
599 instance_count,
600 first_index,
601 base_vertex,
602 first_instance,
603 } => C::DrawIndexed {
604 index_count,
605 instance_count,
606 first_index,
607 base_vertex,
608 first_instance,
609 },
610 C::DrawMeshTasks {
611 group_count_x,
612 group_count_y,
613 group_count_z,
614 } => C::DrawMeshTasks {
615 group_count_x,
616 group_count_y,
617 group_count_z,
618 },
619 C::DrawIndirect {
620 buffer,
621 offset,
622 count,
623 family,
624 vertex_or_index_limit,
625 instance_limit,
626 } => C::DrawIndirect {
627 buffer: buffer.into_trace(),
628 offset,
629 count,
630 family,
631 vertex_or_index_limit,
632 instance_limit,
633 },
634 C::MultiDrawIndirectCount {
635 buffer,
636 offset,
637 count_buffer,
638 count_buffer_offset,
639 max_count,
640 family,
641 } => C::MultiDrawIndirectCount {
642 buffer: buffer.into_trace(),
643 offset,
644 count_buffer: count_buffer.into_trace(),
645 count_buffer_offset,
646 max_count,
647 family,
648 },
649 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
650 C::PopDebugGroup => C::PopDebugGroup,
651 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
652 C::WriteTimestamp {
653 query_set,
654 query_index,
655 } => C::WriteTimestamp {
656 query_set: query_set.into_trace(),
657 query_index,
658 },
659 C::BeginOcclusionQuery { query_index } => C::BeginOcclusionQuery { query_index },
660 C::EndOcclusionQuery => C::EndOcclusionQuery,
661 C::BeginPipelineStatisticsQuery {
662 query_set,
663 query_index,
664 } => C::BeginPipelineStatisticsQuery {
665 query_set: query_set.into_trace(),
666 query_index,
667 },
668 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
669 C::ExecuteBundle(bundle) => C::ExecuteBundle(bundle.into_trace()),
670 }
671 }
672}
673
674impl IntoTrace for crate::binding_model::ResolvedPipelineLayoutDescriptor<'_> {
675 type Output = crate::binding_model::PipelineLayoutDescriptor<
676 'static,
677 PointerId<markers::BindGroupLayout>,
678 >;
679 fn into_trace(self) -> Self::Output {
680 crate::binding_model::PipelineLayoutDescriptor {
681 label: self.label.map(|l| Cow::Owned(l.into_owned())),
682 bind_group_layouts: self
683 .bind_group_layouts
684 .iter()
685 .map(|bgl| bgl.to_trace())
686 .collect(),
687 immediate_size: self.immediate_size,
688 }
689 }
690}
691
692impl<'a> IntoTrace for &'_ crate::binding_model::ResolvedBindGroupDescriptor<'a> {
693 type Output = TraceBindGroupDescriptor<'a>;
694
695 fn into_trace(self) -> Self::Output {
696 use crate::binding_model::{
697 BindGroupEntry, BindingResource, BufferBinding, ResolvedBindingResource,
698 };
699 TraceBindGroupDescriptor {
700 label: self.label.clone(),
701 layout: self.layout.to_trace(),
702 entries: Cow::Owned(
703 self.entries
704 .iter()
705 .map(|entry| {
706 let resource = match &entry.resource {
707 ResolvedBindingResource::Buffer(buffer_binding) => {
708 BindingResource::Buffer(BufferBinding {
709 buffer: buffer_binding.buffer.to_trace(),
710 offset: buffer_binding.offset,
711 size: buffer_binding.size,
712 })
713 }
714 ResolvedBindingResource::BufferArray(buffer_bindings) => {
715 let resolved_buffers: Vec<_> = buffer_bindings
716 .iter()
717 .map(|bb| BufferBinding {
718 buffer: bb.buffer.to_trace(),
719 offset: bb.offset,
720 size: bb.size,
721 })
722 .collect();
723 BindingResource::BufferArray(Cow::Owned(resolved_buffers))
724 }
725 ResolvedBindingResource::Sampler(sampler_id) => {
726 BindingResource::Sampler(sampler_id.to_trace())
727 }
728 ResolvedBindingResource::SamplerArray(sampler_ids) => {
729 let resolved: Vec<_> =
730 sampler_ids.iter().map(|id| id.to_trace()).collect();
731 BindingResource::SamplerArray(Cow::Owned(resolved))
732 }
733 ResolvedBindingResource::TextureView(texture_view_id) => {
734 BindingResource::TextureView(texture_view_id.to_trace())
735 }
736 ResolvedBindingResource::TextureViewArray(texture_view_ids) => {
737 let resolved: Vec<_> =
738 texture_view_ids.iter().map(|id| id.to_trace()).collect();
739 BindingResource::TextureViewArray(Cow::Owned(resolved))
740 }
741 ResolvedBindingResource::AccelerationStructure(tlas_id) => {
742 BindingResource::AccelerationStructure(tlas_id.to_trace())
743 }
744 ResolvedBindingResource::AccelerationStructureArray(tlas_ids) => {
745 let resolved: Vec<_> =
746 tlas_ids.iter().map(|id| id.to_trace()).collect();
747 BindingResource::AccelerationStructureArray(Cow::Owned(resolved))
748 }
749 ResolvedBindingResource::ExternalTexture(external_texture_id) => {
750 BindingResource::ExternalTexture(external_texture_id.to_trace())
751 }
752 };
753 BindGroupEntry {
754 binding: entry.binding,
755 resource,
756 }
757 })
758 .collect(),
759 ),
760 }
761 }
762}
763
764impl<'a> IntoTrace for crate::pipeline::ResolvedGeneralRenderPipelineDescriptor<'a> {
765 type Output = TraceGeneralRenderPipelineDescriptor<'a>;
766
767 fn into_trace(self) -> Self::Output {
768 TraceGeneralRenderPipelineDescriptor {
769 label: self.label,
770 layout: self.layout.into_trace(),
771 vertex: self.vertex.into_trace(),
772 primitive: self.primitive,
773 depth_stencil: self.depth_stencil,
774 multisample: self.multisample,
775 fragment: self.fragment.map(|f| f.into_trace()),
776 multiview_mask: self.multiview_mask,
777 cache: self.cache.map(|c| c.into_trace()),
778 }
779 }
780}
781
782impl<'a> IntoTrace for crate::pipeline::ResolvedComputePipelineDescriptor<'a> {
783 type Output = TraceComputePipelineDescriptor<'a>;
784
785 fn into_trace(self) -> Self::Output {
786 TraceComputePipelineDescriptor {
787 label: self.label,
788 layout: self.layout.into_trace(),
789 stage: self.stage.into_trace(),
790 cache: self.cache.map(|c| c.into_trace()),
791 }
792 }
793}
794
795impl<'a> IntoTrace for crate::pipeline::ResolvedProgrammableStageDescriptor<'a> {
796 type Output =
797 crate::pipeline::ProgrammableStageDescriptor<'a, PointerId<markers::ShaderModule>>;
798 fn into_trace(self) -> Self::Output {
799 crate::pipeline::ProgrammableStageDescriptor {
800 module: self.module.into_trace(),
801 entry_point: self.entry_point,
802 constants: self.constants,
803 zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
804 }
805 }
806}
807
808impl<'a> IntoTrace
809 for crate::pipeline::RenderPipelineVertexProcessor<'a, Arc<crate::pipeline::ShaderModule>>
810{
811 type Output =
812 crate::pipeline::RenderPipelineVertexProcessor<'a, PointerId<markers::ShaderModule>>;
813 fn into_trace(self) -> Self::Output {
814 match self {
815 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex) => {
816 crate::pipeline::RenderPipelineVertexProcessor::Vertex(vertex.into_trace())
817 }
818 crate::pipeline::RenderPipelineVertexProcessor::Mesh(task, mesh) => {
819 crate::pipeline::RenderPipelineVertexProcessor::Mesh(
820 task.map(|t| t.into_trace()),
821 mesh.into_trace(),
822 )
823 }
824 }
825 }
826}
827
828impl<'a> IntoTrace for crate::pipeline::ResolvedTaskState<'a> {
829 type Output = crate::pipeline::TaskState<'a, PointerId<markers::ShaderModule>>;
830 fn into_trace(self) -> Self::Output {
831 crate::pipeline::TaskState {
832 stage: self.stage.into_trace(),
833 }
834 }
835}
836
837impl<'a> IntoTrace for crate::pipeline::ResolvedMeshState<'a> {
838 type Output = crate::pipeline::MeshState<'a, PointerId<markers::ShaderModule>>;
839 fn into_trace(self) -> Self::Output {
840 crate::pipeline::MeshState {
841 stage: self.stage.into_trace(),
842 }
843 }
844}
845
846impl<'a> IntoTrace for crate::pipeline::ResolvedVertexState<'a> {
847 type Output = crate::pipeline::VertexState<'a, PointerId<markers::ShaderModule>>;
848 fn into_trace(self) -> Self::Output {
849 crate::pipeline::VertexState {
850 stage: self.stage.into_trace(),
851 buffers: self.buffers,
852 }
853 }
854}
855
856impl<'a> IntoTrace for crate::pipeline::ResolvedFragmentState<'a> {
857 type Output = crate::pipeline::FragmentState<'a, PointerId<markers::ShaderModule>>;
858 fn into_trace(self) -> Self::Output {
859 crate::pipeline::FragmentState {
860 stage: self.stage.into_trace(),
861 targets: self.targets,
862 }
863 }
864}
865
866impl<T: IntoTrace> IntoTrace for Option<T> {
867 type Output = Option<T::Output>;
868 fn into_trace(self) -> Self::Output {
869 self.map(|v| v.into_trace())
870 }
871}
872
873fn action_to_owned(action: Action<'_, PointerReferences>) -> Action<'static, PointerReferences> {
877 use Action as A;
878 match action {
879 A::Init { desc, backend } => A::Init {
880 desc: desc.map_label(owned_label),
881 backend,
882 },
883 A::ConfigureSurface(surface, config) => A::ConfigureSurface(surface, config),
884 A::CreateBuffer(buffer, desc) => A::CreateBuffer(buffer, desc.map_label(owned_label)),
885 A::DestroyBuffer(buffer) => A::DestroyBuffer(buffer),
886 A::DropBuffer(buffer) => A::DropBuffer(buffer),
887 A::DestroyTexture(texture) => A::DestroyTexture(texture),
888 A::DropTexture(texture) => A::DropTexture(texture),
889 A::DropTextureView(texture_view) => A::DropTextureView(texture_view),
890 A::DestroyExternalTexture(external_texture) => A::DestroyExternalTexture(external_texture),
891 A::DropExternalTexture(external_texture) => A::DropExternalTexture(external_texture),
892 A::DropSampler(sampler) => A::DropSampler(sampler),
893 A::GetSurfaceTexture { id, parent } => A::GetSurfaceTexture { id, parent },
894 A::Present(surface) => A::Present(surface),
895 A::DiscardSurfaceTexture(surface) => A::DiscardSurfaceTexture(surface),
896 A::ReleaseSurfaceTexture(surface) => A::ReleaseSurfaceTexture(surface),
897 A::DropBindGroupLayout(layout) => A::DropBindGroupLayout(layout),
898 A::GetRenderPipelineBindGroupLayout {
899 id,
900 pipeline,
901 index,
902 } => A::GetRenderPipelineBindGroupLayout {
903 id,
904 pipeline,
905 index,
906 },
907 A::GetComputePipelineBindGroupLayout {
908 id,
909 pipeline,
910 index,
911 } => A::GetComputePipelineBindGroupLayout {
912 id,
913 pipeline,
914 index,
915 },
916 A::DropPipelineLayout(layout) => A::DropPipelineLayout(layout),
917 A::DropBindGroup(bind_group) => A::DropBindGroup(bind_group),
918 A::DropShaderModule(shader_module) => A::DropShaderModule(shader_module),
919 A::DropComputePipeline(pipeline) => A::DropComputePipeline(pipeline),
920 A::DropRenderPipeline(pipeline) => A::DropRenderPipeline(pipeline),
921 A::DropPipelineCache(cache) => A::DropPipelineCache(cache),
922 A::DropRenderBundle(render_bundle) => A::DropRenderBundle(render_bundle),
923 A::DestroyQuerySet(query_set) => A::DestroyQuerySet(query_set),
924 A::DropQuerySet(query_set) => A::DropQuerySet(query_set),
925 A::WriteBuffer {
926 id,
927 data,
928 offset,
929 size,
930 queued,
931 } => A::WriteBuffer {
932 id,
933 data,
934 offset,
935 size,
936 queued,
937 },
938 A::WriteTexture {
939 to,
940 data,
941 layout,
942 size,
943 } => A::WriteTexture {
944 to,
945 data,
946 layout,
947 size,
948 },
949 A::Submit(index, commands) => A::Submit(index, commands),
950 A::FailedCommands {
951 commands,
952 failed_at_submit,
953 error,
954 } => A::FailedCommands {
955 commands,
956 failed_at_submit,
957 error,
958 },
959 A::DropBlas(blas) => A::DropBlas(blas),
960 A::DropTlas(tlas) => A::DropTlas(tlas),
961
962 A::CreateTexture(id, desc) => A::CreateTexture(id, desc.map_label(owned_label)),
963 A::CreateTextureError(id, desc) => A::CreateTextureError(id, desc.map_label(owned_label)),
964 A::CreateTextureView { id, parent, desc } => A::CreateTextureView {
965 id,
966 parent,
967 desc: crate::resource::TextureViewDescriptor {
968 label: owned_label(&desc.label),
969 format: desc.format,
970 dimension: desc.dimension,
971 usage: desc.usage,
972 range: desc.range,
973 },
974 },
975 A::CreateExternalTexture { id, desc, planes } => A::CreateExternalTexture {
976 id,
977 desc: desc.map_label(owned_label),
978 planes,
979 },
980 A::CreateSampler(id, desc) => A::CreateSampler(
981 id,
982 crate::resource::SamplerDescriptor {
983 label: owned_label(&desc.label),
984 address_modes: desc.address_modes,
985 mag_filter: desc.mag_filter,
986 min_filter: desc.min_filter,
987 mipmap_filter: desc.mipmap_filter,
988 lod_min_clamp: desc.lod_min_clamp,
989 lod_max_clamp: desc.lod_max_clamp,
990 compare: desc.compare,
991 anisotropy_clamp: desc.anisotropy_clamp,
992 border_color: desc.border_color,
993 },
994 ),
995 A::CreateBindGroupLayout(id, desc) => A::CreateBindGroupLayout(
996 id,
997 crate::binding_model::BindGroupLayoutDescriptor {
998 label: owned_label(&desc.label),
999 entries: Cow::Owned(desc.entries.into_owned()),
1000 },
1001 ),
1002 A::CreatePipelineLayout(id, desc) => A::CreatePipelineLayout(
1003 id,
1004 crate::binding_model::PipelineLayoutDescriptor {
1005 label: owned_label(&desc.label),
1006 bind_group_layouts: Cow::Owned(desc.bind_group_layouts.into_owned()),
1007 immediate_size: desc.immediate_size,
1008 },
1009 ),
1010 A::CreateBindGroup(id, desc) => A::CreateBindGroup(
1011 id,
1012 crate::binding_model::BindGroupDescriptor {
1013 label: owned_label(&desc.label),
1014 layout: desc.layout,
1015 entries: desc
1016 .entries
1017 .iter()
1018 .map(|e| crate::binding_model::BindGroupEntry {
1019 binding: e.binding,
1020 resource: match &e.resource {
1021 crate::binding_model::BindingResource::Buffer(buffer_binding) => {
1022 crate::binding_model::BindingResource::Buffer(
1023 buffer_binding.clone(),
1024 )
1025 }
1026 crate::binding_model::BindingResource::BufferArray(cow) => {
1027 crate::binding_model::BindingResource::BufferArray(Cow::Owned(
1028 cow.clone().into_owned(),
1029 ))
1030 }
1031 crate::binding_model::BindingResource::Sampler(sampler) => {
1032 crate::binding_model::BindingResource::Sampler(*sampler)
1033 }
1034 crate::binding_model::BindingResource::SamplerArray(cow) => {
1035 crate::binding_model::BindingResource::SamplerArray(Cow::Owned(
1036 cow.clone().into_owned(),
1037 ))
1038 }
1039 crate::binding_model::BindingResource::TextureView(texture_view) => {
1040 crate::binding_model::BindingResource::TextureView(*texture_view)
1041 }
1042 crate::binding_model::BindingResource::TextureViewArray(cow) => {
1043 crate::binding_model::BindingResource::TextureViewArray(Cow::Owned(
1044 cow.clone().into_owned(),
1045 ))
1046 }
1047 crate::binding_model::BindingResource::AccelerationStructure(
1048 acceleration_structure,
1049 ) => crate::binding_model::BindingResource::AccelerationStructure(
1050 *acceleration_structure,
1051 ),
1052 crate::binding_model::BindingResource::AccelerationStructureArray(
1053 cow,
1054 ) => crate::binding_model::BindingResource::AccelerationStructureArray(
1055 Cow::Owned(cow.clone().into_owned()),
1056 ),
1057 crate::binding_model::BindingResource::ExternalTexture(
1058 external_texture,
1059 ) => crate::binding_model::BindingResource::ExternalTexture(
1060 *external_texture,
1061 ),
1062 },
1063 })
1064 .collect(),
1065 },
1066 ),
1067 A::CreateShaderModule { id, desc, data } => A::CreateShaderModule {
1068 id,
1069 desc: crate::pipeline::ShaderModuleDescriptor {
1070 label: owned_label(&desc.label),
1071 runtime_checks: desc.runtime_checks,
1072 },
1073 data,
1074 },
1075 A::CreateShaderModulePassthrough {
1076 id,
1077 data,
1078 label,
1079 entry_points,
1080 } => A::CreateShaderModulePassthrough {
1081 id,
1082 data,
1083 label: owned_label(&label),
1084 entry_points: entry_points
1085 .iter()
1086 .map(|ep| wgt::PassthroughShaderEntryPoint {
1087 name: Cow::Owned(ep.name.to_string()),
1088 workgroup_size: ep.workgroup_size,
1089 })
1090 .collect(),
1091 },
1092 A::CreateComputePipeline { id, desc } => A::CreateComputePipeline {
1093 id,
1094 desc: crate::pipeline::ComputePipelineDescriptor {
1095 label: owned_label(&desc.label),
1096 layout: desc.layout,
1097 stage: owned_stage(desc.stage),
1098 cache: desc.cache,
1099 },
1100 },
1101 A::CreateGeneralRenderPipeline { id, desc } => A::CreateGeneralRenderPipeline {
1102 id,
1103 desc: crate::pipeline::GeneralRenderPipelineDescriptor {
1104 label: owned_label(&desc.label),
1105 layout: desc.layout,
1106 vertex: match desc.vertex {
1107 crate::pipeline::RenderPipelineVertexProcessor::Vertex(
1108 crate::pipeline::VertexState { stage, buffers },
1109 ) => crate::pipeline::RenderPipelineVertexProcessor::Vertex(
1110 crate::pipeline::VertexState {
1111 stage: owned_stage(stage),
1112 buffers: buffers
1113 .iter()
1114 .map(|b| {
1115 b.clone().map(|buffer| crate::pipeline::VertexBufferLayout {
1116 array_stride: buffer.array_stride,
1117 step_mode: buffer.step_mode,
1118 attributes: Cow::Owned(buffer.attributes.into_owned()),
1119 })
1120 })
1121 .collect(),
1122 },
1123 ),
1124 crate::pipeline::RenderPipelineVertexProcessor::Mesh(task, mesh) => {
1125 crate::pipeline::RenderPipelineVertexProcessor::Mesh(
1126 task.map(|t| crate::pipeline::TaskState {
1127 stage: owned_stage(t.stage),
1128 }),
1129 crate::pipeline::MeshState {
1130 stage: owned_stage(mesh.stage),
1131 },
1132 )
1133 }
1134 },
1135 primitive: desc.primitive,
1136 depth_stencil: desc.depth_stencil,
1137 multisample: desc.multisample,
1138 fragment: desc.fragment.map(|f| crate::pipeline::FragmentState {
1139 stage: owned_stage(f.stage),
1140 targets: Cow::Owned(f.targets.into_owned()),
1141 }),
1142 multiview_mask: desc.multiview_mask,
1143 cache: desc.cache,
1144 },
1145 },
1146 A::CreatePipelineCache { id, desc } => A::CreatePipelineCache {
1147 id,
1148 desc: crate::pipeline::PipelineCacheDescriptor {
1149 label: owned_label(&desc.label),
1150 data: desc.data.map(|d| Cow::Owned(d.to_vec())),
1151 fallback: desc.fallback,
1152 },
1153 },
1154 A::CreateRenderBundle { id, desc, base } => A::CreateRenderBundle {
1155 id,
1156 desc: crate::command::RenderBundleEncoderDescriptor {
1157 label: owned_label(&desc.label),
1158 color_formats: Cow::Owned(desc.color_formats.into_owned()),
1159 depth_stencil: desc.depth_stencil,
1160 sample_count: desc.sample_count,
1161 multiview: desc.multiview,
1162 },
1163 base,
1164 },
1165 A::CreateQuerySet { id, desc } => A::CreateQuerySet {
1166 id,
1167 desc: desc.map_label(owned_label),
1168 },
1169 A::CreateBlas { id, desc, sizes } => A::CreateBlas {
1170 id,
1171 desc: desc.map_label(owned_label),
1172 sizes,
1173 },
1174 A::CreateTlas { id, desc } => A::CreateTlas {
1175 id,
1176 desc: desc.map_label(owned_label),
1177 },
1178 }
1179}
1180
1181fn owned_stage<SM>(
1182 stage: crate::pipeline::ProgrammableStageDescriptor<'_, SM>,
1183) -> crate::pipeline::ProgrammableStageDescriptor<'static, SM> {
1184 crate::pipeline::ProgrammableStageDescriptor {
1185 module: stage.module,
1186 entry_point: owned_label(&stage.entry_point),
1187 constants: stage.constants,
1188 zero_initialize_workgroup_memory: stage.zero_initialize_workgroup_memory,
1189 }
1190}
1191
1192fn owned_label(l: &Option<Cow<'_, str>>) -> Option<Cow<'static, str>> {
1193 l.as_ref().map(|l| Cow::Owned(l.to_string()))
1194}