1#![cfg(not(target_arch = "wasm32"))]
4#![warn(clippy::allow_attributes, unsafe_op_in_unsafe_fn)]
5
6extern crate wgpu_core as wgc;
7extern crate wgpu_types as wgt;
8
9use std::{borrow::Cow, convert::Infallible, sync::Arc};
10
11use hashbrown::HashMap;
12
13use wgc::{
14 binding_model::BindingResource,
15 command::{ArcCommand, ArcReferences, BasePass, Command, PointerReferences},
16 device::trace::{self, DataKind, DataLoader},
17 id::{Marker, PointerId},
18};
19
20pub struct Player {
21 pipeline_layouts: HashMap<
22 wgc::id::PointerId<wgc::id::markers::PipelineLayout>,
23 Arc<wgc::binding_model::PipelineLayout>,
24 >,
25 shader_modules: HashMap<
26 wgc::id::PointerId<wgc::id::markers::ShaderModule>,
27 Arc<wgc::pipeline::ShaderModule>,
28 >,
29 bind_group_layouts: HashMap<
30 wgc::id::PointerId<wgc::id::markers::BindGroupLayout>,
31 Arc<wgc::binding_model::BindGroupLayout>,
32 >,
33 bind_groups: HashMap<
34 wgc::id::PointerId<wgc::id::markers::BindGroup>,
35 Arc<wgc::binding_model::BindGroup>,
36 >,
37 render_bundles: HashMap<
38 wgc::id::PointerId<wgc::id::markers::RenderBundle>,
39 Arc<wgc::command::RenderBundle>,
40 >,
41 render_pipelines: HashMap<
42 wgc::id::PointerId<wgc::id::markers::RenderPipeline>,
43 Arc<wgc::pipeline::RenderPipeline>,
44 >,
45 compute_pipelines: HashMap<
46 wgc::id::PointerId<wgc::id::markers::ComputePipeline>,
47 Arc<wgc::pipeline::ComputePipeline>,
48 >,
49 pipeline_caches: HashMap<
50 wgc::id::PointerId<wgc::id::markers::PipelineCache>,
51 Arc<wgc::pipeline::PipelineCache>,
52 >,
53 query_sets:
54 HashMap<wgc::id::PointerId<wgc::id::markers::QuerySet>, Arc<wgc::resource::QuerySet>>,
55 buffers: HashMap<wgc::id::PointerId<wgc::id::markers::Buffer>, Arc<wgc::resource::Buffer>>,
56 textures: HashMap<wgc::id::PointerId<wgc::id::markers::Texture>, Arc<wgc::resource::Texture>>,
57 texture_views:
58 HashMap<wgc::id::PointerId<wgc::id::markers::TextureView>, Arc<wgc::resource::TextureView>>,
59 external_textures: HashMap<
60 wgc::id::PointerId<wgc::id::markers::ExternalTexture>,
61 Arc<wgc::resource::ExternalTexture>,
62 >,
63 samplers: HashMap<wgc::id::PointerId<wgc::id::markers::Sampler>, Arc<wgc::resource::Sampler>>,
64 blas_s: HashMap<wgc::id::PointerId<wgc::id::markers::Blas>, Arc<wgc::resource::Blas>>,
65 tlas_s: HashMap<wgc::id::PointerId<wgc::id::markers::Tlas>, Arc<wgc::resource::Tlas>>,
66}
67
68impl Default for Player {
69 fn default() -> Self {
70 Self {
71 pipeline_layouts: HashMap::new(),
72 shader_modules: HashMap::new(),
73 bind_group_layouts: HashMap::new(),
74 bind_groups: HashMap::new(),
75 render_bundles: HashMap::new(),
76 render_pipelines: HashMap::new(),
77 compute_pipelines: HashMap::new(),
78 pipeline_caches: HashMap::new(),
79 query_sets: HashMap::new(),
80 buffers: HashMap::new(),
81 textures: HashMap::new(),
82 texture_views: HashMap::new(),
83 external_textures: HashMap::new(),
84 samplers: HashMap::new(),
85 blas_s: HashMap::new(),
86 tlas_s: HashMap::new(),
87 }
88 }
89}
90
91fn process_result<T: Marker, U>(
92 op: &str,
93 map: &mut HashMap<PointerId<T>, U>,
94 id: Option<PointerId<T>>,
95 value: Result<U, impl std::error::Error>,
96) {
97 match (id, value) {
98 (Some(id), Ok(value)) => {
99 map.insert(id, value);
100 }
101 (Some(_), Err(err)) => {
102 panic!("{op} succeeded when recording, but failed on playback: {err}");
103 }
104 (None, Ok(_)) => {
105 panic!("{op} failed when recording, but succeeded on playback");
106 }
107 (None, Err(err)) => {
108 panic!("{op} failed when recording, and failed on playback: {err}");
109 }
110 }
111}
112
113impl Player {
114 pub fn process(
115 &mut self,
116 device: &Arc<wgc::device::Device>,
117 queue: &Arc<wgc::device::queue::Queue>,
118 action: trace::Action<PointerReferences>,
119 loader: impl DataLoader,
120 ) {
121 use wgc::device::trace::Action;
122 log::debug!("action {action:?}");
123 match action {
124 Action::Init { .. } => {
125 panic!("Unexpected Action::Init: has to be the first action only")
126 }
127 Action::ConfigureSurface { .. }
128 | Action::Present(_)
129 | Action::DiscardSurfaceTexture(_) => {
130 panic!("Unexpected Surface action: winit feature is not enabled")
131 }
132 Action::CreateBuffer(id, desc) => {
133 let buffer = device.create_buffer(&desc).expect("create_buffer error");
134 self.buffers.insert(id, buffer);
135 }
136 Action::DestroyBuffer(id) => {
137 let buffer = self.buffers.get(&id).expect("invalid buffer");
138 buffer.destroy();
139 }
140 Action::DropBuffer(id) => {
141 let buffer = self.buffers.remove(&id).expect("invalid buffer");
142 let _ = buffer.unmap();
143 }
144 Action::CreateTexture(id, desc) => {
145 let texture = device.create_texture(&desc).expect("create_texture error");
146 self.textures.insert(id, texture);
147 }
148 Action::DestroyTexture(id) => {
149 let texture = self.textures.get(&id).expect("invalid texture");
150 texture.destroy();
151 }
152 Action::DropTexture(id) => {
153 self.textures.remove(&id).expect("invalid texture");
154 }
155 Action::CreateTextureView { id, parent, desc } => {
156 let parent_texture = self.resolve_texture_id(parent);
157 let texture_view = device
158 .create_texture_view(&parent_texture, &desc)
159 .expect("create_texture_view error");
160 self.texture_views.insert(id, texture_view);
161 }
162 Action::DropTextureView(id) => {
163 self.texture_views
164 .remove(&id)
165 .expect("invalid texture view");
166 }
167 Action::CreateExternalTexture { id, desc, planes } => {
168 let planes = planes
169 .iter()
170 .map(|&id| self.resolve_texture_view_id(id))
171 .collect::<Vec<_>>();
172 let external_texture = device
173 .create_external_texture(&desc, &planes)
174 .expect("create_external_texture error");
175 self.external_textures.insert(id, external_texture);
176 }
177 Action::DestroyExternalTexture(id) => {
178 let external_texture = self
179 .external_textures
180 .get(&id)
181 .expect("invalid external texture");
182 external_texture.destroy();
183 }
184 Action::DropExternalTexture(id) => {
185 self.external_textures
186 .remove(&id)
187 .expect("invalid external texture");
188 }
189 Action::CreateSampler(id, desc) => {
190 let sampler = device.create_sampler(&desc).expect("create_sampler error");
191 self.samplers.insert(id, sampler);
192 }
193 Action::DropSampler(id) => {
194 self.samplers.remove(&id).expect("invalid sampler");
195 }
196 Action::GetSurfaceTexture { .. } => {
197 unimplemented!()
198 }
199 Action::CreateBindGroupLayout(id, desc) => {
200 let bind_group_layout = device
201 .create_bind_group_layout(&desc)
202 .expect("create_bind_group_layout error");
203 self.bind_group_layouts.insert(id, bind_group_layout);
204 }
205 Action::GetRenderPipelineBindGroupLayout {
206 id,
207 pipeline,
208 index,
209 } => {
210 let pipeline = self.resolve_render_pipeline_id(pipeline);
211 let bgl = pipeline
212 .get_bind_group_layout(index)
213 .expect("invalid render pipeline");
214 self.bind_group_layouts.insert(id, bgl);
215 }
216 Action::GetComputePipelineBindGroupLayout {
217 id,
218 pipeline,
219 index,
220 } => {
221 let pipeline = self.resolve_compute_pipeline_id(pipeline);
222 let bgl = pipeline
223 .get_bind_group_layout(index)
224 .expect("invalid compute pipeline");
225 self.bind_group_layouts.insert(id, bgl);
226 }
227 Action::DropBindGroupLayout(id) => {
228 self.bind_group_layouts
229 .remove(&id)
230 .expect("invalid bind group layout");
231 }
232 Action::CreatePipelineLayout(id, desc) => {
233 let bind_group_layouts: Vec<_> = desc
234 .bind_group_layouts
235 .to_vec()
236 .into_iter()
237 .map(|bgl_id| bgl_id.map(|bgl_id| self.resolve_bind_group_layout_id(bgl_id)))
238 .collect();
239
240 let resolved_desc = wgc::binding_model::ResolvedPipelineLayoutDescriptor {
241 label: desc.label.clone(),
242 bind_group_layouts: Cow::from(&bind_group_layouts),
243 immediate_size: desc.immediate_size,
244 };
245
246 let pipeline_layout = device
247 .create_pipeline_layout(&resolved_desc)
248 .expect("create_pipeline_layout error");
249 self.pipeline_layouts.insert(id, pipeline_layout);
250 }
251 Action::DropPipelineLayout(id) => {
252 self.pipeline_layouts
253 .remove(&id)
254 .expect("invalid pipeline layout");
255 }
256 Action::CreateBindGroup(id, desc) => {
257 let resolved_desc = self.resolve_bind_group_descriptor(desc);
258 let bind_group = device
259 .create_bind_group(resolved_desc)
260 .expect("create_bind_group error");
261 self.bind_groups.insert(id, bind_group);
262 }
263 Action::DropBindGroup(id) => {
264 let _bind_group = self.bind_groups.remove(&id).expect("invalid bind group");
265 }
266 Action::CreateShaderModule { id, desc, data } => {
267 let code = loader.load_utf8(&data);
268 let source = if data.kind() == DataKind::Wgsl {
269 wgc::pipeline::ShaderModuleSource::Wgsl(code.clone())
270 } else if data.kind() == DataKind::Ron {
271 let module = ron::de::from_str(&code).unwrap();
272 wgc::pipeline::ShaderModuleSource::Naga(module)
273 } else {
274 panic!(
275 "Unknown data kind for CreateShaderModule: {:?}",
276 data.kind()
277 );
278 };
279 match device.create_shader_module(&desc, source) {
280 Ok(module) => self.shader_modules.insert(id, module),
281 Err(e) => panic!("shader compilation error:\n---{code}\n---\n{e}"),
282 };
283 }
284 Action::CreateShaderModulePassthrough {
285 id,
286 data,
287 label,
288 entry_points,
289 } => {
290 let spirv = data.iter().find_map(|a| {
291 if a.kind() == DataKind::Spv {
292 let data = loader.load(a);
293 assert!(data.len().is_multiple_of(4));
294
295 Some(Cow::Owned(bytemuck::pod_collect_to_vec(&data)))
296 } else {
297 None
298 }
299 });
300 let dxil = data.iter().find_map(|a| {
301 (a.kind() == DataKind::Dxil).then(|| Cow::Owned(loader.load(a).into_owned()))
302 });
303 let hlsl = data.iter().find_map(|a| {
304 (a.kind() == DataKind::Hlsl)
305 .then(|| Cow::Owned(loader.load_utf8(a).into_owned()))
306 });
307 let metallib = data.iter().find_map(|a| {
308 (a.kind() == DataKind::MetalLib)
309 .then(|| Cow::Owned(loader.load(a).into_owned()))
310 });
311 let msl = data.iter().find_map(|a| {
312 (a.kind() == DataKind::Msl)
313 .then(|| Cow::Owned(loader.load_utf8(a).into_owned()))
314 });
315 let glsl = data.iter().find_map(|a| {
316 (a.kind() == DataKind::Glsl)
317 .then(|| Cow::Owned(loader.load_utf8(a).into_owned()))
318 });
319 let wgsl = data.iter().find_map(|a| {
320 (a.kind() == DataKind::Wgsl)
321 .then(|| Cow::Owned(loader.load_utf8(a).into_owned()))
322 });
323
324 let desc = wgt::CreateShaderModuleDescriptorPassthrough {
325 label,
326 entry_points,
327
328 spirv,
329 dxil,
330 hlsl,
331 metallib,
332 msl,
333 glsl,
334 wgsl,
335 };
336 match unsafe { device.create_shader_module_passthrough(&desc) } {
337 Ok(module) => self.shader_modules.insert(id, module),
338 Err(e) => panic!("shader compilation error:\n{e}"),
339 };
340 }
341 Action::DropShaderModule(id) => {
342 self.shader_modules
343 .remove(&id)
344 .expect("invalid shader module");
345 }
346 Action::CreateComputePipeline { id, desc } => {
347 let resolved_desc = self.resolve_compute_pipeline_descriptor(desc);
348 let pipeline = device.create_compute_pipeline(resolved_desc);
349 process_result(
350 "create_compute_pipeline",
351 &mut self.compute_pipelines,
352 id,
353 pipeline,
354 );
355 }
356 Action::DropComputePipeline(id) => {
357 self.compute_pipelines
358 .remove(&id)
359 .expect("invalid compute pipeline");
360 }
361 Action::CreateGeneralRenderPipeline { id, desc } => {
362 let resolved_desc = self.resolve_render_pipeline_descriptor(desc);
366 let pipeline = device.create_render_pipeline(resolved_desc);
367 process_result(
368 "create_render_pipeline",
369 &mut self.render_pipelines,
370 id,
371 pipeline,
372 );
373 }
374 Action::DropRenderPipeline(id) => {
375 self.render_pipelines
376 .remove(&id)
377 .expect("invalid render pipeline");
378 }
379 Action::CreatePipelineCache { id, desc } => {
380 let cache = unsafe { device.create_pipeline_cache(&desc) }.unwrap();
381 self.pipeline_caches.insert(id, cache);
382 }
383 Action::DropPipelineCache(id) => {
384 self.pipeline_caches
385 .remove(&id)
386 .expect("invalid pipeline cache");
387 }
388 Action::CreateRenderBundle { .. } => {
389 unimplemented!("traced render bundles are not supported");
390 }
391 Action::DropRenderBundle(id) => {
392 self.render_bundles
393 .remove(&id)
394 .expect("invalid render bundle");
395 }
396 Action::CreateQuerySet { id, desc } => {
397 let query_set = device
398 .create_query_set(&desc)
399 .expect("create_query_set error");
400 self.query_sets.insert(id, query_set);
401 }
402 Action::DestroyQuerySet(id) => {
403 let query_set = self.query_sets.get(&id).expect("invalid query set");
404 query_set.destroy();
405 }
406 Action::DropQuerySet(id) => {
407 self.query_sets.remove(&id).expect("invalid query set");
408 }
409 Action::WriteBuffer {
410 id,
411 data,
412 offset,
413 size,
414 queued,
415 } => {
416 let buffer = self.resolve_buffer_id(id);
417 let bin = loader.load(&data);
418 if queued {
419 queue
420 .write_buffer(buffer, offset, &bin[..size.try_into().unwrap()])
421 .expect("Queue::write_buffer error");
422 } else {
423 device
424 .set_buffer_data(&buffer, offset, &bin[..size.try_into().unwrap()])
425 .expect("Device::set_buffer_data error");
426 }
427 }
428 Action::WriteTexture {
429 to,
430 data,
431 layout,
432 size,
433 } => {
434 let to = self.resolve_texel_copy_texture_info(to);
435 let bin = loader.load(&data);
436 queue
437 .write_texture(to, &bin, &layout, &size)
438 .expect("Queue::write_texture error");
439 }
440 Action::Submit(_index, ref commands) if commands.is_empty() => {
441 queue.submit(&[]).unwrap();
442 }
443 Action::Submit(_index, commands) => {
444 let resolved_commands: Vec<_> = commands
445 .into_iter()
446 .map(|cmd| self.resolve_command(cmd))
447 .collect();
448 let buffer = wgc::command::CommandBuffer::from_trace(device, resolved_commands);
449 queue.submit(&[buffer]).unwrap();
450 }
451 Action::FailedCommands {
452 commands,
453 failed_at_submit,
454 error,
455 } => {
456 let action = if failed_at_submit.is_some() {
457 "submitting"
458 } else {
459 "encoding"
460 };
461 if let Some(commands) = commands {
462 log::trace!(
463 "Trace recorded an error {action} the following commands: {commands:#?}"
464 );
465 }
466 panic!("Error recorded in trace: {error}");
467 }
468 Action::CreateBlas { id, desc, sizes } => {
469 let blas = device.create_blas(&desc, sizes).expect("create_blas error");
470 self.blas_s.insert(id, blas);
471 }
472 Action::DropBlas(id) => {
473 self.blas_s.remove(&id).expect("invalid blas");
474 }
475 Action::CreateTlas { id, desc } => {
476 let tlas = device.create_tlas(&desc).expect("create_tlas error");
477 self.tlas_s.insert(id, tlas);
478 }
479 Action::DropTlas(id) => {
480 self.tlas_s.remove(&id).expect("invalid tlas");
481 }
482 }
483 }
484
485 pub fn get_surface_texture(
489 &mut self,
490 id: wgc::id::PointerId<wgc::id::markers::Texture>,
491 surface: &wgc::instance::Surface,
492 ) {
493 let frame = surface
494 .get_current_texture()
495 .expect("get_current_texture error");
496 let texture = frame.texture.expect("did not obtain a surface texture");
497 self.textures.insert(id, texture);
498 }
499
500 pub fn resolve_buffer_id(
501 &self,
502 id: wgc::id::PointerId<wgc::id::markers::Buffer>,
503 ) -> Arc<wgc::resource::Buffer> {
504 self.buffers.get(&id).expect("invalid buffer").clone()
505 }
506
507 fn resolve_texture_id(
508 &self,
509 id: wgc::id::PointerId<wgc::id::markers::Texture>,
510 ) -> Arc<wgc::resource::Texture> {
511 self.textures.get(&id).expect("invalid texture").clone()
512 }
513
514 fn resolve_texture_view_id(
515 &self,
516 id: wgc::id::PointerId<wgc::id::markers::TextureView>,
517 ) -> Arc<wgc::resource::TextureView> {
518 self.texture_views
519 .get(&id)
520 .expect("invalid texture view")
521 .clone()
522 }
523
524 fn resolve_external_texture_id(
525 &self,
526 id: wgc::id::PointerId<wgc::id::markers::ExternalTexture>,
527 ) -> Arc<wgc::resource::ExternalTexture> {
528 self.external_textures
529 .get(&id)
530 .expect("invalid external texture")
531 .clone()
532 }
533
534 fn resolve_sampler_id(
535 &self,
536 id: wgc::id::PointerId<wgc::id::markers::Sampler>,
537 ) -> Arc<wgc::resource::Sampler> {
538 self.samplers.get(&id).expect("invalid sampler").clone()
539 }
540
541 fn resolve_bind_group_layout_id(
542 &self,
543 id: wgc::id::PointerId<wgc::id::markers::BindGroupLayout>,
544 ) -> Arc<wgc::binding_model::BindGroupLayout> {
545 self.bind_group_layouts
546 .get(&id)
547 .expect("invalid bind group layout")
548 .clone()
549 }
550
551 fn resolve_bind_group_id(
552 &self,
553 id: wgc::id::PointerId<wgc::id::markers::BindGroup>,
554 ) -> Arc<wgc::binding_model::BindGroup> {
555 self.bind_groups
556 .get(&id)
557 .expect("invalid bind group")
558 .clone()
559 }
560
561 fn resolve_pipeline_layout_id(
562 &self,
563 id: wgc::id::PointerId<wgc::id::markers::PipelineLayout>,
564 ) -> Arc<wgc::binding_model::PipelineLayout> {
565 self.pipeline_layouts
566 .get(&id)
567 .expect("invalid pipeline layout")
568 .clone()
569 }
570
571 fn resolve_shader_module_id(
572 &self,
573 id: wgc::id::PointerId<wgc::id::markers::ShaderModule>,
574 ) -> Arc<wgc::pipeline::ShaderModule> {
575 self.shader_modules
576 .get(&id)
577 .expect("invalid shader module")
578 .clone()
579 }
580
581 fn resolve_render_pipeline_id(
582 &self,
583 id: wgc::id::PointerId<wgc::id::markers::RenderPipeline>,
584 ) -> Arc<wgc::pipeline::RenderPipeline> {
585 self.render_pipelines
586 .get(&id)
587 .expect("invalid render pipeline")
588 .clone()
589 }
590
591 fn resolve_compute_pipeline_id(
592 &self,
593 id: wgc::id::PointerId<wgc::id::markers::ComputePipeline>,
594 ) -> Arc<wgc::pipeline::ComputePipeline> {
595 self.compute_pipelines
596 .get(&id)
597 .expect("invalid compute pipeline")
598 .clone()
599 }
600
601 fn resolve_pipeline_cache_id(
602 &self,
603 id: wgc::id::PointerId<wgc::id::markers::PipelineCache>,
604 ) -> Arc<wgc::pipeline::PipelineCache> {
605 self.pipeline_caches
606 .get(&id)
607 .expect("invalid pipeline cache")
608 .clone()
609 }
610
611 fn resolve_render_bundle_id(
612 &self,
613 id: wgc::id::PointerId<wgc::id::markers::RenderBundle>,
614 ) -> Arc<wgc::command::RenderBundle> {
615 self.render_bundles
616 .get(&id)
617 .expect("invalid render bundle")
618 .clone()
619 }
620
621 fn resolve_query_set_id(
622 &self,
623 id: wgc::id::PointerId<wgc::id::markers::QuerySet>,
624 ) -> Arc<wgc::resource::QuerySet> {
625 self.query_sets.get(&id).expect("invalid query set").clone()
626 }
627
628 fn resolve_blas_id(
629 &self,
630 id: wgc::id::PointerId<wgc::id::markers::Blas>,
631 ) -> Arc<wgc::resource::Blas> {
632 self.blas_s.get(&id).expect("invalid blas").clone()
633 }
634
635 fn resolve_tlas_id(
636 &self,
637 id: wgc::id::PointerId<wgc::id::markers::Tlas>,
638 ) -> Arc<wgc::resource::Tlas> {
639 self.tlas_s.get(&id).expect("invalid tlas").clone()
640 }
641
642 fn resolve_texel_copy_texture_info(
643 &self,
644 info: wgt::TexelCopyTextureInfo<wgc::id::PointerId<wgc::id::markers::Texture>>,
645 ) -> wgt::TexelCopyTextureInfo<Arc<wgc::resource::Texture>> {
646 wgt::TexelCopyTextureInfo {
647 texture: self.resolve_texture_id(info.texture),
648 mip_level: info.mip_level,
649 origin: info.origin,
650 aspect: info.aspect,
651 }
652 }
653
654 fn resolve_compute_pipeline_descriptor<'a>(
655 &self,
656 desc: wgc::device::trace::TraceComputePipelineDescriptor<'a>,
657 ) -> wgc::pipeline::ResolvedComputePipelineDescriptor<'a> {
658 wgc::pipeline::ResolvedComputePipelineDescriptor {
659 label: desc.label,
660 layout: desc.layout.map(|id| self.resolve_pipeline_layout_id(id)),
661 stage: wgc::pipeline::ResolvedProgrammableStageDescriptor {
662 module: self.resolve_shader_module_id(desc.stage.module),
663 entry_point: desc.stage.entry_point,
664 constants: desc.stage.constants,
665 zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
666 },
667 cache: desc.cache.map(|id| self.resolve_pipeline_cache_id(id)),
668 }
669 }
670
671 fn resolve_render_pipeline_descriptor<'a>(
672 &self,
673 desc: wgc::device::trace::TraceGeneralRenderPipelineDescriptor<'a>,
674 ) -> wgc::pipeline::ResolvedGeneralRenderPipelineDescriptor<'a> {
675 let layout = desc.layout.map(|id| self.resolve_pipeline_layout_id(id));
676
677 let vertex = match desc.vertex {
678 wgc::pipeline::RenderPipelineVertexProcessor::Vertex(vertex_state) => {
679 wgc::pipeline::RenderPipelineVertexProcessor::Vertex(
680 wgc::pipeline::ResolvedVertexState {
681 stage: wgc::pipeline::ResolvedProgrammableStageDescriptor {
682 module: self.resolve_shader_module_id(vertex_state.stage.module),
683 entry_point: vertex_state.stage.entry_point,
684 constants: vertex_state.stage.constants,
685 zero_initialize_workgroup_memory: vertex_state
686 .stage
687 .zero_initialize_workgroup_memory,
688 },
689 buffers: vertex_state.buffers,
690 },
691 )
692 }
693 wgc::pipeline::RenderPipelineVertexProcessor::Mesh(task_state, mesh_state) => {
694 let resolved_task = task_state.map(|task| wgc::pipeline::ResolvedTaskState {
695 stage: wgc::pipeline::ResolvedProgrammableStageDescriptor {
696 module: self.resolve_shader_module_id(task.stage.module),
697 entry_point: task.stage.entry_point,
698 constants: task.stage.constants,
699 zero_initialize_workgroup_memory: task
700 .stage
701 .zero_initialize_workgroup_memory,
702 },
703 });
704 let resolved_mesh = wgc::pipeline::ResolvedMeshState {
705 stage: wgc::pipeline::ResolvedProgrammableStageDescriptor {
706 module: self.resolve_shader_module_id(mesh_state.stage.module),
707 entry_point: mesh_state.stage.entry_point,
708 constants: mesh_state.stage.constants,
709 zero_initialize_workgroup_memory: mesh_state
710 .stage
711 .zero_initialize_workgroup_memory,
712 },
713 };
714 wgc::pipeline::RenderPipelineVertexProcessor::Mesh(resolved_task, resolved_mesh)
715 }
716 };
717
718 let fragment = desc
719 .fragment
720 .map(|fragment_state| wgc::pipeline::ResolvedFragmentState {
721 stage: wgc::pipeline::ResolvedProgrammableStageDescriptor {
722 module: self.resolve_shader_module_id(fragment_state.stage.module),
723 entry_point: fragment_state.stage.entry_point,
724 constants: fragment_state.stage.constants,
725 zero_initialize_workgroup_memory: fragment_state
726 .stage
727 .zero_initialize_workgroup_memory,
728 },
729 targets: fragment_state.targets,
730 });
731
732 wgc::pipeline::ResolvedGeneralRenderPipelineDescriptor {
733 label: desc.label,
734 layout,
735 vertex,
736 primitive: desc.primitive,
737 depth_stencil: desc.depth_stencil,
738 multisample: desc.multisample,
739 fragment,
740 multiview_mask: desc.multiview_mask,
741 cache: desc.cache.map(|id| self.resolve_pipeline_cache_id(id)),
742 }
743 }
744
745 fn resolve_bind_group_descriptor<'a>(
746 &self,
747 desc: wgc::device::trace::TraceBindGroupDescriptor<'a>,
748 ) -> wgc::binding_model::ResolvedBindGroupDescriptor<'a> {
749 let layout = self.resolve_bind_group_layout_id(desc.layout);
750
751 let entries: Vec<wgc::binding_model::ResolvedBindGroupEntry> = desc
752 .entries
753 .to_vec()
754 .into_iter()
755 .map(|entry| {
756 let resource = match entry.resource {
757 BindingResource::Buffer(buffer_binding) => {
758 let buffer = self.resolve_buffer_id(buffer_binding.buffer);
759 wgc::binding_model::ResolvedBindingResource::Buffer(
760 wgc::binding_model::ResolvedBufferBinding {
761 buffer,
762 offset: buffer_binding.offset,
763 size: buffer_binding.size,
764 },
765 )
766 }
767 BindingResource::BufferArray(buffer_bindings) => {
768 let resolved_buffers: Vec<_> = buffer_bindings
769 .to_vec()
770 .into_iter()
771 .map(|bb| {
772 let buffer = self.resolve_buffer_id(bb.buffer);
773 wgc::binding_model::ResolvedBufferBinding {
774 buffer,
775 offset: bb.offset,
776 size: bb.size,
777 }
778 })
779 .collect();
780 wgc::binding_model::ResolvedBindingResource::BufferArray(Cow::Owned(
781 resolved_buffers,
782 ))
783 }
784 BindingResource::Sampler(sampler_id) => {
785 let sampler = self.resolve_sampler_id(sampler_id);
786 wgc::binding_model::ResolvedBindingResource::Sampler(sampler)
787 }
788 BindingResource::SamplerArray(sampler_ids) => {
789 let resolved_samplers: Vec<_> = sampler_ids
790 .to_vec()
791 .into_iter()
792 .map(|id| self.resolve_sampler_id(id))
793 .collect();
794 wgc::binding_model::ResolvedBindingResource::SamplerArray(Cow::Owned(
795 resolved_samplers,
796 ))
797 }
798 BindingResource::TextureView(texture_view_id) => {
799 let texture_view = self.resolve_texture_view_id(texture_view_id);
800 wgc::binding_model::ResolvedBindingResource::TextureView(texture_view)
801 }
802 BindingResource::TextureViewArray(texture_view_ids) => {
803 let resolved_views: Vec<_> = texture_view_ids
804 .to_vec()
805 .into_iter()
806 .map(|id| self.resolve_texture_view_id(id))
807 .collect();
808 wgc::binding_model::ResolvedBindingResource::TextureViewArray(Cow::Owned(
809 resolved_views,
810 ))
811 }
812 BindingResource::AccelerationStructure(tlas_id) => {
813 let tlas = self.resolve_tlas_id(tlas_id);
814 wgc::binding_model::ResolvedBindingResource::AccelerationStructure(tlas)
815 }
816 BindingResource::AccelerationStructureArray(tlas_ids) => {
817 let resolved_tlas: Vec<_> = tlas_ids
818 .to_vec()
819 .into_iter()
820 .map(|id| self.resolve_tlas_id(id))
821 .collect();
822 wgc::binding_model::ResolvedBindingResource::AccelerationStructureArray(
823 Cow::Owned(resolved_tlas),
824 )
825 }
826 BindingResource::ExternalTexture(external_texture_id) => {
827 let external_texture =
828 self.resolve_external_texture_id(external_texture_id);
829 wgc::binding_model::ResolvedBindingResource::ExternalTexture(
830 external_texture,
831 )
832 }
833 };
834
835 wgc::binding_model::ResolvedBindGroupEntry {
836 binding: entry.binding,
837 resource,
838 }
839 })
840 .collect();
841
842 wgc::binding_model::ResolvedBindGroupDescriptor {
843 label: desc.label.clone(),
844 layout,
845 entries: entries.into(),
846 }
847 }
848
849 fn resolve_command(&self, command: Command<PointerReferences>) -> ArcCommand {
850 match command {
851 Command::CopyBufferToBuffer {
852 src,
853 src_offset,
854 dst,
855 dst_offset,
856 size,
857 } => Command::CopyBufferToBuffer {
858 src: self.resolve_buffer_id(src),
859 src_offset,
860 dst: self.resolve_buffer_id(dst),
861 dst_offset,
862 size,
863 },
864 Command::CopyBufferToTexture { src, dst, size } => Command::CopyBufferToTexture {
865 src: self.resolve_texel_copy_buffer_info(src),
866 dst: self.resolve_texel_copy_texture_info(dst),
867 size,
868 },
869 Command::CopyTextureToBuffer { src, dst, size } => Command::CopyTextureToBuffer {
870 src: self.resolve_texel_copy_texture_info(src),
871 dst: self.resolve_texel_copy_buffer_info(dst),
872 size,
873 },
874 Command::CopyTextureToTexture { src, dst, size } => Command::CopyTextureToTexture {
875 src: self.resolve_texel_copy_texture_info(src),
876 dst: self.resolve_texel_copy_texture_info(dst),
877 size,
878 },
879 Command::ClearBuffer { dst, offset, size } => Command::ClearBuffer {
880 dst: self.resolve_buffer_id(dst),
881 offset,
882 size,
883 },
884 Command::ClearTexture {
885 dst,
886 subresource_range,
887 } => Command::ClearTexture {
888 dst: self.resolve_texture_id(dst),
889 subresource_range,
890 },
891 Command::WriteTimestamp {
892 query_set,
893 query_index,
894 } => Command::WriteTimestamp {
895 query_set: self.resolve_query_set_id(query_set),
896 query_index,
897 },
898 Command::ResolveQuerySet {
899 query_set,
900 start_query,
901 query_count,
902 destination,
903 destination_offset,
904 } => Command::ResolveQuerySet {
905 query_set: self.resolve_query_set_id(query_set),
906 start_query,
907 query_count,
908 destination: self.resolve_buffer_id(destination),
909 destination_offset,
910 },
911 Command::PushDebugGroup(label) => Command::PushDebugGroup(label.clone()),
912 Command::PopDebugGroup => Command::PopDebugGroup,
913 Command::InsertDebugMarker(label) => Command::InsertDebugMarker(label.clone()),
914 Command::RunComputePass {
915 pass,
916 timestamp_writes,
917 } => Command::RunComputePass {
918 pass: self.resolve_compute_pass(pass),
919 timestamp_writes: timestamp_writes.map(|tw| self.resolve_pass_timestamp_writes(tw)),
920 },
921 Command::RunRenderPass {
922 pass,
923 color_attachments,
924 depth_stencil_attachment,
925 timestamp_writes,
926 occlusion_query_set,
927 multiview_mask,
928 } => Command::RunRenderPass {
929 pass: self.resolve_render_pass(pass),
930 color_attachments: self.resolve_color_attachments(color_attachments),
931 depth_stencil_attachment: depth_stencil_attachment
932 .map(|att| self.resolve_depth_stencil_attachment(att)),
933 timestamp_writes: timestamp_writes.map(|tw| self.resolve_pass_timestamp_writes(tw)),
934 occlusion_query_set: occlusion_query_set.map(|qs| self.resolve_query_set_id(qs)),
935 multiview_mask,
936 },
937 Command::BuildAccelerationStructures { blas, tlas } => {
938 Command::BuildAccelerationStructures {
939 blas: blas
940 .into_iter()
941 .map(|entry| self.resolve_blas_build_entry(entry))
942 .collect(),
943 tlas: tlas
944 .into_iter()
945 .map(|package| self.resolve_tlas_package(package))
946 .collect(),
947 }
948 }
949 Command::TransitionResources {
950 buffer_transitions,
951 texture_transitions,
952 } => Command::TransitionResources {
953 buffer_transitions: buffer_transitions
954 .into_iter()
955 .map(|trans| self.resolve_buffer_transition(trans))
956 .collect(),
957 texture_transitions: texture_transitions
958 .into_iter()
959 .map(|trans| self.resolve_texture_transition(trans))
960 .collect(),
961 },
962 }
963 }
964
965 fn resolve_texel_copy_buffer_info(
967 &self,
968 info: wgt::TexelCopyBufferInfo<PointerId<wgc::id::markers::Buffer>>,
969 ) -> wgt::TexelCopyBufferInfo<Arc<wgc::resource::Buffer>> {
970 wgt::TexelCopyBufferInfo {
971 buffer: self
972 .buffers
973 .get(&info.buffer)
974 .cloned()
975 .expect("invalid buffer"),
976 layout: info.layout,
977 }
978 }
979
980 fn resolve_compute_pass(
981 &self,
982 pass: BasePass<wgc::command::ComputeCommand<PointerReferences>, Infallible>,
983 ) -> BasePass<wgc::command::ComputeCommand<ArcReferences>, Infallible> {
984 let BasePass {
985 label,
986 error,
987 commands,
988 dynamic_offsets,
989 immediates_data,
990 string_data,
991 } = pass;
992
993 BasePass {
994 label,
995 error,
996 commands: commands
997 .into_iter()
998 .map(|cmd| self.resolve_compute_command(cmd))
999 .collect(),
1000 dynamic_offsets,
1001 immediates_data,
1002 string_data,
1003 }
1004 }
1005
1006 fn resolve_render_pass(
1007 &self,
1008 pass: BasePass<wgc::command::RenderCommand<PointerReferences>, Infallible>,
1009 ) -> BasePass<wgc::command::RenderCommand<ArcReferences>, Infallible> {
1010 let BasePass {
1011 label,
1012 error,
1013 commands,
1014 dynamic_offsets,
1015 immediates_data,
1016 string_data,
1017 } = pass;
1018
1019 BasePass {
1020 label,
1021 error,
1022 commands: commands
1023 .into_iter()
1024 .map(|cmd| self.resolve_render_command(cmd))
1025 .collect(),
1026 dynamic_offsets,
1027 immediates_data,
1028 string_data,
1029 }
1030 }
1031
1032 fn resolve_compute_command(
1033 &self,
1034 command: wgc::command::ComputeCommand<PointerReferences>,
1035 ) -> wgc::command::ComputeCommand<ArcReferences> {
1036 use wgc::command::ComputeCommand as C;
1037 match command {
1038 C::SetBindGroup {
1039 index,
1040 num_dynamic_offsets,
1041 bind_group,
1042 } => C::SetBindGroup {
1043 index,
1044 num_dynamic_offsets,
1045 bind_group: bind_group.map(|bg| self.resolve_bind_group_id(bg)),
1046 },
1047 C::SetPipeline(id) => C::SetPipeline(self.resolve_compute_pipeline_id(id)),
1048 C::SetImmediate {
1049 offset,
1050 size_bytes,
1051 values_offset,
1052 } => C::SetImmediate {
1053 offset,
1054 size_bytes,
1055 values_offset,
1056 },
1057 C::DispatchWorkgroups(groups) => C::DispatchWorkgroups(groups),
1058 C::DispatchWorkgroupsIndirect { buffer, offset } => C::DispatchWorkgroupsIndirect {
1059 buffer: self.resolve_buffer_id(buffer),
1060 offset,
1061 },
1062 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
1063 C::PopDebugGroup => C::PopDebugGroup,
1064 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
1065 C::WriteTimestamp {
1066 query_set,
1067 query_index,
1068 } => C::WriteTimestamp {
1069 query_set: self.resolve_query_set_id(query_set),
1070 query_index,
1071 },
1072 C::BeginPipelineStatisticsQuery {
1073 query_set,
1074 query_index,
1075 } => C::BeginPipelineStatisticsQuery {
1076 query_set: self.resolve_query_set_id(query_set),
1077 query_index,
1078 },
1079 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
1080 C::TransitionResources {
1081 buffer_transitions,
1082 texture_transitions,
1083 } => C::TransitionResources {
1084 buffer_transitions: buffer_transitions
1085 .into_iter()
1086 .map(|buffer_transition| wgt::BufferTransition {
1087 buffer: self.resolve_buffer_id(buffer_transition.buffer),
1088 state: buffer_transition.state,
1089 })
1090 .collect(),
1091 texture_transitions: texture_transitions
1092 .into_iter()
1093 .map(|texture_transition| wgt::TextureTransition {
1094 texture: self.resolve_texture_view_id(texture_transition.texture),
1095 selector: texture_transition.selector,
1096 state: texture_transition.state,
1097 })
1098 .collect(),
1099 },
1100 }
1101 }
1102
1103 fn resolve_render_command(
1104 &self,
1105 command: wgc::command::RenderCommand<PointerReferences>,
1106 ) -> wgc::command::RenderCommand<ArcReferences> {
1107 use wgc::command::RenderCommand as C;
1108 match command {
1109 C::SetBindGroup {
1110 index,
1111 num_dynamic_offsets,
1112 bind_group,
1113 } => C::SetBindGroup {
1114 index,
1115 num_dynamic_offsets,
1116 bind_group: bind_group.map(|bg| self.resolve_bind_group_id(bg)),
1117 },
1118 C::SetPipeline(id) => C::SetPipeline(self.resolve_render_pipeline_id(id)),
1119 C::SetIndexBuffer {
1120 buffer,
1121 index_format,
1122 offset,
1123 size,
1124 } => C::SetIndexBuffer {
1125 buffer: self.resolve_buffer_id(buffer),
1126 index_format,
1127 offset,
1128 size,
1129 },
1130 C::SetVertexBuffer {
1131 slot,
1132 buffer,
1133 offset,
1134 size,
1135 } => C::SetVertexBuffer {
1136 slot,
1137 buffer: buffer.map(|buffer| self.resolve_buffer_id(buffer)),
1138 offset,
1139 size,
1140 },
1141 C::SetBlendConstant(color) => C::SetBlendConstant(color),
1142 C::SetStencilReference(val) => C::SetStencilReference(val),
1143 C::SetViewport {
1144 rect,
1145 depth_min,
1146 depth_max,
1147 } => C::SetViewport {
1148 rect,
1149 depth_min,
1150 depth_max,
1151 },
1152 C::SetScissor(rect) => C::SetScissor(rect),
1153 C::SetImmediate {
1154 offset,
1155 size_bytes,
1156 values_offset,
1157 } => C::SetImmediate {
1158 offset,
1159 size_bytes,
1160 values_offset,
1161 },
1162 C::Draw {
1163 vertex_count,
1164 instance_count,
1165 first_vertex,
1166 first_instance,
1167 } => C::Draw {
1168 vertex_count,
1169 instance_count,
1170 first_vertex,
1171 first_instance,
1172 },
1173 C::DrawIndexed {
1174 index_count,
1175 instance_count,
1176 first_index,
1177 base_vertex,
1178 first_instance,
1179 } => C::DrawIndexed {
1180 index_count,
1181 instance_count,
1182 first_index,
1183 base_vertex,
1184 first_instance,
1185 },
1186 C::DrawMeshTasks {
1187 group_count_x,
1188 group_count_y,
1189 group_count_z,
1190 } => C::DrawMeshTasks {
1191 group_count_x,
1192 group_count_y,
1193 group_count_z,
1194 },
1195 C::DrawIndirect {
1196 buffer,
1197 offset,
1198 count,
1199 family,
1200 vertex_or_index_limit,
1201 instance_limit,
1202 } => C::DrawIndirect {
1203 buffer: self.resolve_buffer_id(buffer),
1204 offset,
1205 count,
1206 family,
1207 vertex_or_index_limit,
1208 instance_limit,
1209 },
1210 C::MultiDrawIndirectCount {
1211 buffer,
1212 offset,
1213 count_buffer,
1214 count_buffer_offset,
1215 max_count,
1216 family,
1217 } => C::MultiDrawIndirectCount {
1218 buffer: self.resolve_buffer_id(buffer),
1219 offset,
1220 count_buffer: self.resolve_buffer_id(count_buffer),
1221 count_buffer_offset,
1222 max_count,
1223 family,
1224 },
1225 C::PushDebugGroup { color, len } => C::PushDebugGroup { color, len },
1226 C::PopDebugGroup => C::PopDebugGroup,
1227 C::InsertDebugMarker { color, len } => C::InsertDebugMarker { color, len },
1228 C::WriteTimestamp {
1229 query_set,
1230 query_index,
1231 } => C::WriteTimestamp {
1232 query_set: self.resolve_query_set_id(query_set),
1233 query_index,
1234 },
1235 C::BeginOcclusionQuery { query_index } => C::BeginOcclusionQuery { query_index },
1236 C::EndOcclusionQuery => C::EndOcclusionQuery,
1237 C::BeginPipelineStatisticsQuery {
1238 query_set,
1239 query_index,
1240 } => C::BeginPipelineStatisticsQuery {
1241 query_set: self.resolve_query_set_id(query_set),
1242 query_index,
1243 },
1244 C::EndPipelineStatisticsQuery => C::EndPipelineStatisticsQuery,
1245 C::ExecuteBundle(bundle) => C::ExecuteBundle(self.resolve_render_bundle_id(bundle)),
1246 }
1247 }
1248
1249 fn resolve_pass_timestamp_writes(
1250 &self,
1251 writes: wgc::command::PassTimestampWrites<PointerId<wgc::id::markers::QuerySet>>,
1252 ) -> wgc::command::PassTimestampWrites<Arc<wgc::resource::QuerySet>> {
1253 wgc::command::PassTimestampWrites {
1254 query_set: self.resolve_query_set_id(writes.query_set),
1255 beginning_of_pass_write_index: writes.beginning_of_pass_write_index,
1256 end_of_pass_write_index: writes.end_of_pass_write_index,
1257 }
1258 }
1259
1260 fn resolve_color_attachments(
1261 &self,
1262 attachments: wgc::command::ColorAttachments<PointerId<wgc::id::markers::TextureView>>,
1263 ) -> wgc::command::ColorAttachments<Arc<wgc::resource::TextureView>> {
1264 attachments
1265 .into_iter()
1266 .map(|opt| {
1267 opt.map(|att| wgc::command::RenderPassColorAttachment {
1268 view: self.resolve_texture_view_id(att.view),
1269 depth_slice: att.depth_slice,
1270 resolve_target: att
1271 .resolve_target
1272 .map(|rt| self.resolve_texture_view_id(rt)),
1273 load_op: att.load_op,
1274 store_op: att.store_op,
1275 })
1276 })
1277 .collect()
1278 }
1279
1280 fn resolve_depth_stencil_attachment(
1281 &self,
1282 attachment: wgc::command::ResolvedRenderPassDepthStencilAttachment<
1283 PointerId<wgc::id::markers::TextureView>,
1284 >,
1285 ) -> wgc::command::ResolvedRenderPassDepthStencilAttachment<Arc<wgc::resource::TextureView>>
1286 {
1287 wgc::command::ResolvedRenderPassDepthStencilAttachment {
1288 view: self.resolve_texture_view_id(attachment.view),
1289 depth: attachment.depth,
1290 stencil: attachment.stencil,
1291 }
1292 }
1293
1294 fn resolve_blas_build_entry(
1295 &self,
1296 entry: wgc::ray_tracing::OwnedBlasBuildEntry<PointerReferences>,
1297 ) -> wgc::ray_tracing::OwnedBlasBuildEntry<ArcReferences> {
1298 wgc::ray_tracing::OwnedBlasBuildEntry {
1299 blas: self.resolve_blas_id(entry.blas),
1300 geometries: self.resolve_blas_geometries(entry.geometries),
1301 }
1302 }
1303
1304 fn resolve_tlas_package(
1305 &self,
1306 package: wgc::ray_tracing::OwnedTlasPackage<PointerReferences>,
1307 ) -> wgc::ray_tracing::OwnedTlasPackage<ArcReferences> {
1308 wgc::ray_tracing::OwnedTlasPackage {
1309 tlas: self.resolve_tlas_id(package.tlas),
1310 instances: package
1311 .instances
1312 .into_iter()
1313 .map(|opt| opt.map(|inst| self.resolve_tlas_instance(inst)))
1314 .collect(),
1315 lowest_unmodified: package.lowest_unmodified,
1316 }
1317 }
1318
1319 fn resolve_blas_geometries(
1321 &self,
1322 geometries: wgc::ray_tracing::OwnedBlasGeometries<PointerReferences>,
1323 ) -> wgc::ray_tracing::OwnedBlasGeometries<ArcReferences> {
1324 match geometries {
1325 wgc::ray_tracing::OwnedBlasGeometries::TriangleGeometries(geos) => {
1326 wgc::ray_tracing::OwnedBlasGeometries::TriangleGeometries(
1327 geos.into_iter()
1328 .map(|geo| self.resolve_blas_triangle_geometry(geo))
1329 .collect(),
1330 )
1331 }
1332 wgc::ray_tracing::OwnedBlasGeometries::AabbGeometries(geos) => {
1333 wgc::ray_tracing::OwnedBlasGeometries::AabbGeometries(
1334 geos.into_iter()
1335 .map(|geo| self.resolve_blas_aabb_geometry(geo))
1336 .collect(),
1337 )
1338 }
1339 }
1340 }
1341
1342 fn resolve_blas_triangle_geometry(
1343 &self,
1344 geometry: wgc::ray_tracing::OwnedBlasTriangleGeometry<PointerReferences>,
1345 ) -> wgc::ray_tracing::OwnedBlasTriangleGeometry<ArcReferences> {
1346 wgc::ray_tracing::OwnedBlasTriangleGeometry {
1347 size: geometry.size,
1348 vertex_buffer: self.resolve_buffer_id(geometry.vertex_buffer),
1349 index_buffer: geometry.index_buffer.map(|buf| self.resolve_buffer_id(buf)),
1350 transform_buffer: geometry
1351 .transform_buffer
1352 .map(|buf| self.resolve_buffer_id(buf)),
1353 first_vertex: geometry.first_vertex,
1354 vertex_stride: geometry.vertex_stride,
1355 first_index: geometry.first_index,
1356 transform_buffer_offset: geometry.transform_buffer_offset,
1357 }
1358 }
1359
1360 fn resolve_blas_aabb_geometry(
1361 &self,
1362 geometry: wgc::ray_tracing::OwnedBlasAabbGeometry<PointerReferences>,
1363 ) -> wgc::ray_tracing::OwnedBlasAabbGeometry<ArcReferences> {
1364 wgc::ray_tracing::OwnedBlasAabbGeometry {
1365 size: geometry.size,
1366 stride: geometry.stride,
1367 aabb_buffer: self.resolve_buffer_id(geometry.aabb_buffer),
1368 primitive_offset: geometry.primitive_offset,
1369 }
1370 }
1371
1372 fn resolve_tlas_instance(
1373 &self,
1374 instance: wgc::ray_tracing::OwnedTlasInstance<PointerReferences>,
1375 ) -> wgc::ray_tracing::OwnedTlasInstance<ArcReferences> {
1376 wgc::ray_tracing::OwnedTlasInstance {
1377 blas: self.resolve_blas_id(instance.blas),
1378 transform: instance.transform,
1379 custom_data: instance.custom_data,
1380 mask: instance.mask,
1381 }
1382 }
1383
1384 fn resolve_buffer_transition(
1385 &self,
1386 trans: wgt::BufferTransition<PointerId<wgc::id::markers::Buffer>>,
1387 ) -> wgt::BufferTransition<Arc<wgc::resource::Buffer>> {
1388 wgt::BufferTransition {
1389 buffer: self
1390 .buffers
1391 .get(&trans.buffer)
1392 .cloned()
1393 .expect("invalid buffer"),
1394 state: trans.state,
1395 }
1396 }
1397
1398 fn resolve_texture_transition(
1399 &self,
1400 trans: wgt::TextureTransition<PointerId<wgc::id::markers::Texture>>,
1401 ) -> wgt::TextureTransition<Arc<wgc::resource::Texture>> {
1402 wgt::TextureTransition {
1403 texture: self
1404 .textures
1405 .get(&trans.texture)
1406 .cloned()
1407 .expect("invalid texture"),
1408 selector: trans.selector.clone(),
1409 state: trans.state,
1410 }
1411 }
1412}