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 // NOTE: forward declarations
const std::string dumpTextFile(const char* filepath); const std::string dumpTextFile(const char* filepath);
void bool
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx); 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 // NOTE: interface
@ -78,24 +83,21 @@ addShaderProgram(memory_arena* arena,
initCTXSizes(gl_ctx); initCTXSizes(gl_ctx);
dumpShader(s->prog_id); dumpShader(s->prog_id);
s->model_xform_id = glGetUniformLocation(s->prog_id, "model_xform"); 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, vs_id);
glDetachShader(s->prog_id, fs_id); glDetachShader(s->prog_id, fs_id);
glDeleteShader(vs_id); glDeleteShader(vs_id);
glDeleteShader(fs_id); glDeleteShader(fs_id);
if (parseShaderUniforms(arena, s, gl_ctx)
&& parseUniformBlocks(arena, s, gl_ctx)
&& parseAttributes(arena, s, gl_ctx))
{
return true; return true;
} else {
printf("%s(), Error parsing shader component\n", __FUNCTION__);
return false;
}
} }
printf("%s(), Error linking shader\n", __FUNCTION__); printf("%s(), Error linking shader\n", __FUNCTION__);
@ -144,37 +146,35 @@ getGLTypeSize(GLenum e)
case 0x8b51: return 4 * sizeof(GLfloat); // GL_FLOAT_VEC3 case 0x8b51: return 4 * sizeof(GLfloat); // GL_FLOAT_VEC3
case 0x8b52: return 4 * sizeof(GLfloat); // GL_FLOAT_VEC4 case 0x8b52: return 4 * sizeof(GLfloat); // GL_FLOAT_VEC4
case 0x8b5c: return 16 * sizeof(GLfloat); // GL_FLOAT_MAT4 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) parseUniform(memory_arena* arena, shader_program* s, u32 uniform_idx)
{ {
assert(uniform_idx < s->num_uniforms); gl_uniform unif = {0};
gl_uniform& unif = s->uniforms[uniform_idx];
GLchar unif_name[256] = {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; glGetActiveUniform(s->prog_id,
unif.name = (char*) arenaAllocateBlock( uniform_idx,
arena, (length + 1) * sizeof(char)); sizeof(unif_name),
std::strncpy(unif.name, unif_name, length); &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; 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.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) if (unif.data_size == 0)
printf("%s(), error getting data_size\n", __FUNCTION__); printf("%s(), error getting data_size\n", __FUNCTION__);
@ -182,21 +182,94 @@ parseUniform(memory_arena* arena, shader_program* s, u32 uniform_idx)
return unif; return unif;
} }
void bool
parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx) parseShaderUniforms(memory_arena* arena, shader_program* s, GLContext* gl_ctx)
{ {
GLint unif_count; // NOTE: only add uniforms in the default block to the base uniform array
glGetProgramiv(s->prog_id, GL_ACTIVE_UNIFORMS, &unif_count); GLint num_uniforms_total = 0;
s->num_uniforms = unif_count; 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( s->uniforms = (gl_uniform*) arenaAllocateBlock(
arena, s->num_uniforms * sizeof(gl_uniform)); arena, s->num_uniforms * sizeof(gl_uniform));
for (u32 i = 0; i < s->num_uniforms; i++) { for (u32 i = 0; i < s->num_uniforms; i++) {
glGetActiveUniformsiv(s->prog_id, 1, &i, const gl_uniform unif = parseUniform(arena, s, indices[i]);
GL_UNIFORM_BLOCK_INDEX, &s->uniforms[i].block_idx); 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 bool

24
src/shader.h

@ -22,23 +22,33 @@ struct gl_buffer
GLenum target; GLenum target;
GLenum data_type; GLenum data_type;
GLuint data_size; GLuint data_size;
GLuint binding_idx; // NOTE: set when used as backing for UBO GLuint binding_idx;
char* name;
}; };
struct gl_uniform struct gl_uniform
{ {
GLuint idx; // NOTE: seems to map to location if not part of uniform block // NOTE: would be nice to use idx as the location parameter because it seems
//GLuint location; // 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; GLint block_idx;
GLenum data_type; GLenum data_type;
GLint data_size; GLint data_size;
GLint num_elements;
GLsizei name_len;
char* name; char* name;
}; };
struct GLUniformBlock struct GLUniformBlock
{ {
GLuint block_id; GLuint block_id;
GLuint prog_id; GLint binding_idx;
GLuint num_uniforms;
gl_uniform* uniforms;
GLsizei name_len;
char* name;
}; };
struct shader_program struct shader_program
@ -47,11 +57,10 @@ struct shader_program
GLuint xforms_ubo_id; GLuint xforms_ubo_id;
GLuint model_xform_id; GLuint model_xform_id;
u32 num_uniform_blocks; u32 num_blocks;
GLUniformBlock* uniform_blocks; GLUniformBlock* uniform_blocks;
u32 num_uniforms; u32 num_uniforms;
// NOTE: contains individual uniforms, and uniforms part of a block
gl_uniform* uniforms; gl_uniform* uniforms;
u32 num_buffers; 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 }; 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, bool addShaderProgram(memory_arena* arena,
GLContext* gl_ctx, GLContext* gl_ctx,
const char* vs, const char* vs,

Loading…
Cancel
Save