Re-try adapter creation if creation with WebGPU enabled fails and WebGL was enabled. (#3895)
* Filed this in relation to the changes here https://github.com/gfx-rs/wgpu/issues/5142 * Fixes https://github.com/rerun-io/rerun/issues/4915 Draft until fully confirmed this works on Linux Chrome
This commit is contained in:
parent
5d0bc2bf7d
commit
40ed503ebd
|
|
@ -87,42 +87,100 @@ impl WebPainterWgpu {
|
||||||
pub async fn new(canvas_id: &str, options: &WebOptions) -> Result<Self, String> {
|
pub async fn new(canvas_id: &str, options: &WebOptions) -> Result<Self, String> {
|
||||||
log::debug!("Creating wgpu painter");
|
log::debug!("Creating wgpu painter");
|
||||||
|
|
||||||
{
|
let mut backends = options.wgpu_options.supported_backends;
|
||||||
|
|
||||||
|
// Don't try WebGPU if we're not in a secure context.
|
||||||
|
if backends.contains(wgpu::Backends::BROWSER_WEBGPU) {
|
||||||
let is_secure_context = web_sys::window().map_or(false, |w| w.is_secure_context());
|
let is_secure_context = web_sys::window().map_or(false, |w| w.is_secure_context());
|
||||||
if !is_secure_context {
|
if !is_secure_context {
|
||||||
log::info!(
|
log::info!(
|
||||||
"WebGPU is only available in secure contexts, i.e. on HTTPS and on localhost"
|
"WebGPU is only available in secure contexts, i.e. on HTTPS and on localhost."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Don't try WebGPU since we established now that it will fail.
|
||||||
|
backends.remove(wgpu::Backends::BROWSER_WEBGPU);
|
||||||
|
|
||||||
|
if backends.is_empty() {
|
||||||
|
return Err("No available supported graphics backends.".to_owned());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
log::debug!("Creating wgpu instance with backends {:?}", backends);
|
||||||
backends: options.wgpu_options.supported_backends,
|
let mut instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
backends,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
let canvas = super::canvas_element_or_die(canvas_id);
|
// It can happen that a browser advertises WebGPU support, but then fails to create a
|
||||||
|
// suitable adapter. As of writing this happens for example on Linux with Chrome 121.
|
||||||
|
//
|
||||||
|
// Since WebGPU is handled in a special way in wgpu, we have to recreate the instance
|
||||||
|
// if we instead want to try with WebGL.
|
||||||
|
//
|
||||||
|
// To make matters worse, once a canvas has been used with either WebGL or WebGPU,
|
||||||
|
// we can't go back and change that without replacing the canvas (which is hard to do from here).
|
||||||
|
// Therefore, we have to create the surface *after* requesting the adapter.
|
||||||
|
// However, wgpu offers to pass in a surface on adapter creation to ensure it is actually compatible with the chosen backend.
|
||||||
|
// This in turn isn't all that important on the web, but it still makes sense for the design of
|
||||||
|
// `egui::RenderState`!
|
||||||
|
// Therefore, we have to first check if it's possible to create a WebGPU adapter,
|
||||||
|
// and if it is not, start over with a WebGL instance.
|
||||||
|
//
|
||||||
|
// Note that we also might needlessly try this here if wgpu already determined that there's no
|
||||||
|
// WebGPU support in the first place. This is not a huge problem since it fails very fast, but
|
||||||
|
// it would be nice to avoid this. See https://github.com/gfx-rs/wgpu/issues/5142
|
||||||
|
if backends.contains(wgpu::Backends::BROWSER_WEBGPU) {
|
||||||
|
log::debug!("Attempting to create WebGPU adapter to check for support.");
|
||||||
|
if let Some(adapter) = instance
|
||||||
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
|
power_preference: options.wgpu_options.power_preference,
|
||||||
|
compatible_surface: None,
|
||||||
|
force_fallback_adapter: false,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// WebGPU doesn't spec yet a destroy on the adapter, only on the device.
|
||||||
|
//adapter.destroy();
|
||||||
|
log::debug!(
|
||||||
|
"Successfully created WebGPU adapter, WebGPU confirmed to be supported!"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
log::debug!("Failed to create WebGPU adapter.");
|
||||||
|
|
||||||
|
if backends.contains(wgpu::Backends::GL) {
|
||||||
|
log::debug!("Recreating wgpu instance with WebGL backend only.");
|
||||||
|
backends = wgpu::Backends::GL;
|
||||||
|
instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||||
|
backends,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Err(
|
||||||
|
"Failed to create WebGPU adapter and WebGL was not enabled.".to_owned()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let canvas = super::canvas_element_or_die(canvas_id);
|
||||||
let surface = instance
|
let surface = instance
|
||||||
.create_surface(wgpu::SurfaceTarget::Canvas(canvas.clone()))
|
.create_surface(wgpu::SurfaceTarget::Canvas(canvas.clone()))
|
||||||
.map_err(|err| format!("failed to create wgpu surface: {err}"))?;
|
.map_err(|err| format!("failed to create wgpu surface: {err}"))?;
|
||||||
|
|
||||||
let depth_format = egui_wgpu::depth_format_from_bits(options.depth_buffer, 0);
|
let depth_format = egui_wgpu::depth_format_from_bits(options.depth_buffer, 0);
|
||||||
|
|
||||||
let render_state =
|
let render_state =
|
||||||
RenderState::create(&options.wgpu_options, &instance, &surface, depth_format, 1)
|
RenderState::create(&options.wgpu_options, &instance, &surface, depth_format, 1)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| err.to_string())?;
|
.map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
let (width, height) = (0, 0);
|
|
||||||
|
|
||||||
let surface_configuration = wgpu::SurfaceConfiguration {
|
let surface_configuration = wgpu::SurfaceConfiguration {
|
||||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
|
||||||
format: render_state.target_format,
|
format: render_state.target_format,
|
||||||
present_mode: options.wgpu_options.present_mode,
|
present_mode: options.wgpu_options.present_mode,
|
||||||
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
|
||||||
view_formats: vec![render_state.target_format],
|
view_formats: vec![render_state.target_format],
|
||||||
..surface
|
..surface
|
||||||
.get_default_config(&render_state.adapter, width, height)
|
.get_default_config(&render_state.adapter, 0, 0) // Width/height is set later.
|
||||||
.ok_or("The surface isn't supported by this adapter")?
|
.ok_or("The surface isn't supported by this adapter")?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue