mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-19 06:36:11 +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)]
|
#[derive(Debug)]
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
pub device: wgpu::Device,
|
pub device: wgpu::Device,
|
||||||
@ -5,9 +7,66 @@ pub struct Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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(
|
pub async fn new(
|
||||||
adapter: &wgpu::Adapter,
|
adapter: &wgpu::Adapter,
|
||||||
) -> Result<(Self, wgpu::Features), wgpu::RequestDeviceError> {
|
) -> Result<(Self, wgpu::Features), DeviceError> {
|
||||||
let features = {
|
let features = {
|
||||||
let desired_features = wgpu::Features::POLYGON_MODE_LINE;
|
let desired_features = wgpu::Features::POLYGON_MODE_LINE;
|
||||||
let available_features = adapter.features();
|
let available_features = adapter.features();
|
||||||
@ -49,3 +108,19 @@ impl Device {
|
|||||||
Ok((Device { device, queue }, features))
|
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;
|
mod vertices;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
|
device::DeviceError,
|
||||||
draw_config::DrawConfig,
|
draw_config::DrawConfig,
|
||||||
renderer::{DrawError, Renderer, RendererInitError},
|
renderer::{DrawError, Renderer, RendererInitError},
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{io, mem::size_of, vec};
|
use std::{io, mem::size_of, vec};
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, error, trace};
|
||||||
use wgpu::util::DeviceExt as _;
|
use wgpu::util::DeviceExt as _;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -13,7 +13,7 @@ use super::{
|
|||||||
device::Device, draw_config::DrawConfig, drawables::Drawables,
|
device::Device, draw_config::DrawConfig, drawables::Drawables,
|
||||||
geometries::Geometries, navigation_cube::NavigationCubeRenderer,
|
geometries::Geometries, navigation_cube::NavigationCubeRenderer,
|
||||||
pipelines::Pipelines, transform::Transform, uniforms::Uniforms,
|
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
|
/// Graphics rendering state and target abstraction
|
||||||
@ -50,18 +50,28 @@ impl Renderer {
|
|||||||
debug!("Available adapter: {:?}", adapter.get_info());
|
debug!("Available adapter: {:?}", adapter.get_info());
|
||||||
}
|
}
|
||||||
|
|
||||||
let adapter = instance
|
let result = Device::from_preferred_adapter(&instance, &surface).await;
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
let (device, adapter, features) = match result {
|
||||||
power_preference: wgpu::PowerPreference::None,
|
Ok((device, adapter, features)) => (device, adapter, features),
|
||||||
force_fallback_adapter: false,
|
Err(_) => {
|
||||||
compatible_surface: Some(&surface),
|
error!("Failed to acquire device from preferred adapter");
|
||||||
})
|
|
||||||
.await
|
|
||||||
.ok_or(RendererInitError::RequestAdapter)?;
|
|
||||||
|
|
||||||
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 color_format = 'color_format: {
|
||||||
let capabilities = surface.get_capabilities(&adapter);
|
let capabilities = surface.get_capabilities(&adapter);
|
||||||
@ -374,15 +384,9 @@ pub enum RendererInitError {
|
|||||||
#[error("Error creating surface")]
|
#[error("Error creating surface")]
|
||||||
CreateSurface(#[from] wgpu::CreateSurfaceError),
|
CreateSurface(#[from] wgpu::CreateSurfaceError),
|
||||||
|
|
||||||
/// Graphics accelerator acquisition error
|
/// Device error
|
||||||
#[error("Error request adapter")]
|
#[error(transparent)]
|
||||||
RequestAdapter,
|
Device(#[from] DeviceError),
|
||||||
|
|
||||||
/// Device request errors
|
|
||||||
///
|
|
||||||
/// See: [wgpu::RequestDeviceError](https://docs.rs/wgpu/latest/wgpu/struct.RequestDeviceError.html)
|
|
||||||
#[error("Error requesting device")]
|
|
||||||
RequestDevice(#[from] wgpu::RequestDeviceError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draw error
|
/// Draw error
|
||||||
|
@ -18,7 +18,7 @@ mod screen;
|
|||||||
mod viewer;
|
mod viewer;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
graphics::RendererInitError,
|
graphics::{DeviceError, RendererInitError},
|
||||||
input::InputEvent,
|
input::InputEvent,
|
||||||
screen::{NormalizedScreenPosition, Screen, ScreenSize},
|
screen::{NormalizedScreenPosition, Screen, ScreenSize},
|
||||||
viewer::Viewer,
|
viewer::Viewer,
|
||||||
|
Loading…
Reference in New Issue
Block a user