Skip to content

Commit

Permalink
Support zero-sized mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Sep 22, 2021
1 parent 08ff76f commit 58db387
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 19 deletions.
1 change: 1 addition & 0 deletions cts_runner/test.lst
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
unittests:*
webgpu:api,operation,command_buffer,basic:*
webgpu:api,operation,command_buffer,copyBufferToBuffer:*
webgpu:api,operation,compute,basic:*
//FAIL: webgpu:api,validation,queue,copyToTexture,ImageBitmap:destination_texture,format:format="stencil8";*'
webgpu:api,operation,rendering,basic:clear:*
Expand Down
38 changes: 23 additions & 15 deletions wgpu-core/src/device/life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use hal::Device as _;
use parking_lot::Mutex;
use thiserror::Error;

use std::mem;
use std::{mem, ptr};

/// A struct that keeps lists of resources that are no longer needed by the user.
#[derive(Debug, Default)]
Expand Down Expand Up @@ -188,6 +188,7 @@ pub enum WaitIdleError {
pub(super) struct LifetimeTracker<A: hal::Api> {
/// Resources that the user has requested be mapped, but are still in use.
mapped: Vec<Stored<id::BufferId>>,
empty_mapping: [u8; 4],
/// Buffers can be used in a submission that is yet to be made, by the
/// means of `write_buffer()`, so we have a special place for them.
pub future_suspected_buffers: Vec<Stored<id::BufferId>>,
Expand All @@ -209,6 +210,7 @@ impl<A: hal::Api> LifetimeTracker<A> {
pub fn new() -> Self {
Self {
mapped: Vec::new(),
empty_mapping: [0; 4],
future_suspected_buffers: Vec::new(),
future_suspected_textures: Vec::new(),
suspected_resources: SuspectedResources::default(),
Expand Down Expand Up @@ -674,28 +676,34 @@ impl<A: HalApi> LifetimeTracker<A> {
}
_ => panic!("No pending mapping."),
};
let status = if mapping.range.start != mapping.range.end {

let size = mapping.range.end - mapping.range.start;
let host = mapping.op.host;
let ptr_maybe = if size != 0 {
log::debug!("Buffer {:?} map state -> Active", buffer_id);
let host = mapping.op.host;
let size = mapping.range.end - mapping.range.start;
match super::map_buffer(raw, buffer, mapping.range.start, size, host) {
Ok(ptr) => {
buffer.map_state = resource::BufferMapState::Active {
ptr,
range: mapping.range.start..mapping.range.start + size,
host,
};
resource::BufferMapAsyncStatus::Success
}
Ok(ptr) => Some(ptr),
Err(e) => {
log::error!("Mapping failed {:?}", e);
resource::BufferMapAsyncStatus::Error
None
}
}
} else {
resource::BufferMapAsyncStatus::Success
ptr::NonNull::new(self.empty_mapping.as_mut_ptr())
};
let status = match ptr_maybe {
Some(ptr) => {
buffer.map_state = resource::BufferMapState::Active {
ptr,
range: mapping.range.start..mapping.range.start + size,
host,
};
resource::BufferMapAsyncStatus::Success
}
None => resource::BufferMapAsyncStatus::Error,
};
pending_callbacks.push((mapping.op, status));

pending_callbacks.push((mapping.op, status, buffer_id.0));
}
}
pending_callbacks
Expand Down
16 changes: 12 additions & 4 deletions wgpu-core/src/device/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ impl RenderPassContext {
}
}

pub type BufferMapPendingClosure = (resource::BufferMapOperation, resource::BufferMapAsyncStatus);
pub type BufferMapPendingClosure = (
resource::BufferMapOperation,
resource::BufferMapAsyncStatus,
id::BufferId,
);

#[derive(Default)]
pub struct UserClosures {
Expand All @@ -127,7 +131,7 @@ impl UserClosures {
unsafe fn fire(self) {
//Note: this logic is specifically moved out of `handle_mapping()` in order to
// have nothing locked by the time we execute users callback code.
for (operation, status) in self.mappings {
for (operation, status, _id) in self.mappings {
(operation.callback)(status, operation.user_data);
}
for closure in self.submissions {
Expand Down Expand Up @@ -4815,7 +4819,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return Err(resource::BufferAccessError::NotMapped);
}
resource::BufferMapState::Waiting(pending) => {
return Ok(Some((pending.op, resource::BufferMapAsyncStatus::Aborted)));
return Ok(Some((
pending.op,
resource::BufferMapAsyncStatus::Aborted,
buffer_id,
)));
}
resource::BufferMapState::Active { ptr, range, host } => {
if host == HostMap::Write {
Expand Down Expand Up @@ -4852,7 +4860,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
) -> Result<(), resource::BufferAccessError> {
//Note: outside inner function so no locks are held when calling the callback
let closure = self.buffer_unmap_inner::<A>(buffer_id)?;
if let Some((operation, status)) = closure {
if let Some((operation, status, _)) = closure {
unsafe {
(operation.callback)(status, operation.user_data);
}
Expand Down

0 comments on commit 58db387

Please sign in to comment.