forked from suyu/suyu
Merge pull request #1744 from degasus/shader_cache
shader_cache: Only lock covered instructions.
This commit is contained in:
commit
69b3f98d3a
4 changed files with 24 additions and 8 deletions
|
@ -84,6 +84,7 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
entries = program_result.second;
|
entries = program_result.second;
|
||||||
|
shader_length = entries.shader_length;
|
||||||
|
|
||||||
if (program_type != Maxwell::ShaderProgram::Geometry) {
|
if (program_type != Maxwell::ShaderProgram::Geometry) {
|
||||||
OGLShader shader;
|
OGLShader shader;
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t GetSizeInBytes() const override {
|
std::size_t GetSizeInBytes() const override {
|
||||||
return GLShader::MAX_PROGRAM_CODE_LENGTH * sizeof(u64);
|
return shader_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do not have to flush this cache as things in it are never modified by us.
|
// We do not have to flush this cache as things in it are never modified by us.
|
||||||
|
@ -82,6 +82,7 @@ private:
|
||||||
u32 max_vertices, const std::string& debug_name);
|
u32 max_vertices, const std::string& debug_name);
|
||||||
|
|
||||||
VAddr addr;
|
VAddr addr;
|
||||||
|
std::size_t shader_length;
|
||||||
Maxwell::ShaderProgram program_type;
|
Maxwell::ShaderProgram program_type;
|
||||||
GLShader::ShaderSetup setup;
|
GLShader::ShaderSetup setup;
|
||||||
GLShader::ShaderEntries entries;
|
GLShader::ShaderEntries entries;
|
||||||
|
|
|
@ -84,7 +84,8 @@ struct Subroutine {
|
||||||
class ControlFlowAnalyzer {
|
class ControlFlowAnalyzer {
|
||||||
public:
|
public:
|
||||||
ControlFlowAnalyzer(const ProgramCode& program_code, u32 main_offset, const std::string& suffix)
|
ControlFlowAnalyzer(const ProgramCode& program_code, u32 main_offset, const std::string& suffix)
|
||||||
: program_code(program_code) {
|
: program_code(program_code), shader_coverage_begin(main_offset),
|
||||||
|
shader_coverage_end(main_offset + 1) {
|
||||||
|
|
||||||
// Recursively finds all subroutines.
|
// Recursively finds all subroutines.
|
||||||
const Subroutine& program_main = AddSubroutine(main_offset, PROGRAM_END, suffix);
|
const Subroutine& program_main = AddSubroutine(main_offset, PROGRAM_END, suffix);
|
||||||
|
@ -96,10 +97,16 @@ public:
|
||||||
return std::move(subroutines);
|
return std::move(subroutines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t GetShaderLength() const {
|
||||||
|
return shader_coverage_end * sizeof(u64);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ProgramCode& program_code;
|
const ProgramCode& program_code;
|
||||||
std::set<Subroutine> subroutines;
|
std::set<Subroutine> subroutines;
|
||||||
std::map<std::pair<u32, u32>, ExitMethod> exit_method_map;
|
std::map<std::pair<u32, u32>, ExitMethod> exit_method_map;
|
||||||
|
u32 shader_coverage_begin;
|
||||||
|
u32 shader_coverage_end;
|
||||||
|
|
||||||
/// Adds and analyzes a new subroutine if it is not added yet.
|
/// Adds and analyzes a new subroutine if it is not added yet.
|
||||||
const Subroutine& AddSubroutine(u32 begin, u32 end, const std::string& suffix) {
|
const Subroutine& AddSubroutine(u32 begin, u32 end, const std::string& suffix) {
|
||||||
|
@ -141,6 +148,9 @@ private:
|
||||||
return exit_method;
|
return exit_method;
|
||||||
|
|
||||||
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
|
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
|
||||||
|
shader_coverage_begin = std::min(shader_coverage_begin, offset);
|
||||||
|
shader_coverage_end = std::max(shader_coverage_end, offset + 1);
|
||||||
|
|
||||||
const Instruction instr = {program_code[offset]};
|
const Instruction instr = {program_code[offset]};
|
||||||
if (const auto opcode = OpCode::Decode(instr)) {
|
if (const auto opcode = OpCode::Decode(instr)) {
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
|
@ -939,9 +949,10 @@ private:
|
||||||
class GLSLGenerator {
|
class GLSLGenerator {
|
||||||
public:
|
public:
|
||||||
GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
|
GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
|
||||||
u32 main_offset, Maxwell3D::Regs::ShaderStage stage, const std::string& suffix)
|
u32 main_offset, Maxwell3D::Regs::ShaderStage stage, const std::string& suffix,
|
||||||
|
std::size_t shader_length)
|
||||||
: subroutines(subroutines), program_code(program_code), main_offset(main_offset),
|
: subroutines(subroutines), program_code(program_code), main_offset(main_offset),
|
||||||
stage(stage), suffix(suffix) {
|
stage(stage), suffix(suffix), shader_length(shader_length) {
|
||||||
std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
|
std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
|
||||||
local_memory_size = header.GetLocalMemorySize();
|
local_memory_size = header.GetLocalMemorySize();
|
||||||
regs.SetLocalMemory(local_memory_size);
|
regs.SetLocalMemory(local_memory_size);
|
||||||
|
@ -954,7 +965,7 @@ public:
|
||||||
|
|
||||||
/// Returns entries in the shader that are useful for external functions
|
/// Returns entries in the shader that are useful for external functions
|
||||||
ShaderEntries GetEntries() const {
|
ShaderEntries GetEntries() const {
|
||||||
return {regs.GetConstBuffersDeclarations(), regs.GetSamplers()};
|
return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), shader_length};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -3748,6 +3759,7 @@ private:
|
||||||
Maxwell3D::Regs::ShaderStage stage;
|
Maxwell3D::Regs::ShaderStage stage;
|
||||||
const std::string& suffix;
|
const std::string& suffix;
|
||||||
u64 local_memory_size;
|
u64 local_memory_size;
|
||||||
|
std::size_t shader_length;
|
||||||
|
|
||||||
ShaderWriter shader;
|
ShaderWriter shader;
|
||||||
ShaderWriter declarations;
|
ShaderWriter declarations;
|
||||||
|
@ -3766,9 +3778,10 @@ std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u
|
||||||
Maxwell3D::Regs::ShaderStage stage,
|
Maxwell3D::Regs::ShaderStage stage,
|
||||||
const std::string& suffix) {
|
const std::string& suffix) {
|
||||||
try {
|
try {
|
||||||
const auto subroutines =
|
ControlFlowAnalyzer analyzer(program_code, main_offset, suffix);
|
||||||
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
|
const auto subroutines = analyzer.GetSubroutines();
|
||||||
GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix);
|
GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix,
|
||||||
|
analyzer.GetShaderLength());
|
||||||
return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
|
return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
|
||||||
} catch (const DecompileFail& exception) {
|
} catch (const DecompileFail& exception) {
|
||||||
LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
||||||
|
|
|
@ -163,6 +163,7 @@ private:
|
||||||
struct ShaderEntries {
|
struct ShaderEntries {
|
||||||
std::vector<ConstBufferEntry> const_buffer_entries;
|
std::vector<ConstBufferEntry> const_buffer_entries;
|
||||||
std::vector<SamplerEntry> texture_samplers;
|
std::vector<SamplerEntry> texture_samplers;
|
||||||
|
std::size_t shader_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ProgramResult = std::pair<std::string, ShaderEntries>;
|
using ProgramResult = std::pair<std::string, ShaderEntries>;
|
||||||
|
|
Loading…
Reference in a new issue