Add wgpu crate features for backends (#4815)

* Introduce `dx12` and `metal` crate features to `wgpu`

* Implement dummy `Context` to allow compilation with `--no-default-features`

* Address review

* Remove `dummy::Context` in favor of `hal::api::Empty`

* Add changelog entry

* Panic early in `Instance::new()` if no backend is enabled

Co-Authored-By: Andreas Reich <1220815+Wumpf@users.noreply.github.com>

---------

Co-authored-by: Andreas Reich <1220815+Wumpf@users.noreply.github.com>
This commit is contained in:
daxpedda 2023-12-16 10:39:53 +01:00 committed by GitHub
parent 855b06977f
commit 2053358d89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 20 deletions

View File

@ -55,6 +55,10 @@ Previously, `DeviceExt::create_texture_with_data` only allowed data to be provid
This feature allowed you to call `global_id` on any wgpu opaque handle to get a unique hashable identity for the given resource. This is now available without the feature flag. By @cwfitzgerald in [#4841](https://github.com/gfx-rs/wgpu/pull/4841)
### `dx12` and `metal` backend crate features
Wgpu now exposes backend feature for the Direct3D 12 (`dx12`) and Metal (`metal`) backend. These are enabled by default, but don't do anything when not targetting the corresponding OS. By @daxpedda in [#4815](https://github.com/gfx-rs/wgpu/pull/4815)
### New Features
#### General

View File

@ -222,6 +222,10 @@ define_backend_caller! { gfx_if_vulkan, gfx_if_vulkan_hidden, "vulkan" if all(fe
define_backend_caller! { gfx_if_metal, gfx_if_metal_hidden, "metal" if all(feature = "metal", any(target_os = "macos", target_os = "ios")) }
define_backend_caller! { gfx_if_dx12, gfx_if_dx12_hidden, "dx12" if all(feature = "dx12", windows) }
define_backend_caller! { gfx_if_gles, gfx_if_gles_hidden, "gles" if feature = "gles" }
define_backend_caller! { gfx_if_empty, gfx_if_empty_hidden, "empty" if all(
not(any(feature = "metal", feature = "vulkan", feature = "gles")),
any(target_os = "macos", target_os = "ios"),
) }
/// Dispatch on an [`Id`]'s backend to a backend-generic method.
///
@ -276,6 +280,7 @@ macro_rules! gfx_select {
wgt::Backend::Metal => $crate::gfx_if_metal!($global.$method::<$crate::api::Metal>( $($param),* )),
wgt::Backend::Dx12 => $crate::gfx_if_dx12!($global.$method::<$crate::api::Dx12>( $($param),* )),
wgt::Backend::Gl => $crate::gfx_if_gles!($global.$method::<$crate::api::Gles>( $($param),+ )),
wgt::Backend::Empty => $crate::gfx_if_empty!($global.$method::<$crate::api::Empty>( $($param),+ )),
other => panic!("Unexpected backend {:?}", other),
}
};

View File

@ -507,7 +507,7 @@ impl super::Instance {
Ok(self.create_surface_from_vk_surface_khr(surface))
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg(all(any(target_os = "macos", target_os = "ios"), feature = "metal"))]
fn create_surface_from_view(
&self,
view: *mut c_void,
@ -805,13 +805,13 @@ impl crate::Instance<super::Api> for super::Instance {
let hinstance = unsafe { GetModuleHandleW(std::ptr::null()) };
self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd.get() as *mut _)
}
#[cfg(target_os = "macos")]
#[cfg(all(target_os = "macos", feature = "metal"))]
(Rwh::AppKit(handle), _)
if self.shared.extensions.contains(&ext::MetalSurface::name()) =>
{
self.create_surface_from_view(handle.ns_view.as_ptr())
}
#[cfg(target_os = "ios")]
#[cfg(all(target_os = "ios", feature = "metal"))]
(Rwh::UiKit(handle), _)
if self.shared.extensions.contains(&ext::MetalSurface::name()) =>
{

View File

@ -24,7 +24,7 @@ targets = [
[lib]
[features]
default = ["wgsl"]
default = ["wgsl", "dx12", "metal"]
# Apply run-time checks, even in release builds. These are in addition
# to the validation carried out at public APIs in all builds.
strict_asserts = ["wgc?/strict_asserts", "wgt/strict_asserts"]
@ -33,11 +33,6 @@ glsl = ["naga/glsl-in"]
wgsl = ["wgc?/wgsl"]
trace = ["serde", "wgc/trace"]
replay = ["serde", "wgc/replay"]
# Enables the GLES backend on Windows & macOS
angle = ["wgc/gles"]
webgl = ["hal", "wgc/gles"]
# Enables the Vulkan backend on macOS & iOS
vulkan-portability = ["wgc/vulkan"]
# Implement `Send` and `Sync` on Wasm.
fragile-send-sync-non-atomic-wasm = [
"hal/fragile-send-sync-non-atomic-wasm",
@ -46,6 +41,17 @@ fragile-send-sync-non-atomic-wasm = [
]
# Log all API entry points at info instead of trace level.
api_log_info = ["wgc/api_log_info"]
# Backends
# Enables the DX12 backend on Windows
dx12 = ["wgc?/dx12"]
# Enables the Metal backend on macOS & iOS
metal = ["wgc?/metal"]
# Enables the GLES backend on Windows & macOS
angle = ["wgc?/gles"]
# Enables the Vulkan backend on macOS & iOS
vulkan-portability = ["wgc?/vulkan"]
# Enables the GLES backend on Wasm (currently will also enable GLES dependencies on any other target)
webgl = ["hal", "wgc/gles"]
# wgpu-core is always available as an optional dependency, "wgc".
# Whenever wgpu-core is selected, we want raw window handle support.
@ -60,15 +66,15 @@ features = ["raw-window-handle"]
workspace = true
features = ["raw-window-handle"]
# We want the wgpu-core Metal backend on macOS and iOS.
# Enable `wgc` by default on macOS and iOS to allow the `metal` crate feature to
# enable the Metal backend while being no-op on other targets.
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc]
workspace = true
features = ["metal"]
# We want the wgpu-core Direct3D backend and OpenGL (via WGL) on Windows.
[target.'cfg(windows)'.dependencies.wgc]
workspace = true
features = ["dx12", "gles"]
features = ["gles"]
# We want the wgpu-core Vulkan backend on Unix (but not emscripten, macOS, iOS) and Windows.
[target.'cfg(any(windows, all(unix, not(target_os = "emscripten"), not(target_os = "ios"), not(target_os = "macos"))))'.dependencies.wgc]

View File

@ -229,7 +229,7 @@ impl Context {
self.0.generate_report()
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(all(any(target_os = "ios", target_os = "macos"), feature = "metal"))]
pub unsafe fn create_surface_from_core_animation_layer(
&self,
layer: *mut std::ffi::c_void,
@ -265,7 +265,7 @@ impl Context {
})
}
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", feature = "dx12"))]
pub unsafe fn create_surface_from_visual(&self, visual: *mut std::ffi::c_void) -> Surface {
let id = unsafe { self.0.instance_create_surface_from_visual(visual, ()) };
Surface {
@ -274,7 +274,7 @@ impl Context {
}
}
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", feature = "dx12"))]
pub unsafe fn create_surface_from_surface_handle(
&self,
surface_handle: *mut std::ffi::c_void,
@ -289,7 +289,7 @@ impl Context {
}
}
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", feature = "dx12"))]
pub unsafe fn create_surface_from_swap_chain_panel(
&self,
swap_chain_panel: *mut std::ffi::c_void,

View File

@ -1786,19 +1786,62 @@ impl Default for Instance {
/// Creates a new instance of wgpu with default options.
///
/// Backends are set to `Backends::all()`, and FXC is chosen as the `dx12_shader_compiler`.
///
/// # Panics
///
/// If no backend feature for the active target platform is enabled,
/// this method will panic, see [`Instance::any_backend_feature_enabled()`].
fn default() -> Self {
Self::new(InstanceDescriptor::default())
}
}
impl Instance {
/// Returns `true` if any backend feature is enabled for the current build configuration.
///
/// Which feature makes this method return true depends on the target platform:
/// * MacOS/iOS: `metal`, `vulkan-portability` or `angle`
/// * All other: Always returns true
///
/// TODO: Right now it's otherwise not possible yet to opt-out of all features on most platforms.
/// See <https://github.com/gfx-rs/wgpu/issues/3514>
/// * Windows: always enables Vulkan and GLES with no way to opt out
/// * Linux: always enables Vulkan and GLES with no way to opt out
/// * Web: either targets WebGPU backend or, if `webgl` enabled, WebGL
/// * TODO: Support both WebGPU and WebGL at the same time, see <https://github.com/gfx-rs/wgpu/issues/2804>
pub const fn any_backend_feature_enabled() -> bool {
// Method intentionally kept verbose to keep it a bit easier to follow!
// On macOS and iOS, at least one of Metal, Vulkan or GLES backend must be enabled.
let is_mac_or_ios = cfg!(target_os = "macos") || cfg!(target_os = "ios");
if is_mac_or_ios {
cfg!(feature = "metal")
|| cfg!(feature = "vulkan-portability")
|| cfg!(feature = "angle")
} else {
true
}
}
/// Create an new instance of wgpu.
///
/// # Arguments
///
/// - `instance_desc` - Has fields for which [backends][Backends] wgpu will choose
/// during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use.
///
/// # Panics
///
/// If no backend feature for the active target platform is enabled,
/// this method will panic, see [`Instance::any_backend_feature_enabled()`].
pub fn new(instance_desc: InstanceDescriptor) -> Self {
if !Self::any_backend_feature_enabled() {
panic!(
"No wgpu backend feature that is implemented for the target platform was enabled. \
See `wgpu::Instance::any_backend_feature_enabled()` for more information."
);
}
Self {
context: Arc::from(crate::backend::Context::init(instance_desc)),
}
@ -2029,7 +2072,7 @@ impl Instance {
/// # Safety
///
/// - layer must be a valid object to create a surface upon.
#[cfg(any(target_os = "ios", target_os = "macos"))]
#[cfg(all(any(target_os = "ios", target_os = "macos"), feature = "metal"))]
pub unsafe fn create_surface_from_core_animation_layer(
&self,
layer: *mut std::ffi::c_void,
@ -2055,7 +2098,7 @@ impl Instance {
/// # Safety
///
/// - visual must be a valid IDCompositionVisual to create a surface upon.
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", feature = "dx12"))]
pub unsafe fn create_surface_from_visual(
&self,
visual: *mut std::ffi::c_void,
@ -2081,7 +2124,7 @@ impl Instance {
/// # Safety
///
/// - surface_handle must be a valid SurfaceHandle to create a surface upon.
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", feature = "dx12"))]
pub unsafe fn create_surface_from_surface_handle(
&self,
surface_handle: *mut std::ffi::c_void,
@ -2107,7 +2150,7 @@ impl Instance {
/// # Safety
///
/// - visual must be a valid SwapChainPanel to create a surface upon.
#[cfg(target_os = "windows")]
#[cfg(all(target_os = "windows", feature = "dx12"))]
pub unsafe fn create_surface_from_swap_chain_panel(
&self,
swap_chain_panel: *mut std::ffi::c_void,