mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
hal/linux: Work around Intel+Nvidia presentation conflict
This commit is contained in:
parent
86c2a8057e
commit
d23288e455
@ -7,6 +7,9 @@ pub mod db {
|
||||
pub const DEVICE_KABY_LAKE_MASK: u32 = 0x5900;
|
||||
pub const DEVICE_SKY_LAKE_MASK: u32 = 0x1900;
|
||||
}
|
||||
pub mod nvidia {
|
||||
pub const VENDOR: u32 = 0x10DE;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_naga_stage(stage: naga::ShaderStage) -> wgt::ShaderStages {
|
||||
|
@ -698,6 +698,7 @@ impl super::Instance {
|
||||
.contains(vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT)
|
||||
},
|
||||
non_coherent_map_mask: phd_capabilities.properties.limits.non_coherent_atom_size - 1,
|
||||
can_present: true,
|
||||
};
|
||||
|
||||
let capabilities = crate::Capabilities {
|
||||
@ -1023,6 +1024,10 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
||||
&self,
|
||||
surface: &super::Surface,
|
||||
) -> Option<crate::SurfaceCapabilities> {
|
||||
if !self.private_caps.can_present {
|
||||
return None;
|
||||
}
|
||||
|
||||
let queue_family_index = 0; //TODO
|
||||
match surface.functor.get_physical_device_surface_support(
|
||||
self.raw,
|
||||
|
@ -600,10 +600,33 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||
}
|
||||
};
|
||||
|
||||
raw_devices
|
||||
let mut exposed_adapters = raw_devices
|
||||
.into_iter()
|
||||
.flat_map(|device| self.expose_adapter(device))
|
||||
.collect()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// detect if it's an Intel + NVidia configuration
|
||||
if cfg!(target_os = "linux") {
|
||||
use crate::auxil::db;
|
||||
let has_nvidia_dgpu = exposed_adapters.iter().any(|exposed| {
|
||||
exposed.info.device_type == wgt::DeviceType::DiscreteGpu
|
||||
&& exposed.info.vendor == db::nvidia::VENDOR as usize
|
||||
});
|
||||
if has_nvidia_dgpu {
|
||||
for exposed in exposed_adapters.iter_mut() {
|
||||
if exposed.info.device_type == wgt::DeviceType::IntegratedGpu
|
||||
&& exposed.info.vendor == db::intel::VENDOR as usize
|
||||
{
|
||||
// See https://gitlab.freedesktop.org/mesa/mesa/-/issues/4688
|
||||
log::warn!("Disabling presentation on '{}' (id {:?}) because of an Nvidia dGPU (on Linux)",
|
||||
exposed.info.name, exposed.adapter.raw);
|
||||
exposed.adapter.private_caps.can_present = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposed_adapters
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,6 +158,8 @@ struct PrivateCapabilities {
|
||||
timeline_semaphores: bool,
|
||||
texture_d24: bool,
|
||||
texture_d24_s8: bool,
|
||||
/// Ability to present contents to any screen. Only needed to work around broken platform configurations.
|
||||
can_present: bool,
|
||||
non_coherent_map_mask: wgt::BufferAddress,
|
||||
}
|
||||
|
||||
|
@ -824,6 +824,8 @@ pub enum DeviceType {
|
||||
Cpu,
|
||||
}
|
||||
|
||||
//TODO: convert `vendor` and `device` to `u32`
|
||||
|
||||
/// Information about an adapter.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
|
@ -118,9 +118,10 @@ async fn setup<E: Example>(title: &str) -> Setup {
|
||||
let surface = instance.create_surface(&window);
|
||||
(size, surface)
|
||||
};
|
||||
let adapter = wgpu::util::initialize_adapter_from_env_or_default(&instance, backend)
|
||||
.await
|
||||
.expect("No suitable GPU adapters found on the system!");
|
||||
let adapter =
|
||||
wgpu::util::initialize_adapter_from_env_or_default(&instance, backend, Some(&surface))
|
||||
.await
|
||||
.expect("No suitable GPU adapters found on the system!");
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
use wgt::{Backends, PowerPreference, RequestAdapterOptions};
|
||||
|
||||
use crate::{Adapter, Instance};
|
||||
use crate::{Adapter, Instance, Surface};
|
||||
|
||||
/// Get a set of backend bits from the environment variable WGPU_BACKEND.
|
||||
pub fn backend_bits_from_env() -> Option<Backends> {
|
||||
@ -72,6 +72,7 @@ pub fn initialize_adapter_from_env(
|
||||
pub async fn initialize_adapter_from_env_or_default(
|
||||
instance: &Instance,
|
||||
backend_bits: wgt::Backends,
|
||||
compatible_surface: Option<&Surface>,
|
||||
) -> Option<Adapter> {
|
||||
match initialize_adapter_from_env(instance, backend_bits) {
|
||||
Some(a) => Some(a),
|
||||
@ -80,7 +81,7 @@ pub async fn initialize_adapter_from_env_or_default(
|
||||
.request_adapter(&RequestAdapterOptions {
|
||||
power_preference: power_preference_from_env()
|
||||
.unwrap_or_else(PowerPreference::default),
|
||||
compatible_surface: None,
|
||||
compatible_surface,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -186,6 +186,7 @@ pub fn initialize_test(parameters: TestParameters, test_function: impl FnOnce(Te
|
||||
let adapter = pollster::block_on(util::initialize_adapter_from_env_or_default(
|
||||
&instance,
|
||||
backend_bits,
|
||||
None,
|
||||
))
|
||||
.expect("could not find sutable adapter on the system");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user