From 1d06caf7afe518e177ea771b6ceef7dc17dbe20e Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Mon, 9 Nov 2026 11:34:02 -0400 Subject: [PATCH] perf(webgpu): pooled buffer uploads; core adapter for compatibility requests - Bump wgpu to the fork commit that sub-allocates small Queue::write_buffer uploads from reused staging chunks and records them as batched copies, instead of creating, mapping and copying from a new staging buffer per call. - Android: a featureLevel "compatibility" request now gets the hardware Vulkan adapter (GL only without it), and the adapter reports core with "core-features-and-limits" unless it is GL. Before, it went to the GL backend, which returned no adapter, so libraries that ask for compatibility (three.js WebGPURenderer) fell back to WebGL2. --- Cargo.toml | 6 ++--- crates/canvas-c/src/webgpu/gpu.rs | 42 +++++++++++++++++-------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a3ff69c..e8056ce3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ cpal = { path = "crates/vendor/cpal" } [workspace.dependencies.wgt] package = "wgpu-types" git = "https://github.com/triniwiz/wgpu" -rev = "e5c0aa02" +rev = "399344e78" @@ -103,8 +103,8 @@ quick-xml = "0.34" skia-safe = { git = "https://github.com/triniwiz/rust-skia", rev = "b9d29071cd8876b2447d58a14346b9fe6a5d21e2", features = ["textlayout"] } itertools = "0.14.0" ustr = "1.1.0" -wgpu-core = { git = "https://github.com/triniwiz/wgpu", rev = "e5c0aa02", features = ["wgsl"] } -wgpu-hal = { git = "https://github.com/triniwiz/wgpu", rev = "e5c0aa02" } +wgpu-core = { git = "https://github.com/triniwiz/wgpu", rev = "399344e78", features = ["wgsl"] } +wgpu-hal = { git = "https://github.com/triniwiz/wgpu", rev = "399344e78" } ureq = "2.10.1" jni = "0.21.1" regex-lite = "0.1.9" diff --git a/crates/canvas-c/src/webgpu/gpu.rs b/crates/canvas-c/src/webgpu/gpu.rs index 86d4a720..8cdb40d0 100644 --- a/crates/canvas-c/src/webgpu/gpu.rs +++ b/crates/canvas-c/src/webgpu/gpu.rs @@ -174,28 +174,26 @@ pub unsafe extern "C" fn canvas_native_webgpu_request_adapter( inner.request_adapter(&opts, wgt::Backends::METAL) } + // Compatibility requests may get a core adapter: hardware Vulkan first, GL + // only without it. #[cfg(target_os = "android")] { - if options.feature_level == CanvasGPUFeatureLevel::Compatibility { - inner.request_adapter(&opts, wgt::Backends::GL) - } else { - let vulkan_adapter = inner.request_adapter(&opts, wgt::Backends::VULKAN); + let vulkan_adapter = inner.request_adapter(&opts, wgt::Backends::VULKAN); - let is_hardware_vulkan = vulkan_adapter.as_ref().map_or(false, |adapter| { - adapter.get_info().device_type != wgt::DeviceType::Cpu - }); + let is_hardware_vulkan = vulkan_adapter.as_ref().map_or(false, |adapter| { + adapter.get_info().device_type != wgt::DeviceType::Cpu + }); - if is_hardware_vulkan { - vulkan_adapter + if is_hardware_vulkan { + vulkan_adapter + } else { + let gl_adapter = inner.request_adapter(&opts, wgt::Backends::GL); + if gl_adapter.is_ok() { + // dropping the Arc releases it; there is no adapter_drop any more + drop(vulkan_adapter); + gl_adapter } else { - let gl_adapter = inner.request_adapter(&opts, wgt::Backends::GL); - if gl_adapter.is_ok() { - // dropping the Arc releases it; there is no adapter_drop any more - drop(vulkan_adapter); - gl_adapter - } else { - vulkan_adapter - } + vulkan_adapter } } } @@ -213,7 +211,13 @@ pub unsafe extern "C" fn canvas_native_webgpu_request_adapter( let adapter = adapter_id.map(|adapter| { let mut features = build_features(adapter.features()); - if options.feature_level != CanvasGPUFeatureLevel::Compatibility { + // Only the GL backend is limited to compatibility. + let feature_level = if adapter.get_info().backend == wgt::Backend::Gl { + options.feature_level + } else { + CanvasGPUFeatureLevel::Core + }; + if feature_level != CanvasGPUFeatureLevel::Compatibility { features.push("core-features-and-limits"); } let limits = adapter.limits(); @@ -221,7 +225,7 @@ pub unsafe extern "C" fn canvas_native_webgpu_request_adapter( instance, adapter, is_fallback_adapter: options.force_fallback_adapter, - feature_level: options.feature_level.into(), + feature_level: feature_level.into(), features, limits, };