Meshes use mapped buffers;

This commit is contained in:
bjorn 2017-03-11 17:27:18 -08:00
parent b417df1de9
commit 94a5dab7b5
5 changed files with 60 additions and 74 deletions

View File

@ -575,15 +575,17 @@ int l_lovrGraphicsNewMesh(lua_State* L) {
Mesh* mesh = lovrMeshCreate(size, format.length ? &format : NULL, *drawMode, *usage);
if (dataIndex) {
int count = lua_objlen(L, dataIndex);
MeshFormat format = lovrMeshGetVertexFormat(mesh);
for (size_t i = 0; i < lua_objlen(L, dataIndex); i++) {
char* vertex = lovrMeshMap(mesh, 0, count);
for (int i = 0; i < count; i++) {
lua_rawgeti(L, dataIndex, i + 1);
if (!lua_istable(L, -1)) {
return luaL_error(L, "Vertex information should be specified as a table");
}
int component = 0;
char* vertex = lovrMeshGetScratchVertex(mesh);
for (int j = 0; j < format.length; j++) {
MeshAttribute attribute = format.data[j];
for (int k = 0; k < attribute.count; k++) {
@ -598,7 +600,6 @@ int l_lovrGraphicsNewMesh(lua_State* L) {
}
}
lovrMeshSetVertex(mesh, i, lovrMeshGetScratchVertex(mesh));
lua_pop(L, 1);
}
}

View File

@ -82,8 +82,7 @@ int l_lovrMeshGetVertexCount(lua_State* L) {
int l_lovrMeshGetVertex(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
int index = luaL_checkint(L, 2) - 1;
char* vertex = lovrMeshGetScratchVertex(mesh);
lovrMeshGetVertex(mesh, index, vertex);
char* vertex = lovrMeshMap(mesh, index, 1);
MeshFormat format = lovrMeshGetVertexFormat(mesh);
int total = 0;
@ -107,13 +106,14 @@ int l_lovrMeshGetVertex(lua_State* L) {
int l_lovrMeshSetVertex(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
int index = luaL_checkint(L, 2) - 1;
MeshFormat format = lovrMeshGetVertexFormat(mesh);
char* vertex = lovrMeshGetScratchVertex(mesh);
if (index < 0 || index >= mesh->size) {
if (index < 0 || index >= lovrMeshGetVertexCount(mesh)) {
return luaL_error(L, "Invalid mesh vertex index: %d", index + 1);
}
MeshFormat format = lovrMeshGetVertexFormat(mesh);
char* vertex = lovrMeshMap(mesh, index, 1);
// Unwrap table
int arg = 3;
if (lua_istable(L, 3)) {
@ -136,7 +136,6 @@ int l_lovrMeshSetVertex(lua_State* L) {
}
}
lovrMeshSetVertex(mesh, index, lovrMeshGetScratchVertex(mesh));
return 0;
}
@ -144,16 +143,16 @@ int l_lovrMeshGetVertexAttribute(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
int vertexIndex = luaL_checkint(L, 2) - 1;
int attributeIndex = luaL_checkint(L, 3) - 1;
char* vertex = lovrMeshGetScratchVertex(mesh);
lovrMeshGetVertex(mesh, vertexIndex, vertex);
MeshFormat format = lovrMeshGetVertexFormat(mesh);
if (vertexIndex < 0 || vertexIndex >= mesh->size) {
if (vertexIndex < 0 || vertexIndex >= lovrMeshGetVertexCount(mesh)) {
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
}
char* vertex = lovrMeshMap(mesh, vertexIndex, 1);
MeshAttribute attribute;
for (int i = 0; i <= attributeIndex; i++) {
attribute = format.data[i];
@ -178,16 +177,16 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
int vertexIndex = luaL_checkint(L, 2) - 1;
int attributeIndex = luaL_checkint(L, 3) - 1;
char* vertex = lovrMeshGetScratchVertex(mesh);
lovrMeshGetVertex(mesh, vertexIndex, vertex);
MeshFormat format = lovrMeshGetVertexFormat(mesh);
if (vertexIndex < 0 || vertexIndex >= mesh->size) {
if (vertexIndex < 0 || vertexIndex >= lovrMeshGetVertexCount(mesh)) {
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
}
char* vertex = lovrMeshMap(mesh, vertexIndex, 1);
int arg = 4;
for (int i = 0; i <= attributeIndex; i++) {
MeshAttribute attribute = format.data[i];
@ -205,7 +204,6 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
}
}
lovrMeshSetVertex(mesh, vertexIndex, lovrMeshGetScratchVertex(mesh));
return 0;
}
@ -214,12 +212,9 @@ int l_lovrMeshSetVertices(lua_State* L) {
MeshFormat format = lovrMeshGetVertexFormat(mesh);
luaL_checktype(L, 2, LUA_TTABLE);
int vertexCount = lua_objlen(L, 2);
int start = luaL_optnumber(L, 3, 1) - 1;
if (vertexCount > lovrMeshGetVertexCount(mesh)) {
return luaL_error(L, "Too many vertices for Mesh (max is %d, got %d)\n", lovrMeshGetVertexCount(mesh), vertexCount);
}
char* vertices = malloc(mesh->stride * vertexCount);
void* vertices = lovrMeshMap(mesh, start, vertexCount);
char* vertex = vertices;
for (int i = 0; i < vertexCount; i++) {
@ -241,8 +236,6 @@ int l_lovrMeshSetVertices(lua_State* L) {
lua_pop(L, 1);
}
lovrMeshSetVertices(mesh, vertices, mesh->stride * vertexCount);
free(vertices);
return 0;
}
@ -285,7 +278,7 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
}
int index = lua_tointeger(L, -1);
if (index > mesh->size || index < 0) {
if (index > lovrMeshGetVertexCount(mesh) || index < 0) {
free(indices);
return luaL_error(L, "Invalid vertex map value: %d", index);
}

View File

@ -36,7 +36,7 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
mesh->attributesDirty = 0;
}
Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
Mesh* mesh = lovrAlloc(sizeof(Mesh), lovrMeshDestroy);
if (!mesh) return NULL;
@ -65,10 +65,8 @@ Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUs
return NULL;
}
mesh->size = size;
mesh->count = count;
mesh->stride = stride;
mesh->data = malloc(mesh->size * mesh->stride);
mesh->scratchVertex = malloc(mesh->stride);
mesh->enabledAttributes = ~0;
mesh->attributesDirty = 1;
mesh->drawMode = drawMode;
@ -78,13 +76,13 @@ Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUs
mesh->ibo = 0;
mesh->isRangeEnabled = 0;
mesh->rangeStart = 0;
mesh->rangeCount = mesh->size;
mesh->rangeCount = mesh->count;
mesh->texture = NULL;
mesh->lastShader = NULL;
glGenBuffers(1, &mesh->vbo);
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
glBufferData(GL_ARRAY_BUFFER, mesh->count * mesh->stride, NULL, mesh->usage);
glGenVertexArrays(1, &mesh->vao);
glGenBuffers(1, &mesh->ibo);
@ -100,12 +98,14 @@ void lovrMeshDestroy(const Ref* ref) {
glDeleteVertexArrays(1, &mesh->vao);
vec_deinit(&mesh->map);
vec_deinit(&mesh->format);
free(mesh->scratchVertex);
free(mesh->data);
free(mesh);
}
void lovrMeshDraw(Mesh* mesh, mat4 transform) {
if (mesh->isMapped) {
lovrMeshUnmap(mesh);
}
int usingIbo = mesh->map.length > 0;
lovrGraphicsPush();
@ -116,17 +116,15 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
glBindVertexArray(mesh->vao);
lovrMeshBindAttributes(mesh);
// Determine range of vertices to be rendered and whether we're using an IBO or not
int start, count;
if (mesh->isRangeEnabled) {
start = mesh->rangeStart;
count = mesh->rangeCount;
} else {
start = 0;
count = usingIbo ? mesh->map.length : mesh->size;
count = usingIbo ? mesh->map.length : mesh->count;
}
// Render! Use the IBO if a draw range is set
if (usingIbo) {
uintptr_t startAddress = (uintptr_t) start;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);
@ -152,41 +150,13 @@ int lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode) {
}
int lovrMeshGetVertexCount(Mesh* mesh) {
return mesh->size;
return mesh->count;
}
int lovrMeshGetVertexSize(Mesh* mesh) {
return mesh->stride;
}
void* lovrMeshGetScratchVertex(Mesh* mesh) {
return mesh->scratchVertex;
}
void lovrMeshGetVertex(Mesh* mesh, int index, void* dest) {
if (index >= mesh->size) {
return;
}
memcpy(dest, (char*) mesh->data + index * mesh->stride, mesh->stride);
}
void lovrMeshSetVertex(Mesh* mesh, int index, void* vertex) {
memcpy((char*) mesh->data + index * mesh->stride, vertex, mesh->stride);
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
}
void lovrMeshSetVertices(Mesh* mesh, void* vertices, int size) {
if (size > mesh->size * mesh->stride) {
error("Mesh is not big enough");
}
memcpy(mesh->data, vertices, size);
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
}
unsigned int* lovrMeshGetVertexMap(Mesh* mesh, int* count) {
*count = mesh->map.length;
return mesh->map.data;
@ -248,7 +218,7 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count) {
}
int lovrMeshSetDrawRange(Mesh* mesh, int start, int count) {
if (start < 0 || count < 0 || start + count > mesh->size) {
if (start < 0 || count < 0 || start + count > mesh->count) {
return 1;
}
@ -273,3 +243,25 @@ void lovrMeshSetTexture(Mesh* mesh, Texture* texture) {
lovrRetain(&mesh->texture->ref);
}
}
void* lovrMeshMap(Mesh* mesh, int start, int count) {
// Unmap because the mapped ranges aren't necessarily the same. Could be improved.
if (mesh->isMapped && (mesh->mapStart != start || mesh->mapCount != count)) {
lovrMeshUnmap(mesh);
}
mesh->isMapped = 1;
mesh->mapStart = start;
mesh->mapCount = count;
GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
return glMapBufferRange(GL_ARRAY_BUFFER, start * mesh->stride, count * mesh->stride, access);
}
void lovrMeshUnmap(Mesh* mesh) {
if (mesh->isMapped) {
mesh->isMapped = 0;
glUnmapBuffer(GL_ARRAY_BUFFER);
}
}

View File

@ -35,12 +35,13 @@ typedef vec_t(MeshAttribute) MeshFormat;
typedef struct {
Ref ref;
int size;
int count;
int stride;
void* data;
void* scratchVertex;
int enabledAttributes;
int attributesDirty;
int isMapped;
int mapStart;
int mapCount;
MeshFormat format;
MeshDrawMode drawMode;
MeshUsage usage;
@ -55,7 +56,7 @@ typedef struct {
Shader* lastShader;
} Mesh;
Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage);
Mesh* lovrMeshCreate(int count, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage);
void lovrMeshDestroy(const Ref* ref);
void lovrMeshDraw(Mesh* mesh, mat4 transform);
MeshFormat lovrMeshGetVertexFormat(Mesh* mesh);
@ -63,10 +64,6 @@ MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh);
int lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode);
int lovrMeshGetVertexCount(Mesh* mesh);
int lovrMeshGetVertexSize(Mesh* mesh);
void* lovrMeshGetScratchVertex(Mesh* mesh);
void lovrMeshGetVertex(Mesh* mesh, int index, void* dest);
void lovrMeshSetVertex(Mesh* mesh, int index, void* vertex);
void lovrMeshSetVertices(Mesh* mesh, void* vertices, int size);
unsigned int* lovrMeshGetVertexMap(Mesh* mesh, int* count);
void lovrMeshSetVertexMap(Mesh* mesh, unsigned int* map, int count);
int lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name);
@ -77,3 +74,5 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count);
int lovrMeshSetDrawRange(Mesh* mesh, int start, int count);
Texture* lovrMeshGetTexture(Mesh* mesh);
void lovrMeshSetTexture(Mesh* mesh, Texture* texture);
void* lovrMeshMap(Mesh* mesh, int start, int count);
void lovrMeshUnmap(Mesh* mesh);

View File

@ -91,7 +91,8 @@ Model* lovrModelCreate(ModelData* modelData) {
}
model->mesh = lovrMeshCreate(vertices.length / components, &format, MESH_TRIANGLES, MESH_STATIC);
lovrMeshSetVertices(model->mesh, (void*) vertices.data, vertices.length * sizeof(float));
void* data = lovrMeshMap(model->mesh, 0, vertices.length / components);
memcpy(data, vertices.data, vertices.length * sizeof(float));
lovrMeshSetVertexMap(model->mesh, indices.data, indices.length);
model->texture = NULL;