Skip to content

Commit

Permalink
Add multi draw indirect draw calls (#6392)
Browse files Browse the repository at this point in the history
# Objective

- Allows bevy users to dispatch `multi_draw_indirect`, `multi_draw_indexed_indirect`,  `multi_draw_indirect_count`, `multi_draw_indexed_indirect_count` draw calls.
- Fixes #6216

## Solution

- Added the corresponding wrapper methods to `TrackedRenderPass`

---

## Changelog

> Added  `multi_draw_*` draw calls to `TrackedRenderPass`


Co-authored-by: Zhixing Zhang <me@neoto.xin>
  • Loading branch information
Neo-Zhixing and Neo-Zhixing committed Oct 28, 2022
1 parent 306c1ac commit dd7ff88
Showing 1 changed file with 160 additions and 0 deletions.
160 changes: 160 additions & 0 deletions crates/bevy_render/src/render_phase/draw_state.rs
Expand Up @@ -283,6 +283,166 @@ impl<'a> TrackedRenderPass<'a> {
.draw_indexed_indirect(indirect_buffer, indirect_offset);
}

/// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
/// `count` draw calls are issued.
///
/// The active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
///
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// first_vertex: u32, // The Index of the first vertex to draw.
/// first_instance: u32, // The instance ID of the first instance to draw.
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
/// }
/// ```
pub fn multi_draw_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count: u32,
) {
trace!(
"multi draw indirect: {:?} {}, {}x",
indirect_buffer,
indirect_offset,
count
);
self.pass
.multi_draw_indirect(indirect_buffer, indirect_offset, count);
}

/// Dispatches 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` elements
/// will be read, where `count` is the value read from `count_buffer` capped at `max_count`.
///
/// The active vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
///
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// first_vertex: u32, // The Index of the first vertex to draw.
/// first_instance: u32, // The instance ID of the first instance to draw.
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
/// }
/// ```
pub fn multi_draw_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count_buffer: &'a Buffer,
count_offset: u64,
max_count: u32,
) {
trace!(
"multi draw indirect count: {:?} {}, ({:?} {})x, max {}x",
indirect_buffer,
indirect_offset,
count_buffer,
count_offset,
max_count
);
self.pass.multi_draw_indirect_count(
indirect_buffer,
indirect_offset,
count_buffer,
count_offset,
max_count,
);
}

/// Dispatches 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.
///
/// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the active
/// vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
///
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndexedIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// first_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.
/// first_instance: u32, // The instance ID of the first instance to draw.
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
/// }
/// ```
pub fn multi_draw_indexed_indirect(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count: u32,
) {
trace!(
"multi draw indexed indirect: {:?} {}, {}x",
indirect_buffer,
indirect_offset,
count
);
self.pass
.multi_draw_indexed_indirect(indirect_buffer, indirect_offset, count);
}

/// Dispatches 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` elements
/// will be read, where `count` is the value read from `count_buffer` capped at `max_count`.
///
/// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the active
/// vertex buffers can be set with [`TrackedRenderPass::set_vertex_buffer`].
///
/// `indirect_buffer` should contain `count` tightly packed elements of the following structure:
///
/// ```rust
/// #[repr(C)]
/// struct DrawIndexedIndirect {
/// vertex_count: u32, // The number of vertices to draw.
/// instance_count: u32, // The number of instances to draw.
/// first_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.
/// first_instance: u32, // The instance ID of the first instance to draw.
/// // has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`] is enabled.
/// }
/// ```
pub fn multi_draw_indexed_indirect_count(
&mut self,
indirect_buffer: &'a Buffer,
indirect_offset: u64,
count_buffer: &'a Buffer,
count_offset: u64,
max_count: u32,
) {
trace!(
"multi draw indexed indirect count: {:?} {}, ({:?} {})x, max {}x",
indirect_buffer,
indirect_offset,
count_buffer,
count_offset,
max_count
);
self.pass.multi_draw_indexed_indirect_count(
indirect_buffer,
indirect_offset,
count_buffer,
count_offset,
max_count,
);
}

/// Sets the stencil reference.
///
/// Subsequent stencil tests will test against this value.
Expand Down

0 comments on commit dd7ff88

Please sign in to comment.