1use std::sync::Arc;
2use std::{borrow::Cow, collections::HashMap};
3
4use crate::{
5 api_log, api_log_debug,
6 device::{queue::Queue, resource::Device, DeviceDescriptor, DeviceError},
7 global::Global,
8 hal_api::HalApi,
9 id::{markers, AdapterId, DeviceId, QueueId, SurfaceId},
10 lock::{rank, Mutex},
11 present::Presentation,
12 resource::ResourceType,
13 resource_log, DOWNLEVEL_WARNING_MESSAGE,
14};
15
16use wgt::{Backend, Backends, PowerPreference};
17
18use thiserror::Error;
19
20pub type RequestAdapterOptions = wgt::RequestAdapterOptions<SurfaceId>;
21
22#[derive(Clone, Debug, Error)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[error("Limit '{name}' value {requested} is better than allowed {allowed}")]
25pub struct FailedLimit {
26 name: Cow<'static, str>,
27 requested: u64,
28 allowed: u64,
29}
30
31fn check_limits(requested: &wgt::Limits, allowed: &wgt::Limits) -> Vec<FailedLimit> {
32 let mut failed = Vec::new();
33
34 requested.check_limits_with_fail_fn(allowed, false, |name, requested, allowed| {
35 failed.push(FailedLimit {
36 name: Cow::Borrowed(name),
37 requested,
38 allowed,
39 })
40 });
41
42 failed
43}
44
45#[test]
46fn downlevel_default_limits_less_than_default_limits() {
47 let res = check_limits(&wgt::Limits::downlevel_defaults(), &wgt::Limits::default());
48 assert!(
49 res.is_empty(),
50 "Downlevel limits are greater than default limits",
51 )
52}
53
54#[derive(Default)]
55pub struct Instance {
56 #[allow(dead_code)]
57 pub name: String,
58 pub instance_per_backend: Vec<(Backend, Box<dyn hal::DynInstance>)>,
62 pub flags: wgt::InstanceFlags,
63}
64
65impl Instance {
66 pub fn new(name: &str, instance_desc: &wgt::InstanceDescriptor) -> Self {
67 fn init<A: HalApi>(
68 _: A,
69 instance_desc: &wgt::InstanceDescriptor,
70 instance_per_backend: &mut Vec<(Backend, Box<dyn hal::DynInstance>)>,
71 ) {
72 if instance_desc.backends.contains(A::VARIANT.into()) {
73 let hal_desc = hal::InstanceDescriptor {
74 name: "wgpu",
75 flags: instance_desc.flags,
76 dx12_shader_compiler: instance_desc
77 .backend_options
78 .dx12
79 .shader_compiler
80 .clone(),
81 gles_minor_version: instance_desc.backend_options.gl.gles_minor_version,
82 };
83
84 use hal::Instance as _;
85 match unsafe { A::Instance::init(&hal_desc) } {
86 Ok(instance) => {
87 log::debug!("Instance::new: created {:?} backend", A::VARIANT);
88 instance_per_backend.push((A::VARIANT, Box::new(instance)));
89 }
90 Err(err) => {
91 log::debug!(
92 "Instance::new: failed to create {:?} backend: {:?}",
93 A::VARIANT,
94 err
95 );
96 }
97 }
98 } else {
99 log::trace!("Instance::new: backend {:?} not requested", A::VARIANT);
100 }
101 }
102
103 let mut instance_per_backend = Vec::new();
104
105 #[cfg(vulkan)]
106 init(hal::api::Vulkan, instance_desc, &mut instance_per_backend);
107 #[cfg(metal)]
108 init(hal::api::Metal, instance_desc, &mut instance_per_backend);
109 #[cfg(dx12)]
110 init(hal::api::Dx12, instance_desc, &mut instance_per_backend);
111 #[cfg(gles)]
112 init(hal::api::Gles, instance_desc, &mut instance_per_backend);
113
114 Self {
115 name: name.to_string(),
116 instance_per_backend,
117 flags: instance_desc.flags,
118 }
119 }
120
121 pub fn raw(&self, backend: Backend) -> Option<&dyn hal::DynInstance> {
122 self.instance_per_backend
123 .iter()
124 .find_map(|(instance_backend, instance)| {
125 (*instance_backend == backend).then(|| instance.as_ref())
126 })
127 }
128
129 pub unsafe fn as_hal<A: HalApi>(&self) -> Option<&A::Instance> {
133 self.raw(A::VARIANT).map(|instance| {
134 instance
135 .as_any()
136 .downcast_ref()
137 .expect("Stored instance is not of the correct type")
139 })
140 }
141
142 #[cfg(feature = "raw-window-handle")]
157 pub unsafe fn create_surface(
158 &self,
159 display_handle: raw_window_handle::RawDisplayHandle,
160 window_handle: raw_window_handle::RawWindowHandle,
161 ) -> Result<Surface, CreateSurfaceError> {
162 profiling::scope!("Instance::create_surface");
163
164 let mut errors = HashMap::default();
165 let mut surface_per_backend = HashMap::default();
166
167 for (backend, instance) in &self.instance_per_backend {
168 match unsafe {
169 instance
170 .as_ref()
171 .create_surface(display_handle, window_handle)
172 } {
173 Ok(raw) => {
174 surface_per_backend.insert(*backend, raw);
175 }
176 Err(err) => {
177 log::debug!(
178 "Instance::create_surface: failed to create surface for {:?}: {:?}",
179 backend,
180 err
181 );
182 errors.insert(*backend, err);
183 }
184 }
185 }
186
187 if surface_per_backend.is_empty() {
188 Err(CreateSurfaceError::FailedToCreateSurfaceForAnyBackend(
189 errors,
190 ))
191 } else {
192 let surface = Surface {
193 presentation: Mutex::new(rank::SURFACE_PRESENTATION, None),
194 surface_per_backend,
195 };
196
197 Ok(surface)
198 }
199 }
200
201 #[cfg(metal)]
205 pub unsafe fn create_surface_metal(
206 &self,
207 layer: *mut std::ffi::c_void,
208 ) -> Result<Surface, CreateSurfaceError> {
209 profiling::scope!("Instance::create_surface_metal");
210
211 let instance = unsafe { self.as_hal::<hal::api::Metal>() }
212 .ok_or(CreateSurfaceError::BackendNotEnabled(Backend::Metal))?;
213
214 let layer = layer.cast();
215 let layer = unsafe { &*layer };
227 let raw_surface: Box<dyn hal::DynSurface> =
228 Box::new(instance.create_surface_from_layer(layer));
229
230 let surface = Surface {
231 presentation: Mutex::new(rank::SURFACE_PRESENTATION, None),
232 surface_per_backend: std::iter::once((Backend::Metal, raw_surface)).collect(),
233 };
234
235 Ok(surface)
236 }
237
238 #[cfg(dx12)]
239 fn create_surface_dx12(
240 &self,
241 create_surface_func: impl FnOnce(&hal::dx12::Instance) -> hal::dx12::Surface,
242 ) -> Result<Surface, CreateSurfaceError> {
243 let instance = unsafe { self.as_hal::<hal::api::Dx12>() }
244 .ok_or(CreateSurfaceError::BackendNotEnabled(Backend::Dx12))?;
245 let surface: Box<dyn hal::DynSurface> = Box::new(create_surface_func(instance));
246
247 let surface = Surface {
248 presentation: Mutex::new(rank::SURFACE_PRESENTATION, None),
249 surface_per_backend: std::iter::once((Backend::Dx12, surface)).collect(),
250 };
251
252 Ok(surface)
253 }
254
255 #[cfg(dx12)]
256 pub unsafe fn create_surface_from_visual(
260 &self,
261 visual: *mut std::ffi::c_void,
262 ) -> Result<Surface, CreateSurfaceError> {
263 profiling::scope!("Instance::instance_create_surface_from_visual");
264 self.create_surface_dx12(|inst| unsafe { inst.create_surface_from_visual(visual) })
265 }
266
267 #[cfg(dx12)]
268 pub unsafe fn create_surface_from_surface_handle(
272 &self,
273 surface_handle: *mut std::ffi::c_void,
274 ) -> Result<Surface, CreateSurfaceError> {
275 profiling::scope!("Instance::instance_create_surface_from_surface_handle");
276 self.create_surface_dx12(|inst| unsafe {
277 inst.create_surface_from_surface_handle(surface_handle)
278 })
279 }
280
281 #[cfg(dx12)]
282 pub unsafe fn create_surface_from_swap_chain_panel(
286 &self,
287 swap_chain_panel: *mut std::ffi::c_void,
288 ) -> Result<Surface, CreateSurfaceError> {
289 profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel");
290 self.create_surface_dx12(|inst| unsafe {
291 inst.create_surface_from_swap_chain_panel(swap_chain_panel)
292 })
293 }
294
295 pub fn enumerate_adapters(&self, backends: Backends) -> Vec<Adapter> {
296 profiling::scope!("Instance::enumerate_adapters");
297 api_log!("Instance::enumerate_adapters");
298
299 let mut adapters = Vec::new();
300 for (_backend, instance) in self
301 .instance_per_backend
302 .iter()
303 .filter(|(backend, _)| backends.contains(Backends::from(*backend)))
304 {
305 profiling::scope!("enumerating", &*format!("{:?}", _backend));
308
309 let hal_adapters = unsafe { instance.enumerate_adapters(None) };
310 for raw in hal_adapters {
311 let adapter = Adapter::new(raw);
312 api_log_debug!("Adapter {:?}", adapter.raw.info);
313 adapters.push(adapter);
314 }
315 }
316 adapters
317 }
318
319 pub fn request_adapter(
320 &self,
321 desc: &wgt::RequestAdapterOptions<&Surface>,
322 backends: Backends,
323 ) -> Result<Adapter, RequestAdapterError> {
324 profiling::scope!("Instance::request_adapter");
325 api_log!("Instance::request_adapter");
326
327 let mut adapters = Vec::new();
328
329 for (backend, instance) in self
330 .instance_per_backend
331 .iter()
332 .filter(|(backend, _)| backends.contains(Backends::from(*backend)))
333 {
334 let compatible_hal_surface = desc
335 .compatible_surface
336 .and_then(|surface| surface.raw(*backend));
337 let mut backend_adapters =
338 unsafe { instance.enumerate_adapters(compatible_hal_surface) };
339 if desc.force_fallback_adapter {
340 backend_adapters.retain(|exposed| exposed.info.device_type == wgt::DeviceType::Cpu);
341 }
342 if let Some(surface) = desc.compatible_surface {
343 backend_adapters.retain(|exposed| {
344 let capabilities = surface.get_capabilities_with_raw(exposed);
345 if let Err(err) = capabilities {
346 log::debug!(
347 "Adapter {:?} not compatible with surface: {}",
348 exposed.info,
349 err
350 );
351 false
352 } else {
353 true
354 }
355 });
356 }
357 adapters.extend(backend_adapters);
358 }
359
360 match desc.power_preference {
361 PowerPreference::LowPower => {
362 sort(&mut adapters, true);
363 }
364 PowerPreference::HighPerformance => {
365 sort(&mut adapters, false);
366 }
367 PowerPreference::None => {}
368 };
369
370 fn sort(adapters: &mut [hal::DynExposedAdapter], prefer_integrated_gpu: bool) {
371 adapters.sort_by(|a, b| {
372 get_order(a.info.device_type, prefer_integrated_gpu)
373 .cmp(&get_order(b.info.device_type, prefer_integrated_gpu))
374 });
375 }
376
377 fn get_order(device_type: wgt::DeviceType, prefer_integrated_gpu: bool) -> u8 {
378 match device_type {
386 wgt::DeviceType::DiscreteGpu if prefer_integrated_gpu => 2,
387 wgt::DeviceType::IntegratedGpu if prefer_integrated_gpu => 1,
388 wgt::DeviceType::DiscreteGpu => 1,
389 wgt::DeviceType::IntegratedGpu => 2,
390 wgt::DeviceType::Other => 3,
391 wgt::DeviceType::VirtualGpu => 4,
392 wgt::DeviceType::Cpu => 5,
393 }
394 }
395
396 if adapters.is_empty() {
399 log::debug!("Request adapter didn't find compatible adapters.");
400 } else {
401 log::debug!(
402 "Found {} compatible adapters. Sorted by preference:",
403 adapters.len()
404 );
405 for adapter in &adapters {
406 log::debug!("* {:?}", adapter.info);
407 }
408 }
409
410 if let Some(adapter) = adapters.into_iter().next() {
411 api_log_debug!("Request adapter result {:?}", adapter.info);
412 let adapter = Adapter::new(adapter);
413 Ok(adapter)
414 } else {
415 Err(RequestAdapterError::NotFound)
416 }
417 }
418}
419
420pub struct Surface {
421 pub(crate) presentation: Mutex<Option<Presentation>>,
422 pub surface_per_backend: HashMap<Backend, Box<dyn hal::DynSurface>>,
423}
424
425impl ResourceType for Surface {
426 const TYPE: &'static str = "Surface";
427}
428impl crate::storage::StorageItem for Surface {
429 type Marker = markers::Surface;
430}
431
432impl Surface {
433 pub fn get_capabilities(
434 &self,
435 adapter: &Adapter,
436 ) -> Result<hal::SurfaceCapabilities, GetSurfaceSupportError> {
437 self.get_capabilities_with_raw(&adapter.raw)
438 }
439
440 pub fn get_capabilities_with_raw(
441 &self,
442 adapter: &hal::DynExposedAdapter,
443 ) -> Result<hal::SurfaceCapabilities, GetSurfaceSupportError> {
444 let backend = adapter.backend();
445 let suf = self
446 .raw(backend)
447 .ok_or(GetSurfaceSupportError::NotSupportedByBackend(backend))?;
448 profiling::scope!("surface_capabilities");
449 let caps = unsafe { adapter.adapter.surface_capabilities(suf) }
450 .ok_or(GetSurfaceSupportError::FailedToRetrieveSurfaceCapabilitiesForAdapter)?;
451 Ok(caps)
452 }
453
454 pub fn raw(&self, backend: Backend) -> Option<&dyn hal::DynSurface> {
455 self.surface_per_backend
456 .get(&backend)
457 .map(|surface| surface.as_ref())
458 }
459}
460
461impl Drop for Surface {
462 fn drop(&mut self) {
463 if let Some(present) = self.presentation.lock().take() {
464 for (&backend, surface) in &self.surface_per_backend {
465 if backend == present.device.backend() {
466 unsafe { surface.unconfigure(present.device.raw()) };
467 }
468 }
469 }
470 }
471}
472
473pub struct Adapter {
474 pub(crate) raw: hal::DynExposedAdapter,
475}
476
477impl Adapter {
478 pub fn new(mut raw: hal::DynExposedAdapter) -> Self {
479 const MIN_BUFFER_OFFSET_ALIGNMENT_LOWER_BOUND: u32 = 32;
481
482 let limits = &mut raw.capabilities.limits;
483
484 limits.min_uniform_buffer_offset_alignment = limits
485 .min_uniform_buffer_offset_alignment
486 .max(MIN_BUFFER_OFFSET_ALIGNMENT_LOWER_BOUND);
487 limits.min_storage_buffer_offset_alignment = limits
488 .min_storage_buffer_offset_alignment
489 .max(MIN_BUFFER_OFFSET_ALIGNMENT_LOWER_BOUND);
490
491 Self { raw }
492 }
493
494 pub fn backend(&self) -> Backend {
496 self.raw.backend()
497 }
498
499 pub fn is_surface_supported(&self, surface: &Surface) -> bool {
500 surface.get_capabilities(self).is_ok()
505 }
506
507 pub fn get_info(&self) -> wgt::AdapterInfo {
508 self.raw.info.clone()
509 }
510
511 pub fn features(&self) -> wgt::Features {
512 self.raw.features
513 }
514
515 pub fn limits(&self) -> wgt::Limits {
516 self.raw.capabilities.limits.clone()
517 }
518
519 pub fn downlevel_capabilities(&self) -> wgt::DownlevelCapabilities {
520 self.raw.capabilities.downlevel.clone()
521 }
522
523 pub fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp {
524 unsafe { self.raw.adapter.get_presentation_timestamp() }
525 }
526
527 pub fn get_texture_format_features(
528 &self,
529 format: wgt::TextureFormat,
530 ) -> wgt::TextureFormatFeatures {
531 use hal::TextureFormatCapabilities as Tfc;
532
533 let caps = unsafe { self.raw.adapter.texture_format_capabilities(format) };
534 let mut allowed_usages = wgt::TextureUsages::empty();
535
536 allowed_usages.set(wgt::TextureUsages::COPY_SRC, caps.contains(Tfc::COPY_SRC));
537 allowed_usages.set(wgt::TextureUsages::COPY_DST, caps.contains(Tfc::COPY_DST));
538 allowed_usages.set(
539 wgt::TextureUsages::TEXTURE_BINDING,
540 caps.contains(Tfc::SAMPLED),
541 );
542 allowed_usages.set(
543 wgt::TextureUsages::STORAGE_BINDING,
544 caps.intersects(
545 Tfc::STORAGE_WRITE_ONLY
546 | Tfc::STORAGE_READ_ONLY
547 | Tfc::STORAGE_READ_WRITE
548 | Tfc::STORAGE_ATOMIC,
549 ),
550 );
551 allowed_usages.set(
552 wgt::TextureUsages::RENDER_ATTACHMENT,
553 caps.intersects(Tfc::COLOR_ATTACHMENT | Tfc::DEPTH_STENCIL_ATTACHMENT),
554 );
555 allowed_usages.set(
556 wgt::TextureUsages::STORAGE_ATOMIC,
557 caps.contains(Tfc::STORAGE_ATOMIC),
558 );
559
560 let mut flags = wgt::TextureFormatFeatureFlags::empty();
561 flags.set(
562 wgt::TextureFormatFeatureFlags::STORAGE_READ_ONLY,
563 caps.contains(Tfc::STORAGE_READ_ONLY),
564 );
565 flags.set(
566 wgt::TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
567 caps.contains(Tfc::STORAGE_WRITE_ONLY),
568 );
569 flags.set(
570 wgt::TextureFormatFeatureFlags::STORAGE_READ_WRITE,
571 caps.contains(Tfc::STORAGE_READ_WRITE),
572 );
573
574 flags.set(
575 wgt::TextureFormatFeatureFlags::STORAGE_ATOMIC,
576 caps.contains(Tfc::STORAGE_ATOMIC),
577 );
578
579 flags.set(
580 wgt::TextureFormatFeatureFlags::FILTERABLE,
581 caps.contains(Tfc::SAMPLED_LINEAR),
582 );
583
584 flags.set(
585 wgt::TextureFormatFeatureFlags::BLENDABLE,
586 caps.contains(Tfc::COLOR_ATTACHMENT_BLEND),
587 );
588
589 flags.set(
590 wgt::TextureFormatFeatureFlags::MULTISAMPLE_X2,
591 caps.contains(Tfc::MULTISAMPLE_X2),
592 );
593 flags.set(
594 wgt::TextureFormatFeatureFlags::MULTISAMPLE_X4,
595 caps.contains(Tfc::MULTISAMPLE_X4),
596 );
597 flags.set(
598 wgt::TextureFormatFeatureFlags::MULTISAMPLE_X8,
599 caps.contains(Tfc::MULTISAMPLE_X8),
600 );
601 flags.set(
602 wgt::TextureFormatFeatureFlags::MULTISAMPLE_X16,
603 caps.contains(Tfc::MULTISAMPLE_X16),
604 );
605
606 flags.set(
607 wgt::TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE,
608 caps.contains(Tfc::MULTISAMPLE_RESOLVE),
609 );
610
611 wgt::TextureFormatFeatures {
612 allowed_usages,
613 flags,
614 }
615 }
616
617 #[allow(clippy::type_complexity)]
618 fn create_device_and_queue_from_hal(
619 self: &Arc<Self>,
620 hal_device: hal::DynOpenDevice,
621 desc: &DeviceDescriptor,
622 instance_flags: wgt::InstanceFlags,
623 trace_path: Option<&std::path::Path>,
624 ) -> Result<(Arc<Device>, Arc<Queue>), RequestDeviceError> {
625 api_log!("Adapter::create_device");
626
627 let device = Device::new(hal_device.device, self, desc, trace_path, instance_flags)?;
628 let device = Arc::new(device);
629
630 let queue = Queue::new(device.clone(), hal_device.queue)?;
631 let queue = Arc::new(queue);
632
633 device.set_queue(&queue);
634
635 Ok((device, queue))
636 }
637
638 pub fn create_device_and_queue(
639 self: &Arc<Self>,
640 desc: &DeviceDescriptor,
641 instance_flags: wgt::InstanceFlags,
642 trace_path: Option<&std::path::Path>,
643 ) -> Result<(Arc<Device>, Arc<Queue>), RequestDeviceError> {
644 if !self.raw.features.contains(desc.required_features) {
646 return Err(RequestDeviceError::UnsupportedFeature(
647 desc.required_features - self.raw.features,
648 ));
649 }
650
651 let caps = &self.raw.capabilities;
652 if Backends::PRIMARY.contains(Backends::from(self.backend()))
653 && !caps.downlevel.is_webgpu_compliant()
654 {
655 let missing_flags = wgt::DownlevelFlags::compliant() - caps.downlevel.flags;
656 log::warn!(
657 "Missing downlevel flags: {:?}\n{}",
658 missing_flags,
659 DOWNLEVEL_WARNING_MESSAGE
660 );
661 log::warn!("{:#?}", caps.downlevel);
662 }
663
664 if desc
666 .required_features
667 .contains(wgt::Features::MAPPABLE_PRIMARY_BUFFERS)
668 && self.raw.info.device_type == wgt::DeviceType::DiscreteGpu
669 {
670 log::warn!(
671 "Feature MAPPABLE_PRIMARY_BUFFERS enabled on a discrete gpu. \
672 This is a massive performance footgun and likely not what you wanted"
673 );
674 }
675
676 if let Some(failed) = check_limits(&desc.required_limits, &caps.limits).pop() {
677 return Err(RequestDeviceError::LimitsExceeded(failed));
678 }
679
680 let open = unsafe {
681 self.raw.adapter.open(
682 desc.required_features,
683 &desc.required_limits,
684 &desc.memory_hints,
685 )
686 }
687 .map_err(DeviceError::from_hal)?;
688
689 self.create_device_and_queue_from_hal(open, desc, instance_flags, trace_path)
690 }
691}
692
693crate::impl_resource_type!(Adapter);
694crate::impl_storage_item!(Adapter);
695
696#[derive(Clone, Debug, Error)]
697#[non_exhaustive]
698pub enum GetSurfaceSupportError {
699 #[error("Surface is not supported for the specified backend {0}")]
700 NotSupportedByBackend(Backend),
701 #[error("Failed to retrieve surface capabilities for the specified adapter.")]
702 FailedToRetrieveSurfaceCapabilitiesForAdapter,
703}
704
705#[derive(Clone, Debug, Error)]
706#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
707#[non_exhaustive]
709pub enum RequestDeviceError {
710 #[error(transparent)]
711 Device(#[from] DeviceError),
712 #[error(transparent)]
713 LimitsExceeded(#[from] FailedLimit),
714 #[error("Unsupported features were requested: {0:?}")]
715 UnsupportedFeature(wgt::Features),
716}
717
718#[derive(Clone, Debug, Error)]
719#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
720#[non_exhaustive]
721pub enum RequestAdapterError {
722 #[error("No suitable adapter found")]
723 NotFound,
724}
725
726#[derive(Clone, Debug, Error)]
727#[non_exhaustive]
728pub enum CreateSurfaceError {
729 #[error("The backend {0} was not enabled on the instance.")]
730 BackendNotEnabled(Backend),
731 #[error("Failed to create surface for any enabled backend: {0:?}")]
732 FailedToCreateSurfaceForAnyBackend(HashMap<Backend, hal::InstanceError>),
733}
734
735impl Global {
736 #[cfg(feature = "raw-window-handle")]
754 pub unsafe fn instance_create_surface(
755 &self,
756 display_handle: raw_window_handle::RawDisplayHandle,
757 window_handle: raw_window_handle::RawWindowHandle,
758 id_in: Option<SurfaceId>,
759 ) -> Result<SurfaceId, CreateSurfaceError> {
760 let surface = unsafe { self.instance.create_surface(display_handle, window_handle) }?;
761 let id = self.surfaces.prepare(id_in).assign(Arc::new(surface));
762 Ok(id)
763 }
764
765 #[cfg(metal)]
769 pub unsafe fn instance_create_surface_metal(
770 &self,
771 layer: *mut std::ffi::c_void,
772 id_in: Option<SurfaceId>,
773 ) -> Result<SurfaceId, CreateSurfaceError> {
774 let surface = unsafe { self.instance.create_surface_metal(layer) }?;
775 let id = self.surfaces.prepare(id_in).assign(Arc::new(surface));
776 Ok(id)
777 }
778
779 #[cfg(dx12)]
780 pub unsafe fn instance_create_surface_from_visual(
784 &self,
785 visual: *mut std::ffi::c_void,
786 id_in: Option<SurfaceId>,
787 ) -> Result<SurfaceId, CreateSurfaceError> {
788 let surface = unsafe { self.instance.create_surface_from_visual(visual) }?;
789 let id = self.surfaces.prepare(id_in).assign(Arc::new(surface));
790 Ok(id)
791 }
792
793 #[cfg(dx12)]
794 pub unsafe fn instance_create_surface_from_surface_handle(
798 &self,
799 surface_handle: *mut std::ffi::c_void,
800 id_in: Option<SurfaceId>,
801 ) -> Result<SurfaceId, CreateSurfaceError> {
802 let surface = unsafe {
803 self.instance
804 .create_surface_from_surface_handle(surface_handle)
805 }?;
806 let id = self.surfaces.prepare(id_in).assign(Arc::new(surface));
807 Ok(id)
808 }
809
810 #[cfg(dx12)]
811 pub unsafe fn instance_create_surface_from_swap_chain_panel(
815 &self,
816 swap_chain_panel: *mut std::ffi::c_void,
817 id_in: Option<SurfaceId>,
818 ) -> Result<SurfaceId, CreateSurfaceError> {
819 let surface = unsafe {
820 self.instance
821 .create_surface_from_swap_chain_panel(swap_chain_panel)
822 }?;
823 let id = self.surfaces.prepare(id_in).assign(Arc::new(surface));
824 Ok(id)
825 }
826
827 pub fn surface_drop(&self, id: SurfaceId) {
828 profiling::scope!("Surface::drop");
829
830 api_log!("Surface::drop {id:?}");
831
832 self.surfaces.remove(id);
833 }
834
835 pub fn enumerate_adapters(&self, backends: Backends) -> Vec<AdapterId> {
836 let adapters = self.instance.enumerate_adapters(backends);
837 adapters
838 .into_iter()
839 .map(|adapter| self.hub.adapters.prepare(None).assign(Arc::new(adapter)))
840 .collect()
841 }
842
843 pub fn request_adapter(
844 &self,
845 desc: &RequestAdapterOptions,
846 backends: Backends,
847 id_in: Option<AdapterId>,
848 ) -> Result<AdapterId, RequestAdapterError> {
849 let compatible_surface = desc.compatible_surface.map(|id| self.surfaces.get(id));
850 let desc = wgt::RequestAdapterOptions {
851 power_preference: desc.power_preference,
852 force_fallback_adapter: desc.force_fallback_adapter,
853 compatible_surface: compatible_surface.as_deref(),
854 };
855 let adapter = self.instance.request_adapter(&desc, backends)?;
856 let id = self.hub.adapters.prepare(id_in).assign(Arc::new(adapter));
857 Ok(id)
858 }
859
860 pub unsafe fn create_adapter_from_hal(
864 &self,
865 hal_adapter: hal::DynExposedAdapter,
866 input: Option<AdapterId>,
867 ) -> AdapterId {
868 profiling::scope!("Instance::create_adapter_from_hal");
869
870 let fid = self.hub.adapters.prepare(input);
871 let id = fid.assign(Arc::new(Adapter::new(hal_adapter)));
872
873 resource_log!("Created Adapter {:?}", id);
874 id
875 }
876
877 pub fn adapter_get_info(&self, adapter_id: AdapterId) -> wgt::AdapterInfo {
878 let adapter = self.hub.adapters.get(adapter_id);
879 adapter.get_info()
880 }
881
882 pub fn adapter_get_texture_format_features(
883 &self,
884 adapter_id: AdapterId,
885 format: wgt::TextureFormat,
886 ) -> wgt::TextureFormatFeatures {
887 let adapter = self.hub.adapters.get(adapter_id);
888 adapter.get_texture_format_features(format)
889 }
890
891 pub fn adapter_features(&self, adapter_id: AdapterId) -> wgt::Features {
892 let adapter = self.hub.adapters.get(adapter_id);
893 adapter.features()
894 }
895
896 pub fn adapter_limits(&self, adapter_id: AdapterId) -> wgt::Limits {
897 let adapter = self.hub.adapters.get(adapter_id);
898 adapter.limits()
899 }
900
901 pub fn adapter_downlevel_capabilities(
902 &self,
903 adapter_id: AdapterId,
904 ) -> wgt::DownlevelCapabilities {
905 let adapter = self.hub.adapters.get(adapter_id);
906 adapter.downlevel_capabilities()
907 }
908
909 pub fn adapter_get_presentation_timestamp(
910 &self,
911 adapter_id: AdapterId,
912 ) -> wgt::PresentationTimestamp {
913 let adapter = self.hub.adapters.get(adapter_id);
914 adapter.get_presentation_timestamp()
915 }
916
917 pub fn adapter_drop(&self, adapter_id: AdapterId) {
918 profiling::scope!("Adapter::drop");
919 api_log!("Adapter::drop {adapter_id:?}");
920
921 self.hub.adapters.remove(adapter_id);
922 }
923}
924
925impl Global {
926 pub fn adapter_request_device(
927 &self,
928 adapter_id: AdapterId,
929 desc: &DeviceDescriptor,
930 trace_path: Option<&std::path::Path>,
931 device_id_in: Option<DeviceId>,
932 queue_id_in: Option<QueueId>,
933 ) -> Result<(DeviceId, QueueId), RequestDeviceError> {
934 profiling::scope!("Adapter::request_device");
935 api_log!("Adapter::request_device");
936
937 let device_fid = self.hub.devices.prepare(device_id_in);
938 let queue_fid = self.hub.queues.prepare(queue_id_in);
939
940 let adapter = self.hub.adapters.get(adapter_id);
941 let (device, queue) =
942 adapter.create_device_and_queue(desc, self.instance.flags, trace_path)?;
943
944 let device_id = device_fid.assign(device);
945 resource_log!("Created Device {:?}", device_id);
946
947 let queue_id = queue_fid.assign(queue);
948 resource_log!("Created Queue {:?}", queue_id);
949
950 Ok((device_id, queue_id))
951 }
952
953 pub unsafe fn create_device_from_hal(
958 &self,
959 adapter_id: AdapterId,
960 hal_device: hal::DynOpenDevice,
961 desc: &DeviceDescriptor,
962 trace_path: Option<&std::path::Path>,
963 device_id_in: Option<DeviceId>,
964 queue_id_in: Option<QueueId>,
965 ) -> Result<(DeviceId, QueueId), RequestDeviceError> {
966 profiling::scope!("Global::create_device_from_hal");
967
968 let devices_fid = self.hub.devices.prepare(device_id_in);
969 let queues_fid = self.hub.queues.prepare(queue_id_in);
970
971 let adapter = self.hub.adapters.get(adapter_id);
972 let (device, queue) = adapter.create_device_and_queue_from_hal(
973 hal_device,
974 desc,
975 self.instance.flags,
976 trace_path,
977 )?;
978
979 let device_id = devices_fid.assign(device);
980 resource_log!("Created Device {:?}", device_id);
981
982 let queue_id = queues_fid.assign(queue);
983 resource_log!("Created Queue {:?}", queue_id);
984
985 Ok((device_id, queue_id))
986 }
987}