Skip to content

Commit

Permalink
Add uniform and storage buffer arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
csnewman authored and kvark committed Apr 29, 2021
1 parent 048551c commit 5d2e88c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 24 deletions.
8 changes: 3 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,27 @@ all-features = true
default = []
trace = ["serde", "wgc/trace"]
replay = ["serde", "wgc/replay"]
# Make Vulkan backend available on platforms where it is by default not, e.g. macOS
vulkan-portability = ["wgc/gfx-backend-vulkan"]
webgl = ["wgc"]
# Enable SPIRV-Cross
cross = ["wgc/cross"]

[target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
rev = "13015c8621daade1decb7e1083b7e0f73eeab6c7"
rev = "e5ddb94be0221b0f53a8f43adfb15458daebfd7c"
features = ["raw-window-handle"]

[target.'cfg(target_arch = "wasm32")'.dependencies.wgc]
package = "wgpu-core"
git = "https://github.com/gfx-rs/wgpu"
rev = "13015c8621daade1decb7e1083b7e0f73eeab6c7"
rev = "e5ddb94be0221b0f53a8f43adfb15458daebfd7c"
features = ["raw-window-handle"]
optional = true

[dependencies.wgt]
package = "wgpu-types"
git = "https://github.com/gfx-rs/wgpu"
rev = "13015c8621daade1decb7e1083b7e0f73eeab6c7"
rev = "e5ddb94be0221b0f53a8f43adfb15458daebfd7c"

[dependencies]
arrayvec = "0.5"
Expand Down
4 changes: 2 additions & 2 deletions examples/shadow/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,11 +349,11 @@ impl framework::Example for Example {
layout: &local_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer {
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: &entity_uniform_buf,
offset: 0,
size: wgpu::BufferSize::new(entity_uniform_size),
},
}),
}],
label: None,
});
Expand Down
27 changes: 24 additions & 3 deletions src/backend/direct.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
backend::{error::ContextError, native_gpu_future},
AdapterInfo, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource,
AdapterInfo, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BufferBinding,
CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor,
DownlevelProperties, Features, Label, Limits, LoadOp, MapMode, Operations,
PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor,
Expand Down Expand Up @@ -875,21 +875,42 @@ impl crate::Context for Context {
}
let mut remaining_arrayed_texture_views = &arrayed_texture_views[..];

let mut arrayed_buffer_bindings = Vec::new();
if device.features.contains(Features::BUFFER_BINDING_ARRAY) {
// gather all the buffers first
for entry in desc.entries.iter() {
if let BindingResource::BufferArray(array) = entry.resource {
arrayed_buffer_bindings.extend(array.iter().map(|binding| bm::BufferBinding {
buffer_id: binding.buffer.id.id,
offset: binding.offset,
size: binding.size,
}));
}
}
}
let mut remaining_arrayed_buffer_bindings = &arrayed_buffer_bindings[..];

let entries = desc
.entries
.iter()
.map(|entry| bm::BindGroupEntry {
binding: entry.binding,
resource: match entry.resource {
BindingResource::Buffer {
BindingResource::Buffer(BufferBinding {
buffer,
offset,
size,
} => bm::BindingResource::Buffer(bm::BufferBinding {
}) => bm::BindingResource::Buffer(bm::BufferBinding {
buffer_id: buffer.id.id,
offset,
size,
}),
BindingResource::BufferArray(array) => {
let slice = &remaining_arrayed_buffer_bindings[..array.len()];
remaining_arrayed_buffer_bindings =
&remaining_arrayed_buffer_bindings[array.len()..];
bm::BindingResource::BufferArray(Borrowed(slice))
}
BindingResource::Sampler(sampler) => bm::BindingResource::Sampler(sampler.id),
BindingResource::TextureView(texture_view) => {
bm::BindingResource::TextureView(texture_view.id)
Expand Down
7 changes: 5 additions & 2 deletions src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1267,11 +1267,11 @@ impl crate::Context for Context {
.iter()
.map(|binding| {
let mapped_resource = match binding.resource {
crate::BindingResource::Buffer {
crate::BindingResource::Buffer(crate::BufferBinding {
ref buffer,
offset,
size,
} => {
}) => {
let mut mapped_buffer_binding =
web_sys::GpuBufferBinding::new(&buffer.id.0);
mapped_buffer_binding.offset(offset as f64);
Expand All @@ -1280,6 +1280,9 @@ impl crate::Context for Context {
}
JsValue::from(mapped_buffer_binding.clone())
}
crate::BindingResource::BufferArray(..) => {
panic!("Web backend does not support arrays of buffers")
}
crate::BindingResource::Sampler(ref sampler) => {
JsValue::from(sampler.id.0.clone())
}
Expand Down
40 changes: 28 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,17 +949,14 @@ pub enum BindingResource<'a> {
///
/// Corresponds to [`wgt::BufferBindingType::Uniform`] and [`wgt::BufferBindingType::Storage`]
/// with [`BindGroupLayoutEntry::count`] set to None.
Buffer {
/// The buffer to bind.
buffer: &'a Buffer,
/// Base offset of the buffer. For bindings with `dynamic == true`, this offset
/// will be added to the dynamic offset provided in [`RenderPass::set_bind_group`].
///
/// The offset has to be aligned to [`BIND_BUFFER_ALIGNMENT`].
offset: BufferAddress,
/// Size of the binding, or `None` for using the rest of the buffer.
size: Option<BufferSize>,
},
Buffer(BufferBinding<'a>),
/// Binding is backed by an array of buffers.
///
/// [`Features::BUFFER_BINDING_ARRAY`] must be supported to use this feature.
///
/// Corresponds to [`wgt::BufferBindingType::Uniform`] and [`wgt::BufferBindingType::Storage`]
/// with [`BindGroupLayoutEntry::count`] set to Some.
BufferArray(&'a [BufferBinding<'a>]),
/// Binding is a sampler.
///
/// Corresponds to [`wgt::BindingType::Sampler`] with [`BindGroupLayoutEntry::count`] set to None.
Expand All @@ -978,6 +975,20 @@ pub enum BindingResource<'a> {
TextureViewArray(&'a [&'a TextureView]),
}

/// Describes the segment of a buffer to bind.
#[derive(Clone, Debug)]
pub struct BufferBinding<'a> {
/// The buffer to bind.
pub buffer: &'a Buffer,
/// Base offset of the buffer. For bindings with `dynamic == true`, this offset
/// will be added to the dynamic offset provided in [`RenderPass::set_bind_group`].
///
/// The offset has to be aligned to [`BIND_BUFFER_ALIGNMENT`].
pub offset: BufferAddress,
/// Size of the binding, or `None` for using the rest of the buffer.
pub size: Option<BufferSize>,
}

/// Operation to perform to the output attachment at the start of a renderpass.
///
/// The render target must be cleared at least once before its content is loaded.
Expand Down Expand Up @@ -1833,7 +1844,12 @@ impl Drop for BufferViewMut<'_> {
impl Buffer {
/// Return the binding view of the entire buffer.
pub fn as_entire_binding(&self) -> BindingResource {
BindingResource::Buffer {
BindingResource::Buffer(self.as_entire_buffer_binding())
}

/// Return the binding view of the entire buffer.
pub fn as_entire_buffer_binding(&self) -> BufferBinding {
BufferBinding {
buffer: self,
offset: 0,
size: None,
Expand Down

0 comments on commit 5d2e88c

Please sign in to comment.