mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 13:20:05 -04:00
[wgpu] Expose wgpu::Adapter via RenderState (#2954)
* [wgpu] Expose adapter, better errors, better docs, more code sharing, use stencil bits * doc fix * remove unnecessary unsafe * handle missing framebuffer format * better handling of renderstate creation in winit.rs * remove unnecessary use directive
This commit is contained in:
@@ -80,7 +80,7 @@ egui = { version = "0.21.0", path = "../egui", default-features = false, feature
|
||||
"log",
|
||||
] }
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
thiserror = "1.0.37"
|
||||
thiserror.workspace = true
|
||||
|
||||
#! ### Optional dependencies
|
||||
## Enable this when generating docs.
|
||||
|
||||
@@ -312,10 +312,6 @@ pub struct NativeOptions {
|
||||
/// Sets the number of bits in the depth buffer.
|
||||
///
|
||||
/// `egui` doesn't need the depth buffer, so the default value is 0.
|
||||
///
|
||||
/// On `wgpu` backends, due to limited depth texture format options, this
|
||||
/// will be interpreted as a boolean (non-zero = true) for whether or not
|
||||
/// specifically a `Depth32Float` buffer is used.
|
||||
pub depth_buffer: u8,
|
||||
|
||||
/// Sets the number of bits in the stencil buffer.
|
||||
@@ -475,6 +471,12 @@ pub struct WebOptions {
|
||||
/// Default: `Theme::Dark`.
|
||||
pub default_theme: Theme,
|
||||
|
||||
/// Sets the number of bits in the depth buffer.
|
||||
///
|
||||
/// `egui` doesn't need the depth buffer, so the default value is 0.
|
||||
/// Unused by webgl context as of writing.
|
||||
pub depth_buffer: u8,
|
||||
|
||||
/// Which version of WebGl context to select
|
||||
///
|
||||
/// Default: [`WebGlContextOption::BestFirst`].
|
||||
@@ -492,6 +494,7 @@ impl Default for WebOptions {
|
||||
Self {
|
||||
follow_system_theme: true,
|
||||
default_theme: Theme::Dark,
|
||||
depth_buffer: 0,
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
webgl_context_option: WebGlContextOption::BestFirst,
|
||||
|
||||
@@ -1122,9 +1122,7 @@ mod wgpu_integration {
|
||||
) -> std::result::Result<(), egui_wgpu::WgpuError> {
|
||||
self.window = Some(window);
|
||||
if let Some(running) = &mut self.running {
|
||||
unsafe {
|
||||
pollster::block_on(running.painter.set_window(self.window.as_ref()))?;
|
||||
}
|
||||
pollster::block_on(running.painter.set_window(self.window.as_ref()))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1134,9 +1132,7 @@ mod wgpu_integration {
|
||||
fn drop_window(&mut self) -> std::result::Result<(), egui_wgpu::WgpuError> {
|
||||
self.window = None;
|
||||
if let Some(running) = &mut self.running {
|
||||
unsafe {
|
||||
pollster::block_on(running.painter.set_window(None))?;
|
||||
}
|
||||
pollster::block_on(running.painter.set_window(None))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1148,16 +1144,16 @@ mod wgpu_integration {
|
||||
window: winit::window::Window,
|
||||
) -> std::result::Result<(), egui_wgpu::WgpuError> {
|
||||
#[allow(unsafe_code, unused_mut, unused_unsafe)]
|
||||
let painter = unsafe {
|
||||
let mut painter = egui_wgpu::winit::Painter::new(
|
||||
self.native_options.wgpu_options.clone(),
|
||||
self.native_options.multisampling.max(1) as _,
|
||||
let mut painter = egui_wgpu::winit::Painter::new(
|
||||
self.native_options.wgpu_options.clone(),
|
||||
self.native_options.multisampling.max(1) as _,
|
||||
egui_wgpu::depth_format_from_bits(
|
||||
self.native_options.depth_buffer,
|
||||
self.native_options.transparent,
|
||||
);
|
||||
pollster::block_on(painter.set_window(Some(&window)))?;
|
||||
painter
|
||||
};
|
||||
self.native_options.stencil_buffer,
|
||||
),
|
||||
self.native_options.transparent,
|
||||
);
|
||||
pollster::block_on(painter.set_window(Some(&window)))?;
|
||||
|
||||
let wgpu_render_state = painter.render_state();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::sync::Arc;
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::HtmlCanvasElement;
|
||||
|
||||
use egui::mutex::RwLock;
|
||||
use egui_wgpu::{renderer::ScreenDescriptor, RenderState, SurfaceErrorAction};
|
||||
|
||||
use crate::WebOptions;
|
||||
@@ -99,43 +98,20 @@ impl WebPainterWgpu {
|
||||
}
|
||||
.map_err(|err| format!("failed to create wgpu surface: {err}"))?;
|
||||
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: options.wgpu_options.power_preference,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: None,
|
||||
})
|
||||
.await
|
||||
.ok_or_else(|| "No suitable GPU adapters found on the system".to_owned())?;
|
||||
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
&(*options.wgpu_options.device_descriptor)(&adapter),
|
||||
None, // Capture doesn't work in the browser environment.
|
||||
)
|
||||
.await
|
||||
.map_err(|err| format!("Failed to find wgpu device: {}", err))?;
|
||||
|
||||
let target_format =
|
||||
egui_wgpu::preferred_framebuffer_format(&surface.get_capabilities(&adapter).formats);
|
||||
|
||||
let depth_format = options.wgpu_options.depth_format;
|
||||
let renderer = egui_wgpu::Renderer::new(&device, target_format, depth_format, 1);
|
||||
let render_state = RenderState {
|
||||
device: Arc::new(device),
|
||||
queue: Arc::new(queue),
|
||||
target_format,
|
||||
renderer: Arc::new(RwLock::new(renderer)),
|
||||
};
|
||||
let depth_format = egui_wgpu::depth_format_from_bits(options.depth_buffer, 0);
|
||||
let render_state =
|
||||
RenderState::create(&options.wgpu_options, &instance, &surface, depth_format, 1)
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
let surface_configuration = wgpu::SurfaceConfiguration {
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
format: target_format,
|
||||
format: render_state.target_format,
|
||||
width: 0,
|
||||
height: 0,
|
||||
present_mode: options.wgpu_options.present_mode,
|
||||
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
||||
view_formats: vec![target_format],
|
||||
view_formats: vec![render_state.target_format],
|
||||
};
|
||||
|
||||
log::debug!("wgpu painter initialized.");
|
||||
|
||||
Reference in New Issue
Block a user