From 445786d4748656f809b82de1d02f1e412a8fb721 Mon Sep 17 00:00:00 2001 From: Paul Kernfeld Date: Fri, 8 May 2020 12:56:02 -0400 Subject: [PATCH] [rs] Add Buffer.slice fn for #199 This fn is used for set_index_buffer, set_vertex_buffer, and BindingResource --- wgpu/examples/boids/main.rs | 21 +++----- wgpu/examples/cube/main.rs | 9 ++-- wgpu/examples/hello-compute/main.rs | 5 +- wgpu/examples/mipmap/main.rs | 7 +-- wgpu/examples/msaa-line/main.rs | 2 +- wgpu/examples/shadow/main.rs | 34 ++++-------- wgpu/examples/skybox/main.rs | 6 +-- wgpu/src/backend/direct.rs | 17 +++--- wgpu/src/backend/web.rs | 13 ++--- wgpu/src/lib.rs | 82 ++++++++++++++++++++--------- 10 files changed, 95 insertions(+), 101 deletions(-) diff --git a/wgpu/examples/boids/main.rs b/wgpu/examples/boids/main.rs index d171786e67..79127c50e6 100644 --- a/wgpu/examples/boids/main.rs +++ b/wgpu/examples/boids/main.rs @@ -202,24 +202,17 @@ impl framework::Example for Example { bindings: &[ wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &sim_param_buffer, - range: 0..(4 * sim_param_data.len() as u64), // 4 = size_of f32 - }, + resource: wgpu::BindingResource::Buffer(sim_param_buffer.slice(..)), }, wgpu::Binding { binding: 1, - resource: wgpu::BindingResource::Buffer { - buffer: &particle_buffers[i], - range: 0..(4 * initial_particle_data.len() as u64), // 4 = size_of f32 - }, + resource: wgpu::BindingResource::Buffer(particle_buffers[i].slice(..)), }, wgpu::Binding { binding: 2, - resource: wgpu::BindingResource::Buffer { - buffer: &particle_buffers[(i + 1) % 2], // bind to opposite buffer - range: 0..(4 * initial_particle_data.len() as u64), // 4 = size_of f32 - }, + resource: wgpu::BindingResource::Buffer( + particle_buffers[(i + 1) % 2].slice(..), // bind to opposite buffer + ), }, ], label: None, @@ -296,9 +289,9 @@ impl framework::Example for Example { let mut rpass = command_encoder.begin_render_pass(&render_pass_descriptor); rpass.set_pipeline(&self.render_pipeline); // render dst particles - rpass.set_vertex_buffer(0, &self.particle_buffers[(self.frame_num + 1) % 2], 0, 0); + rpass.set_vertex_buffer(0, self.particle_buffers[(self.frame_num + 1) % 2].slice(..)); // the three instance-local vertices - rpass.set_vertex_buffer(1, &self.vertices_buffer, 0, 0); + rpass.set_vertex_buffer(1, self.vertices_buffer.slice(..)); rpass.draw(0..3, 0..NUM_PARTICLES); } diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index a014ec0f15..c685f7029c 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -224,10 +224,7 @@ impl framework::Example for Example { bindings: &[ wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0..64, - }, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }, wgpu::Binding { binding: 1, @@ -356,8 +353,8 @@ impl framework::Example for Example { }); rpass.set_pipeline(&self.pipeline); rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.set_index_buffer(&self.index_buf, 0, 0); - rpass.set_vertex_buffer(0, &self.vertex_buf, 0, 0); + rpass.set_index_buffer(self.index_buf.slice(..)); + rpass.set_vertex_buffer(0, self.vertex_buf.slice(..)); rpass.draw_indexed(0..self.index_count as u32, 0, 0..1); } diff --git a/wgpu/examples/hello-compute/main.rs b/wgpu/examples/hello-compute/main.rs index 9e4e954198..2273c3debc 100644 --- a/wgpu/examples/hello-compute/main.rs +++ b/wgpu/examples/hello-compute/main.rs @@ -80,10 +80,7 @@ async fn execute_gpu(numbers: Vec) -> Vec { layout: &bind_group_layout, bindings: &[wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &storage_buffer, - range: 0..size, - }, + resource: wgpu::BindingResource::Buffer(storage_buffer.slice(..)), }], label: None, }); diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index a9e12fc838..86662366c6 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -319,10 +319,7 @@ impl framework::Example for Example { bindings: &[ wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0..64, - }, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }, wgpu::Binding { binding: 1, @@ -440,7 +437,7 @@ impl framework::Example for Example { }); rpass.set_pipeline(&self.draw_pipeline); rpass.set_bind_group(0, &self.bind_group, &[]); - rpass.set_vertex_buffer(0, &self.vertex_buf, 0, 0); + rpass.set_vertex_buffer(0, self.vertex_buf.slice(..)); rpass.draw(0..4, 0..1); } diff --git a/wgpu/examples/msaa-line/main.rs b/wgpu/examples/msaa-line/main.rs index 25368b9b9b..d8e68a6a30 100644 --- a/wgpu/examples/msaa-line/main.rs +++ b/wgpu/examples/msaa-line/main.rs @@ -260,7 +260,7 @@ impl framework::Example for Example { depth_stencil_attachment: None, }); rpass.set_pipeline(&self.pipeline); - rpass.set_vertex_buffer(0, &self.vertex_buffer, 0, 0); + rpass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); rpass.draw(0..self.vertex_count, 0..1); } diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index a451bb4e18..b5bd10c77e 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -257,10 +257,7 @@ impl framework::Example for Example { layout: &local_bind_group_layout, bindings: &[wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &plane_uniform_buf, - range: 0..entity_uniform_size, - }, + resource: wgpu::BindingResource::Buffer(plane_uniform_buf.slice(..)), }], label: None, }); @@ -333,10 +330,7 @@ impl framework::Example for Example { layout: &local_bind_group_layout, bindings: &[wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0..entity_uniform_size, - }, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }], label: None, }), @@ -452,10 +446,7 @@ impl framework::Example for Example { layout: &bind_group_layout, bindings: &[wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0..uniform_size, - }, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }], label: None, }); @@ -555,7 +546,6 @@ impl framework::Example for Example { proj: *mx_total.as_ref(), num_lights: [lights.len() as u32, 0, 0, 0], }; - let uniform_size = mem::size_of::() as wgpu::BufferAddress; let uniform_buf = device.create_buffer_with_data( bytemuck::bytes_of(&forward_uniforms), wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, @@ -567,17 +557,11 @@ impl framework::Example for Example { bindings: &[ wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0..uniform_size, - }, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }, wgpu::Binding { binding: 1, - resource: wgpu::BindingResource::Buffer { - buffer: &light_uniform_buf, - range: 0..light_uniform_size, - }, + resource: wgpu::BindingResource::Buffer(light_uniform_buf.slice(..)), }, wgpu::Binding { binding: 2, @@ -820,8 +804,8 @@ impl framework::Example for Example { for entity in &self.entities { pass.set_bind_group(1, &entity.bind_group, &[]); - pass.set_index_buffer(&entity.index_buf, 0, 0); - pass.set_vertex_buffer(0, &entity.vertex_buf, 0, 0); + pass.set_index_buffer(entity.index_buf.slice(..)); + pass.set_vertex_buffer(0, entity.vertex_buf.slice(..)); pass.draw_indexed(0..entity.index_count as u32, 0, 0..1); } } @@ -856,8 +840,8 @@ impl framework::Example for Example { for entity in &self.entities { pass.set_bind_group(1, &entity.bind_group, &[]); - pass.set_index_buffer(&entity.index_buf, 0, 0); - pass.set_vertex_buffer(0, &entity.vertex_buf, 0, 0); + pass.set_index_buffer(entity.index_buf.slice(..)); + pass.set_vertex_buffer(0, entity.vertex_buf.slice(..)); pass.draw_indexed(0..entity.index_count as u32, 0, 0..1); } } diff --git a/wgpu/examples/skybox/main.rs b/wgpu/examples/skybox/main.rs index 3301eeecae..a230e7f8ac 100644 --- a/wgpu/examples/skybox/main.rs +++ b/wgpu/examples/skybox/main.rs @@ -96,7 +96,6 @@ impl framework::Example for Skybox { &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 { bind_group_layouts: &[&bind_group_layout], @@ -234,10 +233,7 @@ impl framework::Example for Skybox { bindings: &[ wgpu::Binding { binding: 0, - resource: wgpu::BindingResource::Buffer { - buffer: &uniform_buf, - range: 0..uniform_buf_size as wgpu::BufferAddress, - }, + resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)), }, wgpu::Binding { binding: 1, diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 7d2ee40bf8..ae423c8ce0 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -356,15 +356,14 @@ impl crate::Context for Context { .iter() .map(|binding| bm::BindGroupEntry { binding: binding.binding, - resource: match binding.resource { - BindingResource::Buffer { - ref buffer, - ref range, - } => bm::BindingResource::Buffer(bm::BufferBinding { - buffer: buffer.id, - offset: range.start, - size: range.end - range.start, - }), + resource: match &binding.resource { + BindingResource::Buffer(buffer_slice) => { + bm::BindingResource::Buffer(bm::BufferBinding { + buffer: buffer_slice.buffer.id, + offset: buffer_slice.offset, + size: buffer_slice.size_or_0(), + }) + } BindingResource::Sampler(ref sampler) => { bm::BindingResource::Sampler(sampler.id) } diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index fec2f63c8e..fd4fd832d2 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -826,15 +826,12 @@ impl crate::Context for Context { .bindings .iter() .map(|binding| { - let mapped_resource = match binding.resource { - BindingResource::Buffer { - ref buffer, - ref range, - } => { + let mapped_resource = match &binding.resource { + BindingResource::Buffer(buffer_slice) => { let mut mapped_buffer_binding = - web_sys::GpuBufferBinding::new(&buffer.id.0); - mapped_buffer_binding.offset(range.start as f64); - mapped_buffer_binding.size((range.end - range.start) as f64); + web_sys::GpuBufferBinding::new(&buffer_slice.buffer.id.0); + mapped_buffer_binding.offset(buffer_slice.offset as f64); + mapped_buffer_binding.size(buffer_slice.size_or_0() as f64); JsValue::from(mapped_buffer_binding.clone()) } BindingResource::Sampler(ref sampler) => JsValue::from(sampler.id.0.clone()), diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 6f787b78d8..a78ce8af64 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -6,7 +6,13 @@ mod backend; mod macros; use futures::FutureExt as _; -use std::{future::Future, marker::PhantomData, ops::Range, sync::Arc, thread}; +use std::{ + future::Future, + marker::PhantomData, + ops::{Bound, Range, RangeBounds}, + sync::Arc, + thread, +}; #[cfg(not(target_arch = "wasm32"))] pub use wgc::instance::{AdapterInfo, DeviceType}; @@ -339,6 +345,21 @@ pub struct Buffer { //detail: ::BufferDetail, } +/// A description of what portion of a buffer to use +pub struct BufferSlice<'a> { + buffer: &'a Buffer, + offset: BufferAddress, + size: Option, +} + +impl<'a> BufferSlice<'a> { + /// This fn can be used for calling lower-level APIs where `0` denotes that the slice should + /// extend to the end of the buffer. + fn size_or_0(&self) -> BufferAddress { + self.size.unwrap_or(0) + } +} + /// A handle to a texture on the GPU. pub struct Texture { context: Arc, @@ -535,10 +556,7 @@ pub struct Queue { /// A resource that can be bound to a pipeline. pub enum BindingResource<'a> { - Buffer { - buffer: &'a Buffer, - range: Range, - }, + Buffer(BufferSlice<'a>), Sampler(&'a Sampler), TextureView(&'a TextureView), } @@ -1167,6 +1185,26 @@ impl Drop for BufferWriteMapping { } impl Buffer { + /// Use only a portion of this Buffer for a given operation. Choosing a range with 0 size will + /// return a slice that extends to the end of the buffer. + pub fn slice>(&self, bounds: S) -> BufferSlice { + let offset = match bounds.start_bound() { + Bound::Included(&bound) => bound, + Bound::Excluded(&bound) => bound + 1, + Bound::Unbounded => 0, + }; + let size = match bounds.end_bound() { + Bound::Included(&bound) => Some(bound + 1 - offset), + Bound::Excluded(&bound) => Some(bound - offset), + Bound::Unbounded => None, + }; + BufferSlice { + buffer: self, + offset, + size, + } + } + /// Map the buffer for reading. The result is returned in a future. /// /// For the future to complete, `device.poll(...)` must be called elsewhere in the runtime, possibly integrated @@ -1376,15 +1414,13 @@ impl<'a> RenderPass<'a> { /// /// Subsequent calls to [`draw_indexed`](RenderPass::draw_indexed) on this [`RenderPass`] will /// use `buffer` as the source index buffer. - /// - /// If `size == 0`, the remaining part of the buffer is considered. - pub fn set_index_buffer( - &mut self, - buffer: &'a Buffer, - offset: BufferAddress, - size: BufferAddress, - ) { - RenderPassInner::set_index_buffer(&mut self.id, &buffer.id, offset, size) + pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>) { + RenderPassInner::set_index_buffer( + &mut self.id, + &buffer_slice.buffer.id, + buffer_slice.offset, + buffer_slice.size_or_0(), + ) } /// Assign a vertex buffer to a slot. @@ -1395,20 +1431,18 @@ impl<'a> RenderPass<'a> { /// The `slot` refers to the index of the matching descriptor in /// [`RenderPipelineDescriptor::vertex_buffers`]. /// - /// If `size == 0`, the remaining part of the buffer is considered. - /// /// [`draw`]: #method.draw /// [`draw_indexed`]: #method.draw_indexed /// [`RenderPass`]: struct.RenderPass.html /// [`RenderPipelineDescriptor::vertex_buffers`]: struct.RenderPipelineDescriptor.html#structfield.vertex_buffers - pub fn set_vertex_buffer( - &mut self, - slot: u32, - buffer: &'a Buffer, - offset: BufferAddress, - size: BufferAddress, - ) { - RenderPassInner::set_vertex_buffer(&mut self.id, slot, &buffer.id, offset, size) + pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) { + RenderPassInner::set_vertex_buffer( + &mut self.id, + slot, + &buffer_slice.buffer.id, + buffer_slice.offset, + buffer_slice.size_or_0(), + ) } /// Sets the scissor region.