mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Error types for buffer mapping API
This commit is contained in:
parent
73b230871e
commit
ec12d9547d
@ -390,7 +390,8 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
|
|||||||
self.queue_write_buffer::<B>(device, id, range.start, &bin);
|
self.queue_write_buffer::<B>(device, id, range.start, &bin);
|
||||||
} else {
|
} else {
|
||||||
self.device_wait_for_buffer::<B>(device, id).unwrap();
|
self.device_wait_for_buffer::<B>(device, id).unwrap();
|
||||||
self.device_set_buffer_sub_data::<B>(device, id, range.start, &bin[..size]);
|
self.device_set_buffer_sub_data::<B>(device, id, range.start, &bin[..size])
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
A::WriteTexture {
|
A::WriteTexture {
|
||||||
|
|||||||
@ -97,7 +97,8 @@ impl Test {
|
|||||||
callback: map_callback,
|
callback: map_callback,
|
||||||
user_data: ptr::null_mut(),
|
user_data: ptr::null_mut(),
|
||||||
}
|
}
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("\t\t\tWaiting...");
|
println!("\t\t\tWaiting...");
|
||||||
@ -107,7 +108,8 @@ impl Test {
|
|||||||
println!("\t\t\tChecking {}", expect.name);
|
println!("\t\t\tChecking {}", expect.name);
|
||||||
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend);
|
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend);
|
||||||
let ptr =
|
let ptr =
|
||||||
gfx_select!(device => global.buffer_get_mapped_range(buffer, expect.offset, None));
|
gfx_select!(device => global.buffer_get_mapped_range(buffer, expect.offset, None))
|
||||||
|
.unwrap();
|
||||||
let contents = unsafe { slice::from_raw_parts(ptr, expect.data.len()) };
|
let contents = unsafe { slice::from_raw_parts(ptr, expect.data.len()) };
|
||||||
assert_eq!(&expect.data[..], contents);
|
assert_eq!(&expect.data[..], contents);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,8 @@ use crate::{
|
|||||||
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Hub, Input, Token},
|
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Hub, Input, Token},
|
||||||
id, pipeline, resource, span, swap_chain,
|
id, pipeline, resource, span, swap_chain,
|
||||||
track::{BufferState, TextureState, TrackerSet},
|
track::{BufferState, TextureState, TrackerSet},
|
||||||
validation, FastHashMap, LifeGuard, MultiRefCount, PrivateFeatures, Stored, SubmissionIndex,
|
validation::{self, check_buffer_usage, MissingBufferUsageError},
|
||||||
|
FastHashMap, LifeGuard, MultiRefCount, PrivateFeatures, Stored, SubmissionIndex,
|
||||||
MAX_BIND_GROUPS,
|
MAX_BIND_GROUPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,7 +126,6 @@ impl RenderPassContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type BufferMapResult = Result<ptr::NonNull<u8>, hal::device::MapError>;
|
|
||||||
type BufferMapPendingCallback = (resource::BufferMapOperation, resource::BufferMapAsyncStatus);
|
type BufferMapPendingCallback = (resource::BufferMapOperation, resource::BufferMapAsyncStatus);
|
||||||
|
|
||||||
fn map_buffer<B: hal::Backend>(
|
fn map_buffer<B: hal::Backend>(
|
||||||
@ -133,7 +133,7 @@ fn map_buffer<B: hal::Backend>(
|
|||||||
buffer: &mut resource::Buffer<B>,
|
buffer: &mut resource::Buffer<B>,
|
||||||
sub_range: hal::buffer::SubRange,
|
sub_range: hal::buffer::SubRange,
|
||||||
kind: HostMap,
|
kind: HostMap,
|
||||||
) -> BufferMapResult {
|
) -> Result<ptr::NonNull<u8>, BufferMapError> {
|
||||||
let (ptr, segment, needs_sync) = {
|
let (ptr, segment, needs_sync) = {
|
||||||
let segment = hal::memory::Segment {
|
let segment = hal::memory::Segment {
|
||||||
offset: sub_range.offset,
|
offset: sub_range.offset,
|
||||||
@ -783,7 +783,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
buffer_id: id::BufferId,
|
buffer_id: id::BufferId,
|
||||||
offset: BufferAddress,
|
offset: BufferAddress,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) {
|
) -> Result<(), BufferMapError> {
|
||||||
span!(_guard, INFO, "Device::set_buffer_sub_data");
|
span!(_guard, INFO, "Device::set_buffer_sub_data");
|
||||||
|
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
@ -793,11 +793,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
let (mut buffer_guard, _) = hub.buffers.write(&mut token);
|
let (mut buffer_guard, _) = hub.buffers.write(&mut token);
|
||||||
let device = &device_guard[device_id];
|
let device = &device_guard[device_id];
|
||||||
let mut buffer = &mut buffer_guard[buffer_id];
|
let mut buffer = &mut buffer_guard[buffer_id];
|
||||||
assert!(
|
check_buffer_usage(buffer.usage, wgt::BufferUsage::MAP_WRITE)?;
|
||||||
buffer.usage.contains(wgt::BufferUsage::MAP_WRITE),
|
|
||||||
"Buffer usage {:?} must contain usage flag MAP_WRITE",
|
|
||||||
buffer.usage
|
|
||||||
);
|
|
||||||
//assert!(buffer isn't used by the GPU);
|
//assert!(buffer isn't used by the GPU);
|
||||||
|
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
@ -815,7 +811,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
None => (),
|
None => (),
|
||||||
};
|
};
|
||||||
|
|
||||||
match map_buffer(
|
let ptr = map_buffer(
|
||||||
&device.raw,
|
&device.raw,
|
||||||
&mut buffer,
|
&mut buffer,
|
||||||
hal::buffer::SubRange {
|
hal::buffer::SubRange {
|
||||||
@ -823,17 +819,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
size: Some(data.len() as BufferAddress),
|
size: Some(data.len() as BufferAddress),
|
||||||
},
|
},
|
||||||
HostMap::Write,
|
HostMap::Write,
|
||||||
) {
|
)?;
|
||||||
Ok(ptr) => unsafe {
|
|
||||||
ptr::copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), data.len());
|
unsafe {
|
||||||
},
|
ptr::copy_nonoverlapping(data.as_ptr(), ptr.as_ptr(), data.len());
|
||||||
Err(e) => {
|
|
||||||
log::error!("failed to map a buffer: {:?}", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unmap_buffer(&device.raw, buffer);
|
unmap_buffer(&device.raw, buffer);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_get_buffer_sub_data<B: GfxBackend>(
|
pub fn device_get_buffer_sub_data<B: GfxBackend>(
|
||||||
@ -2852,7 +2846,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
buffer_id: id::BufferId,
|
buffer_id: id::BufferId,
|
||||||
range: Range<BufferAddress>,
|
range: Range<BufferAddress>,
|
||||||
op: resource::BufferMapOperation,
|
op: resource::BufferMapOperation,
|
||||||
) {
|
) -> Result<(), BufferMapError> {
|
||||||
span!(_guard, INFO, "Device::buffer_map_async");
|
span!(_guard, INFO, "Device::buffer_map_async");
|
||||||
|
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
@ -2863,26 +2857,24 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
HostMap::Write => (wgt::BufferUsage::MAP_WRITE, resource::BufferUse::MAP_WRITE),
|
HostMap::Write => (wgt::BufferUsage::MAP_WRITE, resource::BufferUse::MAP_WRITE),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(range.start % wgt::COPY_BUFFER_ALIGNMENT, 0);
|
if range.start % wgt::COPY_BUFFER_ALIGNMENT != 0
|
||||||
assert_eq!(range.end % wgt::COPY_BUFFER_ALIGNMENT, 0);
|
|| range.end % wgt::COPY_BUFFER_ALIGNMENT != 0
|
||||||
|
{
|
||||||
|
return Err(BufferMapError::UnalignedRange);
|
||||||
|
}
|
||||||
|
|
||||||
let (device_id, ref_count) = {
|
let (device_id, ref_count) = {
|
||||||
let (mut buffer_guard, _) = hub.buffers.write(&mut token);
|
let (mut buffer_guard, _) = hub.buffers.write(&mut token);
|
||||||
let buffer = &mut buffer_guard[buffer_id];
|
let buffer = &mut buffer_guard[buffer_id];
|
||||||
|
|
||||||
assert!(
|
check_buffer_usage(buffer.usage, pub_usage)?;
|
||||||
buffer.usage.contains(pub_usage),
|
|
||||||
"Buffer usage {:?} must contain usage flag(s) {:?}",
|
|
||||||
buffer.usage,
|
|
||||||
pub_usage
|
|
||||||
);
|
|
||||||
buffer.map_state = match buffer.map_state {
|
buffer.map_state = match buffer.map_state {
|
||||||
resource::BufferMapState::Init { .. } | resource::BufferMapState::Active { .. } => {
|
resource::BufferMapState::Init { .. } | resource::BufferMapState::Active { .. } => {
|
||||||
panic!("Buffer already mapped")
|
return Err(BufferMapError::AlreadyMapped);
|
||||||
}
|
}
|
||||||
resource::BufferMapState::Waiting(_) => {
|
resource::BufferMapState::Waiting(_) => {
|
||||||
op.call_error();
|
op.call_error();
|
||||||
return;
|
return Ok(());
|
||||||
}
|
}
|
||||||
resource::BufferMapState::Idle => {
|
resource::BufferMapState::Idle => {
|
||||||
resource::BufferMapState::Waiting(resource::BufferPendingMapping {
|
resource::BufferMapState::Waiting(resource::BufferPendingMapping {
|
||||||
@ -2908,6 +2900,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
.change_replace(buffer_id, &ref_count, (), internal_use);
|
.change_replace(buffer_id, &ref_count, (), internal_use);
|
||||||
|
|
||||||
device.lock_life(&mut token).map(buffer_id, ref_count);
|
device.lock_life(&mut token).map(buffer_id, ref_count);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_get_mapped_range<B: GfxBackend>(
|
pub fn buffer_get_mapped_range<B: GfxBackend>(
|
||||||
@ -2915,7 +2909,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
buffer_id: id::BufferId,
|
buffer_id: id::BufferId,
|
||||||
offset: BufferAddress,
|
offset: BufferAddress,
|
||||||
_size: Option<BufferSize>,
|
_size: Option<BufferSize>,
|
||||||
) -> *mut u8 {
|
) -> Result<*mut u8, BufferNotMappedError> {
|
||||||
span!(_guard, INFO, "Device::buffer_get_mapped_range");
|
span!(_guard, INFO, "Device::buffer_get_mapped_range");
|
||||||
|
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
@ -2926,16 +2920,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
match buffer.map_state {
|
match buffer.map_state {
|
||||||
resource::BufferMapState::Init { ptr, .. }
|
resource::BufferMapState::Init { ptr, .. }
|
||||||
| resource::BufferMapState::Active { ptr, .. } => unsafe {
|
| resource::BufferMapState::Active { ptr, .. } => unsafe {
|
||||||
ptr.as_ptr().offset(offset as isize)
|
Ok(ptr.as_ptr().offset(offset as isize))
|
||||||
},
|
},
|
||||||
resource::BufferMapState::Idle | resource::BufferMapState::Waiting(_) => {
|
resource::BufferMapState::Idle | resource::BufferMapState::Waiting(_) => {
|
||||||
log::error!("Buffer is not mapped");
|
Err(BufferNotMappedError)
|
||||||
ptr::null_mut()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_unmap<B: GfxBackend>(&self, buffer_id: id::BufferId) {
|
pub fn buffer_unmap<B: GfxBackend>(
|
||||||
|
&self,
|
||||||
|
buffer_id: id::BufferId,
|
||||||
|
) -> Result<(), BufferNotMappedError> {
|
||||||
span!(_guard, INFO, "Device::buffer_unmap");
|
span!(_guard, INFO, "Device::buffer_unmap");
|
||||||
|
|
||||||
let hub = B::hub(self);
|
let hub = B::hub(self);
|
||||||
@ -3005,7 +3001,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
.consume_temp(stage_buffer, stage_memory);
|
.consume_temp(stage_buffer, stage_memory);
|
||||||
}
|
}
|
||||||
resource::BufferMapState::Idle => {
|
resource::BufferMapState::Idle => {
|
||||||
log::error!("Buffer is not mapped");
|
return Err(BufferNotMappedError);
|
||||||
}
|
}
|
||||||
resource::BufferMapState::Waiting(_) => {}
|
resource::BufferMapState::Waiting(_) => {}
|
||||||
resource::BufferMapState::Active {
|
resource::BufferMapState::Active {
|
||||||
@ -3036,6 +3032,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||||||
unmap_buffer(&device.raw, buffer);
|
unmap_buffer(&device.raw, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3057,3 +3054,19 @@ pub enum CreateTextureError {
|
|||||||
)]
|
)]
|
||||||
InvalidMipLevelCount(u32),
|
InvalidMipLevelCount(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Error)]
|
||||||
|
pub enum BufferMapError {
|
||||||
|
#[error(transparent)]
|
||||||
|
MissingBufferUsage(#[from] MissingBufferUsageError),
|
||||||
|
#[error(transparent)]
|
||||||
|
MapError(#[from] hal::device::MapError),
|
||||||
|
#[error("buffer map range is not aligned to {}", wgt::COPY_BUFFER_ALIGNMENT)]
|
||||||
|
UnalignedRange,
|
||||||
|
#[error("buffer is already mapped")]
|
||||||
|
AlreadyMapped,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Error)]
|
||||||
|
#[error("buffer is not mapped")]
|
||||||
|
pub struct BufferNotMappedError;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user