Buffers individually keep track of their flush range;

Fixes bugs with attached Mesh attributes, where flushing wasn't
happening when it should have.
This commit is contained in:
bjorn 2019-01-22 12:11:01 -08:00
parent 25606738c5
commit c473bf50e8
9 changed files with 40 additions and 28 deletions

View File

@ -1179,7 +1179,7 @@ static int l_lovrGraphicsNewMesh(lua_State* L) {
memcpy(vertices, vertexData->blob.data, vertexData->count * vertexData->format.stride);
}
lovrBufferFlush(vertexBuffer, 0, count * format.stride);
lovrBufferMarkRange(vertexBuffer, 0, count * format.stride);
lovrRelease(vertexBuffer);
luax_pushobject(L, mesh);

View File

@ -139,7 +139,7 @@ int l_lovrMeshSetVertex(lua_State* L) {
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
VertexPointer vertex = { .raw = lovrBufferMap(buffer, index * format->stride) };
luax_setvertex(L, 3, &vertex, format);
lovrMeshMarkVertices(mesh, index * format->stride, (index + 1) * format->stride);
lovrBufferMarkRange(buffer, index * format->stride, (index + 1) * format->stride);
return 0;
}
@ -168,7 +168,7 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
Buffer* buffer = lovrMeshGetVertexBuffer(mesh);
VertexPointer vertex = { .raw = lovrBufferMap(buffer, vertexIndex * format->stride + attribute.offset) };
luax_setvertexattribute(L, 4, &vertex, attribute);
lovrMeshMarkVertices(mesh, vertexIndex * format->stride + attribute.offset, vertexIndex * format->stride + attribute.offset + attribute.size);
lovrBufferMarkRange(buffer, vertexIndex * format->stride + attribute.offset, vertexIndex * format->stride + attribute.offset + attribute.size);
return 0;
}
@ -207,7 +207,7 @@ int l_lovrMeshSetVertices(lua_State* L) {
}
}
lovrMeshMarkVertices(mesh, start * format->stride, (start + count) * format->stride);
lovrBufferMarkRange(buffer, start * format->stride, (start + count) * format->stride);
return 0;
}
@ -270,7 +270,7 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
} else {
void* indices = lovrBufferMap(indexBuffer, 0);
memcpy(indices, blob->data, blob->size);
lovrBufferFlush(indexBuffer, 0, blob->size);
lovrBufferMarkRange(indexBuffer, 0, blob->size);
}
} else {
luaL_checktype(L, 2, LUA_TTABLE);
@ -309,7 +309,7 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
}
lovrMeshSetIndexBuffer(mesh, indexBuffer, count, size);
lovrBufferFlush(indexBuffer, 0, count * size);
lovrBufferMarkRange(indexBuffer, 0, count * size);
}
return 0;

View File

@ -32,7 +32,7 @@ int l_lovrShaderBlockSend(lua_State* L) {
Buffer* buffer = lovrShaderBlockGetBuffer(block);
uint8_t* data = lovrBufferMap(buffer, uniform->offset);
luax_checkuniform(L, 3, uniform, data, name);
lovrBufferFlush(buffer, uniform->offset, uniform->size);
lovrBufferMarkRange(buffer, uniform->offset, uniform->size);
return 0;
} else {
Blob* blob = luax_checktype(L, 1, Blob);
@ -41,7 +41,7 @@ int l_lovrShaderBlockSend(lua_State* L) {
size_t bufferSize = lovrBufferGetSize(buffer);
size_t copySize = MIN(bufferSize, blob->size);
memcpy(data, blob->data, copySize);
lovrBufferFlush(buffer, 0, copySize);
lovrBufferMarkRange(buffer, 0, copySize);
lua_pushinteger(L, copySize);
return 1;
}

View File

@ -11,3 +11,19 @@ bool lovrBufferIsReadable(Buffer* buffer) {
BufferUsage lovrBufferGetUsage(Buffer* buffer) {
return buffer->usage;
}
void lovrBufferMarkRange(Buffer* buffer, size_t offset, size_t size) {
size_t end = offset + size;
buffer->flushFrom = MIN(buffer->flushFrom, offset);
buffer->flushTo = MAX(buffer->flushTo, end);
}
void lovrBufferFlush(Buffer* buffer) {
if (buffer->flushTo < buffer->flushFrom) {
return;
}
lovrBufferFlushRange(buffer, buffer->flushFrom, buffer->flushTo - buffer->flushFrom);
buffer->flushFrom = SIZE_MAX;
buffer->flushTo = -SIZE_MAX;
}

View File

@ -24,6 +24,8 @@ typedef struct {
Ref ref;
void* data;
size_t size;
size_t flushFrom;
size_t flushTo;
bool readable;
BufferType type;
BufferUsage usage;
@ -37,4 +39,6 @@ size_t lovrBufferGetSize(Buffer* buffer);
bool lovrBufferIsReadable(Buffer* buffer);
BufferUsage lovrBufferGetUsage(Buffer* buffer);
void* lovrBufferMap(Buffer* buffer, size_t offset);
void lovrBufferFlush(Buffer* buffer, size_t offset, size_t size);
void lovrBufferFlushRange(Buffer* buffer, size_t offset, size_t size);
void lovrBufferMarkRange(Buffer* buffer, size_t offset, size_t size);
void lovrBufferFlush(Buffer* buffer);

View File

@ -65,7 +65,7 @@ static void lovrGraphicsInitBuffers() {
state.identityBuffer = lovrBufferCreate(256, NULL, BUFFER_VERTEX, USAGE_STATIC, false);
uint8_t* id = lovrBufferMap(state.identityBuffer, 0);
for (int i = 0; i < 256; i++) id[i] = i;
lovrBufferFlush(state.identityBuffer, 0, 256);
lovrBufferFlushRange(state.identityBuffer, 0, 256);
VertexFormat empty = { .count = 0 };
Buffer* vertexBuffer = state.buffers[STREAM_VERTEX];
@ -743,23 +743,23 @@ void lovrGraphicsFlush() {
// Flush vertex buffer
if (flushGeometry && batch->vertexCount > 0) {
size_t stride = BUFFER_STRIDES[STREAM_VERTEX];
lovrBufferFlush(state.buffers[STREAM_VERTEX], batch->vertexStart * stride, batch->vertexCount * stride);
lovrBufferFlushRange(state.buffers[STREAM_VERTEX], batch->vertexStart * stride, batch->vertexCount * stride);
if (!instanced) {
lovrBufferFlush(state.buffers[STREAM_DRAW_ID], batch->vertexStart, batch->vertexCount);
lovrBufferFlushRange(state.buffers[STREAM_DRAW_ID], batch->vertexStart, batch->vertexCount);
}
}
// Flush index buffer
if (flushGeometry && batch->indexCount > 0) {
size_t stride = BUFFER_STRIDES[STREAM_INDEX];
lovrBufferFlush(state.buffers[STREAM_INDEX], batch->indexStart * stride, batch->indexCount * stride);
lovrBufferFlushRange(state.buffers[STREAM_INDEX], batch->indexStart * stride, batch->indexCount * stride);
}
// Flush draw data buffer
size_t drawDataOffset = batch->drawStart * BUFFER_STRIDES[STREAM_DRAW_DATA];
size_t drawDataSize = batch->drawCount * BUFFER_STRIDES[STREAM_DRAW_DATA];
lovrBufferFlush(state.buffers[STREAM_DRAW_DATA], drawDataOffset, drawDataSize);
lovrBufferFlushRange(state.buffers[STREAM_DRAW_DATA], drawDataOffset, drawDataSize);
lovrShaderSetBlock(batch->shader, "lovrDrawData", state.buffers[STREAM_DRAW_DATA], drawDataOffset, state.maxDraws * BUFFER_STRIDES[STREAM_DRAW_DATA], ACCESS_READ);
// Uniforms

View File

@ -25,11 +25,6 @@ size_t lovrMeshGetIndexSize(Mesh* mesh) {
return mesh->indexSize;
}
void lovrMeshMarkVertices(Mesh* mesh, size_t start, size_t end) {
mesh->flushStart = MIN(mesh->flushStart, start);
mesh->flushEnd = MAX(mesh->flushEnd, end);
}
void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute) {
lovrAssert(!map_get(&mesh->attributes, name), "Mesh already has an attribute named '%s'", name);
lovrAssert(attribute->divisor >= 0, "Divisor can't be negative");

View File

@ -41,8 +41,6 @@ typedef struct {
uint32_t vertexCount;
uint32_t indexCount;
size_t indexSize;
size_t flushStart;
size_t flushEnd;
uint32_t drawStart;
uint32_t drawCount;
Material* material;
@ -61,7 +59,6 @@ void lovrMeshSetIndexBuffer(Mesh* mesh, Buffer* buffer, uint32_t indexCount, siz
uint32_t lovrMeshGetVertexCount(Mesh* mesh);
uint32_t lovrMeshGetIndexCount(Mesh* mesh);
size_t lovrMeshGetIndexSize(Mesh* mesh);
void lovrMeshMarkVertices(Mesh* mesh, size_t start, size_t end);
void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute);
void lovrMeshDetachAttribute(Mesh* mesh, const char* name);
MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, const char* name);

View File

@ -470,6 +470,7 @@ static void lovrGpuBindMesh(Mesh* mesh, Shader* shader, int divisorMultiplier) {
if (mesh->indexBuffer && mesh->indexCount > 0) {
lovrGpuBindBuffer(BUFFER_INDEX, mesh->indexBuffer->id, true);
lovrBufferFlush(mesh->indexBuffer);
#ifndef EMSCRIPTEN
uint32_t primitiveRestart = (1 << (mesh->indexSize * 8)) - 1;
if (state.primitiveRestart != primitiveRestart) {
@ -479,11 +480,6 @@ static void lovrGpuBindMesh(Mesh* mesh, Shader* shader, int divisorMultiplier) {
#endif
}
if (mesh->flushEnd > 0) {
lovrBufferFlush(mesh->vertexBuffer, mesh->flushStart, mesh->flushEnd - mesh->flushStart);
mesh->flushStart = mesh->flushEnd = 0;
}
while ((key = map_next(&mesh->attributes, &iter)) != NULL) {
int location = lovrShaderGetAttributeId(shader, key);
@ -497,6 +493,10 @@ static void lovrGpuBindMesh(Mesh* mesh, Shader* shader, int divisorMultiplier) {
MeshAttribute previous = mesh->layout[i];
MeshAttribute current = layout[i];
if (current.enabled) {
lovrBufferFlush(current.buffer);
}
if (!memcmp(&previous, &current, sizeof(MeshAttribute))) {
continue;
}
@ -1577,7 +1577,7 @@ void* lovrBufferMap(Buffer* buffer, size_t offset) {
return (uint8_t*) buffer->data + offset;
}
void lovrBufferFlush(Buffer* buffer, size_t offset, size_t size) {
void lovrBufferFlushRange(Buffer* buffer, size_t offset, size_t size) {
lovrGpuBindBuffer(buffer->type, buffer->id, false);
#ifndef EMSCRIPTEN
if (GLAD_GL_ARB_buffer_storage) {