me-main #1

Merged
Nate Rupsis merged 123 commits from me-main into main 2023-02-13 18:39:11 +01:00
11 changed files with 280 additions and 170 deletions
Showing only changes of commit 7e0e07657c - Show all commits

View File

@ -507,7 +507,7 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
if (!GPU_batch_vertbuf_has(batch, vbo)) {
/* Currently, the code assumes that all objects that share the same mesh in the
* current frame also share the same mesh on other frames. */
GPU_batch_vertbuf_add_ex(batch, vbo, false);
GPU_batch_vertbuf_add(batch, vbo, false);
}
}
}

View File

@ -904,10 +904,10 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
/* Create the batches */
cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, nullptr);
GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo);
GPU_batch_vertbuf_add(cache->edit_points_batch, cache->edit_vbo, false);
cache->edit_lines_batch = GPU_batch_create(GPU_PRIM_LINE_STRIP, cache->vbo, nullptr);
GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo);
GPU_batch_vertbuf_add(cache->edit_lines_batch, cache->edit_vbo, false);
}
/* Curve Handles and Points for Editing. */
@ -941,11 +941,11 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
cache->edit_curve_handles_batch = GPU_batch_create(
GPU_PRIM_LINES, cache->edit_curve_vbo, nullptr);
GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo);
GPU_batch_vertbuf_add(cache->edit_curve_handles_batch, cache->edit_curve_vbo, false);
cache->edit_curve_points_batch = GPU_batch_create(
GPU_PRIM_POINTS, cache->edit_curve_vbo, nullptr);
GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo);
GPU_batch_vertbuf_add(cache->edit_curve_points_batch, cache->edit_curve_vbo, false);
}
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;

View File

@ -197,7 +197,7 @@ static void drw_volume_wireframe_cb(
GPU_PRIM_LINES, cache->face_wire.pos_nor_in_order, ibo, GPU_BATCH_OWNS_INDEX);
}
GPU_batch_vertbuf_add_ex(cache->face_wire.batch, vbo_wiredata, true);
GPU_batch_vertbuf_add(cache->face_wire.batch, vbo_wiredata, true);
}
GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)

View File

@ -71,7 +71,7 @@ BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
}
if (batch != NULL) {
/* HACK we set VBO's that may not yet be valid. */
GPU_batch_vertbuf_add(batch, *vbo);
GPU_batch_vertbuf_add(batch, *vbo, false);
}
}

View File

@ -226,11 +226,11 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
GPU_batch_copy(batch, geom);
if (inst_batch != NULL) {
for (int i = 0; i < GPU_BATCH_INST_VBO_MAX_LEN && inst_batch->verts[i]; i++) {
GPU_batch_instbuf_add_ex(batch, inst_batch->verts[i], false);
GPU_batch_instbuf_add(batch, inst_batch->verts[i], false);
}
}
else {
GPU_batch_instbuf_add_ex(batch, inst_buf, false);
GPU_batch_instbuf_add(batch, inst_buf, false);
}
/* Add reference to avoid comparing pointers (in DRW_temp_batch_request) that could
* potentially be the same. This will delay the freeing of the GPUVertBuf itself. */

View File

@ -1303,10 +1303,10 @@ struct PBVHBatches {
int vbo_i = get_vbo_index(vbo);
batch.vbos.append(vbo_i);
GPU_batch_vertbuf_add_ex(batch.tris, vbo->vert_buf, false);
GPU_batch_vertbuf_add(batch.tris, vbo->vert_buf, false);
if (batch.lines) {
GPU_batch_vertbuf_add_ex(batch.lines, vbo->vert_buf, false);
GPU_batch_vertbuf_add(batch.lines, vbo->vert_buf, false);
}
}

View File

@ -1630,7 +1630,7 @@ static void icon_draw_cache_texture_flush_ex(GPUTexture *texture,
GPUBatch *quad = GPU_batch_preset_quad();
GPU_batch_set_shader(quad, shader);
GPU_batch_draw_instanced(quad, texture_draw_calls->calls);
GPU_batch_draw_instance_range(quad, 0, texture_draw_calls->calls);
GPU_texture_unbind(texture);
GPU_uniformbuf_unbind(ubo);

View File

@ -1157,7 +1157,7 @@ void UI_widgetbase_draw_cache_flush()
MAX_WIDGET_PARAMETERS * MAX_WIDGET_BASE_BATCH,
(float(*)[4])g_widget_base_batch.params);
GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
GPU_batch_draw_instanced(batch, g_widget_base_batch.count);
GPU_batch_draw_instance_range(batch, 0, g_widget_base_batch.count);
}
g_widget_base_batch.count = 0;
}

View File

@ -4,8 +4,15 @@
/** \file
* \ingroup gpu
*
* GPU geometry batch
* Contains VAOs + VBOs + Shader representing a drawable entity.
* GPU geometry batch.
*
* Contains Vertex Buffers, Index Buffers, and Shader reference, altogether representing a drawable
* entity. It is meant to be used for drawing large (> 1000 vertices) reusable (drawn multiple
* times) model with complex data layout. In other words, it is meant for all cases where the
* immediate drawing module (imm) is inadequate.
*
* Vertex & Index Buffers can be owned by a batch. In such case they will be freed when the batch
* gets cleared or discarded.
*/
#pragma once
@ -60,7 +67,8 @@ extern "C" {
/**
* IMPORTANT: Do not allocate manually as the real struct is bigger (i.e: GLBatch). This is only
* the common and "public" part of the struct. Use the provided allocator.
* the common and "public" part of the struct. Use `GPU_batch_calloc()` and `GPU_batch_create()`
* instead.
* TODO(fclem): Make the content of this struct hidden and expose getters/setters.
*/
typedef struct GPUBatch {
@ -80,75 +88,163 @@ typedef struct GPUBatch {
struct GPUShader *shader;
} GPUBatch;
/* -------------------------------------------------------------------- */
/** \name Creation
* \{ */
/**
* Allocate a #GPUBatch with a cleared state.
* The returned #GPUBatch needs to be passed to `GPU_batch_init` before being usable.
*/
GPUBatch *GPU_batch_calloc(void);
GPUBatch *GPU_batch_create_ex(GPUPrimType prim,
GPUVertBuf *vert,
GPUIndexBuf *elem,
eGPUBatchFlag owns_flag);
void GPU_batch_init_ex(GPUBatch *batch,
GPUPrimType prim,
GPUVertBuf *vert,
GPUIndexBuf *elem,
/**
* Creates a #GPUBatch with explicit buffer ownership.
*/
GPUBatch *GPU_batch_create_ex(GPUPrimType primitive_type,
GPUVertBuf *vertex_buf,
GPUIndexBuf *index_buf,
eGPUBatchFlag owns_flag);
/**
* Creates a #GPUBatch without buffer ownership.
*/
#define GPU_batch_create(primitive_type, vertex_buf, index_buf) \
GPU_batch_create_ex(primitive_type, vertex_buf, index_buf, (eGPUBatchFlag)0)
/**
* Initialize a cleared #GPUBatch with explicit buffer ownership.
* A #GPUBatch is in cleared state if it was just allocated using `GPU_batch_calloc()` or cleared
* using `GPU_batch_clear()`.
*/
void GPU_batch_init_ex(GPUBatch *batch,
GPUPrimType primitive_type,
GPUVertBuf *vertex_buf,
GPUIndexBuf *index_buf,
eGPUBatchFlag owns_flag);
/**
* Initialize a cleared #GPUBatch without buffer ownership.
* A #GPUBatch is in cleared state if it was just allocated using `GPU_batch_calloc()` or cleared
* using `GPU_batch_clear()`.
*/
#define GPU_batch_init(batch, primitive_type, vertex_buf, index_buf) \
GPU_batch_init_ex(batch, primitive_type, vertex_buf, index_buf, (eGPUBatchFlag)0)
/**
* DEPRECATED: It is easy to loose ownership with this. To be removed.
* This will share the VBOs with the new batch.
*/
void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src);
#define GPU_batch_create(prim, verts, elem) \
GPU_batch_create_ex(prim, verts, elem, (eGPUBatchFlag)0)
#define GPU_batch_init(batch, prim, verts, elem) \
GPU_batch_init_ex(batch, prim, verts, elem, (eGPUBatchFlag)0)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Deletion
* \{ */
/**
* Same as discard but does not free. (does not call free callback).
* Clear a #GPUBatch without freeing its own memory.
* The #GPUBatch can then be reused using `GPU_batch_init()`.
* Discards all owned vertex and index buffers.
*/
void GPU_batch_clear(GPUBatch *);
void GPU_batch_clear(GPUBatch *batch);
#define GPU_BATCH_CLEAR_SAFE(batch) \
do { \
if (batch != NULL) { \
GPU_batch_clear(batch); \
memset(batch, 0, sizeof(*(batch))); \
} \
} while (0)
/**
* \note Verts & elem are not discarded.
* Free a #GPUBatch object.
* Discards all owned vertex and index buffers.
*/
void GPU_batch_discard(GPUBatch *);
void GPU_batch_discard(GPUBatch *batch);
#define GPU_BATCH_DISCARD_SAFE(batch) \
do { \
if (batch != NULL) { \
GPU_batch_discard(batch); \
batch = NULL; \
} \
} while (0)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Buffers Management
* \{ */
/**
* Add the given \a vertex_buf as vertex buffer to a #GPUBatch.
* \return the index of verts in the batch.
*/
int GPU_batch_vertbuf_add(GPUBatch *batch, GPUVertBuf *vertex_buf, bool own_vbo);
/**
* Add the given \a vertex_buf as instanced vertex buffer to a #GPUBatch.
* \return the index of verts in the batch.
*/
int GPU_batch_instbuf_add(GPUBatch *batch, GPUVertBuf *vertex_buf, bool own_vbo);
/**
* Set the first instanced vertex buffer of a #GPUBatch.
* \note Override ONLY the first instance VBO (and free them if owned).
*/
void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancing */
void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *vertex_buf, bool own_vbo);
/**
* \note Override any previously assigned elem (and free it if owned).
* Set the index buffer of a #GPUBatch.
* \note Override any previously assigned index buffer (and free it if owned).
*/
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo);
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *index_buf, bool own_ibo);
int GPU_batch_instbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
/**
* Returns the index of verts in the batch.
* Returns true if the #GPUbatch has \a vertex_buf in its vertex buffer list.
* \note The search is only conducted on the non-instance rate vertex buffer list.
*/
int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
bool GPU_batch_vertbuf_has(GPUBatch *, GPUVertBuf *);
#define GPU_batch_vertbuf_add(batch, verts) GPU_batch_vertbuf_add_ex(batch, verts, false)
bool GPU_batch_vertbuf_has(GPUBatch *batch, GPUVertBuf *vertex_buf);
/**
* Set resource id buffer to bind as instance attribute to workaround the lack of gl_BaseInstance.
* Set resource id buffer to bind as instance attribute to workaround the lack of gl_BaseInstance
* on some hardware / platform.
* \note Only to be used by draw manager.
*/
void GPU_batch_resource_id_buf_set(GPUBatch *batch, GPUStorageBuf *resource_id_buf);
void GPU_batch_set_shader(GPUBatch *batch, GPUShader *shader);
/**
* Bind program bound to IMM to the batch.
/** \} */
/* -------------------------------------------------------------------- */
/** \name Shader Binding & Uniforms
*
* XXX Use this with much care. Drawing with the #GPUBatch API is not compatible with IMM.
* DO NOT DRAW WITH THE BATCH BEFORE CALLING #immUnbindProgram.
* TODO(fclem): This whole section should be removed. See the other `TODO`s in this section.
* This is because we want to remove #GPUBatch.shader to avoid usage mistakes.
* Interacting directly with the #GPUShader provide a clearer interface and less error-prone.
* \{ */
/**
* Sets the shader to be drawn with this #GPUBatch.
* \note This need to be called first for the `GPU_batch_uniform_*` functions to work.
*/
void GPU_batch_program_set_imm_shader(GPUBatch *batch);
/* TODO(fclem): These should be removed and replaced by `GPU_shader_bind()`. */
void GPU_batch_set_shader(GPUBatch *batch, GPUShader *shader);
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id);
void GPU_batch_program_set_builtin_with_config(GPUBatch *batch,
eGPUBuiltinShader shader_id,
eGPUShaderConfig sh_cfg);
/**
* Bind program bound to IMM (immediate mode) to the #GPUBatch.
*
* XXX: Use this with much care. Drawing with the #GPUBatch API is not compatible with IMM.
* DO NOT DRAW WITH THE BATCH BEFORE CALLING #immUnbindProgram.
*/
void GPU_batch_program_set_imm_shader(GPUBatch *batch);
/* Will only work after setting the batch program. */
/**
* Set uniform variables for the shader currently bound to the #GPUBatch.
*/
/* TODO(fclem): These need to be replaced by GPU_shader_uniform_* with explicit shader. */
#define GPU_batch_uniform_1i(batch, name, x) GPU_shader_uniform_1i((batch)->shader, name, x);
#define GPU_batch_uniform_1b(batch, name, x) GPU_shader_uniform_1b((batch)->shader, name, x);
#define GPU_batch_uniform_1f(batch, name, x) GPU_shader_uniform_1f((batch)->shader, name, x);
@ -171,99 +267,105 @@ void GPU_batch_program_set_builtin_with_config(GPUBatch *batch,
#define GPU_batch_texture_bind(batch, name, tex) \
GPU_texture_bind(tex, GPU_shader_get_texture_binding((batch)->shader, name));
/**
* Return indirect draw call parameters for this batch.
* NOTE: r_base_index is set to -1 if not using an index buffer.
*/
void GPU_batch_draw_parameter_get(
GPUBatch *batch, int *r_v_count, int *r_v_first, int *r_base_index, int *r_i_count);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Shader Binding & Uniforms
* \{ */
/**
* Draw the #GPUBatch with vertex count and instance count from its vertex buffers lengths.
* Ensures the associated shader is bound. TODO(fclem) remove this behavior.
*/
void GPU_batch_draw(GPUBatch *batch);
void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count);
/**
* Draw multiple instance of a batch without having any instance attributes.
*/
void GPU_batch_draw_instanced(GPUBatch *batch, int i_count);
/**
* This does not bind/unbind shader and does not call GPU_matrix_bind().
* Draw the #GPUBatch with vertex count and instance count from its vertex buffers lengths.
* Ensures the associated shader is bound. TODO(fclem) remove this behavior.
*
* A \a vertex_count of 0 will use the default number of vertex.
* The \a vertex_first sets the start of the instance-rate attributes.
*
* \note No out-of-bound access check is made on the vertex buffers since they are tricky to
* detect. Double check that the range of vertex has data or that the data isn't read by the
* shader.
*/
void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count);
void GPU_batch_draw_range(GPUBatch *batch, int vertex_first, int vertex_count);
/**
* 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).
* Draw multiple instances of the #GPUBatch with custom instance range.
* Ensures the associated shader is bound. TODO(fclem) remove this behavior.
*
* An \a instance_count of 0 will use the default number of instances.
* The \a instance_first sets the start of the instance-rate attributes.
*
* \note this can be used even if the #GPUBatch contains no instance-rate attributes.
* \note No out-of-bound access check is made on the vertex buffers since they are tricky to
* detect. Double check that the range of vertex has data or that the data isn't read by the
* shader.
*/
void GPU_batch_draw_instance_range(GPUBatch *batch, int instance_first, int instance_count);
/**
* Draw the #GPUBatch custom parameters.
* IMPORTANT: This does not bind/unbind shader and does not call GPU_matrix_bind().
*
* A \a vertex_count of 0 will use the default number of vertex.
* An \a instance_count of 0 will use the default number of instances.
*
* \note No out-of-bound access check is made on the vertex buffers since they are tricky to
* detect. Double check that the range of vertex has data or that the data isn't read by the
* shader.
*/
void GPU_batch_draw_advanced(
GPUBatch *batch, int vertex_first, int vertex_count, int instance_first, int instance_count);
/**
* Issue a single draw call using arguments sourced from a #GPUStorageBuf.
* The argument are expected to be valid for the type of geometry contained by this #GPUBatch
* (index or non-indexed).
*
* A `GPU_BARRIER_COMMAND` memory barrier is automatically added before the call.
*
* For more info see the GL documentation:
* https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDrawArraysIndirect.xhtml
*/
void GPU_batch_draw_indirect(GPUBatch *batch, GPUStorageBuf *indirect_buf, intptr_t offset);
/**
* Issue \a count draw calls using arguments sourced from a #GPUStorageBuf.
* The \a stride (in bytes) control the spacing between each command description.
* The argument are expected to be valid for the type of geometry contained by this #GPUBatch
* (index or non-indexed).
*
* A `GPU_BARRIER_COMMAND` memory barrier is automatically added before the call.
*
* For more info see the GL documentation:
* https://registry.khronos.org/OpenGL-Refpages/gl4/html/glMultiDrawArraysIndirect.xhtml
*/
void GPU_batch_multi_draw_indirect(
GPUBatch *batch, GPUStorageBuf *indirect_buf, int count, intptr_t offset, intptr_t stride);
#if 0 /* future plans */
/**
* Return indirect draw call parameters for this #GPUBatch.
* NOTE: \a r_base_index is set to -1 if not using an index buffer.
*/
void GPU_batch_draw_parameter_get(GPUBatch *batch,
int *r_vertex_count,
int *r_vertex_first,
int *r_base_index,
int *r_indices_count);
/* Can multiple batches share a #GPUVertBuf? Use ref count? */
/** \} */
/* We often need a batch with its own data, to be created and discarded together. */
/* WithOwn variants reduce number of system allocations. */
typedef struct BatchWithOwnVertexBuffer {
GPUBatch batch;
GPUVertBuf verts; /* link batch.verts to this */
} BatchWithOwnVertexBuffer;
typedef struct BatchWithOwnElementList {
GPUBatch batch;
GPUIndexBuf elem; /* link batch.elem to this */
} BatchWithOwnElementList;
typedef struct BatchWithOwnVertexBufferAndElementList {
GPUBatch batch;
GPUIndexBuf elem; /* link batch.elem to this */
GPUVertBuf verts; /* link batch.verts to this */
} BatchWithOwnVertexBufferAndElementList;
GPUBatch *create_BatchWithOwnVertexBuffer(GPUPrimType, GPUVertFormat *, uint v_len, GPUIndexBuf *);
GPUBatch *create_BatchWithOwnElementList(GPUPrimType, GPUVertBuf *, uint prim_len);
GPUBatch *create_BatchWithOwnVertexBufferAndElementList(GPUPrimType,
GPUVertFormat *,
uint v_len,
uint prim_len);
/* verts: shared, own */
/* elem: none, shared, own */
GPUBatch *create_BatchInGeneral(GPUPrimType, VertexBufferStuff, ElementListStuff);
#endif /* future plans */
/* -------------------------------------------------------------------- */
/** \name Module init/exit
* \{ */
void gpu_batch_init(void);
void gpu_batch_exit(void);
/* Macros */
#define GPU_BATCH_DISCARD_SAFE(batch) \
do { \
if (batch != NULL) { \
GPU_batch_discard(batch); \
batch = NULL; \
} \
} while (0)
#define GPU_BATCH_CLEAR_SAFE(batch) \
do { \
if (batch != NULL) { \
GPU_batch_clear(batch); \
memset(batch, 0, sizeof(*(batch))); \
} \
} while (0)
#define GPU_BATCH_DISCARD_ARRAY_SAFE(_batch_array, _len) \
do { \
if (_batch_array != NULL) { \
BLI_assert(_len > 0); \
for (int _i = 0; _i < _len; _i++) { \
GPU_BATCH_DISCARD_SAFE(_batch_array[_i]); \
} \
MEM_freeN(_batch_array); \
} \
} while (0)
/** \} */
#ifdef __cplusplus
}

View File

@ -40,40 +40,43 @@ GPUBatch *GPU_batch_calloc()
return batch;
}
GPUBatch *GPU_batch_create_ex(GPUPrimType prim_type,
GPUVertBuf *verts,
GPUIndexBuf *elem,
GPUBatch *GPU_batch_create_ex(GPUPrimType primitive_type,
GPUVertBuf *vertex_buf,
GPUIndexBuf *index_buf,
eGPUBatchFlag owns_flag)
{
GPUBatch *batch = GPU_batch_calloc();
GPU_batch_init_ex(batch, prim_type, verts, elem, owns_flag);
GPU_batch_init_ex(batch, primitive_type, vertex_buf, index_buf, owns_flag);
return batch;
}
void GPU_batch_init_ex(GPUBatch *batch,
GPUPrimType prim_type,
GPUVertBuf *verts,
GPUIndexBuf *elem,
GPUPrimType primitive_type,
GPUVertBuf *vertex_buf,
GPUIndexBuf *index_buf,
eGPUBatchFlag owns_flag)
{
/* Do not pass any other flag */
BLI_assert((owns_flag & ~(GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX)) == 0);
/* Batch needs to be in cleared state. */
BLI_assert((batch->flag & GPU_BATCH_INIT) == 0);
batch->verts[0] = verts;
batch->verts[0] = vertex_buf;
for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; v++) {
batch->verts[v] = nullptr;
}
for (auto &v : batch->inst) {
v = nullptr;
}
batch->elem = elem;
batch->prim_type = prim_type;
batch->elem = index_buf;
batch->prim_type = primitive_type;
batch->flag = owns_flag | GPU_BATCH_INIT | GPU_BATCH_DIRTY;
batch->shader = nullptr;
}
void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src)
{
GPU_batch_clear(batch_dst);
GPU_batch_init_ex(
batch_dst, GPU_PRIM_POINTS, batch_src->verts[0], batch_src->elem, GPU_BATCH_INVALID);
@ -118,35 +121,35 @@ void GPU_batch_discard(GPUBatch *batch)
/** \name Buffers Management
* \{ */
void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *vertex_buf, bool own_vbo)
{
BLI_assert(inst);
BLI_assert(vertex_buf);
batch->flag |= GPU_BATCH_DIRTY;
if (batch->inst[0] && (batch->flag & GPU_BATCH_OWNS_INST_VBO)) {
GPU_vertbuf_discard(batch->inst[0]);
}
batch->inst[0] = inst;
batch->inst[0] = vertex_buf;
SET_FLAG_FROM_TEST(batch->flag, own_vbo, GPU_BATCH_OWNS_INST_VBO);
}
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo)
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *index_buf, bool own_ibo)
{
BLI_assert(elem);
BLI_assert(index_buf);
batch->flag |= GPU_BATCH_DIRTY;
if (batch->elem && (batch->flag & GPU_BATCH_OWNS_INDEX)) {
GPU_indexbuf_discard(batch->elem);
}
batch->elem = elem;
batch->elem = index_buf;
SET_FLAG_FROM_TEST(batch->flag, own_ibo, GPU_BATCH_OWNS_INDEX);
}
int GPU_batch_instbuf_add_ex(GPUBatch *batch, GPUVertBuf *insts, bool own_vbo)
int GPU_batch_instbuf_add(GPUBatch *batch, GPUVertBuf *vertex_buf, bool own_vbo)
{
BLI_assert(insts);
BLI_assert(vertex_buf);
batch->flag |= GPU_BATCH_DIRTY;
for (uint v = 0; v < GPU_BATCH_INST_VBO_MAX_LEN; v++) {
@ -157,7 +160,7 @@ int GPU_batch_instbuf_add_ex(GPUBatch *batch, GPUVertBuf *insts, bool own_vbo)
// BLI_assert(insts->vertex_len == batch->inst[0]->vertex_len);
}
batch->inst[v] = insts;
batch->inst[v] = vertex_buf;
SET_FLAG_FROM_TEST(batch->flag, own_vbo, (eGPUBatchFlag)(GPU_BATCH_OWNS_INST_VBO << v));
return v;
}
@ -167,9 +170,9 @@ int GPU_batch_instbuf_add_ex(GPUBatch *batch, GPUVertBuf *insts, bool own_vbo)
return -1;
}
int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
int GPU_batch_vertbuf_add(GPUBatch *batch, GPUVertBuf *vertex_buf, bool own_vbo)
{
BLI_assert(verts);
BLI_assert(vertex_buf);
batch->flag |= GPU_BATCH_DIRTY;
for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
@ -179,7 +182,7 @@ int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
/* This is an issue for the HACK inside DRW_vbo_request(). */
// BLI_assert(verts->vertex_len == batch->verts[0]->vertex_len);
}
batch->verts[v] = verts;
batch->verts[v] = vertex_buf;
SET_FLAG_FROM_TEST(batch->flag, own_vbo, (eGPUBatchFlag)(GPU_BATCH_OWNS_VBO << v));
return v;
}
@ -189,10 +192,10 @@ int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
return -1;
}
bool GPU_batch_vertbuf_has(GPUBatch *batch, GPUVertBuf *verts)
bool GPU_batch_vertbuf_has(GPUBatch *batch, GPUVertBuf *vertex_buf)
{
for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
if (batch->verts[v] == verts) {
if (batch->verts[v] == vertex_buf) {
return true;
}
}
@ -211,7 +214,6 @@ void GPU_batch_resource_id_buf_set(GPUBatch *batch, GPUStorageBuf *resource_id_b
/* -------------------------------------------------------------------- */
/** \name Uniform setters
*
* TODO(fclem): port this to GPUShader.
* \{ */
void GPU_batch_set_shader(GPUBatch *batch, GPUShader *shader)
@ -226,19 +228,22 @@ void GPU_batch_set_shader(GPUBatch *batch, GPUShader *shader)
/** \name Drawing / Drawcall functions
* \{ */
void GPU_batch_draw_parameter_get(
GPUBatch *gpu_batch, int *r_v_count, int *r_v_first, int *r_base_index, int *r_i_count)
void GPU_batch_draw_parameter_get(GPUBatch *gpu_batch,
int *r_vertex_count,
int *r_vertex_first,
int *r_base_index,
int *r_indices_count)
{
Batch *batch = static_cast<Batch *>(gpu_batch);
if (batch->elem) {
*r_v_count = batch->elem_()->index_len_get();
*r_v_first = batch->elem_()->index_start_get();
*r_vertex_count = batch->elem_()->index_len_get();
*r_vertex_first = batch->elem_()->index_start_get();
*r_base_index = batch->elem_()->index_base_get();
}
else {
*r_v_count = batch->verts_(0)->vertex_len;
*r_v_first = 0;
*r_vertex_count = batch->verts_(0)->vertex_len;
*r_vertex_first = 0;
*r_base_index = -1;
}
@ -247,7 +252,7 @@ void GPU_batch_draw_parameter_get(
if (batch->inst[1] != nullptr) {
i_count = min_ii(i_count, batch->inst_(1)->vertex_len);
}
*r_i_count = i_count;
*r_indices_count = i_count;
}
void GPU_batch_draw(GPUBatch *batch)
@ -256,48 +261,51 @@ void GPU_batch_draw(GPUBatch *batch)
GPU_batch_draw_advanced(batch, 0, 0, 0, 0);
}
void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count)
void GPU_batch_draw_range(GPUBatch *batch, int vertex_first, int vertex_count)
{
GPU_shader_bind(batch->shader);
GPU_batch_draw_advanced(batch, v_first, v_count, 0, 0);
GPU_batch_draw_advanced(batch, vertex_first, vertex_count, 0, 0);
}
void GPU_batch_draw_instanced(GPUBatch *batch, int i_count)
void GPU_batch_draw_instance_range(GPUBatch *batch, int instance_first, int instance_count)
{
BLI_assert(batch->inst[0] == nullptr);
GPU_shader_bind(batch->shader);
GPU_batch_draw_advanced(batch, 0, 0, 0, i_count);
GPU_batch_draw_advanced(batch, 0, 0, instance_first, instance_count);
}
void GPU_batch_draw_advanced(
GPUBatch *gpu_batch, int v_first, int v_count, int i_first, int i_count)
void GPU_batch_draw_advanced(GPUBatch *gpu_batch,
int vertex_first,
int vertex_count,
int instance_first,
int instance_count)
{
BLI_assert(Context::get()->shader != nullptr);
Batch *batch = static_cast<Batch *>(gpu_batch);
if (v_count == 0) {
if (vertex_count == 0) {
if (batch->elem) {
v_count = batch->elem_()->index_len_get();
vertex_count = batch->elem_()->index_len_get();
}
else {
v_count = batch->verts_(0)->vertex_len;
vertex_count = batch->verts_(0)->vertex_len;
}
}
if (i_count == 0) {
i_count = (batch->inst[0]) ? batch->inst_(0)->vertex_len : 1;
if (instance_count == 0) {
instance_count = (batch->inst[0]) ? batch->inst_(0)->vertex_len : 1;
/* Meh. This is to be able to use different numbers of verts in instance VBO's. */
if (batch->inst[1] != nullptr) {
i_count = min_ii(i_count, batch->inst_(1)->vertex_len);
instance_count = min_ii(instance_count, batch->inst_(1)->vertex_len);
}
}
if (v_count == 0 || i_count == 0) {
if (vertex_count == 0 || instance_count == 0) {
/* Nothing to draw. */
return;
}
batch->draw(v_first, v_count, i_first, i_count);
batch->draw(vertex_first, vertex_count, instance_first, instance_count);
}
void GPU_batch_draw_indirect(GPUBatch *gpu_batch, GPUStorageBuf *indirect_buf, intptr_t offset)

View File

@ -157,7 +157,7 @@ static PyObject *pygpu_batch_vertbuf_add(BPyGPUBatch *self, BPyGPUVertBuf *py_bu
PyList_Append(self->references, (PyObject *)py_buf);
#endif
GPU_batch_vertbuf_add(self->batch, py_buf->buf);
GPU_batch_vertbuf_add(self->batch, py_buf->buf, false);
Py_RETURN_NONE;
}