Only load precompiled shaders if their sanitize_mul setting matches
This commit is contained in:
parent
6945b6539f
commit
cf4125a6a5
|
@ -557,7 +557,7 @@ std::optional<std::string> GetCurrentDir() {
|
||||||
#endif
|
#endif
|
||||||
free(dir);
|
free(dir);
|
||||||
return strDir;
|
return strDir;
|
||||||
}
|
} // namespace FileUtil
|
||||||
|
|
||||||
bool SetCurrentDir(const std::string& directory) {
|
bool SetCurrentDir(const std::string& directory) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
|
@ -889,16 +889,17 @@ bool exec_shader();
|
||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> DecompileProgram(const Pica::Shader::ProgramCode& program_code,
|
std::optional<ProgramResult> DecompileProgram(const Pica::Shader::ProgramCode& program_code,
|
||||||
const Pica::Shader::SwizzleData& swizzle_data,
|
const Pica::Shader::SwizzleData& swizzle_data,
|
||||||
u32 main_offset, const RegGetter& inputreg_getter,
|
u32 main_offset, const RegGetter& inputreg_getter,
|
||||||
const RegGetter& outputreg_getter, bool sanitize_mul) {
|
const RegGetter& outputreg_getter,
|
||||||
|
bool sanitize_mul) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto subroutines = ControlFlowAnalyzer(program_code, main_offset).MoveSubroutines();
|
auto subroutines = ControlFlowAnalyzer(program_code, main_offset).MoveSubroutines();
|
||||||
GLSLGenerator generator(subroutines, program_code, swizzle_data, main_offset,
|
GLSLGenerator generator(subroutines, program_code, swizzle_data, main_offset,
|
||||||
inputreg_getter, outputreg_getter, sanitize_mul);
|
inputreg_getter, outputreg_getter, sanitize_mul);
|
||||||
return generator.MoveShaderCode();
|
return {ProgramResult{generator.MoveShaderCode()}};
|
||||||
} catch (const DecompileFail& exception) {
|
} catch (const DecompileFail& exception) {
|
||||||
LOG_INFO(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
LOG_INFO(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
namespace OpenGL::ShaderDecompiler {
|
namespace OpenGL::ShaderDecompiler {
|
||||||
|
|
||||||
using RegGetter = std::function<std::string(u32)>;
|
using RegGetter = std::function<std::string(u32)>;
|
||||||
using ProgramResult = std::string;
|
|
||||||
|
struct ProgramResult {
|
||||||
|
std::string code;
|
||||||
|
};
|
||||||
|
|
||||||
std::string GetCommonDeclarations();
|
std::string GetCommonDeclarations();
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,12 @@ ShaderDiskCache::LoadPrecompiledFile(FileUtil::IOFile& file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ShaderDiskCacheDecompiled> ShaderDiskCache::LoadDecompiledEntry() {
|
std::optional<ShaderDiskCacheDecompiled> ShaderDiskCache::LoadDecompiledEntry() {
|
||||||
|
|
||||||
|
bool sanitize_mul;
|
||||||
|
if (!LoadObjectFromPrecompiled(sanitize_mul)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
u32 code_size{};
|
u32 code_size{};
|
||||||
if (!LoadObjectFromPrecompiled(code_size)) {
|
if (!LoadObjectFromPrecompiled(code_size)) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -281,17 +287,19 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCache::LoadDecompiledEntry()
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderDiskCacheDecompiled entry;
|
ShaderDiskCacheDecompiled entry;
|
||||||
entry.code = std::move(code);
|
entry.result.code = std::move(code);
|
||||||
|
entry.sanitize_mul = sanitize_mul;
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderDiskCache::SaveDecompiledFile(u64 unique_identifier,
|
bool ShaderDiskCache::SaveDecompiledFile(u64 unique_identifier,
|
||||||
const ShaderDecompiler::ProgramResult& code) {
|
const ShaderDecompiler::ProgramResult& result,
|
||||||
|
bool sanitize_mul) {
|
||||||
if (!SaveObjectToPrecompiled(static_cast<u32>(PrecompiledEntryKind::Decompiled)) ||
|
if (!SaveObjectToPrecompiled(static_cast<u32>(PrecompiledEntryKind::Decompiled)) ||
|
||||||
!SaveObjectToPrecompiled(unique_identifier) ||
|
!SaveObjectToPrecompiled(unique_identifier) || !SaveObjectToPrecompiled(sanitize_mul) ||
|
||||||
!SaveObjectToPrecompiled(static_cast<u32>(code.size())) ||
|
!SaveObjectToPrecompiled(static_cast<u32>(result.code.size())) ||
|
||||||
!SaveArrayToPrecompiled(code.data(), code.size())) {
|
!SaveArrayToPrecompiled(result.code.data(), result.code.size())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +346,8 @@ void ShaderDiskCache::SaveRaw(const ShaderDiskCacheRaw& entry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderDiskCache::SaveDecompiled(u64 unique_identifier,
|
void ShaderDiskCache::SaveDecompiled(u64 unique_identifier,
|
||||||
const ShaderDecompiler::ProgramResult& code) {
|
const ShaderDecompiler::ProgramResult& code,
|
||||||
|
bool sanitize_mul) {
|
||||||
if (!IsUsable())
|
if (!IsUsable())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -346,7 +355,7 @@ void ShaderDiskCache::SaveDecompiled(u64 unique_identifier,
|
||||||
SavePrecompiledHeaderToVirtualPrecompiledCache();
|
SavePrecompiledHeaderToVirtualPrecompiledCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SaveDecompiledFile(unique_identifier, code)) {
|
if (!SaveDecompiledFile(unique_identifier, code, sanitize_mul)) {
|
||||||
LOG_ERROR(Render_OpenGL,
|
LOG_ERROR(Render_OpenGL,
|
||||||
"Failed to save decompiled entry to the precompiled file - removing");
|
"Failed to save decompiled entry to the precompiled file - removing");
|
||||||
InvalidatePrecompiled();
|
InvalidatePrecompiled();
|
||||||
|
|
|
@ -78,7 +78,8 @@ private:
|
||||||
|
|
||||||
/// Contains decompiled data from a shader
|
/// Contains decompiled data from a shader
|
||||||
struct ShaderDiskCacheDecompiled {
|
struct ShaderDiskCacheDecompiled {
|
||||||
ShaderDecompiler::ProgramResult code;
|
ShaderDecompiler::ProgramResult result;
|
||||||
|
bool sanitize_mul;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains an OpenGL dumped binary program
|
/// Contains an OpenGL dumped binary program
|
||||||
|
@ -108,7 +109,8 @@ public:
|
||||||
void SaveRaw(const ShaderDiskCacheRaw& entry);
|
void SaveRaw(const ShaderDiskCacheRaw& entry);
|
||||||
|
|
||||||
/// Saves a decompiled entry to the precompiled file. Does not check for collisions.
|
/// Saves a decompiled entry to the precompiled file. Does not check for collisions.
|
||||||
void SaveDecompiled(u64 unique_identifier, const ShaderDecompiler::ProgramResult& code);
|
void SaveDecompiled(u64 unique_identifier, const ShaderDecompiler::ProgramResult& code,
|
||||||
|
bool sanitize_mul);
|
||||||
|
|
||||||
/// Saves a dump entry to the precompiled file. Does not check for collisions.
|
/// Saves a dump entry to the precompiled file. Does not check for collisions.
|
||||||
void SaveDump(u64 unique_identifier, GLuint program);
|
void SaveDump(u64 unique_identifier, GLuint program);
|
||||||
|
@ -126,7 +128,8 @@ private:
|
||||||
std::optional<ShaderDiskCacheDecompiled> LoadDecompiledEntry();
|
std::optional<ShaderDiskCacheDecompiled> LoadDecompiledEntry();
|
||||||
|
|
||||||
/// Saves a decompiled entry to the passed file. Returns true on success.
|
/// Saves a decompiled entry to the passed file. Returns true on success.
|
||||||
bool SaveDecompiledFile(u64 unique_identifier, const ShaderDecompiler::ProgramResult& code);
|
bool SaveDecompiledFile(u64 unique_identifier, const ShaderDecompiler::ProgramResult& code,
|
||||||
|
bool sanitize_mul);
|
||||||
|
|
||||||
/// Returns if the cache can be used
|
/// Returns if the cache can be used
|
||||||
bool IsUsable() const;
|
bool IsUsable() const;
|
||||||
|
|
|
@ -1231,7 +1231,8 @@ float ProcTexNoiseCoef(vec2 x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateFragmentShader(const PicaFSConfig& config, bool separable_shader) {
|
ShaderDecompiler::ProgramResult GenerateFragmentShader(const PicaFSConfig& config,
|
||||||
|
bool separable_shader) {
|
||||||
const auto& state = config.state;
|
const auto& state = config.state;
|
||||||
|
|
||||||
std::string out = R"(
|
std::string out = R"(
|
||||||
|
@ -1482,7 +1483,7 @@ vec4 secondary_fragment_color = vec4(0.0);
|
||||||
// Do not do any sort of processing if it's obvious we're not going to pass the alpha test
|
// Do not do any sort of processing if it's obvious we're not going to pass the alpha test
|
||||||
if (state.alpha_test_func == FramebufferRegs::CompareFunc::Never) {
|
if (state.alpha_test_func == FramebufferRegs::CompareFunc::Never) {
|
||||||
out += "discard; }";
|
out += "discard; }";
|
||||||
return out;
|
return {out};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the scissor test
|
// Append the scissor test
|
||||||
|
@ -1546,7 +1547,7 @@ vec4 secondary_fragment_color = vec4(0.0);
|
||||||
"VideoCore_Pica_UseGasMode", true);
|
"VideoCore_Pica_UseGasMode", true);
|
||||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented gas mode");
|
LOG_CRITICAL(Render_OpenGL, "Unimplemented gas mode");
|
||||||
out += "discard; }";
|
out += "discard; }";
|
||||||
return out;
|
return {out};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.shadow_rendering) {
|
if (state.shadow_rendering) {
|
||||||
|
@ -1584,10 +1585,10 @@ do {
|
||||||
|
|
||||||
out += "}";
|
out += "}";
|
||||||
|
|
||||||
return out;
|
return {out};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateTrivialVertexShader(bool separable_shader) {
|
ShaderDecompiler::ProgramResult GenerateTrivialVertexShader(bool separable_shader) {
|
||||||
std::string out = "";
|
std::string out = "";
|
||||||
if (separable_shader) {
|
if (separable_shader) {
|
||||||
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
||||||
|
@ -1630,11 +1631,11 @@ void main() {
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
return out;
|
return {out};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> GenerateVertexShader(const Pica::Shader::ShaderSetup& setup,
|
std::optional<ShaderDecompiler::ProgramResult> GenerateVertexShader(
|
||||||
const PicaVSConfig& config, bool separable_shader) {
|
const Pica::Shader::ShaderSetup& setup, const PicaVSConfig& config, bool separable_shader) {
|
||||||
std::string out = "";
|
std::string out = "";
|
||||||
if (separable_shader) {
|
if (separable_shader) {
|
||||||
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
out += "#extension GL_ARB_separate_shader_objects : enable\n";
|
||||||
|
@ -1664,7 +1665,7 @@ std::optional<std::string> GenerateVertexShader(const Pica::Shader::ShaderSetup&
|
||||||
if (!program_source_opt)
|
if (!program_source_opt)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::string& program_source = *program_source_opt;
|
std::string& program_source = program_source_opt->code;
|
||||||
|
|
||||||
out += R"(
|
out += R"(
|
||||||
#define uniforms vs_uniforms
|
#define uniforms vs_uniforms
|
||||||
|
@ -1696,7 +1697,7 @@ layout (std140) uniform vs_config {
|
||||||
|
|
||||||
out += program_source;
|
out += program_source;
|
||||||
|
|
||||||
return out;
|
return {{out}};
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetGSCommonSource(const PicaGSConfigCommonRaw& config, bool separable_shader) {
|
static std::string GetGSCommonSource(const PicaGSConfigCommonRaw& config, bool separable_shader) {
|
||||||
|
@ -1784,7 +1785,8 @@ void EmitPrim(Vertex vtx0, Vertex vtx1, Vertex vtx2) {
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string GenerateFixedGeometryShader(const PicaFixedGSConfig& config, bool separable_shader) {
|
ShaderDecompiler::ProgramResult GenerateFixedGeometryShader(const PicaFixedGSConfig& config,
|
||||||
|
bool separable_shader) {
|
||||||
std::string out = "";
|
std::string out = "";
|
||||||
if (separable_shader) {
|
if (separable_shader) {
|
||||||
out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
|
||||||
|
@ -1814,6 +1816,6 @@ void main() {
|
||||||
out += " EmitPrim(prim_buffer[0], prim_buffer[1], prim_buffer[2]);\n";
|
out += " EmitPrim(prim_buffer[0], prim_buffer[1], prim_buffer[2]);\n";
|
||||||
out += "}\n";
|
out += "}\n";
|
||||||
|
|
||||||
return out;
|
return {out};
|
||||||
}
|
}
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
|
namespace ShaderDecompiler {
|
||||||
|
struct ProgramResult;
|
||||||
|
}
|
||||||
|
|
||||||
enum class ProgramType : u32 { VS, GS, FS };
|
enum class ProgramType : u32 { VS, GS, FS };
|
||||||
|
|
||||||
enum Attributes {
|
enum Attributes {
|
||||||
|
@ -202,20 +206,21 @@ struct PicaFixedGSConfig : Common::HashableStruct<PicaGSConfigCommonRaw> {
|
||||||
* @param separable_shader generates shader that can be used for separate shader object
|
* @param separable_shader generates shader that can be used for separate shader object
|
||||||
* @returns String of the shader source code
|
* @returns String of the shader source code
|
||||||
*/
|
*/
|
||||||
std::string GenerateTrivialVertexShader(bool separable_shader);
|
ShaderDecompiler::ProgramResult GenerateTrivialVertexShader(bool separable_shader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the GLSL vertex shader program source code for the given VS program
|
* Generates the GLSL vertex shader program source code for the given VS program
|
||||||
* @returns String of the shader source code; boost::none on failure
|
* @returns String of the shader source code; boost::none on failure
|
||||||
*/
|
*/
|
||||||
std::optional<std::string> GenerateVertexShader(const Pica::Shader::ShaderSetup& setup,
|
std::optional<ShaderDecompiler::ProgramResult> GenerateVertexShader(
|
||||||
const PicaVSConfig& config, bool separable_shader);
|
const Pica::Shader::ShaderSetup& setup, const PicaVSConfig& config, bool separable_shader);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generates the GLSL fixed geometry shader program source code for non-GS PICA pipeline
|
* Generates the GLSL fixed geometry shader program source code for non-GS PICA pipeline
|
||||||
* @returns String of the shader source code
|
* @returns String of the shader source code
|
||||||
*/
|
*/
|
||||||
std::string GenerateFixedGeometryShader(const PicaFixedGSConfig& config, bool separable_shader);
|
ShaderDecompiler::ProgramResult GenerateFixedGeometryShader(const PicaFixedGSConfig& config,
|
||||||
|
bool separable_shader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the GLSL fragment shader program source code for the current Pica state
|
* Generates the GLSL fragment shader program source code for the current Pica state
|
||||||
|
@ -224,7 +229,8 @@ std::string GenerateFixedGeometryShader(const PicaFixedGSConfig& config, bool se
|
||||||
* @param separable_shader generates shader that can be used for separate shader object
|
* @param separable_shader generates shader that can be used for separate shader object
|
||||||
* @returns String of the shader source code
|
* @returns String of the shader source code
|
||||||
*/
|
*/
|
||||||
std::string GenerateFragmentShader(const PicaFSConfig& config, bool separable_shader);
|
ShaderDecompiler::ProgramResult GenerateFragmentShader(const PicaFSConfig& config,
|
||||||
|
bool separable_shader);
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,19 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
static u64 GetUniqueIdentifier(const Pica::Regs& regs, const ProgramCode& code) {
|
static u64 GetUniqueIdentifier(const Pica::Regs& regs, const ProgramCode& code) {
|
||||||
u64 hash = 0;
|
std::size_t hash = 0;
|
||||||
u64 regs_uid = Common::ComputeHash64(regs.reg_array.data(), Pica::Regs::NUM_REGS * sizeof(u32));
|
u64 regs_uid = Common::ComputeHash64(regs.reg_array.data(), Pica::Regs::NUM_REGS * sizeof(u32));
|
||||||
boost::hash_combine(hash, regs_uid);
|
boost::hash_combine(hash, regs_uid);
|
||||||
if (code.size() > 0) {
|
if (code.size() > 0) {
|
||||||
u64 code_uid = Common::ComputeHash64(code.data(), code.size() * sizeof(u32));
|
u64 code_uid = Common::ComputeHash64(code.data(), code.size() * sizeof(u32));
|
||||||
boost::hash_combine(hash, code_uid);
|
boost::hash_combine(hash, code_uid);
|
||||||
}
|
}
|
||||||
return hash;
|
return static_cast<u64>(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static OGLProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump,
|
static OGLProgram GeneratePrecompiledProgram(const ShaderDiskCacheDump& dump,
|
||||||
|
@ -200,7 +201,7 @@ private:
|
||||||
class TrivialVertexShader {
|
class TrivialVertexShader {
|
||||||
public:
|
public:
|
||||||
explicit TrivialVertexShader(bool separable) : program(separable) {
|
explicit TrivialVertexShader(bool separable) : program(separable) {
|
||||||
program.Create(GenerateTrivialVertexShader(separable).c_str(), GL_VERTEX_SHADER);
|
program.Create(GenerateTrivialVertexShader(separable).code.c_str(), GL_VERTEX_SHADER);
|
||||||
}
|
}
|
||||||
GLuint Get() const {
|
GLuint Get() const {
|
||||||
return program.GetHandle();
|
return program.GetHandle();
|
||||||
|
@ -210,7 +211,8 @@ private:
|
||||||
OGLShaderStage program;
|
OGLShaderStage program;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename KeyConfigType, std::string (*CodeGenerator)(const KeyConfigType&, bool),
|
template <typename KeyConfigType,
|
||||||
|
ShaderDecompiler::ProgramResult (*CodeGenerator)(const KeyConfigType&, bool),
|
||||||
GLenum ShaderType>
|
GLenum ShaderType>
|
||||||
class ShaderCache {
|
class ShaderCache {
|
||||||
public:
|
public:
|
||||||
|
@ -222,7 +224,7 @@ public:
|
||||||
std::optional<ShaderDecompiler::ProgramResult> result{};
|
std::optional<ShaderDecompiler::ProgramResult> result{};
|
||||||
if (new_shader) {
|
if (new_shader) {
|
||||||
result = CodeGenerator(config, separable);
|
result = CodeGenerator(config, separable);
|
||||||
cached_shader.Create(result->c_str(), ShaderType);
|
cached_shader.Create(result->code.c_str(), ShaderType);
|
||||||
}
|
}
|
||||||
return {cached_shader.GetHandle(), result};
|
return {cached_shader.GetHandle(), result};
|
||||||
}
|
}
|
||||||
|
@ -244,8 +246,8 @@ private:
|
||||||
// program buffer from the previous shader, which is hashed into the config, resulting several
|
// program buffer from the previous shader, which is hashed into the config, resulting several
|
||||||
// different config values from the same shader program.
|
// different config values from the same shader program.
|
||||||
template <typename KeyConfigType,
|
template <typename KeyConfigType,
|
||||||
std::optional<std::string> (*CodeGenerator)(const Pica::Shader::ShaderSetup&,
|
std::optional<ShaderDecompiler::ProgramResult> (*CodeGenerator)(
|
||||||
const KeyConfigType&, bool),
|
const Pica::Shader::ShaderSetup&, const KeyConfigType&, bool),
|
||||||
GLenum ShaderType>
|
GLenum ShaderType>
|
||||||
class ShaderDoubleCache {
|
class ShaderDoubleCache {
|
||||||
public:
|
public:
|
||||||
|
@ -261,11 +263,11 @@ public:
|
||||||
return {0, {}};
|
return {0, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string& program = *program_opt;
|
std::string& program = program_opt->code;
|
||||||
auto [iter, new_shader] = shader_cache.emplace(program, OGLShaderStage{separable});
|
auto [iter, new_shader] = shader_cache.emplace(program, OGLShaderStage{separable});
|
||||||
OGLShaderStage& cached_shader = iter->second;
|
OGLShaderStage& cached_shader = iter->second;
|
||||||
if (new_shader) {
|
if (new_shader) {
|
||||||
result = program;
|
result->code = program;
|
||||||
cached_shader.Create(program.c_str(), ShaderType);
|
cached_shader.Create(program.c_str(), ShaderType);
|
||||||
}
|
}
|
||||||
shader_map[key] = &cached_shader;
|
shader_map[key] = &cached_shader;
|
||||||
|
@ -336,6 +338,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
bool is_amd;
|
bool is_amd;
|
||||||
|
bool separable;
|
||||||
|
|
||||||
ShaderTuple current;
|
ShaderTuple current;
|
||||||
|
|
||||||
|
@ -345,8 +348,6 @@ public:
|
||||||
FixedGeometryShaders fixed_geometry_shaders;
|
FixedGeometryShaders fixed_geometry_shaders;
|
||||||
|
|
||||||
FragmentShaders fragment_shaders;
|
FragmentShaders fragment_shaders;
|
||||||
|
|
||||||
bool separable;
|
|
||||||
std::unordered_map<ShaderTuple, OGLProgram, ShaderTuple::Hash> program_cache;
|
std::unordered_map<ShaderTuple, OGLProgram, ShaderTuple::Hash> program_cache;
|
||||||
OGLPipeline pipeline;
|
OGLPipeline pipeline;
|
||||||
ShaderDiskCache disk_cache;
|
ShaderDiskCache disk_cache;
|
||||||
|
@ -401,7 +402,7 @@ void ShaderProgramManager::UseFragmentShader(const Pica::Regs& regs) {
|
||||||
u64 unique_identifier = GetUniqueIdentifier(regs, {});
|
u64 unique_identifier = GetUniqueIdentifier(regs, {});
|
||||||
ShaderDiskCacheRaw raw{unique_identifier, ProgramType::FS, regs, {}};
|
ShaderDiskCacheRaw raw{unique_identifier, ProgramType::FS, regs, {}};
|
||||||
disk_cache.SaveRaw(raw);
|
disk_cache.SaveRaw(raw);
|
||||||
disk_cache.SaveDecompiled(unique_identifier, *result);
|
disk_cache.SaveDecompiled(unique_identifier, *result, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,6 +490,12 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
|
|
||||||
const auto dump{dumps.find(unique_identifier)};
|
const auto dump{dumps.find(unique_identifier)};
|
||||||
const auto decomp{decompiled.find(unique_identifier)};
|
const auto decomp{decompiled.find(unique_identifier)};
|
||||||
|
|
||||||
|
// Only load this shader if its sanitize_mul setting matches
|
||||||
|
if (decomp->second.sanitize_mul == VideoCore::g_hw_shader_accurate_mul) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
OGLProgram shader;
|
OGLProgram shader;
|
||||||
|
|
||||||
if (dump != dumps.end() && decomp != decompiled.end()) {
|
if (dump != dumps.end() && decomp != decompiled.end()) {
|
||||||
|
@ -505,12 +512,14 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
if (raw.GetProgramType() == ProgramType::VS) {
|
if (raw.GetProgramType() == ProgramType::VS) {
|
||||||
auto [conf, setup] = BuildVSConfigFromRaw(raw);
|
auto [conf, setup] = BuildVSConfigFromRaw(raw);
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
impl->programmable_vertex_shaders.Inject(conf, decomp->second.code,
|
|
||||||
|
impl->programmable_vertex_shaders.Inject(conf, decomp->second.result.code,
|
||||||
std::move(shader));
|
std::move(shader));
|
||||||
} else if (raw.GetProgramType() == ProgramType::FS) {
|
} else if (raw.GetProgramType() == ProgramType::FS) {
|
||||||
PicaFSConfig conf = PicaFSConfig::BuildFromRegs(raw.GetRawShaderConfig());
|
PicaFSConfig conf = PicaFSConfig::BuildFromRegs(raw.GetRawShaderConfig());
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
impl->fragment_shaders.Inject(conf, decomp->second.code, std::move(shader));
|
impl->fragment_shaders.Inject(conf, decomp->second.result.code,
|
||||||
|
std::move(shader));
|
||||||
} else {
|
} else {
|
||||||
// Unsupported shader type got stored somehow so nuke the cache
|
// Unsupported shader type got stored somehow so nuke the cache
|
||||||
|
|
||||||
|
@ -554,6 +563,7 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
const auto& raw{raws[i]};
|
const auto& raw{raws[i]};
|
||||||
const u64 unique_identifier{raw.GetUniqueIdentifier()};
|
const u64 unique_identifier{raw.GetUniqueIdentifier()};
|
||||||
|
|
||||||
|
bool sanitize_mul = false;
|
||||||
GLuint handle{0};
|
GLuint handle{0};
|
||||||
std::optional<ShaderDecompiler::ProgramResult> result;
|
std::optional<ShaderDecompiler::ProgramResult> result;
|
||||||
// Otherwise decompile and build the shader at boot and save the result to the
|
// Otherwise decompile and build the shader at boot and save the result to the
|
||||||
|
@ -566,6 +576,7 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
auto [h, r] = impl->programmable_vertex_shaders.Get(conf, setup);
|
auto [h, r] = impl->programmable_vertex_shaders.Get(conf, setup);
|
||||||
handle = h;
|
handle = h;
|
||||||
result = r;
|
result = r;
|
||||||
|
sanitize_mul = conf.state.sanitize_mul;
|
||||||
} else if (raw.GetProgramType() == ProgramType::FS) {
|
} else if (raw.GetProgramType() == ProgramType::FS) {
|
||||||
PicaFSConfig conf = PicaFSConfig::BuildFromRegs(raw.GetRawShaderConfig());
|
PicaFSConfig conf = PicaFSConfig::BuildFromRegs(raw.GetRawShaderConfig());
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
@ -587,7 +598,7 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
}
|
}
|
||||||
// If this is a new shader, add it the precompiled cache
|
// If this is a new shader, add it the precompiled cache
|
||||||
if (result) {
|
if (result) {
|
||||||
disk_cache.SaveDecompiled(unique_identifier, *result);
|
disk_cache.SaveDecompiled(unique_identifier, *result, sanitize_mul);
|
||||||
disk_cache.SaveDump(unique_identifier, handle);
|
disk_cache.SaveDump(unique_identifier, handle);
|
||||||
precompiled_cache_altered = true;
|
precompiled_cache_altered = true;
|
||||||
}
|
}
|
||||||
|
@ -607,6 +618,6 @@ void ShaderProgramManager::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||||
if (precompiled_cache_altered) {
|
if (precompiled_cache_altered) {
|
||||||
disk_cache.SaveVirtualPrecompiledFile();
|
disk_cache.SaveVirtualPrecompiledFile();
|
||||||
}
|
}
|
||||||
}
|
} // namespace OpenGL
|
||||||
|
|
||||||
} // namespace OpenGL
|
} // namespace OpenGL
|
||||||
|
|
Reference in New Issue