mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Implement software adapter selection
This commit is contained in:
parent
97d6db4d18
commit
1ee6036f44
@ -216,6 +216,7 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RequestAdapterArgs {
|
||||
power_preference: Option<wgpu_types::PowerPreference>,
|
||||
force_fallback_adapter: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -259,7 +260,7 @@ pub async fn op_webgpu_request_adapter(
|
||||
Some(power_preference) => power_preference.into(),
|
||||
None => PowerPreference::default(),
|
||||
},
|
||||
// TODO(lucacasonato): respect forceFallbackAdapter
|
||||
force_fallback_adapter: args.force_fallback_adapter,
|
||||
compatible_surface: None, // windowless
|
||||
};
|
||||
let res = instance.request_adapter(
|
||||
|
@ -55,6 +55,7 @@ fn main() {
|
||||
.request_adapter(
|
||||
&wgc::instance::RequestAdapterOptions {
|
||||
power_preference: wgt::PowerPreference::LowPower,
|
||||
force_fallback_adapter: false,
|
||||
#[cfg(feature = "winit")]
|
||||
compatible_surface: Some(surface),
|
||||
#[cfg(not(feature = "winit"))]
|
||||
|
@ -186,6 +186,7 @@ impl Corpus {
|
||||
let adapter = match global.request_adapter(
|
||||
&wgc::instance::RequestAdapterOptions {
|
||||
power_preference: wgt::PowerPreference::LowPower,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: None,
|
||||
},
|
||||
wgc::instance::AdapterInputs::IdSet(
|
||||
|
@ -551,7 +551,34 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
) -> Result<AdapterId, RequestAdapterError> {
|
||||
profiling::scope!("pick_adapter", "Instance");
|
||||
|
||||
let instance = &self.instance;
|
||||
fn gather<A: HalApi, I: Clone>(
|
||||
_: A,
|
||||
instance: Option<&A::Instance>,
|
||||
inputs: &AdapterInputs<I>,
|
||||
compatible_surface: Option<&Surface>,
|
||||
force_software: bool,
|
||||
device_types: &mut Vec<wgt::DeviceType>,
|
||||
) -> (Option<I>, Vec<hal::ExposedAdapter<A>>) {
|
||||
let id = inputs.find(A::VARIANT);
|
||||
match instance {
|
||||
Some(inst) if id.is_some() => {
|
||||
let mut adapters = unsafe { inst.enumerate_adapters() };
|
||||
if force_software {
|
||||
adapters.retain(|exposed| exposed.info.device_type == wgt::DeviceType::Cpu);
|
||||
}
|
||||
if let Some(surface) = compatible_surface {
|
||||
let suf_raw = &A::get_surface(surface).raw;
|
||||
adapters.retain(|exposed| unsafe {
|
||||
exposed.adapter.surface_capabilities(suf_raw).is_some()
|
||||
});
|
||||
}
|
||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type));
|
||||
(id, adapters)
|
||||
}
|
||||
_ => (id, Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
let mut token = Token::root();
|
||||
let (surface_guard, mut token) = self.surfaces.read(&mut token);
|
||||
let compatible_surface = desc
|
||||
@ -564,67 +591,51 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.transpose()?;
|
||||
let mut device_types = Vec::new();
|
||||
|
||||
let mut id_vulkan = inputs.find(Backend::Vulkan);
|
||||
let mut id_metal = inputs.find(Backend::Metal);
|
||||
let mut id_dx12 = inputs.find(Backend::Dx12);
|
||||
let mut id_dx11 = inputs.find(Backend::Dx11);
|
||||
let mut id_gl = inputs.find(Backend::Gl);
|
||||
|
||||
backends_map! {
|
||||
let map = |(instance_backend, id_backend, surface_backend)| {
|
||||
match *instance_backend {
|
||||
Some(ref inst) if id_backend.is_some() => {
|
||||
let mut adapters = unsafe { inst.enumerate_adapters() };
|
||||
if let Some(surface_backend) = compatible_surface.and_then(surface_backend) {
|
||||
adapters.retain(|exposed| unsafe {
|
||||
exposed.adapter.surface_capabilities(&surface_backend.raw).is_some()
|
||||
});
|
||||
}
|
||||
device_types.extend(adapters.iter().map(|ad| ad.info.device_type));
|
||||
adapters
|
||||
}
|
||||
_ => Vec::new(),
|
||||
}
|
||||
};
|
||||
|
||||
// NB: The internal function definitions are a workaround for Rust
|
||||
// being weird with lifetimes for closure literals...
|
||||
#[cfg(vulkan)]
|
||||
let adapters_vk = map((&instance.vulkan, &id_vulkan, {
|
||||
fn surface_vulkan(surf: &Surface) -> Option<&HalSurface<hal::api::Vulkan>> {
|
||||
surf.vulkan.as_ref()
|
||||
}
|
||||
surface_vulkan
|
||||
}));
|
||||
#[cfg(metal)]
|
||||
let adapters_mtl = map((&instance.metal, &id_metal, {
|
||||
fn surface_metal(surf: &Surface) -> Option<&HalSurface<hal::api::Metal>> {
|
||||
surf.metal.as_ref()
|
||||
}
|
||||
surface_metal
|
||||
}));
|
||||
#[cfg(dx12)]
|
||||
let adapters_dx12 = map((&instance.dx12, &id_dx12, {
|
||||
fn surface_dx12(surf: &Surface) -> Option<&HalSurface<hal::api::Dx12>> {
|
||||
surf.dx12.as_ref()
|
||||
}
|
||||
surface_dx12
|
||||
}));
|
||||
#[cfg(dx11)]
|
||||
let adapters_dx11 = map((&instance.dx11, &id_dx11, {
|
||||
fn surface_dx11(surf: &Surface) -> Option<&HalSurface<hal::api::Dx11>> {
|
||||
surf.dx11.as_ref()
|
||||
}
|
||||
surface_dx11
|
||||
}));
|
||||
#[cfg(gl)]
|
||||
let adapters_gl = map((&instance.gl, &id_gl, {
|
||||
fn surface_gl(surf: &Surface) -> Option<&HalSurface<hal::api::Gles>> {
|
||||
surf.gl.as_ref()
|
||||
}
|
||||
surface_gl
|
||||
}));
|
||||
}
|
||||
#[cfg(vulkan)]
|
||||
let (mut id_vulkan, adapters_vk) = gather(
|
||||
hal::api::Vulkan,
|
||||
self.instance.vulkan.as_ref(),
|
||||
&inputs,
|
||||
compatible_surface,
|
||||
desc.force_fallback_adapter,
|
||||
&mut device_types,
|
||||
);
|
||||
#[cfg(metal)]
|
||||
let (mut id_metal, adapters_metal) = gather(
|
||||
hal::api::Metal,
|
||||
self.instance.metal.as_ref(),
|
||||
&inputs,
|
||||
compatible_surface,
|
||||
desc.force_fallback_adapter,
|
||||
&mut device_types,
|
||||
);
|
||||
#[cfg(dx12)]
|
||||
let (mut id_dx12, adapters_dx12) = gather(
|
||||
hal::api::Dx12,
|
||||
self.instance.dx12.as_ref(),
|
||||
&inputs,
|
||||
compatible_surface,
|
||||
desc.force_fallback_adapter,
|
||||
&mut device_types,
|
||||
);
|
||||
#[cfg(dx11)]
|
||||
let (mut id_dx11, adapters_dx11) = gather(
|
||||
hal::api::Dx11,
|
||||
self.instance.dx11.as_ref(),
|
||||
&inputs,
|
||||
compatible_surface,
|
||||
desc.force_fallback_adapter,
|
||||
&mut device_types,
|
||||
);
|
||||
#[cfg(gl)]
|
||||
let (mut id_gl, adapters_gl) = gather(
|
||||
hal::api::Gles,
|
||||
self.instance.gl.as_ref(),
|
||||
&inputs,
|
||||
compatible_surface,
|
||||
desc.force_fallback_adapter,
|
||||
&mut device_types,
|
||||
);
|
||||
|
||||
if device_types.is_empty() {
|
||||
return Err(RequestAdapterError::NotFound);
|
||||
@ -676,7 +687,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
#[cfg(vulkan)]
|
||||
map(("Vulkan", &mut id_vulkan, adapters_vk)),
|
||||
#[cfg(metal)]
|
||||
map(("Metal", &mut id_metal, adapters_mtl)),
|
||||
map(("Metal", &mut id_metal, adapters_metal)),
|
||||
#[cfg(dx12)]
|
||||
map(("Dx12", &mut id_dx12, adapters_dx12)),
|
||||
#[cfg(dx11)]
|
||||
@ -685,14 +696,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
map(("GL", &mut id_gl, adapters_gl)),
|
||||
}
|
||||
|
||||
let _ = (
|
||||
selected,
|
||||
id_vulkan.take(),
|
||||
id_metal.take(),
|
||||
id_dx12.take(),
|
||||
id_dx11.take(),
|
||||
id_gl.take(),
|
||||
);
|
||||
let _ = selected;
|
||||
log::warn!("Some adapters are present, but enumerating them failed!");
|
||||
Err(RequestAdapterError::NotFound)
|
||||
}
|
||||
|
@ -131,6 +131,9 @@ impl From<Backend> for Backends {
|
||||
pub struct RequestAdapterOptions<S> {
|
||||
/// Power preference for the adapter.
|
||||
pub power_preference: PowerPreference,
|
||||
/// Indicates that only a fallback adapter can be returned. This is generally a "software"
|
||||
/// implementation on the system.
|
||||
pub force_fallback_adapter: bool,
|
||||
/// Surface that is required to be presentable with the requested adapter. This does not
|
||||
/// create the surface, only guarantees that the adapter can present to said surface.
|
||||
pub compatible_surface: Option<S>,
|
||||
@ -140,6 +143,7 @@ impl<S> Default for RequestAdapterOptions<S> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
power_preference: PowerPreference::default(),
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: None,
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::default(),
|
||||
force_fallback_adapter: false,
|
||||
// Request an adapter which can render to our surface
|
||||
compatible_surface: Some(&surface),
|
||||
})
|
||||
|
@ -66,9 +66,9 @@ async fn run(event_loop: EventLoop<()>, viewports: Vec<(Window, wgpu::Color)>) {
|
||||
.collect();
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::default(),
|
||||
// Request an adapter which can render to our surface
|
||||
compatible_surface: viewports.first().map(|desc| &desc.surface),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.expect("Failed to find an appropriate adapter");
|
||||
|
@ -777,6 +777,7 @@ impl crate::Context for Context {
|
||||
let id = self.0.request_adapter(
|
||||
&wgc::instance::RequestAdapterOptions {
|
||||
power_preference: options.power_preference,
|
||||
force_fallback_adapter: options.force_fallback_adapter,
|
||||
compatible_surface: options.compatible_surface.map(|surface| surface.id.id),
|
||||
},
|
||||
wgc::instance::AdapterInputs::Mask(wgt::Backends::all(), |_| PhantomData),
|
||||
|
@ -79,6 +79,7 @@ pub async fn initialize_adapter_from_env_or_default(
|
||||
instance
|
||||
.request_adapter(&RequestAdapterOptions {
|
||||
power_preference: power_preference_from_env().unwrap_or_default(),
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface,
|
||||
})
|
||||
.await
|
||||
|
@ -12,6 +12,7 @@ fn request_adapter_inner(power: wgt::PowerPreference) {
|
||||
|
||||
let _adapter = pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: power,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: None,
|
||||
}))
|
||||
.unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user