1
1
Fork 0
forked from suyu/suyu

shader_ir: propagate shader size to the IR

This commit is contained in:
Fernando Sahmkow 2019-06-25 07:57:32 -04:00 committed by FernandoS27
parent 8a6fc529a9
commit 459fce3a8f
6 changed files with 28 additions and 17 deletions

View file

@ -129,9 +129,11 @@ std::size_t CalculateProgramSize(const GLShader::ProgramCode& program) {
/// Hashes one (or two) program streams /// Hashes one (or two) program streams
u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode& code, u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode& code,
const ProgramCode& code_b) { const ProgramCode& code_b, std::size_t size_a = 0, std::size_t size_b = 0) {
u64 unique_identifier = if (size_a == 0) {
Common::CityHash64(reinterpret_cast<const char*>(code.data()), CalculateProgramSize(code)); size_a = CalculateProgramSize(code);
}
u64 unique_identifier = Common::CityHash64(reinterpret_cast<const char*>(code.data()), size_a);
if (program_type != Maxwell::ShaderProgram::VertexA) { if (program_type != Maxwell::ShaderProgram::VertexA) {
return unique_identifier; return unique_identifier;
} }
@ -140,8 +142,11 @@ u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode&
std::size_t seed = 0; std::size_t seed = 0;
boost::hash_combine(seed, unique_identifier); boost::hash_combine(seed, unique_identifier);
const u64 identifier_b = Common::CityHash64(reinterpret_cast<const char*>(code_b.data()), if (size_b == 0) {
CalculateProgramSize(code_b)); size_b = CalculateProgramSize(code_b);
}
const u64 identifier_b =
Common::CityHash64(reinterpret_cast<const char*>(code_b.data()), size_b);
boost::hash_combine(seed, identifier_b); boost::hash_combine(seed, identifier_b);
return static_cast<u64>(seed); return static_cast<u64>(seed);
} }
@ -150,14 +155,17 @@ u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode&
GLShader::ProgramResult CreateProgram(const Device& device, Maxwell::ShaderProgram program_type, GLShader::ProgramResult CreateProgram(const Device& device, Maxwell::ShaderProgram program_type,
ProgramCode program_code, ProgramCode program_code_b) { ProgramCode program_code, ProgramCode program_code_b) {
GLShader::ShaderSetup setup(program_code); GLShader::ShaderSetup setup(program_code);
setup.program.size_a = CalculateProgramSize(program_code);
setup.program.size_b = 0;
if (program_type == Maxwell::ShaderProgram::VertexA) { if (program_type == Maxwell::ShaderProgram::VertexA) {
// VertexB is always enabled, so when VertexA is enabled, we have two vertex shaders. // VertexB is always enabled, so when VertexA is enabled, we have two vertex shaders.
// Conventional HW does not support this, so we combine VertexA and VertexB into one // Conventional HW does not support this, so we combine VertexA and VertexB into one
// stage here. // stage here.
setup.SetProgramB(program_code_b); setup.SetProgramB(program_code_b);
setup.program.size_b = CalculateProgramSize(program_code_b);
} }
setup.program.unique_identifier = setup.program.unique_identifier = GetUniqueIdentifier(
GetUniqueIdentifier(program_type, program_code, program_code_b); program_type, program_code, program_code_b, setup.program.size_a, setup.program.size_b);
switch (program_type) { switch (program_type) {
case Maxwell::ShaderProgram::VertexA: case Maxwell::ShaderProgram::VertexA:

View file

@ -29,14 +29,14 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
}; };
)"; )";
const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET, setup.program.size_a);
ProgramResult program = ProgramResult program =
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex"); Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
out += program.first; out += program.first;
if (setup.IsDualProgram()) { if (setup.IsDualProgram()) {
const ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET); const ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET, setup.program.size_b);
ProgramResult program_b = ProgramResult program_b =
Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b"); Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
@ -80,7 +80,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
}; };
)"; )";
const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET, setup.program.size_a);
ProgramResult program = ProgramResult program =
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry"); Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
out += program.first; out += program.first;
@ -115,7 +115,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
}; };
)"; )";
const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET, setup.program.size_a);
ProgramResult program = ProgramResult program =
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment"); Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");

View file

@ -27,6 +27,8 @@ struct ShaderSetup {
ProgramCode code; ProgramCode code;
ProgramCode code_b; // Used for dual vertex shaders ProgramCode code_b; // Used for dual vertex shaders
u64 unique_identifier; u64 unique_identifier;
std::size_t size_a;
std::size_t size_b;
} program; } program;
/// Used in scenarios where we have a dual vertex shaders /// Used in scenarios where we have a dual vertex shaders

View file

@ -39,7 +39,7 @@ void ShaderIR::Decode() {
std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
ShaderCharacteristics shader_info{}; ShaderCharacteristics shader_info{};
bool can_proceed = ScanFlow(program_code, MAX_PROGRAM_LENGTH, main_offset, shader_info); bool can_proceed = ScanFlow(program_code, program_code.size(), main_offset, shader_info);
if (can_proceed) { if (can_proceed) {
coverage_begin = shader_info.start; coverage_begin = shader_info.start;
coverage_end = shader_info.end; coverage_end = shader_info.end;
@ -52,12 +52,12 @@ void ShaderIR::Decode() {
} }
return; return;
} }
LOG_CRITICAL(HW_GPU, "Flow Analysis failed, falling back to brute force compiling"); LOG_WARNING(HW_GPU, "Flow Analysis failed, falling back to brute force compiling");
// Now we need to deal with an undecompilable shader. We need to brute force // Now we need to deal with an undecompilable shader. We need to brute force
// a shader that captures every position. // a shader that captures every position.
coverage_begin = shader_info.start; coverage_begin = shader_info.start;
const u32 shader_end = static_cast<u32>(MAX_PROGRAM_LENGTH); const u32 shader_end = static_cast<u32>(program_size / sizeof(u64));
coverage_end = shader_end; coverage_end = shader_end;
for (u32 label = main_offset; label < shader_end; label++) { for (u32 label = main_offset; label < shader_end; label++) {
basic_blocks.insert({label, DecodeRange(label, label + 1)}); basic_blocks.insert({label, DecodeRange(label, label + 1)});

View file

@ -22,8 +22,8 @@ using Tegra::Shader::PredCondition;
using Tegra::Shader::PredOperation; using Tegra::Shader::PredOperation;
using Tegra::Shader::Register; using Tegra::Shader::Register;
ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset) ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset, const std::size_t size)
: program_code{program_code}, main_offset{main_offset} { : program_code{program_code}, main_offset{main_offset}, program_size{size} {
Decode(); Decode();
} }

View file

@ -65,7 +65,7 @@ struct GlobalMemoryUsage {
class ShaderIR final { class ShaderIR final {
public: public:
explicit ShaderIR(const ProgramCode& program_code, u32 main_offset); explicit ShaderIR(const ProgramCode& program_code, u32 main_offset, std::size_t size);
~ShaderIR(); ~ShaderIR();
const std::map<u32, NodeBlock>& GetBasicBlocks() const { const std::map<u32, NodeBlock>& GetBasicBlocks() const {
@ -316,6 +316,7 @@ private:
const ProgramCode& program_code; const ProgramCode& program_code;
const u32 main_offset; const u32 main_offset;
const std::size_t program_size;
u32 coverage_begin{}; u32 coverage_begin{};
u32 coverage_end{}; u32 coverage_end{};