diff --git a/deno_webgpu/buffer.rs b/deno_webgpu/buffer.rs index 3cb9fdf83..9a2ebb003 100644 --- a/deno_webgpu/buffer.rs +++ b/deno_webgpu/buffer.rs @@ -98,7 +98,8 @@ pub async fn op_webgpu_buffer_get_map_async( // TODO(lucacasonato): error handling let maybe_err = gfx_select!(buffer => instance.buffer_map_async( buffer, - offset..(offset + size), + offset, + Some(size), wgpu_core::resource::BufferMapOperation { host: match mode { 1 => wgpu_core::device::HostMap::Read, diff --git a/player/tests/test.rs b/player/tests/test.rs index e38de1cea..c04622b42 100644 --- a/player/tests/test.rs +++ b/player/tests/test.rs @@ -131,7 +131,8 @@ impl Test<'_> { let buffer = wgc::id::Id::zip(expect.buffer.index, expect.buffer.epoch, backend); wgc::gfx_select!(device_id => global.buffer_map_async( buffer, - expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress, + expect.offset, + Some(expect.data.len() as u64), wgc::resource::BufferMapOperation { host: wgc::device::HostMap::Read, callback: Some(wgc::resource::BufferMapCallback::from_rust( diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 64fd6d4de..e5c4e733b 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -26,9 +26,7 @@ use wgt::{BufferAddress, TextureFormat}; use std::{ borrow::Cow, - iter, - ops::Range, - ptr, + iter, ptr, sync::{atomic::Ordering, Arc}, }; @@ -2336,15 +2334,18 @@ impl Global { pub fn buffer_map_async( &self, buffer_id: id::BufferId, - range: Range, + offset: BufferAddress, + size: Option, op: BufferMapOperation, ) -> BufferAccessResult { - api_log!("Buffer::map_async {buffer_id:?} range {range:?} op: {op:?}"); + api_log!("Buffer::map_async {buffer_id:?} offset {offset:?} size {size:?} op: {op:?}"); // User callbacks must not be called while holding buffer_map_async_inner's locks, so we // defer the error callback if it needs to be called immediately (typically when running // into errors). - if let Err((mut operation, err)) = self.buffer_map_async_inner::(buffer_id, range, op) { + if let Err((mut operation, err)) = + self.buffer_map_async_inner::(buffer_id, offset, size, op) + { if let Some(callback) = operation.callback.take() { callback.call(Err(err.clone())); } @@ -2360,7 +2361,8 @@ impl Global { fn buffer_map_async_inner( &self, buffer_id: id::BufferId, - range: Range, + offset: BufferAddress, + size: Option, op: BufferMapOperation, ) -> Result<(), (BufferMapOperation, BufferAccessError)> { profiling::scope!("Buffer::map_async"); @@ -2372,22 +2374,43 @@ impl Global { HostMap::Write => (wgt::BufferUsages::MAP_WRITE, hal::BufferUses::MAP_WRITE), }; - if range.start % wgt::MAP_ALIGNMENT != 0 || range.end % wgt::COPY_BUFFER_ALIGNMENT != 0 { - return Err((op, BufferAccessError::UnalignedRange)); - } - let buffer = { - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| BufferAccessError::Invalid); + let buffer = hub.buffers.get(buffer_id); let buffer = match buffer { Ok(b) => b, - Err(e) => { - return Err((op, e)); + Err(_) => { + return Err((op, BufferAccessError::Invalid)); } }; + { + let snatch_guard = buffer.device.snatchable_lock.read(); + if buffer.is_destroyed(&snatch_guard) { + return Err((op, BufferAccessError::Destroyed)); + } + } + + let range_size = if let Some(size) = size { + size + } else if offset > buffer.size { + 0 + } else { + buffer.size - offset + }; + + if offset % wgt::MAP_ALIGNMENT != 0 { + return Err((op, BufferAccessError::UnalignedOffset { offset })); + } + if range_size % wgt::COPY_BUFFER_ALIGNMENT != 0 { + return Err((op, BufferAccessError::UnalignedRangeSize { range_size })); + } + + let range = offset..(offset + range_size); + + if range.start % wgt::MAP_ALIGNMENT != 0 || range.end % wgt::COPY_BUFFER_ALIGNMENT != 0 + { + return Err((op, BufferAccessError::UnalignedRange)); + } let device = &buffer.device; if !device.is_valid() { @@ -2417,11 +2440,6 @@ impl Global { )); } - let snatch_guard = device.snatchable_lock.read(); - if buffer.is_destroyed(&snatch_guard) { - return Err((op, BufferAccessError::Destroyed)); - } - { let map_state = &mut *buffer.map_state.lock(); *map_state = match *map_state { @@ -2442,6 +2460,8 @@ impl Global { }; } + let snatch_guard = buffer.device.snatchable_lock.read(); + { let mut trackers = buffer.device.as_ref().trackers.lock(); trackers.buffers.set_single(&buffer, internal_use); diff --git a/wgpu/src/backend/wgpu_core.rs b/wgpu/src/backend/wgpu_core.rs index 3901e7d44..b43291e79 100644 --- a/wgpu/src/backend/wgpu_core.rs +++ b/wgpu/src/backend/wgpu_core.rs @@ -1453,7 +1453,8 @@ impl crate::Context for ContextWgpuCore { ))), }; - match wgc::gfx_select!(buffer => self.0.buffer_map_async(*buffer, range, operation)) { + match wgc::gfx_select!(buffer => self.0.buffer_map_async(*buffer, range.start, Some(range.end-range.start), operation)) + { Ok(()) => (), Err(cause) => { self.handle_error_nolabel(&buffer_data.error_sink, cause, "Buffer::map_async")