From 79b20bb6b07a07f1f4d48445829a00f4d5485f85 Mon Sep 17 00:00:00 2001 From: cinnaboot Date: Fri, 28 Jan 2022 19:12:16 -0500 Subject: [PATCH] load a dummy shader to init GLContext limits This solves a chicken and egg problem when loading shaders that need to know about GLContext limits. Also moved initGLContext() from tangerine.cpp to shader.cpp --- src/dummy_shader.h | 30 ++++++++++++++++++++++++++++++ src/shader.cpp | 41 ++++++++++++++++++++++++++++++++++++++--- src/shader.h | 5 +++++ src/tangerine.cpp | 33 +++++++-------------------------- src/tangerine.h | 14 +++++++++++++- 5 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 src/dummy_shader.h diff --git a/src/dummy_shader.h b/src/dummy_shader.h new file mode 100644 index 0000000..38316e7 --- /dev/null +++ b/src/dummy_shader.h @@ -0,0 +1,30 @@ + +#pragma once + + +const char* DUMMY_VERTEX_SHADER = R"VS( +#version 330 core +layout (location = 0) in vec3 position; + +uniform mat4 world_transform; +uniform mat4 MVP; + + +void main() +{ + gl_Position = MVP * world_transform * vec4(position, 1); +} +)VS"; + +const char* DUMMY_FRAGMENT_SHADER = R"FS( +#version 330 core + +out vec4 color; + + +void main() +{ + color = vec4(1, 0, 0, 1); +} +)FS"; + diff --git a/src/shader.cpp b/src/shader.cpp index e416dce..32ecaa4 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -12,6 +12,7 @@ #include "asset.h" #include "dumbLog.h" +#include "dummy_shader.h" #define GL_DEBUG_IMPLEMENTATION #include "GLDebug.h" #include "shader.h" @@ -22,6 +23,7 @@ const std::string dumpTextFile(const char* filepath); bool parseShader(MemoryArena* arena, GLContext* gl_ctx, ShaderProgram* s); +void loadDummyShader(); void initCTXSizes(GLContext* gl_ctx); bool compileAndLinkShader(ShaderProgram* shader, const char* vert_src, @@ -36,6 +38,28 @@ void* getMeshData(const Mesh& m, const GLBufferToAttribMapping& mapping); // NOTE: interface +GLContext* +initGLContext(MemoryArena* arena, + u32 max_shaders, + u32 max_textures, + u32 max_ubos) +{ + GLContext* gl_ctx = ARENA_ALLOC(arena, GLContext, 1); + gl_ctx->max_shaders = max_shaders; + gl_ctx->shaders = ARENA_ALLOC(arena, ShaderProgram, max_shaders); + gl_ctx->max_ubos = max_ubos; + gl_ctx->uniform_buffers = ARENA_ALLOC(arena, GLBuffer, max_ubos); + gl_ctx->max_textures = max_textures; + gl_ctx->textures = ARENA_ALLOC(arena, GLTexture, max_textures); + + // NOTE: load a dummy shader to avoid chicken and egg problem where we need + // GLContext info before we can parse a shader, which needs GLContext info + loadDummyShader(); + initCTXSizes(gl_ctx); + + return gl_ctx; +} + bool addShaderProgram(MemoryArena* arena, GLContext* gl_ctx, @@ -66,9 +90,6 @@ addShaderProgram(MemoryArena* arena, GLuint vs_id, fs_id; 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); s->node_xform_id = glGetUniformLocation(s->prog_id, "node_xform"); // TODO: add sampler uniform detection in dynamic shader parsing s->sampler_id = glGetUniformLocation(s->prog_id, "sampler"); @@ -418,6 +439,20 @@ dumpTextFile(const char* filepath) return s; } +void +loadDummyShader() +{ + GLuint vs_id = 0, fs_id = 0; + ShaderProgram temp_shader = {0}; + bool ret = compileAndLinkShader(&temp_shader, + DUMMY_VERTEX_SHADER, + DUMMY_FRAGMENT_SHADER, + vs_id, + fs_id); + assert(ret); + glDeleteProgram(temp_shader.prog_id); +} + u32 getGLTypeSize(GLenum e) { diff --git a/src/shader.h b/src/shader.h index 18c9dd1..1c6f42f 100644 --- a/src/shader.h +++ b/src/shader.h @@ -164,6 +164,11 @@ const glm::vec3 DEFAULT_CAM_POS = { 0, 0, 50.f }; const glm::vec3 DEFAULT_LOOK_POS = { 0, 0, 0 }; +GLContext* initGLContext(MemoryArena* arena, + u32 max_shaders, + u32 max_textures, + u32 max_ubos); + // NOTE: every shader program is assumed to have one uniform block named // "matrices" that contains the projection and view matrices, and one uniform // named "node_xform" for the node matrix diff --git a/src/tangerine.cpp b/src/tangerine.cpp index 9571ea0..567e254 100644 --- a/src/tangerine.cpp +++ b/src/tangerine.cpp @@ -41,9 +41,10 @@ initRenderState(u32 max_models, rs->render_groups = ARENA_ALLOC(rs->rg_arena, RenderGroup, DEFAULT_RENDER_GROUP_COUNT); - // FIXME: revisit for 'Scene' abstraction - rs->max_lights = 32; - rs->lights = ARENA_ALLOC(rs->rg_arena, PointLight, rs->max_lights); + if (!initGraphics(&rs->handles)) { + LOGF(Error, "error initializing renderer\n"); + return nullptr; + } rs->gl_ctx = initGLContext(rs->assets.arena, max_shaders, @@ -51,8 +52,6 @@ initRenderState(u32 max_models, max_ubos); rs->xforms = ARENA_ALLOC(rs->assets.arena, Transforms, 1); - rs->handles = UTIL_ALLOC(1, SDLHandles); - initGraphics(rs->handles); // FIXME: need to test this with another shader that has another UBO GLBuffer& ubo = rs->gl_ctx->uniform_buffers[rs->gl_ctx->num_ubos++]; @@ -69,11 +68,10 @@ void freeRenderState(RenderState*& rs) { if (rs) { - SDL_GL_DeleteContext(rs->handles->sdl_gl_ctx); - SDL_DestroyWindow(rs->handles->window); + SDL_GL_DeleteContext(rs->handles.sdl_gl_ctx); + SDL_DestroyWindow(rs->handles.window); arenaFree(rs->assets.arena); arenaFree(rs->rg_arena); - utilSafeFree(rs->handles); utilSafeFree(rs); rs = nullptr; } @@ -153,7 +151,7 @@ doRenderLoop(RenderState* rs, if (cb_func_post != nullptr) cb_func_post(rs); - SDL_GL_SwapWindow(rs->handles->window); + SDL_GL_SwapWindow(rs->handles.window); frameTime = SDL_GetTicks() - frameStart; if (delay > frameTime) @@ -291,20 +289,3 @@ initGraphics(SDLHandles* handles) return handles->window != nullptr; } -GLContext* -initGLContext(MemoryArena* arena, - u32 max_shaders, - u32 max_textures, - u32 max_ubos) -{ - GLContext* gl_ctx = ARENA_ALLOC(arena, GLContext, 1); - gl_ctx->max_shaders = max_shaders; - gl_ctx->shaders = ARENA_ALLOC(arena, ShaderProgram, max_shaders); - gl_ctx->max_ubos = max_ubos; - gl_ctx->uniform_buffers = ARENA_ALLOC(arena, GLBuffer, max_ubos); - gl_ctx->max_textures = max_textures; - gl_ctx->textures = ARENA_ALLOC(arena, GLTexture, max_textures); - - return gl_ctx; -} - diff --git a/src/tangerine.h b/src/tangerine.h index eb44e19..8178c16 100644 --- a/src/tangerine.h +++ b/src/tangerine.h @@ -106,12 +106,24 @@ struct GLClearColor GLfloat A; }; +// NOTE: structure to match the layout of the 'lights' uniform in a shader +struct LightsBuffer +{ + u32 active_p_lights; + u32 max_p_lights; + u32 active_d_lights; + u32 max_d_lights; + // FIXME: do we need any padding here for layout(std 140)? + PointLight* p_lights; + PointLight* d_lights; // TODO: directional lights +}; + struct RenderState { bool running; GLClearColor clear_col; Transforms* xforms; // NOTE: would be part of camera in libTangerine - SDLHandles* handles; + SDLHandles handles; GLContext* gl_ctx; Assets assets;