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

desktop: Improve backend selection #15647

Merged
merged 3 commits into from
Mar 24, 2024
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
11 changes: 2 additions & 9 deletions desktop/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -92,7 +91,6 @@ pub struct RuffleGui {
currently_opened: Option<(Url, PlayerOptions)>,
was_suspended_before_debug: bool,
preferences: GlobalPreferences,
descriptors: Arc<Descriptors>,
}

impl RuffleGui {
Expand All @@ -101,7 +99,6 @@ impl RuffleGui {
default_path: Option<Url>,
default_player_options: PlayerOptions,
preferences: GlobalPreferences,
descriptors: Arc<Descriptors>,
) -> Self {
Self {
is_about_visible: false,
Expand All @@ -122,7 +119,6 @@ impl RuffleGui {
default_player_options,
currently_opened: None,
preferences,
descriptors,
}
}

Expand Down Expand Up @@ -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) {
Expand Down
72 changes: 47 additions & 25 deletions desktop/src/gui/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,7 @@ impl GuiController {
initial_movie_url: Option<Url>,
no_gui: bool,
) -> anyhow::Result<Self> {
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())?)
}?;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<wgpu::Instance> {
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,
Expand Down
37 changes: 23 additions & 14 deletions desktop/src/gui/preferences_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

earlier you mentioned that

I think we can remove that code now, wgpu added an api to show which backends are (roughly) available

Just wanna make sure whether that was checked :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, turns out that's unreleased still :(
wgpu::Instance::enabled_backend_features() in the next major wgpu update

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
}
4 changes: 2 additions & 2 deletions render/wgpu/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
Expand Down
Loading