DRW: Move procedural batch to GPUContext

This remove relying on a global for storing
the batch and allow for more streamlined usage
of procedural drawing.
This commit is contained in:
Clément Foucault
2025-02-12 17:24:31 +01:00
parent db920add50
commit c91d60cda5
9 changed files with 128 additions and 91 deletions

View File

@@ -102,10 +102,6 @@ struct VertShaded {
/* Batch's only (freed as an array). */
static struct DRWShapeCache {
blender::gpu::Batch *drw_procedural_verts;
blender::gpu::Batch *drw_procedural_lines;
blender::gpu::Batch *drw_procedural_tris;
blender::gpu::Batch *drw_procedural_tri_strips;
blender::gpu::Batch *drw_cursor;
blender::gpu::Batch *drw_cursor_only_circle;
blender::gpu::Batch *drw_quad;
@@ -125,71 +121,6 @@ void DRW_shape_cache_free()
/** \} */
/* -------------------------------------------------------------------- */
/** \name Procedural Batches
* \{ */
blender::gpu::Batch *drw_cache_procedural_points_get()
{
if (!SHC.drw_procedural_verts) {
/* TODO(fclem): get rid of this dummy VBO. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, 1);
SHC.drw_procedural_verts = GPU_batch_create_ex(
GPU_PRIM_POINTS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_procedural_verts;
}
blender::gpu::Batch *drw_cache_procedural_lines_get()
{
if (!SHC.drw_procedural_lines) {
/* TODO(fclem): get rid of this dummy VBO. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, 1);
SHC.drw_procedural_lines = GPU_batch_create_ex(
GPU_PRIM_LINES, vbo, nullptr, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_procedural_lines;
}
blender::gpu::Batch *drw_cache_procedural_triangles_get()
{
if (!SHC.drw_procedural_tris) {
/* TODO(fclem): get rid of this dummy VBO. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, 1);
SHC.drw_procedural_tris = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_procedural_tris;
}
blender::gpu::Batch *drw_cache_procedural_triangle_strips_get()
{
if (!SHC.drw_procedural_tri_strips) {
/* TODO(fclem): get rid of this dummy VBO. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, 1);
SHC.drw_procedural_tri_strips = GPU_batch_create_ex(
GPU_PRIM_TRI_STRIP, vbo, nullptr, GPU_BATCH_OWNS_VBO);
}
return SHC.drw_procedural_tri_strips;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Helper functions
* \{ */

View File

@@ -25,13 +25,13 @@ static gpu::Batch *procedural_batch_get(GPUPrimType primitive)
{
switch (primitive) {
case GPU_PRIM_POINTS:
return drw_cache_procedural_points_get();
return GPU_batch_procedural_points_get();
case GPU_PRIM_LINES:
return drw_cache_procedural_lines_get();
return GPU_batch_procedural_lines_get();
case GPU_PRIM_TRIS:
return drw_cache_procedural_triangles_get();
return GPU_batch_procedural_triangles_get();
case GPU_PRIM_TRI_STRIP:
return drw_cache_procedural_triangle_strips_get();
return GPU_batch_procedural_triangle_strips_get();
default:
/* Add new one as needed. */
BLI_assert_unreachable();

View File

@@ -240,7 +240,7 @@ void DebugDraw::display_lines()
command::StateSet::set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
gpu::Batch *batch = drw_cache_procedural_lines_get();
gpu::Batch *batch = GPU_batch_procedural_lines_get();
GPUShader *shader = DRW_shader_debug_draw_display_get();
GPU_batch_set_shader(batch, shader);
GPU_shader_uniform_mat4(shader, "persmat", persmat.ptr());

View File

@@ -617,13 +617,13 @@ template<class T> inline gpu::Batch *PassBase<T>::procedural_batch_get(GPUPrimTy
{
switch (primitive) {
case GPU_PRIM_POINTS:
return drw_cache_procedural_points_get();
return GPU_batch_procedural_points_get();
case GPU_PRIM_LINES:
return drw_cache_procedural_lines_get();
return GPU_batch_procedural_lines_get();
case GPU_PRIM_TRIS:
return drw_cache_procedural_triangles_get();
return GPU_batch_procedural_triangles_get();
case GPU_PRIM_TRI_STRIP:
return drw_cache_procedural_triangle_strips_get();
return GPU_batch_procedural_triangle_strips_get();
default:
/* Add new one as needed. */
BLI_assert_unreachable();

View File

@@ -432,6 +432,40 @@ blender::IndexRange GPU_batch_draw_expanded_parameter_get(GPUPrimType input_prim
/** \} */
/* -------------------------------------------------------------------- */
/** \name Procedural drawing
*
* A drawcall always need a batch to be issued.
* These are dummy batches that contains no vertex data and can be used to render geometry
* without per vertex inputs.
* \{ */
/**
* Batch with no attributes, suited for rendering procedural geometry.
* IMPORTANT: The returned batch is only valid for the current context.
*/
blender::gpu::Batch *GPU_batch_procedural_points_get();
/**
* Batch with no attributes, suited for rendering procedural geometry.
* IMPORTANT: The returned batch is only valid for the current context.
*/
blender::gpu::Batch *GPU_batch_procedural_lines_get();
/**
* Batch with no attributes, suited for rendering procedural geometry.
* IMPORTANT: The returned batch is only valid for the current context.
*/
blender::gpu::Batch *GPU_batch_procedural_triangles_get();
/**
* Batch with no attributes, suited for rendering procedural geometry.
* IMPORTANT: The returned batch is only valid for the current context.
*/
blender::gpu::Batch *GPU_batch_procedural_triangle_strips_get();
/** \} */
/* -------------------------------------------------------------------- */
/** \name Module init/exit
* \{ */

View File

@@ -385,7 +385,7 @@ static void polyline_draw_workaround(
GPU_batch_bind_as_resources(batch, batch->shader);
blender::IndexRange range = GPU_batch_draw_expanded_parameter_get(
batch->prim_type, GPU_PRIM_TRIS, vertex_count, vertex_first, 2);
Batch *tri_batch = Context::get()->polyline_batch_get();
Batch *tri_batch = Context::get()->procedural_triangles_batch_get();
GPU_batch_set_shader(tri_batch, batch->shader);
int vert_stride_count[3] = {(batch->prim_type == GPU_PRIM_LINES) ? 2 : 1, vertex_count, 0};
@@ -521,6 +521,26 @@ void GPU_batch_program_set_imm_shader(Batch *batch)
GPU_batch_set_shader(batch, immGetShader());
}
blender::gpu::Batch *GPU_batch_procedural_points_get()
{
return blender::gpu::Context::get()->procedural_points_batch_get();
}
blender::gpu::Batch *GPU_batch_procedural_lines_get()
{
return blender::gpu::Context::get()->procedural_lines_batch_get();
}
blender::gpu::Batch *GPU_batch_procedural_triangles_get()
{
return blender::gpu::Context::get()->procedural_triangles_batch_get();
}
blender::gpu::Batch *GPU_batch_procedural_triangle_strips_get()
{
return blender::gpu::Context::get()->procedural_triangle_strips_batch_get();
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -80,7 +80,11 @@ Context::~Context()
BLI_assert(back_right == nullptr);
GPU_matrix_state_discard(matrix_state);
GPU_BATCH_DISCARD_SAFE(polyline_batch);
GPU_BATCH_DISCARD_SAFE(procedural_points_batch);
GPU_BATCH_DISCARD_SAFE(procedural_lines_batch);
GPU_BATCH_DISCARD_SAFE(procedural_triangles_batch);
GPU_BATCH_DISCARD_SAFE(procedural_triangle_strips_batch);
GPU_VERTBUF_DISCARD_SAFE(dummy_vbo);
delete texture_pool;
delete state_manager;
delete imm;
@@ -109,20 +113,59 @@ Context *Context::get()
return active_ctx;
}
Batch *Context::polyline_batch_get()
VertBuf *Context::dummy_vbo_get()
{
if (polyline_batch) {
return polyline_batch;
if (this->dummy_vbo) {
return this->dummy_vbo;
}
/* TODO(fclem): get rid of this dummy VBO. */
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, 1);
this->dummy_vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*this->dummy_vbo, 1);
return this->dummy_vbo;
}
polyline_batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
return polyline_batch;
Batch *Context::procedural_points_batch_get()
{
if (procedural_points_batch) {
return procedural_points_batch;
}
procedural_points_batch = GPU_batch_create(GPU_PRIM_POINTS, dummy_vbo_get(), nullptr);
return procedural_points_batch;
}
Batch *Context::procedural_lines_batch_get()
{
if (procedural_lines_batch) {
return procedural_lines_batch;
}
procedural_lines_batch = GPU_batch_create(GPU_PRIM_LINES, dummy_vbo_get(), nullptr);
return procedural_lines_batch;
}
Batch *Context::procedural_triangles_batch_get()
{
if (procedural_triangles_batch) {
return procedural_triangles_batch;
}
procedural_triangles_batch = GPU_batch_create(GPU_PRIM_TRIS, dummy_vbo_get(), nullptr);
return procedural_triangles_batch;
}
Batch *Context::procedural_triangle_strips_batch_get()
{
if (procedural_triangle_strips_batch) {
return procedural_triangle_strips_batch;
}
procedural_triangle_strips_batch = GPU_batch_create(
GPU_PRIM_TRI_STRIP, dummy_vbo_get(), nullptr);
return procedural_triangle_strips_batch;
}
} // namespace blender::gpu

View File

@@ -65,8 +65,13 @@ class Context {
/* Used as a stack. Each render_begin/end pair will push pop from the stack. */
Vector<GPUStorageBuf *> printf_buf;
/** Dummy triangle batch for polyline workaround. */
Batch *polyline_batch = nullptr;
/** Dummy VBO to feed the procedural batches. */
VertBuf *dummy_vbo = nullptr;
/** Dummy batches for procedural geometry rendering. */
Batch *procedural_points_batch = nullptr;
Batch *procedural_lines_batch = nullptr;
Batch *procedural_triangles_batch = nullptr;
Batch *procedural_triangle_strips_batch = nullptr;
/** Texture pool used to recycle temporary texture (or render target) memory. */
TexturePool *texture_pool = nullptr;
@@ -113,7 +118,11 @@ class Context {
bool is_active_on_thread();
Batch *polyline_batch_get();
VertBuf *dummy_vbo_get();
Batch *procedural_points_batch_get();
Batch *procedural_lines_batch_get();
Batch *procedural_triangles_batch_get();
Batch *procedural_triangle_strips_batch_get();
/* When using `--debug-gpu`, assert that the shader fragments write to all the writable
* attachments of the bound frame-buffer. */

View File

@@ -284,7 +284,7 @@ void Immediate::polyline_draw_workaround(uint64_t offset)
/* Check compatible input primitive. */
BLI_assert(ELEM(imm->prim_type, GPU_PRIM_LINES, GPU_PRIM_LINE_STRIP, GPU_PRIM_LINE_LOOP));
Batch *tri_batch = Context::get()->polyline_batch_get();
Batch *tri_batch = Context::get()->procedural_triangles_batch_get();
GPU_batch_set_shader(tri_batch, imm->shader);
BLI_assert(offset % 4 == 0);