mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-29 17:15:40 +00:00
GL/ShaderCache: Recreate cache when creating program from binary fails
This is probably due to a driver or GPU change, so all programs will be "bad" and if we don't start from scratch, we'll never cache any new program versions.
This commit is contained in:
parent
ca2f691dbe
commit
f566ca7a50
|
@ -2,6 +2,7 @@
|
||||||
#include "../file_system.h"
|
#include "../file_system.h"
|
||||||
#include "../log.h"
|
#include "../log.h"
|
||||||
#include "../md5_digest.h"
|
#include "../md5_digest.h"
|
||||||
|
#include "../string_util.h"
|
||||||
Log_SetChannel(GL::ShaderCache);
|
Log_SetChannel(GL::ShaderCache);
|
||||||
|
|
||||||
namespace GL {
|
namespace GL {
|
||||||
|
@ -46,6 +47,7 @@ bool ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
|
||||||
|
|
||||||
void ShaderCache::Open(bool is_gles, std::string_view base_path)
|
void ShaderCache::Open(bool is_gles, std::string_view base_path)
|
||||||
{
|
{
|
||||||
|
m_base_path = base_path;
|
||||||
m_program_binary_supported = is_gles || GLAD_GL_ARB_get_program_binary;
|
m_program_binary_supported = is_gles || GLAD_GL_ARB_get_program_binary;
|
||||||
if (m_program_binary_supported)
|
if (m_program_binary_supported)
|
||||||
{
|
{
|
||||||
|
@ -63,9 +65,8 @@ void ShaderCache::Open(bool is_gles, std::string_view base_path)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string base_filename = GetCacheBaseFileName(base_path);
|
const std::string index_filename = GetIndexFileName();
|
||||||
const std::string index_filename = base_filename + ".idx";
|
const std::string blob_filename = GetBlobFileName();
|
||||||
const std::string blob_filename = base_filename + ".bin";
|
|
||||||
|
|
||||||
if (!ReadExisting(index_filename, blob_filename))
|
if (!ReadExisting(index_filename, blob_filename))
|
||||||
CreateNew(index_filename, blob_filename);
|
CreateNew(index_filename, blob_filename);
|
||||||
|
@ -172,18 +173,21 @@ bool ShaderCache::ReadExisting(const std::string& index_filename, const std::str
|
||||||
|
|
||||||
void ShaderCache::Close()
|
void ShaderCache::Close()
|
||||||
{
|
{
|
||||||
|
m_index.clear();
|
||||||
if (m_index_file)
|
if (m_index_file)
|
||||||
std::fclose(m_index_file);
|
std::fclose(m_index_file);
|
||||||
if (m_blob_file)
|
if (m_blob_file)
|
||||||
std::fclose(m_blob_file);
|
std::fclose(m_blob_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ShaderCache::GetCacheBaseFileName(const std::string_view& base_path)
|
bool ShaderCache::Recreate()
|
||||||
{
|
{
|
||||||
std::string base_filename(base_path);
|
Close();
|
||||||
base_filename += FS_OSPATH_SEPERATOR_CHARACTER;
|
|
||||||
base_filename += "gl_programs";
|
const std::string index_filename = GetIndexFileName();
|
||||||
return base_filename;
|
const std::string blob_filename = GetBlobFileName();
|
||||||
|
|
||||||
|
return CreateNew(index_filename, blob_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(const std::string_view& vertex_shader,
|
ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(const std::string_view& vertex_shader,
|
||||||
|
@ -214,6 +218,16 @@ ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(const std::string_view& vert
|
||||||
fragment_hash.low, fragment_hash.high, static_cast<u32>(fragment_shader.length())};
|
fragment_hash.low, fragment_hash.high, static_cast<u32>(fragment_shader.length())};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ShaderCache::GetIndexFileName() const
|
||||||
|
{
|
||||||
|
return StringUtil::StdStringFromFormat("%s%cgl_programs.idx", m_base_path.c_str(), FS_OSPATH_SEPERATOR_CHARACTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ShaderCache::GetBlobFileName() const
|
||||||
|
{
|
||||||
|
return StringUtil::StdStringFromFormat("%s%cgl_programs.bin", m_base_path.c_str(), FS_OSPATH_SEPERATOR_CHARACTER);
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_shader,
|
std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_shader,
|
||||||
const std::string_view fragment_shader, const PreLinkCallback& callback)
|
const std::string_view fragment_shader, const PreLinkCallback& callback)
|
||||||
{
|
{
|
||||||
|
@ -237,7 +251,12 @@ std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_sha
|
||||||
if (prog.CreateFromBinary(data.data(), static_cast<u32>(data.size()), iter->second.blob_format))
|
if (prog.CreateFromBinary(data.data(), static_cast<u32>(data.size()), iter->second.blob_format))
|
||||||
return prog;
|
return prog;
|
||||||
|
|
||||||
return CompileProgram(vertex_shader, fragment_shader, callback, false);
|
Log_WarningPrintf(
|
||||||
|
"Failed to create program from binary, this may be due to a driver or GPU Change. Recreating cache.");
|
||||||
|
if (!Recreate())
|
||||||
|
return CompileProgram(vertex_shader, fragment_shader, callback, false);
|
||||||
|
else
|
||||||
|
return CompileAndAddProgram(key, vertex_shader, fragment_shader, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Program> ShaderCache::CompileProgram(const std::string_view& vertex_shader,
|
std::optional<Program> ShaderCache::CompileProgram(const std::string_view& vertex_shader,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -60,18 +61,22 @@ private:
|
||||||
|
|
||||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||||
|
|
||||||
static std::string GetCacheBaseFileName(const std::string_view& base_path);
|
|
||||||
static CacheIndexKey GetCacheKey(const std::string_view& vertex_shader, const std::string_view& fragment_shader);
|
static CacheIndexKey GetCacheKey(const std::string_view& vertex_shader, const std::string_view& fragment_shader);
|
||||||
|
|
||||||
|
std::string GetIndexFileName() const;
|
||||||
|
std::string GetBlobFileName() const;
|
||||||
|
|
||||||
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
|
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
|
||||||
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
|
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
|
||||||
void Close();
|
void Close();
|
||||||
|
bool Recreate();
|
||||||
|
|
||||||
std::optional<Program> CompileProgram(const std::string_view& vertex_shader, const std::string_view& fragment_shader,
|
std::optional<Program> CompileProgram(const std::string_view& vertex_shader, const std::string_view& fragment_shader,
|
||||||
const PreLinkCallback& callback, bool set_retrievable);
|
const PreLinkCallback& callback, bool set_retrievable);
|
||||||
std::optional<Program> CompileAndAddProgram(const CacheIndexKey& key, const std::string_view& vertex_shader,
|
std::optional<Program> CompileAndAddProgram(const CacheIndexKey& key, const std::string_view& vertex_shader,
|
||||||
const std::string_view& fragment_shader, const PreLinkCallback& callback);
|
const std::string_view& fragment_shader, const PreLinkCallback& callback);
|
||||||
|
|
||||||
|
std::string m_base_path;
|
||||||
std::FILE* m_index_file = nullptr;
|
std::FILE* m_index_file = nullptr;
|
||||||
std::FILE* m_blob_file = nullptr;
|
std::FILE* m_blob_file = nullptr;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue