1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 23:21:08 +03:00

add some config options to influence webgpu selection

This commit is contained in:
Wez Furlong 2022-11-18 08:08:46 -07:00
parent 883e2d11d7
commit 783b39aae1
No known key found for this signature in database
6 changed files with 189 additions and 24 deletions

View File

@ -22,8 +22,9 @@ use crate::unix::UnixDomain;
use crate::wsl::WslDomain;
use crate::{
default_config_with_overrides_applied, default_one_point_oh, default_one_point_oh_f64,
default_true, KeyMapPreference, LoadedConfig, MouseEventTriggerMods, RgbaColor, CONFIG_DIR,
CONFIG_FILE_OVERRIDE, CONFIG_OVERRIDES, CONFIG_SKIP, HOME_DIR,
default_true, GpuInfo, KeyMapPreference, LoadedConfig, MouseEventTriggerMods, RgbaColor,
WebGpuPowerPreference, CONFIG_DIR, CONFIG_FILE_OVERRIDE, CONFIG_OVERRIDES, CONFIG_SKIP,
HOME_DIR,
};
use anyhow::Context;
use luahelper::impl_lua_conversion_dynamic;
@ -262,6 +263,18 @@ pub struct Config {
#[dynamic(default)]
pub front_end: FrontEndSelection,
/// Whether to select the higher powered discrete GPU when
/// the system has a choice of integrated or discrete.
/// Defaults to low power.
#[dynamic(default)]
pub webgpu_power_preference: WebGpuPowerPreference,
#[dynamic(default)]
pub webgpu_force_fallback_adapater: bool,
#[dynamic(default)]
pub webgpu_preferred_adapter: Option<GpuInfo>,
#[dynamic(default = "WslDomain::default_domains")]
pub wsl_domains: Vec<WslDomain>,

View File

@ -1,3 +1,4 @@
use luahelper::impl_lua_conversion_dynamic;
use wezterm_dynamic::{FromDynamic, ToDynamic};
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromDynamic, ToDynamic)]
@ -12,3 +13,50 @@ impl Default for FrontEndSelection {
FrontEndSelection::OpenGL
}
}
/// Corresponds to <https://docs.rs/wgpu/latest/wgpu/struct.AdapterInfo.html>
#[derive(Debug, Clone, FromDynamic, ToDynamic)]
pub struct GpuInfo {
pub name: String,
pub device_type: String,
pub backend: String,
pub driver: Option<String>,
pub driver_info: Option<String>,
pub vendor: Option<usize>,
pub device: Option<usize>,
}
impl_lua_conversion_dynamic!(GpuInfo);
impl ToString for GpuInfo {
fn to_string(&self) -> String {
let mut result = format!(
"name={}, device_type={}, backend={}",
self.name, self.device_type, self.backend
);
if let Some(driver) = &self.driver {
result.push_str(&format!(", driver={driver}"));
}
if let Some(driver_info) = &self.driver_info {
result.push_str(&format!(", driver_info={driver_info}"));
}
if let Some(vendor) = &self.vendor {
result.push_str(&format!(", vendor={vendor}"));
}
if let Some(device) = &self.device {
result.push_str(&format!(", device={device}"));
}
result
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromDynamic, ToDynamic)]
pub enum WebGpuPowerPreference {
LowPower,
HighPerformance,
}
impl Default for WebGpuPowerPreference {
fn default() -> Self {
Self::LowPower
}
}

View File

@ -1,7 +1,7 @@
use super::glyphcache::GlyphCache;
use super::quad::*;
use super::utilsprites::{RenderMetrics, UtilSprites};
use crate::termwindow::webgpu::{WebGpuState, WebGpuTexture};
use crate::termwindow::webgpu::{adapter_info_to_gpu_info, WebGpuState, WebGpuTexture};
use ::window::bitmaps::atlas::OutOfTextureSpace;
use ::window::bitmaps::Texture2d;
use ::window::glium::backend::Context as GliumContext;
@ -114,11 +114,8 @@ impl RenderContext {
ctx.get_opengl_version_string()
),
Self::WebGpu(state) => {
let info = &state.adapter_info;
format!(
"WebGPU: adapter={}, device_type={:?}, driver={}, driver_info={}, backend={:?}",
info.name, info.device_type, info.driver, info.driver_info, info.backend
)
let info = adapter_info_to_gpu_info(state.adapter_info.clone());
format!("WebGPU: {}", info.to_string())
}
}
}

View File

@ -3,7 +3,7 @@ use crate::inputmap::InputMap;
use config::keyassignment::KeyTable;
use config::lua::get_or_create_sub_module;
use config::lua::mlua::{self, Lua};
use config::{DeferredKeyCode, Key, KeyNoAction};
use config::{DeferredKeyCode, GpuInfo, Key, KeyNoAction};
use luahelper::dynamic_to_lua_value;
use mux::window::WindowId as MuxWindowId;
use std::collections::HashMap;
@ -69,5 +69,21 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> {
})?,
)?;
window_mod.set(
"enumerate_gpus",
lua.create_function(|_, _: ()| {
let backends = wgpu::Backends::all();
let instance = wgpu::Instance::new(backends);
let gpus: Vec<GpuInfo> = instance
.enumerate_adapters(backends)
.map(|adapter| {
let info = adapter.get_info();
crate::termwindow::webgpu::adapter_info_to_gpu_info(info)
})
.collect();
Ok(gpus)
})?,
)?;
Ok(())
}

View File

@ -811,9 +811,9 @@ impl TermWindow {
{
let mut myself = tw.borrow_mut();
let webgpu = match config.front_end {
FrontEndSelection::WebGpu => {
Some(Rc::new(WebGpuState::new(&window, dimensions).await?))
}
FrontEndSelection::WebGpu => Some(Rc::new(
WebGpuState::new(&window, dimensions, &config).await?,
)),
_ => None,
};
myself.config_subscription.replace(config_subscription);

View File

@ -1,5 +1,6 @@
use crate::quad::Vertex;
use anyhow::anyhow;
use config::{ConfigHandle, GpuInfo, WebGpuPowerPreference};
use std::cell::RefCell;
use std::num::NonZeroU32;
use std::sync::Arc;
@ -141,24 +142,114 @@ impl WebGpuTexture {
}
}
pub fn adapter_info_to_gpu_info(info: wgpu::AdapterInfo) -> GpuInfo {
GpuInfo {
name: info.name,
vendor: Some(info.vendor),
device: Some(info.device),
device_type: format!("{:?}", info.device_type),
driver: if info.driver.is_empty() {
None
} else {
Some(info.driver)
},
driver_info: if info.driver_info.is_empty() {
None
} else {
Some(info.driver_info)
},
backend: format!("{:?}", info.backend),
}
}
impl WebGpuState {
pub async fn new(window: &Window, dimensions: Dimensions) -> anyhow::Result<Self> {
pub async fn new(
window: &Window,
dimensions: Dimensions,
config: &ConfigHandle,
) -> anyhow::Result<Self> {
let handle = RawHandlePair::new(window);
Self::new_impl(handle, dimensions).await
Self::new_impl(handle, dimensions, config).await
}
pub async fn new_impl(handle: RawHandlePair, dimensions: Dimensions) -> anyhow::Result<Self> {
let instance = wgpu::Instance::new(wgpu::Backends::all());
pub async fn new_impl(
handle: RawHandlePair,
dimensions: Dimensions,
config: &ConfigHandle,
) -> anyhow::Result<Self> {
let backends = wgpu::Backends::all();
let instance = wgpu::Instance::new(backends);
let surface = unsafe { instance.create_surface(&handle) };
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: Some(&surface),
force_fallback_adapter: false,
})
.await
.ok_or_else(|| anyhow!("no matching adapter found"))?;
let mut adapter: Option<wgpu::Adapter> = None;
if let Some(preference) = &config.webgpu_preferred_adapter {
for a in instance.enumerate_adapters(backends) {
if !a.is_surface_supported(&surface) {
let info = adapter_info_to_gpu_info(a.get_info());
log::warn!("{} is not compatible with surface", info.to_string());
continue;
}
let info = a.get_info();
if preference.name != info.name {
continue;
}
if preference.device_type != format!("{:?}", info.device_type) {
continue;
}
if preference.backend != format!("{:?}", info.backend) {
continue;
}
if let Some(driver) = &preference.driver {
if *driver != info.driver {
continue;
}
}
if let Some(vendor) = &preference.vendor {
if *vendor != info.vendor {
continue;
}
}
if let Some(device) = &preference.device {
if *device != info.device {
continue;
}
}
adapter.replace(a);
break;
}
if adapter.is_none() {
log::warn!(
"Your webgpu preferred adapter '{}' was either not \
found or is not compatible with your display",
preference.to_string()
);
}
}
if adapter.is_none() {
adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: match config.webgpu_power_preference {
WebGpuPowerPreference::HighPerformance => {
wgpu::PowerPreference::HighPerformance
}
WebGpuPowerPreference::LowPower => wgpu::PowerPreference::LowPower,
},
compatible_surface: Some(&surface),
force_fallback_adapter: config.webgpu_force_fallback_adapater,
})
.await;
}
let adapter = adapter.ok_or_else(|| anyhow!("no matching adapter found"))?;
let adapter_info = adapter.get_info();
log::trace!("Using adapter: {adapter_info:?}");