Skip to content
This repository has been archived by the owner on Jun 18, 2021. It is now read-only.

Commit

Permalink
Merge #414
Browse files Browse the repository at this point in the history
414: Implement MultiDrawIndirect Extensions r=kvark a=cwfitzgerald

The wgpu-rs component of gfx-rs/wgpu#754.

I didn't include the modifications to the example as they are particularly awful and ugly. One of my next steps following this is to make an example of both binding indexing and these multi-draw extensions.

Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
  • Loading branch information
bors[bot] and cwfitzgerald authored Jun 28, 2020
2 parents 18be98d + cc5ff8e commit 6309dc2
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ vulkan = ["wgc/gfx-backend-vulkan"]
package = "wgpu-core"
version = "0.5"
git = "https://github.com/gfx-rs/wgpu"
rev = "3b6e128877d74f8310967e377c5193fd4105ee13"
rev = "43c67ac59c2dedaa4d78601bc460aab7c3257973"
features = ["raw-window-handle"]

[dependencies.wgt]
package = "wgpu-types"
version = "0.5"
git = "https://github.com/gfx-rs/wgpu"
rev = "3b6e128877d74f8310967e377c5193fd4105ee13"
rev = "43c67ac59c2dedaa4d78601bc460aab7c3257973"

[dependencies]
arrayvec = "0.5"
Expand Down
91 changes: 91 additions & 0 deletions src/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,61 @@ mod pass_impl {
) {
wgpu_render_pass_draw_indexed_indirect(self, *indirect_buffer, indirect_offset)
}
fn multi_draw_indirect(
&mut self,
indirect_buffer: &wgc::id::BufferId,
indirect_offset: wgt::BufferAddress,
count: u32,
) {
wgpu_render_pass_multi_draw_indirect(self, *indirect_buffer, indirect_offset, count)
}
fn multi_draw_indexed_indirect(
&mut self,
indirect_buffer: &wgc::id::BufferId,
indirect_offset: wgt::BufferAddress,
count: u32,
) {
wgpu_render_pass_multi_draw_indexed_indirect(
self,
*indirect_buffer,
indirect_offset,
count,
)
}
fn multi_draw_indirect_count(
&mut self,
indirect_buffer: &wgc::id::BufferId,
indirect_offset: wgt::BufferAddress,
count_buffer: &wgc::id::BufferId,
count_buffer_offset: wgt::BufferAddress,
max_count: u32,
) {
wgpu_render_pass_multi_draw_indirect_count(
self,
*indirect_buffer,
indirect_offset,
*count_buffer,
count_buffer_offset,
max_count,
)
}
fn multi_draw_indexed_indirect_count(
&mut self,
indirect_buffer: &wgc::id::BufferId,
indirect_offset: wgt::BufferAddress,
count_buffer: &wgc::id::BufferId,
count_buffer_offset: wgt::BufferAddress,
max_count: u32,
) {
wgpu_render_pass_multi_draw_indexed_indirect_count(
self,
*indirect_buffer,
indirect_offset,
*count_buffer,
count_buffer_offset,
max_count,
)
}
}

impl crate::RenderPassInner<Context> for wgc::command::RenderPass {
Expand Down Expand Up @@ -266,6 +321,42 @@ mod pass_impl {
) {
wgpu_render_pass_bundle_indexed_indirect(self, *indirect_buffer, indirect_offset)
}
fn multi_draw_indirect(
&mut self,
_indirect_buffer: &wgc::id::BufferId,
_indirect_offset: wgt::BufferAddress,
_count: u32,
) {
unimplemented!()
}
fn multi_draw_indexed_indirect(
&mut self,
_indirect_buffer: &wgc::id::BufferId,
_indirect_offset: wgt::BufferAddress,
_count: u32,
) {
unimplemented!()
}
fn multi_draw_indirect_count(
&mut self,
_indirect_buffer: &wgc::id::BufferId,
_indirect_offset: wgt::BufferAddress,
_count_buffer: &wgc::id::BufferId,
_count_buffer_offset: wgt::BufferAddress,
_max_count: u32,
) {
unimplemented!()
}
fn multi_draw_indexed_indirect_count(
&mut self,
_indirect_buffer: &wgc::id::BufferId,
_indirect_offset: wgt::BufferAddress,
_count_buffer: &wgc::id::BufferId,
_count_buffer_offset: wgt::BufferAddress,
_max_count: u32,
) {
unimplemented!()
}
}
}

Expand Down
38 changes: 38 additions & 0 deletions src/backend/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,44 @@ impl crate::RenderInner<Context> for RenderPass {
self.0
.draw_indexed_indirect_with_f64(&indirect_buffer.0, indirect_offset as f64);
}
fn multi_draw_indirect(
&mut self,
_indirect_buffer: &Sendable<web_sys::GpuBuffer>,
_indirect_offset: wgt::BufferAddress,
_count: u32,
) {
panic!("MULTI_DRAW_INDIRECT feature must be enabled to call multi_draw_indirect")
}
fn multi_draw_indexed_indirect(
&mut self,
_indirect_buffer: &Sendable<web_sys::GpuBuffer>,
_indirect_offset: wgt::BufferAddress,
_count: u32,
) {
panic!("MULTI_DRAW_INDIRECT feature must be enabled to call multi_draw_indexed_indirect")
}
fn multi_draw_indirect_count(
&mut self,
_indirect_buffer: &Sendable<web_sys::GpuBuffer>,
_indirect_offset: wgt::BufferAddress,
_count_buffer: &Sendable<web_sys::GpuBuffer>,
_count_buffer_offset: wgt::BufferAddress,
_max_count: u32,
) {
panic!(
"MULTI_DRAW_INDIRECT_COUNT feature must be enabled to call multi_draw_indirect_count"
)
}
fn multi_draw_indexed_indirect_count(
&mut self,
_indirect_buffer: &Sendable<web_sys::GpuBuffer>,
_indirect_offset: wgt::BufferAddress,
_count_buffer: &Sendable<web_sys::GpuBuffer>,
_count_buffer_offset: wgt::BufferAddress,
_max_count: u32,
) {
panic!("MULTI_DRAW_INDIRECT_COUNT feature must be enabled to call multi_draw_indexed_indirect_count")
}
}

impl crate::RenderPassInner<Context> for RenderPass {
Expand Down
190 changes: 190 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,34 @@ trait RenderInner<Ctx: Context> {
indirect_buffer: &Ctx::BufferId,
indirect_offset: BufferAddress,
);
fn multi_draw_indirect(
&mut self,
indirect_buffer: &Ctx::BufferId,
indirect_offset: BufferAddress,
count: u32,
);
fn multi_draw_indexed_indirect(
&mut self,
indirect_buffer: &Ctx::BufferId,
indirect_offset: BufferAddress,
count: u32,
);
fn multi_draw_indirect_count(
&mut self,
indirect_buffer: &Ctx::BufferId,
indirect_offset: BufferAddress,
count_buffer: &Ctx::BufferId,
count_buffer_offset: BufferAddress,
max_count: u32,
);
fn multi_draw_indexed_indirect_count(
&mut self,
indirect_buffer: &Ctx::BufferId,
indirect_offset: BufferAddress,
count_buffer: &Ctx::BufferId,
count_buffer_offset: BufferAddress,
max_count: u32,
);
}

trait RenderPassInner<Ctx: Context>: RenderInner<Ctx> {
Expand Down Expand Up @@ -1850,6 +1878,168 @@ impl<'a> RenderPass<'a> {
.draw_indexed_indirect(&indirect_buffer.id, indirect_offset);
}

/// Disptaches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
/// `count` draw calls are issued.
///
/// [`Features::MULTI_DRAW_INDIRECT`] must be enabled on the device in order to call this function.
///
/// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
///
/// The structure expected in `indirect_buffer` is the following:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// base_vertex: u32, // The Index of the first vertex to draw.
/// base_instance: u32, // The instance ID of the first instance to draw.
/// }
/// ```
///
/// These draw structures are expected to be tightly packed.
pub fn multi_draw_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
count: u32,
) {
self.id
.multi_draw_indirect(&indirect_buffer.id, indirect_offset, count);
}

/// Disptaches multiple draw calls from the active index buffer and the active vertex buffers,
/// based on the contents of the `indirect_buffer`. `count` draw calls are issued.
///
/// [`Features::MULTI_DRAW_INDIRECT`] must be enabled on the device in order to call this function.
///
/// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
/// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
///
/// The structure expected in `indirect_buffer` is the following:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndexedIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// base_index: u32, // The base index within the index buffer.
/// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
/// base_instance: u32, // The instance ID of the first instance to draw.
/// }
/// ```
///
/// These draw structures are expected to be tightly packed.
pub fn multi_draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
count: u32,
) {
self.id
.multi_draw_indexed_indirect(&indirect_buffer.id, indirect_offset, count);
}

/// Disptaches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
/// The count buffer is read to determine how many draws to issue.
///
/// The indirect buffer must be long enough to account for `max_count` draws, however only `count` will
/// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
///
/// [`Features::MULTI_DRAW_INDIRECT_COUNT`] must be enabled on the device in order to call this function.
///
/// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
///
/// The structure expected in `indirect_buffer` is the following:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// base_vertex: u32, // The Index of the first vertex to draw.
/// base_instance: u32, // The instance ID of the first instance to draw.
/// }
/// ```
///
/// These draw structures are expected to be tightly packed.
///
/// The structure expected in `count_buffer` is the following:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndirectCount {
/// count: u32, // Number of draw calls to issue.
/// }
/// ```
pub fn multi_draw_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
count_buffer: &'a Buffer,
count_offset: BufferAddress,
max_count: u32,
) {
self.id.multi_draw_indirect_count(
&indirect_buffer.id,
indirect_offset,
&count_buffer.id,
count_offset,
max_count,
);
}

/// Disptaches multiple draw calls from the active index buffer and the active vertex buffers,
/// based on the contents of the `indirect_buffer`. The count buffer is read to determine how many draws to issue.
///
/// The indirect buffer must be long enough to account for `max_count` draws, however only `count` will
/// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
///
/// [`Features::MULTI_DRAW_INDIRECT_COUNT`] must be enabled on the device in order to call this function.
///
/// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
/// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
///
/// The structure expected in `indirect_buffer` is the following:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndexedIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// base_index: u32, // The base index within the index buffer.
/// vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
/// base_instance: u32, // The instance ID of the first instance to draw.
/// }
/// ```
///
/// These draw structures are expected to be tightly packed.
///
/// The structure expected in `count_buffer` is the following:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndexedIndirectCount {
/// count: u32, // Number of draw calls to issue.
/// }
/// ```
pub fn multi_draw_indexed_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: BufferAddress,
count_buffer: &'a Buffer,
count_offset: BufferAddress,
max_count: u32,
) {
self.id.multi_draw_indexed_indirect_count(
&indirect_buffer.id,
indirect_offset,
&count_buffer.id,
count_offset,
max_count,
);
}

/// Execute a [render bundle][RenderBundle], which is a set of pre-recorded commands
/// that can be run together.
pub fn execute_bundles<I: Iterator<Item = &'a RenderBundle>>(&mut self, render_bundles: I) {
Expand Down

0 comments on commit 6309dc2

Please sign in to comment.