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