hal/linux: Work around Intel+Nvidia presentation conflict

This commit is contained in:
Dzmitry Malyshau 2021-09-02 14:27:27 -04:00 committed by Dzmitry Malyshau
parent 86c2a8057e
commit d23288e455
8 changed files with 45 additions and 7 deletions

View File

@ -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 {

View File

@ -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,

View File

@ -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
}
}

View File

@ -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,
}

View File

@ -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))]

View File

@ -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"))]
{

View File

@ -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
}

View File

@ -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");