diff --git a/desktop/src/gui.rs b/desktop/src/gui.rs index 634a73ea3885..17e53d318ba8 100644 --- a/desktop/src/gui.rs +++ b/desktop/src/gui.rs @@ -22,10 +22,9 @@ use fluent_templates::{static_loader, Loader}; use rfd::FileDialog; use ruffle_core::debug_ui::Message as DebugMessage; use ruffle_core::Player; -use ruffle_render_wgpu::descriptors::Descriptors; use std::collections::HashMap; use std::fs; -use std::sync::{Arc, MutexGuard}; +use std::sync::MutexGuard; use unic_langid::LanguageIdentifier; use winit::event_loop::EventLoopProxy; @@ -92,7 +91,6 @@ pub struct RuffleGui { currently_opened: Option<(Url, PlayerOptions)>, was_suspended_before_debug: bool, preferences: GlobalPreferences, - descriptors: Arc, } impl RuffleGui { @@ -101,7 +99,6 @@ impl RuffleGui { default_path: Option, default_player_options: PlayerOptions, preferences: GlobalPreferences, - descriptors: Arc, ) -> Self { Self { is_about_visible: false, @@ -122,7 +119,6 @@ impl RuffleGui { default_player_options, currently_opened: None, preferences, - descriptors, } } @@ -513,10 +509,7 @@ impl RuffleGui { } fn open_preferences(&mut self) { - self.preferences_dialog = Some(PreferencesDialog::new( - &self.descriptors, - self.preferences.clone(), - )); + self.preferences_dialog = Some(PreferencesDialog::new(self.preferences.clone())); } fn close_movie(&mut self, ui: &mut egui::Ui) { diff --git a/desktop/src/gui/controller.rs b/desktop/src/gui/controller.rs index 1d93fe196137..23f0776fcdfc 100644 --- a/desktop/src/gui/controller.rs +++ b/desktop/src/gui/controller.rs @@ -48,30 +48,7 @@ impl GuiController { initial_movie_url: Option, no_gui: bool, ) -> anyhow::Result { - let mut backend: wgpu::Backends = preferences.graphics_backends().into(); - if wgpu::Backends::SECONDARY.contains(backend) { - tracing::warn!( - "{} graphics backend support may not be fully supported.", - format_list(&get_backend_names(backend), "and") - ); - } - let mut instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: backend, - flags: wgpu::InstanceFlags::default().with_env(), - ..Default::default() - }); - if instance.enumerate_adapters(backend).is_empty() && backend != wgpu::Backends::all() { - tracing::warn!( - "Graphics backend {} is not available; falling back to any available backend", - format_list(&get_backend_names(backend), "and") - ); - backend = wgpu::Backends::all(); - instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: backend, - flags: wgpu::InstanceFlags::default().with_env(), - ..Default::default() - }); - } + let (instance, backend) = create_wgpu_instance(preferences.graphics_backends().into())?; let surface = unsafe { instance.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(window.as_ref())?) }?; @@ -135,7 +112,6 @@ impl GuiController { initial_movie_url.clone(), PlayerOptions::from(&preferences), preferences.clone(), - descriptors.clone(), ); let system_fonts = load_system_fonts(font_database, preferences.language().to_owned()).unwrap_or_default(); @@ -361,6 +337,52 @@ impl GuiController { } } +fn create_wgpu_instance( + preferred_backends: wgpu::Backends, +) -> anyhow::Result<(wgpu::Instance, wgpu::Backends)> { + for backend in preferred_backends.iter() { + if let Some(instance) = try_wgpu_backend(backend) { + tracing::info!( + "Using preferred backend {}", + format_list(&get_backend_names(backend), "and") + ); + return Ok((instance, backend)); + } + } + + tracing::warn!( + "Preferred backend(s) of {} not available; falling back to any", + format_list(&get_backend_names(preferred_backends), "or") + ); + + for backend in wgpu::Backends::all() - preferred_backends { + if let Some(instance) = try_wgpu_backend(backend) { + tracing::info!( + "Using fallback backend {}", + format_list(&get_backend_names(backend), "and") + ); + return Ok((instance, backend)); + } + } + + Err(anyhow!( + "No compatible graphics backends of any kind were available" + )) +} + +fn try_wgpu_backend(backend: wgpu::Backends) -> Option { + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: backend, + flags: wgpu::InstanceFlags::default().with_env(), + ..Default::default() + }); + if instance.enumerate_adapters(backend).is_empty() { + None + } else { + Some(instance) + } +} + // try to load known unicode supporting fonts to draw cjk characters in egui fn load_system_fonts( font_database: &Database, diff --git a/desktop/src/gui/preferences_dialog.rs b/desktop/src/gui/preferences_dialog.rs index e7cd2983fc47..d5ac4c8a3084 100644 --- a/desktop/src/gui/preferences_dialog.rs +++ b/desktop/src/gui/preferences_dialog.rs @@ -4,7 +4,6 @@ use crate::preferences::GlobalPreferences; use cpal::traits::{DeviceTrait, HostTrait}; use egui::{Align2, Button, ComboBox, Grid, Ui, Widget, Window}; use ruffle_render_wgpu::clap::{GraphicsBackend, PowerPreference}; -use ruffle_render_wgpu::descriptors::Descriptors; use std::borrow::Cow; use unic_langid::LanguageIdentifier; @@ -32,13 +31,8 @@ pub struct PreferencesDialog { } impl PreferencesDialog { - pub fn new(descriptors: &Descriptors, preferences: GlobalPreferences) -> Self { - let mut available_backends = wgpu::Backends::empty(); - - available_backends |= backend_availability(descriptors, wgpu::Backends::VULKAN); - available_backends |= backend_availability(descriptors, wgpu::Backends::GL); - available_backends |= backend_availability(descriptors, wgpu::Backends::METAL); - available_backends |= backend_availability(descriptors, wgpu::Backends::DX12); + pub fn new(preferences: GlobalPreferences) -> Self { + let available_backends = find_available_graphics_backends(); let audio_host = cpal::default_host(); let mut available_output_devices = Vec::new(); @@ -320,14 +314,29 @@ fn filename_pattern_name(locale: &LanguageIdentifier, pattern: FilenamePattern) } } -fn backend_availability(descriptors: &Descriptors, backend: wgpu::Backends) -> wgpu::Backends { - if descriptors - .wgpu_instance - .enumerate_adapters(backend) - .is_empty() - { +fn backend_availability(instance: &wgpu::Instance, backend: wgpu::Backends) -> wgpu::Backends { + if instance.enumerate_adapters(backend).is_empty() { wgpu::Backends::empty() } else { backend } } + +fn find_available_graphics_backends() -> wgpu::Backends { + let mut available_backends = wgpu::Backends::empty(); + + // We have to make a new instance here, as the one created for the entire application may not have + // all backends enabled + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + flags: wgpu::InstanceFlags::default().with_env(), + ..Default::default() + }); + + available_backends |= backend_availability(&instance, wgpu::Backends::VULKAN); + available_backends |= backend_availability(&instance, wgpu::Backends::GL); + available_backends |= backend_availability(&instance, wgpu::Backends::METAL); + available_backends |= backend_availability(&instance, wgpu::Backends::DX12); + + available_backends +} diff --git a/render/wgpu/src/backend.rs b/render/wgpu/src/backend.rs index 23e1f70d41db..cdb387925e11 100644 --- a/render/wgpu/src/backend.rs +++ b/render/wgpu/src/backend.rs @@ -1105,8 +1105,8 @@ pub async fn request_adapter_and_device( let names = get_backend_names(backend); if names.is_empty() { "Ruffle requires hardware acceleration, but no compatible graphics device was found (no backend provided?)".to_string() - } else if cfg!(any(windows, target_os = "macos")) { - format!("Ruffle does not support OpenGL on {}.", if cfg!(windows) { "Windows" } else { "macOS" }) + } else if cfg!(target_os = "macos") { + "Ruffle does not support OpenGL on macOS.".to_string() } else { format!("Ruffle requires hardware acceleration, but no compatible graphics device was found supporting {}", format_list(&names, "or")) }