diff --git a/Cargo.toml b/Cargo.toml index 71b7bf12e..e00aba38f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/capture/main.rs b/examples/capture/main.rs index d0757c0c6..e7da3cb64 100644 --- a/examples/capture/main.rs +++ b/examples/capture/main.rs @@ -12,7 +12,8 @@ fn main() { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, - ).unwrap(); + ) + .unwrap(); let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { diff --git a/examples/cube/main.rs b/examples/cube/main.rs index 25838b701..e629efae3 100644 --- a/examples/cube/main.rs +++ b/examples/cube/main.rs @@ -1,8 +1,10 @@ #[path = "../framework.rs"] mod framework; +use zerocopy::{AsBytes, FromBytes}; + #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct Vertex { _pos: [f32; 4], _tex_coord: [f32; 2], @@ -107,7 +109,10 @@ impl Example { } impl framework::Example for Example { - fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option) { + fn init( + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> (Self, Option) { use std::mem; let mut init_encoder = @@ -116,13 +121,12 @@ impl framework::Example for Example { // Create the vertex and index buffers let vertex_size = mem::size_of::(); let (vertex_data, index_data) = create_vertices(); - let vertex_buf = device - .create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX) - .fill_from_slice(&vertex_data); - let index_buf = device - .create_buffer_mapped(index_data.len(), wgpu::BufferUsage::INDEX) - .fill_from_slice(&index_data); + let vertex_buf = + device.create_buffer_with_data(vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX); + + let index_buf = + device.create_buffer_with_data(index_data.as_bytes(), wgpu::BufferUsage::INDEX); // Create pipeline layout let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -130,9 +134,7 @@ impl framework::Example for Example { wgpu::BindGroupLayoutBinding { binding: 0, visibility: wgpu::ShaderStage::VERTEX, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - }, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, }, wgpu::BindGroupLayoutBinding { binding: 1, @@ -171,9 +173,8 @@ impl framework::Example for Example { usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, }); let texture_view = texture.create_default_view(); - let temp_buf = device - .create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC) - .fill_from_slice(&texels); + let temp_buf = + device.create_buffer_with_data(texels.as_slice(), wgpu::BufferUsage::COPY_SRC); init_encoder.copy_buffer_to_texture( wgpu::BufferCopyView { buffer: &temp_buf, @@ -208,12 +209,10 @@ 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 = device - .create_buffer_mapped( - 16, - wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - ) - .fill_from_slice(mx_ref); + let uniform_buf = device.create_buffer_with_data( + mx_ref.as_bytes(), + wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + ); // Create bind group let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -310,13 +309,16 @@ impl framework::Example for Example { //empty } - fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option { + fn resize( + &mut self, + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> Option { 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::BufferUsage::COPY_SRC) - .fill_from_slice(mx_ref); + let temp_buf = + device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC); let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); @@ -324,7 +326,11 @@ impl framework::Example for Example { Some(encoder.finish()) } - fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer { + fn render( + &mut self, + frame: &wgpu::SwapChainOutput, + device: &wgpu::Device, + ) -> wgpu::CommandBuffer { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); { diff --git a/examples/describe/main.rs b/examples/describe/main.rs index 287bd787a..bde3b5d17 100644 --- a/examples/describe/main.rs +++ b/examples/describe/main.rs @@ -7,7 +7,8 @@ fn main() { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, - ).unwrap(); + ) + .unwrap(); println!("{:?}", adapter.get_info()) } diff --git a/examples/framework.rs b/examples/framework.rs index b7933006a..f6825dd80 100644 --- a/examples/framework.rs +++ b/examples/framework.rs @@ -99,7 +99,8 @@ pub fn run(title: &str) { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, - ).unwrap(); + ) + .unwrap(); let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { @@ -163,7 +164,8 @@ pub fn run(title: &str) { } }, event::Event::EventsCleared => { - let frame = swap_chain.get_next_texture() + let frame = swap_chain + .get_next_texture() .expect("Timeout when acquiring next swap chain texture"); let command_buf = example.render(&frame, &device); queue.submit(&[command_buf]); diff --git a/examples/hello-compute/main.rs b/examples/hello-compute/main.rs index d3bdf388a..0b03b97b8 100644 --- a/examples/hello-compute/main.rs +++ b/examples/hello-compute/main.rs @@ -1,4 +1,5 @@ -use std::str::FromStr; +use std::{convert::TryInto as _, str::FromStr}; +use zerocopy::AsBytes as _; fn main() { env_logger::init(); @@ -12,14 +13,16 @@ fn main() { .map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!")) .collect(); - let size = (numbers.len() * std::mem::size_of::()) as wgpu::BufferAddress; + let slice_size = numbers.len() * std::mem::size_of::(); + let size = slice_size as wgpu::BufferAddress; let adapter = wgpu::Adapter::request( &wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, - ).unwrap(); + ) + .unwrap(); let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { @@ -29,16 +32,13 @@ fn main() { }); let cs = include_bytes!("shader.comp.spv"); - let cs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap()); + let cs_module = + device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap()); - let staging_buffer = device - .create_buffer_mapped( - numbers.len(), - wgpu::BufferUsage::MAP_READ - | wgpu::BufferUsage::COPY_DST - | wgpu::BufferUsage::COPY_SRC, - ) - .fill_from_slice(&numbers); + let staging_buffer = device.create_buffer_with_data( + numbers.as_slice().as_bytes(), + wgpu::BufferUsage::MAP_READ | wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::COPY_SRC, + ); let storage_buffer = device.create_buffer(&wgpu::BufferDescriptor { size, @@ -48,13 +48,14 @@ fn main() { }); let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[ - wgpu::BindGroupLayoutBinding { - binding: 0, - visibility: wgpu::ShaderStage::COMPUTE, - ty: wgpu::BindingType::StorageBuffer { dynamic: false, readonly: false }, + bindings: &[wgpu::BindGroupLayoutBinding { + binding: 0, + visibility: wgpu::ShaderStage::COMPUTE, + ty: wgpu::BindingType::StorageBuffer { + dynamic: false, + readonly: false, }, - ], + }], }); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -92,9 +93,15 @@ fn main() { queue.submit(&[encoder.finish()]); - staging_buffer.map_read_async(0, numbers.len(), |result: wgpu::BufferMapAsyncResult<&[u32]>| { + // FIXME: Align and use `LayoutVerified` + staging_buffer.map_read_async(0, slice_size, |result| { if let Ok(mapping) = result { - println!("Times: {:?}", mapping.data); + let times: Box<[u32]> = mapping + .data + .chunks_exact(4) + .map(|b| u32::from_ne_bytes(b.try_into().unwrap())) + .collect(); + println!("Times: {:?}", times); } }); } diff --git a/examples/hello-triangle/main.rs b/examples/hello-triangle/main.rs index 18bc2a027..9a9f70e27 100644 --- a/examples/hello-triangle/main.rs +++ b/examples/hello-triangle/main.rs @@ -1,7 +1,7 @@ fn main() { use winit::{ - event_loop::{ControlFlow, EventLoop}, event, + event_loop::{ControlFlow, EventLoop}, }; env_logger::init(); @@ -10,9 +10,7 @@ fn main() { #[cfg(not(feature = "gl"))] let (_window, size, surface) = { let window = winit::window::Window::new(&event_loop).unwrap(); - let size = window - .inner_size() - .to_physical(window.hidpi_factor()); + let size = window.inner_size().to_physical(window.hidpi_factor()); let surface = wgpu::Surface::create(&window); (window, size, surface) @@ -43,7 +41,8 @@ fn main() { power_preference: wgpu::PowerPreference::Default, }, wgpu::BackendBit::PRIMARY, - ).unwrap(); + ) + .unwrap(); let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { @@ -53,14 +52,15 @@ fn main() { }); let vs = include_bytes!("shader.vert.spv"); - let vs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs[..])).unwrap()); + let vs_module = + device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&vs[..])).unwrap()); let fs = include_bytes!("shader.frag.spv"); - let fs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap()); + let fs_module = + device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&fs[..])).unwrap()); - let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[], - }); + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: &[] }); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { layout: &bind_group_layout, bindings: &[], @@ -135,7 +135,8 @@ fn main() { _ => {} }, event::Event::EventsCleared => { - let frame = swap_chain.get_next_texture() + let frame = swap_chain + .get_next_texture() .expect("Timeout when acquiring next swap chain texture"); let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); diff --git a/examples/mipmap/main.rs b/examples/mipmap/main.rs index 1129c571b..2e63aa2c6 100644 --- a/examples/mipmap/main.rs +++ b/examples/mipmap/main.rs @@ -1,10 +1,12 @@ #[path = "../framework.rs"] mod framework; +use zerocopy::{AsBytes, FromBytes}; + const TEXTURE_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8UnormSrgb; #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct Vertex { #[allow(dead_code)] pos: [f32; 4], @@ -96,14 +98,10 @@ impl Example { bind_group_layouts: &[&bind_group_layout], }); - let vs_bytes = framework::load_glsl( - include_str!("blit.vert"), - framework::ShaderStage::Vertex, - ); - let fs_bytes = framework::load_glsl( - include_str!("blit.frag"), - framework::ShaderStage::Fragment, - ); + let vs_bytes = + framework::load_glsl(include_str!("blit.vert"), framework::ShaderStage::Vertex); + let fs_bytes = + framework::load_glsl(include_str!("blit.frag"), framework::ShaderStage::Fragment); let vs_module = device.create_shader_module(&vs_bytes); let fs_module = device.create_shader_module(&fs_bytes); @@ -152,15 +150,17 @@ impl Example { }); let views = (0 .. mip_count) - .map(|mip| texture.create_view(&wgpu::TextureViewDescriptor { - format: TEXTURE_FORMAT, - dimension: wgpu::TextureViewDimension::D2, - aspect: wgpu::TextureAspect::All, - base_mip_level: mip, - level_count: 1, - base_array_layer: 0, - array_layer_count: 1, - })) + .map(|mip| { + texture.create_view(&wgpu::TextureViewDescriptor { + format: TEXTURE_FORMAT, + dimension: wgpu::TextureViewDimension::D2, + aspect: wgpu::TextureAspect::All, + base_mip_level: mip, + level_count: 1, + base_array_layer: 0, + array_layer_count: 1, + }) + }) .collect::>(); for target_mip in 1 .. mip_count as usize { @@ -196,7 +196,10 @@ impl Example { } impl framework::Example for Example { - fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option) { + fn init( + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> (Self, Option) { use std::mem; let mut init_encoder = @@ -205,9 +208,8 @@ impl framework::Example for Example { // Create the vertex and index buffers let vertex_size = mem::size_of::(); let vertex_data = create_vertices(); - let vertex_buf = device - .create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX) - .fill_from_slice(&vertex_data); + let vertex_buf = + device.create_buffer_with_data(vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX); // Create pipeline layout let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -215,9 +217,7 @@ impl framework::Example for Example { wgpu::BindGroupLayoutBinding { binding: 0, visibility: wgpu::ShaderStage::VERTEX, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - }, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, }, wgpu::BindGroupLayoutBinding { binding: 1, @@ -254,12 +254,13 @@ impl framework::Example for Example { sample_count: 1, dimension: wgpu::TextureDimension::D2, format: TEXTURE_FORMAT, - usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::COPY_DST, + usage: wgpu::TextureUsage::SAMPLED + | wgpu::TextureUsage::OUTPUT_ATTACHMENT + | wgpu::TextureUsage::COPY_DST, }); let texture_view = texture.create_default_view(); - let temp_buf = device - .create_buffer_mapped(texels.len(), wgpu::BufferUsage::COPY_SRC) - .fill_from_slice(&texels); + let temp_buf = + device.create_buffer_with_data(texels.as_slice(), wgpu::BufferUsage::COPY_SRC); init_encoder.copy_buffer_to_texture( wgpu::BufferCopyView { buffer: &temp_buf, @@ -294,12 +295,10 @@ 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 = device - .create_buffer_mapped( - 16, - wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - ) - .fill_from_slice(mx_ref); + let uniform_buf = device.create_buffer_with_data( + mx_ref.as_bytes(), + wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + ); // Create bind group let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -324,14 +323,10 @@ impl framework::Example for Example { }); // Create the render pipeline - let vs_bytes = framework::load_glsl( - include_str!("draw.vert"), - framework::ShaderStage::Vertex, - ); - let fs_bytes = framework::load_glsl( - include_str!("draw.frag"), - framework::ShaderStage::Fragment, - ); + let vs_bytes = + framework::load_glsl(include_str!("draw.vert"), framework::ShaderStage::Vertex); + let fs_bytes = + framework::load_glsl(include_str!("draw.frag"), framework::ShaderStage::Fragment); let vs_module = device.create_shader_module(&vs_bytes); let fs_module = device.create_shader_module(&fs_bytes); @@ -364,13 +359,11 @@ impl framework::Example for Example { vertex_buffers: &[wgpu::VertexBufferDescriptor { stride: vertex_size as wgpu::BufferAddress, step_mode: wgpu::InputStepMode::Vertex, - attributes: &[ - wgpu::VertexAttributeDescriptor { - format: wgpu::VertexFormat::Float4, - offset: 0, - shader_location: 0, - }, - ], + attributes: &[wgpu::VertexAttributeDescriptor { + format: wgpu::VertexFormat::Float4, + offset: 0, + shader_location: 0, + }], }], sample_count: 1, sample_mask: !0, @@ -393,13 +386,16 @@ impl framework::Example for Example { //empty } - fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option { + fn resize( + &mut self, + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> Option { 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::BufferUsage::COPY_SRC) - .fill_from_slice(mx_ref); + let temp_buf = + device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC); let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); @@ -407,7 +403,11 @@ impl framework::Example for Example { Some(encoder.finish()) } - fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer { + fn render( + &mut self, + frame: &wgpu::SwapChainOutput, + device: &wgpu::Device, + ) -> wgpu::CommandBuffer { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); { diff --git a/examples/msaa-line/main.rs b/examples/msaa-line/main.rs index ea932a28c..caaa70dc0 100644 --- a/examples/msaa-line/main.rs +++ b/examples/msaa-line/main.rs @@ -10,10 +10,12 @@ #[path = "../framework.rs"] mod framework; +use zerocopy::{AsBytes, FromBytes}; + #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct Vertex { - _pos: [f32; 2], + _pos: [f32; 2], _color: [f32; 4], } @@ -31,7 +33,14 @@ struct Example { } impl Example { - fn create_pipeline(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, vs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule, pipeline_layout: &wgpu::PipelineLayout, sample_count: u32) -> wgpu::RenderPipeline { + fn create_pipeline( + device: &wgpu::Device, + sc_desc: &wgpu::SwapChainDescriptor, + vs_module: &wgpu::ShaderModule, + fs_module: &wgpu::ShaderModule, + pipeline_layout: &wgpu::PipelineLayout, + sample_count: u32, + ) -> wgpu::RenderPipeline { println!("sample_count: {}", sample_count); device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { layout: &pipeline_layout, @@ -81,7 +90,11 @@ impl Example { }) } - fn create_multisampled_framebuffer(device: &wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor, sample_count: u32) -> wgpu::TextureView { + fn create_multisampled_framebuffer( + device: &wgpu::Device, + sc_desc: &wgpu::SwapChainDescriptor, + sample_count: u32, + ) -> wgpu::TextureView { let multisampled_texture_extent = wgpu::Extent3d { width: sc_desc.width, height: sc_desc.height, @@ -97,17 +110,26 @@ impl Example { usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, }; - device.create_texture(multisampled_frame_descriptor).create_default_view() + device + .create_texture(multisampled_frame_descriptor) + .create_default_view() } } impl framework::Example for Example { - fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option) { + fn init( + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> (Self, Option) { println!("Press left/right arrow keys to change sample_count."); let sample_count = 4; - let vs_bytes = framework::load_glsl(include_str!("shader.vert"), framework::ShaderStage::Vertex); - let fs_bytes = framework::load_glsl(include_str!("shader.frag"), framework::ShaderStage::Fragment); + let vs_bytes = + framework::load_glsl(include_str!("shader.vert"), framework::ShaderStage::Vertex); + let fs_bytes = framework::load_glsl( + include_str!("shader.frag"), + framework::ShaderStage::Fragment, + ); let vs_module = device.create_shader_module(&vs_bytes); let fs_module = device.create_shader_module(&fs_bytes); @@ -115,13 +137,21 @@ impl framework::Example for Example { bind_group_layouts: &[], }); - let pipeline = Example::create_pipeline(device, &sc_desc, &vs_module, &fs_module, &pipeline_layout, sample_count); - let multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, sample_count); + let pipeline = Example::create_pipeline( + device, + &sc_desc, + &vs_module, + &fs_module, + &pipeline_layout, + sample_count, + ); + let multisampled_framebuffer = + Example::create_multisampled_framebuffer(device, sc_desc, sample_count); - let mut vertex_data = vec!(); + let mut vertex_data = vec![]; let max = 50; - for i in 0..max { + for i in 0 .. max { let percent = i as f32 / max as f32; let (sin, cos) = (percent * 2.0 * std::f32::consts::PI).sin_cos(); vertex_data.push(Vertex { @@ -134,9 +164,8 @@ impl framework::Example for Example { }); } - let vertex_buffer = device - .create_buffer_mapped(vertex_data.len(), wgpu::BufferUsage::VERTEX) - .fill_from_slice(&vertex_data); + let vertex_buffer = + device.create_buffer_with_data(vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX); let vertex_count = vertex_data.len() as u32; let this = Example { @@ -171,28 +200,46 @@ impl framework::Example for Example { self.rebuild_pipeline = true; } } - _ => { } + _ => {} } } } - _ => { } + _ => {} } } - fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option { + fn resize( + &mut self, + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> Option { self.sc_desc = sc_desc.clone(); - self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count); + self.multisampled_framebuffer = + Example::create_multisampled_framebuffer(device, sc_desc, self.sample_count); None } - fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer { + fn render( + &mut self, + frame: &wgpu::SwapChainOutput, + device: &wgpu::Device, + ) -> wgpu::CommandBuffer { if self.rebuild_pipeline { - self.pipeline = Example::create_pipeline(device, &self.sc_desc, &self.vs_module, &self.fs_module, &self.pipeline_layout, self.sample_count); - self.multisampled_framebuffer = Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count); + self.pipeline = Example::create_pipeline( + device, + &self.sc_desc, + &self.vs_module, + &self.fs_module, + &self.pipeline_layout, + self.sample_count, + ); + self.multisampled_framebuffer = + Example::create_multisampled_framebuffer(device, &self.sc_desc, self.sample_count); self.rebuild_pipeline = false; } - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); + let mut encoder = + device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); { let rpass_color_attachment = if self.sample_count == 1 { wgpu::RenderPassColorAttachmentDescriptor { @@ -218,7 +265,7 @@ impl framework::Example for Example { }); rpass.set_pipeline(&self.pipeline); rpass.set_vertex_buffers(0, &[(&self.vertex_buffer, 0)]); - rpass.draw(0..self.vertex_count, 0..1); + rpass.draw(0 .. self.vertex_count, 0 .. 1); } encoder.finish() diff --git a/examples/shadow/main.rs b/examples/shadow/main.rs index 8572cc788..1bda583d6 100644 --- a/examples/shadow/main.rs +++ b/examples/shadow/main.rs @@ -3,8 +3,10 @@ use std::{mem, ops::Range, rc::Rc}; #[path = "../framework.rs"] mod framework; +use zerocopy::{AsBytes, FromBytes}; + #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct Vertex { _pos: [i8; 4], @@ -97,7 +99,7 @@ struct Light { } #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct LightRaw { proj: [[f32; 4]; 4], pos: [f32; 4], @@ -116,24 +118,30 @@ impl Light { far: self.depth.end, }; let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; - let mx_view_proj = mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view; + let mx_view_proj = + mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view; LightRaw { proj: *mx_view_proj.as_ref(), pos: [self.pos.x, self.pos.y, self.pos.z, 1.0], - color: [self.color.r as f32, self.color.g as f32, self.color.b as f32, 1.0], + color: [ + self.color.r as f32, + self.color.g as f32, + self.color.b as f32, + 1.0, + ], } } } #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct ForwardUniforms { proj: [[f32; 4]; 4], num_lights: [u32; 4], } #[repr(C)] -#[derive(Clone, Copy, zerocopy::AsBytes, zerocopy::FromBytes)] +#[derive(Clone, Copy, AsBytes, FromBytes)] struct EntityUniforms { model: [[f32; 4]; 4], color: [f32; 4], @@ -183,30 +191,27 @@ impl Example { } impl framework::Example for Example { - fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> (Self, Option) { + fn init( + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> (Self, Option) { // Create the vertex and index buffers let vertex_size = mem::size_of::(); let (cube_vertex_data, cube_index_data) = create_cube(); let cube_vertex_buf = Rc::new( - device - .create_buffer_mapped(cube_vertex_data.len(), wgpu::BufferUsage::VERTEX) - .fill_from_slice(&cube_vertex_data), + device.create_buffer_with_data(cube_vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX), ); let cube_index_buf = Rc::new( - device - .create_buffer_mapped(cube_index_data.len(), wgpu::BufferUsage::INDEX) - .fill_from_slice(&cube_index_data), + device.create_buffer_with_data(cube_index_data.as_bytes(), wgpu::BufferUsage::INDEX), ); let (plane_vertex_data, plane_index_data) = create_plane(7); - let plane_vertex_buf = device - .create_buffer_mapped(plane_vertex_data.len(), wgpu::BufferUsage::VERTEX) - .fill_from_slice(&plane_vertex_data); + let plane_vertex_buf = + device.create_buffer_with_data(plane_vertex_data.as_bytes(), wgpu::BufferUsage::VERTEX); - let plane_index_buf = device - .create_buffer_mapped(plane_index_data.len(), wgpu::BufferUsage::INDEX) - .fill_from_slice(&plane_index_data); + let plane_index_buf = + device.create_buffer_with_data(plane_index_data.as_bytes(), wgpu::BufferUsage::INDEX); let entity_uniform_size = mem::size_of::() as wgpu::BufferAddress; let plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { @@ -214,15 +219,14 @@ impl framework::Example for Example { usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, }); - let local_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[ - wgpu::BindGroupLayoutBinding { + let local_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[wgpu::BindGroupLayoutBinding { binding: 0, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - }, - ], - }); + }], + }); let mut entities = vec![{ use cgmath::SquareMatrix; @@ -406,15 +410,14 @@ impl framework::Example for Example { let shadow_pass = { // Create pipeline layout - let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[ - wgpu::BindGroupLayoutBinding { + let bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + bindings: &[wgpu::BindGroupLayoutBinding { binding: 0, // global visibility: wgpu::ShaderStage::VERTEX, ty: wgpu::BindingType::UniformBuffer { dynamic: false }, - }, - ], - }); + }], + }); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], }); @@ -495,16 +498,12 @@ impl framework::Example for Example { wgpu::BindGroupLayoutBinding { binding: 0, // global visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - }, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, }, wgpu::BindGroupLayoutBinding { binding: 1, // lights visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - }, + ty: wgpu::BindingType::UniformBuffer { dynamic: false }, }, wgpu::BindGroupLayoutBinding { binding: 2, @@ -531,12 +530,10 @@ impl framework::Example for Example { num_lights: [lights.len() as u32, 0, 0, 0], }; let uniform_size = mem::size_of::() as wgpu::BufferAddress; - let uniform_buf = device - .create_buffer_mapped( - 1, - wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - ) - .fill_from_slice(&[forward_uniforms]); + let uniform_buf = device.create_buffer_with_data( + forward_uniforms.as_bytes(), + wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + ); // Create bind group let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -654,13 +651,16 @@ impl framework::Example for Example { //empty } - fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &wgpu::Device) -> Option { + fn resize( + &mut self, + sc_desc: &wgpu::SwapChainDescriptor, + device: &wgpu::Device, + ) -> Option { let command_buf = { 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::BufferUsage::COPY_SRC) - .fill_from_slice(mx_ref); + let temp_buf = + device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC); let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); @@ -686,30 +686,42 @@ impl framework::Example for Example { Some(command_buf) } - fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &wgpu::Device) -> wgpu::CommandBuffer { + fn render( + &mut self, + frame: &wgpu::SwapChainOutput, + device: &wgpu::Device, + ) -> wgpu::CommandBuffer { let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); { - let size = mem::size_of::() as wgpu::BufferAddress; - let temp_buf_data = - device.create_buffer_mapped(self.entities.len(), wgpu::BufferUsage::COPY_SRC); - - for (i, entity) in self.entities.iter_mut().enumerate() { + let size = mem::size_of::(); + let temp_buf_data = device + .create_buffer_mapped(self.entities.len() * size, wgpu::BufferUsage::COPY_SRC); + + // FIXME: Align and use `LayoutVerified` + for (entity, slot) in self + .entities + .iter_mut() + .zip(temp_buf_data.data.chunks_exact_mut(size)) + { 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.into(), - color: [ - entity.color.r as f32, - entity.color.g as f32, - entity.color.b as f32, - entity.color.a as f32, - ], - }; + slot.copy_from_slice( + EntityUniforms { + model: entity.mx_world.into(), + color: [ + entity.color.r as f32, + entity.color.g as f32, + entity.color.b as f32, + entity.color.a as f32, + ], + } + .as_bytes(), + ); } let temp_buf = temp_buf_data.finish(); @@ -717,28 +729,34 @@ impl framework::Example for Example { for (i, entity) in self.entities.iter().enumerate() { encoder.copy_buffer_to_buffer( &temp_buf, - i as wgpu::BufferAddress * size, + (i * size) as wgpu::BufferAddress, &entity.uniform_buf, 0, - size, + size as wgpu::BufferAddress, ); } } if self.lights_are_dirty { self.lights_are_dirty = false; - let size = (self.lights.len() * mem::size_of::()) as wgpu::BufferAddress; + let size = mem::size_of::(); + let total_size = size * self.lights.len(); let temp_buf_data = - device.create_buffer_mapped(self.lights.len(), wgpu::BufferUsage::COPY_SRC); - for (i, light) in self.lights.iter().enumerate() { - temp_buf_data.data[i] = light.to_raw(); + device.create_buffer_mapped(total_size, wgpu::BufferUsage::COPY_SRC); + // FIXME: Align and use `LayoutVerified` + for (light, slot) in self + .lights + .iter() + .zip(temp_buf_data.data.chunks_exact_mut(size)) + { + slot.copy_from_slice(light.to_raw().as_bytes()); } encoder.copy_buffer_to_buffer( &temp_buf_data.finish(), 0, &self.light_uniform_buf, 0, - size, + total_size as wgpu::BufferAddress, ); } diff --git a/examples/skybox/main.rs b/examples/skybox/main.rs index 6ff570e2d..89ca3a97c 100644 --- a/examples/skybox/main.rs +++ b/examples/skybox/main.rs @@ -1,9 +1,12 @@ #[path = "../framework.rs"] mod framework; +use zerocopy::AsBytes as _; + const SKYBOX_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm; -type Uniforms = [cgmath::Matrix4; 2]; +type Uniform = cgmath::Matrix4; +type Uniforms = [Uniform; 2]; pub struct Skybox { aspect: f32, @@ -26,6 +29,23 @@ impl Skybox { } } +fn buffer_from_uniforms( + device: &wgpu::Device, + uniforms: &Uniforms, + usage: wgpu::BufferUsage, +) -> wgpu::Buffer { + let uniform_buf = device.create_buffer_mapped(std::mem::size_of::(), usage); + // FIXME: Align and use `LayoutVerified` + for (u, slot) in uniforms.iter().zip( + uniform_buf + .data + .chunks_exact_mut(std::mem::size_of::()), + ) { + slot.copy_from_slice(AsRef::<[[f32; 4]; 4]>::as_ref(u).as_bytes()); + } + uniform_buf.finish() +} + impl framework::Example for Skybox { fn init( sc_desc: &wgpu::SwapChainDescriptor, @@ -71,15 +91,11 @@ impl framework::Example for Skybox { let aspect = sc_desc.width as f32 / sc_desc.height as f32; let uniforms = Self::generate_uniforms(aspect); - let uniform_buf = device - .create_buffer_mapped::<[[f32; 4]; 4]>( - uniforms.len(), - wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - ) - .fill_from_slice(&[ - uniforms[0].into(), - uniforms[1].into(), - ]); + let uniform_buf = buffer_from_uniforms( + &device, + &uniforms, + wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + ); let uniform_buf_size = std::mem::size_of::(); let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { @@ -175,11 +191,11 @@ impl framework::Example for Skybox { for (i, image) in faces.iter().enumerate() { log::debug!( "Copying skybox image {} of size {},{} to gpu", - i, image_width, image_height, + i, + image_width, + image_height, ); - let image_buf = device - .create_buffer_mapped(image.len(), wgpu::BufferUsage::COPY_SRC) - .fill_from_slice(&image); + let image_buf = device.create_buffer_with_data(image, wgpu::BufferUsage::COPY_SRC); init_encoder.copy_buffer_to_texture( wgpu::BufferCopyView { @@ -218,7 +234,7 @@ impl framework::Example for Skybox { binding: 0, resource: wgpu::BindingResource::Buffer { buffer: &uniform_buf, - range: 0..uniform_buf_size as wgpu::BufferAddress, + range: 0 .. uniform_buf_size as wgpu::BufferAddress, }, }, wgpu::Binding { @@ -257,9 +273,8 @@ impl framework::Example for Skybox { let mx_total = uniforms[0] * uniforms[1]; let mx_ref: &[f32; 16] = mx_total.as_ref(); - let temp_buf = device - .create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC) - .fill_from_slice(mx_ref); + let temp_buf = + device.create_buffer_with_data(mx_ref.as_bytes(), wgpu::BufferUsage::COPY_SRC); let mut init_encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); @@ -278,15 +293,7 @@ impl framework::Example for Skybox { let rotation = cgmath::Matrix4::::from_angle_x(cgmath::Deg(0.25)); self.uniforms[1] = self.uniforms[1] * rotation; let uniform_buf_size = std::mem::size_of::(); - let temp_buf = device - .create_buffer_mapped::<[[f32; 4]; 4]>( - self.uniforms.len(), - wgpu::BufferUsage::COPY_SRC, - ) - .fill_from_slice(&[ - self.uniforms[0].into(), - self.uniforms[1].into(), - ]); + let temp_buf = buffer_from_uniforms(&device, &self.uniforms, wgpu::BufferUsage::COPY_SRC); init_encoder.copy_buffer_to_buffer( &temp_buf, @@ -315,7 +322,7 @@ impl framework::Example for Skybox { rpass.set_pipeline(&self.pipeline); rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.draw(0..3 as u32, 0..1); + rpass.draw(0 .. 3 as u32, 0 .. 1); } init_encoder.finish() } diff --git a/src/lib.rs b/src/lib.rs index 633aa3286..d197cb39f 100644 --- a/src/lib.rs +++ b/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; @@ -11,12 +9,10 @@ use std::slice; use std::thread; pub use wgc::{ - binding_model::{ - ShaderStage, - }, + binding_model::ShaderStage, command::{ - CommandEncoderDescriptor, CommandBufferDescriptor, + CommandEncoderDescriptor, LoadOp, RenderPassDepthStencilAttachmentDescriptor, StoreOp, @@ -50,6 +46,7 @@ pub use wgc::{ VertexAttributeDescriptor, VertexFormat, }, + read_spirv, resource::{ AddressMode, BufferDescriptor, @@ -66,24 +63,18 @@ pub use wgc::{ TextureViewDescriptor, TextureViewDimension, }, - swap_chain::{ - PresentMode, - SwapChainDescriptor, - }, + swap_chain::{PresentMode, SwapChainDescriptor}, BufferAddress, Color, Extent3d, Origin3d, - read_spirv, }; - //TODO: avoid heap allocating vectors during resource creation. -#[derive(Default)] -#[derive(Debug)] +#[derive(Default, Debug)] struct Temp { //bind_group_descriptors: Vec, - //vertex_buffers: Vec, +//vertex_buffers: Vec, } /// A handle to a physical graphics and/or compute device. @@ -500,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); @@ -551,15 +527,21 @@ impl Adapter { /// /// If no adapters are found that suffice all the "hard" options, `None` is returned. pub fn request(options: &RequestAdapterOptions, backends: BackendBit) -> Option { - unsafe extern "C" fn adapter_callback(id: wgc::id::AdapterId, user_data: *mut std::ffi::c_void) { + unsafe extern "C" fn adapter_callback( + id: wgc::id::AdapterId, + user_data: *mut std::ffi::c_void, + ) { *(user_data as *mut wgc::id::AdapterId) = id; } let mut id = wgc::id::AdapterId::ERROR; - wgn::wgpu_request_adapter_async(Some(options), backends, adapter_callback, &mut id as *mut _ as *mut std::ffi::c_void); - Some(Adapter { - id, - }) + wgn::wgpu_request_adapter_async( + Some(options), + backends, + adapter_callback, + &mut id as *mut _ as *mut std::ffi::c_void, + ); + Some(Adapter { id }) } /// Requests a connection to a physical device, creating a logical device. @@ -617,7 +599,7 @@ impl Device { let bindings = desc .bindings - .into_iter() + .iter() .map(|binding| bm::BindGroupBinding { binding: binding.binding, resource: match binding.resource { @@ -655,22 +637,27 @@ impl Device { pub fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> BindGroupLayout { use wgc::binding_model as bm; - let temp_layouts = desc.bindings + let temp_layouts = desc + .bindings .iter() .map(|bind| bm::BindGroupLayoutBinding { binding: bind.binding, visibility: bind.visibility, ty: match bind.ty { BindingType::UniformBuffer { .. } => bm::BindingType::UniformBuffer, - BindingType::StorageBuffer { readonly: false, .. } => bm::BindingType::StorageBuffer, - BindingType::StorageBuffer { readonly: true, .. } => bm::BindingType::ReadonlyStorageBuffer, + BindingType::StorageBuffer { + readonly: false, .. + } => bm::BindingType::StorageBuffer, + BindingType::StorageBuffer { readonly: true, .. } => { + bm::BindingType::ReadonlyStorageBuffer + } BindingType::Sampler => bm::BindingType::Sampler, BindingType::SampledTexture { .. } => bm::BindingType::SampledTexture, BindingType::StorageTexture { .. } => bm::BindingType::StorageTexture, }, dynamic: match bind.ty { - BindingType::UniformBuffer { dynamic } | - BindingType::StorageBuffer { dynamic, .. } => dynamic, + BindingType::UniformBuffer { dynamic } + | BindingType::StorageBuffer { dynamic, .. } => dynamic, _ => false, }, multisampled: match bind.ty { @@ -678,8 +665,8 @@ impl Device { _ => false, }, texture_dimension: match bind.ty { - BindingType::SampledTexture { dimension, .. } | - BindingType::StorageTexture { dimension } => dimension, + BindingType::SampledTexture { dimension, .. } + | BindingType::StorageTexture { dimension } => dimension, _ => TextureViewDimension::D2, }, }) @@ -756,7 +743,8 @@ impl Device { fragment_stage: fragment_stage .as_ref() .map_or(ptr::null(), |fs| fs as *const _), - rasterization_state: desc.rasterization_state + rasterization_state: desc + .rasterization_state .as_ref() .map_or(ptr::null(), |p| p as *const _), primitive_topology: desc.primitive_topology, @@ -808,32 +796,32 @@ impl Device { /// Creates a new buffer and maps it into host-visible memory. /// - /// This returns a [`CreateBufferMapped`], 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::() 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. @@ -883,50 +871,39 @@ impl Drop for BufferAsyncMapping { } } -struct BufferMapReadAsyncUserData +struct BufferMapReadAsyncUserData 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, } -struct BufferMapWriteAsyncUserData +struct BufferMapWriteAsyncUserData 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, } impl Buffer { - pub fn map_read_async(&self, start: BufferAddress, count: usize, callback: F) + pub fn map_read_async(&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( + extern "C" fn buffer_map_read_callback_wrapper( 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) }; - 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) }; + 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, @@ -936,44 +913,34 @@ impl Buffer { } } - let size = (count * std::mem::size_of::()) 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::, + size as BufferAddress, + buffer_map_read_callback_wrapper::, Box::into_raw(user_data) as *mut u8, ); } - pub fn map_write_async(&self, start: BufferAddress, count: usize, callback: F) + pub fn map_write_async(&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( + extern "C" fn buffer_map_write_callback_wrapper( 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) }; - 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) }; + 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, @@ -983,19 +950,16 @@ impl Buffer { } } - let size = (count * std::mem::size_of::()) 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::, + size as BufferAddress, + buffer_map_write_callback_wrapper::, Box::into_raw(user_data) as *mut u8, ); } @@ -1294,7 +1258,11 @@ impl<'a> RenderPass<'a> { /// /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active /// vertex buffers can be set with [`RenderPass::set_vertex_buffers`]. - pub fn draw_indexed_indirect(&mut self, indirect_buffer: &Buffer, indirect_offset: BufferAddress) { + pub fn draw_indexed_indirect( + &mut self, + indirect_buffer: &Buffer, + indirect_offset: BufferAddress, + ) { wgn::wgpu_render_pass_draw_indexed_indirect(self.id, indirect_buffer.id, indirect_offset); } } diff --git a/tests/multithreaded_compute.rs b/tests/multithreaded_compute.rs index 4324b3007..820df9cd7 100644 --- a/tests/multithreaded_compute.rs +++ b/tests/multithreaded_compute.rs @@ -1,3 +1,6 @@ +#[cfg(any(feature = "vulkan", feature = "metal", feature = "dx12"))] +use std::convert::TryInto as _; + #[test] #[cfg(any(feature = "vulkan", feature = "metal", feature = "dx12"))] fn multithreaded_compute() { @@ -13,14 +16,18 @@ fn multithreaded_compute() { thread::spawn(move || { let numbers = vec![100, 100, 100]; - let size = (numbers.len() * std::mem::size_of::()) as wgpu::BufferAddress; + let slice_size = numbers.len() * std::mem::size_of::(); + let size = slice_size as wgpu::BufferAddress; - let instance = wgpu::Instance::new(); - let adapter = instance.request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::Default, - }); + let adapter = wgpu::Adapter::request( + &wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::Default, + }, + wgpu::BackendBit::PRIMARY, + ) + .unwrap(); - let mut device = adapter.request_device(&wgpu::DeviceDescriptor { + let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor { extensions: wgpu::Extensions { anisotropic_filtering: false, }, @@ -28,16 +35,15 @@ fn multithreaded_compute() { }); let cs = include_bytes!("../examples/hello-compute/shader.comp.spv"); - let cs_module = device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap()); + let cs_module = device + .create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(&cs[..])).unwrap()); - let staging_buffer = device - .create_buffer_mapped( - numbers.len(), - wgpu::BufferUsage::MAP_READ - | wgpu::BufferUsage::COPY_DST - | wgpu::BufferUsage::COPY_SRC, - ) - .fill_from_slice(&numbers); + let staging_buffer = device.create_buffer_with_data( + numbers.as_slice(), + wgpu::BufferUsage::MAP_READ + | wgpu::BufferUsage::COPY_DST + | wgpu::BufferUsage::COPY_SRC, + ); let storage_buffer = device.create_buffer(&wgpu::BufferDescriptor { size, @@ -48,16 +54,14 @@ fn multithreaded_compute() { let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: &[ - wgpu::BindGroupLayoutBinding { - binding: 0, - visibility: wgpu::ShaderStage::COMPUTE, - ty: wgpu::BindingType::StorageBuffer { - dynamic: false, - readonly: false, - }, + bindings: &[wgpu::BindGroupLayoutBinding { + binding: 0, + visibility: wgpu::ShaderStage::COMPUTE, + ty: wgpu::BindingType::StorageBuffer { + dynamic: false, + readonly: false, }, - ], + }], }); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { @@ -95,10 +99,17 @@ fn multithreaded_compute() { } encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size); - device.get_queue().submit(&[encoder.finish()]); - - staging_buffer.map_read_async(0, size, |result: wgpu::BufferMapAsyncResult<&[u32]>| { - assert_eq!(result.unwrap().data, [25, 25, 25]); + queue.submit(&[encoder.finish()]); + + // FIXME: Align and use `LayoutVerified` + staging_buffer.map_read_async(0, slice_size, |result| { + let result_data: Box<[u32]> = result + .unwrap() + .data + .chunks_exact(std::mem::size_of::()) + .map(|c| u32::from_ne_bytes(c.try_into().unwrap())) + .collect(); + assert_eq!(&*result_data, &[25, 25, 25]); }); tx.send(true).unwrap(); });