414: Implement MultiDrawIndirect Extensions r=kvark a=cwfitzgerald

The wgpu-rs component of https://github.com/gfx-rs/wgpu/pull/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>
This commit is contained in:
bors[bot]
2020-06-28 15:12:32 +00:00
committed by GitHub
4 changed files with 321 additions and 2 deletions

View File

@@ -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"

View File

@@ -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 {
@@ -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!()
}
}
}

View File

@@ -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 {

View File

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