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