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