1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "Rendering/Shaders/ShaderHandler.h"
#include "Rendering/Shaders/Shader.h"
#include "System/Log/ILog.h"
#include <cassert>
CShaderHandler* CShaderHandler::GetInstance()
{
static CShaderHandler instance;
return &instance;
}
void CShaderHandler::ClearShaders(bool persistent)
{
for (auto& p: programObjects[persistent]) {
// release by poMap (not poClass) to avoid erase-while-iterating pattern
ReleaseProgramObjectsMap(p.second);
}
programObjects[persistent].clear();
}
void CShaderHandler::ReloadShaders(bool persistent)
{
for (const auto& p1: programObjects[persistent]) {
for (const auto& p2: p1.second) {
p2.second->Reload(true, false);
}
}
}
void CShaderHandler::InsertExtProgramObject(const char* name, Shader::IProgramObject* prog)
{
assert(name[0] != 0);
if (GetExtProgramObject(name) != nullptr)
return;
assert(GetExtShaderSources(name) == nullptr);
// for RenderDataBuffer shaders, collision freedom is
// guaranteed at compile-time by GetShaderName switch
const unsigned int hash = hashString(name);
extProgramObjects.insert(hash, prog);
extShaderSources.insert(hash, {});
// the attached shader objects may go away later, so make
// copies of their source strings while those still exist
for (const Shader::IShaderObject* shader: prog->GetShaderObjs()) {
extShaderSources[hash][ GL::ShaderTypeToEnum(shader->GetType()) ] = shader->GetSrc(false);
}
}
bool CShaderHandler::ReleaseProgramObjects(const std::string& poClass, bool persistent)
{
ProgramTable& pTable = programObjects[persistent];
if (pTable.find(poClass) == pTable.end())
return false;
ReleaseProgramObjectsMap(pTable[poClass]);
pTable.erase(poClass);
return true;
}
void CShaderHandler::ReleaseProgramObjectsMap(ProgramObjMap& poMap)
{
for (const auto& item: poMap) {
Shader::IProgramObject* po = item.second;
// free the program object and its attachments
if (po == Shader::nullProgramObject)
continue;
// erases
shaderCache.Find(po->GetHash());
po->Release();
delete po;
}
poMap.clear();
}
Shader::IProgramObject* CShaderHandler::CreateProgramObject(const std::string& poClass, const std::string& poName, bool persistent)
{
assert(!poClass.empty());
assert(!poName.empty());
ProgramTable& pTable = programObjects[persistent];
if (pTable.find(poClass) == pTable.end())
pTable[poClass] = ProgramObjMap();
if (pTable[poClass].find(poName) == pTable[poClass].end())
return (pTable[poClass][poName] = new Shader::GLSLProgramObject(poName));
// do not allow multiple references to the same shader
LOG_L(L_WARNING, "[SH::%s] program-object \"%s\" in class \"%s\" already exists", __func__, poName.c_str(), poClass.c_str());
return Shader::nullProgramObject;
}
Shader::IShaderObject* CShaderHandler::CreateShaderObject(const std::string& soName, const std::string& soDefs, int soType)
{
assert(!soName.empty());
return (new Shader::GLSLShaderObject(soType, soName, soDefs));
}
|