Treat UBOs and SSBOs more similarly to reduce duplication;

This commit is contained in:
bjorn 2018-08-03 11:34:11 -07:00
parent 76fb1681fa
commit f6f322fc7f
3 changed files with 35 additions and 61 deletions

View File

@ -909,8 +909,8 @@ int l_lovrGraphicsNewShaderBlock(lua_State* L) {
lua_pop(L, 1);
}
BlockType type = BLOCK_UNIFORM;
BufferUsage usage = USAGE_DYNAMIC;
bool writable = false;
if (lua_istable(L, 2)) {
lua_getfield(L, 2, "usage");
@ -918,11 +918,11 @@ int l_lovrGraphicsNewShaderBlock(lua_State* L) {
lua_pop(L, 1);
lua_getfield(L, 2, "writable");
writable = lua_toboolean(L, -1);
type = lua_toboolean(L, -1) ? BLOCK_STORAGE : BLOCK_UNIFORM;
lua_pop(L, 1);
}
ShaderBlock* block = lovrShaderBlockCreate(&uniforms, writable, usage);
ShaderBlock* block = lovrShaderBlockCreate(&uniforms, type, usage);
luax_pushobject(L, block);
vec_deinit(&uniforms);
return 1;

View File

@ -23,8 +23,7 @@
// Types
#define MAX_TEXTURES 16
#define MAX_STORAGE_BUFFERS 8
#define MAX_UNIFORM_BUFFERS 32
#define MAX_BLOCK_BUFFERS 8
#define LOVR_SHADER_POSITION 0
#define LOVR_SHADER_NORMAL 1
@ -55,8 +54,7 @@ static struct {
uint32_t indexBuffer;
uint32_t program;
Texture* textures[MAX_TEXTURES];
uint32_t storageBuffers[MAX_STORAGE_BUFFERS];
uint32_t uniformBuffers[MAX_UNIFORM_BUFFERS];
uint32_t blockBuffers[2][MAX_BLOCK_BUFFERS];
uint32_t vertexArray;
uint32_t vertexBuffer;
float viewport[4];
@ -68,11 +66,12 @@ static struct {
struct ShaderBlock {
Ref ref;
bool writable;
BlockType type;
BufferUsage usage;
vec_uniform_t uniforms;
map_int_t uniformMap;
uint32_t buffer;
GLenum target;
size_t size;
void* data;
bool mapped;
@ -88,11 +87,6 @@ typedef struct {
typedef vec_t(UniformBlock) vec_block_t;
enum {
BLOCK_UNIFORM,
BLOCK_STORAGE
};
struct Shader {
Ref ref;
uint32_t program;
@ -370,17 +364,10 @@ void lovrGpuDirtyTexture(int slot) {
state.textures[slot] = NULL;
}
static void lovrGpuBindStorageBuffer(uint32_t buffer, int slot) {
if (state.storageBuffers[slot] != buffer) {
state.storageBuffers[slot] = buffer;
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, buffer);
}
}
static void lovrGpuBindUniformBuffer(uint32_t buffer, int slot) {
if (state.uniformBuffers[slot] != buffer) {
state.uniformBuffers[slot] = buffer;
glBindBufferBase(GL_UNIFORM_BUFFER, slot, buffer);
static void lovrGpuBindBlockBuffer(BlockType type, uint32_t buffer, int slot) {
if (state.blockBuffers[type][slot] != buffer) {
state.blockBuffers[type][slot] = buffer;
glBindBufferBase(type == BLOCK_UNIFORM ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER, slot, buffer);
}
}
@ -1529,22 +1516,14 @@ void lovrShaderBind(Shader* shader) {
// Bind uniform blocks
UniformBlock* block;
vec_foreach_ptr(&shader->blocks[BLOCK_UNIFORM], block, i) {
if (block->source) {
lovrShaderBlockUnmap(block->source);
lovrGpuBindUniformBuffer(block->source->buffer, block->binding);
} else {
lovrGpuBindUniformBuffer(0, block->binding);
}
}
// Bind storage blocks
vec_foreach_ptr(&shader->blocks[BLOCK_STORAGE], block, i) {
if (block->source) {
lovrShaderBlockUnmap(block->source);
lovrGpuBindStorageBuffer(block->source->buffer, block->binding);
} else {
lovrGpuBindStorageBuffer(0, block->binding);
for (BlockType type = BLOCK_UNIFORM; type <= BLOCK_STORAGE; type++) {
vec_foreach_ptr(&shader->blocks[type], block, i) {
if (block->source) {
lovrShaderBlockUnmap(block->source);
lovrGpuBindBlockBuffer(type, block->source->buffer, block->binding);
} else {
lovrGpuBindBlockBuffer(type, 0, block->binding);
}
}
}
}
@ -1636,7 +1615,7 @@ void lovrShaderSetBlock(Shader* shader, const char* name, ShaderBlock* source) {
// ShaderBlock
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms, bool writable, BufferUsage usage) {
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms, BlockType type, BufferUsage usage) {
ShaderBlock* block = lovrAlloc(ShaderBlock, lovrShaderBlockDestroy);
if (!block) return NULL;
@ -1662,20 +1641,16 @@ ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms, bool writable, Buffe
map_set(&block->uniformMap, uniform->name, i);
}
glGenBuffers(1, &block->buffer);
if (writable) {
lovrGpuBindStorageBuffer(block->buffer, 0);
glBufferData(GL_SHADER_STORAGE_BUFFER, size, NULL, usage);
} else {
lovrGpuBindUniformBuffer(block->buffer, 0);
glBufferData(GL_UNIFORM_BUFFER, size, NULL, usage);
}
block->writable = writable;
block->target = block->type == BLOCK_UNIFORM ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
block->type = type;
block->usage = usage;
block->size = size;
block->data = calloc(1, size);
glGenBuffers(1, &block->buffer);
lovrGpuBindBlockBuffer(block->type, block->buffer, 0);
glBufferData(block->target, size, NULL, usage);
return block;
}
@ -1709,15 +1684,9 @@ void lovrShaderBlockUnmap(ShaderBlock* block) {
return;
}
if (block->writable) {
lovrGpuBindStorageBuffer(block->buffer, 0);
} else {
lovrGpuBindUniformBuffer(block->buffer, 0);
}
GLenum binding = block->writable ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER;
glBufferData(binding, block->size, NULL, block->usage);
glBufferSubData(binding, 0, block->size, block->data);
lovrGpuBindBlockBuffer(block->type, block->buffer, 0);
glBufferData(block->target, block->size, NULL, block->usage);
glBufferSubData(block->target, 0, block->size, block->data);
block->mapped = false;
}

View File

@ -14,6 +14,11 @@ typedef enum {
USAGE_STREAM
} BufferUsage;
typedef enum {
BLOCK_UNIFORM,
BLOCK_STORAGE
} BlockType;
typedef enum {
UNIFORM_FLOAT,
UNIFORM_MATRIX,
@ -67,7 +72,7 @@ void lovrShaderSetTexture(Shader* shader, const char* name, Texture** data, int
ShaderBlock* lovrShaderGetBlock(Shader* shader, const char* name);
void lovrShaderSetBlock(Shader* shader, const char* name, ShaderBlock* block);
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms, bool writable, BufferUsage usage);
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms, BlockType type, BufferUsage usage);
void lovrShaderBlockDestroy(void* ref);
size_t lovrShaderBlockGetSize(ShaderBlock* block);
const Uniform* lovrShaderBlockGetUniform(ShaderBlock* block, const char* name);