From 69e25640fb42faaf3a937589a6d5fe6ed09aa6a0 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 25 Oct 2013 01:44:34 +0200 Subject: [PATCH] Reload shaders on resolution change. --- BBGE/AfterEffect.cpp | 32 +++++++++++++++++++++++++++----- BBGE/AfterEffect.h | 3 ++- BBGE/Shader.cpp | 41 +++++++++++++++++++++++++++-------------- BBGE/Shader.h | 3 ++- 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/BBGE/AfterEffect.cpp b/BBGE/AfterEffect.cpp index 938d535..6b6b92c 100644 --- a/BBGE/AfterEffect.cpp +++ b/BBGE/AfterEffect.cpp @@ -113,6 +113,13 @@ void AfterEffectManager::deleteShaders() } } +void AfterEffectManager::unloadShaders() +{ + for(size_t i = 0; i < loadedShaders.size(); ++i) + if(loadedShaders[i]) + loadedShaders[i]->unload(); +} + void AfterEffectManager::clear() { deleteEffects(); @@ -196,7 +203,7 @@ void AfterEffectManager::renderGrid() Shader *activeShader = 0; for (size_t i = 0; i < shaderPipeline.size(); ++i) { - if(shaderPipeline[i]) + if(shaderPipeline[i] && shaderPipeline[i]->isLoaded()) { if(firstShader < 0) { @@ -275,7 +282,7 @@ void AfterEffectManager::renderGrid() for(int i = firstShader + 1; i <= lastShader; ++i) { activeShader = shaderPipeline[i]; - if(!activeShader) + if(!(activeShader && activeShader->isLoaded())) continue; // Swap and exchange framebuffers. The old output buffer serves as texture input for the other one @@ -373,7 +380,7 @@ void AfterEffectManager::renderGridPoints() void AfterEffectManager::unloadDevice() { backupBuffer.unloadDevice(); - deleteShaders(); + unloadShaders(); } void AfterEffectManager::reloadDevice() @@ -399,7 +406,22 @@ void AfterEffectManager::reloadDevice() else backupBuffer.init(-1, -1, true); - loadShaders(); + for (size_t i = 0; i < loadedShaders.size(); ++i) + { + if (Shader *sh = loadedShaders[i]) + { + sh->reload(); + if (!sh->isLoaded()) + { + debugLog("AfterEffect::reloadDevice(): Failed to reload shader"); + delete sh; + loadedShaders[i] = 0; + for(size_t j = 0; j < shaderPipeline.size(); ++j) + if(sh == shaderPipeline[j]) + shaderPipeline[j] = 0; + } + } + } } void AfterEffectManager::addEffect(Effect *e) @@ -612,7 +634,7 @@ int AfterEffectManager::_insertShader(Shader *sh) return loadedShaders.size(); } -void AfterEffectManager::unloadShader(int handle) +void AfterEffectManager::deleteShader(int handle) { Shader *sh = getShaderPtr(handle); if(!sh) diff --git a/BBGE/AfterEffect.h b/BBGE/AfterEffect.h index 90c7d9f..251635f 100644 --- a/BBGE/AfterEffect.h +++ b/BBGE/AfterEffect.h @@ -91,6 +91,7 @@ public: void renderGridPoints(); void loadShaders(); + void unloadShaders(); // unloads shaders but keeps code and data intact, so that they can be reloaded. void deleteShaders(); void unloadDevice(); @@ -116,7 +117,7 @@ public: Shader *getShaderPtr(int handle); void setShaderPipelineSize(size_t size); bool setShaderPipelinePos(int handle, size_t pos); - void unloadShader(int handle); + void deleteShader(int handle); protected: int _insertShader(Shader *sh); diff --git a/BBGE/Shader.cpp b/BBGE/Shader.cpp index c6468bc..af5e882 100644 --- a/BBGE/Shader.cpp +++ b/BBGE/Shader.cpp @@ -164,7 +164,10 @@ bool Shader::isLoaded() const void Shader::reload() { - load(vertFile, fragFile); + if (vertFile.size() || fragFile.size()) + load(vertFile, fragFile); + else + loadSrc(vertSrc.c_str(), fragSrc.c_str()); } void Shader::bind() @@ -321,6 +324,9 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) return; } + vertSrc = vertCode ? vertCode : ""; + fragSrc = fragCode ? fragCode : ""; + _queryUniforms(); #endif @@ -328,15 +334,6 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode) void Shader::_setUniform(Uniform *u) { - /*if(u->location == -1) - { - u->location = glGetUniformLocationARB(g_programObj, u->name); - if(u->location == -1) - { - u->dirty = false; - return; - } - }*/ switch(u->type) { case GL_FLOAT: glUniform1fvARB(u->location, 1, u->data.f); break; @@ -381,9 +378,13 @@ void Shader::_queryUniforms() glGetObjectParameterivARB(g_programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB , &numUniforms); if (numUniforms <= 0) + { + uniforms.clear(); return; + } uniforms.reserve(numUniforms); + size_t total = 0; for (unsigned int i = 0; i < numUniforms; ++i) { @@ -396,15 +397,27 @@ void Shader::_queryUniforms() u.location = glGetUniformLocationARB(g_programObj, u.name); if(u.location == -1) continue; - u.dirty = false; - u.type = type; - memset(&u.data, 0, sizeof(u.data)); - uniforms.push_back(u); + bool add = total >= uniforms.size(); + if(add || type != u.type) // keep data intact on reload + memset(&u.data, 0, sizeof(u.data)); + u.dirty = true; + u.type = type; + + if(add) + uniforms.push_back(u); + else + uniforms[total] = u; + + ++total; } + uniforms.resize(total); + // sort to be able to do binary search later std::sort(uniforms.begin(), uniforms.end()); + + uniformsDirty = true; } int Shader::_getUniformIndex(const char *name) diff --git a/BBGE/Shader.h b/BBGE/Shader.h index 2b978e7..30b8ba0 100644 --- a/BBGE/Shader.h +++ b/BBGE/Shader.h @@ -44,6 +44,7 @@ public: protected: std::string vertFile, fragFile; + std::string vertSrc, fragSrc; #ifdef BBGE_BUILD_OPENGL GLuint g_programObj; int numUniforms; @@ -72,7 +73,7 @@ private: float f[4]; }; } data; - char name[32]; + char name[64]; bool operator< (const Uniform&) const; };