mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-02-16 17:02:32 +00:00
Merge #80
80: Typed mapping of buffers r=kvark a=swiftcoder Add a sprinkling of generics to remove the need for unsafe code to typecast slices resulting from mapping buffers. Co-authored-by: Tristam MacDonald <tristam@trist.am>
This commit is contained in:
commit
2d166d2155
@ -96,10 +96,9 @@ fn main() {
|
||||
encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);
|
||||
|
||||
|
||||
staging_buffer.map_read_async(0, size, |result: wgpu::BufferMapAsyncResult<&[u8]>| {
|
||||
staging_buffer.map_read_async(0, size, |result: wgpu::BufferMapAsyncResult<&[u32]>| {
|
||||
if let wgpu::BufferMapAsyncResult::Success(data) = result {
|
||||
let results = unsafe { ::std::slice::from_raw_parts(data.as_ptr() as *const u32, data.len() / std::mem::size_of::<u32>()) };
|
||||
println!("Times: {:?}", results);
|
||||
println!("Times: {:?}", data);
|
||||
}
|
||||
|
||||
staging_buffer.unmap();
|
||||
|
@ -1,7 +1,7 @@
|
||||
mod framework;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Copy)]
|
||||
struct Vertex {
|
||||
pos: [f32; 4],
|
||||
tex_coord: [f32; 2],
|
||||
@ -123,9 +123,9 @@ impl framework::Example for Example {
|
||||
});
|
||||
|
||||
//vertex_buf.set_sub_data(0, framework::cast_slice(&vertex_data));
|
||||
vertex_buf.map_write_async(0, vertex_buffer_length as u32, |result: wgpu::BufferMapAsyncResult<&mut [u8]>| {
|
||||
vertex_buf.map_write_async(0, vertex_buffer_length as u32, |result: wgpu::BufferMapAsyncResult<&mut [Vertex]>| {
|
||||
if let wgpu::BufferMapAsyncResult::Success(data) = result {
|
||||
unsafe { std::ptr::copy_nonoverlapping(vertex_data.as_ptr() as *const u8, data.as_mut_ptr(), vertex_buffer_length) };
|
||||
data.copy_from_slice(&vertex_data);
|
||||
}
|
||||
|
||||
vertex_buf.unmap();
|
||||
@ -136,9 +136,9 @@ impl framework::Example for Example {
|
||||
usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST | wgpu::BufferUsageFlags::MAP_WRITE,
|
||||
});
|
||||
// index_buf.set_sub_data(0, framework::cast_slice(&index_data));
|
||||
index_buf.map_write_async(0, index_buffer_length as u32, |result: wgpu::BufferMapAsyncResult<&mut [u8]>| {
|
||||
index_buf.map_write_async(0, index_buffer_length as u32, |result: wgpu::BufferMapAsyncResult<&mut [u16]>| {
|
||||
if let wgpu::BufferMapAsyncResult::Success(data) = result {
|
||||
unsafe { std::ptr::copy_nonoverlapping(index_data.as_ptr() as *const u8, data.as_mut_ptr(), index_buffer_length) };
|
||||
data.copy_from_slice(&index_data);
|
||||
}
|
||||
|
||||
index_buf.unmap();
|
||||
@ -191,7 +191,7 @@ impl framework::Example for Example {
|
||||
// temp_buf.set_sub_data(0, &texels);
|
||||
temp_buf.map_write_async(0, texels.len() as u32, |result: wgpu::BufferMapAsyncResult<&mut [u8]>| {
|
||||
if let wgpu::BufferMapAsyncResult::Success(data) = result {
|
||||
unsafe { std::ptr::copy_nonoverlapping(texels.as_ptr() as *const u8, data.as_mut_ptr(), texels.len()) };
|
||||
data.copy_from_slice(&texels);
|
||||
}
|
||||
|
||||
temp_buf.unmap();
|
||||
@ -237,9 +237,9 @@ impl framework::Example for Example {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
// uniform_buf.set_sub_data(0, framework::cast_slice(&mx_ref[..]));
|
||||
uniform_buf.map_write_async(0, 64, |result: wgpu::BufferMapAsyncResult<&mut [u8]>| {
|
||||
uniform_buf.map_write_async(0, 64, |result: wgpu::BufferMapAsyncResult<&mut [f32]>| {
|
||||
if let wgpu::BufferMapAsyncResult::Success(data) = result {
|
||||
unsafe { std::ptr::copy_nonoverlapping(mx_ref.as_ptr() as *const u8, data.as_mut_ptr(), 64) };
|
||||
data.copy_from_slice(mx_ref);
|
||||
}
|
||||
|
||||
uniform_buf.unmap();
|
||||
@ -343,9 +343,9 @@ impl framework::Example for Example {
|
||||
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
|
||||
let mx_ref: &[f32; 16] = mx_total.as_ref();
|
||||
// self.uniform_buf.set_sub_data(0, framework::cast_slice(&mx_ref[..]));
|
||||
self.uniform_buf.map_write_async(0, 64, |result: wgpu::BufferMapAsyncResult<&mut [u8]>| {
|
||||
self.uniform_buf.map_write_async(0, 64, |result: wgpu::BufferMapAsyncResult<&mut [f32]>| {
|
||||
if let wgpu::BufferMapAsyncResult::Success(data) = result {
|
||||
unsafe { std::ptr::copy_nonoverlapping(mx_ref.as_ptr() as *const u8, data.as_mut_ptr(), 64) };
|
||||
data.copy_from_slice(mx_ref);
|
||||
}
|
||||
|
||||
self.uniform_buf.unmap();
|
||||
|
@ -465,14 +465,18 @@ pub enum BufferMapAsyncResult<T> {
|
||||
Error,
|
||||
}
|
||||
|
||||
struct BufferMapReadAsyncUserData<F: FnOnce(BufferMapAsyncResult<&[u8]>)> {
|
||||
struct BufferMapReadAsyncUserData<T,F>
|
||||
where F: FnOnce(BufferMapAsyncResult<&[T]>) {
|
||||
size: u32,
|
||||
callback: F,
|
||||
phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
struct BufferMapWriteAsyncUserData<F: FnOnce(BufferMapAsyncResult<&mut [u8]>)> {
|
||||
struct BufferMapWriteAsyncUserData<T, F>
|
||||
where F: FnOnce(BufferMapAsyncResult<&mut [T]>) {
|
||||
size: u32,
|
||||
callback: F,
|
||||
phantom: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
@ -480,38 +484,46 @@ impl Buffer {
|
||||
wgn::wgpu_buffer_set_sub_data(self.id, offset, data.len() as u32, data.as_ptr());
|
||||
}
|
||||
|
||||
pub fn map_read_async<F>(&self, start: u32, size: u32, callback: F)
|
||||
where F: FnOnce(BufferMapAsyncResult<&[u8]>) {
|
||||
extern "C" fn buffer_map_read_callback_wrapper<F>(status: wgn::BufferMapAsyncStatus, data: *const u8, userdata: *mut u8)
|
||||
where F: FnOnce(BufferMapAsyncResult<&[u8]>) {
|
||||
let userdata = unsafe { Box::from_raw(userdata as *mut BufferMapReadAsyncUserData<F>) };
|
||||
let data = unsafe { slice::from_raw_parts(data, userdata.size as usize) };
|
||||
pub fn map_read_async<T, F>(&self, start: u32, size: u32, callback: F)
|
||||
where T: 'static + Copy, F: FnOnce(BufferMapAsyncResult<&[T]>) {
|
||||
let type_size = std::mem::size_of::<T>() as u32;
|
||||
assert_ne!(type_size, 0);
|
||||
assert_eq!(size % type_size, 0);
|
||||
|
||||
extern "C" fn buffer_map_read_callback_wrapper<T, F>(status: wgn::BufferMapAsyncStatus, data: *const u8, userdata: *mut u8)
|
||||
where F: FnOnce(BufferMapAsyncResult<&[T]>) {
|
||||
let userdata = unsafe { Box::from_raw(userdata as *mut BufferMapReadAsyncUserData<T, F>) };
|
||||
let data = unsafe { slice::from_raw_parts(data as *const T, userdata.size as usize / std::mem::size_of::<T>()) };
|
||||
if let wgn::BufferMapAsyncStatus::Success = status {
|
||||
(userdata.callback)(BufferMapAsyncResult::Success(data));
|
||||
(userdata.callback)(BufferMapAsyncResult::Success::<&[T]>(data));
|
||||
} else {
|
||||
(userdata.callback)(BufferMapAsyncResult::Error);
|
||||
}
|
||||
}
|
||||
|
||||
let userdata = Box::new(BufferMapReadAsyncUserData{size, callback});
|
||||
wgn::wgpu_buffer_map_read_async(self.id, start, size, buffer_map_read_callback_wrapper::<F>, Box::into_raw(userdata) as *mut u8);
|
||||
let userdata = Box::new(BufferMapReadAsyncUserData{size, callback, phantom: std::marker::PhantomData});
|
||||
wgn::wgpu_buffer_map_read_async(self.id, start, size, buffer_map_read_callback_wrapper::<T, F>, Box::into_raw(userdata) as *mut u8);
|
||||
}
|
||||
|
||||
pub fn map_write_async<F>(&self, start: u32, size: u32, callback: F)
|
||||
where F: FnOnce(BufferMapAsyncResult<&mut [u8]>) {
|
||||
extern "C" fn buffer_map_write_callback_wrapper<F>(status: wgn::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8)
|
||||
where F: FnOnce(BufferMapAsyncResult<&mut [u8]>) {
|
||||
let userdata = unsafe { Box::from_raw(userdata as *mut BufferMapWriteAsyncUserData<F>) };
|
||||
let data = unsafe { slice::from_raw_parts_mut(data, userdata.size as usize) };
|
||||
pub fn map_write_async<T, F>(&self, start: u32, size: u32, callback: F)
|
||||
where T: 'static + Copy, F: FnOnce(BufferMapAsyncResult<&mut [T]>) {
|
||||
let type_size = std::mem::size_of::<T>() as u32;
|
||||
assert_ne!(type_size, 0);
|
||||
assert_eq!(size % type_size, 0);
|
||||
|
||||
extern "C" fn buffer_map_write_callback_wrapper<T, F>(status: wgn::BufferMapAsyncStatus, data: *mut u8, userdata: *mut u8)
|
||||
where F: FnOnce(BufferMapAsyncResult<&mut [T]>) {
|
||||
let userdata = unsafe { Box::from_raw(userdata as *mut BufferMapWriteAsyncUserData<T, F>) };
|
||||
let data = unsafe { slice::from_raw_parts_mut(data as *mut T, userdata.size as usize / std::mem::size_of::<T>()) };
|
||||
if let wgn::BufferMapAsyncStatus::Success = status {
|
||||
(userdata.callback)(BufferMapAsyncResult::Success(data));
|
||||
(userdata.callback)(BufferMapAsyncResult::Success::<&mut [T]>(data));
|
||||
} else {
|
||||
(userdata.callback)(BufferMapAsyncResult::Error);
|
||||
}
|
||||
}
|
||||
|
||||
let userdata = Box::new(BufferMapWriteAsyncUserData{size, callback});
|
||||
wgn::wgpu_buffer_map_write_async(self.id, start, size, buffer_map_write_callback_wrapper::<F>, Box::into_raw(userdata) as *mut u8);
|
||||
let userdata = Box::new(BufferMapWriteAsyncUserData{size, callback, phantom: std::marker::PhantomData});
|
||||
wgn::wgpu_buffer_map_write_async(self.id, start, size, buffer_map_write_callback_wrapper::<T, F>, Box::into_raw(userdata) as *mut u8);
|
||||
}
|
||||
|
||||
pub fn unmap(&self) {
|
||||
|
Loading…
Reference in New Issue
Block a user