1use alloc::borrow::ToOwned;
2use alloc::{
3 borrow::Cow::{self, Borrowed},
4 boxed::Box,
5 string::String,
6 sync::Arc,
7 vec::Vec,
8};
9use core::{
10 error::Error,
11 fmt,
12 future::ready,
13 ops::{Deref, Range},
14 pin::Pin,
15 ptr::NonNull,
16 slice,
17};
18use wgc::resource::{BufferMapping, ParentDevice as _};
19use wgt::error::WebGpuError;
20
21use arrayvec::ArrayVec;
22use smallvec::SmallVec;
23use wgc::resource::BlasPrepareCompactResult;
24use wgt::WasmNotSendSync;
25
26use crate::{
27 api,
28 dispatch::{self, BlasCompactCallback},
29 BindingResource, Blas, BufferBinding, BufferDescriptor, Features, LoadOp, Operations,
30 ShaderSource, SurfaceTargetUnsafe, TextureDescriptor, Tlas, WriteOnly,
31};
32use crate::{dispatch::DispatchAdapter, util::Mutex};
33
34use wgc::error::format_error;
35
36#[derive(Clone)]
37pub struct ContextWgpuCore(Arc<wgc::instance::Instance>);
38
39impl fmt::Debug for ContextWgpuCore {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.debug_struct("ContextWgpuCore")
42 .field("type", &"Native")
43 .finish()
44 }
45}
46
47#[track_caller]
48#[cold]
49fn handle_error_fatal(cause: impl Error + WasmNotSendSync + 'static, operation: &'static str) -> ! {
50 panic!("Error in {operation}: {f}", f = format_error(&cause));
51}
52
53impl ContextWgpuCore {
54 pub unsafe fn from_hal_instance<A: hal::Api>(hal_instance: A::Instance) -> Self {
55 Self(wgc::instance::Instance::from_hal_instance::<A>(
56 "wgpu".to_owned(),
57 hal_instance,
58 ))
59 }
60
61 pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
65 unsafe { self.0.as_hal::<A>() }
66 }
67
68 pub fn from_core_instance(core_instance: Arc<wgc::instance::Instance>) -> Self {
69 Self(core_instance)
70 }
71
72 #[cfg(wgpu_core)]
73 pub fn enumerate_adapters(&self, backends: wgt::Backends) -> Vec<Arc<wgc::instance::Adapter>> {
74 self.0
75 .enumerate_adapters(backends, false )
76 }
77
78 pub unsafe fn create_adapter_from_hal<A: hal::Api>(
79 &self,
80 hal_adapter: hal::ExposedAdapter<A>,
81 ) -> Arc<wgc::instance::Adapter> {
82 unsafe { self.0.create_adapter_from_hal(hal_adapter.into()) }
83 }
84
85 pub(crate) fn as_core(&self) -> Arc<wgc::instance::Instance> {
86 self.0.clone()
87 }
88}
89
90fn map_buffer_copy_view(
91 view: crate::TexelCopyBufferInfo<'_>,
92) -> wgt::TexelCopyBufferInfo<Arc<wgc::resource::Buffer>> {
93 wgt::TexelCopyBufferInfo {
94 buffer: view.buffer.inner.as_core().wgpu_buffer.clone(),
95 layout: view.layout,
96 }
97}
98
99fn map_texture_copy_view(
100 view: crate::TexelCopyTextureInfo<'_>,
101) -> wgt::TexelCopyTextureInfo<Arc<wgc::resource::Texture>> {
102 wgt::TexelCopyTextureInfo {
103 texture: view.texture.inner.as_core().wgpu_texture.clone(),
104 mip_level: view.mip_level,
105 origin: view.origin,
106 aspect: view.aspect,
107 }
108}
109
110#[cfg_attr(not(webgl), expect(unused))]
111fn map_texture_tagged_copy_view(
112 view: crate::CopyExternalImageDestInfo<&api::Texture>,
113) -> wgt::CopyExternalImageDestInfo<Arc<wgc::resource::Texture>> {
114 wgt::CopyExternalImageDestInfo {
115 texture: view.texture.inner.as_core().wgpu_texture.clone(),
116 mip_level: view.mip_level,
117 origin: view.origin,
118 aspect: view.aspect,
119 color_space: view.color_space,
120 premultiplied_alpha: view.premultiplied_alpha,
121 }
122}
123
124fn map_load_op<V: Copy>(load: &LoadOp<V>) -> LoadOp<Option<V>> {
125 match *load {
126 LoadOp::Clear(clear_value) => LoadOp::Clear(Some(clear_value)),
127 LoadOp::DontCare(token) => LoadOp::DontCare(token),
128 LoadOp::Load => LoadOp::Load,
129 }
130}
131
132fn map_pass_channel<V: Copy>(ops: Option<&Operations<V>>) -> wgc::command::PassChannel<Option<V>> {
133 match ops {
134 Some(&Operations { load, store }) => wgc::command::PassChannel {
135 load_op: Some(map_load_op(&load)),
136 store_op: Some(store),
137 read_only: false,
138 },
139 None => wgc::command::PassChannel {
140 load_op: None,
141 store_op: None,
142 read_only: true,
143 },
144 }
145}
146
147#[derive(Clone)]
148pub struct CoreSurface {
149 pub(crate) wgpu_surface: Arc<wgc::instance::Surface>,
150 configured_device: Arc<Mutex<Option<Arc<wgc::device::Device>>>>,
153}
154
155impl fmt::Debug for CoreSurface {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 f.debug_struct("CoreSurface")
158 .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
159 .field("configured_device", &self.configured_device)
160 .finish()
161 }
162}
163
164impl CoreSurface {
165 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Surface>> {
166 unsafe { self.wgpu_surface.clone().as_hal::<A>() }
167 }
168}
169
170#[derive(Clone)]
171pub struct CoreAdapter {
172 pub(crate) wgpu_adapter: Arc<wgc::instance::Adapter>,
173}
174
175impl fmt::Debug for CoreAdapter {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 f.debug_struct("CoreAdapter")
178 .field("wgpu_adapter", &Arc::as_ptr(&self.wgpu_adapter))
179 .finish()
180 }
181}
182
183impl CoreAdapter {
184 pub unsafe fn as_hal<A: hal::Api>(
185 &self,
186 ) -> Option<impl Deref<Target = A::Adapter> + WasmNotSendSync> {
187 unsafe { self.wgpu_adapter.clone().as_hal::<A>() }
188 }
189
190 pub unsafe fn create_device_from_hal<A: hal::Api>(
191 &self,
192 hal_device: hal::OpenDevice<A>,
193 desc: &crate::DeviceDescriptor<'_>,
194 ) -> Result<(CoreDevice, CoreQueue), crate::RequestDeviceError> {
195 let (device, queue) = unsafe {
196 self.wgpu_adapter.create_device_and_queue_from_hal(
197 hal_device.into(),
198 &desc.map_label(|l| l.map(Borrowed)),
199 )
200 }?;
201 let device = CoreDevice {
202 wgpu_device: device.clone(),
203 };
204 let queue = CoreQueue { wgpu_queue: queue };
205 Ok((device, queue))
206 }
207
208 pub(crate) fn from_core(core_adapter: Arc<wgc::instance::Adapter>) -> Self {
209 Self {
210 wgpu_adapter: core_adapter,
211 }
212 }
213
214 pub(crate) fn as_core(&self) -> Arc<wgc::instance::Adapter> {
215 self.wgpu_adapter.clone()
216 }
217}
218
219#[derive(Debug, Clone)]
220pub struct CoreDevice {
221 pub(crate) wgpu_device: Arc<wgc::device::Device>,
222}
223
224impl CoreDevice {
225 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Device>> {
226 unsafe { self.wgpu_device.clone().as_hal::<A>() }
227 }
228
229 pub unsafe fn create_texture_from_hal<A: hal::Api>(
230 &self,
231 hal_texture: A::Texture,
232 desc: &TextureDescriptor<'_>,
233 initial_state: wgt::TextureUses,
234 cleared: bool,
235 ) -> CoreTexture {
236 let descriptor = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
237 let (wgpu_texture, error) = unsafe {
238 self.wgpu_device.create_texture_from_hal(
239 Box::new(hal_texture),
240 &descriptor,
241 initial_state,
242 cleared,
243 )
244 };
245 if let Some(cause) = error {
246 self.wgpu_device
247 .handle_error(cause, desc.label, "Device::create_texture_from_hal");
248 }
249 CoreTexture { wgpu_texture }
250 }
251
252 pub unsafe fn create_buffer_from_hal<A: hal::Api>(
259 &self,
260 hal_buffer: A::Buffer,
261 desc: &BufferDescriptor<'_>,
262 ) -> CoreBuffer {
263 let (wgpu_buffer, error) = unsafe {
264 self.wgpu_device
265 .create_buffer_from_hal(Box::new(hal_buffer), &desc.map_label(|l| l.map(Borrowed)))
266 };
267 if let Some(cause) = error {
268 self.wgpu_device
269 .handle_error(cause, desc.label, "Device::create_buffer_from_hal");
270 }
271 CoreBuffer { wgpu_buffer }
272 }
273
274 #[cfg(webgl)]
276 pub fn texture_belongs_to_device(&self, texture: &CoreTexture) -> bool {
277 use wgc::resource::ParentDevice as _;
278 texture.wgpu_texture.same_device(&self.wgpu_device).is_ok()
279 }
280
281 pub(crate) fn from_core(core_device: Arc<wgc::device::Device>) -> Self {
282 Self {
283 wgpu_device: core_device,
284 }
285 }
286
287 pub(crate) fn as_core(&self) -> Arc<wgc::device::Device> {
288 self.wgpu_device.clone()
289 }
290}
291
292#[derive(Debug, Clone)]
293pub struct CoreBuffer {
294 pub(crate) wgpu_buffer: Arc<wgc::resource::Buffer>,
295}
296
297impl CoreBuffer {
298 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Buffer>> {
299 unsafe { self.wgpu_buffer.clone().as_hal::<A>() }
300 }
301
302 pub(crate) fn from_core(core_buffer: Arc<wgc::resource::Buffer>) -> Self {
303 Self {
304 wgpu_buffer: core_buffer,
305 }
306 }
307
308 pub(crate) fn as_core(&self) -> Arc<wgc::resource::Buffer> {
309 self.wgpu_buffer.clone()
310 }
311}
312
313#[derive(Debug, Clone)]
314pub struct CoreShaderModule {
315 pub(crate) wgpu_shader_module: Arc<wgc::pipeline::ShaderModule>,
316}
317
318impl CoreShaderModule {
319 pub(crate) fn from_core(core_shader_module: Arc<wgc::pipeline::ShaderModule>) -> Self {
320 Self {
321 wgpu_shader_module: core_shader_module,
322 }
323 }
324
325 pub(crate) fn as_core(&self) -> Arc<wgc::pipeline::ShaderModule> {
326 self.wgpu_shader_module.clone()
327 }
328}
329
330#[derive(Debug, Clone)]
331pub struct CoreBindGroupLayout {
332 pub(crate) wgpu_bind_group_layout: Arc<wgc::binding_model::BindGroupLayout>,
333}
334
335impl CoreBindGroupLayout {
336 pub(crate) fn from_core(
337 core_bind_group_layout: Arc<wgc::binding_model::BindGroupLayout>,
338 ) -> Self {
339 Self {
340 wgpu_bind_group_layout: core_bind_group_layout,
341 }
342 }
343
344 pub(crate) fn as_core(&self) -> Arc<wgc::binding_model::BindGroupLayout> {
345 self.wgpu_bind_group_layout.clone()
346 }
347}
348
349#[derive(Debug, Clone)]
350pub struct CoreBindGroup {
351 pub(crate) wgpu_bind_group: Arc<wgc::binding_model::BindGroup>,
352}
353impl CoreBindGroup {
354 pub(crate) fn from_core(core_bind_group: Arc<wgc::binding_model::BindGroup>) -> Self {
355 Self {
356 wgpu_bind_group: core_bind_group,
357 }
358 }
359
360 pub(crate) fn as_core(&self) -> Arc<wgc::binding_model::BindGroup> {
361 self.wgpu_bind_group.clone()
362 }
363}
364
365#[derive(Debug, Clone)]
366pub struct CoreTexture {
367 pub(crate) wgpu_texture: Arc<wgc::resource::Texture>,
368}
369
370impl CoreTexture {
371 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Texture>> {
372 unsafe { self.wgpu_texture.clone().as_hal::<A>() }
373 }
374
375 pub(crate) fn from_core(core_texture: Arc<wgc::resource::Texture>) -> Self {
376 Self {
377 wgpu_texture: core_texture,
378 }
379 }
380
381 pub(crate) fn as_core(&self) -> Arc<wgc::resource::Texture> {
382 self.wgpu_texture.clone()
383 }
384}
385
386#[derive(Debug, Clone)]
387pub struct CoreTextureView {
388 pub(crate) wgpu_texture_view: Arc<wgc::resource::TextureView>,
389}
390
391impl CoreTextureView {
392 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::TextureView>> {
393 unsafe { self.wgpu_texture_view.clone().as_hal::<A>() }
394 }
395
396 pub(crate) fn from_core(core_texture_view: Arc<wgc::resource::TextureView>) -> Self {
397 Self {
398 wgpu_texture_view: core_texture_view,
399 }
400 }
401
402 pub(crate) fn as_core(&self) -> Arc<wgc::resource::TextureView> {
403 self.wgpu_texture_view.clone()
404 }
405}
406
407#[derive(Debug, Clone)]
408pub struct CoreExternalTexture {
409 pub(crate) wgpu_external_texture: Arc<wgc::resource::ExternalTexture>,
410}
411
412impl CoreExternalTexture {
413 pub(crate) fn from_core(core_external_texture: Arc<wgc::resource::ExternalTexture>) -> Self {
414 Self {
415 wgpu_external_texture: core_external_texture,
416 }
417 }
418
419 pub(crate) fn as_core(&self) -> Arc<wgc::resource::ExternalTexture> {
420 self.wgpu_external_texture.clone()
421 }
422}
423
424#[derive(Debug, Clone)]
425pub struct CoreSampler {
426 pub(crate) wgpu_sampler: Arc<wgc::resource::Sampler>,
427}
428
429impl CoreSampler {
430 pub(crate) fn from_core(core_sampler: Arc<wgc::resource::Sampler>) -> Self {
431 Self {
432 wgpu_sampler: core_sampler,
433 }
434 }
435
436 pub(crate) fn as_core(&self) -> Arc<wgc::resource::Sampler> {
437 self.wgpu_sampler.clone()
438 }
439}
440
441#[derive(Debug, Clone)]
442pub struct CoreQuerySet {
443 pub(crate) wgpu_query_set: Arc<wgc::resource::QuerySet>,
444}
445
446impl CoreQuerySet {
447 pub(crate) fn from_core(core_query_set: Arc<wgc::resource::QuerySet>) -> Self {
448 Self {
449 wgpu_query_set: core_query_set,
450 }
451 }
452
453 pub(crate) fn as_core(&self) -> Arc<wgc::resource::QuerySet> {
454 self.wgpu_query_set.clone()
455 }
456}
457
458#[derive(Debug, Clone)]
459pub struct CorePipelineLayout {
460 pub(crate) wgpu_pipeline_layout: Arc<wgc::binding_model::PipelineLayout>,
461}
462
463impl CorePipelineLayout {
464 pub(crate) fn from_core(core_pipeline_layout: Arc<wgc::binding_model::PipelineLayout>) -> Self {
465 Self {
466 wgpu_pipeline_layout: core_pipeline_layout,
467 }
468 }
469
470 pub(crate) fn as_core(&self) -> Arc<wgc::binding_model::PipelineLayout> {
471 self.wgpu_pipeline_layout.clone()
472 }
473}
474
475#[derive(Debug, Clone)]
476pub struct CorePipelineCache {
477 pub(crate) wgpu_pipeline_cache: Arc<wgc::pipeline::PipelineCache>,
478}
479
480pub struct CoreCommandBuffer {
481 pub(crate) wgpu_command_buffer: Arc<wgc::command::CommandBuffer>,
482}
483impl CoreCommandBuffer {
484 pub(crate) fn from_core(core_buffer: Arc<wgc::command::CommandBuffer>) -> Self {
485 Self {
486 wgpu_command_buffer: core_buffer,
487 }
488 }
489
490 pub(crate) fn as_core(&self) -> Arc<wgc::command::CommandBuffer> {
491 self.wgpu_command_buffer.clone()
492 }
493}
494
495impl fmt::Debug for CoreCommandBuffer {
496 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
497 f.debug_struct("CoreCommandBuffer")
498 .field(
499 "wgpu_command_buffer",
500 &Arc::as_ptr(&self.wgpu_command_buffer),
501 )
502 .finish()
503 }
504}
505
506#[derive(Debug)]
507pub struct CoreRenderBundleEncoder {
508 encoder: Box<wgc::command::RenderBundleEncoder>,
509}
510
511#[derive(Debug, Clone)]
512pub struct CoreRenderBundle {
513 pub(crate) wgpu_render_bundle: Arc<wgc::command::RenderBundle>,
514}
515
516#[derive(Clone)]
517pub struct CoreQueue {
518 pub(crate) wgpu_queue: Arc<wgc::device::queue::Queue>,
519}
520
521impl fmt::Debug for CoreQueue {
522 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523 f.debug_struct("CoreQueue")
524 .field("wgpu_queue", &Arc::as_ptr(&self.wgpu_queue))
525 .finish()
526 }
527}
528
529impl CoreQueue {
530 pub unsafe fn as_hal<A: hal::Api>(
531 &self,
532 ) -> Option<impl Deref<Target = A::Queue> + WasmNotSendSync> {
533 unsafe { self.wgpu_queue.clone().as_hal::<A>() }
534 }
535
536 pub(crate) fn from_core(core_queue: Arc<wgc::device::queue::Queue>) -> Self {
537 Self {
538 wgpu_queue: core_queue,
539 }
540 }
541
542 pub(crate) fn as_core(&self) -> Arc<wgc::device::queue::Queue> {
543 self.wgpu_queue.clone()
544 }
545}
546
547#[derive(Debug, Clone)]
548pub struct CoreComputePipeline {
549 pub(crate) wgpu_compute_pipeline: Arc<wgc::pipeline::ComputePipeline>,
550}
551
552impl CoreComputePipeline {
553 pub(crate) fn from_core(core_compute_pipeline: Arc<wgc::pipeline::ComputePipeline>) -> Self {
554 Self {
555 wgpu_compute_pipeline: core_compute_pipeline,
556 }
557 }
558
559 pub(crate) fn as_core(&self) -> Arc<wgc::pipeline::ComputePipeline> {
560 self.wgpu_compute_pipeline.clone()
561 }
562}
563
564#[derive(Debug, Clone)]
565pub struct CoreRenderPipeline {
566 pub(crate) wgpu_render_pipeline: Arc<wgc::pipeline::RenderPipeline>,
567}
568
569impl CoreRenderPipeline {
570 pub(crate) fn from_core(core_render_pipeline: Arc<wgc::pipeline::RenderPipeline>) -> Self {
571 Self {
572 wgpu_render_pipeline: core_render_pipeline,
573 }
574 }
575
576 pub(crate) fn as_core(&self) -> Arc<wgc::pipeline::RenderPipeline> {
577 self.wgpu_render_pipeline.clone()
578 }
579}
580
581#[derive(Debug)]
582pub struct CoreComputePass {
583 pass: wgc::command::ComputePass,
584
585 id: crate::cmp::Identifier,
586}
587
588#[derive(Debug)]
589pub struct CoreRenderPass {
590 pass: wgc::command::RenderPass,
591
592 id: crate::cmp::Identifier,
593}
594
595pub struct CoreCommandEncoder {
596 pub(crate) wgpu_command_encoder: Arc<wgc::command::CommandEncoder>,
597}
598
599impl fmt::Debug for CoreCommandEncoder {
600 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
601 f.debug_struct("CoreCommandEncoder")
602 .field(
603 "wgpu_command_encoder",
604 &Arc::as_ptr(&self.wgpu_command_encoder),
605 )
606 .finish()
607 }
608}
609
610impl CoreCommandEncoder {
611 pub unsafe fn as_hal_mut<A: hal::Api, F: FnOnce(Option<&mut A::CommandEncoder>) -> R, R>(
613 &self,
614 hal_command_encoder_callback: F,
615 ) -> R {
616 unsafe {
617 self.wgpu_command_encoder
618 .as_hal_mut::<A, F, R>(hal_command_encoder_callback)
619 }
620 }
621
622 pub(crate) fn from_core(core_encoder: Arc<wgc::command::CommandEncoder>) -> Self {
623 Self {
624 wgpu_command_encoder: core_encoder,
625 }
626 }
627
628 pub(crate) fn as_core(&self) -> Arc<wgc::command::CommandEncoder> {
629 self.wgpu_command_encoder.clone()
630 }
631}
632
633#[derive(Debug, Clone)]
634pub struct CoreBlas {
635 pub(crate) wgpu_blas: Arc<wgc::resource::Blas>,
636}
637
638impl CoreBlas {
639 pub unsafe fn as_hal<A: hal::Api>(
640 &self,
641 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
642 unsafe { self.wgpu_blas.clone().as_hal::<A>() }
643 }
644}
645
646#[derive(Debug, Clone)]
647pub struct CoreTlas {
648 pub(crate) wgpu_tlas: Arc<wgc::resource::Tlas>,
649}
650
651impl CoreTlas {
652 pub unsafe fn as_hal<A: hal::Api>(
653 &self,
654 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
655 unsafe { self.wgpu_tlas.clone().as_hal::<A>() }
656 }
657}
658
659#[derive(Clone)]
660pub struct CoreSurfaceOutputDetail {
661 wgpu_surface: Arc<wgc::instance::Surface>,
662 error_sink: ErrorSink,
663}
664
665impl fmt::Debug for CoreSurfaceOutputDetail {
666 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
667 f.debug_struct("CoreSurfaceOutputDetail")
668 .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
669 .finish()
670 }
671}
672
673#[derive(Debug)]
674pub struct CoreQueueWriteBuffer {
675 wgpu_staging_buffer: wgc::resource::StagingBuffer,
676}
677
678#[derive(Debug)]
679pub struct CoreBufferMappedRange(BufferMapping);
680
681#[cfg(send_sync)]
682unsafe impl Send for CoreBufferMappedRange {}
683#[cfg(send_sync)]
684unsafe impl Sync for CoreBufferMappedRange {}
685
686impl Drop for CoreBufferMappedRange {
687 fn drop(&mut self) {
688 }
691}
692
693crate::cmp::impl_eq_ord_hash_arc_address!(ContextWgpuCore => .0);
694crate::cmp::impl_eq_ord_hash_arc_address!(CoreAdapter => .wgpu_adapter);
695crate::cmp::impl_eq_ord_hash_arc_address!(CoreDevice => .wgpu_device);
696crate::cmp::impl_eq_ord_hash_arc_address!(CoreQueue => .wgpu_queue);
697crate::cmp::impl_eq_ord_hash_arc_address!(CoreShaderModule => .wgpu_shader_module);
698crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroupLayout => .wgpu_bind_group_layout);
699crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroup => .wgpu_bind_group);
700crate::cmp::impl_eq_ord_hash_arc_address!(CoreTextureView => .wgpu_texture_view);
701crate::cmp::impl_eq_ord_hash_arc_address!(CoreSampler => .wgpu_sampler);
702crate::cmp::impl_eq_ord_hash_arc_address!(CoreBuffer => .wgpu_buffer);
703crate::cmp::impl_eq_ord_hash_arc_address!(CoreTexture => .wgpu_texture);
704crate::cmp::impl_eq_ord_hash_arc_address!(CoreExternalTexture => .wgpu_external_texture);
705crate::cmp::impl_eq_ord_hash_arc_address!(CoreBlas => .wgpu_blas);
706crate::cmp::impl_eq_ord_hash_arc_address!(CoreTlas => .wgpu_tlas);
707crate::cmp::impl_eq_ord_hash_arc_address!(CoreQuerySet => .wgpu_query_set);
708crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineLayout => .wgpu_pipeline_layout);
709crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderPipeline => .wgpu_render_pipeline);
710crate::cmp::impl_eq_ord_hash_arc_address!(CoreComputePipeline => .wgpu_compute_pipeline);
711crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineCache => .wgpu_pipeline_cache);
712crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandEncoder => .wgpu_command_encoder);
713crate::cmp::impl_eq_ord_hash_proxy!(CoreComputePass => .id);
714crate::cmp::impl_eq_ord_hash_proxy!(CoreRenderPass => .id);
715crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandBuffer => .wgpu_command_buffer);
716crate::cmp::impl_eq_ord_hash_box_address!(CoreRenderBundleEncoder => .encoder);
717crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderBundle => .wgpu_render_bundle);
718crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurface => .wgpu_surface);
719crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurfaceOutputDetail => .wgpu_surface);
720impl PartialEq for CoreQueueWriteBuffer {
721 fn eq(&self, other: &Self) -> bool {
722 unsafe { self.wgpu_staging_buffer.ptr() == other.wgpu_staging_buffer.ptr() }
723 }
724}
725impl Eq for CoreQueueWriteBuffer {}
726impl PartialOrd for CoreQueueWriteBuffer {
727 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
728 Some(self.cmp(other))
729 }
730}
731impl Ord for CoreQueueWriteBuffer {
732 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
733 unsafe {
734 self.wgpu_staging_buffer
735 .ptr()
736 .cmp(&other.wgpu_staging_buffer.ptr())
737 }
738 }
739}
740impl core::hash::Hash for CoreQueueWriteBuffer {
741 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
742 unsafe { self.wgpu_staging_buffer.ptr().hash(state) }
743 }
744}
745crate::cmp::impl_eq_ord_hash_proxy!(CoreBufferMappedRange => .0.ptr());
746
747impl dispatch::InstanceInterface for ContextWgpuCore {
748 fn new(desc: wgt::InstanceDescriptor) -> Self
749 where
750 Self: Sized,
751 {
752 Self(wgc::instance::Instance::new("wgpu", desc, None))
753 }
754
755 unsafe fn create_surface(
756 &self,
757 target: crate::api::SurfaceTargetUnsafe,
758 ) -> Result<dispatch::DispatchSurface, crate::CreateSurfaceError> {
759 let wgpu_surface = match target {
760 SurfaceTargetUnsafe::RawHandle {
761 raw_display_handle,
762 raw_window_handle,
763 } => unsafe { self.0.create_surface(raw_display_handle, raw_window_handle) },
764
765 #[cfg(all(drm, not(target_os = "netbsd")))]
766 SurfaceTargetUnsafe::Drm {
767 fd,
768 plane,
769 connector_id,
770 width,
771 height,
772 refresh_rate,
773 } => unsafe {
774 self.0
775 .create_surface_from_drm(fd, plane, connector_id, width, height, refresh_rate)
776 },
777
778 #[cfg(metal)]
779 SurfaceTargetUnsafe::CoreAnimationLayer(layer) => unsafe {
780 self.0.create_surface_metal(layer)
781 },
782
783 #[cfg(all(drm, target_os = "netbsd"))]
784 SurfaceTargetUnsafe::Drm { .. } => Err(
785 wgc::instance::CreateSurfaceError::BackendNotEnabled(wgt::Backend::Vulkan),
786 ),
787
788 #[cfg(dx12)]
789 SurfaceTargetUnsafe::CompositionVisual(visual) => unsafe {
790 self.0.create_surface_from_visual(visual)
791 },
792
793 #[cfg(dx12)]
794 SurfaceTargetUnsafe::SurfaceHandle(surface_handle) => unsafe {
795 self.0.create_surface_from_surface_handle(surface_handle)
796 },
797
798 #[cfg(dx12)]
799 SurfaceTargetUnsafe::SwapChainPanel(swap_chain_panel) => unsafe {
800 self.0
801 .create_surface_from_swap_chain_panel(swap_chain_panel)
802 },
803 }?;
804
805 Ok(CoreSurface {
806 wgpu_surface,
807 configured_device: Arc::new(Mutex::default()),
808 }
809 .into())
810 }
811
812 fn request_adapter(
813 &self,
814 options: &crate::api::RequestAdapterOptions<'_, '_>,
815 ) -> Pin<Box<dyn dispatch::RequestAdapterFuture>> {
816 let adapter = self.0.request_adapter(
817 &wgt::RequestAdapterOptions {
818 power_preference: options.power_preference,
819 force_fallback_adapter: options.force_fallback_adapter,
820 compatible_surface: options
821 .compatible_surface
822 .map(|surface| &*surface.inner.as_core().wgpu_surface),
823 apply_limit_buckets: false,
824 },
825 wgt::Backends::all(),
826 );
827 let adapter = adapter.map(|wgpu_adapter| {
828 let core = CoreAdapter { wgpu_adapter };
829 let generic: dispatch::DispatchAdapter = core.into();
830 generic
831 });
832 Box::pin(ready(adapter))
833 }
834
835 fn poll_all_devices(&self, force_wait: bool) -> bool {
836 match self.0.poll_all_devices(force_wait) {
837 Ok(all_queue_empty) => all_queue_empty,
838 Err(err) => handle_error_fatal(err, "Instance::poll_all_devices"),
839 }
840 }
841
842 #[cfg(feature = "wgsl")]
843 fn wgsl_language_features(&self) -> crate::WgslLanguageFeatures {
844 use wgc::naga::front::wgsl::ImplementedLanguageExtension;
845 ImplementedLanguageExtension::all().iter().copied().fold(
846 crate::WgslLanguageFeatures::empty(),
847 |acc, wle| {
848 acc | match wle {
849 ImplementedLanguageExtension::ReadOnlyAndReadWriteStorageTextures => {
850 crate::WgslLanguageFeatures::ReadOnlyAndReadWriteStorageTextures
851 }
852 ImplementedLanguageExtension::Packed4x8IntegerDotProduct => {
853 crate::WgslLanguageFeatures::Packed4x8IntegerDotProduct
854 }
855 ImplementedLanguageExtension::PointerCompositeAccess => {
856 crate::WgslLanguageFeatures::PointerCompositeAccess
857 }
858 ImplementedLanguageExtension::ImmediateAddressSpace => {
859 crate::WgslLanguageFeatures::ImmediateAddressSpace
860 }
861 }
862 },
863 )
864 }
865
866 fn enumerate_adapters(
867 &self,
868 backends: crate::Backends,
869 ) -> Pin<Box<dyn dispatch::EnumerateAdapterFuture>> {
870 let adapters: Vec<DispatchAdapter> = self
871 .enumerate_adapters(backends)
872 .into_iter()
873 .map(|adapter| {
874 let core = crate::backend::wgpu_core::CoreAdapter {
875 wgpu_adapter: adapter,
876 };
877 core.into()
878 })
879 .collect();
880 Box::pin(ready(adapters))
881 }
882}
883
884impl dispatch::AdapterInterface for CoreAdapter {
885 fn request_device(
886 &self,
887 desc: &crate::DeviceDescriptor<'_>,
888 ) -> Pin<Box<dyn dispatch::RequestDeviceFuture>> {
889 let res = self
890 .wgpu_adapter
891 .request_device(&desc.map_label(|l| l.map(Borrowed)));
892 let (device, queue) = match res {
893 Ok(ids) => ids,
894 Err(err) => {
895 return Box::pin(ready(Err(err.into())));
896 }
897 };
898 let device = CoreDevice {
899 wgpu_device: device,
900 };
901 let queue = CoreQueue { wgpu_queue: queue };
902 Box::pin(ready(Ok((device.into(), queue.into()))))
903 }
904
905 fn is_surface_supported(&self, surface: &dispatch::DispatchSurface) -> bool {
906 let surface = surface.as_core();
907
908 self.wgpu_adapter
909 .is_surface_supported(&surface.wgpu_surface)
910 }
911
912 fn features(&self) -> crate::Features {
913 self.wgpu_adapter.features()
914 }
915
916 fn limits(&self) -> crate::Limits {
917 self.wgpu_adapter.limits()
918 }
919
920 fn downlevel_capabilities(&self) -> crate::DownlevelCapabilities {
921 self.wgpu_adapter.downlevel_capabilities()
922 }
923
924 fn get_info(&self) -> crate::AdapterInfo {
925 self.wgpu_adapter.get_info()
926 }
927
928 fn get_texture_format_features(
929 &self,
930 format: crate::TextureFormat,
931 ) -> crate::TextureFormatFeatures {
932 self.wgpu_adapter.get_texture_format_features(format)
933 }
934
935 fn get_presentation_timestamp(&self) -> crate::PresentationTimestamp {
936 self.wgpu_adapter.get_presentation_timestamp()
937 }
938
939 fn cooperative_matrix_properties(&self) -> Vec<crate::wgt::CooperativeMatrixProperties> {
940 self.wgpu_adapter.cooperative_matrix_properties()
941 }
942}
943
944impl Drop for CoreAdapter {
945 fn drop(&mut self) {}
946}
947
948impl dispatch::DeviceInterface for CoreDevice {
949 fn features(&self) -> crate::Features {
950 *self.wgpu_device.features()
951 }
952
953 fn limits(&self) -> crate::Limits {
954 self.wgpu_device.limits().clone()
955 }
956
957 fn adapter_info(&self) -> crate::AdapterInfo {
958 self.wgpu_device.adapter_info()
959 }
960
961 #[cfg_attr(
963 not(any(
964 feature = "spirv",
965 feature = "glsl",
966 feature = "wgsl",
967 feature = "naga-ir"
968 )),
969 expect(unused)
970 )]
971 fn create_shader_module(
972 &self,
973 desc: crate::ShaderModuleDescriptor<'_>,
974 shader_bound_checks: wgt::ShaderRuntimeChecks,
975 ) -> dispatch::DispatchShaderModule {
976 let descriptor = wgc::pipeline::ShaderModuleDescriptor {
977 label: desc.label.map(Borrowed),
978 runtime_checks: shader_bound_checks,
979 };
980 let source = match desc.source {
981 #[cfg(feature = "spirv")]
982 ShaderSource::SpirV(ref spv) => {
983 let options = naga::front::spv::Options {
985 adjust_coordinate_space: false, strict_capabilities: true,
987 block_ctx_dump_prefix: None,
988 };
989 wgc::pipeline::ShaderModuleSource::SpirV(Borrowed(spv), options)
990 }
991 #[cfg(feature = "glsl")]
992 ShaderSource::Glsl {
993 ref shader,
994 stage,
995 defines,
996 } => {
997 let options = naga::front::glsl::Options {
998 stage,
999 defines: defines
1000 .iter()
1001 .map(|&(key, value)| (String::from(key), String::from(value)))
1002 .collect(),
1003 };
1004 wgc::pipeline::ShaderModuleSource::Glsl(Borrowed(shader), options)
1005 }
1006 #[cfg(feature = "wgsl")]
1007 ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)),
1008 #[cfg(feature = "naga-ir")]
1009 ShaderSource::Naga(module) => wgc::pipeline::ShaderModuleSource::Naga(module),
1010 ShaderSource::Dummy(_) => panic!("found `ShaderSource::Dummy`"),
1011 };
1012 let wgpu_shader_module = self.wgpu_device.create_shader_module(&descriptor, source);
1013
1014 CoreShaderModule { wgpu_shader_module }.into()
1015 }
1016
1017 unsafe fn create_shader_module_passthrough(
1018 &self,
1019 desc: &crate::ShaderModuleDescriptorPassthrough<'_>,
1020 ) -> dispatch::DispatchShaderModule {
1021 let desc = desc.map_label(|l| l.map(Cow::from));
1022 let wgpu_shader_module =
1023 unsafe { self.wgpu_device.create_shader_module_passthrough(&desc) };
1024
1025 CoreShaderModule { wgpu_shader_module }.into()
1026 }
1027
1028 fn create_bind_group_layout(
1029 &self,
1030 desc: &crate::BindGroupLayoutDescriptor<'_>,
1031 ) -> dispatch::DispatchBindGroupLayout {
1032 let descriptor = wgc::binding_model::BindGroupLayoutDescriptor {
1033 label: desc.label.map(Borrowed),
1034 entries: Borrowed(desc.entries),
1035 };
1036 let wgpu_bind_group_layout = self.wgpu_device.create_bind_group_layout(&descriptor);
1037 CoreBindGroupLayout {
1038 wgpu_bind_group_layout,
1039 }
1040 .into()
1041 }
1042
1043 fn create_bind_group(
1044 &self,
1045 desc: &crate::BindGroupDescriptor<'_>,
1046 ) -> dispatch::DispatchBindGroup {
1047 use wgc::binding_model as bm;
1048
1049 let mut arrayed_texture_views = Vec::new();
1050 let mut arrayed_samplers = Vec::new();
1051 if self
1052 .wgpu_device
1053 .features()
1054 .contains(Features::TEXTURE_BINDING_ARRAY)
1055 {
1056 for entry in desc.entries.iter() {
1058 if let BindingResource::TextureViewArray(array) = entry.resource {
1059 arrayed_texture_views.extend(
1060 array
1061 .iter()
1062 .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
1063 );
1064 }
1065 if let BindingResource::SamplerArray(array) = entry.resource {
1066 arrayed_samplers.extend(
1067 array
1068 .iter()
1069 .map(|sampler| sampler.inner.as_core().wgpu_sampler.clone()),
1070 );
1071 }
1072 }
1073 }
1074 let mut remaining_arrayed_texture_views = &arrayed_texture_views[..];
1075 let mut remaining_arrayed_samplers = &arrayed_samplers[..];
1076
1077 let mut arrayed_buffer_bindings = Vec::new();
1078 if self
1079 .wgpu_device
1080 .features()
1081 .contains(Features::BUFFER_BINDING_ARRAY)
1082 {
1083 for entry in desc.entries.iter() {
1085 if let BindingResource::BufferArray(array) = entry.resource {
1086 arrayed_buffer_bindings.extend(array.iter().map(|binding| bm::BufferBinding {
1087 buffer: binding.buffer.inner.as_core().wgpu_buffer.clone(),
1088 offset: binding.offset,
1089 size: binding.size.map(wgt::BufferSize::get),
1090 }));
1091 }
1092 }
1093 }
1094 let mut remaining_arrayed_buffer_bindings = &arrayed_buffer_bindings[..];
1095
1096 let mut arrayed_acceleration_structures = Vec::new();
1097 if self
1098 .wgpu_device
1099 .features()
1100 .contains(Features::ACCELERATION_STRUCTURE_BINDING_ARRAY)
1101 {
1102 for entry in desc.entries.iter() {
1104 if let BindingResource::AccelerationStructureArray(array) = entry.resource {
1105 arrayed_acceleration_structures.extend(
1106 array
1107 .iter()
1108 .map(|tlas| tlas.inner.as_core().wgpu_tlas.clone()),
1109 );
1110 }
1111 }
1112 }
1113 let mut remaining_arrayed_acceleration_structures = &arrayed_acceleration_structures[..];
1114
1115 let entries = desc
1116 .entries
1117 .iter()
1118 .map(|entry| bm::BindGroupEntry {
1119 binding: entry.binding,
1120 resource: match entry.resource {
1121 BindingResource::Buffer(BufferBinding {
1122 buffer,
1123 offset,
1124 size,
1125 }) => bm::BindingResource::Buffer(bm::BufferBinding {
1126 buffer: buffer.inner.as_core().wgpu_buffer.clone(),
1127 offset,
1128 size: size.map(wgt::BufferSize::get),
1129 }),
1130 BindingResource::BufferArray(array) => {
1131 let slice = &remaining_arrayed_buffer_bindings[..array.len()];
1132 remaining_arrayed_buffer_bindings =
1133 &remaining_arrayed_buffer_bindings[array.len()..];
1134 bm::BindingResource::BufferArray(Borrowed(slice))
1135 }
1136 BindingResource::Sampler(sampler) => {
1137 bm::BindingResource::Sampler(sampler.inner.as_core().wgpu_sampler.clone())
1138 }
1139 BindingResource::SamplerArray(array) => {
1140 let slice = &remaining_arrayed_samplers[..array.len()];
1141 remaining_arrayed_samplers = &remaining_arrayed_samplers[array.len()..];
1142 bm::BindingResource::SamplerArray(Borrowed(slice))
1143 }
1144 BindingResource::TextureView(texture_view) => bm::BindingResource::TextureView(
1145 texture_view.inner.as_core().wgpu_texture_view.clone(),
1146 ),
1147 BindingResource::TextureViewArray(array) => {
1148 let slice = &remaining_arrayed_texture_views[..array.len()];
1149 remaining_arrayed_texture_views =
1150 &remaining_arrayed_texture_views[array.len()..];
1151 bm::BindingResource::TextureViewArray(Borrowed(slice))
1152 }
1153 BindingResource::AccelerationStructure(acceleration_structure) => {
1154 bm::BindingResource::AccelerationStructure(
1155 acceleration_structure.inner.as_core().wgpu_tlas.clone(),
1156 )
1157 }
1158 BindingResource::AccelerationStructureArray(array) => {
1159 let slice = &remaining_arrayed_acceleration_structures[..array.len()];
1160 remaining_arrayed_acceleration_structures =
1161 &remaining_arrayed_acceleration_structures[array.len()..];
1162 bm::BindingResource::AccelerationStructureArray(Borrowed(slice))
1163 }
1164 BindingResource::ExternalTexture(external_texture) => {
1165 bm::BindingResource::ExternalTexture(
1166 external_texture
1167 .inner
1168 .as_core()
1169 .wgpu_external_texture
1170 .clone(),
1171 )
1172 }
1173 },
1174 })
1175 .collect::<Vec<_>>();
1176 let descriptor = bm::BindGroupDescriptor {
1177 label: desc.label.as_ref().map(|label| Borrowed(&label[..])),
1178 layout: desc.layout.inner.as_core().wgpu_bind_group_layout.clone(),
1179 entries: Borrowed(&entries),
1180 };
1181
1182 let wgpu_bind_group = self.wgpu_device.create_bind_group(&descriptor);
1183 CoreBindGroup { wgpu_bind_group }.into()
1184 }
1185
1186 fn create_pipeline_layout(
1187 &self,
1188 desc: &crate::PipelineLayoutDescriptor<'_>,
1189 ) -> dispatch::DispatchPipelineLayout {
1190 assert!(
1193 desc.bind_group_layouts.len() <= wgc::MAX_BIND_GROUPS,
1194 "Bind group layout count {} exceeds device bind group limit {}",
1195 desc.bind_group_layouts.len(),
1196 wgc::MAX_BIND_GROUPS
1197 );
1198
1199 let temp_layouts = desc
1200 .bind_group_layouts
1201 .iter()
1202 .map(|bgl| bgl.map(|bgl| bgl.inner.as_core().wgpu_bind_group_layout.clone()))
1203 .collect::<ArrayVec<_, { wgc::MAX_BIND_GROUPS }>>();
1204 let descriptor = wgc::binding_model::PipelineLayoutDescriptor {
1205 label: desc.label.map(Borrowed),
1206 bind_group_layouts: Borrowed(&temp_layouts),
1207 immediate_size: desc.immediate_size,
1208 };
1209
1210 let wgpu_pipeline_layout = self.wgpu_device.create_pipeline_layout(&descriptor);
1211
1212 CorePipelineLayout {
1213 wgpu_pipeline_layout,
1214 }
1215 .into()
1216 }
1217
1218 fn create_render_pipeline(
1219 &self,
1220 desc: &crate::RenderPipelineDescriptor<'_>,
1221 ) -> dispatch::DispatchRenderPipeline {
1222 use wgc::pipeline as pipe;
1223
1224 let vertex_buffers: ArrayVec<_, { wgc::MAX_VERTEX_BUFFERS }> = desc
1225 .vertex
1226 .buffers
1227 .iter()
1228 .map(|vbuf| {
1229 vbuf.as_ref().map(|vbuf| pipe::VertexBufferLayout {
1230 array_stride: vbuf.array_stride,
1231 step_mode: vbuf.step_mode,
1232 attributes: Borrowed(vbuf.attributes),
1233 })
1234 })
1235 .collect();
1236
1237 let vert_constants = desc
1238 .vertex
1239 .compilation_options
1240 .constants
1241 .iter()
1242 .map(|&(key, value)| (String::from(key), value))
1243 .collect();
1244
1245 let descriptor = pipe::ResolvedGeneralRenderPipelineDescriptor {
1246 label: desc.label.map(Borrowed),
1247 layout: desc
1248 .layout
1249 .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1250 vertex: wgc::pipeline::RenderPipelineVertexProcessor::Vertex(pipe::VertexState {
1251 stage: pipe::ProgrammableStageDescriptor {
1252 module: desc
1253 .vertex
1254 .module
1255 .inner
1256 .as_core()
1257 .wgpu_shader_module
1258 .clone(),
1259 entry_point: desc.vertex.entry_point.map(Borrowed),
1260 constants: vert_constants,
1261 zero_initialize_workgroup_memory: desc
1262 .vertex
1263 .compilation_options
1264 .zero_initialize_workgroup_memory,
1265 },
1266 buffers: Borrowed(&vertex_buffers),
1267 }),
1268 primitive: desc.primitive,
1269 depth_stencil: desc.depth_stencil.clone(),
1270 multisample: desc.multisample,
1271 fragment: desc.fragment.as_ref().map(|frag| {
1272 let frag_constants = frag
1273 .compilation_options
1274 .constants
1275 .iter()
1276 .map(|&(key, value)| (String::from(key), value))
1277 .collect();
1278 pipe::FragmentState {
1279 stage: pipe::ProgrammableStageDescriptor {
1280 module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1281 entry_point: frag.entry_point.map(Borrowed),
1282 constants: frag_constants,
1283 zero_initialize_workgroup_memory: frag
1284 .compilation_options
1285 .zero_initialize_workgroup_memory,
1286 },
1287 targets: Borrowed(frag.targets),
1288 }
1289 }),
1290 multiview_mask: desc.multiview_mask,
1291 cache: desc
1292 .cache
1293 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1294 };
1295
1296 let wgpu_render_pipeline = self.wgpu_device.create_render_pipeline(descriptor);
1297 CoreRenderPipeline {
1298 wgpu_render_pipeline,
1299 }
1300 .into()
1301 }
1302
1303 fn create_mesh_pipeline(
1304 &self,
1305 desc: &crate::MeshPipelineDescriptor<'_>,
1306 ) -> dispatch::DispatchRenderPipeline {
1307 use wgc::pipeline as pipe;
1308
1309 let mesh_constants = desc
1310 .mesh
1311 .compilation_options
1312 .constants
1313 .iter()
1314 .map(|&(key, value)| (String::from(key), value))
1315 .collect();
1316 let descriptor = pipe::MeshPipelineDescriptor {
1317 label: desc.label.map(Borrowed),
1318 task: desc.task.as_ref().map(|task| {
1319 let task_constants = task
1320 .compilation_options
1321 .constants
1322 .iter()
1323 .map(|&(key, value)| (String::from(key), value))
1324 .collect();
1325 pipe::TaskState {
1326 stage: pipe::ProgrammableStageDescriptor {
1327 module: task.module.inner.as_core().wgpu_shader_module.clone(),
1328 entry_point: task.entry_point.map(Borrowed),
1329 constants: task_constants,
1330 zero_initialize_workgroup_memory: desc
1331 .mesh
1332 .compilation_options
1333 .zero_initialize_workgroup_memory,
1334 },
1335 }
1336 }),
1337 mesh: pipe::MeshState {
1338 stage: pipe::ProgrammableStageDescriptor {
1339 module: desc.mesh.module.inner.as_core().wgpu_shader_module.clone(),
1340 entry_point: desc.mesh.entry_point.map(Borrowed),
1341 constants: mesh_constants,
1342 zero_initialize_workgroup_memory: desc
1343 .mesh
1344 .compilation_options
1345 .zero_initialize_workgroup_memory,
1346 },
1347 },
1348 layout: desc
1349 .layout
1350 .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1351 primitive: desc.primitive,
1352 depth_stencil: desc.depth_stencil.clone(),
1353 multisample: desc.multisample,
1354 fragment: desc.fragment.as_ref().map(|frag| {
1355 let frag_constants = frag
1356 .compilation_options
1357 .constants
1358 .iter()
1359 .map(|&(key, value)| (String::from(key), value))
1360 .collect();
1361 pipe::FragmentState {
1362 stage: pipe::ProgrammableStageDescriptor {
1363 module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1364 entry_point: frag.entry_point.map(Borrowed),
1365 constants: frag_constants,
1366 zero_initialize_workgroup_memory: frag
1367 .compilation_options
1368 .zero_initialize_workgroup_memory,
1369 },
1370 targets: Borrowed(frag.targets),
1371 }
1372 }),
1373 multiview: desc.multiview,
1374 cache: desc
1375 .cache
1376 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1377 };
1378
1379 let wgpu_render_pipeline = self.wgpu_device.create_render_pipeline(descriptor.into());
1380 CoreRenderPipeline {
1381 wgpu_render_pipeline,
1382 }
1383 .into()
1384 }
1385
1386 fn create_compute_pipeline(
1387 &self,
1388 desc: &crate::ComputePipelineDescriptor<'_>,
1389 ) -> dispatch::DispatchComputePipeline {
1390 use wgc::pipeline as pipe;
1391
1392 let constants = desc
1393 .compilation_options
1394 .constants
1395 .iter()
1396 .map(|&(key, value)| (String::from(key), value))
1397 .collect();
1398
1399 let descriptor = pipe::ComputePipelineDescriptor {
1400 label: desc.label.map(Borrowed),
1401 layout: desc
1402 .layout
1403 .map(|pll| pll.inner.as_core().wgpu_pipeline_layout.clone()),
1404 stage: pipe::ProgrammableStageDescriptor {
1405 module: desc.module.inner.as_core().wgpu_shader_module.clone(),
1406 entry_point: desc.entry_point.map(Borrowed),
1407 constants,
1408 zero_initialize_workgroup_memory: desc
1409 .compilation_options
1410 .zero_initialize_workgroup_memory,
1411 },
1412 cache: desc
1413 .cache
1414 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1415 };
1416
1417 let wgpu_compute_pipeline = self.wgpu_device.create_compute_pipeline(descriptor);
1418 CoreComputePipeline {
1419 wgpu_compute_pipeline,
1420 }
1421 .into()
1422 }
1423
1424 unsafe fn create_pipeline_cache(
1425 &self,
1426 desc: &crate::PipelineCacheDescriptor<'_>,
1427 ) -> dispatch::DispatchPipelineCache {
1428 use wgc::pipeline as pipe;
1429
1430 let descriptor = pipe::PipelineCacheDescriptor {
1431 label: desc.label.map(Borrowed),
1432 data: desc.data.map(Borrowed),
1433 fallback: desc.fallback,
1434 };
1435 let (wgpu_pipeline_cache, error) =
1436 unsafe { self.wgpu_device.create_pipeline_cache(&descriptor) };
1437 if let Some(cause) = error {
1438 self.wgpu_device.handle_error(
1439 cause,
1440 desc.label,
1441 "Device::device_create_pipeline_cache_init",
1442 );
1443 }
1444 CorePipelineCache {
1445 wgpu_pipeline_cache,
1446 }
1447 .into()
1448 }
1449
1450 fn create_buffer(&self, desc: &crate::BufferDescriptor<'_>) -> dispatch::DispatchBuffer {
1451 let wgpu_buffer = self
1452 .wgpu_device
1453 .create_buffer(&desc.map_label(|l| l.map(Borrowed)));
1454
1455 CoreBuffer { wgpu_buffer }.into()
1456 }
1457
1458 fn create_texture(&self, desc: &crate::TextureDescriptor<'_>) -> dispatch::DispatchTexture {
1459 let wgt_desc = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
1460 let wgpu_texture = self.wgpu_device.create_texture(&wgt_desc);
1461
1462 CoreTexture { wgpu_texture }.into()
1463 }
1464
1465 fn create_external_texture(
1466 &self,
1467 desc: &crate::ExternalTextureDescriptor<'_>,
1468 planes: &[&crate::TextureView],
1469 ) -> dispatch::DispatchExternalTexture {
1470 let wgt_desc = desc.map_label(|l| l.map(Borrowed));
1471 let planes = planes
1472 .iter()
1473 .map(|plane| plane.inner.as_core().wgpu_texture_view.clone())
1474 .collect::<Vec<_>>();
1475 let wgpu_external_texture = self.wgpu_device.create_external_texture(&wgt_desc, &planes);
1476
1477 CoreExternalTexture {
1478 wgpu_external_texture,
1479 }
1480 .into()
1481 }
1482
1483 fn create_blas(
1484 &self,
1485 desc: &crate::CreateBlasDescriptor<'_>,
1486 sizes: crate::BlasGeometrySizeDescriptors,
1487 ) -> (Option<u64>, dispatch::DispatchBlas) {
1488 let (wgpu_blas, error) = self
1489 .wgpu_device
1490 .create_blas(&desc.map_label(|l| l.map(Borrowed)), sizes);
1491 if let Some(cause) = error {
1492 self.wgpu_device
1493 .handle_error(cause, desc.label, "Device::create_blas");
1494 }
1495 (wgpu_blas.handle(), CoreBlas { wgpu_blas }.into())
1496 }
1497
1498 fn create_tlas(&self, desc: &crate::CreateTlasDescriptor<'_>) -> dispatch::DispatchTlas {
1499 let (wgpu_tlas, error) = self
1500 .wgpu_device
1501 .create_tlas(&desc.map_label(|l| l.map(Borrowed)));
1502 if let Some(cause) = error {
1503 self.wgpu_device
1504 .handle_error(cause, desc.label, "Device::create_tlas");
1505 }
1506 CoreTlas { wgpu_tlas }.into()
1507 }
1508
1509 fn create_sampler(&self, desc: &crate::SamplerDescriptor<'_>) -> dispatch::DispatchSampler {
1510 let descriptor = wgc::resource::SamplerDescriptor {
1511 label: desc.label.map(Borrowed),
1512 address_modes: [
1513 desc.address_mode_u,
1514 desc.address_mode_v,
1515 desc.address_mode_w,
1516 ],
1517 mag_filter: desc.mag_filter,
1518 min_filter: desc.min_filter,
1519 mipmap_filter: desc.mipmap_filter,
1520 lod_min_clamp: desc.lod_min_clamp,
1521 lod_max_clamp: desc.lod_max_clamp,
1522 compare: desc.compare,
1523 anisotropy_clamp: desc.anisotropy_clamp,
1524 border_color: desc.border_color,
1525 };
1526
1527 let wgpu_sampler = self.wgpu_device.create_sampler(&descriptor);
1528 CoreSampler { wgpu_sampler }.into()
1529 }
1530
1531 fn create_query_set(&self, desc: &crate::QuerySetDescriptor<'_>) -> dispatch::DispatchQuerySet {
1532 let wgpu_query_set = self
1533 .wgpu_device
1534 .create_query_set(&desc.map_label(|l| l.map(Borrowed)));
1535 CoreQuerySet { wgpu_query_set }.into()
1536 }
1537
1538 fn create_command_encoder(
1539 &self,
1540 desc: &crate::CommandEncoderDescriptor<'_>,
1541 ) -> dispatch::DispatchCommandEncoder {
1542 let wgpu_command_encoder = self
1543 .wgpu_device
1544 .create_command_encoder(&desc.map_label(|l| l.map(Borrowed)));
1545
1546 CoreCommandEncoder {
1547 wgpu_command_encoder,
1548 }
1549 .into()
1550 }
1551
1552 fn create_render_bundle_encoder(
1553 &self,
1554 desc: &crate::RenderBundleEncoderDescriptor<'_>,
1555 ) -> dispatch::DispatchRenderBundleEncoder {
1556 let descriptor = wgc::command::RenderBundleEncoderDescriptor {
1557 label: desc.label.map(Borrowed),
1558 color_formats: Borrowed(desc.color_formats),
1559 depth_stencil: desc.depth_stencil,
1560 sample_count: desc.sample_count,
1561 multiview: desc.multiview,
1562 };
1563 let encoder = self.wgpu_device.create_render_bundle_encoder(&descriptor);
1564
1565 CoreRenderBundleEncoder { encoder }.into()
1566 }
1567
1568 fn set_device_lost_callback(&self, device_lost_callback: dispatch::BoxDeviceLostCallback) {
1569 self.wgpu_device
1570 .set_device_lost_closure(device_lost_callback);
1571 }
1572
1573 fn on_uncaptured_error(&self, handler: Arc<dyn crate::UncapturedErrorHandler>) {
1574 self.wgpu_device.on_uncaptured_error(handler);
1575 }
1576
1577 fn push_error_scope(&self, filter: crate::ErrorFilter) -> u32 {
1578 self.wgpu_device.push_error_scope_with_index(filter)
1579 }
1580
1581 fn pop_error_scope(&self, index: u32) -> Pin<Box<dyn dispatch::PopErrorScopeFuture>> {
1582 Box::pin(ready(self.wgpu_device.pop_error_scope_checked(index)))
1583 }
1584
1585 unsafe fn start_graphics_debugger_capture(&self) {
1586 unsafe { self.wgpu_device.start_graphics_debugger_capture() };
1587 }
1588
1589 unsafe fn stop_graphics_debugger_capture(&self) {
1590 unsafe { self.wgpu_device.stop_graphics_debugger_capture() };
1591 }
1592
1593 fn poll(&self, poll_type: wgt::PollType<u64>) -> Result<crate::PollStatus, crate::PollError> {
1594 match self.wgpu_device.poll(poll_type) {
1595 Ok(status) => Ok(status),
1596 Err(err) => {
1597 if let Some(poll_error) = err.to_poll_error() {
1598 return Err(poll_error);
1599 }
1600
1601 handle_error_fatal(err, "Device::poll")
1602 }
1603 }
1604 }
1605
1606 fn get_internal_counters(&self) -> crate::InternalCounters {
1607 self.wgpu_device.get_internal_counters()
1608 }
1609
1610 fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
1611 self.wgpu_device.generate_allocator_report()
1612 }
1613
1614 fn destroy(&self) {
1615 self.wgpu_device.destroy();
1616 }
1617}
1618
1619impl Drop for CoreDevice {
1620 fn drop(&mut self) {}
1621}
1622
1623impl dispatch::QueueInterface for CoreQueue {
1624 fn write_buffer(
1625 &self,
1626 buffer: &dispatch::DispatchBuffer,
1627 offset: crate::BufferAddress,
1628 data: &[u8],
1629 ) {
1630 let buffer = buffer.as_core();
1631
1632 self.wgpu_queue
1633 .write_buffer(buffer.wgpu_buffer.clone(), offset, data)
1634 }
1635
1636 fn create_staging_buffer(
1637 &self,
1638 size: crate::BufferSize,
1639 ) -> Option<dispatch::DispatchQueueWriteBuffer> {
1640 match self.wgpu_queue.create_staging_buffer(size) {
1641 Ok((wgpu_staging_buffer, _)) => Some(
1642 CoreQueueWriteBuffer {
1643 wgpu_staging_buffer,
1644 }
1645 .into(),
1646 ),
1647 Err(err) => {
1648 self.wgpu_queue
1649 .device()
1650 .handle_error_nolabel(err, "Queue::write_buffer_with");
1651 None
1652 }
1653 }
1654 }
1655
1656 fn validate_write_buffer(
1657 &self,
1658 buffer: &dispatch::DispatchBuffer,
1659 offset: wgt::BufferAddress,
1660 size: wgt::BufferSize,
1661 ) -> Option<()> {
1662 let buffer = buffer.as_core();
1663
1664 match self
1665 .wgpu_queue
1666 .validate_write_buffer(buffer.wgpu_buffer.clone(), offset, size)
1667 {
1668 Ok(()) => Some(()),
1669 Err(err) => {
1670 self.wgpu_queue
1671 .device()
1672 .handle_error_nolabel(err, "Queue::write_buffer_with");
1673 None
1674 }
1675 }
1676 }
1677
1678 fn write_staging_buffer(
1679 &self,
1680 buffer: &dispatch::DispatchBuffer,
1681 offset: crate::BufferAddress,
1682 staging_buffer: dispatch::DispatchQueueWriteBuffer,
1683 ) {
1684 let buffer = buffer.as_core();
1685 let staging_buffer = {
1686 #[allow(
1687 clippy::allow_attributes,
1688 unreachable_patterns,
1689 reason = "features may be disabled"
1690 )]
1691 match staging_buffer {
1692 dispatch::DispatchQueueWriteBuffer::Core(value) => value,
1693 _ => panic!(concat!(
1694 stringify!(DispatchQueueWriteBuffer),
1695 " is not core"
1696 )),
1697 }
1698 };
1699
1700 match self.wgpu_queue.write_staging_buffer(
1701 buffer.wgpu_buffer.clone(),
1702 offset,
1703 staging_buffer.wgpu_staging_buffer,
1704 ) {
1705 Ok(()) => (),
1706 Err(err) => {
1707 self.wgpu_queue
1708 .device()
1709 .handle_error_nolabel(err, "Queue::write_buffer_with");
1710 }
1711 }
1712 }
1713
1714 fn write_texture(
1715 &self,
1716 texture: crate::TexelCopyTextureInfo<'_>,
1717 data: &[u8],
1718 data_layout: crate::TexelCopyBufferLayout,
1719 size: crate::Extent3d,
1720 ) {
1721 self.wgpu_queue
1722 .write_texture(map_texture_copy_view(texture), data, &data_layout, &size);
1723 }
1724
1725 #[cfg(web)]
1728 #[cfg_attr(not(webgl), expect(unused_variables))]
1729 fn copy_external_image_to_texture(
1730 &self,
1731 source: &crate::CopyExternalImageSourceInfo,
1732 dest: crate::CopyExternalImageDestInfo<&crate::api::Texture>,
1733 size: crate::Extent3d,
1734 ) {
1735 #[cfg(webgl)]
1736 match self.wgpu_queue.copy_external_image_to_texture(
1737 source,
1738 map_texture_tagged_copy_view(dest),
1739 size,
1740 ) {
1741 Ok(()) => (),
1742 Err(err) => self
1743 .wgpu_queue
1744 .device()
1745 .handle_error_nolabel(err, "Queue::copy_external_image_to_texture"),
1746 }
1747 }
1748
1749 fn submit(
1750 &self,
1751 command_buffers: &mut dyn Iterator<Item = dispatch::DispatchCommandBuffer>,
1752 ) -> u64 {
1753 let temp_command_buffers = command_buffers.collect::<SmallVec<[_; 4]>>();
1754 let command_buffers = temp_command_buffers
1755 .iter()
1756 .map(|cmdbuf| cmdbuf.as_core().wgpu_command_buffer.clone())
1757 .collect::<SmallVec<[_; 4]>>();
1758
1759 let index = self.wgpu_queue.submit(&command_buffers);
1760
1761 drop(temp_command_buffers);
1762
1763 index
1764 }
1765
1766 fn get_timestamp_period(&self) -> f32 {
1767 self.wgpu_queue.get_timestamp_period()
1768 }
1769
1770 fn on_submitted_work_done(&self, callback: dispatch::BoxSubmittedWorkDoneCallback) {
1771 self.wgpu_queue.on_submitted_work_done(callback);
1772 }
1773
1774 fn compact_blas(&self, blas: &dispatch::DispatchBlas) -> (Option<u64>, dispatch::DispatchBlas) {
1775 let (wgpu_blas, error) = self.wgpu_queue.compact_blas(&blas.as_core().wgpu_blas);
1776
1777 if let Some(cause) = error {
1778 self.wgpu_queue
1779 .device()
1780 .handle_error_nolabel(cause, "Queue::compact_blas");
1781 }
1782 (wgpu_blas.handle(), CoreBlas { wgpu_blas }.into())
1783 }
1784
1785 fn present(&self, detail: &dispatch::DispatchSurfaceOutputDetail) {
1786 let detail = detail.as_core();
1787 match detail.wgpu_surface.present() {
1788 Ok(_status) => (),
1789 Err(err) => {
1790 self.wgpu_queue
1791 .device()
1792 .handle_error_nolabel(err, "Queue::present");
1793 }
1794 }
1795 }
1796}
1797
1798impl dispatch::ShaderModuleInterface for CoreShaderModule {
1799 fn get_compilation_info(&self) -> Pin<Box<dyn dispatch::ShaderCompilationInfoFuture>> {
1800 Box::pin(ready(self.wgpu_shader_module.compilation_info().clone()))
1801 }
1802}
1803
1804impl dispatch::BindGroupLayoutInterface for CoreBindGroupLayout {}
1805
1806impl dispatch::BindGroupInterface for CoreBindGroup {}
1807
1808impl dispatch::TextureViewInterface for CoreTextureView {}
1809
1810impl dispatch::ExternalTextureInterface for CoreExternalTexture {
1811 fn destroy(&self) {
1812 self.wgpu_external_texture.destroy();
1813 }
1814}
1815
1816impl dispatch::SamplerInterface for CoreSampler {}
1817
1818impl dispatch::BufferInterface for CoreBuffer {
1819 fn map_async(
1820 &self,
1821 mode: crate::MapMode,
1822 range: Range<crate::BufferAddress>,
1823 callback: dispatch::BufferMapCallback,
1824 ) {
1825 let operation = wgc::resource::BufferMapOperation {
1826 mode,
1827 callback: Some(Box::new(|status| {
1828 let res = status.map_err(|_| crate::BufferAsyncError);
1829 callback(res);
1830 })),
1831 };
1832
1833 self.wgpu_buffer
1834 .map_async(range.start, Some(range.end - range.start), operation);
1835 }
1836
1837 fn get_mapped_range(
1838 &self,
1839 sub_range: Range<crate::BufferAddress>,
1840 ) -> Result<dispatch::DispatchBufferMappedRange, crate::MapRangeError> {
1841 let size = sub_range.end - sub_range.start;
1842 self.wgpu_buffer
1843 .get_mapped_range(sub_range.start, Some(size))
1844 .map(|mapping| CoreBufferMappedRange(mapping).into())
1845 .map_err(|err| crate::MapRangeError(format_error(&err)))
1846 }
1847
1848 fn unmap(&self) {
1849 self.wgpu_buffer.unmap();
1850 }
1851
1852 fn destroy(&self) {
1853 self.wgpu_buffer.destroy();
1854 }
1855
1856 fn size(&self) -> crate::BufferAddress {
1857 self.wgpu_buffer.size()
1858 }
1859
1860 fn usage(&self) -> crate::BufferUsages {
1861 self.wgpu_buffer.usage()
1862 }
1863}
1864
1865impl dispatch::TextureInterface for CoreTexture {
1866 fn create_view(
1867 &self,
1868 desc: &crate::TextureViewDescriptor<'_>,
1869 ) -> dispatch::DispatchTextureView {
1870 let descriptor = wgc::resource::TextureViewDescriptor {
1871 label: desc.label.map(Borrowed),
1872 format: desc.format,
1873 dimension: desc.dimension,
1874 usage: desc.usage,
1875 range: wgt::ImageSubresourceRange {
1876 aspect: desc.aspect,
1877 base_mip_level: desc.base_mip_level,
1878 mip_level_count: desc.mip_level_count,
1879 base_array_layer: desc.base_array_layer,
1880 array_layer_count: desc.array_layer_count,
1881 },
1882 swizzle: desc.swizzle,
1883 };
1884 let wgpu_texture_view = self.wgpu_texture.create_view(&descriptor);
1885 CoreTextureView { wgpu_texture_view }.into()
1886 }
1887
1888 fn destroy(&self) {
1889 self.wgpu_texture.destroy();
1890 }
1891
1892 fn size(&self) -> wgt::Extent3d {
1893 self.wgpu_texture.descriptor().size
1894 }
1895
1896 fn mip_level_count(&self) -> u32 {
1897 self.wgpu_texture.descriptor().mip_level_count
1898 }
1899
1900 fn sample_count(&self) -> u32 {
1901 self.wgpu_texture.descriptor().sample_count
1902 }
1903
1904 fn dimension(&self) -> wgt::TextureDimension {
1905 self.wgpu_texture.descriptor().dimension
1906 }
1907
1908 fn format(&self) -> wgt::TextureFormat {
1909 self.wgpu_texture.descriptor().format
1910 }
1911
1912 fn usage(&self) -> wgt::TextureUsages {
1913 self.wgpu_texture.descriptor().usage
1914 }
1915
1916 unsafe fn mark_externally_initialized(&self) {
1917 unsafe { self.wgpu_texture.mark_externally_initialized() }
1918 }
1919}
1920
1921impl dispatch::BlasInterface for CoreBlas {
1922 fn prepare_compact_async(&self, callback: BlasCompactCallback) {
1923 let callback: Option<wgc::resource::BlasCompactCallback> =
1924 Some(Box::new(|status: BlasPrepareCompactResult| {
1925 let res = status.map_err(|_| crate::BlasAsyncError);
1926 callback(res);
1927 }));
1928
1929 match self.wgpu_blas.prepare_compact_async(callback) {
1930 Ok(_) => (),
1931 Err(cause) => self
1932 .wgpu_blas
1933 .device()
1934 .handle_error_nolabel(cause, "Blas::prepare_compact_async"),
1935 }
1936 }
1937
1938 fn ready_for_compaction(&self) -> bool {
1939 match self.wgpu_blas.ready_for_compaction() {
1940 Ok(ready) => ready,
1941 Err(cause) => {
1942 self.wgpu_blas
1943 .device()
1944 .handle_error_nolabel(cause, "Blas::ready_for_compaction");
1945 false
1947 }
1948 }
1949 }
1950}
1951
1952impl dispatch::TlasInterface for CoreTlas {}
1953
1954impl dispatch::QuerySetInterface for CoreQuerySet {
1955 fn destroy(&self) {
1956 self.wgpu_query_set.destroy();
1957 }
1958
1959 fn ty(&self) -> crate::QueryType {
1960 self.wgpu_query_set.descriptor().ty
1961 }
1962
1963 fn count(&self) -> u32 {
1964 self.wgpu_query_set.descriptor().count
1965 }
1966}
1967
1968impl dispatch::PipelineLayoutInterface for CorePipelineLayout {}
1969
1970impl dispatch::RenderPipelineInterface for CoreRenderPipeline {
1971 fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
1972 let wgpu_bind_group_layout = self.wgpu_render_pipeline.get_bind_group_layout(index);
1973 CoreBindGroupLayout {
1974 wgpu_bind_group_layout,
1975 }
1976 .into()
1977 }
1978}
1979
1980impl dispatch::ComputePipelineInterface for CoreComputePipeline {
1981 fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
1982 let wgpu_bind_group_layout = self.wgpu_compute_pipeline.get_bind_group_layout(index);
1983 CoreBindGroupLayout {
1984 wgpu_bind_group_layout,
1985 }
1986 .into()
1987 }
1988}
1989
1990impl dispatch::PipelineCacheInterface for CorePipelineCache {
1991 fn get_data(&self) -> Option<Vec<u8>> {
1992 self.wgpu_pipeline_cache.get_data()
1993 }
1994}
1995
1996impl dispatch::CommandEncoderInterface for CoreCommandEncoder {
1997 fn copy_buffer_to_buffer(
1998 &self,
1999 source: &dispatch::DispatchBuffer,
2000 source_offset: crate::BufferAddress,
2001 destination: &dispatch::DispatchBuffer,
2002 destination_offset: crate::BufferAddress,
2003 copy_size: Option<crate::BufferAddress>,
2004 ) {
2005 let source = source.as_core();
2006 let destination = destination.as_core();
2007
2008 self.wgpu_command_encoder.copy_buffer_to_buffer(
2009 source.wgpu_buffer.clone(),
2010 source_offset,
2011 destination.wgpu_buffer.clone(),
2012 destination_offset,
2013 copy_size,
2014 )
2015 }
2016
2017 fn copy_buffer_to_texture(
2018 &self,
2019 source: crate::TexelCopyBufferInfo<'_>,
2020 destination: crate::TexelCopyTextureInfo<'_>,
2021 copy_size: crate::Extent3d,
2022 ) {
2023 self.wgpu_command_encoder.copy_buffer_to_texture(
2024 &map_buffer_copy_view(source),
2025 &map_texture_copy_view(destination),
2026 ©_size,
2027 )
2028 }
2029
2030 fn copy_texture_to_buffer(
2031 &self,
2032 source: crate::TexelCopyTextureInfo<'_>,
2033 destination: crate::TexelCopyBufferInfo<'_>,
2034 copy_size: crate::Extent3d,
2035 ) {
2036 self.wgpu_command_encoder.copy_texture_to_buffer(
2037 &map_texture_copy_view(source),
2038 &map_buffer_copy_view(destination),
2039 ©_size,
2040 );
2041 }
2042
2043 fn copy_texture_to_texture(
2044 &self,
2045 source: crate::TexelCopyTextureInfo<'_>,
2046 destination: crate::TexelCopyTextureInfo<'_>,
2047 copy_size: crate::Extent3d,
2048 ) {
2049 self.wgpu_command_encoder.copy_texture_to_texture(
2050 &map_texture_copy_view(source),
2051 &map_texture_copy_view(destination),
2052 ©_size,
2053 );
2054 }
2055
2056 fn begin_compute_pass(
2057 &self,
2058 desc: &crate::ComputePassDescriptor<'_>,
2059 ) -> dispatch::DispatchComputePass {
2060 let timestamp_writes =
2061 desc.timestamp_writes
2062 .as_ref()
2063 .map(|tw| wgc::command::PassTimestampWrites {
2064 query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
2065 beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
2066 end_of_pass_write_index: tw.end_of_pass_write_index,
2067 });
2068
2069 let pass =
2070 self.wgpu_command_encoder
2071 .begin_compute_pass(&wgc::command::ComputePassDescriptor {
2072 label: desc.label.map(Borrowed),
2073 timestamp_writes,
2074 });
2075
2076 CoreComputePass {
2077 pass,
2078 id: crate::cmp::Identifier::create(),
2079 }
2080 .into()
2081 }
2082
2083 fn begin_render_pass(
2084 &self,
2085 desc: &crate::RenderPassDescriptor<'_>,
2086 ) -> dispatch::DispatchRenderPass {
2087 let colors = desc
2088 .color_attachments
2089 .iter()
2090 .map(|ca| {
2091 ca.as_ref()
2092 .map(|at| wgc::command::RenderPassColorAttachment {
2093 view: at.view.inner.as_core().wgpu_texture_view.clone(),
2094 depth_slice: at.depth_slice,
2095 resolve_target: at
2096 .resolve_target
2097 .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
2098 load_op: at.ops.load,
2099 store_op: at.ops.store,
2100 })
2101 })
2102 .collect::<Vec<_>>();
2103
2104 let depth_stencil = desc.depth_stencil_attachment.as_ref().map(|dsa| {
2105 wgc::command::RenderPassDepthStencilAttachment {
2106 view: dsa.view.inner.as_core().wgpu_texture_view.clone(),
2107 depth: map_pass_channel(dsa.depth_ops.as_ref()),
2108 stencil: map_pass_channel(dsa.stencil_ops.as_ref()),
2109 }
2110 });
2111
2112 let timestamp_writes =
2113 desc.timestamp_writes
2114 .as_ref()
2115 .map(|tw| wgc::command::PassTimestampWrites {
2116 query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
2117 beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
2118 end_of_pass_write_index: tw.end_of_pass_write_index,
2119 });
2120
2121 let pass = self.wgpu_command_encoder.begin_render_pass(
2122 wgc::command::ResolvedRenderPassDescriptor {
2123 label: desc.label.map(Borrowed),
2124 timestamp_writes,
2125 color_attachments: Borrowed(&colors),
2126 depth_stencil_attachment: depth_stencil,
2127 occlusion_query_set: desc
2128 .occlusion_query_set
2129 .map(|qs| qs.inner.as_core().wgpu_query_set.clone()),
2130 multiview_mask: desc.multiview_mask,
2131 },
2132 );
2133
2134 CoreRenderPass {
2135 pass,
2136 id: crate::cmp::Identifier::create(),
2137 }
2138 .into()
2139 }
2140
2141 fn finish(&mut self) -> dispatch::DispatchCommandBuffer {
2142 let descriptor = wgt::CommandBufferDescriptor::default();
2143 let wgpu_command_buffer = self.wgpu_command_encoder.finish(&descriptor);
2144 CoreCommandBuffer {
2145 wgpu_command_buffer,
2146 }
2147 .into()
2148 }
2149
2150 fn clear_texture(
2151 &self,
2152 texture: &dispatch::DispatchTexture,
2153 subresource_range: &crate::ImageSubresourceRange,
2154 ) {
2155 let texture = texture.as_core();
2156
2157 self.wgpu_command_encoder
2158 .clear_texture(texture.wgpu_texture.clone(), subresource_range)
2159 }
2160
2161 fn clear_buffer(
2162 &self,
2163 buffer: &dispatch::DispatchBuffer,
2164 offset: crate::BufferAddress,
2165 size: Option<crate::BufferAddress>,
2166 ) {
2167 let buffer = buffer.as_core();
2168
2169 self.wgpu_command_encoder
2170 .clear_buffer(buffer.wgpu_buffer.clone(), offset, size)
2171 }
2172
2173 fn insert_debug_marker(&self, label: &str) {
2174 self.wgpu_command_encoder.insert_debug_marker(label)
2175 }
2176
2177 fn push_debug_group(&self, label: &str) {
2178 self.wgpu_command_encoder.push_debug_group(label)
2179 }
2180
2181 fn pop_debug_group(&self) {
2182 self.wgpu_command_encoder.pop_debug_group()
2183 }
2184
2185 fn write_timestamp(&self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2186 let query_set = query_set.as_core();
2187
2188 self.wgpu_command_encoder
2189 .write_timestamp(query_set.wgpu_query_set.clone(), query_index)
2190 }
2191
2192 fn resolve_query_set(
2193 &self,
2194 query_set: &dispatch::DispatchQuerySet,
2195 first_query: u32,
2196 query_count: u32,
2197 destination: &dispatch::DispatchBuffer,
2198 destination_offset: crate::BufferAddress,
2199 ) {
2200 let query_set = query_set.as_core();
2201 let destination = destination.as_core();
2202
2203 self.wgpu_command_encoder.resolve_query_set(
2204 query_set.wgpu_query_set.clone(),
2205 first_query,
2206 query_count,
2207 destination.wgpu_buffer.clone(),
2208 destination_offset,
2209 );
2210 }
2211
2212 fn mark_acceleration_structures_built<'a>(
2213 &self,
2214 blas: &mut dyn Iterator<Item = &'a Blas>,
2215 tlas: &mut dyn Iterator<Item = &'a Tlas>,
2216 ) {
2217 let blas = blas
2218 .map(|b| b.inner.as_core().wgpu_blas.clone())
2219 .collect::<SmallVec<[_; 4]>>();
2220 let tlas = tlas
2221 .map(|t| t.inner.as_core().wgpu_tlas.clone())
2222 .collect::<SmallVec<[_; 4]>>();
2223 self.wgpu_command_encoder
2224 .mark_acceleration_structures_built(&blas, &tlas)
2225 }
2226
2227 fn build_acceleration_structures<'a>(
2228 &self,
2229 blas: &mut dyn Iterator<Item = &'a crate::BlasBuildEntry<'a>>,
2230 tlas: &mut dyn Iterator<Item = &'a crate::Tlas>,
2231 ) {
2232 let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| {
2233 let geometries = match e.geometry {
2234 crate::BlasGeometries::TriangleGeometries(ref triangle_geometries) => {
2235 let iter = triangle_geometries.iter().map(|tg| {
2236 wgc::ray_tracing::BlasTriangleGeometry {
2237 vertex_buffer: tg.vertex_buffer.inner.as_core().wgpu_buffer.clone(),
2238 index_buffer: tg
2239 .index_buffer
2240 .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2241 transform_buffer: tg
2242 .transform_buffer
2243 .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2244 size: tg.size,
2245 transform_buffer_offset: tg.transform_buffer_offset,
2246 first_vertex: tg.first_vertex,
2247 vertex_stride: tg.vertex_stride,
2248 first_index: tg.first_index,
2249 }
2250 });
2251 wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter))
2252 }
2253 crate::BlasGeometries::AabbGeometries(ref aabb_geometries) => {
2254 let iter =
2255 aabb_geometries
2256 .iter()
2257 .map(|ag| wgc::ray_tracing::BlasAabbGeometry {
2258 aabb_buffer: ag.aabb_buffer.inner.as_core().wgpu_buffer.clone(),
2259 stride: ag.stride,
2260 size: ag.size,
2261 primitive_offset: ag.primitive_offset,
2262 });
2263 wgc::ray_tracing::BlasGeometries::AabbGeometries(Box::new(iter))
2264 }
2265 };
2266 wgc::ray_tracing::BlasBuildEntry {
2267 blas: e.blas.inner.as_core().wgpu_blas.clone(),
2268 geometries,
2269 }
2270 });
2271
2272 let tlas = tlas.into_iter().map(|e| {
2273 let instances = e
2274 .instances
2275 .iter()
2276 .map(|instance: &Option<crate::TlasInstance>| {
2277 instance
2278 .as_ref()
2279 .map(|instance| wgc::ray_tracing::ArcTlasInstance {
2280 blas: instance.blas.as_core().wgpu_blas.clone(),
2281 transform: instance.transform,
2282 custom_data: instance.custom_data,
2283 mask: instance.mask,
2284 })
2285 })
2286 .collect();
2287 wgc::ray_tracing::ArcTlasPackage {
2288 tlas: e.inner.as_core().wgpu_tlas.clone(),
2289 instances,
2290 lowest_unmodified: e.lowest_unmodified,
2291 }
2292 });
2293
2294 self.wgpu_command_encoder
2295 .build_acceleration_structures(blas, tlas.collect())
2296 }
2297
2298 fn transition_resources<'a>(
2299 &mut self,
2300 buffer_transitions: &mut dyn Iterator<
2301 Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2302 >,
2303 texture_transitions: &mut dyn Iterator<
2304 Item = wgt::TextureTransition<&'a dispatch::DispatchTexture>,
2305 >,
2306 ) {
2307 self.wgpu_command_encoder.transition_resources(
2308 buffer_transitions.map(|t| wgt::BufferTransition {
2309 buffer: t.buffer.as_core().wgpu_buffer.clone(),
2310 state: t.state,
2311 }),
2312 texture_transitions.map(|t| wgt::TextureTransition {
2313 texture: t.texture.as_core().wgpu_texture.clone(),
2314 selector: t.selector.clone(),
2315 state: t.state,
2316 }),
2317 );
2318 }
2319}
2320
2321impl dispatch::CommandBufferInterface for CoreCommandBuffer {}
2322
2323impl dispatch::ComputePassInterface for CoreComputePass {
2324 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchComputePipeline) {
2325 let pipeline = pipeline.as_core();
2326
2327 self.pass
2328 .set_pipeline(pipeline.wgpu_compute_pipeline.clone());
2329 }
2330
2331 fn set_bind_group(
2332 &mut self,
2333 index: u32,
2334 bind_group: Option<&dispatch::DispatchBindGroup>,
2335 offsets: &[crate::DynamicOffset],
2336 ) {
2337 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2338
2339 self.pass.set_bind_group(index, bg, offsets);
2340 }
2341
2342 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2343 self.pass.set_immediates(offset, data);
2344 }
2345
2346 fn insert_debug_marker(&mut self, label: &str) {
2347 self.pass.insert_debug_marker(label, 0);
2348 }
2349
2350 fn push_debug_group(&mut self, group_label: &str) {
2351 self.pass.push_debug_group(group_label, 0);
2352 }
2353
2354 fn pop_debug_group(&mut self) {
2355 self.pass.pop_debug_group();
2356 }
2357
2358 fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2359 let query_set = query_set.as_core();
2360
2361 self.pass
2362 .write_timestamp(query_set.wgpu_query_set.clone(), query_index);
2363 }
2364
2365 fn begin_pipeline_statistics_query(
2366 &mut self,
2367 query_set: &dispatch::DispatchQuerySet,
2368 query_index: u32,
2369 ) {
2370 let query_set = query_set.as_core();
2371
2372 self.pass
2373 .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index);
2374 }
2375
2376 fn end_pipeline_statistics_query(&mut self) {
2377 self.pass.end_pipeline_statistics_query();
2378 }
2379
2380 fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
2381 self.pass.dispatch_workgroups(x, y, z);
2382 }
2383
2384 fn dispatch_workgroups_indirect(
2385 &mut self,
2386 indirect_buffer: &dispatch::DispatchBuffer,
2387 indirect_offset: crate::BufferAddress,
2388 ) {
2389 let indirect_buffer = indirect_buffer.as_core();
2390
2391 self.pass
2392 .dispatch_workgroups_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2393 }
2394
2395 fn transition_resources<'a>(
2396 &mut self,
2397 buffer_transitions: &mut dyn Iterator<
2398 Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2399 >,
2400 texture_transitions: &mut dyn Iterator<
2401 Item = wgt::TextureTransition<&'a dispatch::DispatchTextureView>,
2402 >,
2403 ) {
2404 self.pass.transition_resources(
2405 buffer_transitions.map(|t| wgt::BufferTransition {
2406 buffer: t.buffer.as_core().wgpu_buffer.clone(),
2407 state: t.state,
2408 }),
2409 texture_transitions.map(|t| wgt::TextureTransition {
2410 texture: t.texture.as_core().wgpu_texture_view.clone(),
2411 selector: t.selector.clone(),
2412 state: t.state,
2413 }),
2414 );
2415 }
2416}
2417
2418impl Drop for CoreComputePass {
2419 fn drop(&mut self) {
2420 self.pass.end();
2421 }
2422}
2423
2424impl dispatch::RenderPassInterface for CoreRenderPass {
2425 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2426 let pipeline = pipeline.as_core();
2427
2428 self.pass
2429 .set_pipeline(pipeline.wgpu_render_pipeline.clone());
2430 }
2431
2432 fn set_bind_group(
2433 &mut self,
2434 index: u32,
2435 bind_group: Option<&dispatch::DispatchBindGroup>,
2436 offsets: &[crate::DynamicOffset],
2437 ) {
2438 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2439
2440 self.pass.set_bind_group(index, bg, offsets);
2441 }
2442
2443 fn set_index_buffer(
2444 &mut self,
2445 buffer: &dispatch::DispatchBuffer,
2446 index_format: crate::IndexFormat,
2447 offset: crate::BufferAddress,
2448 size: Option<crate::BufferAddress>,
2449 ) {
2450 let buffer = buffer.as_core();
2451
2452 self.pass
2453 .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size)
2454 }
2455
2456 fn set_vertex_buffer(
2457 &mut self,
2458 slot: u32,
2459 buffer: Option<&dispatch::DispatchBuffer>,
2460 offset: crate::BufferAddress,
2461 size: Option<crate::BufferAddress>,
2462 ) {
2463 let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
2464
2465 self.pass.set_vertex_buffer(slot, buffer, offset, size);
2466 }
2467
2468 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2469 self.pass.set_immediates(offset, data);
2470 }
2471
2472 fn set_blend_constant(&mut self, color: crate::Color) {
2473 self.pass.set_blend_constant(color);
2474 }
2475
2476 fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
2477 self.pass.set_scissor_rect(x, y, width, height);
2478 }
2479
2480 fn set_viewport(
2481 &mut self,
2482 x: f32,
2483 y: f32,
2484 width: f32,
2485 height: f32,
2486 min_depth: f32,
2487 max_depth: f32,
2488 ) {
2489 self.pass
2490 .set_viewport(x, y, width, height, min_depth, max_depth);
2491 }
2492
2493 fn set_stencil_reference(&mut self, reference: u32) {
2494 self.pass.set_stencil_reference(reference);
2495 }
2496
2497 fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2498 self.pass.draw(
2499 vertices.end - vertices.start,
2500 instances.end - instances.start,
2501 vertices.start,
2502 instances.start,
2503 );
2504 }
2505
2506 fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2507 self.pass.draw_indexed(
2508 indices.end - indices.start,
2509 instances.end - instances.start,
2510 indices.start,
2511 base_vertex,
2512 instances.start,
2513 );
2514 }
2515
2516 fn draw_mesh_tasks(&mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32) {
2517 self.pass
2518 .draw_mesh_tasks(group_count_x, group_count_y, group_count_z);
2519 }
2520
2521 fn draw_indirect(
2522 &mut self,
2523 indirect_buffer: &dispatch::DispatchBuffer,
2524 indirect_offset: crate::BufferAddress,
2525 ) {
2526 let indirect_buffer = indirect_buffer.as_core();
2527
2528 self.pass
2529 .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2530 }
2531
2532 fn draw_indexed_indirect(
2533 &mut self,
2534 indirect_buffer: &dispatch::DispatchBuffer,
2535 indirect_offset: crate::BufferAddress,
2536 ) {
2537 let indirect_buffer = indirect_buffer.as_core();
2538
2539 self.pass
2540 .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2541 }
2542
2543 fn draw_mesh_tasks_indirect(
2544 &mut self,
2545 indirect_buffer: &dispatch::DispatchBuffer,
2546 indirect_offset: crate::BufferAddress,
2547 ) {
2548 let indirect_buffer = indirect_buffer.as_core();
2549
2550 self.pass
2551 .draw_mesh_tasks_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2552 }
2553
2554 fn multi_draw_indirect(
2555 &mut self,
2556 indirect_buffer: &dispatch::DispatchBuffer,
2557 indirect_offset: crate::BufferAddress,
2558 count: u32,
2559 ) {
2560 let indirect_buffer = indirect_buffer.as_core();
2561
2562 self.pass
2563 .multi_draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset, count);
2564 }
2565
2566 fn multi_draw_indexed_indirect(
2567 &mut self,
2568 indirect_buffer: &dispatch::DispatchBuffer,
2569 indirect_offset: crate::BufferAddress,
2570 count: u32,
2571 ) {
2572 let indirect_buffer = indirect_buffer.as_core();
2573
2574 self.pass.multi_draw_indexed_indirect(
2575 indirect_buffer.wgpu_buffer.clone(),
2576 indirect_offset,
2577 count,
2578 );
2579 }
2580
2581 fn multi_draw_mesh_tasks_indirect(
2582 &mut self,
2583 indirect_buffer: &dispatch::DispatchBuffer,
2584 indirect_offset: crate::BufferAddress,
2585 count: u32,
2586 ) {
2587 let indirect_buffer = indirect_buffer.as_core();
2588
2589 self.pass.multi_draw_mesh_tasks_indirect(
2590 indirect_buffer.wgpu_buffer.clone(),
2591 indirect_offset,
2592 count,
2593 );
2594 }
2595
2596 fn multi_draw_indirect_count(
2597 &mut self,
2598 indirect_buffer: &dispatch::DispatchBuffer,
2599 indirect_offset: crate::BufferAddress,
2600 count_buffer: &dispatch::DispatchBuffer,
2601 count_buffer_offset: crate::BufferAddress,
2602 max_count: u32,
2603 ) {
2604 let indirect_buffer = indirect_buffer.as_core();
2605 let count_buffer = count_buffer.as_core();
2606
2607 self.pass.multi_draw_indirect_count(
2608 indirect_buffer.wgpu_buffer.clone(),
2609 indirect_offset,
2610 count_buffer.wgpu_buffer.clone(),
2611 count_buffer_offset,
2612 max_count,
2613 );
2614 }
2615
2616 fn multi_draw_indexed_indirect_count(
2617 &mut self,
2618 indirect_buffer: &dispatch::DispatchBuffer,
2619 indirect_offset: crate::BufferAddress,
2620 count_buffer: &dispatch::DispatchBuffer,
2621 count_buffer_offset: crate::BufferAddress,
2622 max_count: u32,
2623 ) {
2624 let indirect_buffer = indirect_buffer.as_core();
2625 let count_buffer = count_buffer.as_core();
2626
2627 self.pass.multi_draw_indexed_indirect_count(
2628 indirect_buffer.wgpu_buffer.clone(),
2629 indirect_offset,
2630 count_buffer.wgpu_buffer.clone(),
2631 count_buffer_offset,
2632 max_count,
2633 );
2634 }
2635
2636 fn multi_draw_mesh_tasks_indirect_count(
2637 &mut self,
2638 indirect_buffer: &dispatch::DispatchBuffer,
2639 indirect_offset: crate::BufferAddress,
2640 count_buffer: &dispatch::DispatchBuffer,
2641 count_buffer_offset: crate::BufferAddress,
2642 max_count: u32,
2643 ) {
2644 let indirect_buffer = indirect_buffer.as_core();
2645 let count_buffer = count_buffer.as_core();
2646
2647 self.pass.multi_draw_mesh_tasks_indirect_count(
2648 indirect_buffer.wgpu_buffer.clone(),
2649 indirect_offset,
2650 count_buffer.wgpu_buffer.clone(),
2651 count_buffer_offset,
2652 max_count,
2653 );
2654 }
2655
2656 fn insert_debug_marker(&mut self, label: &str) {
2657 self.pass.insert_debug_marker(label, 0);
2658 }
2659
2660 fn push_debug_group(&mut self, group_label: &str) {
2661 self.pass.push_debug_group(group_label, 0);
2662 }
2663
2664 fn pop_debug_group(&mut self) {
2665 self.pass.pop_debug_group();
2666 }
2667
2668 fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2669 let query_set = query_set.as_core();
2670
2671 self.pass
2672 .write_timestamp(query_set.wgpu_query_set.clone(), query_index);
2673 }
2674
2675 fn begin_occlusion_query(&mut self, query_index: u32) {
2676 self.pass.begin_occlusion_query(query_index);
2677 }
2678
2679 fn end_occlusion_query(&mut self) {
2680 self.pass.end_occlusion_query();
2681 }
2682
2683 fn begin_pipeline_statistics_query(
2684 &mut self,
2685 query_set: &dispatch::DispatchQuerySet,
2686 query_index: u32,
2687 ) {
2688 let query_set = query_set.as_core();
2689
2690 self.pass
2691 .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index);
2692 }
2693
2694 fn end_pipeline_statistics_query(&mut self) {
2695 self.pass.end_pipeline_statistics_query();
2696 }
2697
2698 fn execute_bundles(
2699 &mut self,
2700 render_bundles: &mut dyn Iterator<Item = &dispatch::DispatchRenderBundle>,
2701 ) {
2702 let temp_render_bundles = render_bundles
2703 .map(|rb| rb.as_core().wgpu_render_bundle.clone())
2704 .collect::<SmallVec<[_; 4]>>();
2705 self.pass.execute_bundles(&temp_render_bundles);
2706 }
2707}
2708
2709impl Drop for CoreRenderPass {
2710 fn drop(&mut self) {
2711 self.pass.end()
2712 }
2713}
2714
2715impl dispatch::RenderBundleEncoderInterface for CoreRenderBundleEncoder {
2716 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2717 let pipeline = pipeline.as_core();
2718
2719 self.encoder
2720 .set_pipeline(pipeline.wgpu_render_pipeline.clone())
2721 }
2722
2723 fn set_bind_group(
2724 &mut self,
2725 index: u32,
2726 bind_group: Option<&dispatch::DispatchBindGroup>,
2727 offsets: &[crate::DynamicOffset],
2728 ) {
2729 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2730
2731 self.encoder.set_bind_group(index, bg, offsets);
2732 }
2733
2734 fn set_index_buffer(
2735 &mut self,
2736 buffer: &dispatch::DispatchBuffer,
2737 index_format: crate::IndexFormat,
2738 offset: crate::BufferAddress,
2739 size: Option<crate::BufferAddress>,
2740 ) {
2741 let buffer = buffer.as_core();
2742
2743 self.encoder
2744 .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size);
2745 }
2746
2747 fn set_vertex_buffer(
2748 &mut self,
2749 slot: u32,
2750 buffer: Option<&dispatch::DispatchBuffer>,
2751 offset: crate::BufferAddress,
2752 size: Option<crate::BufferAddress>,
2753 ) {
2754 let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
2755
2756 self.encoder.set_vertex_buffer(slot, buffer, offset, size);
2757 }
2758
2759 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2760 if !data
2761 .len()
2762 .is_multiple_of(wgt::IMMEDIATE_DATA_ALIGNMENT as usize)
2763 {
2764 self.encoder.device().handle_error(
2765 wgc::binding_model::ImmediateUploadError::SizeUnaligned(data.len()),
2766 self.encoder.label(),
2767 "RenderBundleEncoder::set_immediates",
2768 );
2769 return;
2770 }
2771
2772 self.encoder.set_immediates(offset, data);
2773 }
2774
2775 fn insert_debug_marker(&mut self, label: &str) {
2776 self.encoder.insert_debug_marker(label);
2777 }
2778
2779 fn push_debug_group(&mut self, group_label: &str) {
2780 self.encoder.push_debug_group(group_label);
2781 }
2782
2783 fn pop_debug_group(&mut self) {
2784 self.encoder.pop_debug_group();
2785 }
2786
2787 fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2788 self.encoder.draw(
2789 vertices.end - vertices.start,
2790 instances.end - instances.start,
2791 vertices.start,
2792 instances.start,
2793 );
2794 }
2795
2796 fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2797 self.encoder.draw_indexed(
2798 indices.end - indices.start,
2799 instances.end - instances.start,
2800 indices.start,
2801 base_vertex,
2802 instances.start,
2803 );
2804 }
2805
2806 fn draw_indirect(
2807 &mut self,
2808 indirect_buffer: &dispatch::DispatchBuffer,
2809 indirect_offset: crate::BufferAddress,
2810 ) {
2811 let indirect_buffer = indirect_buffer.as_core();
2812
2813 self.encoder
2814 .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2815 }
2816
2817 fn draw_indexed_indirect(
2818 &mut self,
2819 indirect_buffer: &dispatch::DispatchBuffer,
2820 indirect_offset: crate::BufferAddress,
2821 ) {
2822 let indirect_buffer = indirect_buffer.as_core();
2823
2824 self.encoder
2825 .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2826 }
2827
2828 fn finish(mut self, desc: &crate::RenderBundleDescriptor<'_>) -> dispatch::DispatchRenderBundle
2829 where
2830 Self: Sized,
2831 {
2832 let wgpu_render_bundle = self.encoder.finish(&desc.map_label(|l| l.map(Borrowed)));
2833 CoreRenderBundle { wgpu_render_bundle }.into()
2834 }
2835
2836 #[cfg(custom)]
2837 fn finish_boxed(
2838 self: Box<Self>,
2839 desc: &crate::RenderBundleDescriptor<'_>,
2840 ) -> dispatch::DispatchRenderBundle {
2841 (*self).finish(desc)
2842 }
2843}
2844
2845impl dispatch::RenderBundleInterface for CoreRenderBundle {}
2846
2847#[derive(Clone)]
2848enum ErrorSink {
2849 Actual(Arc<wgc::device::Device>),
2850 Dummy(Arc<Mutex<wgc::error::ErrorSink>>),
2851}
2852
2853impl ErrorSink {
2854 fn new() -> Self {
2855 Self::Dummy(Arc::new(Mutex::new(wgc::error::ErrorSink::new())))
2856 }
2857
2858 fn handle_error_nolabel(
2859 &self,
2860 source: impl WebGpuError + WasmNotSendSync + 'static,
2861 fn_ident: &'static str,
2862 ) {
2863 match self {
2864 ErrorSink::Actual(device) => device.handle_error_nolabel(source, fn_ident),
2865 ErrorSink::Dummy(sink) => sink.lock().handle_error_nolabel(source, fn_ident),
2866 }
2867 }
2868}
2869
2870impl dispatch::SurfaceInterface for CoreSurface {
2871 fn get_capabilities(&self, adapter: &dispatch::DispatchAdapter) -> wgt::SurfaceCapabilities {
2872 let adapter = adapter.as_core();
2873
2874 self.wgpu_surface
2875 .get_capabilities(&adapter.wgpu_adapter)
2876 .unwrap_or_default()
2877 }
2878
2879 fn display_hdr_info(&self, adapter: &dispatch::DispatchAdapter) -> wgt::DisplayHdrInfo {
2880 let adapter = adapter.as_core();
2881
2882 self.wgpu_surface.display_hdr_info(&adapter.wgpu_adapter)
2883 }
2884
2885 fn configure(&self, device: &dispatch::DispatchDevice, config: &crate::SurfaceConfiguration) {
2886 let device = device.as_core();
2887
2888 let result = self.wgpu_surface.configure(&device.wgpu_device, config);
2889 if let Some(e) = result.err() {
2890 device
2891 .wgpu_device
2892 .handle_error_nolabel(e, "Surface::configure");
2893 } else {
2894 *self.configured_device.lock() = Some(device.wgpu_device.clone());
2895 }
2896 }
2897
2898 fn get_current_texture(
2899 &self,
2900 _desc: Option<crate::TextureDescriptor<'static>>,
2901 ) -> (
2902 Option<dispatch::DispatchTexture>,
2903 crate::SurfaceStatus,
2904 dispatch::DispatchSurfaceOutputDetail,
2905 ) {
2906 let error_sink = if let Some(error_sink) = self.configured_device.lock().as_ref() {
2907 ErrorSink::Actual(error_sink.clone())
2908 } else {
2909 ErrorSink::new()
2910 };
2911
2912 let output_detail = CoreSurfaceOutputDetail {
2913 wgpu_surface: self.wgpu_surface.clone(),
2914 error_sink,
2915 }
2916 .into();
2917
2918 match self.wgpu_surface.get_current_texture() {
2919 Ok(wgc::present::SurfaceOutput {
2920 status,
2921 texture: texture_id,
2922 }) => {
2923 let data = texture_id
2924 .map(|wgpu_texture| CoreTexture { wgpu_texture })
2925 .map(Into::into);
2926
2927 (data, status, output_detail)
2928 }
2929 Err(err) => {
2930 let error_sink = self.configured_device.lock();
2931 match error_sink.as_ref() {
2932 Some(error_sink) => {
2933 error_sink.handle_error_nolabel(err, "Surface::get_current_texture_view");
2934 (None, crate::SurfaceStatus::Validation, output_detail)
2935 }
2936 None => handle_error_fatal(err, "Surface::get_current_texture_view"),
2937 }
2938 }
2939 }
2940 }
2941}
2942
2943impl dispatch::SurfaceOutputDetailInterface for CoreSurfaceOutputDetail {
2944 fn texture_discard(&self) {
2945 match self.wgpu_surface.discard() {
2946 Ok(_status) => (),
2947 Err(err) => self
2948 .error_sink
2949 .handle_error_nolabel(err, "Surface::discard_texture"),
2950 }
2951 }
2952
2953 fn texture_release(&self) {
2954 match self.wgpu_surface.release() {
2955 Ok(_status) => (),
2956 Err(err) => self
2957 .error_sink
2958 .handle_error_nolabel(err, "Surface::release_texture"),
2959 }
2960 }
2961}
2962
2963impl dispatch::QueueWriteBufferInterface for CoreQueueWriteBuffer {
2964 #[inline]
2965 fn len(&self) -> usize {
2966 self.wgpu_staging_buffer.size().get() as usize
2967 }
2968
2969 #[inline]
2970 unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
2971 unsafe {
2972 WriteOnly::new(NonNull::slice_from_raw_parts(
2973 self.wgpu_staging_buffer.ptr(),
2974 self.len(),
2975 ))
2976 }
2977 }
2978}
2979
2980impl dispatch::BufferMappedRangeInterface for CoreBufferMappedRange {
2981 #[inline]
2982 unsafe fn read_slice(&self) -> &[u8] {
2983 unsafe { slice::from_raw_parts(self.0.ptr().as_ptr(), self.0.len() as usize) }
2986 }
2987
2988 #[inline]
2989 unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
2990 self.0.write_slice()
2991 }
2992
2993 #[cfg(webgpu)]
2994 fn as_uint8array(&self) -> &js_sys::Uint8Array {
2995 panic!("Only available on WebGPU")
2996 }
2997}