1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-25 05:49:34 +00:00

Implement persistent cache for compiled shaders.

This commit is contained in:
Sergey Lipskiy 2015-10-08 22:54:01 +06:00
parent 4505f6031d
commit 38baef70de
4 changed files with 167 additions and 3 deletions

View File

@ -1,9 +1,12 @@
#include <fstream>
#include "OpenGL.h"
#include "Combiner.h"
#include "GLSLCombiner.h"
#include "UniformCollection.h"
#include "Debug.h"
#include "gDP.h"
#include "PluginAPI.h"
static int saRGBExpanded[] =
{
@ -68,8 +71,10 @@ void Combiner_Init() {
cmbInfo.init();
InitShaderCombiner();
gDP.otherMode.cycleType = G_CYC_1CYCLE;
cmbInfo.setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
cmbInfo.setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1));
if (cmbInfo.getCombinersNumber() == 0) {
cmbInfo.setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
cmbInfo.setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1));
}
}
void Combiner_Destroy() {
@ -87,6 +92,14 @@ void CombinerInfo::init()
{
m_pCurrent = NULL;
m_pUniformCollection = createUniformCollection();
m_bShaderCacheSupported = OGLVideo::isExtensionSupported("GL_ARB_get_program_binary");
m_shadersLoaded = 0;
if (!_loadCombinersCache()) {
for (Combiners::iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
delete cur->second;
m_combiners.clear();
}
}
void CombinerInfo::destroy()
@ -94,6 +107,7 @@ void CombinerInfo::destroy()
delete m_pUniformCollection;
m_pUniformCollection = NULL;
m_pCurrent = NULL;
_saveCombinersCache();
for (Combiners::iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
delete cur->second;
m_combiners.clear();
@ -300,3 +314,90 @@ void CombinerInfo::updateParameters(OGLRender::RENDER_STATE _renderState)
if (m_pUniformCollection != NULL)
m_pUniformCollection->updateUniforms(m_pCurrent, _renderState);
}
/*
Storage format:
uint32 - format version;
uint32 - len of renderer string
char * - renderer string
uint32 - len of GL version string
char * - GL version string
uint32 - number of shaders
shaders in binary form
*/
static const u32 CombinersCacheFormatVersion = 0x01U;
void CombinerInfo::_saveCombinersCache() const
{
if (!m_bShaderCacheSupported || m_shadersLoaded >= m_combiners.size())
return;
wchar_t strIniFolderPath[PLUGIN_PATH_SIZE];
api().FindPluginPath(strIniFolderPath);
std::wstring fileName(strIniFolderPath);
fileName += L"/GLideN64.shaders.bin";
std::ofstream fout(fileName, std::ofstream::binary | std::ofstream::trunc);
if (!fout)
return;
fout.write((char*)&CombinersCacheFormatVersion, sizeof(CombinersCacheFormatVersion));
const char * strRenderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
u32 len = strlen(strRenderer);
fout.write((char*)&len, sizeof(len));
fout.write(strRenderer, len);
const char * strGLVersion = reinterpret_cast<const char *>(glGetString(GL_VERSION));
len = strlen(strGLVersion);
fout.write((char*)&len, sizeof(len));
fout.write(strGLVersion, len);
len = m_combiners.size();
fout.write((char*)&len, sizeof(len));
for (Combiners::const_iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
fout << *(cur->second);
fout.flush();
fout.close();
}
bool CombinerInfo::_loadCombinersCache()
{
if (!m_bShaderCacheSupported)
return false;
wchar_t strIniFolderPath[PLUGIN_PATH_SIZE];
api().FindPluginPath(strIniFolderPath);
std::wstring fileName(strIniFolderPath);
fileName += L"/GLideN64.shaders.bin";
std::ifstream fin(fileName, std::ofstream::binary);
if (!fin)
return false;
u32 version;
fin.read((char*)&version, sizeof(version));
if (version != CombinersCacheFormatVersion)
return false;
const char * strRenderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
u32 len;
fin.read((char*)&len, sizeof(len));
std::vector<char> strBuf(len);
fin.read(strBuf.data(), len);
if (strncmp(strRenderer, strBuf.data(), len) != 0)
return false;
const char * strGLVersion = reinterpret_cast<const char *>(glGetString(GL_VERSION));
fin.read((char*)&len, sizeof(len));
strBuf.resize(len);
fin.read(strBuf.data(), len);
if (strncmp(strGLVersion, strBuf.data(), len) != 0)
return false;
fin.read((char*)&len, sizeof(len));
for (u32 i = 0; i < len; ++i) {
m_pCurrent = new ShaderCombiner();
fin >> *m_pCurrent;
m_pCurrent->update(true);
m_pUniformCollection->bindWithShaderCombiner(m_pCurrent);
m_combiners[m_pCurrent->getMux()] = m_pCurrent;
}
m_shadersLoaded = m_combiners.size();
fin.close();
return !isGLError();
}

View File

@ -125,6 +125,8 @@ public:
ShaderCombiner * getCurrent() const {return m_pCurrent;}
bool isChanged() const {return m_bChanged;}
bool isShaderCacheSupported() const { return m_bShaderCacheSupported; }
size_t getCombinersNumber() const { return m_combiners.size(); }
static CombinerInfo & get();
@ -141,12 +143,17 @@ public:
void updateParameters(OGLRender::RENDER_STATE _renderState);
private:
CombinerInfo() : m_bChanged(false), m_pCurrent(NULL) {}
CombinerInfo() : m_bChanged(false), m_bShaderCacheSupported(false), m_shadersLoaded(0), m_pCurrent(NULL) {}
CombinerInfo(const CombinerInfo &);
void _saveCombinersCache() const;
bool _loadCombinersCache();
ShaderCombiner * _compile(u64 mux) const;
bool m_bChanged;
bool m_bShaderCacheSupported;
u32 m_shadersLoaded;
ShaderCombiner * m_pCurrent;
typedef std::map<u64, ShaderCombiner *> Combiners;
Combiners m_combiners;

View File

@ -2,11 +2,13 @@
#define GLSL_COMBINER_H
#include <vector>
#include <iostream>
#include "gDP.h"
#include "Combiner.h"
class ShaderCombiner {
public:
ShaderCombiner();
ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCombine & _combine);
~ShaderCombiner();
@ -33,6 +35,9 @@ public:
bool usesShade() const { return (m_nInputs & ((1 << SHADE) | (1 << SHADE_ALPHA))) != 0; }
bool usesShadeColor() const { return (m_nInputs & (1 << SHADE)) != 0; }
friend std::ostream & operator<< (std::ostream & _os, const ShaderCombiner & _combiner);
friend std::istream & operator>> (std::istream & _os, ShaderCombiner & _combiner);
private:
friend class UniformBlock;
friend class UniformSet;

View File

@ -273,6 +273,12 @@ void DestroyShaderCombiner() {
#endif // GL_IMAGE_TEXTURES_SUPPORT
}
ShaderCombiner::ShaderCombiner()
{
m_program = glCreateProgram();
_locate_attributes();
}
ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCombine & _combine) : m_combine(_combine)
{
char strCombiner[1024];
@ -420,6 +426,8 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
glAttachShader(m_program, g_dither_shader_object);
}
#endif
if (CombinerInfo::get().isShaderCacheSupported())
glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
glLinkProgram(m_program);
assert(checkProgramLinkStatus(m_program));
glDeleteShader(fragmentShader);
@ -740,6 +748,49 @@ void ShaderCombiner::updateAlphaTestInfo(bool _bForce) {
}
}
std::ostream & operator<< (std::ostream & _os, const ShaderCombiner & _combiner)
{
GLint binaryLength;
glGetProgramiv(_combiner.m_program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
if (binaryLength < 1)
return _os;
std::vector<char> binary(binaryLength);
if (binary.size() == 0)
return _os;
GLenum binaryFormat;
glGetProgramBinary(_combiner.m_program, binaryLength, &binaryLength, &binaryFormat, binary.data());
if (isGLError())
return _os;
_os.write((char*)&_combiner.m_combine.mux, sizeof(_combiner.m_combine.mux));
_os.write((char*)&_combiner.m_nInputs, sizeof(_combiner.m_nInputs));
_os.write((char*)&binaryFormat, sizeof(binaryFormat));
_os.write((char*)&binaryLength, sizeof(binaryLength));
_os.write(binary.data(), binaryLength);
return _os;
}
std::istream & operator>> (std::istream & _is, ShaderCombiner & _combiner)
{
_is.read((char*)&_combiner.m_combine.mux, sizeof(_combiner.m_combine.mux));
_is.read((char*)&_combiner.m_nInputs, sizeof(_combiner.m_nInputs));
GLenum binaryFormat;
GLint binaryLength;
_is.read((char*)&binaryFormat, sizeof(binaryFormat));
_is.read((char*)&binaryLength, sizeof(binaryLength));
std::vector<char> binary(binaryLength);
_is.read(binary.data(), binaryLength);
glProgramBinary(_combiner.m_program, binaryFormat, binary.data(), binaryLength);
assert(checkProgramLinkStatus(_combiner.m_program));
_combiner._locateUniforms();
return _is;
}
#ifdef GL_IMAGE_TEXTURES_SUPPORT
void SetDepthFogCombiner()
{