From 321ee42771f4301ad1e9057aef726b3ca17bc688 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 27 Jan 2025 09:14:09 -0800 Subject: [PATCH] =?UTF-8?q?Don=E2=80=99t=20copy=20buffer=20data=20back=20t?= =?UTF-8?q?o=20JS=20if=20unnecessary,=20in=20WebGPU=20backend.=20(#7007)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ wgpu/src/backend/webgpu.rs | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a7b70b17..07315f2932 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,10 @@ By @brodycj in [#6924](https://github.com/gfx-rs/wgpu/pull/6924). - Stop naga causing undefined behavior when a ray query misses. By @Vecvec in [#6752](https://github.com/gfx-rs/wgpu/pull/6752). +#### WebGPU + +- Improve efficiency of dropping read-only buffer mappings. By @kpreid in [#7007](https://github.com/gfx-rs/wgpu/pull/7007). + ### Documentation - Improved documentation around pipeline caches and `TextureBlitter`. By @DJMcNab in [#6978](https://github.com/gfx-rs/wgpu/pull/6978) and [#7003](https://github.com/gfx-rs/wgpu/pull/7003). diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index 154f01f02a..adc05210f8 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -1368,7 +1368,11 @@ pub struct WebQueueWriteBuffer { #[derive(Debug)] pub struct WebBufferMappedRange { actual_mapping: js_sys::Uint8Array, + /// Copy of the mapped data that lives in the Rust/Wasm heap instead of JS, + /// so Rust code can borrow it. temporary_mapping: Vec, + /// Whether `temporary_mapping` has possibly been written to and needs to be written back to JS. + temporary_mapping_modified: bool, /// Unique identifier for this BufferMappedRange. ident: crate::cmp::Identifier, } @@ -2672,6 +2676,7 @@ impl dispatch::BufferInterface for WebBuffer { WebBufferMappedRange { actual_mapping, temporary_mapping, + temporary_mapping_modified: false, ident: crate::cmp::Identifier::create(), } .into() @@ -3780,11 +3785,18 @@ impl dispatch::BufferMappedRangeInterface for WebBufferMappedRange { #[inline] fn slice_mut(&mut self) -> &mut [u8] { + self.temporary_mapping_modified = true; &mut self.temporary_mapping } } impl Drop for WebBufferMappedRange { fn drop(&mut self) { + if !self.temporary_mapping_modified { + // For efficiency, skip the copy if it is not needed. + // This is also how we skip copying back on *read-only* mappings. + return; + } + // Copy from the temporary mapping back into the array buffer that was // originally provided by the browser let temporary_mapping_slice = self.temporary_mapping.as_slice();