[rs] Add Buffer.slice fn for #199

This fn is used for set_index_buffer, set_vertex_buffer, and
BindingResource
This commit is contained in:
Paul Kernfeld
2020-05-08 12:56:02 -04:00
parent c985df9fc8
commit 445786d474
10 changed files with 95 additions and 101 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -80,10 +80,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
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,
});

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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::<ForwardUniforms>() 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);
}
}

View File

@@ -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::<Uniforms>();
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,

View File

@@ -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)
}

View File

@@ -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()),

View File

@@ -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: <C as Context>::BufferDetail,
}
/// A description of what portion of a buffer to use
pub struct BufferSlice<'a> {
buffer: &'a Buffer,
offset: BufferAddress,
size: Option<BufferAddress>,
}
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<C>,
@@ -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<BufferAddress>,
},
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<S: RangeBounds<BufferAddress>>(&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.