mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-18 22:26:09 +00:00
Merge pull request #2038 from hannobraun/render
Try all adapters, if one fails to return a device
This commit is contained in:
commit
6f9b3e2f41
@ -1,3 +1,5 @@
|
||||
use tracing::{debug, error};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Device {
|
||||
pub device: wgpu::Device,
|
||||
@ -5,9 +7,66 @@ pub struct Device {
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub async fn from_preferred_adapter(
|
||||
instance: &wgpu::Instance,
|
||||
surface: &wgpu::Surface,
|
||||
) -> Result<(Self, wgpu::Adapter, wgpu::Features), DeviceError> {
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::None,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: Some(surface),
|
||||
})
|
||||
.await
|
||||
.ok_or(DeviceError::RequestAdapter)?;
|
||||
|
||||
debug!("Using adapter: {:?}", adapter.get_info());
|
||||
|
||||
let (device, features) = Device::new(&adapter).await?;
|
||||
|
||||
Ok((device, adapter, features))
|
||||
}
|
||||
|
||||
pub async fn try_from_all_adapters(
|
||||
instance: &wgpu::Instance,
|
||||
) -> Result<(Self, wgpu::Adapter, wgpu::Features), DeviceError> {
|
||||
let mut all_adapters =
|
||||
instance.enumerate_adapters(wgpu::Backends::all());
|
||||
|
||||
let result = loop {
|
||||
let Some(adapter) = all_adapters.next() else {
|
||||
debug!("No more adapters to try");
|
||||
break None;
|
||||
};
|
||||
|
||||
let (device, features) = match Device::new(&adapter).await {
|
||||
Ok((device, adapter)) => (device, adapter),
|
||||
Err(err) => {
|
||||
error!(
|
||||
"Failed to get device from adapter {:?}: {:?}",
|
||||
adapter.get_info(),
|
||||
err,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
break Some((device, adapter, features));
|
||||
};
|
||||
|
||||
for adapter in all_adapters {
|
||||
debug!(
|
||||
"Remaining adapter that wasn't tried: {:?}",
|
||||
adapter.get_info()
|
||||
);
|
||||
}
|
||||
|
||||
result.ok_or(DeviceError::FoundNoWorkingAdapter)
|
||||
}
|
||||
|
||||
pub async fn new(
|
||||
adapter: &wgpu::Adapter,
|
||||
) -> Result<(Self, wgpu::Features), wgpu::RequestDeviceError> {
|
||||
) -> Result<(Self, wgpu::Features), DeviceError> {
|
||||
let features = {
|
||||
let desired_features = wgpu::Features::POLYGON_MODE_LINE;
|
||||
let available_features = adapter.features();
|
||||
@ -49,3 +108,19 @@ impl Device {
|
||||
Ok((Device { device, queue }, features))
|
||||
}
|
||||
}
|
||||
|
||||
/// Render device initialization error
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DeviceError {
|
||||
/// Failed to request adapter
|
||||
#[error("Failed to request adapter")]
|
||||
RequestAdapter,
|
||||
|
||||
/// Failed to request device
|
||||
#[error("Failed to request device")]
|
||||
RequestDevice(#[from] wgpu::RequestDeviceError),
|
||||
|
||||
/// Found no working adapter to get a device from
|
||||
#[error("Found no working adapter to get a device from")]
|
||||
FoundNoWorkingAdapter,
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ mod uniforms;
|
||||
mod vertices;
|
||||
|
||||
pub use self::{
|
||||
device::DeviceError,
|
||||
draw_config::DrawConfig,
|
||||
renderer::{DrawError, Renderer, RendererInitError},
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{io, mem::size_of, vec};
|
||||
|
||||
use thiserror::Error;
|
||||
use tracing::{debug, trace};
|
||||
use tracing::{debug, error, trace};
|
||||
use wgpu::util::DeviceExt as _;
|
||||
|
||||
use crate::{
|
||||
@ -13,7 +13,7 @@ use super::{
|
||||
device::Device, draw_config::DrawConfig, drawables::Drawables,
|
||||
geometries::Geometries, navigation_cube::NavigationCubeRenderer,
|
||||
pipelines::Pipelines, transform::Transform, uniforms::Uniforms,
|
||||
vertices::Vertices, DEPTH_FORMAT, SAMPLE_COUNT,
|
||||
vertices::Vertices, DeviceError, DEPTH_FORMAT, SAMPLE_COUNT,
|
||||
};
|
||||
|
||||
/// Graphics rendering state and target abstraction
|
||||
@ -50,18 +50,28 @@ impl Renderer {
|
||||
debug!("Available adapter: {:?}", adapter.get_info());
|
||||
}
|
||||
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::None,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: Some(&surface),
|
||||
})
|
||||
.await
|
||||
.ok_or(RendererInitError::RequestAdapter)?;
|
||||
let result = Device::from_preferred_adapter(&instance, &surface).await;
|
||||
let (device, adapter, features) = match result {
|
||||
Ok((device, adapter, features)) => (device, adapter, features),
|
||||
Err(_) => {
|
||||
error!("Failed to acquire device from preferred adapter");
|
||||
|
||||
debug!("Using adapter: {:?}", adapter.get_info());
|
||||
match Device::try_from_all_adapters(&instance).await {
|
||||
Ok((device, adapter, features)) => {
|
||||
(device, adapter, features)
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Prepend `RUST_LOG=fj_viewer=debug` and re-run");
|
||||
error!("Then open an issue and post your output");
|
||||
error!(
|
||||
"https://github.com/hannobraun/fornjot/issues/new"
|
||||
);
|
||||
|
||||
let (device, features) = Device::new(&adapter).await?;
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let color_format = 'color_format: {
|
||||
let capabilities = surface.get_capabilities(&adapter);
|
||||
@ -374,15 +384,9 @@ pub enum RendererInitError {
|
||||
#[error("Error creating surface")]
|
||||
CreateSurface(#[from] wgpu::CreateSurfaceError),
|
||||
|
||||
/// Graphics accelerator acquisition error
|
||||
#[error("Error request adapter")]
|
||||
RequestAdapter,
|
||||
|
||||
/// Device request errors
|
||||
///
|
||||
/// See: [wgpu::RequestDeviceError](https://docs.rs/wgpu/latest/wgpu/struct.RequestDeviceError.html)
|
||||
#[error("Error requesting device")]
|
||||
RequestDevice(#[from] wgpu::RequestDeviceError),
|
||||
/// Device error
|
||||
#[error(transparent)]
|
||||
Device(#[from] DeviceError),
|
||||
}
|
||||
|
||||
/// Draw error
|
||||
|
@ -18,7 +18,7 @@ mod screen;
|
||||
mod viewer;
|
||||
|
||||
pub use self::{
|
||||
graphics::RendererInitError,
|
||||
graphics::{DeviceError, RendererInitError},
|
||||
input::InputEvent,
|
||||
screen::{NormalizedScreenPosition, Screen, ScreenSize},
|
||||
viewer::Viewer,
|
||||
|
Loading…
Reference in New Issue
Block a user