diff --git a/.cargo/config.toml b/.cargo/config.toml
index 097c2ea3ba0a..18ecd71a6b15 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -10,6 +10,9 @@ rerun-release = "run --package rerun-cli --no-default-features --features native
# `cargo rerun-web` is short a convenient shorthand for building & starting the web viewer.
rerun-web = "run --package rerun-cli --no-default-features --features web_viewer -- --web-viewer"
+# `cargo rerun-release-web` is short a convenient shorthand for building & starting the web viewer in release mode.
+rerun-release-web = "run --package rerun-cli --no-default-features --features web_viewer --release -- --web-viewer"
+
# Run the codegen. Optionally pass `--profile` to it.
# NOTE: there are several CI jobs with `command: codegen` with the cargo action
codegen = "run --package re_types_builder --"
diff --git a/Cargo.lock b/Cargo.lock
index e0f995289c4a..6c3908e2f41a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5038,7 +5038,9 @@ dependencies = [
"serde_json",
"thiserror",
"time",
+ "wasm-bindgen",
"wasm-bindgen-futures",
+ "web-sys",
"web-time",
"wgpu",
]
diff --git a/crates/re_renderer/src/config.rs b/crates/re_renderer/src/config.rs
index e2408bce6b1c..9b0ef6573b02 100644
--- a/crates/re_renderer/src/config.rs
+++ b/crates/re_renderer/src/config.rs
@@ -230,3 +230,72 @@ pub fn supported_backends() -> wgpu::Backends {
wgpu::Backends::GL | wgpu::Backends::BROWSER_WEBGPU
}
}
+
+/// Generous parsing of a graphics backend string.
+pub fn parse_graphics_backend(backend: &str) -> Option {
+ match backend.to_lowercase().as_str() {
+ // "vulcan" is a common typo that we just swallow. We know what you mean ;)
+ "vulcan" | "vulkan" | "vk" => Some(wgpu::Backend::Vulkan),
+
+ "metal" | "apple" | "mtl" => Some(wgpu::Backend::Metal),
+
+ "dx12" | "dx" | "d3d" | "d3d12" | "directx" => Some(wgpu::Backend::Dx12),
+
+ // We don't want to lie - e.g. `webgl1` should not work!
+ // This means that `gles`/`gles3` stretches it a bit, but it's still close enough.
+ // Similarly, we accept both `webgl` & `opengl` on each desktop & web.
+ // This is a bit dubious but also too much hassle to forbid.
+ "webgl2" | "webgl" | "opengl" | "gles" | "gles3" | "gl" => Some(wgpu::Backend::Gl),
+
+ "browserwebgpu" | "webgpu" => Some(wgpu::Backend::BrowserWebGpu),
+
+ _ => None,
+ }
+}
+
+/// Validates that the given backend is applicable for the current build.
+///
+/// This is meant as a sanity check of first resort.
+/// There are still many other reasons why a backend may not work on a given platform/build combination.
+pub fn validate_graphics_backend_applicability(backend: wgpu::Backend) -> Result<(), &'static str> {
+ match backend {
+ wgpu::Backend::Empty => {
+ // This should never happen.
+ return Err("Cannot run with empty backend.");
+ }
+ wgpu::Backend::Vulkan => {
+ // Through emulation and build configs Vulkan may work everywhere except the web.
+ if cfg!(target_arch = "wasm32") {
+ return Err("Can only run with WebGL or WebGPU on the web.");
+ }
+ }
+ wgpu::Backend::Metal => {
+ if cfg!(target_arch = "wasm32") {
+ return Err("Can only run with WebGL or WebGPU on the web.");
+ }
+ if cfg!(target_os = "linux") || cfg!(target_os = "windows") {
+ return Err("Cannot run with DX12 backend on Linux & Windows.");
+ }
+ }
+ wgpu::Backend::Dx12 => {
+ // We don't have DX12 enabled right now, but someone could.
+ // TODO(wgpu#5166): But if we get this wrong we might crash.
+ // TODO(wgpu#5167): And we also can't query the config.
+ return Err("DX12 backend is currently not supported.");
+ }
+ wgpu::Backend::Gl => {
+ // Using Angle Mac might actually run GL, but we don't enable this.
+ // TODO(wgpu#5166): But if we get this wrong we might crash.
+ // TODO(wgpu#5167): And we also can't query the config.
+ if cfg!(target_os = "macos") {
+ return Err("Cannot run with GL backend on Mac.");
+ }
+ }
+ wgpu::Backend::BrowserWebGpu => {
+ if !cfg!(target_arch = "wasm32") {
+ return Err("Cannot run with WebGPU backend on native application.");
+ }
+ }
+ }
+ Ok(())
+}
diff --git a/crates/re_sdk/src/web_viewer.rs b/crates/re_sdk/src/web_viewer.rs
index d1ce6d06b1f4..2b70ddf7592a 100644
--- a/crates/re_sdk/src/web_viewer.rs
+++ b/crates/re_sdk/src/web_viewer.rs
@@ -79,6 +79,7 @@ impl WebViewerSink {
pub async fn host_web_viewer(
bind_ip: String,
web_port: WebViewerServerPort,
+ force_wgpu_backend: Option,
open_browser: bool,
source_url: String,
) -> anyhow::Result<()> {
@@ -86,7 +87,10 @@ pub async fn host_web_viewer(
let http_web_viewer_url = web_server.server_url();
let web_server_handle = web_server.serve();
- let viewer_url = format!("{http_web_viewer_url}?url={source_url}");
+ let mut viewer_url = format!("{http_web_viewer_url}?url={source_url}");
+ if let Some(force_graphics) = force_wgpu_backend {
+ viewer_url = format!("{viewer_url}&renderer={force_graphics}");
+ }
re_log::info!("Hosting a web-viewer at {viewer_url}");
if open_browser {
diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs
index b27c5bfdbd77..0a9ed503dd74 100644
--- a/crates/re_ui/src/command.rs
+++ b/crates/re_ui/src/command.rs
@@ -74,6 +74,12 @@ pub enum UICommand {
#[cfg(target_arch = "wasm32")]
CopyDirectLink,
+
+ // Graphics options:
+ #[cfg(target_arch = "wasm32")]
+ RestartWithWebGl,
+ #[cfg(target_arch = "wasm32")]
+ RestartWithWebGpu,
}
impl UICommand {
@@ -201,7 +207,18 @@ impl UICommand {
Self::CopyDirectLink => (
"Copy direct link",
"Copy a link to the viewer with the URL parameter set to the current .rrd data source."
- )
+ ),
+
+ #[cfg(target_arch = "wasm32")]
+ Self::RestartWithWebGl => (
+ "Restart with WebGL",
+ "Reloads the webpage and force WebGL for rendering. All data will be lost."
+ ),
+ #[cfg(target_arch = "wasm32")]
+ Self::RestartWithWebGpu => (
+ "Restart with WebGPU",
+ "Reloads the webpage and force WebGPU for rendering. All data will be lost."
+ ),
}
}
@@ -285,6 +302,11 @@ impl UICommand {
#[cfg(target_arch = "wasm32")]
Self::CopyDirectLink => None,
+
+ #[cfg(target_arch = "wasm32")]
+ Self::RestartWithWebGl => None,
+ #[cfg(target_arch = "wasm32")]
+ Self::RestartWithWebGpu => None,
}
}
diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml
index 611ef0558fae..749db3cd6c08 100644
--- a/crates/re_viewer/Cargo.toml
+++ b/crates/re_viewer/Cargo.toml
@@ -106,7 +106,15 @@ wgpu.workspace = true
# web dependencies:
[target.'cfg(target_arch = "wasm32")'.dependencies]
+wasm-bindgen.workspace = true
wasm-bindgen-futures.workspace = true
+web-sys = { workspace = true, features = [
+ 'Location',
+ 'Url',
+ 'UrlSearchParams',
+ 'Window',
+] }
+
[build-dependencies]
re_build_tools.workspace = true
diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs
index 5530b66bd7eb..3a563dcf0ea2 100644
--- a/crates/re_viewer/src/app.rs
+++ b/crates/re_viewer/src/app.rs
@@ -56,6 +56,9 @@ pub struct StartupOptions {
pub resolution_in_points: Option<[f32; 2]>,
pub skip_welcome_screen: bool,
+
+ /// Forces wgpu backend to use the specified graphics API.
+ pub force_wgpu_backend: Option,
}
impl Default for StartupOptions {
@@ -75,6 +78,7 @@ impl Default for StartupOptions {
resolution_in_points: None,
skip_welcome_screen: false,
+ force_wgpu_backend: None,
}
}
}
@@ -639,6 +643,20 @@ impl App {
UICommand::CopyDirectLink => {
self.run_copy_direct_link_command(store_context);
}
+
+ #[cfg(target_arch = "wasm32")]
+ UICommand::RestartWithWebGl => {
+ if crate::web_tools::set_url_parameter_and_refresh("renderer", "webgl").is_err() {
+ re_log::error!("Failed to set URL parameter `renderer=webgl` & refresh page.");
+ }
+ }
+
+ #[cfg(target_arch = "wasm32")]
+ UICommand::RestartWithWebGpu => {
+ if crate::web_tools::set_url_parameter_and_refresh("renderer", "webgpu").is_err() {
+ re_log::error!("Failed to set URL parameter `renderer=webgpu` & refresh page.");
+ }
+ }
}
}
diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs
index 70a283e58400..dd325eba9612 100644
--- a/crates/re_viewer/src/lib.rs
+++ b/crates/re_viewer/src/lib.rs
@@ -55,6 +55,9 @@ pub use native::{run_native_app, run_native_viewer_with_messages};
#[cfg(target_arch = "wasm32")]
mod web;
+#[cfg(target_arch = "wasm32")]
+mod web_tools;
+
// ---------------------------------------------------------------------------
/// Information about this version of the crate.
@@ -129,8 +132,29 @@ impl AppEnvironment {
// ---------------------------------------------------------------------------
-pub(crate) fn wgpu_options() -> egui_wgpu::WgpuConfiguration {
+fn supported_graphics_backends(force_wgpu_backend: Option) -> wgpu::Backends {
+ if let Some(force_wgpu_backend) = force_wgpu_backend {
+ if let Some(backend) = re_renderer::config::parse_graphics_backend(&force_wgpu_backend) {
+ if let Err(err) = re_renderer::config::validate_graphics_backend_applicability(backend)
+ {
+ re_log::error!("Failed to force rendering backend parsed from {force_wgpu_backend:?}: {err}\nUsing default backend instead.");
+ re_renderer::config::supported_backends()
+ } else {
+ re_log::info!("Forcing graphics backend to {backend:?}.");
+ backend.into()
+ }
+ } else {
+ re_log::error!("Failed to parse rendering backend string {force_wgpu_backend:?}. Using default backend instead.");
+ re_renderer::config::supported_backends()
+ }
+ } else {
+ re_renderer::config::supported_backends()
+ }
+}
+
+pub(crate) fn wgpu_options(force_wgpu_backend: Option) -> egui_wgpu::WgpuConfiguration {
re_tracing::profile_function!();
+
egui_wgpu::WgpuConfiguration {
// When running wgpu on native debug builds, we want some extra control over how
// and when a poisoned surface gets recreated.
@@ -150,7 +174,7 @@ pub(crate) fn wgpu_options() -> egui_wgpu::WgpuConfiguration {
egui_wgpu::SurfaceErrorAction::SkipFrame
}
}),
- supported_backends: re_renderer::config::supported_backends(),
+ supported_backends: supported_graphics_backends(force_wgpu_backend),
device_descriptor: std::sync::Arc::new(|adapter| re_renderer::config::DeviceCaps::from_adapter(adapter).device_descriptor()),
..Default::default()
}
diff --git a/crates/re_viewer/src/native.rs b/crates/re_viewer/src/native.rs
index 42cff5bf7fc3..61c1a80dd526 100644
--- a/crates/re_viewer/src/native.rs
+++ b/crates/re_viewer/src/native.rs
@@ -7,8 +7,11 @@ type AppCreator =
Box, re_ui::ReUi) -> Box>;
// NOTE: the name of this function is hard-coded in `crates/rerun/src/crash_handler.rs`!
-pub fn run_native_app(app_creator: AppCreator) -> eframe::Result<()> {
- let native_options = eframe_options();
+pub fn run_native_app(
+ app_creator: AppCreator,
+ force_wgpu_backend: Option,
+) -> eframe::Result<()> {
+ let native_options = eframe_options(force_wgpu_backend);
let window_title = "Rerun Viewer";
eframe::run_native(
@@ -21,7 +24,7 @@ pub fn run_native_app(app_creator: AppCreator) -> eframe::Result<()> {
)
}
-pub fn eframe_options() -> eframe::NativeOptions {
+pub fn eframe_options(force_wgpu_backend: Option) -> eframe::NativeOptions {
re_tracing::profile_function!();
eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
@@ -40,7 +43,7 @@ pub fn eframe_options() -> eframe::NativeOptions {
default_theme: eframe::Theme::Dark,
renderer: eframe::Renderer::Wgpu,
- wgpu_options: crate::wgpu_options(),
+ wgpu_options: crate::wgpu_options(force_wgpu_backend),
depth_buffer: 0,
multisampling: 0, // the 3D views do their own MSAA
@@ -92,9 +95,14 @@ pub fn run_native_viewer_with_messages(
for log_msg in log_messages {
tx.send(log_msg).ok();
}
- run_native_app(Box::new(move |cc, re_ui| {
- let mut app = crate::App::new(build_info, &app_env, startup_options, re_ui, cc.storage);
- app.add_receiver(rx);
- Box::new(app)
- }))
+
+ let force_wgpu_backend = startup_options.force_wgpu_backend.clone();
+ run_native_app(
+ Box::new(move |cc, re_ui| {
+ let mut app = crate::App::new(build_info, &app_env, startup_options, re_ui, cc.storage);
+ app.add_receiver(rx);
+ Box::new(app)
+ }),
+ force_wgpu_backend,
+ )
}
diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs
index 6c124d8ea587..4a5b41ce7665 100644
--- a/crates/re_viewer/src/ui/rerun_menu.rs
+++ b/crates/re_viewer/src/ui/rerun_menu.rs
@@ -83,6 +83,7 @@ impl App {
&self.command_sender,
&self.re_ui,
ui,
+ frame,
&mut self.state.app_options,
);
});
@@ -236,7 +237,7 @@ fn render_state_ui(ui: &mut egui::Ui, render_state: &egui_wgpu::RenderState) {
egui::Grid::new("adapter_info").show(ui, |ui| {
ui.label("Backend");
- ui.label(format!("{backend:?}"));
+ ui.label(backend.to_str()); // TODO(wgpu#5170): Use std::fmt::Display for backend.
ui.end_row();
ui.label("Device Type");
@@ -274,7 +275,8 @@ fn render_state_ui(ui: &mut egui::Ui, render_state: &egui_wgpu::RenderState) {
let wgpu_adapter_ui = |ui: &mut egui::Ui, adapter: &eframe::wgpu::Adapter| {
let info = &adapter.get_info();
- ui.label(format!("{:?}", info.backend)).on_hover_ui(|ui| {
+ // TODO(wgpu#5170): Use std::fmt::Display for backend.
+ ui.label(info.backend.to_str()).on_hover_ui(|ui| {
wgpu_adapter_details_ui(ui, adapter);
});
};
@@ -303,6 +305,7 @@ fn options_menu_ui(
command_sender: &re_viewer_context::CommandSender,
re_ui: &ReUi,
ui: &mut egui::Ui,
+ frame: &eframe::Frame,
app_options: &mut re_viewer_context::AppOptions,
) {
re_ui
@@ -338,6 +341,23 @@ fn options_menu_ui(
ui.label("Experimental features:");
experimental_feature_ui(command_sender, re_ui, ui, app_options);
}
+
+ if let Some(_backend) = frame
+ .wgpu_render_state()
+ .map(|state| state.adapter.get_info().backend)
+ {
+ // Adapter switching only implemented for web so far.
+ // For native it's less well defined since the application may be embedded in another application that reads arguments differently.
+ #[cfg(target_arch = "wasm32")]
+ {
+ ui.add_space(SPACING);
+ if _backend == wgpu::Backend::BrowserWebGpu {
+ UICommand::RestartWithWebGl.menu_button_ui(ui, command_sender);
+ } else {
+ UICommand::RestartWithWebGpu.menu_button_ui(ui, command_sender);
+ }
+ }
+ }
}
fn experimental_feature_ui(
diff --git a/crates/re_viewer/src/web.rs b/crates/re_viewer/src/web.rs
index 1e4abfcbe2f1..aaf08e53296f 100644
--- a/crates/re_viewer/src/web.rs
+++ b/crates/re_viewer/src/web.rs
@@ -31,17 +31,19 @@ impl WebHandle {
/// - `url` is an optional URL to either an .rrd file over http, or a Rerun WebSocket server.
/// - `manifest_url` is an optional URL to an `examples_manifest.json` file over http.
+ /// - `force_wgpu_backend` is an optional string to force a specific backend, either `webgl` or `webgpu`.
#[wasm_bindgen]
pub async fn start(
&self,
canvas_id: &str,
url: Option,
manifest_url: Option,
+ force_wgpu_backend: Option,
) -> Result<(), wasm_bindgen::JsValue> {
let web_options = eframe::WebOptions {
follow_system_theme: false,
default_theme: eframe::Theme::Dark,
- wgpu_options: crate::wgpu_options(),
+ wgpu_options: crate::wgpu_options(force_wgpu_backend),
depth_buffer: 0,
..Default::default()
};
@@ -119,6 +121,7 @@ fn create_app(
persist_state: get_persist_state(&cc.integration_info),
is_in_notebook: is_in_notebook(&cc.integration_info),
skip_welcome_screen: false,
+ force_wgpu_backend: None,
};
let re_ui = crate::customize_eframe(cc);
diff --git a/crates/re_viewer/src/web_tools.rs b/crates/re_viewer/src/web_tools.rs
new file mode 100644
index 000000000000..2575a31a944e
--- /dev/null
+++ b/crates/re_viewer/src/web_tools.rs
@@ -0,0 +1,11 @@
+pub fn set_url_parameter_and_refresh(key: &str, value: &str) -> Result<(), wasm_bindgen::JsValue> {
+ let Some(window) = web_sys::window() else {
+ return Err("Failed to get window".into());
+ };
+ let location = window.location();
+
+ let url = web_sys::Url::new(&location.href()?)?;
+ url.search_params().set(key, value);
+
+ location.assign(&url.href())
+}
diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs
index f8bd8db2bb4b..c3ef96aaa5b8 100644
--- a/crates/rerun/src/run.rs
+++ b/crates/rerun/src/run.rs
@@ -23,7 +23,7 @@ Environment variables:
RERUN_SHADER_PATH The search path for shader/shader-imports. Only available in developer builds.
RERUN_TRACK_ALLOCATIONS Track memory allocations to diagnose memory leaks in the viewer. WARNING: slows down the viewer by a lot!
RUST_LOG Change the log level of the viewer, e.g. `RUST_LOG=debug`.
- WGPU_BACKEND Overwrites the graphics backend used, must be one of `vulkan`, `metal`, `dx12`, `dx11`, or `gl`.
+ WGPU_BACKEND Overwrites the graphics backend used, must be one of `vulkan`, `metal` or `gl`.
Default is `vulkan` everywhere except on Mac where we use `metal`. What is supported depends on your OS.
WGPU_POWER_PREF Overwrites the power setting used for choosing a graphics adapter, must be `high` or `low`. (Default is `high`)
@@ -181,6 +181,21 @@ If no arguments are given, a server will be hosted which a Rerun SDK can connect
#[clap(long, default_value_t = Default::default())]
ws_server_port: RerunServerPort,
+ /// Override the default graphics backend and for a specific one instead.
+ ///
+ /// When using `--web-viewer` this should be one of:
+ /// * `webgpu`
+ /// * `webgl`
+ ///
+ /// When starting a native viewer instead this should be one of:
+ /// * `vulkan` (Linux & Windows only)
+ /// * `gl` (Linux & Windows only)
+ /// * `metal` (macOS only)
+ // Note that we don't compile with DX12 right now, but we could (we don't since this adds permutation and wgpu still has some issues with it).
+ // GL could be enabled on MacOS via `angle` but given prior issues with ANGLE this seems to be a bad idea!
+ #[clap(long)]
+ renderer: Option,
+
// ----------------------------------------------------------------------------
// Debug-options:
/// Ingest data and then quit once the goodbye message has been received.
@@ -499,6 +514,7 @@ async fn run_impl(
} else {
None
},
+ force_wgpu_backend: None,
}
};
@@ -534,6 +550,7 @@ async fn run_impl(
return host_web_viewer(
args.bind.clone(),
args.web_viewer_port,
+ args.renderer,
true,
rerun_server_ws_url,
)
@@ -608,6 +625,7 @@ async fn run_impl(
let web_server_handle = tokio::spawn(host_web_viewer(
args.bind.clone(),
args.web_viewer_port,
+ args.renderer,
open_browser,
_ws_server_url,
));
@@ -620,23 +638,26 @@ async fn run_impl(
}
} else {
#[cfg(feature = "native_viewer")]
- return re_viewer::run_native_app(Box::new(move |cc, re_ui| {
- let mut app = re_viewer::App::new(
- _build_info,
- &call_source.app_env(),
- startup_options,
- re_ui,
- cc.storage,
- );
- for rx in rx {
- app.add_receiver(rx);
- }
- app.set_profiler(profiler);
- if let Ok(url) = std::env::var("EXAMPLES_MANIFEST_URL") {
- app.set_examples_manifest_url(url);
- }
- Box::new(app)
- }))
+ return re_viewer::run_native_app(
+ Box::new(move |cc, re_ui| {
+ let mut app = re_viewer::App::new(
+ _build_info,
+ &call_source.app_env(),
+ startup_options,
+ re_ui,
+ cc.storage,
+ );
+ for rx in rx {
+ app.add_receiver(rx);
+ }
+ app.set_profiler(profiler);
+ if let Ok(url) = std::env::var("EXAMPLES_MANIFEST_URL") {
+ app.set_examples_manifest_url(url);
+ }
+ Box::new(app)
+ }),
+ args.renderer,
+ )
.map_err(|err| err.into());
#[cfg(not(feature = "native_viewer"))]
diff --git a/docs/content/getting-started/troubleshooting.md b/docs/content/getting-started/troubleshooting.md
index 290f8dd06949..b3675290c912 100644
--- a/docs/content/getting-started/troubleshooting.md
+++ b/docs/content/getting-started/troubleshooting.md
@@ -66,13 +66,16 @@ rerun reset
[Wgpu](https://github.com/gfx-rs/wgpu) (the graphics API we use) maintains a list of
[known driver issues](https://github.com/gfx-rs/wgpu/wiki/Known-Driver-Issues) and workarounds for them.
-The following environment variables overwrite the config we choose for wgpu:
-* `WGPU_BACKEND`: Overwrites the graphics backend used, must be one of `vulkan`, `metal`, `dx12`, `dx11`, or `gl`.
- Naturally, support depends on your OS. Default is `vulkan` everywhere except on Mac where we use `metal`.
+The configuration we use for wgpu can be influenced in the following ways:
+* pass `--renderer=` on startup: `` must be one of `vulkan`, `metal` or `gl` for native and
+ either `webgl` or `webgpu` for the web viewer (see also `--web-viewer` argument).
+ Naturally, support depends on your OS. The default backend is `vulkan` everywhere except on Mac where we use `metal`.
+ On the web we prefer WebGPU and fall back automatically to WebGL if no support for WebGPU was detected.
+ * For instance, you can try `rerun --renderer=gl` or for the web viewer respectively `rerun --web-viewer --renderer=webgl`.
+ * Alternatively, for the native viewer you can also use the `WGPU_BACKEND` environment variable with the above values.
+ * The web viewer is configured by the `renderer=` url argument, e.g. [https://app.rerun.io/?renderer=webgl]
* `WGPU_POWER_PREF`: Overwrites the power setting used for choosing a graphics adapter, must be `high` or `low`. (Default is `high`)
-For instance, you can try `WGPU_BACKEND=gl rerun`.
-
We recommend setting these only if you're asked to try them or know what you're doing,
since we don't support all of these settings equally well.
diff --git a/examples/rust/custom_space_view/src/main.rs b/examples/rust/custom_space_view/src/main.rs
index dc13199b4e8a..32d151b6c106 100644
--- a/examples/rust/custom_space_view/src/main.rs
+++ b/examples/rust/custom_space_view/src/main.rs
@@ -40,22 +40,25 @@ async fn main() -> Result<(), Box> {
);
println!("Try for example to run: `cargo run -p minimal_options -- --connect` in another terminal instance.");
- re_viewer::run_native_app(Box::new(move |cc, re_ui| {
- let mut app = re_viewer::App::new(
- re_viewer::build_info(),
- &app_env,
- startup_options,
- re_ui,
- cc.storage,
- );
- app.add_receiver(rx);
-
- // Register the custom space view
- app.add_space_view_class::()
- .unwrap();
-
- Box::new(app)
- }))?;
+ re_viewer::run_native_app(
+ Box::new(move |cc, re_ui| {
+ let mut app = re_viewer::App::new(
+ re_viewer::build_info(),
+ &app_env,
+ startup_options,
+ re_ui,
+ cc.storage,
+ );
+ app.add_receiver(rx);
+
+ // Register the custom space view
+ app.add_space_view_class::()
+ .unwrap();
+
+ Box::new(app)
+ }),
+ None,
+ )?;
Ok(())
}
diff --git a/examples/rust/extend_viewer_ui/src/main.rs b/examples/rust/extend_viewer_ui/src/main.rs
index 4387ffb16b5e..f9f075dc18a1 100644
--- a/examples/rust/extend_viewer_ui/src/main.rs
+++ b/examples/rust/extend_viewer_ui/src/main.rs
@@ -32,7 +32,7 @@ async fn main() -> Result<(), Box> {
let native_options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_app_id("rerun_extend_viewer_ui_example"),
- ..re_viewer::native::eframe_options()
+ ..re_viewer::native::eframe_options(None)
};
let startup_options = re_viewer::StartupOptions::default();
diff --git a/web_viewer/index.html b/web_viewer/index.html
index d49217b1279d..e95445e3b123 100644
--- a/web_viewer/index.html
+++ b/web_viewer/index.html
@@ -218,6 +218,20 @@
load_wasm();
}
+ var urlWebGl = new URL(window.location);
+ urlWebGl.searchParams.set("renderer", "webgl");
+
+ var urlWebGpu = new URL(window.location);
+ urlWebGpu.searchParams.set("renderer", "webgpu");
+
+ const forceWgpuBackendInfoParagraph = `
+
+ For graphics related issues, try forcing to render with WebGL
+ ${urlWebGl}
+ or with WebGPU
+ ${urlWebGpu}
+
`;
+
function load_wasm() {
// We'll defer our execution until the wasm is ready to go.
// Here we tell bindgen the path to the wasm file so it can start
@@ -325,8 +339,10 @@
See the console for details.
- Reload the page to try again.
+ Reload the page to try again.
+ Please consider filing a bug report. Thank you!
+ ${forceWgpuBackendInfoParagraph}
`);
} else {
let delay_ms = 1000;
@@ -336,7 +352,13 @@
check_for_panic();
- handle.start("the_canvas_id").then(on_app_started).catch(on_wasm_error);
+ const urlParams = new URLSearchParams(window.location.search);
+ const forceWgpuBackend = urlParams.get("renderer");
+
+ handle
+ .start("the_canvas_id", null, null, forceWgpuBackend)
+ .then(on_app_started)
+ .catch(on_wasm_error);
}
function on_app_started(handle) {
@@ -363,9 +385,11 @@
${error}
-
- Make sure you use a modern browser with either WebGL or WebGPU support enabled.
+
+ Reload the page to try again.
+ Please consider filing a bug report. Thank you!
+ ${forceWgpuBackendInfoParagraph}
`);
}