GPUBatch: Add multi_draw_indirect capability and indirect buffer offset

This is for completion and to be used by the new draw manager.
This commit is contained in:
2022-08-30 21:57:39 +02:00
parent f5ea2a6434
commit 4944167dee
7 changed files with 61 additions and 13 deletions

View File

@@ -525,14 +525,14 @@ void DebugDraw::display_lines()
if (gpu_draw_buf_used) {
GPU_debug_group_begin("GPU");
GPU_storagebuf_bind(gpu_draw_buf_, slot);
GPU_batch_draw_indirect(batch, gpu_draw_buf_);
GPU_batch_draw_indirect(batch, gpu_draw_buf_, 0);
GPU_storagebuf_unbind(gpu_draw_buf_);
GPU_debug_group_end();
}
GPU_debug_group_begin("CPU");
GPU_storagebuf_bind(cpu_draw_buf_, slot);
GPU_batch_draw_indirect(batch, cpu_draw_buf_);
GPU_batch_draw_indirect(batch, cpu_draw_buf_, 0);
GPU_storagebuf_unbind(cpu_draw_buf_);
GPU_debug_group_end();
@@ -557,14 +557,14 @@ void DebugDraw::display_prints()
if (gpu_print_buf_used) {
GPU_debug_group_begin("GPU");
GPU_storagebuf_bind(gpu_print_buf_, slot);
GPU_batch_draw_indirect(batch, gpu_print_buf_);
GPU_batch_draw_indirect(batch, gpu_print_buf_, 0);
GPU_storagebuf_unbind(gpu_print_buf_);
GPU_debug_group_end();
}
GPU_debug_group_begin("CPU");
GPU_storagebuf_bind(cpu_print_buf_, slot);
GPU_batch_draw_indirect(batch, cpu_print_buf_);
GPU_batch_draw_indirect(batch, cpu_print_buf_, 0);
GPU_storagebuf_unbind(cpu_print_buf_);
GPU_debug_group_end();

View File

@@ -891,7 +891,7 @@ static void draw_call_indirect(DRWShadingGroup *shgroup,
}
GPU_batch_set_shader(batch, shgroup->shader);
GPU_batch_draw_indirect(batch, indirect_buf);
GPU_batch_draw_indirect(batch, indirect_buf, 0);
}
static void draw_call_batching_start(DRWCommandsState *state)

View File

@@ -187,7 +187,9 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi
* Issue a draw call using GPU computed arguments. The argument are expected to be valid for the
* type of geometry drawn (index or non-indexed).
*/
void GPU_batch_draw_indirect(GPUBatch *batch, GPUStorageBuf *indirect_buf);
void GPU_batch_draw_indirect(GPUBatch *batch, GPUStorageBuf *indirect_buf, intptr_t offset);
void GPU_batch_multi_draw_indirect(
GPUBatch *batch, GPUStorageBuf *indirect_buf, int count, intptr_t offset, intptr_t stride);
#if 0 /* future plans */

View File

@@ -294,13 +294,23 @@ void GPU_batch_draw_advanced(
batch->draw(v_first, v_count, i_first, i_count);
}
void GPU_batch_draw_indirect(GPUBatch *gpu_batch, GPUStorageBuf *indirect_buf)
void GPU_batch_draw_indirect(GPUBatch *gpu_batch, GPUStorageBuf *indirect_buf, intptr_t offset)
{
BLI_assert(Context::get()->shader != nullptr);
BLI_assert(indirect_buf != nullptr);
Batch *batch = static_cast<Batch *>(gpu_batch);
batch->draw_indirect(indirect_buf);
batch->draw_indirect(indirect_buf, offset);
}
void GPU_batch_multi_draw_indirect(
GPUBatch *gpu_batch, GPUStorageBuf *indirect_buf, int count, intptr_t offset, intptr_t stride)
{
BLI_assert(Context::get()->shader != nullptr);
BLI_assert(indirect_buf != nullptr);
Batch *batch = static_cast<Batch *>(gpu_batch);
batch->multi_draw_indirect(indirect_buf, count, offset, stride);
}
/** \} */

View File

@@ -29,7 +29,11 @@ class Batch : public GPUBatch {
virtual ~Batch() = default;
virtual void draw(int v_first, int v_count, int i_first, int i_count) = 0;
virtual void draw_indirect(GPUStorageBuf *indirect_buf) = 0;
virtual void draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset) = 0;
virtual void multi_draw_indirect(GPUStorageBuf *indirect_buf,
int count,
intptr_t offset,
intptr_t stride) = 0;
/* Convenience casts. */
IndexBuf *elem_() const

View File

@@ -327,12 +327,13 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
}
}
void GLBatch::draw_indirect(GPUStorageBuf *indirect_buf)
void GLBatch::draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset)
{
GL_CHECK_RESOURCES("Batch");
this->bind(0);
/* TODO(fclem): Make the barrier and binding optional if consecutive draws are issued. */
dynamic_cast<GLStorageBuf *>(unwrap(indirect_buf))->bind_as(GL_DRAW_INDIRECT_BUFFER);
/* This barrier needs to be here as it only work on the currently bound indirect buffer. */
glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
@@ -341,10 +342,37 @@ void GLBatch::draw_indirect(GPUStorageBuf *indirect_buf)
if (elem) {
const GLIndexBuf *el = this->elem_();
GLenum index_type = to_gl(el->index_type_);
glDrawElementsIndirect(gl_type, index_type, (GLvoid *)nullptr);
glDrawElementsIndirect(gl_type, index_type, (GLvoid *)offset);
}
else {
glDrawArraysIndirect(gl_type, (GLvoid *)nullptr);
glDrawArraysIndirect(gl_type, (GLvoid *)offset);
}
/* Unbind. */
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
}
void GLBatch::multi_draw_indirect(GPUStorageBuf *indirect_buf,
int count,
intptr_t offset,
intptr_t stride)
{
GL_CHECK_RESOURCES("Batch");
this->bind(0);
/* TODO(fclem): Make the barrier and binding optional if consecutive draws are issued. */
dynamic_cast<GLStorageBuf *>(unwrap(indirect_buf))->bind_as(GL_DRAW_INDIRECT_BUFFER);
/* This barrier needs to be here as it only work on the currently bound indirect buffer. */
glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
GLenum gl_type = to_gl(prim_type);
if (elem) {
const GLIndexBuf *el = this->elem_();
GLenum index_type = to_gl(el->index_type_);
glMultiDrawElementsIndirect(gl_type, index_type, (GLvoid *)offset, count, stride);
}
else {
glMultiDrawArraysIndirect(gl_type, (GLvoid *)offset, count, stride);
}
/* Unbind. */
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);

View File

@@ -91,7 +91,11 @@ class GLBatch : public Batch {
public:
void draw(int v_first, int v_count, int i_first, int i_count) override;
void draw_indirect(GPUStorageBuf *indirect_buf) override;
void draw_indirect(GPUStorageBuf *indirect_buf, intptr_t offset) override;
void multi_draw_indirect(GPUStorageBuf *indirect_buf,
int count,
intptr_t offset,
intptr_t stride) override;
void bind(int i_first);
/* Convenience getters. */