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:
parent
4505f6031d
commit
38baef70de
105
src/Combiner.cpp
105
src/Combiner.cpp
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user