Use wgpu environment variables (#198)

- Enables projects using `pixels` to select GPU and backend with
  the same environment variables used by `wgpu` examples.
- cc #142
This commit is contained in:
Jay Oster 2021-09-04 15:26:30 -07:00 committed by GitHub
parent 50c77a5f83
commit c94dab65b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 36 deletions

View file

@ -50,7 +50,7 @@ resolver = "2"
### Driver issues
The most common issue is having an outdated graphics driver installed on the host machine. `pixels`
requests a low power (aka integrated) GPU by default. If the examples are not working for any reason, you may try setting the `PIXELS_HIGH_PERF` environment variable (the value does not matter, e.g. `PIXELS_HIGH_PERF=1` is fine) to see if that addresses the issue on your host machine.
requests a low power (aka integrated) GPU by default. If the examples are not working for any reason, you may try setting the `WGPU_POWER_PREF=high` environment variable to see if that addresses the issue on your host machine.
You should also try to keep your graphics drivers up-to-date, especially if you have an old Intel integrated GPU. Keep in mind that some drivers and GPUs are EOL and will not be supported.

View file

@ -2,7 +2,6 @@ use crate::renderers::{ScalingMatrix, ScalingRenderer};
use crate::SurfaceSize;
use crate::{Error, Pixels, PixelsContext, SurfaceTexture};
use raw_window_handle::HasRawWindowHandle;
use std::env;
/// A builder to help create customized pixel buffers.
pub struct PixelsBuilder<'req, 'dev, 'win, W: HasRawWindowHandle> {
@ -51,7 +50,7 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W>
PixelsBuilder {
request_adapter_options: None,
device_descriptor: wgpu::DeviceDescriptor::default(),
backend: wgpu::Backends::PRIMARY,
backend: wgpu::util::backend_bits_from_env().unwrap_or(wgpu::Backends::PRIMARY),
width,
height,
_pixel_aspect_ratio: 1.0,
@ -194,17 +193,25 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle> PixelsBuilder<'req, 'dev, 'win, W>
// TODO: Use `options.pixel_aspect_ratio` to stretch the scaled texture
let surface = unsafe { instance.create_surface(self.surface_texture.window) };
let compatible_surface = Some(&surface);
let adapter = instance.request_adapter(&self.request_adapter_options.map_or_else(
|| wgpu::RequestAdapterOptions {
compatible_surface,
power_preference: get_default_power_preference(),
},
|rao| wgpu::RequestAdapterOptions {
compatible_surface: rao.compatible_surface.or(compatible_surface),
power_preference: rao.power_preference,
},
));
let adapter = pollster::block_on(adapter).ok_or(Error::AdapterNotFound)?;
let request_adapter_options = &self.request_adapter_options;
let adapter =
wgpu::util::initialize_adapter_from_env(&instance, self.backend).or_else(|| {
let future =
instance.request_adapter(&request_adapter_options.as_ref().map_or_else(
|| wgpu::RequestAdapterOptions {
compatible_surface,
power_preference:
wgpu::util::power_preference_from_env().unwrap_or_default(),
},
|rao| wgpu::RequestAdapterOptions {
compatible_surface: rao.compatible_surface.or(compatible_surface),
power_preference: rao.power_preference,
},
));
pollster::block_on(future)
});
let adapter = adapter.ok_or(Error::AdapterNotFound)?;
let (device, queue) =
pollster::block_on(adapter.request_device(&self.device_descriptor, None))
@ -459,14 +466,3 @@ const fn get_texture_format_size(texture_format: wgpu::TextureFormat) -> f32 {
| Astc12x12RgbaUnormSrgb => 9.0, // 12.0 * 12.0 / 16.0
}
}
fn get_default_power_preference() -> wgpu::PowerPreference {
env::var("PIXELS_HIGH_PERF").map_or_else(
|_| {
env::var("PIXELS_LOW_POWER").map_or(wgpu::PowerPreference::default(), |_| {
wgpu::PowerPreference::LowPower
})
},
|_| wgpu::PowerPreference::HighPerformance,
)
}

View file

@ -12,19 +12,22 @@
//!
//! # Environment variables
//!
//! * `PIXELS_HIGH_PERF`: Switch the default adapter to high performance.
//! * `PIXELS_LOW_POWER`: Switch the default adapter to low power.
//! Pixels will default to selecting the most powerful GPU and most modern graphics API available on
//! the system, and these choices can be overridden with environment variables. These are the same
//! vars supported by the [`wgpu` examples](https://github.com/gfx-rs/wgpu/tree/v0.10/wgpu#usage).
//!
//! These variables change the default adapter to request either high performance or low power.
//! (I.e. discrete or integrated GPUs.) The value is not checked, only the existence
//! of the variable is relevant.
//! * `WGPU_BACKEND`: Select the backend (aka graphics API).
//! * Supported values: `vulkan`, `metal`, `dx11`, `dx12`, `gl`, `webgpu`
//! * The default depends on capabilities of the host system, with `vulkan` being preferred on
//! Linux and Windows, and `metal` preferred on macOS.
//! * `WGPU_ADAPTER_NAME`: Select an adapter (aka GPU) with substring matching.
//! * E.g. `1080` will match `NVIDIA GeForce 1080ti`
//! * `WGPU_POWER_PREF`: Select an adapter (aka GPU) that meets the given power profile.
//! * Supported values: `low`, `high`
//! * The default is `low`. I.e. an integrated GPU will be preferred over a discrete GPU.
//!
//! The order of precedence for choosing a power preference is:
//!
//! 1. Application's specific adapter request through [`PixelsBuilder::request_adapter_options`]
//! 2. `PIXELS_HIGH_PERF`
//! 3. `PIXELS_LOW_POWER`
//! 4. `wgpu` default power preference (usually low power)
//! Note that `WGPU_ADAPTER_NAME` and `WGPU_POWER_PREF` are mutually exclusive and that
//! `WGPU_ADAPTER_NAME` takes precedence.
#![deny(clippy::all)]