mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 14:49:06 -04:00
Make wgpu the default renderer for eframe and egui.rs (#7615)
* Closes https://github.com/emilk/egui/issues/5889 See the above issue for motivation. To use glow instead, disable the default features of `eframe` and opt-in to `glow`. This also changes egui.rs to use wgpu, which means WebGPU when available, and WebGL otherwise
This commit is contained in:
@@ -232,6 +232,7 @@ iter_on_single_items = "warn"
|
||||
iter_over_hash_type = "warn"
|
||||
iter_without_into_iter = "warn"
|
||||
large_digit_groups = "warn"
|
||||
large_futures = "warn"
|
||||
large_include_file = "warn"
|
||||
large_stack_arrays = "warn"
|
||||
large_stack_frames = "warn"
|
||||
@@ -329,6 +330,7 @@ unnecessary_semicolon = "warn"
|
||||
unnecessary_struct_initialization = "warn"
|
||||
unnecessary_wraps = "warn"
|
||||
unnested_or_patterns = "warn"
|
||||
unused_async = "warn"
|
||||
unused_peekable = "warn"
|
||||
unused_rounding = "warn"
|
||||
unused_self = "warn"
|
||||
|
||||
@@ -28,9 +28,9 @@ workspace = true
|
||||
default = [
|
||||
"accesskit",
|
||||
"default_fonts",
|
||||
"glow",
|
||||
"wayland", # Required for Linux support (including CI!)
|
||||
"web_screen_reader",
|
||||
"wgpu",
|
||||
"winit/default",
|
||||
"x11",
|
||||
]
|
||||
@@ -52,7 +52,11 @@ android-native-activity = ["egui-winit/android-native-activity"]
|
||||
## If you plan on specifying your own fonts you may disable this feature.
|
||||
default_fonts = ["egui/default_fonts"]
|
||||
|
||||
## Use [`glow`](https://github.com/grovesNL/glow) for painting, via [`egui_glow`](https://github.com/emilk/egui/tree/main/crates/egui_glow).
|
||||
## Enable [`glow`](https://github.com/grovesNL/glow) for painting, via [`egui_glow`](https://github.com/emilk/egui/tree/main/crates/egui_glow).
|
||||
##
|
||||
## There is generally no need to enable both the `wgpu` and `glow` features,
|
||||
## but if you do you can pick the renderer to use with [`NativeOptions::renderer`]
|
||||
## and `WebOptions::renderer`.
|
||||
glow = ["dep:egui_glow", "dep:glow", "dep:glutin-winit", "dep:glutin"]
|
||||
|
||||
## Enable saving app state to disk.
|
||||
@@ -74,9 +78,15 @@ wayland = [
|
||||
## For other platforms, use the `accesskit` feature instead.
|
||||
web_screen_reader = ["web-sys/SpeechSynthesis", "web-sys/SpeechSynthesisUtterance"]
|
||||
|
||||
## Use [`wgpu`](https://docs.rs/wgpu) for painting (via [`egui-wgpu`](https://github.com/emilk/egui/tree/main/crates/egui-wgpu)).
|
||||
## Enable [`wgpu`](https://docs.rs/wgpu) for painting (via [`egui-wgpu`](https://github.com/emilk/egui/tree/main/crates/egui-wgpu)).
|
||||
##
|
||||
## This overrides the `glow` feature.
|
||||
## There is generally no need to enable both the `wgpu` and `glow` features,
|
||||
## but if you do you can pick the renderer to use with [`NativeOptions::renderer`]
|
||||
## and `WebOptions::renderer`.
|
||||
##
|
||||
## Switching from `wgpu (the default)` to `glow` can significantly reduce your binary size
|
||||
## (including the .wasm of a web app).
|
||||
## See <https://github.com/emilk/egui/issues/5889> for more details.
|
||||
##
|
||||
## By default, eframe will prefer WebGPU over WebGL, but
|
||||
## you can configure this at run-time with [`NativeOptions::wgpu_options`].
|
||||
|
||||
@@ -471,6 +471,10 @@ impl Default for NativeOptions {
|
||||
/// Options when using `eframe` in a web page.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub struct WebOptions {
|
||||
/// What rendering backend to use.
|
||||
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
|
||||
pub renderer: Renderer,
|
||||
|
||||
/// Sets the number of bits in the depth buffer.
|
||||
///
|
||||
/// `egui` doesn't need the depth buffer, so the default value is 0.
|
||||
@@ -519,6 +523,9 @@ pub struct WebOptions {
|
||||
impl Default for WebOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
|
||||
renderer: Renderer::default(),
|
||||
|
||||
depth_buffer: 0,
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
@@ -592,8 +599,8 @@ impl Default for Renderer {
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
return Self::Wgpu;
|
||||
|
||||
// By default, only the `glow` feature is enabled, so if the user added `wgpu` to the feature list
|
||||
// they probably wanted to use wgpu:
|
||||
// It's weird that the user has enabled both glow and wgpu,
|
||||
// but let's pick the better of the two (wgpu):
|
||||
#[cfg(feature = "glow")]
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
return Self::Wgpu;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use egui::{TexturesDelta, UserData, ViewportCommand};
|
||||
|
||||
use crate::{App, epi};
|
||||
use crate::{App, epi, web::web_painter::WebPainter};
|
||||
|
||||
use super::{NeedRepaint, now_sec, text_agent::TextAgent, web_painter::WebPainter as _};
|
||||
use super::{NeedRepaint, now_sec, text_agent::TextAgent};
|
||||
|
||||
pub struct AppRunner {
|
||||
#[allow(dead_code, clippy::allow_attributes)]
|
||||
pub(crate) web_options: crate::WebOptions,
|
||||
pub(crate) frame: epi::Frame,
|
||||
egui_ctx: egui::Context,
|
||||
painter: super::ActiveWebPainter,
|
||||
painter: Box<dyn WebPainter>,
|
||||
pub(crate) input: super::WebInput,
|
||||
app: Box<dyn epi::App>,
|
||||
pub(crate) needs_repaint: std::sync::Arc<NeedRepaint>,
|
||||
@@ -34,6 +34,10 @@ impl Drop for AppRunner {
|
||||
impl AppRunner {
|
||||
/// # Errors
|
||||
/// Failure to initialize WebGL renderer, or failure to create app.
|
||||
#[cfg_attr(
|
||||
not(feature = "wgpu_no_default_features"),
|
||||
expect(clippy::unused_async)
|
||||
)]
|
||||
pub async fn new(
|
||||
canvas: web_sys::HtmlCanvasElement,
|
||||
web_options: crate::WebOptions,
|
||||
@@ -41,7 +45,41 @@ impl AppRunner {
|
||||
text_agent: TextAgent,
|
||||
) -> Result<Self, String> {
|
||||
let egui_ctx = egui::Context::default();
|
||||
let painter = super::ActiveWebPainter::new(egui_ctx.clone(), canvas, &web_options).await?;
|
||||
|
||||
#[allow(clippy::allow_attributes, unused_assignments)]
|
||||
#[cfg(feature = "glow")]
|
||||
let mut gl = None;
|
||||
|
||||
#[allow(clippy::allow_attributes, unused_assignments)]
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
let mut wgpu_render_state = None;
|
||||
|
||||
let painter = match web_options.renderer {
|
||||
#[cfg(feature = "glow")]
|
||||
epi::Renderer::Glow => {
|
||||
log::debug!("Using the glow renderer");
|
||||
let painter = super::web_painter_glow::WebPainterGlow::new(
|
||||
egui_ctx.clone(),
|
||||
canvas,
|
||||
&web_options,
|
||||
)?;
|
||||
gl = Some(painter.gl().clone());
|
||||
Box::new(painter) as Box<dyn WebPainter>
|
||||
}
|
||||
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
epi::Renderer::Wgpu => {
|
||||
log::debug!("Using the wgpu renderer");
|
||||
let painter = super::web_painter_wgpu::WebPainterWgpu::new(
|
||||
egui_ctx.clone(),
|
||||
canvas,
|
||||
&web_options,
|
||||
)
|
||||
.await?;
|
||||
wgpu_render_state = painter.render_state();
|
||||
Box::new(painter) as Box<dyn WebPainter>
|
||||
}
|
||||
};
|
||||
|
||||
let info = epi::IntegrationInfo {
|
||||
web_info: epi::WebInfo {
|
||||
@@ -79,15 +117,13 @@ impl AppRunner {
|
||||
storage: Some(&storage),
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
gl: Some(painter.gl().clone()),
|
||||
gl: gl.clone(),
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
get_proc_address: None,
|
||||
|
||||
#[cfg(all(feature = "wgpu_no_default_features", not(feature = "glow")))]
|
||||
wgpu_render_state: painter.render_state(),
|
||||
#[cfg(all(feature = "wgpu_no_default_features", feature = "glow"))]
|
||||
wgpu_render_state: None,
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
wgpu_render_state: wgpu_render_state.clone(),
|
||||
};
|
||||
let app = app_creator(&cc).map_err(|err| err.to_string())?;
|
||||
|
||||
@@ -96,12 +132,10 @@ impl AppRunner {
|
||||
storage: Some(Box::new(storage)),
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
gl: Some(painter.gl().clone()),
|
||||
gl,
|
||||
|
||||
#[cfg(all(feature = "wgpu_no_default_features", not(feature = "glow")))]
|
||||
wgpu_render_state: painter.render_state(),
|
||||
#[cfg(all(feature = "wgpu_no_default_features", feature = "glow"))]
|
||||
wgpu_render_state: None,
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
wgpu_render_state,
|
||||
};
|
||||
|
||||
let needs_repaint: std::sync::Arc<NeedRepaint> =
|
||||
|
||||
@@ -30,13 +30,9 @@ mod web_painter;
|
||||
|
||||
#[cfg(feature = "glow")]
|
||||
mod web_painter_glow;
|
||||
#[cfg(feature = "glow")]
|
||||
pub(crate) type ActiveWebPainter = web_painter_glow::WebPainterGlow;
|
||||
|
||||
#[cfg(feature = "wgpu_no_default_features")]
|
||||
mod web_painter_wgpu;
|
||||
#[cfg(all(feature = "wgpu_no_default_features", not(feature = "glow")))]
|
||||
pub(crate) type ActiveWebPainter = web_painter_wgpu::WebPainterWgpu;
|
||||
|
||||
pub use backend::*;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ impl WebPainterGlow {
|
||||
self.painter.gl()
|
||||
}
|
||||
|
||||
pub async fn new(
|
||||
pub fn new(
|
||||
_ctx: egui::Context,
|
||||
canvas: HtmlCanvasElement,
|
||||
options: &WebOptions,
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::web_painter::WebPainter;
|
||||
use crate::WebOptions;
|
||||
use egui::{Event, UserData, ViewportId};
|
||||
use egui_wgpu::capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel};
|
||||
use egui_wgpu::{RenderState, SurfaceErrorAction};
|
||||
use egui_wgpu::{
|
||||
RenderState, SurfaceErrorAction,
|
||||
capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel},
|
||||
};
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::HtmlCanvasElement;
|
||||
|
||||
use super::web_painter::WebPainter;
|
||||
|
||||
pub(crate) struct WebPainterWgpu {
|
||||
canvas: HtmlCanvasElement,
|
||||
surface: wgpu::Surface<'static>,
|
||||
@@ -23,7 +25,6 @@ pub(crate) struct WebPainterWgpu {
|
||||
}
|
||||
|
||||
impl WebPainterWgpu {
|
||||
#[expect(unused)] // only used if `wgpu` is the only active feature.
|
||||
pub fn render_state(&self) -> Option<RenderState> {
|
||||
self.render_state.clone()
|
||||
}
|
||||
@@ -55,11 +56,10 @@ impl WebPainterWgpu {
|
||||
})
|
||||
}
|
||||
|
||||
#[expect(unused)] // only used if `wgpu` is the only active feature.
|
||||
pub async fn new(
|
||||
ctx: egui::Context,
|
||||
canvas: web_sys::HtmlCanvasElement,
|
||||
options: &WebOptions,
|
||||
options: &crate::WebOptions,
|
||||
) -> Result<Self, String> {
|
||||
log::debug!("Creating wgpu painter");
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ crate-type = ["cdylib", "rlib"]
|
||||
|
||||
|
||||
[features]
|
||||
default = ["glow", "persistence"]
|
||||
default = ["wgpu", "persistence"]
|
||||
|
||||
# image_viewer adds about 0.9 MB of WASM
|
||||
web_app = ["http", "persistence"]
|
||||
|
||||
@@ -13,13 +13,13 @@ OPEN=false
|
||||
OPTIMIZE=false
|
||||
BUILD=debug
|
||||
BUILD_FLAGS=""
|
||||
WGPU=false
|
||||
GLOW=false
|
||||
WASM_OPT_FLAGS="-O2 --fast-math"
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
echo "build_demo_web.sh [--release] [--wgpu] [--open]"
|
||||
echo "build_demo_web.sh [--release] [--glow] [--open]"
|
||||
echo ""
|
||||
echo " -g: Keep debug symbols even with --release."
|
||||
echo " These are useful profiling and size trimming."
|
||||
@@ -29,9 +29,7 @@ while test $# -gt 0; do
|
||||
echo " --release: Build with --release, and then run wasm-opt."
|
||||
echo " NOTE: --release also removes debug symbols, unless you also use -g."
|
||||
echo ""
|
||||
echo " --wgpu: Build a binary using wgpu instead of glow/webgl."
|
||||
echo " The resulting binary will automatically use WebGPU if available and"
|
||||
echo " fall back to a WebGL emulation layer otherwise."
|
||||
echo " --glow: Build a binary using glow instead of wgpu."
|
||||
exit 0
|
||||
;;
|
||||
|
||||
@@ -52,9 +50,9 @@ while test $# -gt 0; do
|
||||
BUILD_FLAGS="--release"
|
||||
;;
|
||||
|
||||
--wgpu)
|
||||
--glow)
|
||||
shift
|
||||
WGPU=true
|
||||
GLOW=true
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -66,10 +64,10 @@ done
|
||||
|
||||
OUT_FILE_NAME="egui_demo_app"
|
||||
|
||||
if [[ "${WGPU}" == true ]]; then
|
||||
FEATURES="${FEATURES},wgpu"
|
||||
else
|
||||
if [[ "${GLOW}" == true ]]; then
|
||||
FEATURES="${FEATURES},glow"
|
||||
else
|
||||
FEATURES="${FEATURES},wgpu"
|
||||
fi
|
||||
|
||||
FINAL_WASM_PATH=web_demo/${OUT_FILE_NAME}_bg.wasm
|
||||
|
||||
Reference in New Issue
Block a user