Buffer orphaning and subrange update optims.

This commit is contained in:
Roz K 2022-12-30 14:14:32 +01:00
parent 306ac3d312
commit 628f8bcaa4
Signed by: roz
GPG Key ID: 51FBF4E483E1C822
2 changed files with 30 additions and 22 deletions

View File

@ -17,7 +17,6 @@
#include "render_opengles.hpp" #include "render_opengles.hpp"
#include "../display/display_glx.hpp" #include "../display/display_glx.hpp"
#include <cstdio> #include <cstdio>
#include <cstring>
typedef void (*rk_DrawElementsInstancedBaseInstanceFunc)(rk_uint, rk_uint, rk_uint, const void *, rk_uint, rk_uint); typedef void (*rk_DrawElementsInstancedBaseInstanceFunc)(rk_uint, rk_uint, rk_uint, const void *, rk_uint, rk_uint);
typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, rk_uint, rk_uint); typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, rk_uint, rk_uint);
@ -376,6 +375,7 @@ static void rk_pack_vec3_short(
dst->x = static_cast<rk_short>(input.x); dst->x = static_cast<rk_short>(input.x);
dst->y = static_cast<rk_short>(input.y); dst->y = static_cast<rk_short>(input.y);
dst->z = static_cast<rk_short>(input.z); dst->z = static_cast<rk_short>(input.z);
dst->pad = 0;
} }
} }
@ -393,6 +393,7 @@ static void rk_pack_vec3_short_norm(
dst->x = _convert(input.x); dst->x = _convert(input.x);
dst->y = _convert(input.y); dst->y = _convert(input.y);
dst->z = _convert(input.z); dst->z = _convert(input.z);
dst->pad = 0;
} }
#undef _convert #undef _convert
} }
@ -496,18 +497,19 @@ rk_batch_t rk_create_batch(
rk_batch * batch = new rk_batch; rk_batch * batch = new rk_batch;
batch->max_size = max_size; batch->max_size = max_size;
batch->nparams = nparams; batch->nparams = nparams;
batch->commands_size = 0;
batch->packed_size = 0;
batch->indices = nullptr; batch->indices = nullptr;
batch->commands = nullptr; batch->commands = nullptr;
batch->params = nullptr; batch->params = nullptr;
batch->packed_params = nullptr; batch->commands_buffer = 0;
batch->indirect_buffer = 0;
batch->params_array = 0; batch->params_array = 0;
unsigned params_size = 0; unsigned packed_size = 0;
if (nparams) { if (nparams) {
batch->params = new rk_parameter[nparams]; batch->params = new rk_parameter[nparams];
rk_parameter * param = batch->params; rk_parameter * param = batch->params;
for (rk_param_format const * f = params_format; *f; ++f, ++param) { for (rk_param_format const * f = params_format; *f; ++f, ++param) {
param->offset = params_size; param->offset = packed_size;
bool const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0; bool const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0;
switch (*f & RK_PARAM_FORMAT_MASK) { switch (*f & RK_PARAM_FORMAT_MASK) {
case RK_PARAM_FORMAT_VEC3_FLOAT: case RK_PARAM_FORMAT_VEC3_FLOAT:
@ -537,26 +539,25 @@ rk_batch_t rk_create_batch(
return nullptr; return nullptr;
break; break;
} }
params_size += max_size * param->size; packed_size += max_size * param->size;
} }
} }
batch->commands_size = max_size * sizeof(rk_command);
batch->packed_size = packed_size;
batch->indices = new rk_ushort[max_size]; batch->indices = new rk_ushort[max_size];
batch->commands = new rk_command[max_size]; batch->commands = new rk_command[max_size];
memset(batch->commands, 0, max_size * sizeof(rk_command)); memset(batch->commands, 0, batch->commands_size);
batch->indirect_buffer = 0;
if (rk_MultiDrawElementsIndirect) { if (rk_MultiDrawElementsIndirect) {
glGenBuffers(1, &batch->indirect_buffer); glGenBuffers(1, &batch->commands_buffer);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->indirect_buffer); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer);
glBufferData(GL_DRAW_INDIRECT_BUFFER, max_size * sizeof(rk_command), nullptr, GL_DYNAMIC_DRAW); glBufferData(GL_DRAW_INDIRECT_BUFFER, batch->commands_size, nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
} }
if (nparams) { if (nparams) {
batch->packed_params = new rk_ubyte[params_size];
memset(batch->packed_params, 0, params_size);
glBindVertexArray(vertices->array); glBindVertexArray(vertices->array);
glGenBuffers(1, &batch->params_array); glGenBuffers(1, &batch->params_array);
glBindBuffer(GL_ARRAY_BUFFER, batch->params_array); glBindBuffer(GL_ARRAY_BUFFER, batch->params_array);
glBufferData(GL_ARRAY_BUFFER, params_size, nullptr, GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, batch->packed_size, nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
rk_parameter const * param = batch->params; rk_parameter const * param = batch->params;
unsigned binding = RK_PARAMS_BINDING_BASE; unsigned binding = RK_PARAMS_BINDING_BASE;
@ -749,6 +750,7 @@ static unsigned rk_batch_build_commands(
commands->nvertices = static_cast<GLuint>(mesh.ntriangles) * 3; commands->nvertices = static_cast<GLuint>(mesh.ntriangles) * 3;
commands->ninstances = first - base; commands->ninstances = first - base;
commands->base_index = mesh.base_index; commands->base_index = mesh.base_index;
commands->base_vertex = 0;
commands->base_instance = base - batch.indices; commands->base_instance = base - batch.indices;
} }
return commands - batch.commands; return commands - batch.commands;
@ -762,9 +764,13 @@ static void rk_batch_pack(
for (rk_parameter const * param = batch.params; param < last_param; ++param) { for (rk_parameter const * param = batch.params; param < last_param; ++param) {
rk_ubyte const * const src = *srcs++; rk_ubyte const * const src = *srcs++;
if (src) { if (src) {
rk_ubyte * const dst = batch.packed_params + param->offset; rk_ubyte * const dst = reinterpret_cast<rk_ubyte *>(
glMapBufferRange(GL_ARRAY_BUFFER, param->offset, ninstances * param->size,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
if (dst) {
param->packer(ninstances, batch.indices, dst, src); param->packer(ninstances, batch.indices, dst, src);
glBufferSubData(GL_ARRAY_BUFFER, param->offset, ninstances * param->size, dst); glUnmapBuffer(GL_ARRAY_BUFFER);
}
} }
} }
} }
@ -785,11 +791,13 @@ void rk_draw_batch(
} }
unsigned const ncommands = rk_batch_build_commands(batch, ninstances, meshes); unsigned const ncommands = rk_batch_build_commands(batch, ninstances, meshes);
if (rk_MultiDrawElementsIndirect) { if (rk_MultiDrawElementsIndirect) {
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch.indirect_buffer); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch.commands_buffer);
glBufferData(GL_DRAW_INDIRECT_BUFFER, batch.commands_size, nullptr, GL_STREAM_DRAW);
glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, ncommands * sizeof(rk_command), batch.commands); glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, ncommands * sizeof(rk_command), batch.commands);
} }
if (batch.nparams && params) { if (batch.nparams && params) {
glBindBuffer(GL_ARRAY_BUFFER, batch.params_array); glBindBuffer(GL_ARRAY_BUFFER, batch.params_array);
glBufferData(GL_ARRAY_BUFFER, batch.packed_size, nullptr, GL_STREAM_DRAW);
rk_batch_pack(batch, ninstances, params); rk_batch_pack(batch, ninstances, params);
} }
if (rk_DrawElementsInstancedBaseInstance) { if (rk_DrawElementsInstancedBaseInstance) {
@ -865,11 +873,10 @@ void rk_destroy_batch(
delete[] batch->indices; delete[] batch->indices;
delete[] batch->commands; delete[] batch->commands;
if (rk_MultiDrawElementsIndirect) { if (rk_MultiDrawElementsIndirect) {
glDeleteBuffers(1, &batch->indirect_buffer); glDeleteBuffers(1, &batch->commands_buffer);
} }
if (batch->nparams) { if (batch->nparams) {
delete[] batch->params; delete[] batch->params;
delete[] batch->packed_params;
glDeleteBuffers(1, &batch->params_array); glDeleteBuffers(1, &batch->params_array);
} }
delete batch; delete batch;

View File

@ -102,11 +102,12 @@ struct rk_parameter {
struct rk_batch { struct rk_batch {
unsigned max_size; unsigned max_size;
unsigned nparams; unsigned nparams;
unsigned commands_size;
unsigned packed_size;
rk_ushort * indices; rk_ushort * indices;
rk_command * commands; rk_command * commands;
rk_parameter * params; rk_parameter * params;
rk_ubyte * packed_params; GLuint commands_buffer;
GLuint indirect_buffer;
GLuint params_array; GLuint params_array;
}; };