From f3b938bbcbfe366c690200b324995daefc3925c4 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Fri, 20 Mar 2026 12:45:14 -0400 Subject: [PATCH] Update to wgpu 29 --- .github/workflows/rust.yml | 2 +- Cargo.lock | 263 +++++++++--------- Cargo.toml | 4 +- crates/eframe/src/native/wgpu_integration.rs | 10 +- crates/eframe/src/web/mod.rs | 3 +- crates/eframe/src/web/web_painter_wgpu.rs | 63 ++++- crates/egui-wgpu/src/lib.rs | 67 ++++- crates/egui-wgpu/src/renderer.rs | 15 +- crates/egui-wgpu/src/setup.rs | 196 +++++++++++-- crates/egui-wgpu/src/winit.rs | 57 +++- .../egui_demo_app/src/apps/custom3d_wgpu.rs | 2 +- crates/egui_kittest/src/wgpu.rs | 4 +- scripts/setup_web.sh | 4 +- 13 files changed, 498 insertions(+), 192 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9018d251b..35f6f3b7c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -94,7 +94,7 @@ jobs: - name: wasm-bindgen uses: jetli/wasm-bindgen-action@v0.1.0 with: - version: "0.2.100" # Keep wasm-bindgen version in sync in: setup_web.sh, Cargo.toml, Cargo.lock, rust.yml + version: "0.2.114" # Keep wasm-bindgen version in sync in: setup_web.sh, Cargo.toml, Cargo.lock, rust.yml - run: ./scripts/wasm_bindgen_check.sh --skip-setup diff --git a/Cargo.lock b/Cargo.lock index 896a36665..f3978bedf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -536,7 +536,16 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec", + "bit-vec 0.8.0", +] + +[[package]] +name = "bit-set" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" +dependencies = [ + "bit-vec 0.9.1", ] [[package]] @@ -545,6 +554,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + [[package]] name = "bitflags" version = "1.3.2" @@ -560,12 +575,6 @@ dependencies = [ "serde", ] -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - [[package]] name = "block2" version = "0.5.1" @@ -804,9 +813,9 @@ dependencies = [ [[package]] name = "codespan-reporting" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ "serde", "termcolor", @@ -923,7 +932,7 @@ checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "core-graphics-types 0.1.3", + "core-graphics-types", "foreign-types", "libc", ] @@ -939,17 +948,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.10.1", - "libc", -] - [[package]] name = "core_maths" version = "0.1.1" @@ -1229,7 +1227,7 @@ dependencies = [ "egui-wgpu", "egui-winit", "egui_glow", - "glow", + "glow 0.16.0", "glutin", "glutin-winit", "home", @@ -1391,7 +1389,7 @@ dependencies = [ "document-features", "egui", "egui-winit", - "glow", + "glow 0.16.0", "glutin", "glutin-winit", "log", @@ -1658,7 +1656,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "998b056554fbe42e03ae0e152895cd1a7e1002aec800fdc6635d20270260c46f" dependencies = [ - "bit-set", + "bit-set 0.8.0", "regex-automata", "regex-syntax", ] @@ -1934,6 +1932,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "glutin" version = "0.32.3" @@ -2427,9 +2437,9 @@ checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -2596,15 +2606,6 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373f5eceeeab7925e0c1098212f2fbc4d416adec9d35051a6ab251e824c1854a" -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.7.4" @@ -2629,21 +2630,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "metal" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" -dependencies = [ - "bitflags 2.9.4", - "block", - "core-graphics-types 0.2.0", - "foreign-types", - "log", - "objc", - "paste", -] - [[package]] name = "mimalloc" version = "0.1.48" @@ -2708,12 +2694,12 @@ dependencies = [ [[package]] name = "naga" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618f667225063219ddfc61251087db8a9aec3c3f0950c916b614e403486f1135" +checksum = "85b4372fed0bd362d646d01b6926df0e837859ccc522fed720c395e0460f29c8" dependencies = [ "arrayvec", - "bit-set", + "bit-set 0.9.1", "bitflags 2.9.4", "cfg-if", "cfg_aliases", @@ -2818,15 +2804,6 @@ dependencies = [ "syn", ] -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - [[package]] name = "objc-sys" version = "0.3.5" @@ -2865,7 +2842,7 @@ dependencies = [ "objc2-core-data", "objc2-core-image", "objc2-foundation 0.2.2", - "objc2-quartz-core", + "objc2-quartz-core 0.2.2", ] [[package]] @@ -2951,7 +2928,7 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", - "objc2-metal", + "objc2-metal 0.2.2", ] [[package]] @@ -3031,6 +3008,18 @@ dependencies = [ "objc2-foundation 0.2.2", ] +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.9.4", + "block2 0.6.2", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + [[package]] name = "objc2-quartz-core" version = "0.2.2" @@ -3041,7 +3030,20 @@ dependencies = [ "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", - "objc2-metal", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.9.4", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", ] [[package]] @@ -3069,7 +3071,7 @@ dependencies = [ "objc2-core-location", "objc2-foundation 0.2.2", "objc2-link-presentation", - "objc2-quartz-core", + "objc2-quartz-core 0.2.2", "objc2-symbols", "objc2-uniform-type-identifiers", "objc2-user-notifications", @@ -3209,12 +3211,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "pathdiff" version = "0.2.3" @@ -3672,6 +3668,18 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + [[package]] name = "rayon" version = "1.11.0" @@ -4220,9 +4228,9 @@ dependencies = [ [[package]] name = "spirv" -version = "0.3.0+sdk-1.3.268.0" +version = "0.4.0+sdk-1.4.341.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" dependencies = [ "bitflags 2.9.4", ] @@ -4876,37 +4884,25 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -4915,9 +4911,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4925,22 +4921,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -5056,9 +5052,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -5107,9 +5103,9 @@ checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "wgpu" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f" +checksum = "78f9f386699b1fb8b8a05bfe82169b24d151f05702d2905a0bf93bc454fcc825" dependencies = [ "arrayvec", "bitflags 2.9.4", @@ -5137,13 +5133,13 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb4c8b5db5f00e56f1f08869d870a0dff7c8bc7ebc01091fec140b0cf0211a9" +checksum = "c7c34181b0acb8f98168f78f8e57ec66f57df5522b39143dbe5f2f45d7ca927c" dependencies = [ "arrayvec", - "bit-set", - "bit-vec", + "bit-set 0.9.1", + "bit-vec 0.9.1", "bitflags 2.9.4", "bytemuck", "cfg_aliases", @@ -5165,62 +5161,62 @@ dependencies = [ "wgpu-core-deps-wasm", "wgpu-core-deps-windows-linux-android", "wgpu-hal", + "wgpu-naga-bridge", "wgpu-types", ] [[package]] name = "wgpu-core-deps-apple" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b7b696b918f337c486bf93142454080a32a37832ba8a31e4f48221890047da" +checksum = "43acd053312501689cd92a01a9638d37f3e41a5fd9534875efa8917ee2d11ac0" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-emscripten" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b251c331f84feac147de3c4aa3aa45112622a95dd7ee1b74384fa0458dbd79" +checksum = "ef043bf135cc68b6f667c55ff4e345ce2b5924d75bad36a47921b0287ca4b24a" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-wasm" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a2cf578ce8d7d50d0e63ddc2345c7dcb599f6eb90b888813406ea78b9b7010" +checksum = "2f7b75e72f49035f000dd5262e4126242e92a090a4fd75931ecfe7e60784e6fa" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-windows-linux-android" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca976e72b2c9964eb243e281f6ce7f14a514e409920920dcda12ae40febaae" +checksum = "725d5c006a8c02967b6d93ef04f6537ec4593313e330cfe86d9d3f946eb90f28" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-hal" -version = "28.0.0" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293080d77fdd14d6b08a67c5487dfddbf874534bb7921526db56a7b75d7e3bef" +checksum = "058b6047337cf323a4f092486443a9337f3d81325347e5d77deed7e563aeaedc" dependencies = [ "android_system_properties", "arrayvec", "ash", - "bit-set", + "bit-set 0.9.1", "bitflags 2.9.4", - "block", + "block2 0.6.2", "bytemuck", "cfg-if", "cfg_aliases", - "core-graphics-types 0.2.0", - "glow", + "glow 0.17.0", "glutin_wgl_sys", "gpu-allocator", "gpu-descriptor", @@ -5230,10 +5226,13 @@ dependencies = [ "libc", "libloading", "log", - "metal", "naga", "ndk-sys", - "objc", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", "once_cell", "ordered-float", "parking_lot", @@ -5242,26 +5241,40 @@ dependencies = [ "profiling", "range-alloc", "raw-window-handle", + "raw-window-metal", "renderdoc-sys", "smallvec", "thiserror 2.0.17", "wasm-bindgen", + "wayland-sys", "web-sys", + "wgpu-naga-bridge", "wgpu-types", "windows", "windows-core 0.62.2", ] [[package]] -name = "wgpu-types" -version = "28.0.0" +name = "wgpu-naga-bridge" +version = "29.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c" +checksum = "d0b8e1e505095f24cb4a578f04b1421d456257dca7fac114d9d9dd3d978c34b8" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15ece45db77dd5451f11c0ce898334317ce8502d304a20454b531fdc0652fae" dependencies = [ "bitflags 2.9.4", "bytemuck", "js-sys", "log", + "raw-window-handle", "web-sys", ] diff --git a/Cargo.toml b/Cargo.toml index d12b040fe..28ccd7be5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,13 +138,13 @@ type-map = "0.5.1" unicode_names2 = { version = "2.0.0", default-features = false } unicode-segmentation = "1.12.0" vello_cpu = { version = "0.0.6", default-features = false, features = ["std", "u8_pipeline", "f32_pipeline"] } -wasm-bindgen = "0.2.100" # Keep wasm-bindgen version in sync in: setup_web.sh, Cargo.toml, Cargo.lock, rust.yml +wasm-bindgen = "0.2.114" # Keep wasm-bindgen version in sync in: setup_web.sh, Cargo.toml, Cargo.lock, rust.yml wasm-bindgen-futures = "0.4.0" wayland-cursor = { version = "0.31.11", default-features = false } web-sys = "0.3.77" web-time = "1.1.0" # Timekeeping for native and web webbrowser = "1.0.5" -wgpu = { version = "28.0.0", default-features = false, features = ["std"] } +wgpu = { version = "29.0.0", default-features = false, features = ["std"] } windows-sys = "0.61.2" winit = { version = "0.30.12", default-features = false } diff --git a/crates/eframe/src/native/wgpu_integration.rs b/crates/eframe/src/native/wgpu_integration.rs index 9d6283808..ea96a1845 100644 --- a/crates/eframe/src/native/wgpu_integration.rs +++ b/crates/eframe/src/native/wgpu_integration.rs @@ -184,9 +184,17 @@ impl<'app> WgpuWinitApp<'app> { builder: ViewportBuilder, ) -> crate::Result<&mut WgpuWinitRunning<'app>> { profiling::function_scope!(); + // Inject the display handle into the wgpu setup so that wgpu can create + // surfaces on platforms that require it (e.g. GLES on Wayland). + let mut wgpu_options = self.native_options.wgpu_options.clone(); + if let egui_wgpu::WgpuSetup::CreateNew(ref mut create_new) = wgpu_options.wgpu_setup + && create_new.display_handle.is_none() + { + create_new.display_handle = Some(Box::new(event_loop.owned_display_handle())); + } let mut painter = pollster::block_on(egui_wgpu::winit::Painter::new( egui_ctx.clone(), - self.native_options.wgpu_options.clone(), + wgpu_options, self.native_options.viewport.transparent.unwrap_or(false), egui_wgpu::RendererOptions { msaa_samples: self.native_options.multisampling as _, diff --git a/crates/eframe/src/web/mod.rs b/crates/eframe/src/web/mod.rs index 1e54d7a84..87771f722 100644 --- a/crates/eframe/src/web/mod.rs +++ b/crates/eframe/src/web/mod.rs @@ -38,6 +38,7 @@ mod web_painter_wgpu; pub use backend::*; use egui::Theme; +use js_sys::Object; use wasm_bindgen::prelude::*; use web_sys::{Document, MediaQueryList, Node}; @@ -370,5 +371,5 @@ pub fn percent_decode(s: &str) -> String { /// Are we running inside the Safari browser? pub fn is_safari_browser() -> bool { - web_sys::window().is_some_and(|window| window.has_own_property(&JsValue::from("safari"))) + web_sys::window().is_some_and(|window| Object::has_own(&window, &JsValue::from("safari"))) } diff --git a/crates/eframe/src/web/web_painter_wgpu.rs b/crates/eframe/src/web/web_painter_wgpu.rs index f7adb8fbb..b82b33bf7 100644 --- a/crates/eframe/src/web/web_painter_wgpu.rs +++ b/crates/eframe/src/web/web_painter_wgpu.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use egui::{Event, UserData, ViewportId}; use egui_wgpu::{ - RenderState, SurfaceErrorAction, + RenderState, SurfaceErrorAction, SurfaceStatus, capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel}, }; use wasm_bindgen::JsValue; @@ -15,7 +15,7 @@ pub(crate) struct WebPainterWgpu { surface: wgpu::Surface<'static>, surface_configuration: wgpu::SurfaceConfiguration, render_state: Option, - on_surface_error: Arc SurfaceErrorAction>, + on_surface_error: Arc SurfaceErrorAction>, depth_stencil_format: Option, depth_texture_view: Option, screen_capture_state: Option, @@ -196,17 +196,58 @@ impl WebPainter for WebPainterWgpu { } let output_frame = match self.surface.get_current_texture() { - Ok(frame) => frame, - Err(err) => match (*self.on_surface_error)(err) { - SurfaceErrorAction::RecreateSurface => { - self.surface - .configure(&render_state.device, &self.surface_configuration); - return Ok(()); + wgpu::CurrentSurfaceTexture::Success(frame) + | wgpu::CurrentSurfaceTexture::Suboptimal(frame) => frame, + wgpu::CurrentSurfaceTexture::Timeout => { + match (*self.on_surface_error)(SurfaceStatus::Timeout) { + SurfaceErrorAction::RecreateSurface => { + self.surface + .configure(&render_state.device, &self.surface_configuration); + } + SurfaceErrorAction::SkipFrame => {} } - SurfaceErrorAction::SkipFrame => { - return Ok(()); + return Ok(()); + } + wgpu::CurrentSurfaceTexture::Outdated => { + match (*self.on_surface_error)(SurfaceStatus::Outdated) { + SurfaceErrorAction::RecreateSurface => { + self.surface + .configure(&render_state.device, &self.surface_configuration); + } + SurfaceErrorAction::SkipFrame => {} } - }, + return Ok(()); + } + wgpu::CurrentSurfaceTexture::Lost => { + match (*self.on_surface_error)(SurfaceStatus::Lost) { + SurfaceErrorAction::RecreateSurface => { + self.surface + .configure(&render_state.device, &self.surface_configuration); + } + SurfaceErrorAction::SkipFrame => {} + } + return Ok(()); + } + wgpu::CurrentSurfaceTexture::Occluded => { + match (*self.on_surface_error)(SurfaceStatus::Occluded) { + SurfaceErrorAction::RecreateSurface => { + self.surface + .configure(&render_state.device, &self.surface_configuration); + } + SurfaceErrorAction::SkipFrame => {} + } + return Ok(()); + } + wgpu::CurrentSurfaceTexture::Validation => { + match (*self.on_surface_error)(SurfaceStatus::Validation) { + SurfaceErrorAction::RecreateSurface => { + self.surface + .configure(&render_state.device, &self.surface_configuration); + } + SurfaceErrorAction::SkipFrame => {} + } + return Ok(()); + } }; { diff --git a/crates/egui-wgpu/src/lib.rs b/crates/egui-wgpu/src/lib.rs index 46becf8f7..4f2840024 100644 --- a/crates/egui-wgpu/src/lib.rs +++ b/crates/egui-wgpu/src/lib.rs @@ -24,7 +24,10 @@ mod renderer; mod setup; pub use renderer::*; -pub use setup::{NativeAdapterSelectorMethod, WgpuSetup, WgpuSetupCreateNew, WgpuSetupExisting}; +pub use setup::{ + EguiDisplayHandle, NativeAdapterSelectorMethod, WgpuSetup, WgpuSetupCreateNew, + WgpuSetupExisting, +}; /// Helpers for capturing screenshots of the UI. #[cfg(feature = "capture")] @@ -191,6 +194,7 @@ impl RenderState { let (adapter, device, queue) = match config.wgpu_setup.clone() { WgpuSetup::CreateNew(WgpuSetupCreateNew { instance_descriptor: _, + display_handle: _, power_preference, native_adapter_selector: _native_adapter_selector, device_descriptor, @@ -272,7 +276,58 @@ fn describe_adapters(adapters: &[wgpu::Adapter]) -> String { } } -/// Specifies which action should be taken as consequence of a [`wgpu::SurfaceError`] +/// Describes a surface error when acquiring a texture for rendering. +/// +/// These correspond to the error variants of [`wgpu::CurrentSurfaceTexture`] — everything +/// except `Success` and `Suboptimal`, which contain usable frames. This enum is passed to the +/// [`WgpuConfiguration::on_surface_error`] callback so you can decide how to respond. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SurfaceStatus { + /// Timed out waiting for the next frame. + /// + /// This is usually transient. Skip the current frame and try again next frame. + Timeout, + + /// The surface configuration no longer matches the underlying display surface. + /// + /// The surface should be reconfigured (egui will do this automatically if you return + /// [`SurfaceErrorAction::RecreateSurface`]). This commonly happens after a window resize + /// or display settings change. + Outdated, + + /// The surface has been lost and must be recreated from scratch. + /// + /// This is more severe than [`Self::Outdated`] — the entire surface is invalid. Return + /// [`SurfaceErrorAction::RecreateSurface`] to recover. + Lost, + + /// The window is not visible (e.g. minimized or fully behind another window). + /// + /// Skip the current frame. There is nothing to render to. + Occluded, + + /// A GPU validation error occurred. + /// + /// This should not be reachable under normal circumstances, unless + /// you wrap the [`winit::Painter::paint_and_update_textures`] in a wgpu + /// error scope, and there is a validation error in the + /// [`wgpu::Surface::get_current_texture`] call. + Validation, +} + +impl std::fmt::Display for SurfaceStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Timeout => write!(f, "Surface timed out"), + Self::Outdated => write!(f, "Surface outdated"), + Self::Lost => write!(f, "Surface lost"), + Self::Occluded => write!(f, "Surface occluded"), + Self::Validation => write!(f, "Surface validation error"), + } + } +} + +/// Specifies which action should be taken as consequence of a [`SurfaceStatus`] pub enum SurfaceErrorAction { /// Do nothing and skip the current frame. SkipFrame, @@ -300,7 +355,7 @@ pub struct WgpuConfiguration { pub wgpu_setup: WgpuSetup, /// Callback for surface errors. - pub on_surface_error: Arc SurfaceErrorAction + Send + Sync>, + pub on_surface_error: Arc SurfaceErrorAction + Send + Sync>, } #[test] @@ -333,9 +388,11 @@ impl Default for WgpuConfiguration { Self { present_mode: wgpu::PresentMode::AutoVsync, desired_maximum_frame_latency: None, - wgpu_setup: Default::default(), + // No display handle available at this point — callers should replace this with + // `WgpuSetup::from_display_handle(...)` before creating the instance if one is available. + wgpu_setup: WgpuSetup::without_display_handle(), on_surface_error: Arc::new(|err| { - if err == wgpu::SurfaceError::Outdated { + if err == SurfaceStatus::Outdated { // This error occurs when the app is minimized on Windows. // Silently return here to prevent spamming the console with: // "The underlying surface has changed, and therefore the swap chain must be updated" diff --git a/crates/egui-wgpu/src/renderer.rs b/crates/egui-wgpu/src/renderer.rs index c37802448..3222a5521 100644 --- a/crates/egui-wgpu/src/renderer.rs +++ b/crates/egui-wgpu/src/renderer.rs @@ -352,7 +352,10 @@ impl Renderer { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("egui_pipeline_layout"), - bind_group_layouts: &[&uniform_bind_group_layout, &texture_bind_group_layout], + bind_group_layouts: &[ + Some(&uniform_bind_group_layout), + Some(&texture_bind_group_layout), + ], immediate_size: 0, }); @@ -360,8 +363,8 @@ impl Renderer { .depth_stencil_format .map(|format| wgpu::DepthStencilState { format, - depth_write_enabled: false, - depth_compare: wgpu::CompareFunction::Always, + depth_write_enabled: Some(false), + depth_compare: Some(wgpu::CompareFunction::Always), stencil: wgpu::StencilState::default(), bias: wgpu::DepthBiasState::default(), }); @@ -968,7 +971,8 @@ impl Renderer { Primitive::Mesh(mesh) => { let size = mesh.indices.len() * std::mem::size_of::(); let slice = index_offset..(size + index_offset); - index_buffer_staging[slice.clone()] + index_buffer_staging + .slice(slice.clone()) .copy_from_slice(bytemuck::cast_slice(&mesh.indices)); self.index_buffer.slices.push(slice); index_offset += size; @@ -1011,7 +1015,8 @@ impl Renderer { Primitive::Mesh(mesh) => { let size = mesh.vertices.len() * std::mem::size_of::(); let slice = vertex_offset..(size + vertex_offset); - vertex_buffer_staging[slice.clone()] + vertex_buffer_staging + .slice(slice.clone()) .copy_from_slice(bytemuck::cast_slice(&mesh.vertices)); self.vertex_buffer.slices.push(slice); vertex_offset += size; diff --git a/crates/egui-wgpu/src/setup.rs b/crates/egui-wgpu/src/setup.rs index 0c3cb8c39..29a04e8bc 100644 --- a/crates/egui-wgpu/src/setup.rs +++ b/crates/egui-wgpu/src/setup.rs @@ -1,5 +1,47 @@ use std::sync::Arc; +/// A cloneable display handle for use with [`wgpu::InstanceDescriptor`]. +/// +/// This trait exists so that a [`winit::event_loop::OwnedDisplayHandle`] (or similar platform +/// display handle) can be stored, cloned, and later passed to wgpu. +/// +/// wgpu requires an explicit display handle for GLES on some platforms (notably Wayland). +/// Because [`wgpu::InstanceDescriptor`] contains a `Box` which is +/// not cloneable, we wrap the handle in this trait so it can be cloned alongside the rest of +/// the egui wgpu configuration. +/// +/// This is automatically implemented for all types that satisfy the bounds (including +/// [`winit::event_loop::OwnedDisplayHandle`]). +pub trait EguiDisplayHandle: + wgpu::rwh::HasDisplayHandle + std::fmt::Debug + Send + Sync + 'static +{ + /// Clone this handle into a `Box` suitable for setting on + /// [`wgpu::InstanceDescriptor::display`]. + fn clone_for_wgpu(&self) -> Box; + + /// Clone this handle into a new `Box`. + fn clone_display_handle(&self) -> Box; +} + +impl Clone for Box { + fn clone(&self) -> Self { + self.clone_display_handle() + } +} + +impl EguiDisplayHandle for T +where + T: wgpu::rwh::HasDisplayHandle + Clone + std::fmt::Debug + Send + Sync + 'static, +{ + fn clone_for_wgpu(&self) -> Box { + Box::new(self.clone()) + } + + fn clone_display_handle(&self) -> Box { + Box::new(self.clone()) + } +} + #[derive(Clone)] pub enum WgpuSetup { /// Construct a wgpu setup using some predefined settings & heuristics. @@ -22,9 +64,32 @@ pub enum WgpuSetup { Existing(WgpuSetupExisting), } -impl Default for WgpuSetup { - fn default() -> Self { - Self::CreateNew(WgpuSetupCreateNew::default()) +impl WgpuSetup { + /// Creates a new [`WgpuSetup::CreateNew`] with the given display handle. + /// + /// This is the recommended constructor. Most platforms (Windows, macOS/iOS, Android, web) + /// work fine without a display handle, but some (e.g. Wayland on Linux with GLES) require + /// one. Providing it unconditionally ensures your app works everywhere. + /// + /// If you don't have a display handle available, use [`Self::without_display_handle`] + /// instead — it will still work on the majority of platforms. + /// + /// With winit, pass [`EventLoop::owned_display_handle`](winit::event_loop::EventLoop::owned_display_handle). + pub fn from_display_handle(display_handle: impl EguiDisplayHandle) -> Self { + Self::CreateNew(WgpuSetupCreateNew::from_display_handle(display_handle)) + } + + /// Creates a new [`WgpuSetup::CreateNew`] without a display handle. + /// + /// A display handle is not required for headless operation (offscreen rendering, tests, + /// compute-only workloads). It also isn't needed on most platforms even when presenting + /// to a window — only some configurations (e.g. Wayland on Linux with GLES) require one. + /// + /// If you do have a display handle available, prefer [`Self::from_display_handle`] for + /// maximum compatibility. With winit you can obtain one via + /// [`EventLoop::owned_display_handle`](winit::event_loop::EventLoop::owned_display_handle). + pub fn without_display_handle() -> Self { + Self::CreateNew(WgpuSetupCreateNew::without_display_handle()) } } @@ -65,8 +130,18 @@ impl WgpuSetup { } log::debug!("Creating wgpu instance with backends {backends:?}"); - wgpu::util::new_instance_with_webgpu_detection(&create_new.instance_descriptor) - .await + let desc = &create_new.instance_descriptor; + let mut descriptor = wgpu::InstanceDescriptor { + backends: desc.backends, + flags: desc.flags, + backend_options: desc.backend_options.clone(), + memory_budget_thresholds: desc.memory_budget_thresholds, + display: None, + }; + if let Some(handle) = &create_new.display_handle { + descriptor.display = Some(handle.clone_for_wgpu()); + } + wgpu::util::new_instance_with_webgpu_detection(descriptor).await } Self::Existing(existing) => existing.instance.clone(), } @@ -98,9 +173,28 @@ pub type NativeAdapterSelectorMethod = Arc< /// Configuration for creating a new wgpu setup. /// /// Used for [`WgpuSetup::CreateNew`]. +/// +/// Use [`Self::from_display_handle`] when you have a display handle available — this is the +/// recommended constructor. With winit you can obtain one via +/// [`EventLoop::owned_display_handle`](winit::event_loop::EventLoop::owned_display_handle). +/// Most platforms (Windows, macOS/iOS, Android, web) work fine without one, but some +/// (e.g. Wayland on Linux with GLES) require it. Providing it unconditionally ensures your +/// app works everywhere. +/// +/// If you don't have a display handle, use [`Self::without_display_handle`] — it will still +/// work on the majority of platforms, and is appropriate for headless rendering, tests, or +/// web targets. +/// +/// Note: The [`wgpu::InstanceDescriptor::display`] field is always stored as `None` in +/// [`Self::instance_descriptor`]. The display handle is stored separately so it can be cloned +/// (since [`wgpu::InstanceDescriptor`] itself does not implement `Clone`), and is injected +/// into the descriptor at instance creation time. pub struct WgpuSetupCreateNew { /// Instance descriptor for creating a wgpu instance. /// + /// The [`wgpu::InstanceDescriptor::display`] field should be left as `None`; use the + /// [`Self::display_handle`] field instead (it will be injected when the instance is created). + /// /// The most important field is [`wgpu::InstanceDescriptor::backends`], which /// controls which backends are supported (wgpu will pick one of these). /// If you only want to support WebGL (and not WebGPU), @@ -110,6 +204,16 @@ pub struct WgpuSetupCreateNew { /// and only if you have enabled the `webgl` feature of crate `wgpu`. pub instance_descriptor: wgpu::InstanceDescriptor, + /// The display handle to pass to wgpu when creating the instance. + /// + /// Most platforms (Windows, macOS/iOS, Android, web) work without this, but some + /// (e.g. Wayland on Linux with GLES) require it. If you have a display handle + /// available, providing it ensures maximum compatibility. + /// + /// When using winit, this is typically the + /// [`winit::event_loop::OwnedDisplayHandle`] obtained from the event loop. + pub display_handle: Option>, + /// Power preference for the adapter if [`Self::native_adapter_selector`] is not set or targeting web. pub power_preference: wgpu::PowerPreference, @@ -128,32 +232,34 @@ pub struct WgpuSetupCreateNew { Arc wgpu::DeviceDescriptor<'static> + Send + Sync>, } -impl Clone for WgpuSetupCreateNew { - fn clone(&self) -> Self { +impl WgpuSetupCreateNew { + /// Creates a new configuration with the given display handle. + /// + /// This is the recommended constructor. Most platforms (Windows, macOS/iOS, Android, web) + /// work fine without a display handle, but some (e.g. Wayland on Linux with GLES) require + /// one. Providing it unconditionally ensures your app works everywhere. + /// + /// If you don't have a display handle available, use [`Self::without_display_handle`] + /// instead — it will still work on the majority of platforms. + /// + /// With winit, pass [`EventLoop::owned_display_handle`](winit::event_loop::EventLoop::owned_display_handle). + pub fn from_display_handle(display_handle: impl EguiDisplayHandle) -> Self { Self { - instance_descriptor: self.instance_descriptor.clone(), - power_preference: self.power_preference, - native_adapter_selector: self.native_adapter_selector.clone(), - device_descriptor: Arc::clone(&self.device_descriptor), + display_handle: Some(Box::new(display_handle)), + ..Self::without_display_handle() } } -} -impl std::fmt::Debug for WgpuSetupCreateNew { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("WgpuSetupCreateNew") - .field("instance_descriptor", &self.instance_descriptor) - .field("power_preference", &self.power_preference) - .field( - "native_adapter_selector", - &self.native_adapter_selector.is_some(), - ) - .finish() - } -} - -impl Default for WgpuSetupCreateNew { - fn default() -> Self { + /// Creates a new configuration without a display handle. + /// + /// A display handle is not required for headless operation (offscreen rendering, tests, + /// compute-only workloads). It also isn't needed on most platforms even when presenting + /// to a window — only some configurations (e.g. Wayland on Linux with GLES) require one. + /// + /// If you do have a display handle available, prefer [`Self::from_display_handle`] for + /// maximum compatibility. With winit you can obtain one via + /// [`EventLoop::owned_display_handle`](winit::event_loop::EventLoop::owned_display_handle). + pub fn without_display_handle() -> Self { Self { instance_descriptor: wgpu::InstanceDescriptor { // Add GL backend, primarily because WebGPU is not stable enough yet. @@ -163,8 +269,11 @@ impl Default for WgpuSetupCreateNew { flags: wgpu::InstanceFlags::from_build_config().with_env(), backend_options: wgpu::BackendOptions::from_env_or_default(), memory_budget_thresholds: wgpu::MemoryBudgetThresholds::default(), + display: None, }, + display_handle: None, + power_preference: wgpu::PowerPreference::from_env() .unwrap_or(wgpu::PowerPreference::HighPerformance), @@ -192,6 +301,39 @@ impl Default for WgpuSetupCreateNew { } } +impl Clone for WgpuSetupCreateNew { + fn clone(&self) -> Self { + let desc = &self.instance_descriptor; + Self { + instance_descriptor: wgpu::InstanceDescriptor { + backends: desc.backends, + flags: desc.flags, + backend_options: desc.backend_options.clone(), + memory_budget_thresholds: desc.memory_budget_thresholds, + display: None, + }, + display_handle: self.display_handle.clone(), + power_preference: self.power_preference, + native_adapter_selector: self.native_adapter_selector.clone(), + device_descriptor: Arc::clone(&self.device_descriptor), + } + } +} + +impl std::fmt::Debug for WgpuSetupCreateNew { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("WgpuSetupCreateNew") + .field("instance_descriptor", &self.instance_descriptor) + .field("display_handle", &self.display_handle) + .field("power_preference", &self.power_preference) + .field( + "native_adapter_selector", + &self.native_adapter_selector.is_some(), + ) + .finish() + } +} + /// Configuration for using an existing wgpu setup. /// /// Used for [`WgpuSetup::Existing`]. diff --git a/crates/egui-wgpu/src/winit.rs b/crates/egui-wgpu/src/winit.rs index 5fb8d123a..f9ef19cc4 100644 --- a/crates/egui-wgpu/src/winit.rs +++ b/crates/egui-wgpu/src/winit.rs @@ -3,7 +3,7 @@ #![expect(clippy::unwrap_used)] // TODO(emilk): avoid unwraps #![expect(unsafe_code)] -use crate::{RenderState, SurfaceErrorAction, WgpuConfiguration, renderer}; +use crate::{RenderState, SurfaceErrorAction, SurfaceStatus, WgpuConfiguration, renderer}; use crate::{ RendererOptions, capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel}, @@ -368,7 +368,7 @@ impl Painter { hal_surface .render_layer() .lock() - .set_presents_with_transaction(resizing); + .setPresentsWithTransaction(resizing); Self::configure_surface( state, @@ -501,16 +501,53 @@ impl Painter { }; let output_frame = match output_frame { - Ok(frame) => frame, - Err(err) => match (*self.configuration.on_surface_error)(err) { - SurfaceErrorAction::RecreateSurface => { - Self::configure_surface(surface_state, render_state, &self.configuration); - return vsync_sec; + wgpu::CurrentSurfaceTexture::Success(frame) + | wgpu::CurrentSurfaceTexture::Suboptimal(frame) => frame, + wgpu::CurrentSurfaceTexture::Timeout => { + match (*self.configuration.on_surface_error)(SurfaceStatus::Timeout) { + SurfaceErrorAction::RecreateSurface => { + Self::configure_surface(surface_state, render_state, &self.configuration); + } + SurfaceErrorAction::SkipFrame => {} } - SurfaceErrorAction::SkipFrame => { - return vsync_sec; + return vsync_sec; + } + wgpu::CurrentSurfaceTexture::Outdated => { + match (*self.configuration.on_surface_error)(SurfaceStatus::Outdated) { + SurfaceErrorAction::RecreateSurface => { + Self::configure_surface(surface_state, render_state, &self.configuration); + } + SurfaceErrorAction::SkipFrame => {} } - }, + return vsync_sec; + } + wgpu::CurrentSurfaceTexture::Lost => { + match (*self.configuration.on_surface_error)(SurfaceStatus::Lost) { + SurfaceErrorAction::RecreateSurface => { + Self::configure_surface(surface_state, render_state, &self.configuration); + } + SurfaceErrorAction::SkipFrame => {} + } + return vsync_sec; + } + wgpu::CurrentSurfaceTexture::Occluded => { + match (*self.configuration.on_surface_error)(SurfaceStatus::Occluded) { + SurfaceErrorAction::RecreateSurface => { + Self::configure_surface(surface_state, render_state, &self.configuration); + } + SurfaceErrorAction::SkipFrame => {} + } + return vsync_sec; + } + wgpu::CurrentSurfaceTexture::Validation => { + match (*self.configuration.on_surface_error)(SurfaceStatus::Validation) { + SurfaceErrorAction::RecreateSurface => { + Self::configure_surface(surface_state, render_state, &self.configuration); + } + SurfaceErrorAction::SkipFrame => {} + } + return vsync_sec; + } }; let mut capture_buffer = None; diff --git a/crates/egui_demo_app/src/apps/custom3d_wgpu.rs b/crates/egui_demo_app/src/apps/custom3d_wgpu.rs index fd1d9ae73..d83f000a4 100644 --- a/crates/egui_demo_app/src/apps/custom3d_wgpu.rs +++ b/crates/egui_demo_app/src/apps/custom3d_wgpu.rs @@ -40,7 +40,7 @@ impl Custom3d { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("custom3d"), - bind_group_layouts: &[&bind_group_layout], + bind_group_layouts: &[Some(&bind_group_layout)], immediate_size: 0, }); diff --git a/crates/egui_kittest/src/wgpu.rs b/crates/egui_kittest/src/wgpu.rs index 3f97e0036..a9f0de9ad 100644 --- a/crates/egui_kittest/src/wgpu.rs +++ b/crates/egui_kittest/src/wgpu.rs @@ -17,7 +17,8 @@ pub(crate) const WAIT_TIMEOUT: Duration = Duration::from_secs(10); /// Default wgpu setup used for the wgpu renderer. pub fn default_wgpu_setup() -> egui_wgpu::WgpuSetup { - let mut setup = egui_wgpu::WgpuSetupCreateNew::default(); + // No display handle needed for headless testing — we don't present to a window. + let mut setup = egui_wgpu::WgpuSetupCreateNew::without_display_handle(); // WebGPU not supported yet since we rely on blocking screenshots. setup @@ -58,6 +59,7 @@ pub fn default_wgpu_setup() -> egui_wgpu::WgpuSetup { } pub fn create_render_state(setup: WgpuSetup) -> egui_wgpu::RenderState { + // No display handle needed for headless testing — we don't present to a window. let instance = pollster::block_on(setup.new_instance()); pollster::block_on(egui_wgpu::RenderState::create( diff --git a/scripts/setup_web.sh b/scripts/setup_web.sh index f51258855..67ff80e38 100755 --- a/scripts/setup_web.sh +++ b/scripts/setup_web.sh @@ -10,6 +10,6 @@ rustup target add wasm32-unknown-unknown # For generating JS bindings: # Keep wasm-bindgen version in sync in: setup_web.sh, Cargo.toml, Cargo.lock, rust.yml -if ! cargo install --list | grep -q 'wasm-bindgen-cli v0.2.100'; then - cargo install --force --quiet wasm-bindgen-cli --version 0.2.100 +if ! cargo install --list | grep -q 'wasm-bindgen-cli v0.2.114'; then + cargo install --force --quiet wasm-bindgen-cli --version 0.2.114 fi