From 996b274a12d048242a8fb069c195c9117272d058 Mon Sep 17 00:00:00 2001 From: Arjo Chakravarty Date: Sat, 16 Nov 2024 09:34:29 +0800 Subject: [PATCH 1/3] Ensure we pick the right gpu card in the example backend --- examples/src/framework.rs | 92 +++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/examples/src/framework.rs b/examples/src/framework.rs index ff86cc2357..9f5d748d5d 100644 --- a/examples/src/framework.rs +++ b/examples/src/framework.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use wgpu::{Instance, Surface}; +use wgpu::{Backends, Instance, Surface}; use winit::{ dpi::PhysicalSize, event::{Event, KeyEvent, StartCause, WindowEvent}, @@ -278,36 +278,63 @@ impl ExampleContext { gles_minor_version, }); surface.pre_adapter(&instance, window); - let adapter = wgpu::util::initialize_adapter_from_env_or_default(&instance, surface.get()) - .await - .expect("No suitable GPU adapters found on the system!"); - - let adapter_info = adapter.get_info(); - log::info!("Using {} ({:?})", adapter_info.name, adapter_info.backend); - - let optional_features = E::optional_features(); - let required_features = E::required_features(); - let adapter_features = adapter.features(); - assert!( - adapter_features.contains(required_features), - "Adapter does not support required features for this example: {:?}", - required_features - adapter_features - ); - - let required_downlevel_capabilities = E::required_downlevel_capabilities(); - let downlevel_capabilities = adapter.get_downlevel_capabilities(); - assert!( - downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model, - "Adapter does not support the minimum shader model required to run this example: {:?}", - required_downlevel_capabilities.shader_model - ); - assert!( - downlevel_capabilities - .flags - .contains(required_downlevel_capabilities.flags), - "Adapter does not support the downlevel capabilities required to run this example: {:?}", - required_downlevel_capabilities.flags - downlevel_capabilities.flags - ); + // Get OS Environment WGPU_ADAPTER_NAME to select the adapter + let adapter = if std::env::var("WGPU_ADAPTER_NAME").is_ok() { + let adapter = + wgpu::util::initialize_adapter_from_env_or_default(&instance, surface.get()) + .await + .expect("No suitable GPU adapters found on the system!"); + + let adapter_info = adapter.get_info(); + log::info!("Using {} ({:?})", adapter_info.name, adapter_info.backend); + + let optional_features = E::optional_features(); + let required_features = E::required_features(); + let adapter_features = adapter.features(); + assert!( + adapter_features.contains(required_features), + "Adapter does not support required features for this example: {:?}", + required_features - adapter_features + ); + + let required_downlevel_capabilities = E::required_downlevel_capabilities(); + let downlevel_capabilities = adapter.get_downlevel_capabilities(); + assert!( + downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model, + "Adapter does not support the minimum shader model required to run this example: {:?}", + required_downlevel_capabilities.shader_model + ); + assert!( + downlevel_capabilities + .flags + .contains(required_downlevel_capabilities.flags), + "Adapter does not support the downlevel capabilities required to run this example: {:?}", + required_downlevel_capabilities.flags - downlevel_capabilities.flags + ); + adapter + } else { + let adapters = instance.enumerate_adapters(Backends::all()); + + let mut chosen_adapter = None; + for adapter in adapters { + if let Some(surface) = surface.get() { + if !adapter.is_surface_supported(surface) { + continue; + } + } + + let required_features = E::required_features(); + let adapter_features = adapter.features(); + if !adapter_features.contains(required_features) { + continue; + } else { + chosen_adapter = Some(adapter); + break; + } + } + + chosen_adapter.expect("No suitable GPU adapters found on the system!") + }; // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the surface. let needed_limits = E::required_limits().using_resolution(adapter.limits()); @@ -317,7 +344,8 @@ impl ExampleContext { .request_device( &wgpu::DeviceDescriptor { label: None, - required_features: (optional_features & adapter_features) | required_features, + required_features: (E::optional_features() & adapter.features()) + | E::required_features(), required_limits: needed_limits, memory_hints: wgpu::MemoryHints::MemoryUsage, }, From 8ce55ca50b654c593eee393c6e22178d209949fa Mon Sep 17 00:00:00 2001 From: Arjo Chakravarty Date: Sun, 17 Nov 2024 11:24:26 +0800 Subject: [PATCH 2/3] Fix WASM support. --- examples/src/framework.rs | 68 ++++----------------------- examples/src/utils.rs | 99 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 58 deletions(-) diff --git a/examples/src/framework.rs b/examples/src/framework.rs index 9f5d748d5d..d228baa207 100644 --- a/examples/src/framework.rs +++ b/examples/src/framework.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use wgpu::{Backends, Instance, Surface}; +use wgpu::{Instance, Surface}; use winit::{ dpi::PhysicalSize, event::{Event, KeyEvent, StartCause, WindowEvent}, @@ -278,64 +278,14 @@ impl ExampleContext { gles_minor_version, }); surface.pre_adapter(&instance, window); - // Get OS Environment WGPU_ADAPTER_NAME to select the adapter - let adapter = if std::env::var("WGPU_ADAPTER_NAME").is_ok() { - let adapter = - wgpu::util::initialize_adapter_from_env_or_default(&instance, surface.get()) - .await - .expect("No suitable GPU adapters found on the system!"); - - let adapter_info = adapter.get_info(); - log::info!("Using {} ({:?})", adapter_info.name, adapter_info.backend); - - let optional_features = E::optional_features(); - let required_features = E::required_features(); - let adapter_features = adapter.features(); - assert!( - adapter_features.contains(required_features), - "Adapter does not support required features for this example: {:?}", - required_features - adapter_features - ); - - let required_downlevel_capabilities = E::required_downlevel_capabilities(); - let downlevel_capabilities = adapter.get_downlevel_capabilities(); - assert!( - downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model, - "Adapter does not support the minimum shader model required to run this example: {:?}", - required_downlevel_capabilities.shader_model - ); - assert!( - downlevel_capabilities - .flags - .contains(required_downlevel_capabilities.flags), - "Adapter does not support the downlevel capabilities required to run this example: {:?}", - required_downlevel_capabilities.flags - downlevel_capabilities.flags - ); - adapter - } else { - let adapters = instance.enumerate_adapters(Backends::all()); - - let mut chosen_adapter = None; - for adapter in adapters { - if let Some(surface) = surface.get() { - if !adapter.is_surface_supported(surface) { - continue; - } - } - - let required_features = E::required_features(); - let adapter_features = adapter.features(); - if !adapter_features.contains(required_features) { - continue; - } else { - chosen_adapter = Some(adapter); - break; - } - } - - chosen_adapter.expect("No suitable GPU adapters found on the system!") - }; + let adapter = get_adapter_with_capabilities_or_from_env( + &instance, + &E::required_features(), + &E::required_downlevel_capabilities(), + &surface.get(), + ) + .await; // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the surface. let needed_limits = E::required_limits().using_resolution(adapter.limits()); @@ -541,6 +491,8 @@ pub fn parse_url_query_string<'a>(query: &'a str, search_key: &str) -> Option<&' #[cfg(test)] pub use wgpu_test::image::ComparisonType; +use crate::utils::get_adapter_with_capabilities_or_from_env; + #[cfg(test)] #[derive(Clone)] pub struct ExampleTestParams { diff --git a/examples/src/utils.rs b/examples/src/utils.rs index 7b663e2bc3..fa7cc35d8d 100644 --- a/examples/src/utils.rs +++ b/examples/src/utils.rs @@ -156,3 +156,102 @@ fn create_output_image_element(document: &web_sys::Document) -> web_sys::HtmlIma log::info!("Created new output target image: {:?}", &new_image); new_image } + +#[cfg(not(target_arch = "wasm32"))] +pub(crate) async fn get_adapter_with_capabilities_or_from_env( + instance: &wgpu::Instance, + required_features: &wgpu::Features, + required_downlevel_capabilities: &wgpu::DownlevelCapabilities, + surface: &Option<&wgpu::Surface<'_>>, +) -> wgpu::Adapter { + use wgpu::Backends; + if std::env::var("WGPU_ADAPTER_NAME").is_ok() { + let adapter = wgpu::util::initialize_adapter_from_env_or_default(instance, *surface) + .await + .expect("No suitable GPU adapters found on the system!"); + + let adapter_info = adapter.get_info(); + log::info!("Using {} ({:?})", adapter_info.name, adapter_info.backend); + + let adapter_features = adapter.features(); + assert!( + adapter_features.contains(*required_features), + "Adapter does not support required features for this example: {:?}", + *required_features - adapter_features + ); + + let downlevel_capabilities = adapter.get_downlevel_capabilities(); + assert!( + downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model, + "Adapter does not support the minimum shader model required to run this example: {:?}", + required_downlevel_capabilities.shader_model + ); + assert!( + downlevel_capabilities + .flags + .contains(required_downlevel_capabilities.flags), + "Adapter does not support the downlevel capabilities required to run this example: {:?}", + required_downlevel_capabilities.flags - downlevel_capabilities.flags + ); + adapter + } else { + let adapters = instance.enumerate_adapters(Backends::all()); + + let mut chosen_adapter = None; + for adapter in adapters { + if let Some(surface) = surface { + if !adapter.is_surface_supported(surface) { + continue; + } + } + + let required_features = *required_features; + let adapter_features = adapter.features(); + if !adapter_features.contains(required_features) { + continue; + } else { + chosen_adapter = Some(adapter); + break; + } + } + + chosen_adapter.expect("No suitable GPU adapters found on the system!") + } +} + +#[cfg(target_arch = "wasm32")] +pub(crate) async fn get_adapter_with_capabilities_or_from_env( + instance: &wgpu::Instance, + required_features: &wgpu::Features, + required_downlevel_capabilities: &wgpu::DownlevelCapabilities, + surface: &Option<&wgpu::Surface<'_>>, +) -> wgpu::Adapter { + let adapter = wgpu::util::initialize_adapter_from_env_or_default(instance, *surface) + .await + .expect("No suitable GPU adapters found on the system!"); + + let adapter_info = adapter.get_info(); + log::info!("Using {} ({:?})", adapter_info.name, adapter_info.backend); + + let adapter_features = adapter.features(); + assert!( + adapter_features.contains(*required_features), + "Adapter does not support required features for this example: {:?}", + *required_features - adapter_features + ); + + let downlevel_capabilities = adapter.get_downlevel_capabilities(); + assert!( + downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model, + "Adapter does not support the minimum shader model required to run this example: {:?}", + required_downlevel_capabilities.shader_model + ); + assert!( + downlevel_capabilities + .flags + .contains(required_downlevel_capabilities.flags), + "Adapter does not support the downlevel capabilities required to run this example: {:?}", + required_downlevel_capabilities.flags - downlevel_capabilities.flags + ); + adapter +} From df50320bf43d074d641765bc0717306bcf52038e Mon Sep 17 00:00:00 2001 From: Arjo Chakravarty Date: Sun, 17 Nov 2024 11:36:06 +0800 Subject: [PATCH 3/3] Docstring. --- examples/src/utils.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/src/utils.rs b/examples/src/utils.rs index fa7cc35d8d..bbc727582b 100644 --- a/examples/src/utils.rs +++ b/examples/src/utils.rs @@ -158,6 +158,9 @@ fn create_output_image_element(document: &web_sys::Document) -> web_sys::HtmlIma } #[cfg(not(target_arch = "wasm32"))] +/// If the environment variable `WGPU_ADAPTER_NAME` is set, this function will attempt to +/// initialize the adapter with that name. If it is not set, it will attempt to initialize +/// the adapter which supports the required features. pub(crate) async fn get_adapter_with_capabilities_or_from_env( instance: &wgpu::Instance, required_features: &wgpu::Features,