From ac8aeb3173fb8a91e759742d1471f1df8c7a4a8e Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Thu, 27 Oct 2022 18:41:05 -0700 Subject: [PATCH 1/3] Add multi draw indirect draw calls --- .../src/render_phase/draw_state.rs | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/crates/bevy_render/src/render_phase/draw_state.rs b/crates/bevy_render/src/render_phase/draw_state.rs index a709c078f921d..0c69eab986b28 100644 --- a/crates/bevy_render/src/render_phase/draw_state.rs +++ b/crates/bevy_render/src/render_phase/draw_state.rs @@ -283,6 +283,128 @@ 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); + } + + /// 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. + /// + /// 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` will + /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used. + /// + /// 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. From fc575352442f4b7038439d23dae5790eda891d03 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Thu, 27 Oct 2022 18:53:58 -0700 Subject: [PATCH 2/3] cargo fmt --- .../src/render_phase/draw_state.rs | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/crates/bevy_render/src/render_phase/draw_state.rs b/crates/bevy_render/src/render_phase/draw_state.rs index 0c69eab986b28..7dcbb1003b7d4 100644 --- a/crates/bevy_render/src/render_phase/draw_state.rs +++ b/crates/bevy_render/src/render_phase/draw_state.rs @@ -300,14 +300,20 @@ impl<'a> TrackedRenderPass<'a> { /// // 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) { + 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); + self.pass + .multi_draw_indirect(indirect_buffer, indirect_offset, count); } /// Disptaches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`. @@ -330,7 +336,14 @@ impl<'a> TrackedRenderPass<'a> { /// // 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) { + 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, @@ -339,7 +352,13 @@ impl<'a> TrackedRenderPass<'a> { count_offset, max_count ); - self.pass.multi_draw_indirect_count(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, @@ -361,14 +380,20 @@ impl<'a> TrackedRenderPass<'a> { /// // 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) { + 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); + 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, @@ -393,7 +418,14 @@ impl<'a> TrackedRenderPass<'a> { /// // 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) { + 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, @@ -402,7 +434,13 @@ impl<'a> TrackedRenderPass<'a> { count_offset, max_count ); - self.pass.multi_draw_indexed_indirect_count(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. From 33ea1fc57111293c684086fe2631c7df3f87de15 Mon Sep 17 00:00:00 2001 From: Zhixing Zhang Date: Fri, 28 Oct 2022 15:15:56 -0700 Subject: [PATCH 3/3] revise comments --- crates/bevy_render/src/render_phase/draw_state.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_render/src/render_phase/draw_state.rs b/crates/bevy_render/src/render_phase/draw_state.rs index 7dcbb1003b7d4..4d4a68b5c9c15 100644 --- a/crates/bevy_render/src/render_phase/draw_state.rs +++ b/crates/bevy_render/src/render_phase/draw_state.rs @@ -316,11 +316,11 @@ impl<'a> TrackedRenderPass<'a> { .multi_draw_indirect(indirect_buffer, indirect_offset, count); } - /// Disptaches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`. + /// 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` will - /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used. + /// 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`]. /// @@ -399,8 +399,8 @@ impl<'a> TrackedRenderPass<'a> { /// 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` will - /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used. + /// 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`].