Browse Source

add parseUniformBlocks() and updated related structs

main
cinnaboot 5 years ago
parent
commit
56ac0b5440
  1. 155
      src/shader.cpp
  2. 24
      src/shader.h

155
src/shader.cpp

@ -18,8 +18,13 @@
// NOTE: forward declarations
const std::string dumpTextFile(const char* filepath);
void
bool
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx);
bool
parseUniformBlocks(memory_arena* arena, shader_program* s, GLContext* gl_ctx);
bool
parseAttributes(memory_arena* arena, shader_program* s, GLContext* gl_ctx);
void initCTXSizes(GLContext* gl_ctx);
// NOTE: interface
@ -78,24 +83,21 @@ addShaderProgram(memory_arena* arena,
initCTXSizes(gl_ctx);
dumpShader(s->prog_id);
s->model_xform_id = glGetUniformLocation(s->prog_id, "model_xform");
// FIXME: testing
// NOTE: set block binding for shader xforms uniform block
GLuint block_idx = glGetUniformBlockIndex(s->prog_id, "matrices");
glUniformBlockBinding(s->prog_id,
block_idx,
gl_ctx->xform_ubo.binding_idx);
//dumpShader(s->prog_id);
parseShaderUniforms(arena, s, gl_ctx);
///
glDetachShader(s->prog_id, vs_id);
glDetachShader(s->prog_id, fs_id);
glDeleteShader(vs_id);
glDeleteShader(fs_id);
if (parseShaderUniforms(arena, s, gl_ctx)
&& parseUniformBlocks(arena, s, gl_ctx)
&& parseAttributes(arena, s, gl_ctx))
{
return true;
} else {
printf("%s(), Error parsing shader component\n", __FUNCTION__);
return false;
}
}
printf("%s(), Error linking shader\n", __FUNCTION__);
@ -144,37 +146,35 @@ getGLTypeSize(GLenum e)
case 0x8b51: return 4 * sizeof(GLfloat); // GL_FLOAT_VEC3
case 0x8b52: return 4 * sizeof(GLfloat); // GL_FLOAT_VEC4
case 0x8b5c: return 16 * sizeof(GLfloat); // GL_FLOAT_MAT4
default: return 0;
default:
printf("%s(), unknown GLenum\n", __FUNCTION__);
return 0;
}
}
gl_uniform
const gl_uniform
parseUniform(memory_arena* arena, shader_program* s, u32 uniform_idx)
{
assert(uniform_idx < s->num_uniforms);
gl_uniform& unif = s->uniforms[uniform_idx];
gl_uniform unif = {0};
GLchar unif_name[256] = {0};
GLsizei length;
GLint size;
GLenum type;
glGetActiveUniform(s->prog_id, uniform_idx, sizeof(unif_name),
&length, &size, &type, unif_name);
unif.data_type = type;
unif.name = (char*) arenaAllocateBlock(
arena, (length + 1) * sizeof(char));
std::strncpy(unif.name, unif_name, length);
glGetActiveUniform(s->prog_id,
uniform_idx,
sizeof(unif_name),
&unif.name_len,
&unif.num_elements,
&unif.data_type,
unif_name);
glGetActiveUniformsiv(s->prog_id, 1, &uniform_idx,
GL_UNIFORM_BLOCK_INDEX, &unif.block_idx);
// FIXME: testing idx == unif location
unif.idx = uniform_idx;
#if 1
GLuint location = glGetUniformLocation(s->prog_id, unif.name);
printf("uniform idx: %d, loc: %d, block idx: %d \n",
unif.idx, location, unif.block_idx);
#endif
unif.data_size = getGLTypeSize(unif.data_type);
unif.name_len += 1; // NOTE: gl param dosen't account for null terminator
unif.name =
(char*) arenaAllocateBlock(arena, (unif.name_len) * sizeof(char));
std::strncpy(unif.name, unif_name, unif.name_len);
unif.location = glGetUniformLocation(s->prog_id, unif.name);
if (unif.data_size == 0)
printf("%s(), error getting data_size\n", __FUNCTION__);
@ -182,21 +182,94 @@ parseUniform(memory_arena* arena, shader_program* s, u32 uniform_idx)
return unif;
}
void
bool
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx)
{
GLint unif_count;
glGetProgramiv(s->prog_id, GL_ACTIVE_UNIFORMS, &unif_count);
s->num_uniforms = unif_count;
// NOTE: only add uniforms in the default block to the base uniform array
GLint num_uniforms_total = 0;
glGetProgramiv(s->prog_id, GL_ACTIVE_UNIFORMS, &num_uniforms_total);
GLint indices[num_uniforms_total];
for (u32 i = 0; i < (u32) num_uniforms_total; i++) {
GLint block_idx = 0;
glGetActiveUniformsiv(s->prog_id, 1, &i,
GL_UNIFORM_BLOCK_INDEX, &block_idx);
if (block_idx == -1) {
indices[s->num_uniforms] = i;
s->num_uniforms++;
}
}
s->uniforms = (gl_uniform*) arenaAllocateBlock(
arena, s->num_uniforms * sizeof(gl_uniform));
for (u32 i = 0; i < s->num_uniforms; i++) {
glGetActiveUniformsiv(s->prog_id, 1, &i,
GL_UNIFORM_BLOCK_INDEX, &s->uniforms[i].block_idx);
const gl_uniform unif = parseUniform(arena, s, indices[i]);
std::memcpy(&s->uniforms[i], &unif, sizeof(unif));
}
return true;
}
parseUniform(arena, s, i);
i32
ctxGetUniformBlockBinding(GLContext* gl_ctx, const char* name)
{
for (u32 i = 0; i < gl_ctx->num_ubos; i++) {
gl_buffer& ubo = gl_ctx->uniform_buffers[i];
if (std::strstr(ubo.name, name))
return ubo.binding_idx;
}
printf("%s(), no buffer found with name: %s\n", __FUNCTION__, name);
return -1;
}
bool
parseUniformBlocks(memory_arena* arena, shader_program* s, GLContext* gl_ctx)
{
glGetProgramiv(s->prog_id, GL_ACTIVE_UNIFORM_BLOCKS,
(GLint*) &s->num_blocks);
s->uniform_blocks = (GLUniformBlock*) arenaAllocateBlock(arena,
s->num_blocks * sizeof(GLUniformBlock));
for (u32 i = 0; i < s->num_blocks; i++) {
GLUniformBlock& ub = s->uniform_blocks[i];
ub.block_id = i;
GLchar block_name[256] = {0};
glGetActiveUniformBlockName(
s->prog_id, i, 256, &ub.name_len, block_name);
ub.name_len++; // NOTE: space for null term
ub.name = (char*) arenaAllocateBlock(arena, ub.name_len * sizeof(char));
std::strncpy(ub.name, block_name, ub.name_len);
glGetActiveUniformBlockiv(s->prog_id, i,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, (GLint*) &ub.num_uniforms);
ub.uniforms = (gl_uniform*)
arenaAllocateBlock(arena, ub.num_uniforms * sizeof(gl_uniform));
GLint indices[ub.num_uniforms] = {0};
glGetActiveUniformBlockiv(s->prog_id, i,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (GLint*) &indices);
for (u32 j = 0; j < ub.num_uniforms; j++) {
const gl_uniform unif = parseUniform(arena, s, indices[j]);
std::memcpy(&ub.uniforms[j], &unif, sizeof(unif));
}
ub.binding_idx = ctxGetUniformBlockBinding(gl_ctx, ub.name);
#if 0
if (ub.binding_idx < 0)
return false;
glUniformBlockBinding(s->prog_id, i, ub.binding_idx);
#endif
}
return true;
}
bool

24
src/shader.h

@ -22,23 +22,33 @@ struct gl_buffer
GLenum target;
GLenum data_type;
GLuint data_size;
GLuint binding_idx; // NOTE: set when used as backing for UBO
GLuint binding_idx;
char* name;
};
struct gl_uniform
{
GLuint idx; // NOTE: seems to map to location if not part of uniform block
//GLuint location;
// NOTE: would be nice to use idx as the location parameter because it seems
// to match when the uniform isn't part of a uniform block, at least with
// intel mesa driver, but apparently that's not guarantied
GLuint idx;
GLint location;
GLint block_idx;
GLenum data_type;
GLint data_size;
GLint num_elements;
GLsizei name_len;
char* name;
};
struct GLUniformBlock
{
GLuint block_id;
GLuint prog_id;
GLint binding_idx;
GLuint num_uniforms;
gl_uniform* uniforms;
GLsizei name_len;
char* name;
};
struct shader_program
@ -47,11 +57,10 @@ struct shader_program
GLuint xforms_ubo_id;
GLuint model_xform_id;
u32 num_uniform_blocks;
u32 num_blocks;
GLUniformBlock* uniform_blocks;
u32 num_uniforms;
// NOTE: contains individual uniforms, and uniforms part of a block
gl_uniform* uniforms;
u32 num_buffers;
@ -135,6 +144,9 @@ const glm::vec3 DEFAULT_CAM_POS = { 0, 0, -30.f };
const glm::vec3 DEFAULT_LOOK_POS = { 0, 0, 0 };
// NOTE: every shader program is assumed to have one uniform block named
// "matrices" that contains the projection and view matrices, and one uniform
// named "model_xform" for the model matrix
bool addShaderProgram(memory_arena* arena,
GLContext* gl_ctx,
const char* vs,

Loading…
Cancel
Save