131: Support dynamic offsets r=kvark a=cloudhead

Closes #125

Adds support for dynamic offsets when setting a bind group.

I haven't actually tried if this works with my use-case, but it's fairly straight forward. 😅 

Co-authored-by: Alexis Sellier <alexis@monadic.xyz>
This commit is contained in:
bors[bot]
2019-04-26 22:34:55 +00:00
12 changed files with 42 additions and 21 deletions

View File

@@ -83,7 +83,7 @@ fn main() {
{
let mut cpass = encoder.begin_compute_pass();
cpass.set_pipeline(&compute_pipeline);
cpass.set_bind_group(0, &bind_group);
cpass.set_bind_group(0, &bind_group, &[]);
cpass.dispatch(numbers.len() as u32, 1, 1);
}
encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);

View File

@@ -122,7 +122,7 @@ fn main() {
depth_stencil_attachment: None,
});
rpass.set_pipeline(&render_pipeline);
rpass.set_bind_group(0, &bind_group);
rpass.set_bind_group(0, &bind_group, &[]);
rpass.draw(0..3, 0..1);
}

View File

@@ -330,7 +330,7 @@ impl framework::Example for Example {
depth_stencil_attachment: None,
});
rpass.set_pipeline(&self.pipeline);
rpass.set_bind_group(0, &self.bind_group);
rpass.set_bind_group(0, &self.bind_group, &[]);
rpass.set_index_buffer(&self.index_buf, 0);
rpass.set_vertex_buffers(&[(&self.vertex_buf, 0)]);
rpass.draw_indexed(0..self.index_count as u32, 0, 0..1);

View File

@@ -741,10 +741,10 @@ impl framework::Example for Example {
}),
});
pass.set_pipeline(&self.shadow_pass.pipeline);
pass.set_bind_group(0, &self.shadow_pass.bind_group);
pass.set_bind_group(0, &self.shadow_pass.bind_group, &[]);
for entity in &self.entities {
pass.set_bind_group(1, &entity.bind_group);
pass.set_bind_group(1, &entity.bind_group, &[]);
pass.set_index_buffer(&entity.index_buf, 0);
pass.set_vertex_buffers(&[(&entity.vertex_buf, 0)]);
pass.draw_indexed(0..entity.index_count as u32, 0, 0..1);
@@ -776,10 +776,10 @@ impl framework::Example for Example {
}),
});
pass.set_pipeline(&self.forward_pass.pipeline);
pass.set_bind_group(0, &self.forward_pass.bind_group);
pass.set_bind_group(0, &self.forward_pass.bind_group, &[]);
for entity in &self.entities {
pass.set_bind_group(1, &entity.bind_group);
pass.set_bind_group(1, &entity.bind_group, &[]);
pass.set_index_buffer(&entity.index_buf, 0);
pass.set_vertex_buffers(&[(&entity.vertex_buf, 0)]);
pass.draw_indexed(0..entity.index_count as u32, 0, 0..1);

View File

@@ -21,6 +21,8 @@ typedef enum {
WGPUBindingType_Sampler = 1,
WGPUBindingType_SampledTexture = 2,
WGPUBindingType_StorageBuffer = 3,
WGPUBindingType_UniformBufferDynamic = 4,
WGPUBindingType_StorageBufferDynamic = 5,
} WGPUBindingType;
typedef enum {

View File

@@ -21,6 +21,8 @@ pub enum BindingType {
Sampler = 1,
SampledTexture = 2,
StorageBuffer = 3,
UniformBufferDynamic = 4,
StorageBufferDynamic = 5,
}
#[repr(C)]

View File

@@ -46,13 +46,13 @@ pub struct BindGroupEntry {
}
impl BindGroupEntry {
fn provide(&mut self, bind_group_id: BindGroupId, bind_group: &BindGroupHandle) -> Provision {
fn provide(&mut self, bind_group_id: BindGroupId, bind_group: &BindGroupHandle, offsets: &[u32]) -> Provision {
let was_compatible = match self.provided {
Some(BindGroupPair {
layout_id,
ref group_id,
}) => {
if group_id.value == bind_group_id {
if group_id.value == bind_group_id && offsets.is_empty() {
assert_eq!(layout_id, bind_group.layout_id);
return Provision::Unchanged;
}
@@ -135,9 +135,10 @@ impl Binder {
index: usize,
bind_group_id: BindGroupId,
bind_group: &BindGroupHandle,
offsets: &[u32],
) -> Option<(PipelineLayoutId, impl 'a + Iterator<Item = BindGroupId>)> {
trace!("\tBinding [{}] = group {:?}", index, bind_group_id);
match self.entries[index].provide(bind_group_id, bind_group) {
match self.entries[index].provide(bind_group_id, bind_group, offsets) {
Provision::Unchanged => None,
Provision::Changed {
now_compatible: false,

View File

@@ -56,6 +56,7 @@ pub extern "C" fn wgpu_compute_pass_set_bind_group(
pass_id: ComputePassId,
index: u32,
bind_group_id: BindGroupId,
offsets: &[u32],
) {
let mut pass_guard = HUB.compute_passes.write();
let pass = &mut pass_guard[pass_id];
@@ -76,7 +77,7 @@ pub extern "C" fn wgpu_compute_pass_set_bind_group(
if let Some((pipeline_layout_id, follow_up)) =
pass.binder
.provide_entry(index as usize, bind_group_id, bind_group)
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
{
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let bind_groups =
@@ -86,7 +87,7 @@ pub extern "C" fn wgpu_compute_pass_set_bind_group(
&pipeline_layout_guard[pipeline_layout_id].raw,
index as usize,
bind_groups,
&[],
offsets,
);
}
};

View File

@@ -224,6 +224,7 @@ pub extern "C" fn wgpu_render_pass_set_bind_group(
pass_id: RenderPassId,
index: u32,
bind_group_id: BindGroupId,
offsets: &[u32],
) {
let mut pass_guard = HUB.render_passes.write();
let pass = &mut pass_guard[pass_id];
@@ -234,7 +235,7 @@ pub extern "C" fn wgpu_render_pass_set_bind_group(
if let Some((pipeline_layout_id, follow_up)) =
pass.binder
.provide_entry(index as usize, bind_group_id, bind_group)
.provide_entry(index as usize, bind_group_id, bind_group, offsets)
{
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let bind_groups =
@@ -244,7 +245,7 @@ pub extern "C" fn wgpu_render_pass_set_bind_group(
&&pipeline_layout_guard[pipeline_layout_id].raw,
index as usize,
bind_groups,
&[],
offsets,
);
}
};

View File

@@ -78,6 +78,8 @@ pub fn map_binding_type(binding_ty: binding_model::BindingType) -> hal::pso::Des
Sampler => H::Sampler,
SampledTexture => H::SampledImage,
StorageBuffer => H::StorageBuffer,
UniformBufferDynamic => H::UniformBufferDynamic,
StorageBufferDynamic => H::StorageBufferDynamic,
}
}

View File

@@ -462,10 +462,18 @@ impl<B: hal::Backend> Device<B> {
ty: hal::pso::DescriptorType::UniformBuffer,
count: 10000,
},
hal::pso::DescriptorRangeDesc {
ty: hal::pso::DescriptorType::UniformBufferDynamic,
count: 100,
},
hal::pso::DescriptorRangeDesc {
ty: hal::pso::DescriptorType::StorageBuffer,
count: 1000,
},
hal::pso::DescriptorRangeDesc {
ty: hal::pso::DescriptorType::StorageBufferDynamic,
count: 100,
},
],
)
}
@@ -1025,13 +1033,17 @@ pub fn device_create_bind_group(
)
.unwrap();
let alignment = match decl.ty {
binding_model::BindingType::UniformBuffer => {
binding_model::BindingType::UniformBuffer
| binding_model::BindingType::UniformBufferDynamic => {
device.limits.min_uniform_buffer_offset_alignment
}
binding_model::BindingType::StorageBuffer => {
binding_model::BindingType::StorageBuffer
| binding_model::BindingType::StorageBufferDynamic => {
device.limits.min_storage_buffer_offset_alignment
}
_ => panic!("Mismatched buffer binding for {:?}", decl),
binding_model::BindingType::Sampler
| binding_model::BindingType::SampledTexture =>
panic!("Mismatched buffer binding for {:?}", decl),
};
assert_eq!(
bb.offset as hal::buffer::Offset % alignment,

View File

@@ -838,8 +838,8 @@ impl CommandEncoder {
}
impl<'a> RenderPass<'a> {
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) {
wgn::wgpu_render_pass_set_bind_group(self.id, index, bind_group.id);
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup, offsets: &[u32]) {
wgn::wgpu_render_pass_set_bind_group(self.id, index, bind_group.id, offsets);
}
pub fn set_pipeline(&mut self, pipeline: &RenderPipeline) {
@@ -898,8 +898,8 @@ impl<'a> Drop for RenderPass<'a> {
}
impl<'a> ComputePass<'a> {
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup) {
wgn::wgpu_compute_pass_set_bind_group(self.id, index, bind_group.id);
pub fn set_bind_group(&mut self, index: u32, bind_group: &BindGroup, offsets: &[u32]) {
wgn::wgpu_compute_pass_set_bind_group(self.id, index, bind_group.id, offsets);
}
pub fn set_pipeline(&mut self, pipeline: &ComputePipeline) {