mirror of https://github.com/axmolengine/axmol.git
133 lines
3.8 KiB
C++
133 lines
3.8 KiB
C++
#include "ProgramCache.h"
|
|
#include "Device.h"
|
|
#include "ShaderModule.h"
|
|
#include "renderer/ccShaders.h"
|
|
|
|
CC_BACKEND_BEGIN
|
|
|
|
std::unordered_map<std::size_t, backend::Program*> ProgramCache::_cachedPrograms;
|
|
ProgramCache* ProgramCache::_sharedProgramCache = nullptr;
|
|
|
|
ProgramCache* ProgramCache::getInstance()
|
|
{
|
|
if(!_sharedProgramCache)
|
|
{
|
|
_sharedProgramCache = new (std::nothrow) ProgramCache();
|
|
if(!_sharedProgramCache->init())
|
|
{
|
|
CC_SAFE_RELEASE(_sharedProgramCache);
|
|
}
|
|
}
|
|
return _sharedProgramCache;
|
|
}
|
|
|
|
void ProgramCache::destroyInstance()
|
|
{
|
|
CC_SAFE_RELEASE_NULL(_sharedProgramCache);
|
|
}
|
|
|
|
ProgramCache::~ProgramCache()
|
|
{
|
|
for(auto& program : _cachedPrograms)
|
|
{
|
|
CC_SAFE_RELEASE(program.second);
|
|
}
|
|
CCLOGINFO("deallocing ProgramCache: %p", this);
|
|
ShaderCache::destroyInstance();
|
|
}
|
|
|
|
bool ProgramCache::init()
|
|
{
|
|
addProgram(positionTextureColor_vert, positionTextureColor_frag);
|
|
addProgram(positionTextureColor_vert, etc1_frag);
|
|
addProgram(positionTextureColor_vert, label_distanceNormal_frag);
|
|
addProgram(positionTextureColor_vert, label_normal_frag);
|
|
addProgram(positionTextureColor_vert, labelOutline_frag);
|
|
addProgram(positionTextureColor_vert, labelDistanceFieldGlow_frag);
|
|
addProgram(positionColorLengthTexture_vert, positionColorLengthTexture_frag);
|
|
addProgram(positionColorTextureAsPointsize_vert, positionColor_frag);
|
|
addProgram(positionColor_vert, positionColor_frag);
|
|
addProgram(position_vert, layer_radialGradient_frag);
|
|
addProgram(positionTexture_vert, positionTexture_frag);
|
|
addProgram(positionTextureColor_vert, positionTextureColorAlphaTest_frag);
|
|
addProgram(positionUColor_vert, positionUColor_frag);
|
|
addProgram(positionTextureColor_vert, etc1Gray_frag);
|
|
addProgram(positionTextureColor_vert, grayScale_frag);
|
|
addProgram(lineColor3D_vert, lineColor3D_frag);
|
|
return true;
|
|
}
|
|
|
|
void ProgramCache::addProgram(const std::string& vertexShader, const std::string& fragmentShader)
|
|
{
|
|
std::string shaderSource = vertexShader + fragmentShader;
|
|
auto key = std::hash<std::string>{}(shaderSource);
|
|
auto program = backend::Device::getInstance()->newProgram(vertexShader, fragmentShader);
|
|
ProgramCache::_cachedPrograms.emplace(key, program);
|
|
}
|
|
|
|
backend::Program* ProgramCache::newProgram(const std::string& vertexShader, const std::string& fragmentShader)
|
|
{
|
|
std::string shaderSource = vertexShader + fragmentShader;
|
|
auto key = std::hash<std::string>{}(shaderSource);
|
|
const auto& iter = ProgramCache::_cachedPrograms.find(key);
|
|
if (ProgramCache::_cachedPrograms.end() != iter)
|
|
{
|
|
CC_SAFE_RETAIN(iter->second);
|
|
return iter->second;
|
|
}
|
|
|
|
auto program = backend::Device::getInstance()->newProgram(vertexShader, fragmentShader);
|
|
ProgramCache::_cachedPrograms.emplace(key, program);
|
|
|
|
return program;
|
|
}
|
|
|
|
void ProgramCache::removeProgram(backend::Program* program)
|
|
{
|
|
if (!program)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (auto it = _cachedPrograms.cbegin(); it != _cachedPrograms.cend();)
|
|
{
|
|
if (it->second == program)
|
|
{
|
|
it->second->release();
|
|
it = _cachedPrograms.erase(it);
|
|
break;
|
|
}
|
|
else
|
|
++it;
|
|
}
|
|
}
|
|
|
|
void ProgramCache::removeUnusedProgram()
|
|
{
|
|
for (auto iter = _cachedPrograms.cbegin(); iter != _cachedPrograms.cend();)
|
|
{
|
|
auto program = iter->second;
|
|
if (program->getReferenceCount() == 1)
|
|
{
|
|
// CCLOG("cocos2d: TextureCache: removing unused program");
|
|
program->release();
|
|
iter = _cachedPrograms.erase(iter);
|
|
}
|
|
else
|
|
{
|
|
++iter;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProgramCache::removeAllPrograms()
|
|
{
|
|
for (auto& program : _cachedPrograms)
|
|
{
|
|
program.second->release();
|
|
}
|
|
_cachedPrograms.clear();
|
|
}
|
|
|
|
CC_BACKEND_END
|