1use alloc::borrow::ToOwned;
2use alloc::{
3 borrow::Cow::{self, Borrowed},
4 boxed::Box,
5 format,
6 string::{String, ToString as _},
7 sync::Arc,
8 vec,
9 vec::Vec,
10};
11use core::{
12 error::Error,
13 fmt,
14 future::ready,
15 ops::{Deref, Range},
16 pin::Pin,
17 ptr::NonNull,
18 slice,
19};
20use hashbrown::HashMap;
21
22use arrayvec::ArrayVec;
23use smallvec::SmallVec;
24use wgc::{
25 error::ContextErrorSource, pipeline::CreateShaderModuleError,
26 resource::BlasPrepareCompactResult,
27};
28use wgt::{
29 error::{ErrorType, WebGpuError},
30 WasmNotSendSync,
31};
32
33use crate::{
34 api,
35 dispatch::{self, BlasCompactCallback, BufferMappedRangeInterface},
36 BindingResource, Blas, BufferBinding, BufferDescriptor, CompilationInfo, CompilationMessage,
37 CompilationMessageType, ErrorSource, Features, Label, LoadOp, MapMode, Operations,
38 ShaderSource, SurfaceTargetUnsafe, TextureDescriptor, Tlas, WriteOnly,
39};
40use crate::{dispatch::DispatchAdapter, util::Mutex};
41
42mod thread_id;
43
44#[derive(Clone)]
45pub struct ContextWgpuCore(Arc<wgc::instance::Instance>);
46
47impl fmt::Debug for ContextWgpuCore {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 f.debug_struct("ContextWgpuCore")
50 .field("type", &"Native")
51 .finish()
52 }
53}
54
55impl ContextWgpuCore {
56 pub unsafe fn from_hal_instance<A: hal::Api>(hal_instance: A::Instance) -> Self {
57 Self(wgc::instance::Instance::from_hal_instance::<A>(
58 "wgpu".to_owned(),
59 hal_instance,
60 ))
61 }
62
63 pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
67 unsafe { self.0.as_hal::<A>() }
68 }
69
70 pub unsafe fn from_core_instance(core_instance: Arc<wgc::instance::Instance>) -> Self {
71 Self(core_instance)
72 }
73
74 #[cfg(wgpu_core)]
75 pub fn enumerate_adapters(&self, backends: wgt::Backends) -> Vec<Arc<wgc::instance::Adapter>> {
76 self.0
77 .enumerate_adapters(backends, false )
78 }
79
80 pub unsafe fn create_adapter_from_hal<A: hal::Api>(
81 &self,
82 hal_adapter: hal::ExposedAdapter<A>,
83 ) -> Arc<wgc::instance::Adapter> {
84 unsafe { self.0.create_adapter_from_hal(hal_adapter.into()) }
85 }
86
87 pub unsafe fn adapter_as_hal<A: hal::Api>(
88 &self,
89 adapter: &CoreAdapter,
90 ) -> Option<impl Deref<Target = A::Adapter> + WasmNotSendSync> {
91 unsafe { adapter.wgpu_adapter.clone().as_hal::<A>() }
92 }
93
94 pub unsafe fn buffer_as_hal<A: hal::Api>(
95 &self,
96 buffer: &CoreBuffer,
97 ) -> Option<impl Deref<Target = A::Buffer>> {
98 unsafe { buffer.wgpu_buffer.clone().as_hal::<A>() }
99 }
100
101 pub unsafe fn create_device_from_hal<A: hal::Api>(
102 &self,
103 adapter: &CoreAdapter,
104 hal_device: hal::OpenDevice<A>,
105 desc: &crate::DeviceDescriptor<'_>,
106 ) -> Result<(CoreDevice, CoreQueue), crate::RequestDeviceError> {
107 let (device, queue) = unsafe {
108 adapter.wgpu_adapter.create_device_and_queue_from_hal(
109 hal_device.into(),
110 &desc.map_label(|l| l.map(Borrowed)),
111 )
112 }?;
113 let error_sink = Arc::new(Mutex::new(ErrorSinkRaw::new()));
114 let device = CoreDevice {
115 context: self.clone(),
116 wgpu_device: device,
117 error_sink: error_sink.clone(),
118 features: desc.required_features,
119 };
120 let queue = CoreQueue {
121 context: self.clone(),
122 wgpu_queue: queue,
123 error_sink,
124 };
125 Ok((device, queue))
126 }
127
128 pub unsafe fn create_texture_from_hal<A: hal::Api>(
129 &self,
130 hal_texture: A::Texture,
131 device: &CoreDevice,
132 desc: &TextureDescriptor<'_>,
133 initial_state: wgt::TextureUses,
134 ) -> CoreTexture {
135 let descriptor = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
136 let (wgpu_texture, error) = unsafe {
137 device.wgpu_device.create_texture_from_hal(
138 Box::new(hal_texture),
139 &descriptor,
140 initial_state,
141 )
142 };
143 if let Some(cause) = error {
144 self.handle_error(
145 &device.error_sink,
146 cause,
147 desc.label,
148 "Device::create_texture_from_hal",
149 );
150 }
151 CoreTexture {
152 context: self.clone(),
153 wgpu_texture,
154 error_sink: Arc::clone(&device.error_sink),
155 }
156 }
157
158 pub unsafe fn create_buffer_from_hal<A: hal::Api>(
165 &self,
166 hal_buffer: A::Buffer,
167 device: &CoreDevice,
168 desc: &BufferDescriptor<'_>,
169 ) -> CoreBuffer {
170 let (wgpu_buffer, error) = unsafe {
171 device
172 .wgpu_device
173 .create_buffer_from_hal(Box::new(hal_buffer), &desc.map_label(|l| l.map(Borrowed)))
174 };
175 if let Some(cause) = error {
176 self.handle_error(
177 &device.error_sink,
178 cause,
179 desc.label,
180 "Device::create_buffer_from_hal",
181 );
182 }
183 CoreBuffer {
184 context: self.clone(),
185 wgpu_buffer,
186 error_sink: Arc::clone(&device.error_sink),
187 }
188 }
189
190 pub unsafe fn device_as_hal<A: hal::Api>(
191 &self,
192 device: &CoreDevice,
193 ) -> Option<impl Deref<Target = A::Device>> {
194 unsafe { device.wgpu_device.clone().as_hal::<A>() }
195 }
196
197 pub unsafe fn surface_as_hal<A: hal::Api>(
198 &self,
199 surface: &CoreSurface,
200 ) -> Option<impl Deref<Target = A::Surface>> {
201 unsafe { surface.wgpu_surface.clone().as_hal::<A>() }
202 }
203
204 pub unsafe fn texture_as_hal<A: hal::Api>(
205 &self,
206 texture: &CoreTexture,
207 ) -> Option<impl Deref<Target = A::Texture>> {
208 unsafe { texture.wgpu_texture.clone().as_hal::<A>() }
209 }
210
211 pub unsafe fn texture_view_as_hal<A: hal::Api>(
212 &self,
213 texture_view: &CoreTextureView,
214 ) -> Option<impl Deref<Target = A::TextureView>> {
215 unsafe { texture_view.wgpu_texture_view.clone().as_hal::<A>() }
216 }
217
218 pub unsafe fn command_encoder_as_hal_mut<
220 A: hal::Api,
221 F: FnOnce(Option<&mut A::CommandEncoder>) -> R,
222 R,
223 >(
224 &self,
225 command_encoder: &CoreCommandEncoder,
226 hal_command_encoder_callback: F,
227 ) -> R {
228 unsafe {
229 command_encoder
230 .wgpu_command_encoder
231 .as_hal_mut::<A, F, R>(hal_command_encoder_callback)
232 }
233 }
234
235 pub unsafe fn blas_as_hal<A: hal::Api>(
236 &self,
237 blas: &CoreBlas,
238 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
239 unsafe { blas.wgpu_blas.clone().as_hal::<A>() }
240 }
241
242 pub unsafe fn tlas_as_hal<A: hal::Api>(
243 &self,
244 tlas: &CoreTlas,
245 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
246 unsafe { tlas.wgpu_tlas.clone().as_hal::<A>() }
247 }
248
249 #[cold]
250 #[track_caller]
251 #[inline(never)]
252 fn handle_error_inner(
253 &self,
254 sink_mutex: &Mutex<ErrorSinkRaw>,
255 error_type: ErrorType,
256 source: ContextErrorSource,
257 label: Label<'_>,
258 fn_ident: &'static str,
259 ) {
260 let source: ErrorSource = Box::new(wgc::error::ContextError {
261 fn_ident,
262 source,
263 label: label.unwrap_or_default().to_string(),
264 });
265 let final_error_handling = {
266 let mut sink = sink_mutex.lock();
267 let description = || self.format_error(&*source);
268 let error = match error_type {
269 ErrorType::Internal => {
270 let description = description();
271 crate::Error::Internal {
272 source,
273 description,
274 }
275 }
276 ErrorType::OutOfMemory => crate::Error::OutOfMemory { source },
277 ErrorType::Validation => {
278 let description = description();
279 crate::Error::Validation {
280 source,
281 description,
282 }
283 }
284 ErrorType::DeviceLost => return, };
286 sink.handle_error_or_return_handler(error)
287 };
288
289 if let Some(f) = final_error_handling {
290 f();
294 }
295 }
296
297 #[inline]
298 #[track_caller]
299 fn handle_error(
300 &self,
301 sink_mutex: &Mutex<ErrorSinkRaw>,
302 source: impl WebGpuError + WasmNotSendSync + 'static,
303 label: Label<'_>,
304 fn_ident: &'static str,
305 ) {
306 let error_type = source.webgpu_error_type();
307 self.handle_error_inner(sink_mutex, error_type, Box::new(source), label, fn_ident)
308 }
309
310 #[inline]
311 #[track_caller]
312 fn handle_error_nolabel(
313 &self,
314 sink_mutex: &Mutex<ErrorSinkRaw>,
315 source: impl WebGpuError + WasmNotSendSync + 'static,
316 fn_ident: &'static str,
317 ) {
318 let error_type = source.webgpu_error_type();
319 self.handle_error_inner(sink_mutex, error_type, Box::new(source), None, fn_ident)
320 }
321
322 #[track_caller]
323 #[cold]
324 fn handle_error_fatal(
325 &self,
326 cause: impl Error + WasmNotSendSync + 'static,
327 operation: &'static str,
328 ) -> ! {
329 panic!("Error in {operation}: {f}", f = self.format_error(&cause));
330 }
331
332 #[inline(never)]
333 fn format_error(&self, err: &(dyn Error + 'static)) -> String {
334 let mut output = String::new();
335 let mut level = 1;
336
337 fn print_tree(output: &mut String, level: &mut usize, e: &(dyn Error + 'static)) {
338 let mut print = |e: &(dyn Error + 'static)| {
339 use core::fmt::Write;
340 writeln!(output, "{}{}", " ".repeat(*level * 2), e).unwrap();
341
342 if let Some(e) = e.source() {
343 *level += 1;
344 print_tree(output, level, e);
345 *level -= 1;
346 }
347 };
348 if let Some(multi) = e.downcast_ref::<wgc::error::MultiError>() {
349 for e in multi.errors() {
350 print(e);
351 }
352 } else {
353 print(e);
354 }
355 }
356
357 print_tree(&mut output, &mut level, err);
358
359 format!("Validation Error\n\nCaused by:\n{output}")
360 }
361
362 pub unsafe fn queue_as_hal<A: hal::Api>(
363 &self,
364 queue: &CoreQueue,
365 ) -> Option<impl Deref<Target = A::Queue> + WasmNotSendSync> {
366 unsafe { queue.wgpu_queue.clone().as_hal::<A>() }
367 }
368}
369
370fn map_buffer_copy_view(
371 view: crate::TexelCopyBufferInfo<'_>,
372) -> wgt::TexelCopyBufferInfo<Arc<wgc::resource::Buffer>> {
373 wgt::TexelCopyBufferInfo {
374 buffer: view.buffer.inner.as_core().wgpu_buffer.clone(),
375 layout: view.layout,
376 }
377}
378
379fn map_texture_copy_view(
380 view: crate::TexelCopyTextureInfo<'_>,
381) -> wgt::TexelCopyTextureInfo<Arc<wgc::resource::Texture>> {
382 wgt::TexelCopyTextureInfo {
383 texture: view.texture.inner.as_core().wgpu_texture.clone(),
384 mip_level: view.mip_level,
385 origin: view.origin,
386 aspect: view.aspect,
387 }
388}
389
390#[cfg_attr(not(webgl), expect(unused))]
391fn map_texture_tagged_copy_view(
392 view: crate::CopyExternalImageDestInfo<&api::Texture>,
393) -> wgt::CopyExternalImageDestInfo<Arc<wgc::resource::Texture>> {
394 wgt::CopyExternalImageDestInfo {
395 texture: view.texture.inner.as_core().wgpu_texture.clone(),
396 mip_level: view.mip_level,
397 origin: view.origin,
398 aspect: view.aspect,
399 color_space: view.color_space,
400 premultiplied_alpha: view.premultiplied_alpha,
401 }
402}
403
404fn map_load_op<V: Copy>(load: &LoadOp<V>) -> LoadOp<Option<V>> {
405 match *load {
406 LoadOp::Clear(clear_value) => LoadOp::Clear(Some(clear_value)),
407 LoadOp::DontCare(token) => LoadOp::DontCare(token),
408 LoadOp::Load => LoadOp::Load,
409 }
410}
411
412fn map_pass_channel<V: Copy>(ops: Option<&Operations<V>>) -> wgc::command::PassChannel<Option<V>> {
413 match ops {
414 Some(&Operations { load, store }) => wgc::command::PassChannel {
415 load_op: Some(map_load_op(&load)),
416 store_op: Some(store),
417 read_only: false,
418 },
419 None => wgc::command::PassChannel {
420 load_op: None,
421 store_op: None,
422 read_only: true,
423 },
424 }
425}
426
427pub struct CoreSurface {
428 pub(crate) context: ContextWgpuCore,
429 pub(crate) wgpu_surface: Arc<wgc::instance::Surface>,
430 configured_device: Mutex<Option<Arc<wgc::device::Device>>>,
433 error_sink: Mutex<Option<ErrorSink>>,
436}
437
438impl fmt::Debug for CoreSurface {
439 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
440 f.debug_struct("CoreSurface")
441 .field("context", &self.context)
442 .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
443 .field("configured_device", &self.configured_device)
444 .field("error_sink", &self.error_sink)
445 .finish()
446 }
447}
448
449pub struct CoreAdapter {
450 pub(crate) context: ContextWgpuCore,
451 pub(crate) wgpu_adapter: Arc<wgc::instance::Adapter>,
452}
453
454impl fmt::Debug for CoreAdapter {
455 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456 f.debug_struct("CoreAdapter")
457 .field("context", &self.context)
458 .field("wgpu_adapter", &Arc::as_ptr(&self.wgpu_adapter))
459 .finish()
460 }
461}
462
463#[derive(Debug)]
464pub struct CoreDevice {
465 pub(crate) context: ContextWgpuCore,
466 pub(crate) wgpu_device: Arc<wgc::device::Device>,
467 error_sink: ErrorSink,
468 features: Features,
469}
470
471#[derive(Debug)]
472pub struct CoreBuffer {
473 pub(crate) context: ContextWgpuCore,
474 pub(crate) wgpu_buffer: Arc<wgc::resource::Buffer>,
475 error_sink: ErrorSink,
476}
477
478#[derive(Debug)]
479pub struct CoreShaderModule {
480 pub(crate) wgpu_shader_module: Arc<wgc::pipeline::ShaderModule>,
481 compilation_info: CompilationInfo,
482}
483
484#[derive(Debug)]
485pub struct CoreBindGroupLayout {
486 pub(crate) wgpu_bind_group_layout: Arc<wgc::binding_model::BindGroupLayout>,
487}
488
489#[derive(Debug)]
490pub struct CoreBindGroup {
491 pub(crate) wgpu_bind_group: Arc<wgc::binding_model::BindGroup>,
492}
493
494#[derive(Debug)]
495pub struct CoreTexture {
496 pub(crate) context: ContextWgpuCore,
497 pub(crate) wgpu_texture: Arc<wgc::resource::Texture>,
498 error_sink: ErrorSink,
499}
500
501#[derive(Debug)]
502pub struct CoreTextureView {
503 pub(crate) context: ContextWgpuCore,
504 pub(crate) wgpu_texture_view: Arc<wgc::resource::TextureView>,
505}
506
507#[derive(Debug)]
508pub struct CoreExternalTexture {
509 pub(crate) wgpu_external_texture: Arc<wgc::resource::ExternalTexture>,
510}
511
512#[derive(Debug)]
513pub struct CoreSampler {
514 pub(crate) wgpu_sampler: Arc<wgc::resource::Sampler>,
515}
516
517#[derive(Debug)]
518pub struct CoreQuerySet {
519 pub(crate) wgpu_query_set: Arc<wgc::resource::QuerySet>,
520}
521
522#[derive(Debug)]
523pub struct CorePipelineLayout {
524 pub(crate) wgpu_pipeline_layout: Arc<wgc::binding_model::PipelineLayout>,
525}
526
527#[derive(Debug)]
528pub struct CorePipelineCache {
529 pub(crate) wgpu_pipeline_cache: Arc<wgc::pipeline::PipelineCache>,
530}
531
532pub struct CoreCommandBuffer {
533 pub(crate) context: ContextWgpuCore,
534 pub(crate) wgpu_command_buffer: Arc<wgc::command::CommandBuffer>,
535}
536
537impl fmt::Debug for CoreCommandBuffer {
538 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539 f.debug_struct("CoreCommandBuffer")
540 .field("context", &self.context)
541 .field(
542 "wgpu_command_buffer",
543 &Arc::as_ptr(&self.wgpu_command_buffer),
544 )
545 .finish()
546 }
547}
548
549#[derive(Debug)]
550pub struct CoreRenderBundleEncoder {
551 pub(crate) context: ContextWgpuCore,
552 error_sink: ErrorSink,
553 encoder: Box<wgc::command::RenderBundleEncoder>,
554}
555
556#[derive(Debug)]
557pub struct CoreRenderBundle {
558 pub(crate) wgpu_render_bundle: Arc<wgc::command::RenderBundle>,
559}
560
561pub struct CoreQueue {
562 pub(crate) context: ContextWgpuCore,
563 pub(crate) wgpu_queue: Arc<wgc::device::queue::Queue>,
564 error_sink: ErrorSink,
565}
566
567impl fmt::Debug for CoreQueue {
568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569 f.debug_struct("CoreQueue")
570 .field("context", &self.context)
571 .field("wgpu_queue", &Arc::as_ptr(&self.wgpu_queue))
572 .field("error_sink", &self.error_sink)
573 .finish()
574 }
575}
576
577#[derive(Debug)]
578pub struct CoreComputePipeline {
579 pub(crate) context: ContextWgpuCore,
580 pub(crate) wgpu_compute_pipeline: Arc<wgc::pipeline::ComputePipeline>,
581 error_sink: ErrorSink,
582}
583
584#[derive(Debug)]
585pub struct CoreRenderPipeline {
586 pub(crate) context: ContextWgpuCore,
587 pub(crate) wgpu_render_pipeline: Arc<wgc::pipeline::RenderPipeline>,
588 error_sink: ErrorSink,
589}
590
591#[derive(Debug)]
592pub struct CoreComputePass {
593 pub(crate) context: ContextWgpuCore,
594 pass: wgc::command::ComputePass,
595 error_sink: ErrorSink,
596 id: crate::cmp::Identifier,
597}
598
599#[derive(Debug)]
600pub struct CoreRenderPass {
601 pub(crate) context: ContextWgpuCore,
602 pass: wgc::command::RenderPass,
603 error_sink: ErrorSink,
604 id: crate::cmp::Identifier,
605}
606
607pub struct CoreCommandEncoder {
608 pub(crate) context: ContextWgpuCore,
609 pub(crate) wgpu_command_encoder: Arc<wgc::command::CommandEncoder>,
610 error_sink: ErrorSink,
611}
612
613impl fmt::Debug for CoreCommandEncoder {
614 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
615 f.debug_struct("CoreCommandEncoder")
616 .field("context", &self.context)
617 .field(
618 "wgpu_command_encoder",
619 &Arc::as_ptr(&self.wgpu_command_encoder),
620 )
621 .field("error_sink", &self.error_sink)
622 .finish()
623 }
624}
625
626#[derive(Debug)]
627pub struct CoreBlas {
628 pub(crate) context: ContextWgpuCore,
629 pub(crate) wgpu_blas: Arc<wgc::resource::Blas>,
630 error_sink: ErrorSink,
631}
632
633#[derive(Debug)]
634pub struct CoreTlas {
635 pub(crate) context: ContextWgpuCore,
636 pub(crate) wgpu_tlas: Arc<wgc::resource::Tlas>,
637 }
639
640pub struct CoreSurfaceOutputDetail {
641 pub(crate) context: ContextWgpuCore,
642 wgpu_surface: Arc<wgc::instance::Surface>,
643 error_sink: ErrorSink,
644}
645
646impl fmt::Debug for CoreSurfaceOutputDetail {
647 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
648 f.debug_struct("CoreSurfaceOutputDetail")
649 .field("context", &self.context)
650 .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
651 .field("error_sink", &self.error_sink)
652 .finish()
653 }
654}
655
656type ErrorSink = Arc<Mutex<ErrorSinkRaw>>;
657
658struct ErrorScope {
659 error: Option<crate::Error>,
660 filter: crate::ErrorFilter,
661}
662
663struct ErrorSinkRaw {
664 scopes: HashMap<thread_id::ThreadId, Vec<ErrorScope>>,
665 uncaptured_handler: Option<Arc<dyn crate::UncapturedErrorHandler>>,
666}
667
668impl ErrorSinkRaw {
669 fn new() -> ErrorSinkRaw {
670 ErrorSinkRaw {
671 scopes: HashMap::new(),
672 uncaptured_handler: None,
673 }
674 }
675
676 #[track_caller]
686 #[must_use]
687 fn handle_error_or_return_handler(&mut self, err: crate::Error) -> Option<impl FnOnce()> {
688 let filter = match err {
689 crate::Error::OutOfMemory { .. } => crate::ErrorFilter::OutOfMemory,
690 crate::Error::Validation { .. } => crate::ErrorFilter::Validation,
691 crate::Error::Internal { .. } => crate::ErrorFilter::Internal,
692 };
693 let thread_id = thread_id::ThreadId::current();
694 let scopes = self.scopes.entry(thread_id).or_default();
695 match scopes.iter_mut().rev().find(|scope| scope.filter == filter) {
696 Some(scope) => {
697 if scope.error.is_none() {
698 scope.error = Some(err);
699 }
700 None
701 }
702 None => {
703 if let Some(custom_handler) = &self.uncaptured_handler {
704 let custom_handler = Arc::clone(custom_handler);
705 Some(move || (custom_handler)(err))
706 } else {
707 default_error_handler(err)
709 }
710 }
711 }
712 }
713}
714
715impl fmt::Debug for ErrorSinkRaw {
716 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
717 write!(f, "ErrorSink")
718 }
719}
720
721#[track_caller]
722fn default_error_handler(err: crate::Error) -> ! {
723 log::error!("Handling wgpu errors as fatal by default");
724 panic!("wgpu error: {err}\n");
725}
726
727impl From<CreateShaderModuleError> for CompilationInfo {
728 fn from(value: CreateShaderModuleError) -> Self {
729 match value {
730 #[cfg(feature = "wgsl")]
731 CreateShaderModuleError::Parsing(v) => v.into(),
732 #[cfg(feature = "glsl")]
733 CreateShaderModuleError::ParsingGlsl(v) => v.into(),
734 #[cfg(feature = "spirv")]
735 CreateShaderModuleError::ParsingSpirV(v) => v.into(),
736 CreateShaderModuleError::Validation(v) => v.into(),
737 CreateShaderModuleError::Device(_) | CreateShaderModuleError::Generation => {
740 CompilationInfo {
741 messages: Vec::new(),
742 }
743 }
744 _ => CompilationInfo {
746 messages: vec![CompilationMessage {
747 message: value.to_string(),
748 message_type: CompilationMessageType::Error,
749 location: None,
750 }],
751 },
752 }
753 }
754}
755
756#[derive(Debug)]
757pub struct CoreQueueWriteBuffer {
758 wgpu_staging_buffer: wgc::resource::StagingBuffer,
759 mapping: CoreBufferMappedRange,
760}
761
762#[derive(Debug)]
763pub struct CoreBufferMappedRange {
764 ptr: NonNull<u8>,
765 size: usize,
766}
767
768#[cfg(send_sync)]
769unsafe impl Send for CoreBufferMappedRange {}
770#[cfg(send_sync)]
771unsafe impl Sync for CoreBufferMappedRange {}
772
773impl Drop for CoreBufferMappedRange {
774 fn drop(&mut self) {
775 }
778}
779
780crate::cmp::impl_eq_ord_hash_arc_address!(ContextWgpuCore => .0);
781crate::cmp::impl_eq_ord_hash_arc_address!(CoreAdapter => .wgpu_adapter);
782crate::cmp::impl_eq_ord_hash_arc_address!(CoreDevice => .wgpu_device);
783crate::cmp::impl_eq_ord_hash_arc_address!(CoreQueue => .wgpu_queue);
784crate::cmp::impl_eq_ord_hash_arc_address!(CoreShaderModule => .wgpu_shader_module);
785crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroupLayout => .wgpu_bind_group_layout);
786crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroup => .wgpu_bind_group);
787crate::cmp::impl_eq_ord_hash_arc_address!(CoreTextureView => .wgpu_texture_view);
788crate::cmp::impl_eq_ord_hash_arc_address!(CoreSampler => .wgpu_sampler);
789crate::cmp::impl_eq_ord_hash_arc_address!(CoreBuffer => .wgpu_buffer);
790crate::cmp::impl_eq_ord_hash_arc_address!(CoreTexture => .wgpu_texture);
791crate::cmp::impl_eq_ord_hash_arc_address!(CoreExternalTexture => .wgpu_external_texture);
792crate::cmp::impl_eq_ord_hash_arc_address!(CoreBlas => .wgpu_blas);
793crate::cmp::impl_eq_ord_hash_arc_address!(CoreTlas => .wgpu_tlas);
794crate::cmp::impl_eq_ord_hash_arc_address!(CoreQuerySet => .wgpu_query_set);
795crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineLayout => .wgpu_pipeline_layout);
796crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderPipeline => .wgpu_render_pipeline);
797crate::cmp::impl_eq_ord_hash_arc_address!(CoreComputePipeline => .wgpu_compute_pipeline);
798crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineCache => .wgpu_pipeline_cache);
799crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandEncoder => .wgpu_command_encoder);
800crate::cmp::impl_eq_ord_hash_proxy!(CoreComputePass => .id);
801crate::cmp::impl_eq_ord_hash_proxy!(CoreRenderPass => .id);
802crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandBuffer => .wgpu_command_buffer);
803crate::cmp::impl_eq_ord_hash_box_address!(CoreRenderBundleEncoder => .encoder);
804crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderBundle => .wgpu_render_bundle);
805crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurface => .wgpu_surface);
806crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurfaceOutputDetail => .wgpu_surface);
807crate::cmp::impl_eq_ord_hash_proxy!(CoreQueueWriteBuffer => .mapping.ptr);
808crate::cmp::impl_eq_ord_hash_proxy!(CoreBufferMappedRange => .ptr);
809
810impl dispatch::InstanceInterface for ContextWgpuCore {
811 fn new(desc: wgt::InstanceDescriptor) -> Self
812 where
813 Self: Sized,
814 {
815 Self(wgc::instance::Instance::new("wgpu", desc, None))
816 }
817
818 unsafe fn create_surface(
819 &self,
820 target: crate::api::SurfaceTargetUnsafe,
821 ) -> Result<dispatch::DispatchSurface, crate::CreateSurfaceError> {
822 let wgpu_surface = match target {
823 SurfaceTargetUnsafe::RawHandle {
824 raw_display_handle,
825 raw_window_handle,
826 } => unsafe { self.0.create_surface(raw_display_handle, raw_window_handle) },
827
828 #[cfg(all(drm, not(target_os = "netbsd")))]
829 SurfaceTargetUnsafe::Drm {
830 fd,
831 plane,
832 connector_id,
833 width,
834 height,
835 refresh_rate,
836 } => unsafe {
837 self.0
838 .create_surface_from_drm(fd, plane, connector_id, width, height, refresh_rate)
839 },
840
841 #[cfg(metal)]
842 SurfaceTargetUnsafe::CoreAnimationLayer(layer) => unsafe {
843 self.0.create_surface_metal(layer)
844 },
845
846 #[cfg(all(drm, target_os = "netbsd"))]
847 SurfaceTargetUnsafe::Drm { .. } => Err(
848 wgc::instance::CreateSurfaceError::BackendNotEnabled(wgt::Backend::Vulkan),
849 ),
850
851 #[cfg(dx12)]
852 SurfaceTargetUnsafe::CompositionVisual(visual) => unsafe {
853 self.0.create_surface_from_visual(visual)
854 },
855
856 #[cfg(dx12)]
857 SurfaceTargetUnsafe::SurfaceHandle(surface_handle) => unsafe {
858 self.0.create_surface_from_surface_handle(surface_handle)
859 },
860
861 #[cfg(dx12)]
862 SurfaceTargetUnsafe::SwapChainPanel(swap_chain_panel) => unsafe {
863 self.0
864 .create_surface_from_swap_chain_panel(swap_chain_panel)
865 },
866 }?;
867
868 Ok(CoreSurface {
869 context: self.clone(),
870 wgpu_surface,
871 configured_device: Mutex::default(),
872 error_sink: Mutex::default(),
873 }
874 .into())
875 }
876
877 fn request_adapter(
878 &self,
879 options: &crate::api::RequestAdapterOptions<'_, '_>,
880 ) -> Pin<Box<dyn dispatch::RequestAdapterFuture>> {
881 let adapter = self.0.request_adapter(
882 &wgt::RequestAdapterOptions {
883 power_preference: options.power_preference,
884 force_fallback_adapter: options.force_fallback_adapter,
885 compatible_surface: options
886 .compatible_surface
887 .map(|surface| &*surface.inner.as_core().wgpu_surface),
888 apply_limit_buckets: false,
889 },
890 wgt::Backends::all(),
891 );
892 let adapter = adapter.map(|wgpu_adapter| {
893 let core = CoreAdapter {
894 context: self.clone(),
895 wgpu_adapter,
896 };
897 let generic: dispatch::DispatchAdapter = core.into();
898 generic
899 });
900 Box::pin(ready(adapter))
901 }
902
903 fn poll_all_devices(&self, force_wait: bool) -> bool {
904 match self.0.poll_all_devices(force_wait) {
905 Ok(all_queue_empty) => all_queue_empty,
906 Err(err) => self.handle_error_fatal(err, "Instance::poll_all_devices"),
907 }
908 }
909
910 #[cfg(feature = "wgsl")]
911 fn wgsl_language_features(&self) -> crate::WgslLanguageFeatures {
912 use wgc::naga::front::wgsl::ImplementedLanguageExtension;
913 ImplementedLanguageExtension::all().iter().copied().fold(
914 crate::WgslLanguageFeatures::empty(),
915 |acc, wle| {
916 acc | match wle {
917 ImplementedLanguageExtension::ReadOnlyAndReadWriteStorageTextures => {
918 crate::WgslLanguageFeatures::ReadOnlyAndReadWriteStorageTextures
919 }
920 ImplementedLanguageExtension::Packed4x8IntegerDotProduct => {
921 crate::WgslLanguageFeatures::Packed4x8IntegerDotProduct
922 }
923 ImplementedLanguageExtension::PointerCompositeAccess => {
924 crate::WgslLanguageFeatures::PointerCompositeAccess
925 }
926 ImplementedLanguageExtension::ImmediateAddressSpace => {
927 crate::WgslLanguageFeatures::ImmediateAddressSpace
928 }
929 }
930 },
931 )
932 }
933
934 fn enumerate_adapters(
935 &self,
936 backends: crate::Backends,
937 ) -> Pin<Box<dyn dispatch::EnumerateAdapterFuture>> {
938 let adapters: Vec<DispatchAdapter> = self
939 .enumerate_adapters(backends)
940 .into_iter()
941 .map(|adapter| {
942 let core = crate::backend::wgpu_core::CoreAdapter {
943 context: self.clone(),
944 wgpu_adapter: adapter,
945 };
946 core.into()
947 })
948 .collect();
949 Box::pin(ready(adapters))
950 }
951}
952
953impl dispatch::AdapterInterface for CoreAdapter {
954 fn request_device(
955 &self,
956 desc: &crate::DeviceDescriptor<'_>,
957 ) -> Pin<Box<dyn dispatch::RequestDeviceFuture>> {
958 let res = self
959 .wgpu_adapter
960 .request_device(&desc.map_label(|l| l.map(Borrowed)));
961 let (device, queue) = match res {
962 Ok(ids) => ids,
963 Err(err) => {
964 return Box::pin(ready(Err(err.into())));
965 }
966 };
967 let error_sink = Arc::new(Mutex::new(ErrorSinkRaw::new()));
968 let device = CoreDevice {
969 context: self.context.clone(),
970 wgpu_device: device,
971 error_sink: error_sink.clone(),
972 features: desc.required_features,
973 };
974 let queue = CoreQueue {
975 context: self.context.clone(),
976 wgpu_queue: queue,
977 error_sink,
978 };
979 Box::pin(ready(Ok((device.into(), queue.into()))))
980 }
981
982 fn is_surface_supported(&self, surface: &dispatch::DispatchSurface) -> bool {
983 let surface = surface.as_core();
984
985 self.wgpu_adapter
986 .is_surface_supported(&surface.wgpu_surface)
987 }
988
989 fn features(&self) -> crate::Features {
990 self.wgpu_adapter.features()
991 }
992
993 fn limits(&self) -> crate::Limits {
994 self.wgpu_adapter.limits()
995 }
996
997 fn downlevel_capabilities(&self) -> crate::DownlevelCapabilities {
998 self.wgpu_adapter.downlevel_capabilities()
999 }
1000
1001 fn get_info(&self) -> crate::AdapterInfo {
1002 self.wgpu_adapter.get_info()
1003 }
1004
1005 fn get_texture_format_features(
1006 &self,
1007 format: crate::TextureFormat,
1008 ) -> crate::TextureFormatFeatures {
1009 self.wgpu_adapter.get_texture_format_features(format)
1010 }
1011
1012 fn get_presentation_timestamp(&self) -> crate::PresentationTimestamp {
1013 self.wgpu_adapter.get_presentation_timestamp()
1014 }
1015
1016 fn cooperative_matrix_properties(&self) -> Vec<crate::wgt::CooperativeMatrixProperties> {
1017 self.wgpu_adapter.cooperative_matrix_properties()
1018 }
1019}
1020
1021impl Drop for CoreAdapter {
1022 fn drop(&mut self) {}
1023}
1024
1025impl dispatch::DeviceInterface for CoreDevice {
1026 fn features(&self) -> crate::Features {
1027 *self.wgpu_device.features()
1028 }
1029
1030 fn limits(&self) -> crate::Limits {
1031 self.wgpu_device.limits().clone()
1032 }
1033
1034 fn adapter_info(&self) -> crate::AdapterInfo {
1035 self.wgpu_device.adapter_info()
1036 }
1037
1038 #[cfg_attr(
1040 not(any(
1041 feature = "spirv",
1042 feature = "glsl",
1043 feature = "wgsl",
1044 feature = "naga-ir"
1045 )),
1046 expect(unused)
1047 )]
1048 fn create_shader_module(
1049 &self,
1050 desc: crate::ShaderModuleDescriptor<'_>,
1051 shader_bound_checks: wgt::ShaderRuntimeChecks,
1052 ) -> dispatch::DispatchShaderModule {
1053 let descriptor = wgc::pipeline::ShaderModuleDescriptor {
1054 label: desc.label.map(Borrowed),
1055 runtime_checks: shader_bound_checks,
1056 };
1057 let source = match desc.source {
1058 #[cfg(feature = "spirv")]
1059 ShaderSource::SpirV(ref spv) => {
1060 let options = naga::front::spv::Options {
1062 adjust_coordinate_space: false, strict_capabilities: true,
1064 block_ctx_dump_prefix: None,
1065 };
1066 wgc::pipeline::ShaderModuleSource::SpirV(Borrowed(spv), options)
1067 }
1068 #[cfg(feature = "glsl")]
1069 ShaderSource::Glsl {
1070 ref shader,
1071 stage,
1072 defines,
1073 } => {
1074 let options = naga::front::glsl::Options {
1075 stage,
1076 defines: defines
1077 .iter()
1078 .map(|&(key, value)| (String::from(key), String::from(value)))
1079 .collect(),
1080 };
1081 wgc::pipeline::ShaderModuleSource::Glsl(Borrowed(shader), options)
1082 }
1083 #[cfg(feature = "wgsl")]
1084 ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)),
1085 #[cfg(feature = "naga-ir")]
1086 ShaderSource::Naga(module) => wgc::pipeline::ShaderModuleSource::Naga(module),
1087 ShaderSource::Dummy(_) => panic!("found `ShaderSource::Dummy`"),
1088 };
1089 let (wgpu_shader_module, error) =
1090 self.wgpu_device.create_shader_module(&descriptor, source);
1091 let compilation_info = match error {
1092 Some(cause) => {
1093 self.context.handle_error(
1094 &self.error_sink,
1095 cause.clone(),
1096 desc.label,
1097 "Device::create_shader_module",
1098 );
1099 CompilationInfo::from(cause)
1100 }
1101 None => CompilationInfo { messages: vec![] },
1102 };
1103
1104 CoreShaderModule {
1105 wgpu_shader_module,
1106 compilation_info,
1107 }
1108 .into()
1109 }
1110
1111 unsafe fn create_shader_module_passthrough(
1112 &self,
1113 desc: &crate::ShaderModuleDescriptorPassthrough<'_>,
1114 ) -> dispatch::DispatchShaderModule {
1115 let desc = desc.map_label(|l| l.map(Cow::from));
1116 let (wgpu_shader_module, error) =
1117 unsafe { self.wgpu_device.create_shader_module_passthrough(&desc) };
1118
1119 let compilation_info = match error {
1120 Some(cause) => {
1121 self.context.handle_error(
1122 &self.error_sink,
1123 cause.clone(),
1124 desc.label.as_deref(),
1125 "Device::create_shader_module_passthrough",
1126 );
1127 CompilationInfo::from(cause)
1128 }
1129 None => CompilationInfo { messages: vec![] },
1130 };
1131
1132 CoreShaderModule {
1133 wgpu_shader_module,
1134 compilation_info,
1135 }
1136 .into()
1137 }
1138
1139 fn create_bind_group_layout(
1140 &self,
1141 desc: &crate::BindGroupLayoutDescriptor<'_>,
1142 ) -> dispatch::DispatchBindGroupLayout {
1143 let descriptor = wgc::binding_model::BindGroupLayoutDescriptor {
1144 label: desc.label.map(Borrowed),
1145 entries: Borrowed(desc.entries),
1146 };
1147 let (wgpu_bind_group_layout, error) =
1148 self.wgpu_device.create_bind_group_layout(&descriptor);
1149 if let Some(cause) = error {
1150 self.context.handle_error(
1151 &self.error_sink,
1152 cause,
1153 desc.label,
1154 "Device::create_bind_group_layout",
1155 );
1156 }
1157 CoreBindGroupLayout {
1158 wgpu_bind_group_layout,
1159 }
1160 .into()
1161 }
1162
1163 fn create_bind_group(
1164 &self,
1165 desc: &crate::BindGroupDescriptor<'_>,
1166 ) -> dispatch::DispatchBindGroup {
1167 use wgc::binding_model as bm;
1168
1169 let mut arrayed_texture_views = Vec::new();
1170 let mut arrayed_samplers = Vec::new();
1171 if self.features.contains(Features::TEXTURE_BINDING_ARRAY) {
1172 for entry in desc.entries.iter() {
1174 if let BindingResource::TextureViewArray(array) = entry.resource {
1175 arrayed_texture_views.extend(
1176 array
1177 .iter()
1178 .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
1179 );
1180 }
1181 if let BindingResource::SamplerArray(array) = entry.resource {
1182 arrayed_samplers.extend(
1183 array
1184 .iter()
1185 .map(|sampler| sampler.inner.as_core().wgpu_sampler.clone()),
1186 );
1187 }
1188 }
1189 }
1190 let mut remaining_arrayed_texture_views = &arrayed_texture_views[..];
1191 let mut remaining_arrayed_samplers = &arrayed_samplers[..];
1192
1193 let mut arrayed_buffer_bindings = Vec::new();
1194 if self.features.contains(Features::BUFFER_BINDING_ARRAY) {
1195 for entry in desc.entries.iter() {
1197 if let BindingResource::BufferArray(array) = entry.resource {
1198 arrayed_buffer_bindings.extend(array.iter().map(|binding| bm::BufferBinding {
1199 buffer: binding.buffer.inner.as_core().wgpu_buffer.clone(),
1200 offset: binding.offset,
1201 size: binding.size.map(wgt::BufferSize::get),
1202 }));
1203 }
1204 }
1205 }
1206 let mut remaining_arrayed_buffer_bindings = &arrayed_buffer_bindings[..];
1207
1208 let mut arrayed_acceleration_structures = Vec::new();
1209 if self
1210 .features
1211 .contains(Features::ACCELERATION_STRUCTURE_BINDING_ARRAY)
1212 {
1213 for entry in desc.entries.iter() {
1215 if let BindingResource::AccelerationStructureArray(array) = entry.resource {
1216 arrayed_acceleration_structures.extend(
1217 array
1218 .iter()
1219 .map(|tlas| tlas.inner.as_core().wgpu_tlas.clone()),
1220 );
1221 }
1222 }
1223 }
1224 let mut remaining_arrayed_acceleration_structures = &arrayed_acceleration_structures[..];
1225
1226 let entries = desc
1227 .entries
1228 .iter()
1229 .map(|entry| bm::BindGroupEntry {
1230 binding: entry.binding,
1231 resource: match entry.resource {
1232 BindingResource::Buffer(BufferBinding {
1233 buffer,
1234 offset,
1235 size,
1236 }) => bm::BindingResource::Buffer(bm::BufferBinding {
1237 buffer: buffer.inner.as_core().wgpu_buffer.clone(),
1238 offset,
1239 size: size.map(wgt::BufferSize::get),
1240 }),
1241 BindingResource::BufferArray(array) => {
1242 let slice = &remaining_arrayed_buffer_bindings[..array.len()];
1243 remaining_arrayed_buffer_bindings =
1244 &remaining_arrayed_buffer_bindings[array.len()..];
1245 bm::BindingResource::BufferArray(Borrowed(slice))
1246 }
1247 BindingResource::Sampler(sampler) => {
1248 bm::BindingResource::Sampler(sampler.inner.as_core().wgpu_sampler.clone())
1249 }
1250 BindingResource::SamplerArray(array) => {
1251 let slice = &remaining_arrayed_samplers[..array.len()];
1252 remaining_arrayed_samplers = &remaining_arrayed_samplers[array.len()..];
1253 bm::BindingResource::SamplerArray(Borrowed(slice))
1254 }
1255 BindingResource::TextureView(texture_view) => bm::BindingResource::TextureView(
1256 texture_view.inner.as_core().wgpu_texture_view.clone(),
1257 ),
1258 BindingResource::TextureViewArray(array) => {
1259 let slice = &remaining_arrayed_texture_views[..array.len()];
1260 remaining_arrayed_texture_views =
1261 &remaining_arrayed_texture_views[array.len()..];
1262 bm::BindingResource::TextureViewArray(Borrowed(slice))
1263 }
1264 BindingResource::AccelerationStructure(acceleration_structure) => {
1265 bm::BindingResource::AccelerationStructure(
1266 acceleration_structure.inner.as_core().wgpu_tlas.clone(),
1267 )
1268 }
1269 BindingResource::AccelerationStructureArray(array) => {
1270 let slice = &remaining_arrayed_acceleration_structures[..array.len()];
1271 remaining_arrayed_acceleration_structures =
1272 &remaining_arrayed_acceleration_structures[array.len()..];
1273 bm::BindingResource::AccelerationStructureArray(Borrowed(slice))
1274 }
1275 BindingResource::ExternalTexture(external_texture) => {
1276 bm::BindingResource::ExternalTexture(
1277 external_texture
1278 .inner
1279 .as_core()
1280 .wgpu_external_texture
1281 .clone(),
1282 )
1283 }
1284 },
1285 })
1286 .collect::<Vec<_>>();
1287 let descriptor = bm::BindGroupDescriptor {
1288 label: desc.label.as_ref().map(|label| Borrowed(&label[..])),
1289 layout: desc.layout.inner.as_core().wgpu_bind_group_layout.clone(),
1290 entries: Borrowed(&entries),
1291 };
1292
1293 let (wgpu_bind_group, error) = self.wgpu_device.create_bind_group(&descriptor);
1294 if let Some(cause) = error {
1295 self.context.handle_error(
1296 &self.error_sink,
1297 cause,
1298 desc.label,
1299 "Device::create_bind_group",
1300 );
1301 }
1302 CoreBindGroup { wgpu_bind_group }.into()
1303 }
1304
1305 fn create_pipeline_layout(
1306 &self,
1307 desc: &crate::PipelineLayoutDescriptor<'_>,
1308 ) -> dispatch::DispatchPipelineLayout {
1309 assert!(
1312 desc.bind_group_layouts.len() <= wgc::MAX_BIND_GROUPS,
1313 "Bind group layout count {} exceeds device bind group limit {}",
1314 desc.bind_group_layouts.len(),
1315 wgc::MAX_BIND_GROUPS
1316 );
1317
1318 let temp_layouts = desc
1319 .bind_group_layouts
1320 .iter()
1321 .map(|bgl| bgl.map(|bgl| bgl.inner.as_core().wgpu_bind_group_layout.clone()))
1322 .collect::<ArrayVec<_, { wgc::MAX_BIND_GROUPS }>>();
1323 let descriptor = wgc::binding_model::PipelineLayoutDescriptor {
1324 label: desc.label.map(Borrowed),
1325 bind_group_layouts: Borrowed(&temp_layouts),
1326 immediate_size: desc.immediate_size,
1327 };
1328
1329 let (wgpu_pipeline_layout, error) = self.wgpu_device.create_pipeline_layout(&descriptor);
1330 if let Some(cause) = error {
1331 self.context.handle_error(
1332 &self.error_sink,
1333 cause,
1334 desc.label,
1335 "Device::create_pipeline_layout",
1336 );
1337 }
1338 CorePipelineLayout {
1339 wgpu_pipeline_layout,
1340 }
1341 .into()
1342 }
1343
1344 fn create_render_pipeline(
1345 &self,
1346 desc: &crate::RenderPipelineDescriptor<'_>,
1347 ) -> dispatch::DispatchRenderPipeline {
1348 use wgc::pipeline as pipe;
1349
1350 let vertex_buffers: ArrayVec<_, { wgc::MAX_VERTEX_BUFFERS }> = desc
1351 .vertex
1352 .buffers
1353 .iter()
1354 .map(|vbuf| {
1355 vbuf.as_ref().map(|vbuf| pipe::VertexBufferLayout {
1356 array_stride: vbuf.array_stride,
1357 step_mode: vbuf.step_mode,
1358 attributes: Borrowed(vbuf.attributes),
1359 })
1360 })
1361 .collect();
1362
1363 let vert_constants = desc
1364 .vertex
1365 .compilation_options
1366 .constants
1367 .iter()
1368 .map(|&(key, value)| (String::from(key), value))
1369 .collect();
1370
1371 let descriptor = pipe::ResolvedGeneralRenderPipelineDescriptor {
1372 label: desc.label.map(Borrowed),
1373 layout: desc
1374 .layout
1375 .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1376 vertex: wgc::pipeline::RenderPipelineVertexProcessor::Vertex(pipe::VertexState {
1377 stage: pipe::ProgrammableStageDescriptor {
1378 module: desc
1379 .vertex
1380 .module
1381 .inner
1382 .as_core()
1383 .wgpu_shader_module
1384 .clone(),
1385 entry_point: desc.vertex.entry_point.map(Borrowed),
1386 constants: vert_constants,
1387 zero_initialize_workgroup_memory: desc
1388 .vertex
1389 .compilation_options
1390 .zero_initialize_workgroup_memory,
1391 },
1392 buffers: Borrowed(&vertex_buffers),
1393 }),
1394 primitive: desc.primitive,
1395 depth_stencil: desc.depth_stencil.clone(),
1396 multisample: desc.multisample,
1397 fragment: desc.fragment.as_ref().map(|frag| {
1398 let frag_constants = frag
1399 .compilation_options
1400 .constants
1401 .iter()
1402 .map(|&(key, value)| (String::from(key), value))
1403 .collect();
1404 pipe::FragmentState {
1405 stage: pipe::ProgrammableStageDescriptor {
1406 module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1407 entry_point: frag.entry_point.map(Borrowed),
1408 constants: frag_constants,
1409 zero_initialize_workgroup_memory: frag
1410 .compilation_options
1411 .zero_initialize_workgroup_memory,
1412 },
1413 targets: Borrowed(frag.targets),
1414 }
1415 }),
1416 multiview_mask: desc.multiview_mask,
1417 cache: desc
1418 .cache
1419 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1420 };
1421
1422 let (wgpu_render_pipeline, error) = self.wgpu_device.create_render_pipeline(descriptor);
1423 if let Some(cause) = error {
1424 if let wgc::pipeline::CreateRenderPipelineError::Internal { stage, ref error } = cause {
1425 log::error!("Shader translation error for stage {stage:?}: {error}");
1426 log::error!("Please report it to https://github.com/gfx-rs/wgpu");
1427 }
1428 self.context.handle_error(
1429 &self.error_sink,
1430 cause,
1431 desc.label,
1432 "Device::create_render_pipeline",
1433 );
1434 }
1435 CoreRenderPipeline {
1436 context: self.context.clone(),
1437 wgpu_render_pipeline,
1438 error_sink: Arc::clone(&self.error_sink),
1439 }
1440 .into()
1441 }
1442
1443 fn create_mesh_pipeline(
1444 &self,
1445 desc: &crate::MeshPipelineDescriptor<'_>,
1446 ) -> dispatch::DispatchRenderPipeline {
1447 use wgc::pipeline as pipe;
1448
1449 let mesh_constants = desc
1450 .mesh
1451 .compilation_options
1452 .constants
1453 .iter()
1454 .map(|&(key, value)| (String::from(key), value))
1455 .collect();
1456 let descriptor = pipe::MeshPipelineDescriptor {
1457 label: desc.label.map(Borrowed),
1458 task: desc.task.as_ref().map(|task| {
1459 let task_constants = task
1460 .compilation_options
1461 .constants
1462 .iter()
1463 .map(|&(key, value)| (String::from(key), value))
1464 .collect();
1465 pipe::TaskState {
1466 stage: pipe::ProgrammableStageDescriptor {
1467 module: task.module.inner.as_core().wgpu_shader_module.clone(),
1468 entry_point: task.entry_point.map(Borrowed),
1469 constants: task_constants,
1470 zero_initialize_workgroup_memory: desc
1471 .mesh
1472 .compilation_options
1473 .zero_initialize_workgroup_memory,
1474 },
1475 }
1476 }),
1477 mesh: pipe::MeshState {
1478 stage: pipe::ProgrammableStageDescriptor {
1479 module: desc.mesh.module.inner.as_core().wgpu_shader_module.clone(),
1480 entry_point: desc.mesh.entry_point.map(Borrowed),
1481 constants: mesh_constants,
1482 zero_initialize_workgroup_memory: desc
1483 .mesh
1484 .compilation_options
1485 .zero_initialize_workgroup_memory,
1486 },
1487 },
1488 layout: desc
1489 .layout
1490 .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1491 primitive: desc.primitive,
1492 depth_stencil: desc.depth_stencil.clone(),
1493 multisample: desc.multisample,
1494 fragment: desc.fragment.as_ref().map(|frag| {
1495 let frag_constants = frag
1496 .compilation_options
1497 .constants
1498 .iter()
1499 .map(|&(key, value)| (String::from(key), value))
1500 .collect();
1501 pipe::FragmentState {
1502 stage: pipe::ProgrammableStageDescriptor {
1503 module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1504 entry_point: frag.entry_point.map(Borrowed),
1505 constants: frag_constants,
1506 zero_initialize_workgroup_memory: frag
1507 .compilation_options
1508 .zero_initialize_workgroup_memory,
1509 },
1510 targets: Borrowed(frag.targets),
1511 }
1512 }),
1513 multiview: desc.multiview,
1514 cache: desc
1515 .cache
1516 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1517 };
1518
1519 let (wgpu_render_pipeline, error) =
1520 self.wgpu_device.create_render_pipeline(descriptor.into());
1521 if let Some(cause) = error {
1522 if let wgc::pipeline::CreateRenderPipelineError::Internal { stage, ref error } = cause {
1523 log::error!("Shader translation error for stage {stage:?}: {error}");
1524 log::error!("Please report it to https://github.com/gfx-rs/wgpu");
1525 }
1526 self.context.handle_error(
1527 &self.error_sink,
1528 cause,
1529 desc.label,
1530 "Device::create_render_pipeline",
1531 );
1532 }
1533 CoreRenderPipeline {
1534 context: self.context.clone(),
1535 wgpu_render_pipeline,
1536 error_sink: Arc::clone(&self.error_sink),
1537 }
1538 .into()
1539 }
1540
1541 fn create_compute_pipeline(
1542 &self,
1543 desc: &crate::ComputePipelineDescriptor<'_>,
1544 ) -> dispatch::DispatchComputePipeline {
1545 use wgc::pipeline as pipe;
1546
1547 let constants = desc
1548 .compilation_options
1549 .constants
1550 .iter()
1551 .map(|&(key, value)| (String::from(key), value))
1552 .collect();
1553
1554 let descriptor = pipe::ComputePipelineDescriptor {
1555 label: desc.label.map(Borrowed),
1556 layout: desc
1557 .layout
1558 .map(|pll| pll.inner.as_core().wgpu_pipeline_layout.clone()),
1559 stage: pipe::ProgrammableStageDescriptor {
1560 module: desc.module.inner.as_core().wgpu_shader_module.clone(),
1561 entry_point: desc.entry_point.map(Borrowed),
1562 constants,
1563 zero_initialize_workgroup_memory: desc
1564 .compilation_options
1565 .zero_initialize_workgroup_memory,
1566 },
1567 cache: desc
1568 .cache
1569 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1570 };
1571
1572 let (wgpu_compute_pipeline, error) = self.wgpu_device.create_compute_pipeline(descriptor);
1573 if let Some(cause) = error {
1574 if let wgc::pipeline::CreateComputePipelineError::Internal(ref error) = cause {
1575 log::error!(
1576 "Shader translation error for stage {:?}: {}",
1577 wgt::ShaderStages::COMPUTE,
1578 error
1579 );
1580 log::error!("Please report it to https://github.com/gfx-rs/wgpu");
1581 }
1582 self.context.handle_error(
1583 &self.error_sink,
1584 cause,
1585 desc.label,
1586 "Device::create_compute_pipeline",
1587 );
1588 }
1589 CoreComputePipeline {
1590 context: self.context.clone(),
1591 wgpu_compute_pipeline,
1592 error_sink: Arc::clone(&self.error_sink),
1593 }
1594 .into()
1595 }
1596
1597 unsafe fn create_pipeline_cache(
1598 &self,
1599 desc: &crate::PipelineCacheDescriptor<'_>,
1600 ) -> dispatch::DispatchPipelineCache {
1601 use wgc::pipeline as pipe;
1602
1603 let descriptor = pipe::PipelineCacheDescriptor {
1604 label: desc.label.map(Borrowed),
1605 data: desc.data.map(Borrowed),
1606 fallback: desc.fallback,
1607 };
1608 let (wgpu_pipeline_cache, error) =
1609 unsafe { self.wgpu_device.create_pipeline_cache(&descriptor) };
1610 if let Some(cause) = error {
1611 self.context.handle_error(
1612 &self.error_sink,
1613 cause,
1614 desc.label,
1615 "Device::device_create_pipeline_cache_init",
1616 );
1617 }
1618 CorePipelineCache {
1619 wgpu_pipeline_cache,
1620 }
1621 .into()
1622 }
1623
1624 fn create_buffer(&self, desc: &crate::BufferDescriptor<'_>) -> dispatch::DispatchBuffer {
1625 let (wgpu_buffer, error) = self
1626 .wgpu_device
1627 .create_buffer(&desc.map_label(|l| l.map(Borrowed)));
1628 if let Some(cause) = error {
1629 self.context
1630 .handle_error(&self.error_sink, cause, desc.label, "Device::create_buffer");
1631 }
1632
1633 CoreBuffer {
1634 context: self.context.clone(),
1635 wgpu_buffer,
1636 error_sink: Arc::clone(&self.error_sink),
1637 }
1638 .into()
1639 }
1640
1641 fn create_texture(&self, desc: &crate::TextureDescriptor<'_>) -> dispatch::DispatchTexture {
1642 let wgt_desc = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
1643 let (wgpu_texture, error) = self.wgpu_device.create_texture(&wgt_desc);
1644 if let Some(cause) = error {
1645 self.context.handle_error(
1646 &self.error_sink,
1647 cause,
1648 desc.label,
1649 "Device::create_texture",
1650 );
1651 }
1652
1653 CoreTexture {
1654 context: self.context.clone(),
1655 wgpu_texture,
1656 error_sink: Arc::clone(&self.error_sink),
1657 }
1658 .into()
1659 }
1660
1661 fn create_external_texture(
1662 &self,
1663 desc: &crate::ExternalTextureDescriptor<'_>,
1664 planes: &[&crate::TextureView],
1665 ) -> dispatch::DispatchExternalTexture {
1666 let wgt_desc = desc.map_label(|l| l.map(Borrowed));
1667 let planes = planes
1668 .iter()
1669 .map(|plane| plane.inner.as_core().wgpu_texture_view.clone())
1670 .collect::<Vec<_>>();
1671 let (wgpu_external_texture, error) =
1672 self.wgpu_device.create_external_texture(&wgt_desc, &planes);
1673 if let Some(cause) = error {
1674 self.context.handle_error(
1675 &self.error_sink,
1676 cause,
1677 desc.label,
1678 "Device::create_external_texture",
1679 );
1680 }
1681
1682 CoreExternalTexture {
1683 wgpu_external_texture,
1684 }
1685 .into()
1686 }
1687
1688 fn create_blas(
1689 &self,
1690 desc: &crate::CreateBlasDescriptor<'_>,
1691 sizes: crate::BlasGeometrySizeDescriptors,
1692 ) -> (Option<u64>, dispatch::DispatchBlas) {
1693 let (wgpu_blas, error) = self
1694 .wgpu_device
1695 .create_blas(&desc.map_label(|l| l.map(Borrowed)), sizes);
1696 if let Some(cause) = error {
1697 self.context
1698 .handle_error(&self.error_sink, cause, desc.label, "Device::create_blas");
1699 }
1700 (
1701 wgpu_blas.handle(),
1702 CoreBlas {
1703 context: self.context.clone(),
1704 wgpu_blas,
1705 error_sink: Arc::clone(&self.error_sink),
1706 }
1707 .into(),
1708 )
1709 }
1710
1711 fn create_tlas(&self, desc: &crate::CreateTlasDescriptor<'_>) -> dispatch::DispatchTlas {
1712 let (wgpu_tlas, error) = self
1713 .wgpu_device
1714 .create_tlas(&desc.map_label(|l| l.map(Borrowed)));
1715 if let Some(cause) = error {
1716 self.context
1717 .handle_error(&self.error_sink, cause, desc.label, "Device::create_tlas");
1718 }
1719 CoreTlas {
1720 context: self.context.clone(),
1721 wgpu_tlas,
1722 }
1724 .into()
1725 }
1726
1727 fn create_sampler(&self, desc: &crate::SamplerDescriptor<'_>) -> dispatch::DispatchSampler {
1728 let descriptor = wgc::resource::SamplerDescriptor {
1729 label: desc.label.map(Borrowed),
1730 address_modes: [
1731 desc.address_mode_u,
1732 desc.address_mode_v,
1733 desc.address_mode_w,
1734 ],
1735 mag_filter: desc.mag_filter,
1736 min_filter: desc.min_filter,
1737 mipmap_filter: desc.mipmap_filter,
1738 lod_min_clamp: desc.lod_min_clamp,
1739 lod_max_clamp: desc.lod_max_clamp,
1740 compare: desc.compare,
1741 anisotropy_clamp: desc.anisotropy_clamp,
1742 border_color: desc.border_color,
1743 };
1744
1745 let (wgpu_sampler, error) = self.wgpu_device.create_sampler(&descriptor);
1746 if let Some(cause) = error {
1747 self.context.handle_error(
1748 &self.error_sink,
1749 cause,
1750 desc.label,
1751 "Device::create_sampler",
1752 );
1753 }
1754 CoreSampler { wgpu_sampler }.into()
1755 }
1756
1757 fn create_query_set(&self, desc: &crate::QuerySetDescriptor<'_>) -> dispatch::DispatchQuerySet {
1758 let (wgpu_query_set, error) = self
1759 .wgpu_device
1760 .create_query_set(&desc.map_label(|l| l.map(Borrowed)));
1761 if let Some(cause) = error {
1762 self.context
1763 .handle_error_nolabel(&self.error_sink, cause, "Device::create_query_set");
1764 }
1765 CoreQuerySet { wgpu_query_set }.into()
1766 }
1767
1768 fn create_command_encoder(
1769 &self,
1770 desc: &crate::CommandEncoderDescriptor<'_>,
1771 ) -> dispatch::DispatchCommandEncoder {
1772 let (wgpu_command_encoder, error) = self
1773 .wgpu_device
1774 .create_command_encoder(&desc.map_label(|l| l.map(Borrowed)));
1775 if let Some(cause) = error {
1776 self.context.handle_error(
1777 &self.error_sink,
1778 cause,
1779 desc.label,
1780 "Device::create_command_encoder",
1781 );
1782 }
1783
1784 CoreCommandEncoder {
1785 context: self.context.clone(),
1786 wgpu_command_encoder,
1787 error_sink: Arc::clone(&self.error_sink),
1788 }
1789 .into()
1790 }
1791
1792 fn create_render_bundle_encoder(
1793 &self,
1794 desc: &crate::RenderBundleEncoderDescriptor<'_>,
1795 ) -> dispatch::DispatchRenderBundleEncoder {
1796 let descriptor = wgc::command::RenderBundleEncoderDescriptor {
1797 label: desc.label.map(Borrowed),
1798 color_formats: Borrowed(desc.color_formats),
1799 depth_stencil: desc.depth_stencil,
1800 sample_count: desc.sample_count,
1801 multiview: desc.multiview,
1802 };
1803 let (encoder, error) = self.wgpu_device.create_render_bundle_encoder(&descriptor);
1804 if let Some(cause) = error {
1805 self.context.handle_error(
1806 &self.error_sink,
1807 cause,
1808 desc.label,
1809 "Device::create_render_bundle_encoder",
1810 );
1811 }
1812
1813 CoreRenderBundleEncoder {
1814 context: self.context.clone(),
1815 error_sink: Arc::clone(&self.error_sink),
1816 encoder,
1817 }
1818 .into()
1819 }
1820
1821 fn set_device_lost_callback(&self, device_lost_callback: dispatch::BoxDeviceLostCallback) {
1822 self.wgpu_device
1823 .set_device_lost_closure(device_lost_callback);
1824 }
1825
1826 fn on_uncaptured_error(&self, handler: Arc<dyn crate::UncapturedErrorHandler>) {
1827 let mut error_sink = self.error_sink.lock();
1828 error_sink.uncaptured_handler = Some(handler);
1829 }
1830
1831 fn push_error_scope(&self, filter: crate::ErrorFilter) -> u32 {
1832 let mut error_sink = self.error_sink.lock();
1833 let thread_id = thread_id::ThreadId::current();
1834 let scopes = error_sink.scopes.entry(thread_id).or_default();
1835 let index = scopes
1836 .len()
1837 .try_into()
1838 .expect("Greater than 2^32 nested error scopes");
1839 scopes.push(ErrorScope {
1840 error: None,
1841 filter,
1842 });
1843 index
1844 }
1845
1846 fn pop_error_scope(&self, index: u32) -> Pin<Box<dyn dispatch::PopErrorScopeFuture>> {
1847 let mut error_sink = self.error_sink.lock();
1848
1849 let is_panicking = crate::util::is_panicking();
1852 let thread_id = thread_id::ThreadId::current();
1853 let err = "Mismatched pop_error_scope call: no error scope for this thread. Error scopes are thread-local.";
1854 let scopes = match error_sink.scopes.get_mut(&thread_id) {
1855 Some(s) => s,
1856 None => {
1857 if !is_panicking {
1858 panic!("{err}");
1859 } else {
1860 return Box::pin(ready(None));
1861 }
1862 }
1863 };
1864 if scopes.is_empty() && !is_panicking {
1865 panic!("{err}");
1866 }
1867 if index as usize != scopes.len() - 1 && !is_panicking {
1868 panic!(
1869 "Mismatched pop_error_scope call: error scopes must be popped in reverse order."
1870 );
1871 }
1872
1873 let scope = match scopes.pop() {
1878 Some(s) => s,
1879 None if !is_panicking => unreachable!(),
1880 None => return Box::pin(ready(None)),
1881 };
1882
1883 Box::pin(ready(scope.error))
1884 }
1885
1886 unsafe fn start_graphics_debugger_capture(&self) {
1887 unsafe { self.wgpu_device.start_graphics_debugger_capture() };
1888 }
1889
1890 unsafe fn stop_graphics_debugger_capture(&self) {
1891 unsafe { self.wgpu_device.stop_graphics_debugger_capture() };
1892 }
1893
1894 fn poll(&self, poll_type: wgt::PollType<u64>) -> Result<crate::PollStatus, crate::PollError> {
1895 match self.wgpu_device.poll(poll_type) {
1896 Ok(status) => Ok(status),
1897 Err(err) => {
1898 if let Some(poll_error) = err.to_poll_error() {
1899 return Err(poll_error);
1900 }
1901
1902 self.context.handle_error_fatal(err, "Device::poll")
1903 }
1904 }
1905 }
1906
1907 fn get_internal_counters(&self) -> crate::InternalCounters {
1908 self.wgpu_device.get_internal_counters()
1909 }
1910
1911 fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
1912 self.wgpu_device.generate_allocator_report()
1913 }
1914
1915 fn destroy(&self) {
1916 self.wgpu_device.destroy();
1917 }
1918}
1919
1920impl Drop for CoreDevice {
1921 fn drop(&mut self) {}
1922}
1923
1924impl dispatch::QueueInterface for CoreQueue {
1925 fn write_buffer(
1926 &self,
1927 buffer: &dispatch::DispatchBuffer,
1928 offset: crate::BufferAddress,
1929 data: &[u8],
1930 ) {
1931 let buffer = buffer.as_core();
1932
1933 match self
1934 .wgpu_queue
1935 .write_buffer(buffer.wgpu_buffer.clone(), offset, data)
1936 {
1937 Ok(()) => (),
1938 Err(err) => {
1939 self.context
1940 .handle_error_nolabel(&self.error_sink, err, "Queue::write_buffer")
1941 }
1942 }
1943 }
1944
1945 fn create_staging_buffer(
1946 &self,
1947 size: crate::BufferSize,
1948 ) -> Option<dispatch::DispatchQueueWriteBuffer> {
1949 match self.wgpu_queue.create_staging_buffer(size) {
1950 Ok((wgpu_staging_buffer, ptr)) => Some(
1951 CoreQueueWriteBuffer {
1952 wgpu_staging_buffer,
1953 mapping: CoreBufferMappedRange {
1954 ptr,
1955 size: size.get() as usize,
1956 },
1957 }
1958 .into(),
1959 ),
1960 Err(err) => {
1961 self.context.handle_error_nolabel(
1962 &self.error_sink,
1963 err,
1964 "Queue::write_buffer_with",
1965 );
1966 None
1967 }
1968 }
1969 }
1970
1971 fn validate_write_buffer(
1972 &self,
1973 buffer: &dispatch::DispatchBuffer,
1974 offset: wgt::BufferAddress,
1975 size: wgt::BufferSize,
1976 ) -> Option<()> {
1977 let buffer = buffer.as_core();
1978
1979 match self
1980 .wgpu_queue
1981 .validate_write_buffer(buffer.wgpu_buffer.clone(), offset, size)
1982 {
1983 Ok(()) => Some(()),
1984 Err(err) => {
1985 self.context.handle_error_nolabel(
1986 &self.error_sink,
1987 err,
1988 "Queue::write_buffer_with",
1989 );
1990 None
1991 }
1992 }
1993 }
1994
1995 fn write_staging_buffer(
1996 &self,
1997 buffer: &dispatch::DispatchBuffer,
1998 offset: crate::BufferAddress,
1999 staging_buffer: dispatch::DispatchQueueWriteBuffer,
2000 ) {
2001 let buffer = buffer.as_core();
2002 let staging_buffer = {
2003 #[allow(
2004 clippy::allow_attributes,
2005 unreachable_patterns,
2006 reason = "features may be disabled"
2007 )]
2008 match staging_buffer {
2009 dispatch::DispatchQueueWriteBuffer::Core(value) => value,
2010 _ => panic!(concat!(
2011 stringify!(DispatchQueueWriteBuffer),
2012 " is not core"
2013 )),
2014 }
2015 };
2016
2017 match self.wgpu_queue.write_staging_buffer(
2018 buffer.wgpu_buffer.clone(),
2019 offset,
2020 staging_buffer.wgpu_staging_buffer,
2021 ) {
2022 Ok(()) => (),
2023 Err(err) => {
2024 self.context.handle_error_nolabel(
2025 &self.error_sink,
2026 err,
2027 "Queue::write_buffer_with",
2028 );
2029 }
2030 }
2031 }
2032
2033 fn write_texture(
2034 &self,
2035 texture: crate::TexelCopyTextureInfo<'_>,
2036 data: &[u8],
2037 data_layout: crate::TexelCopyBufferLayout,
2038 size: crate::Extent3d,
2039 ) {
2040 match self.wgpu_queue.write_texture(
2041 map_texture_copy_view(texture),
2042 data,
2043 &data_layout,
2044 &size,
2045 ) {
2046 Ok(()) => (),
2047 Err(err) => {
2048 self.context
2049 .handle_error_nolabel(&self.error_sink, err, "Queue::write_texture")
2050 }
2051 }
2052 }
2053
2054 #[cfg(web)]
2057 #[cfg_attr(not(webgl), expect(unused_variables))]
2058 fn copy_external_image_to_texture(
2059 &self,
2060 source: &crate::CopyExternalImageSourceInfo,
2061 dest: crate::CopyExternalImageDestInfo<&crate::api::Texture>,
2062 size: crate::Extent3d,
2063 ) {
2064 #[cfg(webgl)]
2065 match self.wgpu_queue.copy_external_image_to_texture(
2066 source,
2067 map_texture_tagged_copy_view(dest),
2068 size,
2069 ) {
2070 Ok(()) => (),
2071 Err(err) => self.context.handle_error_nolabel(
2072 &self.error_sink,
2073 err,
2074 "Queue::copy_external_image_to_texture",
2075 ),
2076 }
2077 }
2078
2079 fn submit(
2080 &self,
2081 command_buffers: &mut dyn Iterator<Item = dispatch::DispatchCommandBuffer>,
2082 ) -> u64 {
2083 let temp_command_buffers = command_buffers.collect::<SmallVec<[_; 4]>>();
2084 let command_buffers = temp_command_buffers
2085 .iter()
2086 .map(|cmdbuf| cmdbuf.as_core().wgpu_command_buffer.clone())
2087 .collect::<SmallVec<[_; 4]>>();
2088
2089 let index = match self.wgpu_queue.submit(&command_buffers) {
2090 Ok(index) => index,
2091 Err((index, err)) => {
2092 self.context
2093 .handle_error_nolabel(&self.error_sink, err, "Queue::submit");
2094 index
2095 }
2096 };
2097
2098 drop(temp_command_buffers);
2099
2100 index
2101 }
2102
2103 fn get_timestamp_period(&self) -> f32 {
2104 self.wgpu_queue.get_timestamp_period()
2105 }
2106
2107 fn on_submitted_work_done(&self, callback: dispatch::BoxSubmittedWorkDoneCallback) {
2108 self.wgpu_queue.on_submitted_work_done(callback);
2109 }
2110
2111 fn compact_blas(&self, blas: &dispatch::DispatchBlas) -> (Option<u64>, dispatch::DispatchBlas) {
2112 let (wgpu_blas, error) = self.wgpu_queue.compact_blas(&blas.as_core().wgpu_blas);
2113
2114 if let Some(cause) = error {
2115 self.context
2116 .handle_error_nolabel(&self.error_sink, cause, "Queue::compact_blas");
2117 }
2118 (
2119 wgpu_blas.handle(),
2120 CoreBlas {
2121 context: self.context.clone(),
2122 wgpu_blas,
2123 error_sink: Arc::clone(&self.error_sink),
2124 }
2125 .into(),
2126 )
2127 }
2128
2129 fn present(&self, detail: &dispatch::DispatchSurfaceOutputDetail) {
2130 let detail = detail.as_core();
2131 match detail.wgpu_surface.present() {
2132 Ok(_status) => (),
2133 Err(err) => {
2134 self.context
2135 .handle_error_nolabel(&self.error_sink, err, "Queue::present");
2136 }
2137 }
2138 }
2139}
2140
2141impl dispatch::ShaderModuleInterface for CoreShaderModule {
2142 fn get_compilation_info(&self) -> Pin<Box<dyn dispatch::ShaderCompilationInfoFuture>> {
2143 Box::pin(ready(self.compilation_info.clone()))
2144 }
2145}
2146
2147impl dispatch::BindGroupLayoutInterface for CoreBindGroupLayout {}
2148
2149impl dispatch::BindGroupInterface for CoreBindGroup {}
2150
2151impl dispatch::TextureViewInterface for CoreTextureView {}
2152
2153impl dispatch::ExternalTextureInterface for CoreExternalTexture {
2154 fn destroy(&self) {
2155 self.wgpu_external_texture.destroy();
2156 }
2157}
2158
2159impl dispatch::SamplerInterface for CoreSampler {}
2160
2161impl dispatch::BufferInterface for CoreBuffer {
2162 fn map_async(
2163 &self,
2164 mode: crate::MapMode,
2165 range: Range<crate::BufferAddress>,
2166 callback: dispatch::BufferMapCallback,
2167 ) {
2168 let operation = wgc::resource::BufferMapOperation {
2169 host: match mode {
2170 MapMode::Read => wgc::device::HostMap::Read,
2171 MapMode::Write => wgc::device::HostMap::Write,
2172 },
2173 callback: Some(Box::new(|status| {
2174 let res = status.map_err(|_| crate::BufferAsyncError);
2175 callback(res);
2176 })),
2177 };
2178
2179 match self
2180 .wgpu_buffer
2181 .map_async(range.start, Some(range.end - range.start), operation)
2182 {
2183 Ok(_) => (),
2184 Err(cause) => {
2185 self.context
2186 .handle_error_nolabel(&self.error_sink, cause, "Buffer::map_async")
2187 }
2188 }
2189 }
2190
2191 fn get_mapped_range(
2192 &self,
2193 sub_range: Range<crate::BufferAddress>,
2194 ) -> Result<dispatch::DispatchBufferMappedRange, crate::MapRangeError> {
2195 let size = sub_range.end - sub_range.start;
2196 self.wgpu_buffer
2197 .get_mapped_range(sub_range.start, Some(size))
2198 .map(|(ptr, size)| {
2199 CoreBufferMappedRange {
2200 ptr,
2201 size: size as usize,
2202 }
2203 .into()
2204 })
2205 .map_err(|err| crate::MapRangeError(self.context.format_error(&err)))
2206 }
2207
2208 fn unmap(&self) {
2209 match self.wgpu_buffer.unmap() {
2210 Ok(()) => (),
2211 Err(cause) => {
2212 self.context
2213 .handle_error_nolabel(&self.error_sink, cause, "Buffer::buffer_unmap")
2214 }
2215 }
2216 }
2217
2218 fn destroy(&self) {
2219 self.wgpu_buffer.destroy();
2220 }
2221}
2222
2223impl dispatch::TextureInterface for CoreTexture {
2224 fn create_view(
2225 &self,
2226 desc: &crate::TextureViewDescriptor<'_>,
2227 ) -> dispatch::DispatchTextureView {
2228 let descriptor = wgc::resource::TextureViewDescriptor {
2229 label: desc.label.map(Borrowed),
2230 format: desc.format,
2231 dimension: desc.dimension,
2232 usage: desc.usage,
2233 range: wgt::ImageSubresourceRange {
2234 aspect: desc.aspect,
2235 base_mip_level: desc.base_mip_level,
2236 mip_level_count: desc.mip_level_count,
2237 base_array_layer: desc.base_array_layer,
2238 array_layer_count: desc.array_layer_count,
2239 },
2240 };
2241 let (wgpu_texture_view, error) = self.wgpu_texture.create_view(&descriptor);
2242 if let Some(cause) = error {
2243 self.context
2244 .handle_error(&self.error_sink, cause, desc.label, "Texture::create_view");
2245 }
2246 CoreTextureView {
2247 context: self.context.clone(),
2248 wgpu_texture_view,
2249 }
2250 .into()
2251 }
2252
2253 fn destroy(&self) {
2254 self.wgpu_texture.destroy();
2255 }
2256}
2257
2258impl dispatch::BlasInterface for CoreBlas {
2259 fn prepare_compact_async(&self, callback: BlasCompactCallback) {
2260 let callback: Option<wgc::resource::BlasCompactCallback> =
2261 Some(Box::new(|status: BlasPrepareCompactResult| {
2262 let res = status.map_err(|_| crate::BlasAsyncError);
2263 callback(res);
2264 }));
2265
2266 match self.wgpu_blas.prepare_compact_async(callback) {
2267 Ok(_) => (),
2268 Err(cause) => self.context.handle_error_nolabel(
2269 &self.error_sink,
2270 cause,
2271 "Blas::prepare_compact_async",
2272 ),
2273 }
2274 }
2275
2276 fn ready_for_compaction(&self) -> bool {
2277 match self.wgpu_blas.ready_for_compaction() {
2278 Ok(ready) => ready,
2279 Err(cause) => {
2280 self.context.handle_error_nolabel(
2281 &self.error_sink,
2282 cause,
2283 "Blas::ready_for_compaction",
2284 );
2285 false
2287 }
2288 }
2289 }
2290}
2291
2292impl dispatch::TlasInterface for CoreTlas {}
2293
2294impl dispatch::QuerySetInterface for CoreQuerySet {
2295 fn destroy(&self) {
2296 self.wgpu_query_set.destroy();
2297 }
2298}
2299
2300impl dispatch::PipelineLayoutInterface for CorePipelineLayout {}
2301
2302impl dispatch::RenderPipelineInterface for CoreRenderPipeline {
2303 fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
2304 let (wgpu_bind_group_layout, error) =
2305 self.wgpu_render_pipeline.get_bind_group_layout(index);
2306 if let Some(err) = error {
2307 self.context.handle_error_nolabel(
2308 &self.error_sink,
2309 err,
2310 "RenderPipeline::get_bind_group_layout",
2311 )
2312 }
2313 CoreBindGroupLayout {
2314 wgpu_bind_group_layout,
2315 }
2316 .into()
2317 }
2318}
2319
2320impl dispatch::ComputePipelineInterface for CoreComputePipeline {
2321 fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
2322 let (wgpu_bind_group_layout, error) =
2323 self.wgpu_compute_pipeline.get_bind_group_layout(index);
2324 if let Some(err) = error {
2325 self.context.handle_error_nolabel(
2326 &self.error_sink,
2327 err,
2328 "ComputePipeline::get_bind_group_layout",
2329 )
2330 }
2331 CoreBindGroupLayout {
2332 wgpu_bind_group_layout,
2333 }
2334 .into()
2335 }
2336}
2337
2338impl dispatch::PipelineCacheInterface for CorePipelineCache {
2339 fn get_data(&self) -> Option<Vec<u8>> {
2340 self.wgpu_pipeline_cache.get_data()
2341 }
2342}
2343
2344impl dispatch::CommandEncoderInterface for CoreCommandEncoder {
2345 fn copy_buffer_to_buffer(
2346 &self,
2347 source: &dispatch::DispatchBuffer,
2348 source_offset: crate::BufferAddress,
2349 destination: &dispatch::DispatchBuffer,
2350 destination_offset: crate::BufferAddress,
2351 copy_size: Option<crate::BufferAddress>,
2352 ) {
2353 let source = source.as_core();
2354 let destination = destination.as_core();
2355
2356 if let Err(cause) = self.wgpu_command_encoder.copy_buffer_to_buffer(
2357 source.wgpu_buffer.clone(),
2358 source_offset,
2359 destination.wgpu_buffer.clone(),
2360 destination_offset,
2361 copy_size,
2362 ) {
2363 self.context.handle_error_nolabel(
2364 &self.error_sink,
2365 cause,
2366 "CommandEncoder::copy_buffer_to_buffer",
2367 );
2368 }
2369 }
2370
2371 fn copy_buffer_to_texture(
2372 &self,
2373 source: crate::TexelCopyBufferInfo<'_>,
2374 destination: crate::TexelCopyTextureInfo<'_>,
2375 copy_size: crate::Extent3d,
2376 ) {
2377 if let Err(cause) = self.wgpu_command_encoder.copy_buffer_to_texture(
2378 &map_buffer_copy_view(source),
2379 &map_texture_copy_view(destination),
2380 ©_size,
2381 ) {
2382 self.context.handle_error_nolabel(
2383 &self.error_sink,
2384 cause,
2385 "CommandEncoder::copy_buffer_to_texture",
2386 );
2387 }
2388 }
2389
2390 fn copy_texture_to_buffer(
2391 &self,
2392 source: crate::TexelCopyTextureInfo<'_>,
2393 destination: crate::TexelCopyBufferInfo<'_>,
2394 copy_size: crate::Extent3d,
2395 ) {
2396 if let Err(cause) = self.wgpu_command_encoder.copy_texture_to_buffer(
2397 &map_texture_copy_view(source),
2398 &map_buffer_copy_view(destination),
2399 ©_size,
2400 ) {
2401 self.context.handle_error_nolabel(
2402 &self.error_sink,
2403 cause,
2404 "CommandEncoder::copy_texture_to_buffer",
2405 );
2406 }
2407 }
2408
2409 fn copy_texture_to_texture(
2410 &self,
2411 source: crate::TexelCopyTextureInfo<'_>,
2412 destination: crate::TexelCopyTextureInfo<'_>,
2413 copy_size: crate::Extent3d,
2414 ) {
2415 if let Err(cause) = self.wgpu_command_encoder.copy_texture_to_texture(
2416 &map_texture_copy_view(source),
2417 &map_texture_copy_view(destination),
2418 ©_size,
2419 ) {
2420 self.context.handle_error_nolabel(
2421 &self.error_sink,
2422 cause,
2423 "CommandEncoder::copy_texture_to_texture",
2424 );
2425 }
2426 }
2427
2428 fn begin_compute_pass(
2429 &self,
2430 desc: &crate::ComputePassDescriptor<'_>,
2431 ) -> dispatch::DispatchComputePass {
2432 let timestamp_writes =
2433 desc.timestamp_writes
2434 .as_ref()
2435 .map(|tw| wgc::command::PassTimestampWrites {
2436 query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
2437 beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
2438 end_of_pass_write_index: tw.end_of_pass_write_index,
2439 });
2440
2441 let (pass, err) =
2442 self.wgpu_command_encoder
2443 .begin_compute_pass(&wgc::command::ComputePassDescriptor {
2444 label: desc.label.map(Borrowed),
2445 timestamp_writes,
2446 });
2447
2448 if let Some(cause) = err {
2449 self.context.handle_error(
2450 &self.error_sink,
2451 cause,
2452 desc.label,
2453 "CommandEncoder::begin_compute_pass",
2454 );
2455 }
2456
2457 CoreComputePass {
2458 context: self.context.clone(),
2459 pass,
2460 error_sink: self.error_sink.clone(),
2461 id: crate::cmp::Identifier::create(),
2462 }
2463 .into()
2464 }
2465
2466 fn begin_render_pass(
2467 &self,
2468 desc: &crate::RenderPassDescriptor<'_>,
2469 ) -> dispatch::DispatchRenderPass {
2470 let colors = desc
2471 .color_attachments
2472 .iter()
2473 .map(|ca| {
2474 ca.as_ref()
2475 .map(|at| wgc::command::RenderPassColorAttachment {
2476 view: at.view.inner.as_core().wgpu_texture_view.clone(),
2477 depth_slice: at.depth_slice,
2478 resolve_target: at
2479 .resolve_target
2480 .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
2481 load_op: at.ops.load,
2482 store_op: at.ops.store,
2483 })
2484 })
2485 .collect::<Vec<_>>();
2486
2487 let depth_stencil = desc.depth_stencil_attachment.as_ref().map(|dsa| {
2488 wgc::command::RenderPassDepthStencilAttachment {
2489 view: dsa.view.inner.as_core().wgpu_texture_view.clone(),
2490 depth: map_pass_channel(dsa.depth_ops.as_ref()),
2491 stencil: map_pass_channel(dsa.stencil_ops.as_ref()),
2492 }
2493 });
2494
2495 let timestamp_writes =
2496 desc.timestamp_writes
2497 .as_ref()
2498 .map(|tw| wgc::command::PassTimestampWrites {
2499 query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
2500 beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
2501 end_of_pass_write_index: tw.end_of_pass_write_index,
2502 });
2503
2504 let (pass, err) = self.wgpu_command_encoder.begin_render_pass(
2505 wgc::command::ResolvedRenderPassDescriptor {
2506 label: desc.label.map(Borrowed),
2507 timestamp_writes,
2508 color_attachments: Borrowed(&colors),
2509 depth_stencil_attachment: depth_stencil,
2510 occlusion_query_set: desc
2511 .occlusion_query_set
2512 .map(|qs| qs.inner.as_core().wgpu_query_set.clone()),
2513 multiview_mask: desc.multiview_mask,
2514 },
2515 );
2516
2517 if let Some(cause) = err {
2518 self.context.handle_error(
2519 &self.error_sink,
2520 cause,
2521 desc.label,
2522 "CommandEncoder::begin_render_pass",
2523 );
2524 }
2525
2526 CoreRenderPass {
2527 context: self.context.clone(),
2528 pass,
2529 error_sink: self.error_sink.clone(),
2530 id: crate::cmp::Identifier::create(),
2531 }
2532 .into()
2533 }
2534
2535 fn finish(&mut self) -> dispatch::DispatchCommandBuffer {
2536 let descriptor = wgt::CommandBufferDescriptor::default();
2537 let (wgpu_command_buffer, opt_label_and_error) =
2538 self.wgpu_command_encoder.finish(&descriptor);
2539 if let Some((label, cause)) = opt_label_and_error {
2540 self.context
2541 .handle_error(&self.error_sink, cause, Some(&label), "a CommandEncoder");
2542 }
2543 CoreCommandBuffer {
2544 context: self.context.clone(),
2545 wgpu_command_buffer,
2546 }
2547 .into()
2548 }
2549
2550 fn clear_texture(
2551 &self,
2552 texture: &dispatch::DispatchTexture,
2553 subresource_range: &crate::ImageSubresourceRange,
2554 ) {
2555 let texture = texture.as_core();
2556
2557 if let Err(cause) = self
2558 .wgpu_command_encoder
2559 .clear_texture(texture.wgpu_texture.clone(), subresource_range)
2560 {
2561 self.context.handle_error_nolabel(
2562 &self.error_sink,
2563 cause,
2564 "CommandEncoder::clear_texture",
2565 );
2566 }
2567 }
2568
2569 fn clear_buffer(
2570 &self,
2571 buffer: &dispatch::DispatchBuffer,
2572 offset: crate::BufferAddress,
2573 size: Option<crate::BufferAddress>,
2574 ) {
2575 let buffer = buffer.as_core();
2576
2577 if let Err(cause) =
2578 self.wgpu_command_encoder
2579 .clear_buffer(buffer.wgpu_buffer.clone(), offset, size)
2580 {
2581 self.context.handle_error_nolabel(
2582 &self.error_sink,
2583 cause,
2584 "CommandEncoder::fill_buffer",
2585 );
2586 }
2587 }
2588
2589 fn insert_debug_marker(&self, label: &str) {
2590 if let Err(cause) = self.wgpu_command_encoder.insert_debug_marker(label) {
2591 self.context.handle_error_nolabel(
2592 &self.error_sink,
2593 cause,
2594 "CommandEncoder::insert_debug_marker",
2595 );
2596 }
2597 }
2598
2599 fn push_debug_group(&self, label: &str) {
2600 if let Err(cause) = self.wgpu_command_encoder.push_debug_group(label) {
2601 self.context.handle_error_nolabel(
2602 &self.error_sink,
2603 cause,
2604 "CommandEncoder::push_debug_group",
2605 );
2606 }
2607 }
2608
2609 fn pop_debug_group(&self) {
2610 if let Err(cause) = self.wgpu_command_encoder.pop_debug_group() {
2611 self.context.handle_error_nolabel(
2612 &self.error_sink,
2613 cause,
2614 "CommandEncoder::pop_debug_group",
2615 );
2616 }
2617 }
2618
2619 fn write_timestamp(&self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2620 let query_set = query_set.as_core();
2621
2622 if let Err(cause) = self
2623 .wgpu_command_encoder
2624 .write_timestamp(query_set.wgpu_query_set.clone(), query_index)
2625 {
2626 self.context.handle_error_nolabel(
2627 &self.error_sink,
2628 cause,
2629 "CommandEncoder::write_timestamp",
2630 );
2631 }
2632 }
2633
2634 fn resolve_query_set(
2635 &self,
2636 query_set: &dispatch::DispatchQuerySet,
2637 first_query: u32,
2638 query_count: u32,
2639 destination: &dispatch::DispatchBuffer,
2640 destination_offset: crate::BufferAddress,
2641 ) {
2642 let query_set = query_set.as_core();
2643 let destination = destination.as_core();
2644
2645 if let Err(cause) = self.wgpu_command_encoder.resolve_query_set(
2646 query_set.wgpu_query_set.clone(),
2647 first_query,
2648 query_count,
2649 destination.wgpu_buffer.clone(),
2650 destination_offset,
2651 ) {
2652 self.context.handle_error_nolabel(
2653 &self.error_sink,
2654 cause,
2655 "CommandEncoder::resolve_query_set",
2656 );
2657 }
2658 }
2659
2660 fn mark_acceleration_structures_built<'a>(
2661 &self,
2662 blas: &mut dyn Iterator<Item = &'a Blas>,
2663 tlas: &mut dyn Iterator<Item = &'a Tlas>,
2664 ) {
2665 let blas = blas
2666 .map(|b| b.inner.as_core().wgpu_blas.clone())
2667 .collect::<SmallVec<[_; 4]>>();
2668 let tlas = tlas
2669 .map(|t| t.inner.as_core().wgpu_tlas.clone())
2670 .collect::<SmallVec<[_; 4]>>();
2671 if let Err(cause) = self
2672 .wgpu_command_encoder
2673 .mark_acceleration_structures_built(&blas, &tlas)
2674 {
2675 self.context.handle_error_nolabel(
2676 &self.error_sink,
2677 cause,
2678 "CommandEncoder::build_acceleration_structures_unsafe_tlas",
2679 );
2680 }
2681 }
2682
2683 fn build_acceleration_structures<'a>(
2684 &self,
2685 blas: &mut dyn Iterator<Item = &'a crate::BlasBuildEntry<'a>>,
2686 tlas: &mut dyn Iterator<Item = &'a crate::Tlas>,
2687 ) {
2688 let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| {
2689 let geometries = match e.geometry {
2690 crate::BlasGeometries::TriangleGeometries(ref triangle_geometries) => {
2691 let iter = triangle_geometries.iter().map(|tg| {
2692 wgc::ray_tracing::BlasTriangleGeometry {
2693 vertex_buffer: tg.vertex_buffer.inner.as_core().wgpu_buffer.clone(),
2694 index_buffer: tg
2695 .index_buffer
2696 .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2697 transform_buffer: tg
2698 .transform_buffer
2699 .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2700 size: tg.size,
2701 transform_buffer_offset: tg.transform_buffer_offset,
2702 first_vertex: tg.first_vertex,
2703 vertex_stride: tg.vertex_stride,
2704 first_index: tg.first_index,
2705 }
2706 });
2707 wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter))
2708 }
2709 crate::BlasGeometries::AabbGeometries(ref aabb_geometries) => {
2710 let iter =
2711 aabb_geometries
2712 .iter()
2713 .map(|ag| wgc::ray_tracing::BlasAabbGeometry {
2714 aabb_buffer: ag.aabb_buffer.inner.as_core().wgpu_buffer.clone(),
2715 stride: ag.stride,
2716 size: ag.size,
2717 primitive_offset: ag.primitive_offset,
2718 });
2719 wgc::ray_tracing::BlasGeometries::AabbGeometries(Box::new(iter))
2720 }
2721 };
2722 wgc::ray_tracing::BlasBuildEntry {
2723 blas: e.blas.inner.as_core().wgpu_blas.clone(),
2724 geometries,
2725 }
2726 });
2727
2728 let tlas = tlas.into_iter().map(|e| {
2729 let instances = e
2730 .instances
2731 .iter()
2732 .map(|instance: &Option<crate::TlasInstance>| {
2733 instance
2734 .as_ref()
2735 .map(|instance| wgc::ray_tracing::TlasInstance {
2736 blas: instance.blas.as_core().wgpu_blas.clone(),
2737 transform: &instance.transform,
2738 custom_data: instance.custom_data,
2739 mask: instance.mask,
2740 })
2741 });
2742 wgc::ray_tracing::TlasPackage {
2743 tlas: e.inner.as_core().wgpu_tlas.clone(),
2744 instances: Box::new(instances),
2745 lowest_unmodified: e.lowest_unmodified,
2746 }
2747 });
2748
2749 if let Err(cause) = self
2750 .wgpu_command_encoder
2751 .build_acceleration_structures(blas, tlas)
2752 {
2753 self.context.handle_error_nolabel(
2754 &self.error_sink,
2755 cause,
2756 "CommandEncoder::build_acceleration_structures_unsafe_tlas",
2757 );
2758 }
2759 }
2760
2761 fn transition_resources<'a>(
2762 &mut self,
2763 buffer_transitions: &mut dyn Iterator<
2764 Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2765 >,
2766 texture_transitions: &mut dyn Iterator<
2767 Item = wgt::TextureTransition<&'a dispatch::DispatchTexture>,
2768 >,
2769 ) {
2770 let result = self.wgpu_command_encoder.transition_resources(
2771 buffer_transitions.map(|t| wgt::BufferTransition {
2772 buffer: t.buffer.as_core().wgpu_buffer.clone(),
2773 state: t.state,
2774 }),
2775 texture_transitions.map(|t| wgt::TextureTransition {
2776 texture: t.texture.as_core().wgpu_texture.clone(),
2777 selector: t.selector.clone(),
2778 state: t.state,
2779 }),
2780 );
2781
2782 if let Err(cause) = result {
2783 self.context.handle_error_nolabel(
2784 &self.error_sink,
2785 cause,
2786 "CommandEncoder::transition_resources",
2787 );
2788 }
2789 }
2790}
2791
2792impl dispatch::CommandBufferInterface for CoreCommandBuffer {}
2793
2794impl dispatch::ComputePassInterface for CoreComputePass {
2795 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchComputePipeline) {
2796 let pipeline = pipeline.as_core();
2797
2798 if let Err(cause) = self
2799 .pass
2800 .set_pipeline(pipeline.wgpu_compute_pipeline.clone())
2801 {
2802 self.context.handle_error(
2803 &self.error_sink,
2804 cause,
2805 self.pass.label(),
2806 "ComputePass::set_pipeline",
2807 );
2808 }
2809 }
2810
2811 fn set_bind_group(
2812 &mut self,
2813 index: u32,
2814 bind_group: Option<&dispatch::DispatchBindGroup>,
2815 offsets: &[crate::DynamicOffset],
2816 ) {
2817 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2818
2819 if let Err(cause) = self.pass.set_bind_group(index, bg, offsets) {
2820 self.context.handle_error(
2821 &self.error_sink,
2822 cause,
2823 self.pass.label(),
2824 "ComputePass::set_bind_group",
2825 );
2826 }
2827 }
2828
2829 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2830 if let Err(cause) = self.pass.set_immediates(offset, data) {
2831 self.context.handle_error(
2832 &self.error_sink,
2833 cause,
2834 self.pass.label(),
2835 "ComputePass::set_immediates",
2836 );
2837 }
2838 }
2839
2840 fn insert_debug_marker(&mut self, label: &str) {
2841 if let Err(cause) = self.pass.insert_debug_marker(label, 0) {
2842 self.context.handle_error(
2843 &self.error_sink,
2844 cause,
2845 self.pass.label(),
2846 "ComputePass::insert_debug_marker",
2847 );
2848 }
2849 }
2850
2851 fn push_debug_group(&mut self, group_label: &str) {
2852 if let Err(cause) = self.pass.push_debug_group(group_label, 0) {
2853 self.context.handle_error(
2854 &self.error_sink,
2855 cause,
2856 self.pass.label(),
2857 "ComputePass::push_debug_group",
2858 );
2859 }
2860 }
2861
2862 fn pop_debug_group(&mut self) {
2863 if let Err(cause) = self.pass.pop_debug_group() {
2864 self.context.handle_error(
2865 &self.error_sink,
2866 cause,
2867 self.pass.label(),
2868 "ComputePass::pop_debug_group",
2869 );
2870 }
2871 }
2872
2873 fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2874 let query_set = query_set.as_core();
2875
2876 if let Err(cause) = self
2877 .pass
2878 .write_timestamp(query_set.wgpu_query_set.clone(), query_index)
2879 {
2880 self.context.handle_error(
2881 &self.error_sink,
2882 cause,
2883 self.pass.label(),
2884 "ComputePass::write_timestamp",
2885 );
2886 }
2887 }
2888
2889 fn begin_pipeline_statistics_query(
2890 &mut self,
2891 query_set: &dispatch::DispatchQuerySet,
2892 query_index: u32,
2893 ) {
2894 let query_set = query_set.as_core();
2895
2896 if let Err(cause) = self
2897 .pass
2898 .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index)
2899 {
2900 self.context.handle_error(
2901 &self.error_sink,
2902 cause,
2903 self.pass.label(),
2904 "ComputePass::begin_pipeline_statistics_query",
2905 );
2906 }
2907 }
2908
2909 fn end_pipeline_statistics_query(&mut self) {
2910 if let Err(cause) = self.pass.end_pipeline_statistics_query() {
2911 self.context.handle_error(
2912 &self.error_sink,
2913 cause,
2914 self.pass.label(),
2915 "ComputePass::end_pipeline_statistics_query",
2916 );
2917 }
2918 }
2919
2920 fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
2921 if let Err(cause) = self.pass.dispatch_workgroups(x, y, z) {
2922 self.context.handle_error(
2923 &self.error_sink,
2924 cause,
2925 self.pass.label(),
2926 "ComputePass::dispatch_workgroups",
2927 );
2928 }
2929 }
2930
2931 fn dispatch_workgroups_indirect(
2932 &mut self,
2933 indirect_buffer: &dispatch::DispatchBuffer,
2934 indirect_offset: crate::BufferAddress,
2935 ) {
2936 let indirect_buffer = indirect_buffer.as_core();
2937
2938 if let Err(cause) = self
2939 .pass
2940 .dispatch_workgroups_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset)
2941 {
2942 self.context.handle_error(
2943 &self.error_sink,
2944 cause,
2945 self.pass.label(),
2946 "ComputePass::dispatch_workgroups_indirect",
2947 );
2948 }
2949 }
2950
2951 fn transition_resources<'a>(
2952 &mut self,
2953 buffer_transitions: &mut dyn Iterator<
2954 Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2955 >,
2956 texture_transitions: &mut dyn Iterator<
2957 Item = wgt::TextureTransition<&'a dispatch::DispatchTextureView>,
2958 >,
2959 ) {
2960 let result = self.pass.transition_resources(
2961 buffer_transitions.map(|t| wgt::BufferTransition {
2962 buffer: t.buffer.as_core().wgpu_buffer.clone(),
2963 state: t.state,
2964 }),
2965 texture_transitions.map(|t| wgt::TextureTransition {
2966 texture: t.texture.as_core().wgpu_texture_view.clone(),
2967 selector: t.selector.clone(),
2968 state: t.state,
2969 }),
2970 );
2971
2972 if let Err(cause) = result {
2973 self.context.handle_error(
2974 &self.error_sink,
2975 cause,
2976 self.pass.label(),
2977 "ComputePass::transition_resources",
2978 );
2979 }
2980 }
2981}
2982
2983impl Drop for CoreComputePass {
2984 fn drop(&mut self) {
2985 if let Err(cause) = self.pass.end() {
2986 self.context.handle_error(
2987 &self.error_sink,
2988 cause,
2989 self.pass.label(),
2990 "ComputePass::end",
2991 );
2992 }
2993 }
2994}
2995
2996impl dispatch::RenderPassInterface for CoreRenderPass {
2997 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2998 let pipeline = pipeline.as_core();
2999
3000 if let Err(cause) = self
3001 .pass
3002 .set_pipeline(pipeline.wgpu_render_pipeline.clone())
3003 {
3004 self.context.handle_error(
3005 &self.error_sink,
3006 cause,
3007 self.pass.label(),
3008 "RenderPass::set_pipeline",
3009 );
3010 }
3011 }
3012
3013 fn set_bind_group(
3014 &mut self,
3015 index: u32,
3016 bind_group: Option<&dispatch::DispatchBindGroup>,
3017 offsets: &[crate::DynamicOffset],
3018 ) {
3019 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
3020
3021 if let Err(cause) = self.pass.set_bind_group(index, bg, offsets) {
3022 self.context.handle_error(
3023 &self.error_sink,
3024 cause,
3025 self.pass.label(),
3026 "RenderPass::set_bind_group",
3027 );
3028 }
3029 }
3030
3031 fn set_index_buffer(
3032 &mut self,
3033 buffer: &dispatch::DispatchBuffer,
3034 index_format: crate::IndexFormat,
3035 offset: crate::BufferAddress,
3036 size: Option<crate::BufferSize>,
3037 ) {
3038 let buffer = buffer.as_core();
3039
3040 if let Err(cause) =
3041 self.pass
3042 .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size)
3043 {
3044 self.context.handle_error(
3045 &self.error_sink,
3046 cause,
3047 self.pass.label(),
3048 "RenderPass::set_index_buffer",
3049 );
3050 }
3051 }
3052
3053 fn set_vertex_buffer(
3054 &mut self,
3055 slot: u32,
3056 buffer: Option<&dispatch::DispatchBuffer>,
3057 offset: crate::BufferAddress,
3058 size: Option<crate::BufferSize>,
3059 ) {
3060 let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
3061
3062 if let Err(cause) = self.pass.set_vertex_buffer(slot, buffer, offset, size) {
3063 self.context.handle_error(
3064 &self.error_sink,
3065 cause,
3066 self.pass.label(),
3067 "RenderPass::set_vertex_buffer",
3068 );
3069 }
3070 }
3071
3072 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3073 if let Err(cause) = self.pass.set_immediates(offset, data) {
3074 self.context.handle_error(
3075 &self.error_sink,
3076 cause,
3077 self.pass.label(),
3078 "RenderPass::set_immediates",
3079 );
3080 }
3081 }
3082
3083 fn set_blend_constant(&mut self, color: crate::Color) {
3084 if let Err(cause) = self.pass.set_blend_constant(color) {
3085 self.context.handle_error(
3086 &self.error_sink,
3087 cause,
3088 self.pass.label(),
3089 "RenderPass::set_blend_constant",
3090 );
3091 }
3092 }
3093
3094 fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
3095 if let Err(cause) = self.pass.set_scissor_rect(x, y, width, height) {
3096 self.context.handle_error(
3097 &self.error_sink,
3098 cause,
3099 self.pass.label(),
3100 "RenderPass::set_scissor_rect",
3101 );
3102 }
3103 }
3104
3105 fn set_viewport(
3106 &mut self,
3107 x: f32,
3108 y: f32,
3109 width: f32,
3110 height: f32,
3111 min_depth: f32,
3112 max_depth: f32,
3113 ) {
3114 if let Err(cause) = self
3115 .pass
3116 .set_viewport(x, y, width, height, min_depth, max_depth)
3117 {
3118 self.context.handle_error(
3119 &self.error_sink,
3120 cause,
3121 self.pass.label(),
3122 "RenderPass::set_viewport",
3123 );
3124 }
3125 }
3126
3127 fn set_stencil_reference(&mut self, reference: u32) {
3128 if let Err(cause) = self.pass.set_stencil_reference(reference) {
3129 self.context.handle_error(
3130 &self.error_sink,
3131 cause,
3132 self.pass.label(),
3133 "RenderPass::set_stencil_reference",
3134 );
3135 }
3136 }
3137
3138 fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
3139 if let Err(cause) = self.pass.draw(
3140 vertices.end - vertices.start,
3141 instances.end - instances.start,
3142 vertices.start,
3143 instances.start,
3144 ) {
3145 self.context.handle_error(
3146 &self.error_sink,
3147 cause,
3148 self.pass.label(),
3149 "RenderPass::draw",
3150 );
3151 }
3152 }
3153
3154 fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
3155 if let Err(cause) = self.pass.draw_indexed(
3156 indices.end - indices.start,
3157 instances.end - instances.start,
3158 indices.start,
3159 base_vertex,
3160 instances.start,
3161 ) {
3162 self.context.handle_error(
3163 &self.error_sink,
3164 cause,
3165 self.pass.label(),
3166 "RenderPass::draw_indexed",
3167 );
3168 }
3169 }
3170
3171 fn draw_mesh_tasks(&mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32) {
3172 if let Err(cause) = self
3173 .pass
3174 .draw_mesh_tasks(group_count_x, group_count_y, group_count_z)
3175 {
3176 self.context.handle_error(
3177 &self.error_sink,
3178 cause,
3179 self.pass.label(),
3180 "RenderPass::draw_mesh_tasks",
3181 );
3182 }
3183 }
3184
3185 fn draw_indirect(
3186 &mut self,
3187 indirect_buffer: &dispatch::DispatchBuffer,
3188 indirect_offset: crate::BufferAddress,
3189 ) {
3190 let indirect_buffer = indirect_buffer.as_core();
3191
3192 if let Err(cause) = self
3193 .pass
3194 .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset)
3195 {
3196 self.context.handle_error(
3197 &self.error_sink,
3198 cause,
3199 self.pass.label(),
3200 "RenderPass::draw_indirect",
3201 );
3202 }
3203 }
3204
3205 fn draw_indexed_indirect(
3206 &mut self,
3207 indirect_buffer: &dispatch::DispatchBuffer,
3208 indirect_offset: crate::BufferAddress,
3209 ) {
3210 let indirect_buffer = indirect_buffer.as_core();
3211
3212 if let Err(cause) = self
3213 .pass
3214 .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset)
3215 {
3216 self.context.handle_error(
3217 &self.error_sink,
3218 cause,
3219 self.pass.label(),
3220 "RenderPass::draw_indexed_indirect",
3221 );
3222 }
3223 }
3224
3225 fn draw_mesh_tasks_indirect(
3226 &mut self,
3227 indirect_buffer: &dispatch::DispatchBuffer,
3228 indirect_offset: crate::BufferAddress,
3229 ) {
3230 let indirect_buffer = indirect_buffer.as_core();
3231
3232 if let Err(cause) = self
3233 .pass
3234 .draw_mesh_tasks_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset)
3235 {
3236 self.context.handle_error(
3237 &self.error_sink,
3238 cause,
3239 self.pass.label(),
3240 "RenderPass::draw_mesh_tasks_indirect",
3241 );
3242 }
3243 }
3244
3245 fn multi_draw_indirect(
3246 &mut self,
3247 indirect_buffer: &dispatch::DispatchBuffer,
3248 indirect_offset: crate::BufferAddress,
3249 count: u32,
3250 ) {
3251 let indirect_buffer = indirect_buffer.as_core();
3252
3253 if let Err(cause) = self.pass.multi_draw_indirect(
3254 indirect_buffer.wgpu_buffer.clone(),
3255 indirect_offset,
3256 count,
3257 ) {
3258 self.context.handle_error(
3259 &self.error_sink,
3260 cause,
3261 self.pass.label(),
3262 "RenderPass::multi_draw_indirect",
3263 );
3264 }
3265 }
3266
3267 fn multi_draw_indexed_indirect(
3268 &mut self,
3269 indirect_buffer: &dispatch::DispatchBuffer,
3270 indirect_offset: crate::BufferAddress,
3271 count: u32,
3272 ) {
3273 let indirect_buffer = indirect_buffer.as_core();
3274
3275 if let Err(cause) = self.pass.multi_draw_indexed_indirect(
3276 indirect_buffer.wgpu_buffer.clone(),
3277 indirect_offset,
3278 count,
3279 ) {
3280 self.context.handle_error(
3281 &self.error_sink,
3282 cause,
3283 self.pass.label(),
3284 "RenderPass::multi_draw_indexed_indirect",
3285 );
3286 }
3287 }
3288
3289 fn multi_draw_mesh_tasks_indirect(
3290 &mut self,
3291 indirect_buffer: &dispatch::DispatchBuffer,
3292 indirect_offset: crate::BufferAddress,
3293 count: u32,
3294 ) {
3295 let indirect_buffer = indirect_buffer.as_core();
3296
3297 if let Err(cause) = self.pass.multi_draw_mesh_tasks_indirect(
3298 indirect_buffer.wgpu_buffer.clone(),
3299 indirect_offset,
3300 count,
3301 ) {
3302 self.context.handle_error(
3303 &self.error_sink,
3304 cause,
3305 self.pass.label(),
3306 "RenderPass::multi_draw_mesh_tasks_indirect",
3307 );
3308 }
3309 }
3310
3311 fn multi_draw_indirect_count(
3312 &mut self,
3313 indirect_buffer: &dispatch::DispatchBuffer,
3314 indirect_offset: crate::BufferAddress,
3315 count_buffer: &dispatch::DispatchBuffer,
3316 count_buffer_offset: crate::BufferAddress,
3317 max_count: u32,
3318 ) {
3319 let indirect_buffer = indirect_buffer.as_core();
3320 let count_buffer = count_buffer.as_core();
3321
3322 if let Err(cause) = self.pass.multi_draw_indirect_count(
3323 indirect_buffer.wgpu_buffer.clone(),
3324 indirect_offset,
3325 count_buffer.wgpu_buffer.clone(),
3326 count_buffer_offset,
3327 max_count,
3328 ) {
3329 self.context.handle_error(
3330 &self.error_sink,
3331 cause,
3332 self.pass.label(),
3333 "RenderPass::multi_draw_indirect_count",
3334 );
3335 }
3336 }
3337
3338 fn multi_draw_indexed_indirect_count(
3339 &mut self,
3340 indirect_buffer: &dispatch::DispatchBuffer,
3341 indirect_offset: crate::BufferAddress,
3342 count_buffer: &dispatch::DispatchBuffer,
3343 count_buffer_offset: crate::BufferAddress,
3344 max_count: u32,
3345 ) {
3346 let indirect_buffer = indirect_buffer.as_core();
3347 let count_buffer = count_buffer.as_core();
3348
3349 if let Err(cause) = self.pass.multi_draw_indexed_indirect_count(
3350 indirect_buffer.wgpu_buffer.clone(),
3351 indirect_offset,
3352 count_buffer.wgpu_buffer.clone(),
3353 count_buffer_offset,
3354 max_count,
3355 ) {
3356 self.context.handle_error(
3357 &self.error_sink,
3358 cause,
3359 self.pass.label(),
3360 "RenderPass::multi_draw_indexed_indirect_count",
3361 );
3362 }
3363 }
3364
3365 fn multi_draw_mesh_tasks_indirect_count(
3366 &mut self,
3367 indirect_buffer: &dispatch::DispatchBuffer,
3368 indirect_offset: crate::BufferAddress,
3369 count_buffer: &dispatch::DispatchBuffer,
3370 count_buffer_offset: crate::BufferAddress,
3371 max_count: u32,
3372 ) {
3373 let indirect_buffer = indirect_buffer.as_core();
3374 let count_buffer = count_buffer.as_core();
3375
3376 if let Err(cause) = self.pass.multi_draw_mesh_tasks_indirect_count(
3377 indirect_buffer.wgpu_buffer.clone(),
3378 indirect_offset,
3379 count_buffer.wgpu_buffer.clone(),
3380 count_buffer_offset,
3381 max_count,
3382 ) {
3383 self.context.handle_error(
3384 &self.error_sink,
3385 cause,
3386 self.pass.label(),
3387 "RenderPass::multi_draw_mesh_tasks_indirect_count",
3388 );
3389 }
3390 }
3391
3392 fn insert_debug_marker(&mut self, label: &str) {
3393 if let Err(cause) = self.pass.insert_debug_marker(label, 0) {
3394 self.context.handle_error(
3395 &self.error_sink,
3396 cause,
3397 self.pass.label(),
3398 "RenderPass::insert_debug_marker",
3399 );
3400 }
3401 }
3402
3403 fn push_debug_group(&mut self, group_label: &str) {
3404 if let Err(cause) = self.pass.push_debug_group(group_label, 0) {
3405 self.context.handle_error(
3406 &self.error_sink,
3407 cause,
3408 self.pass.label(),
3409 "RenderPass::push_debug_group",
3410 );
3411 }
3412 }
3413
3414 fn pop_debug_group(&mut self) {
3415 if let Err(cause) = self.pass.pop_debug_group() {
3416 self.context.handle_error(
3417 &self.error_sink,
3418 cause,
3419 self.pass.label(),
3420 "RenderPass::pop_debug_group",
3421 );
3422 }
3423 }
3424
3425 fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
3426 let query_set = query_set.as_core();
3427
3428 if let Err(cause) = self
3429 .pass
3430 .write_timestamp(query_set.wgpu_query_set.clone(), query_index)
3431 {
3432 self.context.handle_error(
3433 &self.error_sink,
3434 cause,
3435 self.pass.label(),
3436 "RenderPass::write_timestamp",
3437 );
3438 }
3439 }
3440
3441 fn begin_occlusion_query(&mut self, query_index: u32) {
3442 if let Err(cause) = self.pass.begin_occlusion_query(query_index) {
3443 self.context.handle_error(
3444 &self.error_sink,
3445 cause,
3446 self.pass.label(),
3447 "RenderPass::begin_occlusion_query",
3448 );
3449 }
3450 }
3451
3452 fn end_occlusion_query(&mut self) {
3453 if let Err(cause) = self.pass.end_occlusion_query() {
3454 self.context.handle_error(
3455 &self.error_sink,
3456 cause,
3457 self.pass.label(),
3458 "RenderPass::end_occlusion_query",
3459 );
3460 }
3461 }
3462
3463 fn begin_pipeline_statistics_query(
3464 &mut self,
3465 query_set: &dispatch::DispatchQuerySet,
3466 query_index: u32,
3467 ) {
3468 let query_set = query_set.as_core();
3469
3470 if let Err(cause) = self
3471 .pass
3472 .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index)
3473 {
3474 self.context.handle_error(
3475 &self.error_sink,
3476 cause,
3477 self.pass.label(),
3478 "RenderPass::begin_pipeline_statistics_query",
3479 );
3480 }
3481 }
3482
3483 fn end_pipeline_statistics_query(&mut self) {
3484 if let Err(cause) = self.pass.end_pipeline_statistics_query() {
3485 self.context.handle_error(
3486 &self.error_sink,
3487 cause,
3488 self.pass.label(),
3489 "RenderPass::end_pipeline_statistics_query",
3490 );
3491 }
3492 }
3493
3494 fn execute_bundles(
3495 &mut self,
3496 render_bundles: &mut dyn Iterator<Item = &dispatch::DispatchRenderBundle>,
3497 ) {
3498 let temp_render_bundles = render_bundles
3499 .map(|rb| rb.as_core().wgpu_render_bundle.clone())
3500 .collect::<SmallVec<[_; 4]>>();
3501 if let Err(cause) = self.pass.execute_bundles(&temp_render_bundles) {
3502 self.context.handle_error(
3503 &self.error_sink,
3504 cause,
3505 self.pass.label(),
3506 "RenderPass::execute_bundles",
3507 );
3508 }
3509 }
3510}
3511
3512impl Drop for CoreRenderPass {
3513 fn drop(&mut self) {
3514 if let Err(cause) = self.pass.end() {
3515 self.context.handle_error(
3516 &self.error_sink,
3517 cause,
3518 self.pass.label(),
3519 "RenderPass::end",
3520 );
3521 }
3522 }
3523}
3524
3525impl dispatch::RenderBundleEncoderInterface for CoreRenderBundleEncoder {
3526 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
3527 let pipeline = pipeline.as_core();
3528
3529 self.encoder
3530 .set_pipeline(pipeline.wgpu_render_pipeline.clone())
3531 .expect("RenderBundleEncoder should not have ended")
3532 }
3533
3534 fn set_bind_group(
3535 &mut self,
3536 index: u32,
3537 bind_group: Option<&dispatch::DispatchBindGroup>,
3538 offsets: &[crate::DynamicOffset],
3539 ) {
3540 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
3541
3542 self.encoder
3543 .set_bind_group(index, bg, offsets)
3544 .expect("RenderBundleEncoder should not have ended");
3545 }
3546
3547 fn set_index_buffer(
3548 &mut self,
3549 buffer: &dispatch::DispatchBuffer,
3550 index_format: crate::IndexFormat,
3551 offset: crate::BufferAddress,
3552 size: Option<crate::BufferSize>,
3553 ) {
3554 let buffer = buffer.as_core();
3555
3556 self.encoder
3557 .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size)
3558 .expect("RenderBundleEncoder should not have ended");
3559 }
3560
3561 fn set_vertex_buffer(
3562 &mut self,
3563 slot: u32,
3564 buffer: Option<&dispatch::DispatchBuffer>,
3565 offset: crate::BufferAddress,
3566 size: Option<crate::BufferSize>,
3567 ) {
3568 let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
3569
3570 self.encoder
3571 .set_vertex_buffer(slot, buffer, offset, size)
3572 .expect("RenderBundleEncoder should not have ended");
3573 }
3574
3575 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3576 if !data
3577 .len()
3578 .is_multiple_of(wgt::IMMEDIATE_DATA_ALIGNMENT as usize)
3579 {
3580 self.context.handle_error(
3581 &self.error_sink,
3582 wgc::binding_model::ImmediateUploadError::SizeUnaligned(data.len()),
3583 self.encoder.label(),
3584 "RenderBundleEncoder::set_immediates",
3585 );
3586 return;
3587 }
3588
3589 self.encoder
3590 .set_immediates(offset, data)
3591 .expect("RenderBundleEncoder should not have ended");
3592 }
3593
3594 fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
3595 self.encoder
3596 .draw(
3597 vertices.end - vertices.start,
3598 instances.end - instances.start,
3599 vertices.start,
3600 instances.start,
3601 )
3602 .expect("RenderBundleEncoder should not have ended");
3603 }
3604
3605 fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
3606 self.encoder
3607 .draw_indexed(
3608 indices.end - indices.start,
3609 instances.end - instances.start,
3610 indices.start,
3611 base_vertex,
3612 instances.start,
3613 )
3614 .expect("RenderBundleEncoder should not have ended");
3615 }
3616
3617 fn draw_indirect(
3618 &mut self,
3619 indirect_buffer: &dispatch::DispatchBuffer,
3620 indirect_offset: crate::BufferAddress,
3621 ) {
3622 let indirect_buffer = indirect_buffer.as_core();
3623
3624 self.encoder
3625 .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset)
3626 .expect("RenderBundleEncoder should not have ended");
3627 }
3628
3629 fn draw_indexed_indirect(
3630 &mut self,
3631 indirect_buffer: &dispatch::DispatchBuffer,
3632 indirect_offset: crate::BufferAddress,
3633 ) {
3634 let indirect_buffer = indirect_buffer.as_core();
3635
3636 self.encoder
3637 .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset)
3638 .expect("RenderBundleEncoder should not have ended");
3639 }
3640
3641 fn finish(mut self, desc: &crate::RenderBundleDescriptor<'_>) -> dispatch::DispatchRenderBundle
3642 where
3643 Self: Sized,
3644 {
3645 let label = self.encoder.label().map(alloc::string::ToString::to_string);
3646 let (wgpu_render_bundle, error) = self.encoder.finish(&desc.map_label(|l| l.map(Borrowed)));
3647 if let Some(err) = error {
3648 self.context.handle_error(
3649 &self.error_sink,
3650 err,
3651 label.as_deref(),
3652 "RenderBundleEncoder::finish",
3653 );
3654 }
3655 CoreRenderBundle { wgpu_render_bundle }.into()
3656 }
3657
3658 #[cfg(custom)]
3659 fn finish_boxed(
3660 self: Box<Self>,
3661 desc: &crate::RenderBundleDescriptor<'_>,
3662 ) -> dispatch::DispatchRenderBundle {
3663 (*self).finish(desc)
3664 }
3665}
3666
3667impl dispatch::RenderBundleInterface for CoreRenderBundle {}
3668
3669impl dispatch::SurfaceInterface for CoreSurface {
3670 fn get_capabilities(&self, adapter: &dispatch::DispatchAdapter) -> wgt::SurfaceCapabilities {
3671 let adapter = adapter.as_core();
3672
3673 self.wgpu_surface
3674 .get_capabilities(&adapter.wgpu_adapter)
3675 .unwrap_or_default()
3676 }
3677
3678 fn display_hdr_info(&self, adapter: &dispatch::DispatchAdapter) -> wgt::DisplayHdrInfo {
3679 let adapter = adapter.as_core();
3680
3681 self.wgpu_surface.display_hdr_info(&adapter.wgpu_adapter)
3682 }
3683
3684 fn configure(&self, device: &dispatch::DispatchDevice, config: &crate::SurfaceConfiguration) {
3685 let device = device.as_core();
3686
3687 let error = self.wgpu_surface.configure(&device.wgpu_device, config);
3688 if let Some(e) = error {
3689 self.context
3690 .handle_error_nolabel(&device.error_sink, e, "Surface::configure");
3691 } else {
3692 *self.configured_device.lock() = Some(device.wgpu_device.clone());
3693 *self.error_sink.lock() = Some(device.error_sink.clone());
3694 }
3695 }
3696
3697 fn get_current_texture(
3698 &self,
3699 ) -> (
3700 Option<dispatch::DispatchTexture>,
3701 crate::SurfaceStatus,
3702 dispatch::DispatchSurfaceOutputDetail,
3703 ) {
3704 let error_sink = if let Some(error_sink) = self.error_sink.lock().as_ref() {
3705 error_sink.clone()
3706 } else {
3707 Arc::new(Mutex::new(ErrorSinkRaw::new()))
3708 };
3709
3710 let output_detail = CoreSurfaceOutputDetail {
3711 context: self.context.clone(),
3712 wgpu_surface: self.wgpu_surface.clone(),
3713 error_sink: error_sink.clone(),
3714 }
3715 .into();
3716
3717 match self.wgpu_surface.get_current_texture() {
3718 Ok(wgc::present::SurfaceOutput {
3719 status,
3720 texture: texture_id,
3721 }) => {
3722 let data = texture_id
3723 .map(|wgpu_texture| CoreTexture {
3724 context: self.context.clone(),
3725 wgpu_texture,
3726 error_sink,
3727 })
3728 .map(Into::into);
3729
3730 (data, status, output_detail)
3731 }
3732 Err(err) => {
3733 let error_sink = self.error_sink.lock();
3734 match error_sink.as_ref() {
3735 Some(error_sink) => {
3736 self.context.handle_error_nolabel(
3737 error_sink,
3738 err,
3739 "Surface::get_current_texture_view",
3740 );
3741 (None, crate::SurfaceStatus::Validation, output_detail)
3742 }
3743 None => self
3744 .context
3745 .handle_error_fatal(err, "Surface::get_current_texture_view"),
3746 }
3747 }
3748 }
3749 }
3750}
3751
3752impl dispatch::SurfaceOutputDetailInterface for CoreSurfaceOutputDetail {
3753 fn texture_discard(&self) {
3754 match self.wgpu_surface.discard() {
3755 Ok(_status) => (),
3756 Err(err) => {
3757 self.context
3758 .handle_error_nolabel(&self.error_sink, err, "Surface::discard_texture")
3759 }
3760 }
3761 }
3762
3763 fn texture_release(&self) {
3764 match self.wgpu_surface.release() {
3765 Ok(_status) => (),
3766 Err(err) => {
3767 self.context
3768 .handle_error_nolabel(&self.error_sink, err, "Surface::release_texture")
3769 }
3770 }
3771 }
3772}
3773
3774impl dispatch::QueueWriteBufferInterface for CoreQueueWriteBuffer {
3775 #[inline]
3776 fn len(&self) -> usize {
3777 self.mapping.len()
3778 }
3779
3780 #[inline]
3781 unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
3782 unsafe { self.mapping.write_slice() }
3783 }
3784}
3785
3786impl dispatch::BufferMappedRangeInterface for CoreBufferMappedRange {
3787 #[inline]
3788 fn len(&self) -> usize {
3789 self.size
3790 }
3791
3792 #[inline]
3793 unsafe fn read_slice(&self) -> &[u8] {
3794 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.size) }
3795 }
3796
3797 #[inline]
3798 unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
3799 unsafe { WriteOnly::new(NonNull::slice_from_raw_parts(self.ptr, self.size)) }
3800 }
3801
3802 #[cfg(webgpu)]
3803 fn as_uint8array(&self) -> &js_sys::Uint8Array {
3804 panic!("Only available on WebGPU")
3805 }
3806}