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