From f5c2ff11d058eb65d51dc60b2d9196baf97481f1 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 17 May 2022 01:13:58 -0500 Subject: [PATCH] Adapter and Instance as_hal functions (#2663) These functions are added to allow lower level access to adapter and instance from backends. --- wgpu-core/src/hub.rs | 27 +++++++++++++++++++++++++++ wgpu-core/src/resource.rs | 22 +++++++++++++++++++++- wgpu/src/backend/direct.rs | 18 ++++++++++++++++++ wgpu/src/lib.rs | 30 ++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index 5df42bba18..feef06e2e4 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -907,6 +907,17 @@ impl Global { } } + /// # Safety + /// + /// - The raw handle obtained from the hal Instance must not be manually destroyed + pub unsafe fn instance_as_hal) -> R, R>( + &self, + hal_instance_callback: F, + ) -> R { + let hal_instance = A::instance_as_hal(&self.instance); + hal_instance_callback(hal_instance) + } + pub fn clear_backend(&self, _dummy: ()) { let mut surface_guard = self.surfaces.data.write(); let hub = A::hub(self); @@ -991,6 +1002,7 @@ impl Drop for Global { pub trait HalApi: hal::Api { const VARIANT: Backend; fn create_instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance; + fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance>; fn hub(global: &Global) -> &Hub; fn get_surface(surface: &Surface) -> &HalSurface; fn get_surface_mut(surface: &mut Surface) -> &mut HalSurface; @@ -1006,6 +1018,9 @@ impl HalApi for hal::api::Vulkan { ..Default::default() } } + fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance> { + instance.vulkan.as_ref() + } fn hub(global: &Global) -> &Hub { &global.hubs.vulkan } @@ -1027,6 +1042,9 @@ impl HalApi for hal::api::Metal { ..Default::default() } } + fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance> { + instance.metal.as_ref() + } fn hub(global: &Global) -> &Hub { &global.hubs.metal } @@ -1048,6 +1066,9 @@ impl HalApi for hal::api::Dx12 { ..Default::default() } } + fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance> { + instance.dx12.as_ref() + } fn hub(global: &Global) -> &Hub { &global.hubs.dx12 } @@ -1069,6 +1090,9 @@ impl HalApi for hal::api::Dx11 { ..Default::default() } } + fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance> { + instance.dx11.as_ref() + } fn hub(global: &Global) -> &Hub { &global.hubs.dx11 } @@ -1091,6 +1115,9 @@ impl HalApi for hal::api::Gles { ..Default::default() } } + fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance> { + instance.gl.as_ref() + } fn hub(global: &Global) -> &Hub { &global.hubs.gl } diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 3f12aba0d5..1f0af1b388 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -1,7 +1,7 @@ use crate::{ device::{DeviceError, HostMap, MissingFeatures}, hub::{Global, GlobalIdentityHandlerFactory, HalApi, Resource, Token}, - id::{DeviceId, SurfaceId, TextureId, Valid}, + id::{AdapterId, DeviceId, SurfaceId, TextureId, Valid}, init_tracker::{BufferInitTracker, TextureInitTracker}, track::{TextureSelector, DUMMY_SELECTOR}, validation::MissingBufferUsageError, @@ -250,6 +250,26 @@ impl Global { hal_texture_callback(hal_texture); } + /// # Safety + /// + /// - The raw adapter handle must not be manually destroyed + pub unsafe fn adapter_as_hal) -> R, R>( + &self, + id: AdapterId, + hal_adapter_callback: F, + ) -> R { + profiling::scope!("as_hal", "Adapter"); + + let hub = A::hub(self); + let mut token = Token::root(); + + let (guard, _) = hub.adapters.read(&mut token); + let adapter = guard.get(id).ok(); + let hal_adapter = adapter.map(|adapter| &adapter.raw.adapter); + + hal_adapter_callback(hal_adapter) + } + /// # Safety /// /// - The raw device handle must not be manually destroyed diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 64c567b975..fdd599e57b 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -47,6 +47,14 @@ impl Context { )) } + #[cfg(any(not(target_arch = "wasm32"), feature = "webgl2"))] + pub unsafe fn instance_as_hal) -> R, R>( + &self, + hal_instance_callback: F, + ) -> R { + self.0.instance_as_hal::(hal_instance_callback) + } + pub(crate) fn global(&self) -> &wgc::hub::Global { &self.0 } @@ -67,6 +75,16 @@ impl Context { self.0.create_adapter_from_hal(hal_adapter, PhantomData) } + #[cfg(any(not(target_arch = "wasm32"), feature = "webgl2"))] + pub unsafe fn adapter_as_hal) -> R, R>( + &self, + adapter: wgc::id::AdapterId, + hal_adapter_callback: F, + ) -> R { + self.0 + .adapter_as_hal::(adapter, hal_adapter_callback) + } + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_device_from_hal( &self, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index ad56aea9e4..69cb5ecaed 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1632,6 +1632,21 @@ impl Instance { } } + /// Returns the inner hal Instance using a callback. The hal instance will be `None` if the + /// backend type argument does not match with this wgpu Instance + /// + /// # Safety + /// + /// - The raw handle obtained from the hal Instance must not be manually destroyed + #[cfg(any(not(target_arch = "wasm32"), feature = "webgl2"))] + pub unsafe fn as_hal) -> R, R>( + &self, + hal_instance_callback: F, + ) -> R { + self.context + .instance_as_hal::(hal_instance_callback) + } + /// Retrieves all available [`Adapter`]s that match the given [`Backends`]. /// /// # Arguments @@ -1848,6 +1863,21 @@ impl Adapter { }) } + /// Returns the inner hal Adapter using a callback. The hal adapter will be `None` if the + /// backend type argument does not match with this wgpu Adapter + /// + /// # Safety + /// + /// - The raw handle obtained from the hal Adapter must not be manually destroyed + #[cfg(any(not(target_arch = "wasm32"), feature = "webgl2"))] + pub unsafe fn as_hal) -> R, R>( + &self, + hal_adapter_callback: F, + ) -> R { + self.context + .adapter_as_hal::(self.id, hal_adapter_callback) + } + /// Returns whether this adapter may present to the passed surface. pub fn is_surface_supported(&self, surface: &Surface) -> bool { Context::adapter_is_surface_supported(&*self.context, &self.id, &surface.id)