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