mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[rs] Use u8 slices for buffer mapping
This commit is contained in:
@@ -37,7 +37,6 @@ rev = "73b33ea76e2f91b3114aa7640b1d60518d39f915"
|
||||
[dependencies]
|
||||
arrayvec = "0.5"
|
||||
raw-window-handle = "0.3"
|
||||
zerocopy = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
cgmath = "0.17"
|
||||
@@ -46,3 +45,4 @@ glsl-to-spirv = "0.1"
|
||||
log = "0.4"
|
||||
png = "0.15"
|
||||
winit = "0.20.0-alpha4"
|
||||
zerocopy = "0.2"
|
||||
|
||||
117
wgpu/src/lib.rs
117
wgpu/src/lib.rs
@@ -1,9 +1,7 @@
|
||||
//! A cross-platform graphics and compute library based on WebGPU.
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use zerocopy::{AsBytes, FromBytes, LayoutVerified};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CString;
|
||||
use std::ops::Range;
|
||||
use std::ptr;
|
||||
@@ -493,27 +491,12 @@ impl<'a> TextureCopyView<'a> {
|
||||
}
|
||||
|
||||
/// A buffer being created, mapped in host memory.
|
||||
pub struct CreateBufferMapped<'a, T> {
|
||||
pub struct CreateBufferMapped<'a> {
|
||||
id: wgc::id::BufferId,
|
||||
pub data: &'a mut [T],
|
||||
pub data: &'a mut [u8],
|
||||
}
|
||||
|
||||
impl<'a, T> CreateBufferMapped<'a, T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Copies a slice into the mapped buffer and unmaps it, returning a [`Buffer`].
|
||||
///
|
||||
/// `slice` and `self.data` must have the same length.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the slices have different lengths.
|
||||
pub fn fill_from_slice(self, slice: &[T]) -> Buffer {
|
||||
self.data.copy_from_slice(slice);
|
||||
self.finish()
|
||||
}
|
||||
|
||||
impl CreateBufferMapped<'_> {
|
||||
/// Unmaps the buffer from host memory and returns a [`Buffer`].
|
||||
pub fn finish(self) -> Buffer {
|
||||
wgn::wgpu_buffer_unmap(self.id);
|
||||
@@ -813,32 +796,32 @@ impl Device {
|
||||
|
||||
/// Creates a new buffer and maps it into host-visible memory.
|
||||
///
|
||||
/// This returns a [`CreateBufferMapped<T>`], which exposes a `&mut [T]`. The actual [`Buffer`]
|
||||
/// This returns a [`CreateBufferMapped`], which exposes a `&mut [u8]`. The actual [`Buffer`]
|
||||
/// will not be created until calling [`CreateBufferMapped::finish`].
|
||||
pub fn create_buffer_mapped<'a, T>(
|
||||
&'a self,
|
||||
count: usize,
|
||||
usage: BufferUsage,
|
||||
) -> CreateBufferMapped<'a, T>
|
||||
where
|
||||
T: 'static + Copy + AsBytes + FromBytes,
|
||||
{
|
||||
let type_size = std::mem::size_of::<T>() as BufferAddress;
|
||||
assert_ne!(type_size, 0);
|
||||
pub fn create_buffer_mapped(&self, size: usize, usage: BufferUsage) -> CreateBufferMapped<'_> {
|
||||
assert_ne!(size, 0);
|
||||
|
||||
let desc = BufferDescriptor {
|
||||
size: (type_size * count as BufferAddress).max(1),
|
||||
size: size as BufferAddress,
|
||||
usage,
|
||||
};
|
||||
let mut ptr: *mut u8 = std::ptr::null_mut();
|
||||
|
||||
let id = wgn::wgpu_device_create_buffer_mapped(self.id, &desc, &mut ptr as *mut *mut u8);
|
||||
|
||||
let data = unsafe { std::slice::from_raw_parts_mut(ptr as *mut T, count) };
|
||||
let data = unsafe { std::slice::from_raw_parts_mut(ptr as *mut u8, size) };
|
||||
|
||||
CreateBufferMapped { id, data }
|
||||
}
|
||||
|
||||
/// Creates a new buffer, maps it into host-visible memory, copies data from the given slice,
|
||||
/// and finally unmaps it, returning a [`Buffer`].
|
||||
pub fn create_buffer_with_data(&self, data: &[u8], usage: BufferUsage) -> Buffer {
|
||||
let mapped = self.create_buffer_mapped(data.len(), usage);
|
||||
mapped.data.copy_from_slice(data);
|
||||
mapped.finish()
|
||||
}
|
||||
|
||||
/// Creates a new [`Texture`].
|
||||
///
|
||||
/// `desc` specifies the general format of the texture.
|
||||
@@ -888,50 +871,39 @@ impl<T> Drop for BufferAsyncMapping<T> {
|
||||
}
|
||||
}
|
||||
|
||||
struct BufferMapReadAsyncUserData<T, F>
|
||||
struct BufferMapReadAsyncUserData<F>
|
||||
where
|
||||
T: FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&[T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&[u8]>),
|
||||
{
|
||||
size: BufferAddress,
|
||||
size: usize,
|
||||
callback: F,
|
||||
buffer_id: wgc::id::BufferId,
|
||||
phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
struct BufferMapWriteAsyncUserData<T, F>
|
||||
struct BufferMapWriteAsyncUserData<F>
|
||||
where
|
||||
T: AsBytes + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [u8]>),
|
||||
{
|
||||
size: BufferAddress,
|
||||
size: usize,
|
||||
callback: F,
|
||||
buffer_id: wgc::id::BufferId,
|
||||
phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn map_read_async<T, F>(&self, start: BufferAddress, count: usize, callback: F)
|
||||
pub fn map_read_async<F>(&self, start: BufferAddress, size: usize, callback: F)
|
||||
where
|
||||
T: 'static + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&[T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&[u8]>),
|
||||
{
|
||||
extern "C" fn buffer_map_read_callback_wrapper<T, F>(
|
||||
extern "C" fn buffer_map_read_callback_wrapper<F>(
|
||||
status: BufferMapAsyncStatus,
|
||||
data: *const u8,
|
||||
user_data: *mut u8,
|
||||
) where
|
||||
T: FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&[T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&[u8]>),
|
||||
{
|
||||
let user_data =
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapReadAsyncUserData<T, F>) };
|
||||
let data: &[u8] = unsafe {
|
||||
slice::from_raw_parts(data as *const u8, usize::try_from(user_data.size).unwrap())
|
||||
};
|
||||
let data = LayoutVerified::new_slice(data)
|
||||
.expect("could not interpret bytes as &[T]")
|
||||
.into_slice();
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapReadAsyncUserData<F>) };
|
||||
let data: &[u8] = unsafe { slice::from_raw_parts(data as *const u8, user_data.size) };
|
||||
match status {
|
||||
BufferMapAsyncStatus::Success => (user_data.callback)(Ok(BufferAsyncMapping {
|
||||
data,
|
||||
@@ -941,44 +913,34 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
let size = (count * std::mem::size_of::<T>()) as BufferAddress;
|
||||
|
||||
let user_data = Box::new(BufferMapReadAsyncUserData {
|
||||
size,
|
||||
callback,
|
||||
buffer_id: self.id,
|
||||
phantom: std::marker::PhantomData,
|
||||
});
|
||||
wgn::wgpu_buffer_map_read_async(
|
||||
self.id,
|
||||
start,
|
||||
size,
|
||||
buffer_map_read_callback_wrapper::<T, F>,
|
||||
size as BufferAddress,
|
||||
buffer_map_read_callback_wrapper::<F>,
|
||||
Box::into_raw(user_data) as *mut u8,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn map_write_async<T, F>(&self, start: BufferAddress, count: usize, callback: F)
|
||||
pub fn map_write_async<F>(&self, start: BufferAddress, size: usize, callback: F)
|
||||
where
|
||||
T: 'static + AsBytes + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [u8]>),
|
||||
{
|
||||
extern "C" fn buffer_map_write_callback_wrapper<T, F>(
|
||||
extern "C" fn buffer_map_write_callback_wrapper<F>(
|
||||
status: BufferMapAsyncStatus,
|
||||
data: *mut u8,
|
||||
user_data: *mut u8,
|
||||
) where
|
||||
T: AsBytes + FromBytes,
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [T]>),
|
||||
F: FnOnce(BufferMapAsyncResult<&mut [u8]>),
|
||||
{
|
||||
let user_data =
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapWriteAsyncUserData<T, F>) };
|
||||
let data = unsafe {
|
||||
slice::from_raw_parts_mut(data as *mut u8, usize::try_from(user_data.size).unwrap())
|
||||
};
|
||||
let data = LayoutVerified::new_slice(data)
|
||||
.expect("could not interpret bytes as &mut [T]")
|
||||
.into_mut_slice();
|
||||
unsafe { Box::from_raw(user_data as *mut BufferMapWriteAsyncUserData<F>) };
|
||||
let data = unsafe { slice::from_raw_parts_mut(data as *mut u8, user_data.size) };
|
||||
match status {
|
||||
BufferMapAsyncStatus::Success => (user_data.callback)(Ok(BufferAsyncMapping {
|
||||
data,
|
||||
@@ -988,19 +950,16 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
let size = (count * std::mem::size_of::<T>()) as BufferAddress;
|
||||
|
||||
let user_data = Box::new(BufferMapWriteAsyncUserData {
|
||||
size,
|
||||
callback,
|
||||
buffer_id: self.id,
|
||||
phantom: std::marker::PhantomData,
|
||||
});
|
||||
wgn::wgpu_buffer_map_write_async(
|
||||
self.id,
|
||||
start,
|
||||
size,
|
||||
buffer_map_write_callback_wrapper::<T, F>,
|
||||
size as BufferAddress,
|
||||
buffer_map_write_callback_wrapper::<F>,
|
||||
Box::into_raw(user_data) as *mut u8,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user