mirror of https://github.com/bjornbytes/lovr.git
Reorganize uniform/block data structures;
This commit is contained in:
parent
e8afcb9b71
commit
a372abb810
|
@ -854,7 +854,8 @@ int l_lovrGraphicsNewAnimator(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrGraphicsNewShaderBlock(lua_State* L) {
|
||||
Uniform uniforms[MAX_SHADER_BLOCK_UNIFORMS];
|
||||
vec_uniform_t uniforms;
|
||||
vec_init(&uniforms);
|
||||
int count = 0;
|
||||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
@ -872,44 +873,47 @@ int l_lovrGraphicsNewShaderBlock(lua_State* L) {
|
|||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
|
||||
// Name
|
||||
Uniform* uniform = &uniforms[count++];
|
||||
strncpy(uniform->name, lua_tostring(L, -2), LOVR_MAX_UNIFORM_LENGTH - 1);
|
||||
Uniform uniform;
|
||||
strncpy(uniform.name, lua_tostring(L, -2), LOVR_MAX_UNIFORM_LENGTH - 1);
|
||||
|
||||
// Count
|
||||
lua_getfield(L, -1, "count");
|
||||
uniform->count = lua_type(L, -1) == LUA_TNUMBER ? lua_tonumber(L, -1) : 1;
|
||||
uniform.count = lua_type(L, -1) == LUA_TNUMBER ? lua_tonumber(L, -1) : 1;
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Type
|
||||
size_t length;
|
||||
lua_getfield(L, -1, "type");
|
||||
const char* type = lua_tolstring(L, -1, &length);
|
||||
uniform->components = 1;
|
||||
uniform.components = 1;
|
||||
if (strcmp(type, "float")) {
|
||||
uniform->type = UNIFORM_FLOAT;
|
||||
uniform.type = UNIFORM_FLOAT;
|
||||
} else if (strcmp(type, "int")) {
|
||||
uniform->type = UNIFORM_INT;
|
||||
uniform.type = UNIFORM_INT;
|
||||
} else {
|
||||
uniform->components = type[length - 1] - '0';
|
||||
lovrAssert(uniform->components >= 2 && uniform->components <= 4, "Unknown uniform type '%s'", type);
|
||||
uniform.components = type[length - 1] - '0';
|
||||
lovrAssert(uniform.components >= 2 && uniform.components <= 4, "Unknown uniform type '%s'", type);
|
||||
if (!strncmp(type, "vec", 3 * sizeof(char)) && length == 4) {
|
||||
uniform->type = UNIFORM_FLOAT;
|
||||
uniform.type = UNIFORM_FLOAT;
|
||||
} else if (!strncmp(type, "ivec", 4 * sizeof(char)) && length == 5) {
|
||||
uniform->type = UNIFORM_INT;
|
||||
uniform.type = UNIFORM_INT;
|
||||
} else if (!strncmp(type, "mat", 3 * sizeof(char)) && length == 4) {
|
||||
uniform->type = UNIFORM_MATRIX;
|
||||
uniform.type = UNIFORM_MATRIX;
|
||||
} else {
|
||||
lovrThrow("Unknown uniform type '%s'", type);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
vec_push(&uniforms, uniform);
|
||||
|
||||
// Pop the table, leaving the key for lua_next
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
ShaderBlock* block = lovrShaderBlockCreate(uniforms, count);
|
||||
ShaderBlock* block = lovrShaderBlockCreate(&uniforms);
|
||||
luax_pushtype(L, ShaderBlock, block);
|
||||
vec_deinit(&uniforms);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
struct TempData {
|
||||
void* data;
|
||||
size_t size;
|
||||
int size;
|
||||
};
|
||||
|
||||
static struct TempData tempData;
|
||||
|
@ -23,7 +23,7 @@ int l_lovrShaderSend(lua_State* L) {
|
|||
|
||||
int count;
|
||||
int components;
|
||||
size_t size;
|
||||
int size;
|
||||
UniformType type;
|
||||
bool present = lovrShaderGetUniform(shader, name, &count, &components, &size, &type);
|
||||
|
||||
|
|
|
@ -67,8 +67,7 @@ static struct {
|
|||
|
||||
struct ShaderBlock {
|
||||
Ref ref;
|
||||
Uniform uniforms[32];
|
||||
int uniformCount;
|
||||
vec_uniform_t uniforms;
|
||||
uint32_t buffer;
|
||||
};
|
||||
|
||||
|
@ -76,16 +75,19 @@ typedef struct {
|
|||
int index;
|
||||
int binding;
|
||||
ShaderBlock* source;
|
||||
vec_uniform_t uniforms;
|
||||
} UniformBlock;
|
||||
|
||||
typedef map_t(UniformBlock) map_block_t;
|
||||
typedef vec_t(UniformBlock) vec_block_t;
|
||||
|
||||
struct Shader {
|
||||
Ref ref;
|
||||
uint32_t program;
|
||||
map_uniform_t uniforms;
|
||||
map_block_t blocks;
|
||||
vec_uniform_t uniforms;
|
||||
vec_block_t blocks;
|
||||
map_int_t attributes;
|
||||
map_int_t uniformMap;
|
||||
map_int_t blockMap;
|
||||
};
|
||||
|
||||
struct Texture {
|
||||
|
@ -1239,12 +1241,28 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) {
|
|||
glVertexAttribI4iv(LOVR_SHADER_BONES, (int[4]) { 0., 0., 0., 0. });
|
||||
glVertexAttrib4fv(LOVR_SHADER_BONE_WEIGHTS, (float[4]) { 1., 0., 0., 0. });
|
||||
|
||||
// Uniform blocks
|
||||
int32_t blockCount;
|
||||
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount);
|
||||
map_init(&shader->blockMap);
|
||||
vec_init(&shader->blocks);
|
||||
vec_reserve(&shader->blocks, blockCount);
|
||||
for (int i = 0; i < blockCount; i++) {
|
||||
UniformBlock block = { .index = i, .binding = i + 1, .source = NULL };
|
||||
glUniformBlockBinding(program, block.index, block.binding);
|
||||
vec_init(&block.uniforms);
|
||||
|
||||
char name[LOVR_MAX_UNIFORM_LENGTH];
|
||||
glGetActiveUniformBlockName(program, i, LOVR_MAX_UNIFORM_LENGTH, NULL, name);
|
||||
map_set(&shader->blockMap, name, i);
|
||||
}
|
||||
|
||||
// Uniform introspection
|
||||
int32_t uniformCount;
|
||||
int textureSlot = 0;
|
||||
map_init(&shader->uniforms);
|
||||
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformCount);
|
||||
for (int i = 0; i < uniformCount; i++) {
|
||||
for (uint32_t i = 0; i < (uint32_t) uniformCount; i++) {
|
||||
Uniform uniform;
|
||||
GLenum glType;
|
||||
glGetActiveUniform(program, i, LOVR_MAX_UNIFORM_LENGTH, NULL, &uniform.count, &glType, uniform.name);
|
||||
|
@ -1259,7 +1277,16 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) {
|
|||
uniform.components = getUniformComponents(glType);
|
||||
uniform.baseTextureSlot = (uniform.type == UNIFORM_SAMPLER) ? textureSlot : -1;
|
||||
|
||||
if (uniform.location == -1) {
|
||||
int blockIndex;
|
||||
glGetActiveUniformsiv(program, 1, &i, GL_UNIFORM_BLOCK_INDEX, &blockIndex);
|
||||
|
||||
if (blockIndex != -1) {
|
||||
UniformBlock* block = &shader->blocks.data[i];
|
||||
glGetActiveUniformsiv(program, 1, &i, GL_UNIFORM_OFFSET, &uniform.offset);
|
||||
glGetActiveUniformsiv(program, 1, &i, GL_UNIFORM_SIZE, &uniform.size);
|
||||
vec_push(&block->uniforms, uniform);
|
||||
continue;
|
||||
} else if (uniform.location == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1322,22 +1349,11 @@ Shader* lovrShaderCreate(const char* vertexSource, const char* fragmentSource) {
|
|||
}
|
||||
}
|
||||
|
||||
map_set(&shader->uniforms, uniform.name, uniform);
|
||||
map_set(&shader->uniformMap, uniform.name, shader->uniforms.length);
|
||||
vec_push(&shader->uniforms, uniform);
|
||||
textureSlot += (uniform.type == UNIFORM_SAMPLER) ? uniform.count : 0;
|
||||
}
|
||||
|
||||
// Uniform blocks
|
||||
int32_t blockCount;
|
||||
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &blockCount);
|
||||
map_init(&shader->blocks);
|
||||
for (int i = 0; i < blockCount; i++) {
|
||||
char name[LOVR_MAX_UNIFORM_LENGTH];
|
||||
glGetActiveUniformBlockName(program, i, LOVR_MAX_UNIFORM_LENGTH, NULL, name);
|
||||
UniformBlock block = { .index = i, .binding = i + 1, .source = NULL };
|
||||
glUniformBlockBinding(program, block.index, block.binding);
|
||||
map_set(&shader->blocks, name, block);
|
||||
}
|
||||
|
||||
// Attribute cache
|
||||
int32_t attributeCount;
|
||||
glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attributeCount);
|
||||
|
@ -1367,23 +1383,21 @@ Shader* lovrShaderCreateDefault(DefaultShader type) {
|
|||
void lovrShaderDestroy(void* ref) {
|
||||
Shader* shader = ref;
|
||||
glDeleteProgram(shader->program);
|
||||
const char* key;
|
||||
map_iter_t iter = map_iter(&shader->uniforms);
|
||||
while ((key = map_next(&shader->uniforms, &iter)) != NULL) {
|
||||
Uniform* uniform = map_get(&shader->uniforms, key);
|
||||
free(uniform->value.data);
|
||||
for (int i = 0; i < shader->uniforms.length; i++) {
|
||||
free(shader->uniforms.data[i].value.data);
|
||||
}
|
||||
map_deinit(&shader->uniforms);
|
||||
vec_deinit(&shader->uniforms);
|
||||
vec_deinit(&shader->blocks);
|
||||
map_deinit(&shader->attributes);
|
||||
map_deinit(&shader->uniformMap);
|
||||
map_deinit(&shader->blockMap);
|
||||
free(shader);
|
||||
}
|
||||
|
||||
void lovrShaderBind(Shader* shader) {
|
||||
map_iter_t iter = map_iter(&shader->uniforms);
|
||||
const char* key;
|
||||
while ((key = map_next(&shader->uniforms, &iter)) != NULL) {
|
||||
Uniform* uniform = map_get(&shader->uniforms, key);
|
||||
|
||||
int i;
|
||||
Uniform* uniform;
|
||||
vec_foreach_ptr(&shader->uniforms, uniform, i) {
|
||||
if (uniform->type != UNIFORM_SAMPLER && !uniform->dirty) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1427,9 +1441,8 @@ void lovrShaderBind(Shader* shader) {
|
|||
}
|
||||
}
|
||||
|
||||
iter = map_iter(&shader->blocks);
|
||||
while ((key = map_next(&shader->blocks, &iter)) != NULL) {
|
||||
UniformBlock* block = map_get(&shader->blocks, key);
|
||||
UniformBlock* block;
|
||||
vec_foreach_ptr(&shader->blocks, block, i) {
|
||||
lovrGpuBindUniformBuffer(block->source ? block->source->buffer : 0, block->binding);
|
||||
}
|
||||
}
|
||||
|
@ -1440,15 +1453,17 @@ int lovrShaderGetAttributeId(Shader* shader, const char* name) {
|
|||
}
|
||||
|
||||
bool lovrShaderHasUniform(Shader* shader, const char* name) {
|
||||
return map_get(&shader->uniforms, name) != NULL;
|
||||
return map_get(&shader->uniformMap, name) != NULL;
|
||||
}
|
||||
|
||||
bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* components, size_t* size, UniformType* type) {
|
||||
Uniform* uniform = map_get(&shader->uniforms, name);
|
||||
if (!uniform) {
|
||||
bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* components, int* size, UniformType* type) {
|
||||
int* index = map_get(&shader->uniformMap, name);
|
||||
if (!index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Uniform* uniform = &shader->uniforms.data[*index];
|
||||
|
||||
*count = uniform->count;
|
||||
*components = uniform->components;
|
||||
*size = uniform->size;
|
||||
|
@ -1456,15 +1471,16 @@ bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* com
|
|||
return true;
|
||||
}
|
||||
|
||||
static void lovrShaderSetUniform(Shader* shader, const char* name, UniformType type, void* data, int count, size_t size, const char* debug) {
|
||||
Uniform* uniform = map_get(&shader->uniforms, name);
|
||||
if (!uniform) {
|
||||
static void lovrShaderSetUniform(Shader* shader, const char* name, UniformType type, void* data, int count, int size, const char* debug) {
|
||||
int* index = map_get(&shader->uniformMap, name);
|
||||
if (!index) {
|
||||
return;
|
||||
}
|
||||
|
||||
Uniform* uniform = &shader->uniforms.data[*index];
|
||||
const char* plural = (uniform->size / size) > 1 ? "s" : "";
|
||||
lovrAssert(uniform->type == type, "Unable to send %ss to uniform %s", debug, uniform->name);
|
||||
lovrAssert(count * size <= uniform->size, "Expected at most %d %s%s for uniform %s, got %d", uniform->size / size, debug, plural, uniform->name, count);
|
||||
lovrAssert(uniform->type == type, "Unable to send %ss to uniform %s", debug, name);
|
||||
lovrAssert(count * size <= uniform->size, "Expected at most %d %s%s for uniform %s, got %d", uniform->size / size, debug, plural, name, count);
|
||||
|
||||
if (!uniform->dirty && !memcmp(uniform->value.data, data, count * size)) {
|
||||
return;
|
||||
|
@ -1492,37 +1508,36 @@ void lovrShaderSetTexture(Shader* shader, const char* name, Texture** data, int
|
|||
|
||||
// ShaderBlock
|
||||
|
||||
ShaderBlock* lovrShaderBlockCreate(Uniform uniforms[MAX_SHADER_BLOCK_UNIFORMS], int uniformCount) {
|
||||
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms) {
|
||||
ShaderBlock* block = lovrAlloc(sizeof(ShaderBlock), lovrShaderBlockDestroy);
|
||||
if (!block) return NULL;
|
||||
|
||||
memcpy(block->uniforms, uniforms, MAX_SHADER_BLOCK_UNIFORMS * sizeof(Uniform));
|
||||
block->uniformCount = uniformCount;
|
||||
vec_init(&block->uniforms);
|
||||
vec_extend(&block->uniforms, uniforms);
|
||||
|
||||
size_t offset = 0;
|
||||
for (int i = 0; i < uniformCount; i++) {
|
||||
uniforms[i].offset = offset;
|
||||
if (uniforms[i].type != UNIFORM_MATRIX) {
|
||||
if (uniforms[i].count == 1) {
|
||||
offset += 4;
|
||||
} else {
|
||||
offset += uniforms[i].count * 16;
|
||||
}
|
||||
int i;
|
||||
Uniform* uniform;
|
||||
size_t size = 0;
|
||||
vec_foreach_ptr(&block->uniforms, uniform, i) {
|
||||
uniform->offset = size;
|
||||
if (uniform->type == UNIFORM_MATRIX) {
|
||||
size += uniform->components * uniform->components * 4;
|
||||
} else {
|
||||
offset += uniforms[i].components * uniforms[i].components * 4;
|
||||
size += uniform->count == 1 ? 4 : (uniform->count * 16);
|
||||
}
|
||||
}
|
||||
|
||||
size_t totalSize = offset;
|
||||
glGenBuffers(1, &block->buffer);
|
||||
lovrGpuBindUniformBuffer(block->buffer, 0);
|
||||
glBufferData(GL_UNIFORM_BUFFER, totalSize, NULL, GL_STATIC_DRAW);
|
||||
glBufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STATIC_DRAW);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void lovrShaderBlockDestroy(void* ref) {
|
||||
free(ref);
|
||||
UniformBlock* block = ref;
|
||||
vec_deinit(&block->uniforms);
|
||||
free(block);
|
||||
}
|
||||
|
||||
// Mesh
|
||||
|
|
|
@ -30,8 +30,8 @@ typedef struct {
|
|||
int components;
|
||||
int count;
|
||||
int location;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
int offset;
|
||||
int size;
|
||||
union {
|
||||
void* data;
|
||||
int* ints;
|
||||
|
@ -42,7 +42,7 @@ typedef struct {
|
|||
bool dirty;
|
||||
} Uniform;
|
||||
|
||||
typedef map_t(Uniform) map_uniform_t;
|
||||
typedef vec_t(Uniform) vec_uniform_t;
|
||||
|
||||
typedef struct Shader Shader;
|
||||
|
||||
|
@ -52,7 +52,7 @@ void lovrShaderDestroy(void* ref);
|
|||
void lovrShaderBind(Shader* shader);
|
||||
int lovrShaderGetAttributeId(Shader* shader, const char* name);
|
||||
bool lovrShaderHasUniform(Shader* shader, const char* name);
|
||||
bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* components, size_t* size, UniformType* type);
|
||||
bool lovrShaderGetUniform(Shader* shader, const char* name, int* count, int* components, int* size, UniformType* type);
|
||||
void lovrShaderSetFloat(Shader* shader, const char* name, float* data, int count);
|
||||
void lovrShaderSetInt(Shader* shader, const char* name, int* data, int count);
|
||||
void lovrShaderSetMatrix(Shader* shader, const char* name, float* data, int count);
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
|
||||
typedef struct ShaderBlock ShaderBlock;
|
||||
|
||||
ShaderBlock* lovrShaderBlockCreate(Uniform uniforms[MAX_SHADER_BLOCK_UNIFORMS], int uniformCount);
|
||||
ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms);
|
||||
void lovrShaderBlockDestroy(void* ref);
|
||||
|
|
Loading…
Reference in New Issue