Convert shadow sample to map_async

This commit is contained in:
Tristam MacDonald 2019-03-01 20:58:28 -08:00
parent 1faba3c265
commit 6ef53d7705
8 changed files with 359 additions and 329 deletions

1
.gitignore vendored
View File

@ -2,4 +2,5 @@
**/*.rs.bk
#Cargo.lock
.vscode
.vs
build

364
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,14 +4,6 @@ extern crate wgpu_native;
use std::str::FromStr;
// TODO: deduplicate this with the copy in gfx-examples/framework
pub fn cast_slice<T>(data: &[T]) -> &[u8] {
use std::mem::size_of;
use std::slice::from_raw_parts;
unsafe { from_raw_parts(data.as_ptr() as *const u8, data.len() * size_of::<T>()) }
}
fn main() {
env_logger::init();
@ -39,16 +31,17 @@ fn main() {
let cs_bytes = include_bytes!("./../data/collatz.comp.spv");
let cs_module = device.create_shader_module(cs_bytes);
let staging_buffer = device.create_buffer(&wgpu::BufferDescriptor {
size,
usage: wgpu::BufferUsageFlags::MAP_READ
| wgpu::BufferUsageFlags::TRANSFER_DST
| wgpu::BufferUsageFlags::TRANSFER_SRC,
});
staging_buffer.set_sub_data(0, cast_slice(&numbers));
let staging_buffer = device
.create_buffer_mapped(
numbers.len(),
wgpu::BufferUsageFlags::MAP_READ
| wgpu::BufferUsageFlags::TRANSFER_DST
| wgpu::BufferUsageFlags::TRANSFER_SRC,
)
.fill_from_slice(&numbers);
let storage_buffer = device.create_buffer(&wgpu::BufferDescriptor {
size: (numbers.len() * std::mem::size_of::<u32>()) as u32,
size,
usage: wgpu::BufferUsageFlags::STORAGE
| wgpu::BufferUsageFlags::TRANSFER_DST
| wgpu::BufferUsageFlags::TRANSFER_SRC,
@ -68,7 +61,7 @@ fn main() {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &storage_buffer,
range: 0..(numbers.len() as u32),
range: 0..size,
},
}],
});
@ -95,7 +88,6 @@ fn main() {
}
encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);
staging_buffer.map_read_async(0, size, |result: wgpu::BufferMapAsyncResult<&[u32]>| {
if let wgpu::BufferMapAsyncResult::Success(data) = result {
println!("Times: {:?}", data);

View File

@ -3,14 +3,14 @@ mod framework;
#[derive(Clone, Copy)]
struct Vertex {
pos: [f32; 4],
tex_coord: [f32; 2],
_pos: [f32; 4],
_tex_coord: [f32; 2],
}
fn vertex(pos: [i8; 3], tc: [i8; 2]) -> Vertex {
Vertex {
pos: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0],
tex_coord: [tc[0] as f32, tc[1] as f32],
_pos: [pos[0] as f32, pos[1] as f32, pos[2] as f32, 1.0],
_tex_coord: [tc[0] as f32, tc[1] as f32],
}
}
@ -115,27 +115,13 @@ impl framework::Example for Example {
// Create the vertex and index buffers
let vertex_size = mem::size_of::<Vertex>();
let (vertex_data, index_data) = create_vertices();
let vertex_buffer_length = vertex_data.len() * vertex_size;
let index_buffer_length = index_data.len() * mem::size_of::<u16>();
let vertex_buf = {
let (vertex_buf, vertex_buf_data) = device.create_buffer_mapped(&wgpu::BufferDescriptor {
size: vertex_buffer_length as u32,
usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST | wgpu::BufferUsageFlags::MAP_WRITE,
});
vertex_buf_data.copy_from_slice(&vertex_data);
vertex_buf.unmap();
vertex_buf
};
let vertex_buf =
device.create_buffer_mapped(vertex_data.len(), wgpu::BufferUsageFlags::VERTEX)
.fill_from_slice(&vertex_data);
let index_buf = {
let (index_buf, index_buf_data) = device.create_buffer_mapped(&wgpu::BufferDescriptor {
size: index_buffer_length as u32,
usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST | wgpu::BufferUsageFlags::MAP_WRITE,
});
index_buf_data.copy_from_slice(&index_data);
index_buf.unmap();
index_buf
};
let index_buf =
device.create_buffer_mapped(index_data.len(), wgpu::BufferUsageFlags::INDEX)
.fill_from_slice(&index_data);
// Create pipeline layout
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
@ -177,15 +163,9 @@ impl framework::Example for Example {
usage: wgpu::TextureUsageFlags::SAMPLED | wgpu::TextureUsageFlags::TRANSFER_DST,
});
let texture_view = texture.create_default_view();
let temp_buf = {
let (temp_buf, temp_buf_data) = device.create_buffer_mapped(&wgpu::BufferDescriptor {
size: texels.len() as u32,
usage: wgpu::BufferUsageFlags::TRANSFER_SRC | wgpu::BufferUsageFlags::TRANSFER_DST | wgpu::BufferUsageFlags::MAP_WRITE,
});
temp_buf_data.copy_from_slice(&texels);
temp_buf.unmap();
temp_buf
};
let temp_buf =
device.create_buffer_mapped(texels.len(), wgpu::BufferUsageFlags::TRANSFER_SRC)
.fill_from_slice(&texels);
init_encoder.copy_buffer_to_texture(
wgpu::BufferCopyView {
buffer: &temp_buf,
@ -222,15 +202,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();
let uniform_buf = {
let (uniform_buf, uniform_buf_data) = device.create_buffer_mapped(&wgpu::BufferDescriptor {
size: 64,
usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST | wgpu::BufferUsageFlags::MAP_WRITE,
});
uniform_buf_data.copy_from_slice(mx_ref);
uniform_buf.unmap();
uniform_buf
};
let uniform_buf =
device.create_buffer_mapped(16, wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST)
.fill_from_slice(mx_ref);
// Create bind group
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
@ -326,17 +300,17 @@ impl framework::Example for Example {
//empty
}
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, _device: &mut wgpu::Device) {
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) {
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 [f32]>| {
if let wgpu::BufferMapAsyncResult::Success(data) = result {
data.copy_from_slice(mx_ref);
}
self.uniform_buf.unmap();
});
let temp_buf =
device.create_buffer_mapped(16, wgpu::BufferUsageFlags::TRANSFER_SRC)
.fill_from_slice(mx_ref);
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.uniform_buf, 0, 64);
device.get_queue().submit(&[encoder.finish()]);
}
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {

View File

@ -5,16 +5,16 @@ use std::rc::Rc;
mod framework;
#[derive(Clone)]
#[derive(Clone, Copy)]
struct Vertex {
pos: [i8; 4],
normal: [i8; 4],
_pos: [i8; 4],
_normal: [i8; 4],
}
fn vertex(pos: [i8; 3], nor: [i8; 3]) -> Vertex {
Vertex {
pos: [pos[0], pos[1], pos[2], 1],
normal: [nor[0], nor[1], nor[2], 0],
_pos: [pos[0], pos[1], pos[2], 1],
_normal: [nor[0], nor[1], nor[2], 0],
}
}
@ -101,6 +101,7 @@ struct Light {
}
#[repr(C)]
#[derive(Clone, Copy)]
struct LightRaw {
proj: [[f32; 4]; 4],
pos: [f32; 4],
@ -132,14 +133,16 @@ impl Light {
}
#[repr(C)]
#[derive(Clone, Copy)]
struct ForwardUniforms {
proj: [[f32; 4]; 4],
num_lights: [u32; 4],
}
#[repr(C)]
#[derive(Clone, Copy)]
struct EntityUniforms {
model: [[f32; 4]; 4],
model: cgmath::Matrix4<f32>,
color: [f32; 4],
}
@ -190,28 +193,25 @@ impl framework::Example for Example {
// Create the vertex and index buffers
let vertex_size = mem::size_of::<Vertex>();
let (cube_vertex_data, cube_index_data) = create_cube();
let cube_vertex_buf = Rc::new(device.create_buffer(&wgpu::BufferDescriptor {
size: (cube_vertex_data.len() * vertex_size) as u32,
usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST,
}));
cube_vertex_buf.set_sub_data(0, framework::cast_slice(&cube_vertex_data));
let cube_index_buf = Rc::new(device.create_buffer(&wgpu::BufferDescriptor {
size: (cube_index_data.len() * 2) as u32,
usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST,
}));
cube_index_buf.set_sub_data(0, framework::cast_slice(&cube_index_data));
let cube_vertex_buf = Rc::new(
device.create_buffer_mapped(cube_vertex_data.len(), wgpu::BufferUsageFlags::VERTEX)
.fill_from_slice(&cube_vertex_data)
);
let cube_index_buf = Rc::new(
device.create_buffer_mapped(cube_index_data.len(), wgpu::BufferUsageFlags::INDEX)
.fill_from_slice(&cube_index_data)
);
let (plane_vertex_data, plane_index_data) = create_plane(7);
let plane_vertex_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: (plane_vertex_data.len() * vertex_size) as u32,
usage: wgpu::BufferUsageFlags::VERTEX | wgpu::BufferUsageFlags::TRANSFER_DST,
});
plane_vertex_buf.set_sub_data(0, framework::cast_slice(&plane_vertex_data));
let plane_index_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: (plane_index_data.len() * 2) as u32,
usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST,
});
plane_index_buf.set_sub_data(0, framework::cast_slice(&plane_index_data));
let plane_vertex_buf =
device.create_buffer_mapped(plane_vertex_data.len(), wgpu::BufferUsageFlags::VERTEX)
.fill_from_slice(&plane_vertex_data);
let plane_index_buf =
device.create_buffer_mapped(plane_index_data.len(), wgpu::BufferUsageFlags::INDEX)
.fill_from_slice(&plane_index_data);
let entity_uniform_size = mem::size_of::<EntityUniforms>() as u32;
let plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: entity_uniform_size,
@ -517,17 +517,15 @@ impl framework::Example for Example {
],
});
let uniform_size = mem::size_of::<ForwardUniforms>() as u32;
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: uniform_size,
usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST,
});
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
let data = ForwardUniforms {
let forward_uniforms = ForwardUniforms {
proj: *mx_total.as_ref(),
num_lights: [lights.len() as u32, 0, 0, 0],
};
uniform_buf.set_sub_data(0, framework::cast_slice(&[data]));
let uniform_size = mem::size_of::<ForwardUniforms>() as u32;
let uniform_buf =
device.create_buffer_mapped(1, wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST)
.fill_from_slice(&[forward_uniforms]);
// Create bind group
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
@ -639,9 +637,17 @@ impl framework::Example for Example {
}
fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) {
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.forward_pass.uniform_buf.set_sub_data(0, framework::cast_slice(&mx_ref[..]));
{
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();
let temp_buf =
device.create_buffer_mapped(16, wgpu::BufferUsageFlags::TRANSFER_SRC)
.fill_from_slice(mx_ref);
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
encoder.copy_buffer_to_buffer(&temp_buf, 0, &self.forward_pass.uniform_buf, 0, 64);
device.get_queue().submit(&[encoder.finish()]);
}
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d {
@ -658,28 +664,42 @@ impl framework::Example for Example {
}
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {
for entity in &mut self.entities {
if entity.rotation_speed != 0.0 {
let rotation = cgmath::Matrix4::from_angle_x(cgmath::Deg(entity.rotation_speed));
entity.mx_world = entity.mx_world * rotation;
}
let data = EntityUniforms {
model: *entity.mx_world.as_ref(),
color: [entity.color.r, entity.color.g, entity.color.b, entity.color.a],
};
entity.uniform_buf.set_sub_data(0, framework::cast_slice(&[data]));
}
if self.lights_are_dirty {
self.lights_are_dirty = false;
let raw = self.lights
.iter()
.map(|light| light.to_raw())
.collect::<Vec<_>>();
self.light_uniform_buf.set_sub_data(0, framework::cast_slice(&raw));
}
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
{
let size = mem::size_of::<EntityUniforms>() as u32;
let temp_buf_data =
device.create_buffer_mapped(self.entities.len(), wgpu::BufferUsageFlags::TRANSFER_SRC);
for (i, entity) in self.entities.iter_mut().enumerate() {
if entity.rotation_speed != 0.0 {
let rotation = cgmath::Matrix4::from_angle_x(cgmath::Deg(entity.rotation_speed));
entity.mx_world = entity.mx_world * rotation;
}
temp_buf_data.data[i] = EntityUniforms {
model: entity.mx_world.clone(),
color: [entity.color.r, entity.color.g, entity.color.b, entity.color.a],
};
}
let temp_buf = temp_buf_data.finish();
for (i, entity) in self.entities.iter().enumerate() {
encoder.copy_buffer_to_buffer(&temp_buf, i as u32 * size, &entity.uniform_buf, 0, size);
}
}
if self.lights_are_dirty {
self.lights_are_dirty = false;
let size = (self.lights.len() * mem::size_of::<LightRaw>()) as u32;
let temp_buf_data =
device.create_buffer_mapped(self.lights.len(), wgpu::BufferUsageFlags::TRANSFER_SRC);
for (i, light) in self.lights.iter().enumerate() {
temp_buf_data.data[i] = light.to_raw();
}
encoder.copy_buffer_to_buffer(&temp_buf_data.finish(), 0, &self.light_uniform_buf, 0, size);
}
for (i, light) in self.lights.iter().enumerate() {
// The light uniform buffer already has the projection,
// let's just copy it over to the shadow uniform buffer.

View File

@ -277,27 +277,25 @@ impl DestroyedResources<back::Backend> {
let mut operation = None;
let (result, ptr) = {
let mut buffer_guard = HUB.buffers.write();
let buffer = &mut buffer_guard[buffer_id];
let mut buffer = &mut buffer_guard[buffer_id];
std::mem::swap(&mut operation, &mut buffer.pending_map_operation);
match operation.clone().unwrap() {
BufferMapOperation::Read(range, ..) => {
if let Ok(ptr) = unsafe { raw.map_memory(&buffer.memory, range.clone()) } {
if !buffer.memory_properties.contains(hal::memory::Properties::COHERENT) {
unsafe { raw.invalidate_mapped_memory_ranges(iter::once((&buffer.memory, range.clone()))).unwrap() }; // TODO
match map_buffer(raw, &mut buffer, range.clone(), true, false) {
Ok(ptr) => (BufferMapAsyncStatus::Success, Some(ptr)),
Err(e) => {
log::error!("failed to map buffer for reading: {}", e);
(BufferMapAsyncStatus::Error, None)
}
(BufferMapAsyncStatus::Success, Some(ptr))
} else {
(BufferMapAsyncStatus::Error, None)
}
},
BufferMapOperation::Write(range, ..) => {
if let Ok(ptr) = unsafe { raw.map_memory(&buffer.memory, range.clone()) } {
if !buffer.memory_properties.contains(hal::memory::Properties::COHERENT) {
buffer.mapped_write_ranges.push(range.clone());
match map_buffer(raw, &mut buffer, range.clone(), false, true) {
Ok(ptr) => (BufferMapAsyncStatus::Success, Some(ptr)),
Err(e) => {
log::error!("failed to map buffer for writing: {}", e);
(BufferMapAsyncStatus::Error, None)
}
(BufferMapAsyncStatus::Success, Some(ptr))
} else {
(BufferMapAsyncStatus::Error, None)
}
},
}
@ -311,6 +309,23 @@ impl DestroyedResources<back::Backend> {
}
}
fn map_buffer(
raw: &<back::Backend as hal::Backend>::Device,
buffer: &mut resource::Buffer<back::Backend>,
range: std::ops::Range<u64>,
read: bool,
write: bool,
) -> Result<*mut u8, hal::mapping::Error> {
let pointer = unsafe { raw.map_memory(&buffer.memory, range.clone()) }?;
if read && !buffer.memory_properties.contains(hal::memory::Properties::COHERENT) {
unsafe { raw.invalidate_mapped_memory_ranges(iter::once((&buffer.memory, range.clone()))).unwrap() }; // TODO
}
if write && !buffer.memory_properties.contains(hal::memory::Properties::COHERENT) {
buffer.mapped_write_ranges.push(range.clone());
}
Ok(pointer)
}
pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device,
adapter_id: AdapterId,
@ -502,19 +517,24 @@ pub extern "C" fn wgpu_device_create_buffer_mapped(
desc: &resource::BufferDescriptor,
mapped_ptr_out: *mut *mut u8
) -> BufferId {
let buffer = device_create_buffer(device_id, desc);
let mut desc = desc.clone();
desc.usage |= resource::BufferUsageFlags::MAP_WRITE;
let mut buffer = device_create_buffer(device_id, &desc);
let device_guard = HUB.devices.read();
let device = &device_guard[device_id];
if let Ok(ptr) = unsafe { device.raw.map_memory(&buffer.memory, 0..(desc.size as u64)) } {
unsafe{ *mapped_ptr_out = ptr; }
match map_buffer(&device.raw, &mut buffer, 0..(desc.size as u64), false, true) {
Ok(ptr) => unsafe { *mapped_ptr_out = ptr; }
Err(e) => {
log::error!("failed to create buffer in a mapped state: {}", e);
unsafe { *mapped_ptr_out = std::ptr::null_mut(); }
}
}
let ref_count = buffer.life_guard.ref_count.clone();
let id = HUB.buffers.register_local(buffer);
device_track_buffer(device_id, id, ref_count, resource::BufferUsageFlags::MAP_WRITE);
id
}

View File

@ -28,6 +28,7 @@ bitflags! {
}
#[repr(C)]
#[derive(Clone)]
pub struct BufferDescriptor {
pub size: u32,
pub usage: BufferUsageFlags,

View File

@ -233,6 +233,25 @@ impl<'a> TextureCopyView<'a> {
}
}
pub struct CreateBufferMapped<'a, T> {
id: wgn::BufferId,
pub data: &'a mut [T],
}
impl<'a, T> CreateBufferMapped<'a, T>
where T: Copy {
pub fn fill_from_slice(self, slice: &[T]) -> Buffer {
self.data.copy_from_slice(slice);
self.finish()
}
pub fn finish(self) -> Buffer {
wgn::wgpu_buffer_unmap(self.id);
Buffer {
id: self.id,
}
}
}
impl Instance {
pub fn new() -> Self {
@ -432,21 +451,22 @@ impl Device {
}
}
pub fn create_buffer_mapped<T>(&self, desc: &BufferDescriptor) -> (Buffer, &mut [T])
pub fn create_buffer_mapped<'a, T>(&self, count: usize, usage: BufferUsageFlags) -> CreateBufferMapped<'a, T>
where T: 'static + Copy {
let type_size = std::mem::size_of::<T>() as u32;
assert_ne!(type_size, 0);
assert_eq!(desc.size % type_size, 0);
let desc = BufferDescriptor{
size: type_size * count as u32,
usage,
};
let mut ptr : *mut u8 = std::ptr::null_mut();
let buffer = Buffer {
id: wgn::wgpu_device_create_buffer_mapped(self.id, desc, &mut ptr as *mut *mut u8),
};
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, desc.size as usize / std::mem::size_of::<T>()) };
let data = unsafe { std::slice::from_raw_parts_mut(ptr as *mut T, count) };
(buffer, data)
CreateBufferMapped{id, data}
}
pub fn create_texture(&self, desc: &TextureDescriptor) -> Texture {