Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hal/linux: Work around Intel+Nvidia presentation conflict #1898

Merged
merged 1 commit into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions wgpu-hal/src/auxil/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 5 additions & 0 deletions wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
27 changes: 25 additions & 2 deletions wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
2 changes: 2 additions & 0 deletions wgpu-hal/src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
2 changes: 2 additions & 0 deletions wgpu-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down
7 changes: 4 additions & 3 deletions wgpu/examples/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
{
Expand Down
5 changes: 3 additions & 2 deletions wgpu/src/util/init.rs
Original file line number Diff line number Diff line change
@@ -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> {
Expand Down Expand Up @@ -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),
Expand All @@ -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
}
Expand Down
1 change: 1 addition & 0 deletions wgpu/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down