Compare commits

..

4 Commits

Author SHA1 Message Date
d0741afda7 Stores meshes into vertices. 2023-01-03 12:59:07 +01:00
66980e6ea9 Move vertices and indicies buffers to vertices. 2023-01-03 11:38:19 +01:00
a91a852887 Automatic batch freezing. 2023-01-03 11:10:37 +01:00
357066b315 Cleanup makefile. 2023-01-03 11:10:14 +01:00
5 changed files with 87 additions and 38 deletions

View File

@ -21,7 +21,7 @@ cpp/math.cpp
OUTPUTFILE = engine.so OUTPUTFILE = engine.so
CXXFLAGS = -fpic -Wall -Werror -O2 -flto -fomit-frame-pointer -ffast-math -funroll-loops -fno-rtti -fno-exceptions CXXFLAGS = -Wall -Werror -O2 -march=x86-64 -mtune=generic -msse2 -ffast-math -fpic -flto -fno-rtti -fno-exceptions
.PHONY: all .PHONY: all
all: clean $(OUTPUTFILE) all: clean $(OUTPUTFILE)

View File

@ -44,6 +44,10 @@ def _ushort_addr(x):
assert x.typecode == 'H' assert x.typecode == 'H'
return x.buffer_info()[0] return x.buffer_info()[0]
def _uint_addr(x):
assert x.typecode == 'I'
return x.buffer_info()[0]
def _float_addr(x): def _float_addr(x):
assert x.typecode == 'f' assert x.typecode == 'f'
return x.buffer_info()[0] return x.buffer_info()[0]
@ -371,10 +375,13 @@ _create_vertices.argtypes = (
ctypes.c_uint, # nvertices ctypes.c_uint, # nvertices
ctypes.c_void_p, # vertices ctypes.c_void_p, # vertices
ctypes.c_uint, # nindices ctypes.c_uint, # nindices
ctypes.c_void_p) # indices ctypes.c_void_p, # vertices
ctypes.c_uint, # nmeshes
ctypes.c_void_p) # meshes
def create_vertices(format, nvertices, vertices, indices): def create_vertices(format, nvertices, vertices, indices, meshes):
return _create_vertices(format, nvertices, _ubyte_addr(vertices), len(indices), _ushort_addr(indices)) return _create_vertices(format,
nvertices, _ubyte_addr(vertices), len(indices), _ushort_addr(indices), len(meshes), _uint_addr(meshes))
create_batch = _engine.rk_create_batch create_batch = _engine.rk_create_batch
create_batch.restype = _handle create_batch.restype = _handle
@ -382,7 +389,6 @@ create_batch.errcheck = _check_handle
create_batch.argtypes = ( create_batch.argtypes = (
ctypes.c_void_p, # vertices ctypes.c_void_p, # vertices
ctypes.c_uint, # max_size ctypes.c_uint, # max_size
ctypes.c_uint, # max_meshes
ctypes.c_char_p) # params_format ctypes.c_char_p) # params_format
clear_buffer = _engine.rk_clear_buffer clear_buffer = _engine.rk_clear_buffer

View File

@ -116,12 +116,13 @@ RK_EXPORT rk_vertices_t rk_create_vertices(
rk_uint nvertices, rk_uint nvertices,
rk_ubyte const * vertices, rk_ubyte const * vertices,
rk_uint nindices, rk_uint nindices,
rk_ushort const * indices); rk_ushort const * indices,
rk_uint nmeshes,
rk_mesh const * meshes);
RK_EXPORT rk_batch_t rk_create_batch( RK_EXPORT rk_batch_t rk_create_batch(
rk_vertices_t vertices, rk_vertices_t vertices,
rk_uint max_size, rk_uint max_size,
rk_uint max_meshes,
rk_param_format const * params_format); rk_param_format const * params_format);
RK_EXPORT void rk_clear_buffer( RK_EXPORT void rk_clear_buffer(

View File

@ -314,7 +314,9 @@ rk_vertices_t rk_create_vertices(
rk_uint nvertices, rk_uint nvertices,
rk_ubyte const * _vertices, rk_ubyte const * _vertices,
rk_uint nindices, rk_uint nindices,
rk_ushort const * indices) { rk_ushort const * indices,
rk_uint nmeshes,
rk_mesh const * meshes) {
if (!format || !nvertices || !_vertices || !nindices || !indices) { if (!format || !nvertices || !_vertices || !nindices || !indices) {
rk_printf("rk_create_vertices(): invalid params."); rk_printf("rk_create_vertices(): invalid params.");
return RK_INVALID_HANDLE; return RK_INVALID_HANDLE;
@ -345,12 +347,17 @@ rk_vertices_t rk_create_vertices(
rk_vertices * const vertices = new rk_vertices; rk_vertices * const vertices = new rk_vertices;
vertices->nvertices = nvertices; vertices->nvertices = nvertices;
vertices->nindices = nindices; vertices->nindices = nindices;
vertices->nmeshes = nmeshes;
vertices->format = new rk_vertex_format[format_size + 1]; vertices->format = new rk_vertex_format[format_size + 1];
memcpy(vertices->format, format, (format_size + 1) * sizeof(rk_vertex_format)); memcpy(vertices->format, format, (format_size + 1) * sizeof(rk_vertex_format));
vertices->vertices = new rk_ubyte[nvertices * vertex_size]; vertices->vertices = new rk_ubyte[nvertices * vertex_size];
memcpy(vertices->vertices, _vertices, nvertices * vertex_size); memcpy(vertices->vertices, _vertices, nvertices * vertex_size);
vertices->indices = new rk_ushort[nindices]; vertices->indices = new rk_ushort[nindices];
memcpy(vertices->indices, indices, nindices * sizeof(rk_ushort)); memcpy(vertices->indices, indices, nindices * sizeof(rk_ushort));
vertices->meshes = new rk_mesh[nmeshes];
memcpy(vertices->meshes, meshes, nmeshes * sizeof(rk_mesh));
vertices->vertices_buffer = 0;
vertices->indices_buffer = 0;
return reinterpret_cast<rk_vertices_t>(vertices); return reinterpret_cast<rk_vertices_t>(vertices);
} }
@ -488,9 +495,8 @@ static void rk_pack_mat3_int10_norm(
rk_batch_t rk_create_batch( rk_batch_t rk_create_batch(
rk_vertices_t _vertices, rk_vertices_t _vertices,
rk_uint max_size, rk_uint max_size,
rk_uint max_meshes,
rk_param_format const * params_format) { rk_param_format const * params_format) {
rk_vertices const * const vertices = reinterpret_cast<rk_vertices const *>(_vertices); rk_vertices * const vertices = reinterpret_cast<rk_vertices *>(_vertices);
if (!vertices || !max_size || max_size > RK_BATCH_MAX_SIZE) { if (!vertices || !max_size || max_size > RK_BATCH_MAX_SIZE) {
rk_printf("rk_create_batch(): invalid params."); rk_printf("rk_create_batch(): invalid params.");
return RK_INVALID_HANDLE; return RK_INVALID_HANDLE;
@ -542,12 +548,12 @@ rk_batch_t rk_create_batch(
batch->ncommands = 0; batch->ncommands = 0;
batch->ninstances = 0; batch->ninstances = 0;
batch->max_size = max_size; batch->max_size = max_size;
batch->max_meshes = max_meshes; batch->max_meshes = vertices->nmeshes;
batch->nparams = nparams; batch->nparams = nparams;
batch->flags = new rk_instance_flags[max_size]; batch->flags = new rk_instance_flags[max_size];
batch->meshes = new rk_mesh[max_size]; batch->meshes = new rk_mesh[max_size];
batch->indices = new rk_ushort[max_size]; batch->indices = new rk_ushort[max_size];
batch->commands = new rk_command[max_meshes]; batch->commands = new rk_command[batch->max_meshes];
if (nparams) { if (nparams) {
batch->params = new rk_parameter[nparams]; batch->params = new rk_parameter[nparams];
} else { } else {
@ -555,17 +561,23 @@ rk_batch_t rk_create_batch(
} }
glGenVertexArrays(1, &batch->vertex_array); glGenVertexArrays(1, &batch->vertex_array);
glBindVertexArray(batch->vertex_array); glBindVertexArray(batch->vertex_array);
glGenBuffers(1, &batch->vertices_buffer); if (!vertices->vertices_buffer) {
glBindBuffer(GL_ARRAY_BUFFER, batch->vertices_buffer); glGenBuffers(1, &vertices->vertices_buffer);
glBufferData(GL_ARRAY_BUFFER, vertices->nvertices * vertex_size, vertices->vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vertices->vertices_buffer);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBufferData(GL_ARRAY_BUFFER, vertices->nvertices * vertex_size, vertices->vertices, GL_STATIC_DRAW);
glGenBuffers(1, &batch->indices_buffer); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->indices_buffer); }
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertices->nindices * sizeof(rk_ushort), vertices->indices, GL_STATIC_DRAW); if (vertices->indices_buffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertices->indices_buffer);
} else {
glGenBuffers(1, &vertices->indices_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertices->indices_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertices->nindices * sizeof(rk_ushort), vertices->indices, GL_STATIC_DRAW);
}
if (rk_MultiDrawElementsIndirect) { if (rk_MultiDrawElementsIndirect) {
glGenBuffers(1, &batch->commands_buffer); glGenBuffers(1, &batch->commands_buffer);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer);
glBufferData(GL_DRAW_INDIRECT_BUFFER, max_meshes * sizeof(rk_command), nullptr, GL_DYNAMIC_DRAW); glBufferData(GL_DRAW_INDIRECT_BUFFER, batch->max_meshes * sizeof(rk_command), nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
} }
if (nparams) { if (nparams) {
@ -577,7 +589,7 @@ rk_batch_t rk_create_batch(
unsigned binding = 0; unsigned binding = 0;
unsigned attrib = 0; unsigned attrib = 0;
unsigned offset = 0; unsigned offset = 0;
glBindVertexBuffer(binding, batch->vertices_buffer, 0, vertex_size); glBindVertexBuffer(binding, vertices->vertices_buffer, 0, vertex_size);
for (rk_vertex_format const * f = vertices->format; *f; ++f) { for (rk_vertex_format const * f = vertices->format; *f; ++f) {
GLboolean const norm = (*f & RK_VERTEX_FORMAT_NORMALIZE) != 0; GLboolean const norm = (*f & RK_VERTEX_FORMAT_NORMALIZE) != 0;
switch (*f & RK_VERTEX_FORMAT_MASK) { switch (*f & RK_VERTEX_FORMAT_MASK) {
@ -837,6 +849,32 @@ static void rk_pack_batch(
batch.state = RK_BATCH_STATE_PACKED; batch.state = RK_BATCH_STATE_PACKED;
} }
static bool rk_compare_replace(
void * __restrict _dst,
void const * __restrict _src,
unsigned const size) {
rk_ulong hash = 0;
rk_ulong * dst = reinterpret_cast<rk_ulong *>(_dst);
rk_ulong const * src = reinterpret_cast<rk_ulong const *>(_src);
unsigned count = size / sizeof(rk_ulong);
unsigned remain = (size - count * sizeof(rk_ulong));
if (count) {
do {
hash |= *dst ^ *src;
*dst++ = *src++;
} while(--count > 0);
}
rk_ubyte * rdst = reinterpret_cast<rk_ubyte *>(dst);
rk_ubyte const * rsrc = reinterpret_cast<rk_ubyte const *>(src);
if (remain) {
do {
hash |= *rdst ^ *rsrc;
*rdst++ = *rsrc++;
} while(--remain > 0);
}
return (hash != 0);
}
void rk_fill_batch( void rk_fill_batch(
rk_batch_t _batch, rk_batch_t _batch,
rk_uint count, rk_uint count,
@ -861,30 +899,28 @@ void rk_fill_batch(
} }
} }
bool const is_empty = (batch->state < RK_BATCH_STATE_FILLED); bool const is_empty = (batch->state < RK_BATCH_STATE_FILLED);
bool const resized = (count != batch->count);
bool const got_everything = (flags && meshes && got_all_params); bool const got_everything = (flags && meshes && got_all_params);
bool const need_sorting = (is_empty || flags || meshes || count != batch->count);
if (is_empty && !got_everything) { if (is_empty && !got_everything) {
rk_printf("rk_fill_batch(): cannot freeze and empty batch."); rk_printf("rk_fill_batch(): cannot freeze and empty batch.");
return;
} else if (count > batch->count && !got_everything) { } else if (count > batch->count && !got_everything) {
rk_printf("rk_fill_batch(): cannot grow a frozen batch."); rk_printf("rk_fill_batch(): cannot grow a frozen batch.");
} else { return;
batch->count = count;
}
if (flags) {
memcpy(batch->flags, flags, batch->count * sizeof(rk_instance_flags));
}
if (meshes) {
memcpy(batch->meshes, meshes, batch->count * sizeof(rk_mesh));
} }
batch->count = count;
bool const cmp_flags =
(flags && rk_compare_replace(batch->flags, flags, batch->count * sizeof(rk_instance_flags)));
bool const cmp_meshes =
(meshes && rk_compare_replace(batch->meshes, meshes, batch->count * sizeof(rk_mesh)));
bool const need_sorting = (cmp_flags || cmp_meshes || resized);
if (batch->nparams) { if (batch->nparams) {
rk_parameter const * const last_param = batch->params + batch->nparams; rk_parameter const * const last_param = batch->params + batch->nparams;
if (got_any_params) { if (got_any_params) {
rk_ubyte const * const * src = params; rk_ubyte const * const * src = params;
for (rk_parameter const * dst = batch->params; dst < last_param; ++dst, ++src) { for (rk_parameter const * dst = batch->params; dst < last_param; ++dst, ++src) {
dst->dirty = (need_sorting || *src); dst->dirty =
if (*src) { (*src && rk_compare_replace(dst->source, *src, batch->count * dst->src_size)) || need_sorting;
memcpy(dst->source, *src, batch->count * dst->src_size);
}
} }
} else if (need_sorting) { } else if (need_sorting) {
for (rk_parameter const * dst = batch->params; dst < last_param; ++dst) { for (rk_parameter const * dst = batch->params; dst < last_param; ++dst) {
@ -1005,8 +1041,6 @@ void rk_destroy_batch(
delete[] batch->params; delete[] batch->params;
glDeleteBuffers(1, &batch->params_buffer); glDeleteBuffers(1, &batch->params_buffer);
} }
glDeleteBuffers(1, &batch->indices_buffer);
glDeleteBuffers(1, &batch->vertices_buffer);
glDeleteVertexArrays(1, &batch->vertex_array); glDeleteVertexArrays(1, &batch->vertex_array);
delete batch; delete batch;
} }
@ -1029,6 +1063,12 @@ void rk_destroy_vertices(
delete[] vertices->format; delete[] vertices->format;
delete[] vertices->vertices; delete[] vertices->vertices;
delete[] vertices->indices; delete[] vertices->indices;
if (vertices->vertices_buffer) {
glDeleteBuffers(1, &vertices->vertices_buffer);
}
if (vertices->indices_buffer) {
glDeleteBuffers(1, &vertices->indices_buffer);
}
delete vertices; delete vertices;
} }
} }

View File

@ -41,9 +41,13 @@ struct rk_triangles {
struct rk_vertices { struct rk_vertices {
unsigned nvertices; unsigned nvertices;
unsigned nindices; unsigned nindices;
unsigned nmeshes;
rk_vertex_format * format; rk_vertex_format * format;
rk_ubyte * vertices; rk_ubyte * vertices;
rk_ushort * indices; rk_ushort * indices;
rk_mesh * meshes;
GLuint vertices_buffer;
GLuint indices_buffer;
}; };
struct rk_command { struct rk_command {
@ -119,8 +123,6 @@ struct rk_batch {
rk_command * commands; rk_command * commands;
rk_parameter * params; rk_parameter * params;
GLuint vertex_array; GLuint vertex_array;
GLuint vertices_buffer;
GLuint indices_buffer;
GLuint commands_buffer; GLuint commands_buffer;
GLuint params_buffer; GLuint params_buffer;
}; };