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

Rewrite shader cache

This commit is contained in:
Sergey Lipskiy 2017-01-07 22:46:51 +07:00
parent c68b6b9085
commit 7af25b2452
22 changed files with 402 additions and 189 deletions

View File

@ -307,6 +307,7 @@
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramBuilder.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramImpl.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactory.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderStorage.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_SpecialShadersFactory.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_Utils.cpp" />
<ClCompile Include="..\..\src\Graphics\OpenGLContext\opengl_Attributes.cpp" />
@ -451,6 +452,7 @@
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramImpl.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_CombinerProgramUniformFactory.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderPart.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderStorage.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_SpecialShadersFactory.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_Utils.h" />
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_Attributes.h" />

View File

@ -341,6 +341,9 @@
<ClCompile Include="..\..\src\Graphics\CombinerProgram.cpp">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderStorage.cpp">
<Filter>Source Files\Graphics\OpenGL\GLSL</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h">
@ -631,5 +634,8 @@
<ClInclude Include="..\..\src\Graphics\OpenGLContext\opengl_Utils.h">
<Filter>Header Files\Graphics\OpenGL</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Graphics\OpenGLContext\GLSL\glsl_ShaderStorage.h">
<Filter>Header Files\Graphics\OpenGL\GLSL</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -257,6 +257,14 @@ void RDRAMtoColorBuffer::copyFromRDRAM(u32 _address, bool _bCFB)
if (!bCopy)
return;
const u32 cycleType = gDP.otherMode.cycleType;
gDP.otherMode.cycleType = G_CYC_COPY;
CombinerInfo::get().setPolygonMode(OGLRender::rsTexRect);
CombinerInfo::get().update();
gDP.otherMode.cycleType = cycleType;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
#ifndef GLES2
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, fboFormats.colorFormat, fboFormats.colorType, 0);
@ -277,19 +285,11 @@ void RDRAMtoColorBuffer::copyFromRDRAM(u32 _address, bool _bCFB)
gDPTile * pTile0 = gSP.textureTile[0];
gSP.textureTile[0] = &tile0;
const u32 cycleType = gDP.otherMode.cycleType;
gDP.otherMode.cycleType = G_CYC_1CYCLE;
CombinerInfo::get().setPolygonMode(OGLRender::rsTexRect);
CombinerInfo::get().setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
currentCombiner()->disableBlending();
gDP.otherMode.cycleType = cycleType;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// currentCombiner()->updateFrameBufferInfo();
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
CombinerInfo::get().updateParameters();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurBuffer->m_FBO);
OGLRender::TexturedRectParams params((float)x0, (float)y0, (float)width, (float)height,
0.0f, 0.0f, width - 1.0f, height - 1.0f, 1.0f, 1.0f,

View File

@ -112,7 +112,7 @@ void CombinerInfo::init()
m_shadersLoaded = 0;
if (m_bShaderCacheSupported && !_loadShadersStorage()) {
for (Combiners::iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
for (auto cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
delete cur->second;
m_combiners.clear();
}
@ -130,7 +130,7 @@ void CombinerInfo::destroy()
if (m_bShaderCacheSupported)
_saveShadersStorage();
m_shadersLoaded = 0;
for (Combiners::iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
for (auto cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
delete cur->second;
m_combiners.clear();
}
@ -250,7 +250,7 @@ graphics::CombinerProgram * CombinerInfo::_compile(u64 mux) const
}
}
return gfxContext.createCombinerProgram(color, alpha, CombinerKey(combine.mux));
return gfxContext.createCombinerProgram(color, alpha, CombinerKey(mux));
}
void CombinerInfo::update()
@ -274,7 +274,7 @@ void CombinerInfo::setCombine(u64 _mux )
m_bChanged = false;
return;
}
Combiners::const_iterator iter = m_combiners.find(key);
auto iter = m_combiners.find(key);
if (iter != m_combiners.end()) {
m_pCurrent = iter->second;
} else {
@ -315,161 +315,20 @@ void CombinerInfo::setPolygonMode(OGLRender::RENDER_STATE _renderState)
}
}
#ifndef GLES2
#define SHADER_STORAGE_FOLDER_NAME L"shaders"
static
void getStorageFileName(wchar_t * _fileName)
{
wchar_t strCacheFolderPath[PLUGIN_PATH_SIZE];
api().GetUserCachePath(strCacheFolderPath);
wchar_t strShaderFolderPath[PLUGIN_PATH_SIZE];
swprintf(strShaderFolderPath, PLUGIN_PATH_SIZE, L"%ls/%ls", strCacheFolderPath, SHADER_STORAGE_FOLDER_NAME);
wchar_t * pPath = strShaderFolderPath;
if (!osal_path_existsW(strShaderFolderPath) || !osal_is_directory(strShaderFolderPath)) {
if (osal_mkdirp(strShaderFolderPath) != 0)
pPath = strCacheFolderPath;
}
#ifdef GLES3
const wchar_t* strOpenGLType = L"GLES3";
#elif GLES3_1
const wchar_t* strOpenGLType = L"GLES3_1";
#else
const wchar_t* strOpenGLType = L"OpenGL";
#endif
swprintf(_fileName, PLUGIN_PATH_SIZE, L"%ls/GLideN64.%08lx.%ls.shaders", pPath, std::hash<std::string>()(RSP.romname), strOpenGLType);
}
u32 CombinerInfo::_getConfigOptionsBitSet() const
{
std::vector<u32> vecOptions;
ShaderCombiner::getShaderCombinerOptionsSet(vecOptions);
u32 optionsSet = 0;
for (u32 i = 0; i < vecOptions.size(); ++i)
optionsSet |= vecOptions[i] << i;
return optionsSet;
}
/*
Storage format:
uint32 - format version;
uint32 - bitset of config options, which may change how shader is created.
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 ShaderStorageFormatVersion = 0x0DU;
void CombinerInfo::_saveShadersStorage() const
{
if (m_shadersLoaded >= m_combiners.size())
return;
wchar_t fileName[PLUGIN_PATH_SIZE];
getStorageFileName(fileName);
#if defined(OS_WINDOWS) && !defined(MINGW)
std::ofstream fout(fileName, std::ofstream::binary | std::ofstream::trunc);
#else
char fileName_c[PATH_MAX];
wcstombs(fileName_c, fileName, PATH_MAX);
std::ofstream fout(fileName_c, std::ofstream::binary | std::ofstream::trunc);
#endif
if (!fout)
return;
fout.write((char*)&ShaderStorageFormatVersion, sizeof(ShaderStorageFormatVersion));
fout.write((char*)&m_configOptionsBitSet, sizeof(m_configOptionsBitSet));
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();
gfxContext.saveShadersStorage(m_combiners);
}
bool CombinerInfo::_loadShadersStorage()
{
wchar_t fileName[PLUGIN_PATH_SIZE];
getStorageFileName(fileName);
m_configOptionsBitSet = _getConfigOptionsBitSet();
#if defined(OS_WINDOWS) && !defined(MINGW)
std::ifstream fin(fileName, std::ofstream::binary);
#else
char fileName_c[PATH_MAX];
wcstombs(fileName_c, fileName, PATH_MAX);
std::ifstream fin(fileName_c, std::ofstream::binary);
#endif
if (!fin)
return false;
try {
u32 version;
fin.read((char*)&version, sizeof(version));
if (version != ShaderStorageFormatVersion)
return false;
u32 optionsSet;
fin.read((char*)&optionsSet, sizeof(optionsSet));
if (optionsSet != m_configOptionsBitSet)
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) {
// TODO implement
// m_pCurrent = new ShaderCombiner();
fin >> *m_pCurrent;
m_pCurrent->update(true);
// m_pUniformCollection->bindWithShaderCombiner(m_pCurrent);
m_combiners[m_pCurrent->getKey()] = m_pCurrent;
}
}
catch (...) {
m_shadersLoaded = 0;
return false;
if (gfxContext.loadShadersStorage(m_combiners)) {
m_shadersLoaded = m_combiners.size();
return true;
}
m_shadersLoaded = m_combiners.size();
fin.close();
return !isGLError();
return false;
}
#else // GLES2
void CombinerInfo::_saveShadersStorage() const
{}
bool CombinerInfo::_loadShadersStorage()
{
return true;
}
#endif //GLES2

View File

@ -161,8 +161,7 @@ private:
u32 m_configOptionsBitSet;
graphics::CombinerProgram * m_pCurrent;
typedef std::map<CombinerKey, graphics::CombinerProgram *> Combiners;
Combiners m_combiners;
graphics::Combiners m_combiners;
std::unique_ptr<graphics::ShaderProgram> m_shadowmapProgram;
std::unique_ptr<graphics::ShaderProgram> m_monochromeProgram;

View File

@ -42,9 +42,16 @@ bool CombinerKey::operator<(const CombinerKey & _other) const
return m_key.mux < _other.m_key.mux;
}
u32 CombinerKey::getCycleType() const
{
return (m_key.muxs0 >> 25) & 3;
}
bool CombinerKey::isRectKey() const
{
// return ((m_key.muxs0 >> 24) & 1) != 0;
bool res = ((m_key.muxs0 >> 24) & 1) != 0;
return res;
return ((m_key.muxs0 >> 24) & 1) != 0;
}
void CombinerKey::read(std::istream & _is) {
_is.read((char*)&m_key.mux, sizeof(m_key.mux));
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <istream>
#include "gDP.h"
class CombinerKey {
@ -14,8 +15,13 @@ public:
bool operator<(const CombinerKey & _other) const;
bool isRectKey() const;
u32 getCycleType() const;
u64 getMux() const { return m_key.mux; }
void read(std::istream & _is);
private:
gDPCombine m_key;
};

View File

@ -0,0 +1,19 @@
#include "CombinerProgram.h"
#include <Config.h>
namespace graphics {
void CombinerProgram::getShaderCombinerOptionsSet(std::vector<u32> & _vecOptions)
{
// WARNING: Shader Storage format version must be increased after any change in this function.
_vecOptions.push_back(config.video.multisampling > 0 ? 1 : 0);
_vecOptions.push_back(config.texture.bilinearMode);
_vecOptions.push_back(config.generalEmulation.enableHWLighting);
_vecOptions.push_back(config.generalEmulation.enableNoise);
_vecOptions.push_back(config.generalEmulation.enableLOD);
_vecOptions.push_back(config.frameBufferEmulation.N64DepthCompare);
_vecOptions.push_back(config.generalEmulation.enableLegacyBlending);
_vecOptions.push_back(config.generalEmulation.enableFragmentDepthWrite);
}
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <map>
#include <vector>
#include "CombinerKey.h"
@ -20,10 +21,11 @@ namespace graphics {
void disableBlending() {}
void updateFrameBufferInfo(bool _bForce = false) {}
friend std::ostream & operator<< (std::ostream & _os, const CombinerProgram & _combiner);
friend std::istream & operator>> (std::istream & _os, CombinerProgram & _combiner);
virtual bool getBinaryForm(std::vector<char> & _buffer) = 0;
static void getShaderCombinerOptionsSet(std::vector<u32> & _vecOptions);
};
typedef std::map<CombinerKey, graphics::CombinerProgram *> Combiners;
}

View File

@ -83,6 +83,16 @@ CombinerProgram * Context::createCombinerProgram(Combiner & _color, Combiner & _
return m_impl->createCombinerProgram(_color, _alpha, _key);
}
bool Context::saveShadersStorage(const Combiners & _combiners)
{
return m_impl->saveShadersStorage(_combiners);
}
bool Context::loadShadersStorage(Combiners & _combiners)
{
return m_impl->loadShadersStorage(_combiners);
}
ShaderProgram * Context::createDepthFogShader()
{
return m_impl->createDepthFogShader();

View File

@ -105,6 +105,10 @@ namespace graphics {
CombinerProgram * createCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key);
bool saveShadersStorage(const Combiners & _combiners);
bool loadShadersStorage(Combiners & _combiners);
ShaderProgram * createDepthFogShader();
ShaderProgram * createMonochromeShader();

View File

@ -24,6 +24,8 @@ namespace graphics {
virtual void initRenderbuffer(const Context::InitRenderbufferParams & _params) = 0;
virtual PixelWriteBuffer * createPixelWriteBuffer(size_t _sizeInBytes) = 0;
virtual CombinerProgram * createCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key) = 0;
virtual bool saveShadersStorage(const Combiners & _combiners) = 0;
virtual bool loadShadersStorage(Combiners & _combiners) = 0;
virtual ShaderProgram * createDepthFogShader() = 0;
virtual ShaderProgram * createMonochromeShader() = 0;
};

View File

@ -8,6 +8,8 @@ namespace glsl {
public:
explicit CombinerInputs(int _inputs) : m_inputs(_inputs) {}
explicit operator int() { return m_inputs; }
bool usesTile(u32 _t) const;
bool usesTexture() const;

View File

@ -1863,7 +1863,7 @@ graphics::CombinerProgram * CombinerProgramBuilder::buildCombinerProgram(Combine
glDeleteShader(fragmentShader);
UniformGroups uniforms;
m_uniformFactory->buildUniforms(program, combinerInputs, bIsRect, uniforms);
m_uniformFactory->buildUniforms(program, combinerInputs, _key, uniforms);
return new CombinerProgramImpl(_key, program, combinerInputs, std::move(uniforms));
}

View File

@ -1,4 +1,7 @@
#include <fstream>
#include <assert.h>
#include <Combiner.h>
#include "glsl_Utils.h"
#include "glsl_CombinerProgramImpl.h"
using namespace glsl;
@ -56,17 +59,48 @@ bool CombinerProgramImpl::usesLOD() const {
return m_inputs.usesLOD();
}
namespace graphics {
bool CombinerProgramImpl::getBinaryForm(std::vector<char> & _buffer)
{
GLint binaryLength;
glGetProgramiv(m_program, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
// TODO implement
std::ostream & operator<< (std::ostream & _os, const CombinerProgram & _combiner)
{
return _os;
}
if (binaryLength < 1)
return false;
std::istream & operator>> (std::istream & _is, CombinerProgram & _combiner)
{
return _is;
}
std::vector<char> binary(binaryLength);
}
if (binary.size() == 0)
return false;
GLenum binaryFormat;
glGetProgramBinary(m_program, binaryLength, &binaryLength, &binaryFormat, binary.data());
if (isGLError())
return false;
u64 key = m_key.getMux();
int inputs(m_inputs);
int totalSize = sizeof(key)+sizeof(inputs)+sizeof(binaryFormat)+
sizeof(binaryLength)+binaryLength;
_buffer.resize(totalSize);
char* keyData = reinterpret_cast<char*>(&key);
std::copy_n(keyData, sizeof(key), _buffer.data());
int offset = sizeof(key);
char* inputData = reinterpret_cast<char*>(&inputs);
std::copy_n(inputData, sizeof(inputs), _buffer.data() + offset);
offset += sizeof(inputs);
char* binaryFormatData = reinterpret_cast<char*>(&binaryFormat);
std::copy_n(binaryFormatData, sizeof(binaryFormat), _buffer.data() + offset);
offset += sizeof(binaryFormat);
char* binaryLengthData = reinterpret_cast<char*>(&binaryLength);
std::copy_n(binaryLengthData, sizeof(binaryLength), _buffer.data() + offset);
offset += sizeof(binaryLength);
std::copy_n(binary.data(), binaryLength, _buffer.data() + offset);
return true;
}

View File

@ -32,6 +32,8 @@ namespace glsl {
bool usesShade() const override;
bool usesLOD() const override;
bool getBinaryForm(std::vector<char> & _buffer) override;
private:
bool m_bNeedUpdate;
CombinerKey m_key;

View File

@ -769,7 +769,7 @@ private:
void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
const CombinerInputs & _inputs,
bool _rect,
const CombinerKey & _key,
UniformGroups & _uniforms)
{
if (config.generalEmulation.enableNoise != 0)
@ -790,7 +790,7 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
_uniforms.emplace_back(new UFog(_program));
if (config.generalEmulation.enableLegacyBlending == 0) {
switch (gDP.otherMode.cycleType) {
switch (_key.getCycleType()) {
case G_CYC_1CYCLE:
_uniforms.emplace_back(new UBlendMode1Cycle(_program));
break;
@ -831,8 +831,9 @@ void CombinerProgramUniformFactory::buildUniforms(GLuint _program,
_uniforms.emplace_back(new UColors(_program));
if (_inputs.usesTexture()) {
_uniforms.emplace_back(new UTextureSize(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
if (!_rect)
if (m_glInfo.isGLES2)
_uniforms.emplace_back(new UTextureSize(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
if (!_key.isRectKey())
_uniforms.emplace_back(new UTextureParams(_program, _inputs.usesTile(0), _inputs.usesTile(1)));
}
@ -845,8 +846,4 @@ CombinerProgramUniformFactory::CombinerProgramUniformFactory(const opengl::GLInf
{
}
CombinerProgramUniformFactory::~CombinerProgramUniformFactory()
{
}
}

View File

@ -8,9 +8,11 @@ namespace glsl {
{
public:
CombinerProgramUniformFactory(const opengl::GLInfo & _glInfo);
~CombinerProgramUniformFactory();
void buildUniforms(GLuint _program, const CombinerInputs & _inputs, bool _rect, UniformGroups & _uniforms);
void buildUniforms(GLuint _program,
const CombinerInputs & _inputs,
const CombinerKey & _key,
UniformGroups & _uniforms);
private:
const opengl::GLInfo & m_glInfo;

View File

@ -0,0 +1,224 @@
#include <fstream>
#include <assert.h>
#include <Graphics/CombinerProgram.h>
#include <Graphics/OpenGLContext/opengl_Utils.h>
#include <Types.h>
#include <Log.h>
#include <RSP.h>
#include <PluginAPI.h>
#include <osal_files.h>
#include "glsl_Utils.h"
#include "glsl_ShaderStorage.h"
#include "glsl_CombinerProgramImpl.h"
#include "glsl_CombinerProgramUniformFactory.h"
using namespace glsl;
#define SHADER_STORAGE_FOLDER_NAME L"shaders"
static
void getStorageFileName(wchar_t * _fileName)
{
wchar_t strCacheFolderPath[PLUGIN_PATH_SIZE];
api().GetUserCachePath(strCacheFolderPath);
wchar_t strShaderFolderPath[PLUGIN_PATH_SIZE];
swprintf(strShaderFolderPath, PLUGIN_PATH_SIZE, L"%ls/%ls", strCacheFolderPath, SHADER_STORAGE_FOLDER_NAME);
wchar_t * pPath = strShaderFolderPath;
if (!osal_path_existsW(strShaderFolderPath) || !osal_is_directory(strShaderFolderPath)) {
if (osal_mkdirp(strShaderFolderPath) != 0)
pPath = strCacheFolderPath;
}
#ifdef GLES3
const wchar_t* strOpenGLType = L"GLES3";
#elif GLES3_1
const wchar_t* strOpenGLType = L"GLES3_1";
#else
const wchar_t* strOpenGLType = L"OpenGL";
#endif
swprintf(_fileName, PLUGIN_PATH_SIZE, L"%ls/GLideN64.%08lx.%ls.shaders", pPath, std::hash<std::string>()(RSP.romname), strOpenGLType);
}
static
u32 _getConfigOptionsBitSet()
{
std::vector<u32> vecOptions;
graphics::CombinerProgram::getShaderCombinerOptionsSet(vecOptions);
u32 optionsSet = 0;
for (u32 i = 0; i < vecOptions.size(); ++i)
optionsSet |= vecOptions[i] << i;
return optionsSet;
}
/*
Storage format:
uint32 - format version;
uint32 - bitset of config options, which may change how shader is created.
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 ShaderStorageFormatVersion = 0x0DU;
bool ShaderStorage::saveShadersStorage(const graphics::Combiners & _combiners) const
{
wchar_t fileName[PLUGIN_PATH_SIZE];
getStorageFileName(fileName);
#if defined(OS_WINDOWS) && !defined(MINGW)
std::ofstream fout(fileName, std::ofstream::binary | std::ofstream::trunc);
#else
char fileName_c[PATH_MAX];
wcstombs(fileName_c, fileName, PATH_MAX);
std::ofstream fout(fileName_c, std::ofstream::binary | std::ofstream::trunc);
#endif
if (!fout)
return false;
fout.write((char*)&ShaderStorageFormatVersion, sizeof(ShaderStorageFormatVersion));
const u32 configOptionsBitSet = _getConfigOptionsBitSet();
fout.write((char*)&configOptionsBitSet, sizeof(configOptionsBitSet));
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 = _combiners.size();
#if 0
fout.write((char*)&len, sizeof(len));
for (auto cur = _combiners.begin(); cur != _combiners.end(); ++cur)
fout << *(cur->second);
#else
u32 totalWritten = 0;
std::vector<char> allShaderData;
for (auto cur = _combiners.begin(); cur != _combiners.end(); ++cur)
{
std::vector<char> data;
if (cur->second->getBinaryForm(data))
{
allShaderData.insert(allShaderData.end(), data.begin(), data.end());
++totalWritten;
}
else
{
LOG(LOG_ERROR, "Error while writing shader with key key=0x%016lX",
static_cast<long unsigned int>(cur->second->getKey().getMux()));
}
}
fout.write((char*)&totalWritten, sizeof(totalWritten));
fout.write(allShaderData.data(), allShaderData.size());
#endif
fout.flush();
fout.close();
return true;
}
static
CombinerProgramImpl * _readCominerProgramFromStream(std::istream & _is, CombinerProgramUniformFactory & _uniformFactory)
{
CombinerKey cmbKey;
cmbKey.read(_is);
int inputs;
_is.read((char*)&inputs, sizeof(inputs));
CombinerInputs cmbInputs(inputs);
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);
GLuint program = glCreateProgram();
const bool isRect = cmbKey.isRectKey();
glsl::Utils::locateAttributes(program, isRect, cmbInputs.usesTexture());
glProgramBinary(program, binaryFormat, binary.data(), binaryLength);
assert(glsl::Utils::checkProgramLinkStatus(program));
UniformGroups uniforms;
_uniformFactory.buildUniforms(program, cmbInputs, cmbKey, uniforms);
return new CombinerProgramImpl(cmbKey, program, cmbInputs, std::move(uniforms));
}
bool ShaderStorage::loadShadersStorage(graphics::Combiners & _combiners)
{
wchar_t fileName[PLUGIN_PATH_SIZE];
getStorageFileName(fileName);
const u32 configOptionsBitSet = _getConfigOptionsBitSet();
#if defined(OS_WINDOWS) && !defined(MINGW)
std::ifstream fin(fileName, std::ofstream::binary);
#else
char fileName_c[PATH_MAX];
wcstombs(fileName_c, fileName, PATH_MAX);
std::ifstream fin(fileName_c, std::ofstream::binary);
#endif
if (!fin)
return false;
try {
u32 version;
fin.read((char*)&version, sizeof(version));
if (version != ShaderStorageFormatVersion)
return false;
u32 optionsSet;
fin.read((char*)&optionsSet, sizeof(optionsSet));
if (optionsSet != configOptionsBitSet)
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;
CombinerProgramUniformFactory uniformFactory(m_glinfo);
fin.read((char*)&len, sizeof(len));
for (u32 i = 0; i < len; ++i) {
CombinerProgramImpl * pCombiner = _readCominerProgramFromStream(fin, uniformFactory);
pCombiner->update(true);
_combiners[pCombiner->getKey()] = pCombiner;
}
}
catch (...) {
LOG(LOG_ERROR, "Stream error while loading shader cache! Buffer is probably not big enough");
}
// m_shadersLoaded = m_combiners.size();
fin.close();
return !opengl::Utils::isGLError();
}
ShaderStorage::ShaderStorage(const opengl::GLInfo & _glinfo)
: m_glinfo(_glinfo)
{
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <Graphics/OpenGLContext/opengl_GLInfo.h>
namespace glsl {
class ShaderStorage
{
public:
ShaderStorage(const opengl::GLInfo & _glinfo);
bool saveShadersStorage(const graphics::Combiners & _combiners) const;
bool loadShadersStorage(graphics::Combiners & _combiners);
private:
const opengl::GLInfo & m_glinfo;
};
}

View File

@ -3,6 +3,7 @@
#include "opengl_ContextImpl.h"
#include "GLSL/glsl_CombinerProgramBuilder.h"
#include "GLSL/glsl_SpecialShadersFactory.h"
#include "GLSL/glsl_ShaderStorage.h"
using namespace opengl;
@ -123,6 +124,18 @@ graphics::CombinerProgram * ContextImpl::createCombinerProgram(Combiner & _color
return m_combinerProgramBuilder->buildCombinerProgram(_color, _alpha, _key);
}
bool ContextImpl::saveShadersStorage(const graphics::Combiners & _combiners)
{
glsl::ShaderStorage storage(m_glInfo);
return storage.saveShadersStorage(_combiners);
}
bool ContextImpl::loadShadersStorage(graphics::Combiners & _combiners)
{
glsl::ShaderStorage storage(m_glInfo);
return storage.loadShadersStorage(_combiners);
}
graphics::ShaderProgram * ContextImpl::createDepthFogShader()
{
glsl::SpecialShadersFactory shadersFactory(m_glInfo,

View File

@ -46,6 +46,10 @@ namespace opengl {
graphics::CombinerProgram * createCombinerProgram(Combiner & _color, Combiner & _alpha, const CombinerKey & _key) override;
bool saveShadersStorage(const graphics::Combiners & _combiners) override;
bool loadShadersStorage(graphics::Combiners & _combiners) override;
graphics::ShaderProgram * createDepthFogShader() override;
graphics::ShaderProgram * createMonochromeShader() override;