OGL: Reload shader cache when relevant video config changes

This commit is contained in:
Stenzek
2017-06-24 19:20:34 +10:00
parent d1381f5021
commit 62a901508b
4 changed files with 103 additions and 57 deletions

View File

@ -504,29 +504,7 @@ void ProgramShaderCache::Init()
// Read our shader cache, only if supported and enabled
if (g_ogl_config.bSupportsGLSLCache && g_ActiveConfig.bShaderCache)
{
GLint Supported;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported);
if (!Supported)
{
ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So "
"disable shader cache.");
g_ogl_config.bSupportsGLSLCache = false;
}
else
{
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
std::string cache_filename =
StringFromFormat("%sogl-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().GetGameID().c_str());
ProgramShaderCacheInserter inserter;
g_program_disk_cache.OpenAndRead(cache_filename, inserter);
}
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
}
LoadProgramBinaries();
CreateHeader();
@ -534,47 +512,99 @@ void ProgramShaderCache::Init()
last_entry = nullptr;
}
void ProgramShaderCache::Reload()
{
const bool use_cache = g_ogl_config.bSupportsGLSLCache && g_ActiveConfig.bShaderCache;
if (use_cache)
SaveProgramBinaries();
g_program_disk_cache.Close();
DestroyShaders();
if (use_cache)
LoadProgramBinaries();
CurrentProgram = 0;
last_entry = nullptr;
last_uid = {};
}
void ProgramShaderCache::Shutdown()
{
// store all shaders in cache on disk
if (g_ogl_config.bSupportsGLSLCache)
if (g_ogl_config.bSupportsGLSLCache && g_ActiveConfig.bShaderCache)
SaveProgramBinaries();
g_program_disk_cache.Close();
DestroyShaders();
s_buffer.reset();
}
void ProgramShaderCache::LoadProgramBinaries()
{
GLint Supported;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &Supported);
if (!Supported)
{
for (auto& entry : pshaders)
ERROR_LOG(VIDEO, "GL_ARB_get_program_binary is supported, but no binary format is known. So "
"disable shader cache.");
g_ogl_config.bSupportsGLSLCache = false;
}
else
{
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
std::string host_part = g_ActiveConfig.GetHostConfigFilename();
std::string cache_filename =
StringFromFormat("%sogl-%s-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().GetGameID().c_str(), host_part.c_str());
ProgramShaderCacheInserter inserter;
g_program_disk_cache.OpenAndRead(cache_filename, inserter);
}
SETSTAT(stats.numPixelShadersAlive, pshaders.size());
}
void ProgramShaderCache::SaveProgramBinaries()
{
for (auto& entry : pshaders)
{
// Clear any prior error code
glGetError();
if (entry.second.in_cache)
{
// Clear any prior error code
glGetError();
if (entry.second.in_cache)
{
continue;
}
GLint link_status = GL_FALSE, delete_status = GL_TRUE, binary_size = 0;
glGetProgramiv(entry.second.shader.glprogid, GL_LINK_STATUS, &link_status);
glGetProgramiv(entry.second.shader.glprogid, GL_DELETE_STATUS, &delete_status);
glGetProgramiv(entry.second.shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &binary_size);
if (glGetError() != GL_NO_ERROR || link_status == GL_FALSE || delete_status == GL_TRUE ||
!binary_size)
{
continue;
}
std::vector<u8> data(binary_size + sizeof(GLenum));
u8* binary = &data[sizeof(GLenum)];
GLenum* prog_format = (GLenum*)&data[0];
glGetProgramBinary(entry.second.shader.glprogid, binary_size, nullptr, prog_format, binary);
if (glGetError() != GL_NO_ERROR)
{
continue;
}
g_program_disk_cache.Append(entry.first, &data[0], binary_size + sizeof(GLenum));
continue;
}
g_program_disk_cache.Sync();
g_program_disk_cache.Close();
GLint link_status = GL_FALSE, delete_status = GL_TRUE, binary_size = 0;
glGetProgramiv(entry.second.shader.glprogid, GL_LINK_STATUS, &link_status);
glGetProgramiv(entry.second.shader.glprogid, GL_DELETE_STATUS, &delete_status);
glGetProgramiv(entry.second.shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &binary_size);
if (glGetError() != GL_NO_ERROR || link_status == GL_FALSE || delete_status == GL_TRUE ||
!binary_size)
{
continue;
}
std::vector<u8> data(binary_size + sizeof(GLenum));
u8* binary = &data[sizeof(GLenum)];
GLenum* prog_format = (GLenum*)&data[0];
glGetProgramBinary(entry.second.shader.glprogid, binary_size, nullptr, prog_format, binary);
if (glGetError() != GL_NO_ERROR)
{
continue;
}
g_program_disk_cache.Append(entry.first, &data[0], binary_size + sizeof(GLenum));
}
g_program_disk_cache.Sync();
}
void ProgramShaderCache::DestroyShaders()
{
glUseProgram(0);
for (auto& entry : pshaders)
@ -582,8 +612,6 @@ void ProgramShaderCache::Shutdown()
entry.second.Destroy();
}
pshaders.clear();
s_buffer.reset();
}
void ProgramShaderCache::CreateHeader()