From 001190fc7369df028603f8ae9df770e8ad366dc8 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Thu, 16 Dec 2021 12:15:30 -0500 Subject: [PATCH] break up addShader() into logical helper functions --- src/shader.cpp | 153 ++++++++++++++++++++++++++++++++----------------- src/shader.h | 2 + 2 files changed, 101 insertions(+), 54 deletions(-) diff --git a/src/shader.cpp b/src/shader.cpp index 5061853..2c4c7d5 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -19,18 +19,40 @@ // NOTE: forward declarations const std::string dumpTextFile(const char* filepath); -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); +bool parseShader(memory_arena* arena, GLContext* gl_ctx, shader_program* s); void initCTXSizes(GLContext* gl_ctx); +bool compileAndLinkShader(shader_program* shader, + const char* vert_src, + const char* frag_src, + GLuint& vs_id, + GLuint& fs_id); // NOTE: interface -// TODO: clean up this function +shader_program* +getFreeShader(GLContext* gl_ctx) +{ + if (gl_ctx->num_shaders >= gl_ctx->max_shaders) { + printf("%s(), GLContext->shaders full\n", __FUNCTION__); + return nullptr; + } + + shader_program* s = &gl_ctx->shaders[gl_ctx->num_shaders++]; + return s; +} + +shader_program* +getShaderByHash(GLContext* gl_ctx, u64 hash) +{ + for (u32 i; i < gl_ctx->num_shaders; i++) { + if (gl_ctx->shaders[i].hash == hash) + return &gl_ctx->shaders[i]; + } + + return nullptr; +} + bool addShaderProgram(memory_arena* arena, GLContext* gl_ctx, @@ -38,72 +60,45 @@ addShaderProgram(memory_arena* arena, const char* fs, const char* name) { - if (gl_ctx->num_shaders >= gl_ctx->max_shaders) { - printf("%s(), GLContext->shaders full\n", __FUNCTION__); + // TODO: replace std::string w/ utilAllocCStr() ? + std::string hash_str = std::string(vs) + std::string(fs); + const u32 max_len = 256; + u64 hash = utilFNV64a_str(hash_str.substr(0, max_len).c_str()); + + if (getShaderByHash(gl_ctx, hash)) { + printf("%s(), shader is already loaded\n", __FUNCTION__); return false; } - shader_program* s = &gl_ctx->shaders[gl_ctx->num_shaders]; - gl_ctx->num_shaders++; - s->name = arenaCopyCStr(arena, name); + shader_program* s = getFreeShader(gl_ctx); - const u32 max_len = 256; - std::string hash_str = vs; - hash_str += fs; - s->hash = utilFNV64a_str(hash_str.substr(0, max_len).c_str()); - // FIXME: should probably check the hash here against other shaders loaded - - std::string vert = dumpTextFile(vs); - std::string frag = dumpTextFile(fs); - - if (vert.size() > 0 && frag.size() > 0) { - const char* vert_c = vert.c_str(); - const char* frag_c = frag.c_str(); - - GLuint vs_id = glCreateShader(GL_VERTEX_SHADER); - GLuint fs_id = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(vs_id, 1, &vert_c, NULL); - glShaderSource(fs_id, 1, &frag_c, NULL); - // TODO: both of these can fail - glCompileShader(vs_id); - glCompileShader(fs_id); - s->prog_id = glCreateProgram(); - glAttachShader(s->prog_id, vs_id); - glAttachShader(s->prog_id, fs_id); + if (s) { + s->name = arenaCopyCStr(arena, name); + s->hash = hash; - glLinkProgram(s->prog_id); - GLint is_linked = 0; - glGetProgramiv(s->prog_id, GL_LINK_STATUS, &is_linked); + // TODO: replace std::string w/ utilAllocCStr() ? + std::string vert = dumpTextFile(vs); + std::string frag = dumpTextFile(fs); + GLuint vs_id, fs_id; - if (is_linked) { - // NOTE: need to set context maximums after at least one shader has - // been linked + if (compileAndLinkShader(s, vert.c_str(), frag.c_str(), vs_id, fs_id)) { + // NOTE: we call this here because we can only make the GL_MAX* + // queries after at least one shader has been linked initCTXSizes(gl_ctx); -#if 0 - dumpShader(s->prog_id); -#endif s->model_xform_id = glGetUniformLocation(s->prog_id, "model_xform"); 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; - } - + return parseShader(arena, gl_ctx, s); } printf("%s(), Error linking shader\n", __FUNCTION__); return false; } + printf("%s(), error loading shader\n", __FUNCTION__); return false; } @@ -231,8 +226,44 @@ loadGLMesh(shader_program* s, return gm; } + // NOTE: internal +bool +compileAndLinkShader(shader_program* shader, + const char* vert_src, + const char* frag_src, + GLuint& vs_id, + GLuint& fs_id) +{ + if (strlen(vert_src) > 0 && strlen(frag_src) > 0) { + vs_id = glCreateShader(GL_VERTEX_SHADER); + fs_id = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(vs_id, 1, &vert_src, NULL); + glShaderSource(fs_id, 1, &frag_src, NULL); + + // TODO: add a glError to string function in GLDebug.h + glCompileShader(vs_id); + assert(glGetError() == GL_NO_ERROR); + glCompileShader(fs_id); + assert(glGetError() == GL_NO_ERROR); + + shader->prog_id = glCreateProgram(); + glAttachShader(shader->prog_id, vs_id); + glAttachShader(shader->prog_id, fs_id); + + glLinkProgram(shader->prog_id); + GLint is_linked = 0; + glGetProgramiv(shader->prog_id, GL_LINK_STATUS, &is_linked); + + return (is_linked == GL_TRUE); + } + + // TODO: make another logging macro for printf style logging + printf("%s(), empty shader source\n", __FUNCTION__); + return false; +} + const std::string dumpTextFile(const char* filepath) { @@ -412,3 +443,17 @@ parseAttributes(memory_arena* arena, shader_program* s, GLContext* gl_ctx) return true; } +bool +parseShader(memory_arena* arena, GLContext* gl_ctx, shader_program* s) +{ + if (parseShaderUniforms(arena, s, gl_ctx) + && parseUniformBlocks(arena, s, gl_ctx) + && parseAttributes(arena, s, gl_ctx)) + { + return true; + } + + printf("%s(), Error parsing shader\n", __FUNCTION__); + return false; +} + diff --git a/src/shader.h b/src/shader.h index 799dfd8..f9de3cb 100644 --- a/src/shader.h +++ b/src/shader.h @@ -139,6 +139,8 @@ bool addShaderProgram(memory_arena* arena, const char* name); shader_program* getShaderByName(const char* name, GLContext* gl_ctx); shader_program* getShaderByID(GLContext* gl_ctx, GLuint prog_id); +shader_program* getShaderByHash(GLContext* gl_ctx, u64 hash); +shader_program* getFreeShader(GLContext* gl_ctx); void renderVAO(GLmesh* glmesh); GLmesh loadGLMesh(shader_program* s, const mesh& m,