Add Buffer objects;

This commit is contained in:
bjorn 2018-12-06 16:14:30 -08:00
parent b586bc2cce
commit ac33b8b085
3 changed files with 135 additions and 6 deletions

20
src/graphics/buffer.h Normal file
View File

@ -0,0 +1,20 @@
#include <stdlib.h>
#pragma once
typedef enum {
USAGE_STATIC,
USAGE_DYNAMIC,
USAGE_STREAM
} BufferUsage;
typedef struct Buffer Buffer;
Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage);
void lovrBufferDestroy(void* ref);
size_t lovrBufferGetSize(Buffer* buffer);
BufferUsage lovrBufferGetUsage(Buffer* buffer);
void* lovrBufferMap(Buffer* buffer, size_t offset, size_t size);
void lovrBufferFlush(Buffer* buffer, size_t offset, size_t size);
void lovrBufferLock(Buffer* buffer);
void lovrBufferUnlock(Buffer* buffer);

View File

@ -1,4 +1,5 @@
#include "graphics/graphics.h"
#include "graphics/buffer.h"
#include "graphics/canvas.h"
#include "graphics/mesh.h"
#include "graphics/shader.h"
@ -70,6 +71,7 @@ static struct {
uint32_t blockBuffers[2][MAX_BLOCK_BUFFERS];
uint32_t vertexArray;
uint32_t vertexBuffer;
uint32_t genericBuffer;
float viewports[2][4];
vec_void_t incoherents[MAX_BARRIERS];
bool srgb;
@ -78,6 +80,15 @@ static struct {
GpuStats stats;
} state;
struct Buffer {
Ref ref;
void* data;
size_t size;
uint32_t id;
GLsync lock;
BufferUsage usage;
};
struct ShaderBlock {
Ref ref;
BlockType type;
@ -596,6 +607,13 @@ static void lovrGpuBindVertexBuffer(uint32_t vertexBuffer) {
}
}
static void lovrGpuBindGenericBuffer(uint32_t buffer) {
if (state.genericBuffer != buffer) {
state.genericBuffer = buffer;
glBindBuffer(GL_COPY_WRITE_BUFFER, buffer);
}
}
static void lovrGpuUseProgram(uint32_t program) {
if (state.program != program) {
state.program = program;
@ -1480,6 +1498,102 @@ TextureData* lovrCanvasNewTextureData(Canvas* canvas, int index) {
return textureData;
}
// Buffer
Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage) {
Buffer* buffer = lovrAlloc(Buffer, lovrBufferDestroy);
if (!buffer) return NULL;
buffer->size = size;
buffer->usage = usage;
glGenBuffers(1, &buffer->id);
lovrGpuBindGenericBuffer(buffer->id);
#ifndef EMSCRIPTEN
if (GLAD_GL_ARB_buffer_storage) {
GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
glBufferStorage(GL_COPY_WRITE_BUFFER, size, data, flags);
if (usage != USAGE_STATIC) {
buffer->data = glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, size, flags | GL_MAP_FLUSH_EXPLICIT_BIT);
}
} else {
#endif
buffer->data = calloc(1, size);
glBufferData(GL_COPY_WRITE_BUFFER, size, data, convertBufferUsage(usage));
if (data) {
memcpy(buffer->data, data, size);
}
#ifndef EMSCRIPTEN
}
#endif
return buffer;
}
void lovrBufferDestroy(void* ref) {
Buffer* buffer = ref;
glDeleteBuffers(1, &buffer->id);
if (buffer->data) {
free(buffer->data);
}
free(ref);
}
size_t lovrBufferGetSize(Buffer* buffer) {
return buffer->size;
}
BufferUsage lovrBufferGetUsage(Buffer* buffer) {
return buffer->usage;
}
void* lovrBufferMap(Buffer* buffer, size_t offset, size_t size) {
return (uint8_t*) buffer->data + offset;
}
void lovrBufferFlush(Buffer* buffer, size_t offset, size_t size) {
lovrAssert(buffer->usage != USAGE_STATIC, "Static buffers may not be updated");
lovrGpuBindGenericBuffer(buffer->id);
#ifndef EMSCRIPTEN
if (GLAD_GL_ARB_buffer_storage) {
glFlushMappedBufferRange(GL_COPY_WRITE_BUFFER, offset, size);
} else {
#endif
glBufferSubData(GL_COPY_WRITE_BUFFER, offset, size, (GLvoid*) ((uint8_t*) buffer->data + offset));
#ifndef EMSCRIPTEN
}
#endif
}
void lovrBufferLock(Buffer* buffer) {
#ifndef EMSCRIPTEN
if (!GLAD_GL_ARB_buffer_storage || buffer->usage == USAGE_STATIC) {
return;
}
lovrBufferUnlock(buffer);
buffer->lock = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
#endif
}
void lovrBufferUnlock(Buffer* buffer) {
#ifndef EMSCRIPTEN
if (!GLAD_GL_ARB_buffer_storage || buffer->usage == USAGE_STATIC || !buffer->lock) {
return;
}
if (glClientWaitSync(buffer->lock, 0, 0) == GL_TIMEOUT_EXPIRED) {
while (glClientWaitSync(buffer->lock, GL_SYNC_FLUSH_COMMANDS_BIT, 1E9) == GL_TIMEOUT_EXPIRED) {
continue;
}
}
glDeleteSync(buffer->lock);
buffer->lock = NULL;
#endif
}
// Shader
static GLuint compileShader(GLenum type, const char** sources, int count) {

View File

@ -1,3 +1,4 @@
#include "graphics/buffer.h"
#include "graphics/texture.h"
#include "lib/map/map.h"
#include "lib/vec/vec.h"
@ -8,12 +9,6 @@
#define LOVR_MAX_UNIFORM_LENGTH 64
#define LOVR_MAX_ATTRIBUTE_LENGTH 64
typedef enum {
USAGE_STATIC,
USAGE_DYNAMIC,
USAGE_STREAM
} BufferUsage;
typedef enum {
ACCESS_READ,
ACCESS_WRITE,