Add the code required for reloading sp shader on the fly

This commit is contained in:
Benau 2018-01-19 20:47:30 +08:00
parent 0f95d36dbc
commit b199b81427
5 changed files with 140 additions and 77 deletions

View File

@ -383,7 +383,7 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT));
SP::draw(SP::RP_1ST, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_2ND, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_RESERVED, SP::DCT_TRANSPARENT);
PROFILER_POP_CPU_MARKER();
}
@ -493,7 +493,7 @@ void ShaderBasedRenderer::renderScene(scene::ICameraSceneNode * const camnode,
PROFILER_PUSH_CPU_MARKER("- Transparent Pass", 0xFF, 0x00, 0x00);
ScopedGPUTimer Timer(irr_driver->getGPUTimer(Q_TRANSPARENT));
SP::draw(SP::RP_1ST, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_2ND, SP::DCT_TRANSPARENT);
SP::draw(SP::RP_RESERVED, SP::DCT_TRANSPARENT);
PROFILER_POP_CPU_MARKER();
}

View File

@ -70,6 +70,8 @@ bool g_handle_shadow = false;
// ----------------------------------------------------------------------------
std::unordered_map<std::string, SPShader*> g_shaders;
// ----------------------------------------------------------------------------
SPShader* g_normal_visualizer = NULL;
// ----------------------------------------------------------------------------
SPShader* g_glow_shader = NULL;
// ----------------------------------------------------------------------------
// std::string is layer_1 and layer_2 texture name combined
@ -414,7 +416,7 @@ void loadShaders()
addShader(shader);
// ========================================================================
shader = new SPShader("alphatest", 3, false, 0, true);
shader = new SPShader("alphatest", {{ 0, 1, -1 }}, false, 0, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -435,7 +437,7 @@ void loadShaders()
addShader(shader);
shader = new SPShader("alphatest_skinned", 3, false, 0, true);
shader = new SPShader("alphatest_skinned", {{ 0, 1, -1 }}, false, 0, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_alpha_test.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -457,7 +459,7 @@ void loadShaders()
addShader(shader);
// ========================================================================
shader = new SPShader("unlit", 3, false, 0, true);
shader = new SPShader("unlit", {{ 0, 1, -1 }}, false, 0, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -478,7 +480,7 @@ void loadShaders()
addShader(shader);
shader = new SPShader("unlit_skinned", 3, false, 0, true);
shader = new SPShader("unlit_skinned", {{ 0, 1, -1 }}, false, 0, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_unlit.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -521,7 +523,7 @@ void loadShaders()
addShader(shader);
shader = new SPShader("normalmap_skinned", 3, false);
shader = new SPShader("normalmap_skinned", {{ 0, 1, -1 }}, false);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_map.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -543,7 +545,7 @@ void loadShaders()
addShader(shader);
// ========================================================================
shader = new SPShader("grass", 3, false, 0, true);
shader = new SPShader("grass", {{ 0, 1, -1 }}, false, 0, true);
shader->addShaderFile("sp_grass_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_grass.frag", GL_FRAGMENT_SHADER,
RP_1ST);
@ -574,7 +576,7 @@ void loadShaders()
// ========================================================================
// Transparent shader
// ========================================================================
shader = new SPShader("alphablend_skinned", 1, true);
shader = new SPShader("alphablend_skinned", {{ 0, -1, -1 }}, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
@ -590,7 +592,7 @@ void loadShaders()
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("alphablend", 1, true);
shader = new SPShader("alphablend", {{ 0, -1, -1}}, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
@ -606,7 +608,7 @@ void loadShaders()
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("additive_skinned", 1, true);
shader = new SPShader("additive_skinned", {{ 0, -1, -1 }}, true);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
@ -622,7 +624,7 @@ void loadShaders()
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("additive", 1, true);
shader = new SPShader("additive", {{ 0, -1, -1 }}, true);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_transparent.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
@ -638,7 +640,7 @@ void loadShaders()
->addAssignerFunction("custom_alpha", zeroAlphaUniformAssigner);
addShader(shader);
shader = new SPShader("ghost_skinned", 1, true/*transparent_shader*/,
shader = new SPShader("ghost_skinned", {{ 0, -1, -1 }}, true/*transparent_shader*/,
900/*drawing_priority*/);
shader->addShaderFile("sp_skinning.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_ghost.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -652,7 +654,7 @@ void loadShaders()
->addAssignerFunction("custom_alpha", ghostAlphaAssigner);
addShader(shader);
shader = new SPShader("ghost", 1, true/*transparent_shader*/,
shader = new SPShader("ghost", {{ 0, -1, -1 }}, true/*transparent_shader*/,
900/*drawing_priority*/);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_ghost.frag", GL_FRAGMENT_SHADER, RP_1ST);
@ -669,7 +671,7 @@ void loadShaders()
if (CVS->isDefferedEnabled())
{
// This displace shader will be drawn the last in transparent pass
shader = new SPShader("displace", 2, true/*transparent_shader*/,
shader = new SPShader("displace", {{ 0, -1, 2 }}, true/*transparent_shader*/,
999/*drawing_priority*/);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER,
RP_1ST);
@ -693,14 +695,14 @@ void loadShaders()
glClear(GL_COLOR_BUFFER_BIT);
}, RP_1ST);
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER,
RP_2ND);
RP_RESERVED);
shader->addShaderFile("sp_displace.frag", GL_FRAGMENT_SHADER,
RP_2ND);
shader->linkShaderFiles(RP_2ND);
shader->use(RP_2ND);
shader->addBasicUniforms(RP_2ND);
RP_RESERVED);
shader->linkShaderFiles(RP_RESERVED);
shader->use(RP_RESERVED);
shader->addBasicUniforms(RP_RESERVED);
shader->addUniform("direction", typeid(std::array<float, 4>),
RP_2ND);
RP_RESERVED);
shader->setUseFunction([]()->void
{
glEnable(GL_DEPTH_TEST);
@ -712,24 +714,24 @@ void loadShaders()
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
g_stk_sbr->getRTTs()->getFBO(FBO_DISPLACE).bind(),
glClear(GL_COLOR_BUFFER_BIT);
}, RP_2ND);
}, RP_RESERVED);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "displacement_tex", []()->GLuint
{
return irr_driver->getTexture(FileManager::TEXTURE,
"displace.png")->getOpenGLTextureName();
}, RP_2ND);
}, RP_RESERVED);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "mask_tex", []()->GLuint
{
return g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0];
}, RP_2ND);
}, RP_RESERVED);
shader->addCustomPrefilledTextures(ST_BILINEAR,
GL_TEXTURE_2D, "color_tex", []()->GLuint
{
return g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getRTT()[0];
}, RP_2ND);
shader->addAllTextures(RP_2ND);
}, RP_RESERVED);
shader->addAllTextures(RP_RESERVED);
shader->setUnuseFunction([]()->void
{
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).bind();
@ -739,7 +741,7 @@ void loadShaders()
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getWidth(),
g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getHeight());
glDisable(GL_STENCIL_TEST);
}, RP_2ND);
}, RP_RESERVED);
static_cast<SPPerObjectUniform*>(shader)
->addAssignerFunction("direction", displaceUniformAssigner);
addShader(shader);
@ -748,14 +750,17 @@ void loadShaders()
// ========================================================================
// Glow shader
// ========================================================================
g_glow_shader = new SPShader("sp_glow_shader", 1);
g_glow_shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
g_glow_shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER, RP_1ST);
g_glow_shader->linkShaderFiles(RP_1ST);
g_glow_shader->use(RP_1ST);
g_glow_shader->addBasicUniforms(RP_1ST);
g_glow_shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST);
addShader(g_glow_shader);
g_glow_shader = new SPShader("sp_glow_shader", {{ 0, -1, -1 }});
g_glow_shader->setInitFunction([](SPShader* shader)
{
shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST);
});
g_glow_shader->init();
// ========================================================================
// Normal visualizer
@ -763,18 +768,22 @@ void loadShaders()
#ifndef USE_GLES2
if (CVS->isARBGeometryShadersUsable())
{
shader = new SPShader("sp_normal_visualizer", 1);
shader->addShaderFile("sp_normal_visualizer.vert", GL_VERTEX_SHADER,
RP_1ST);
shader->addShaderFile("sp_normal_visualizer.geom", GL_GEOMETRY_SHADER,
RP_1ST);
shader->addShaderFile("sp_normal_visualizer.frag", GL_FRAGMENT_SHADER,
RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
addShader(shader);
g_normal_visualizer =
new SPShader("sp_normal_visualizer", {{ 0, -1, -1 }});
g_normal_visualizer->setInitFunction([](SPShader* shader)
{
shader->addShaderFile("sp_normal_visualizer.vert",
GL_VERTEX_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_visualizer.geom",
GL_GEOMETRY_SHADER, RP_1ST);
shader->addShaderFile("sp_normal_visualizer.frag",
GL_FRAGMENT_SHADER, RP_1ST);
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addAllTextures(RP_1ST);
});
g_normal_visualizer->init();
}
#endif
@ -965,6 +974,10 @@ void destroy()
delete p.second;
}
g_shaders.clear();
delete g_glow_shader;
g_glow_shader = NULL;
delete g_normal_visualizer;
g_normal_visualizer = NULL;
SPTextureManager::destroy();
@ -1004,6 +1017,12 @@ SPShader* getGlowShader()
return g_glow_shader;
} // getGlowShader
// ----------------------------------------------------------------------------
SPShader* getNormalVisualizer()
{
return g_normal_visualizer;
} // getNormalVisualizer
// ----------------------------------------------------------------------------
SPShader* getSPShader(const std::string& name)
{
@ -1613,13 +1632,12 @@ void uploadAll()
// ----------------------------------------------------------------------------
void drawNormal()
{
SPShader* nv = getSPShader("sp_normal_visualizer");
if (nv == NULL)
if (g_normal_visualizer == NULL)
{
return;
}
nv->use();
nv->bindPrefilledTextures();
g_normal_visualizer->use();
g_normal_visualizer->bindPrefilledTextures();
for (unsigned i = 0; i < g_final_draw_calls[0].size(); i++)
{
auto& p = g_final_draw_calls[0][i];
@ -1652,12 +1670,16 @@ void drawNormal()
}
}
}
nv->unuse();
g_normal_visualizer->unuse();
}
// ----------------------------------------------------------------------------
void drawGlow()
{
if (g_glow_meshes.empty())
{
return;
}
g_glow_shader->use();
SPUniformAssigner* glow_color_assigner =
g_glow_shader->getUniformAssigner("col");

View File

@ -104,6 +104,8 @@ void destroy();
// ----------------------------------------------------------------------------
GLuint getSampler(SamplerType);
// ----------------------------------------------------------------------------
SPShader* getNormalVisualizer();
// ----------------------------------------------------------------------------
SPShader* getGlowShader();
// ----------------------------------------------------------------------------
SPShader* getSPShader(const std::string& name);

View File

@ -47,11 +47,8 @@ SPShader::~SPShader()
{
glDeleteProgram(m_program[rp]);
}
for (auto& p : m_uniforms[rp])
{
delete p.second;
}
}
unload();
#endif
} // ~SPShader
@ -60,12 +57,12 @@ void SPShader::addShaderFile(const std::string& name, GLint shader_type,
RenderPass rp)
{
#ifndef SERVER_ONLY
auto shader_id = ShaderFilesManager::getInstance()
auto shader_file = ShaderFilesManager::getInstance()
->getShaderFile(name, shader_type);
if (shader_id)
if (shader_file)
{
m_shaders.insert(shader_id);
glAttachShader(m_program[rp], *shader_id);
m_shader_files.push_back(shader_file);
glAttachShader(m_program[rp], *shader_file);
}
#endif
} // addShaderFile
@ -92,7 +89,7 @@ void SPShader::linkShaderFiles(RenderPass rp)
GLuint shaders[10] = {};
GLsizei count = 0;
glGetAttachedShaders(m_program[rp], 10, &count, shaders);
for (unsigned i = 0; i < count; i++)
for (unsigned i = 0; i < (unsigned)count; i++)
{
glDetachShader(m_program[rp], shaders[i]);
}
@ -252,4 +249,23 @@ SPUniformAssigner* SPShader::getUniformAssigner(const std::string& name,
return ret->second;
} // getUniformAssigner
// ----------------------------------------------------------------------------
void SPShader::unload()
{
for (unsigned rp = RP_1ST; rp < RP_COUNT; rp++)
{
for (auto& p : m_uniforms[rp])
{
delete p.second;
}
m_uniforms[rp].clear();
m_custom_prefilled_getter[rp].clear();
m_prefilled_samplers[rp].clear();
m_samplers[rp].clear();
m_shader_files.clear();
m_use_function[rp] = nullptr;
m_unuse_function[rp] = nullptr;
}
} // unload
}

View File

@ -29,7 +29,6 @@
#include <ostream>
#include <memory>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <vector>
@ -55,8 +54,8 @@ enum SamplerType: unsigned int
enum RenderPass: unsigned int
{
RP_1ST = 0,
RP_2ND,
RP_SHADOW,
RP_RESERVED,
RP_COUNT
};
@ -66,10 +65,10 @@ inline std::ostream& operator<<(std::ostream& os, const RenderPass& rp)
{
case RP_1ST:
return os << "first pass";
case RP_2ND:
return os << "second pass";
case RP_SHADOW:
return os << "shadow pass";
case RP_RESERVED:
return os << "reserved pass";
default:
return os;
}
@ -82,7 +81,7 @@ class SPShader : public NoCopy, public SPPerObjectUniform
private:
std::string m_name;
std::unordered_set<std::shared_ptr<GLuint> > m_shaders;
std::vector<std::shared_ptr<GLuint> > m_shader_files;
GLuint m_program[RP_COUNT];
@ -91,14 +90,15 @@ private:
std::vector<std::tuple<unsigned, std::string, SamplerType,
GLuint> >m_prefilled_samplers[RP_COUNT];
std::unordered_map<std::string, SPUniformAssigner*>
m_uniforms[RP_COUNT];
std::unordered_map<std::string, SPUniformAssigner*> m_uniforms[RP_COUNT];
std::unordered_map<std::string, std::function<GLuint()> >
m_custom_prefilled_getter[RP_COUNT];
std::function<void()> m_use_function[RP_COUNT], m_unuse_function[RP_COUNT];
std::function<void(SPShader*)> m_init_function;
const int m_drawing_priority;
const bool m_transparent_shader;
@ -107,7 +107,8 @@ private:
public:
// ------------------------------------------------------------------------
SPShader(const std::string& name, unsigned pass_count = 3,
SPShader(const std::string& name,
const std::array<int, 3>& pass = {{ 0, 1, -1 }},
bool transparent_shader = false, int drawing_priority = 0,
bool use_alpha_channel = false)
: m_name(name), m_drawing_priority(drawing_priority),
@ -116,9 +117,12 @@ public:
{
memset(m_program, 0, 12);
#ifndef SERVER_ONLY
for (unsigned rp = RP_1ST; rp < pass_count; rp++)
for (int rp : pass)
{
m_program[rp] = glCreateProgram();
if (rp > -1)
{
m_program[rp] = glCreateProgram();
}
}
#endif
}
@ -174,12 +178,6 @@ public:
block_index = glGetUniformBlockIndex(m_program[rp], "SPFogData");
if (block_index != GL_INVALID_INDEX)
glUniformBlockBinding(m_program[rp], block_index, 2);
#ifndef USE_GLES2
// Assign framebuffer output
glBindFragDataLocation(m_program[rp], 0, "o_diffuse_color");
glBindFragDataLocation(m_program[rp], 1, "o_normal_depth");
glBindFragDataLocation(m_program[rp], 2, "o_gloss_map");
#endif
#endif
}
// ------------------------------------------------------------------------
@ -213,6 +211,31 @@ public:
// ------------------------------------------------------------------------
bool samplerLess(RenderPass rp = RP_1ST) const
{ return m_samplers[rp].empty(); }
// ------------------------------------------------------------------------
void setInitFunction(std::function<void(SPShader*)> func)
{
m_init_function = func;
}
// ------------------------------------------------------------------------
void unload();
// ------------------------------------------------------------------------
void init()
{
if (!m_shader_files.empty())
{
Log::error("SPShader",
"Please unload the shader before (re)init.");
return;
}
if (m_init_function)
{
m_init_function(this);
}
else
{
Log::error("SPShader", "Missing init function.");
}
}
};