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:
parent
c68b6b9085
commit
7af25b2452
|
@ -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" />
|
||||
|
|
|
@ -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>
|
|
@ -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,
|
||||
|
|
159
src/Combiner.cpp
159
src/Combiner.cpp
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
19
src/Graphics/CombinerProgram.cpp
Normal file
19
src/Graphics/CombinerProgram.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
224
src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.cpp
Normal file
224
src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.cpp
Normal 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)
|
||||
{
|
||||
}
|
19
src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h
Normal file
19
src/Graphics/OpenGLContext/GLSL/glsl_ShaderStorage.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user