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