Merge pull request #2609 from FernandoS27/new-scan
Implement a New Shader Scanner, Decompile Flow Stack and implement BRX BRA.CC
This commit is contained in:
commit
bb67091c77
16 changed files with 778 additions and 124 deletions
|
@ -129,9 +129,11 @@ std::size_t CalculateProgramSize(const GLShader::ProgramCode& program) {
|
|||
|
||||
/// Hashes one (or two) program streams
|
||||
u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode& code,
|
||||
const ProgramCode& code_b) {
|
||||
u64 unique_identifier =
|
||||
Common::CityHash64(reinterpret_cast<const char*>(code.data()), CalculateProgramSize(code));
|
||||
const ProgramCode& code_b, std::size_t size_a = 0, std::size_t size_b = 0) {
|
||||
if (size_a == 0) {
|
||||
size_a = CalculateProgramSize(code);
|
||||
}
|
||||
u64 unique_identifier = Common::CityHash64(reinterpret_cast<const char*>(code.data()), size_a);
|
||||
if (program_type != Maxwell::ShaderProgram::VertexA) {
|
||||
return unique_identifier;
|
||||
}
|
||||
|
@ -140,8 +142,11 @@ u64 GetUniqueIdentifier(Maxwell::ShaderProgram program_type, const ProgramCode&
|
|||
std::size_t seed = 0;
|
||||
boost::hash_combine(seed, unique_identifier);
|
||||
|
||||
const u64 identifier_b = Common::CityHash64(reinterpret_cast<const char*>(code_b.data()),
|
||||
CalculateProgramSize(code_b));
|
||||
if (size_b == 0) {
|
||||
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);
|
||||
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,
|
||||
ProgramCode program_code, ProgramCode program_code_b) {
|
||||
GLShader::ShaderSetup setup(program_code);
|
||||
setup.program.size_a = CalculateProgramSize(program_code);
|
||||
setup.program.size_b = 0;
|
||||
if (program_type == Maxwell::ShaderProgram::VertexA) {
|
||||
// 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
|
||||
// stage here.
|
||||
setup.SetProgramB(program_code_b);
|
||||
setup.program.size_b = CalculateProgramSize(program_code_b);
|
||||
}
|
||||
setup.program.unique_identifier =
|
||||
GetUniqueIdentifier(program_type, program_code, program_code_b);
|
||||
setup.program.unique_identifier = GetUniqueIdentifier(
|
||||
program_type, program_code, program_code_b, setup.program.size_a, setup.program.size_b);
|
||||
|
||||
switch (program_type) {
|
||||
case Maxwell::ShaderProgram::VertexA:
|
||||
|
|
|
@ -191,10 +191,12 @@ public:
|
|||
|
||||
// TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
|
||||
// unlikely that shaders will use 20 nested SSYs and PBKs.
|
||||
constexpr u32 FLOW_STACK_SIZE = 20;
|
||||
for (const auto stack : std::array{MetaStackClass::Ssy, MetaStackClass::Pbk}) {
|
||||
code.AddLine("uint {}[{}];", FlowStackName(stack), FLOW_STACK_SIZE);
|
||||
code.AddLine("uint {} = 0u;", FlowStackTopName(stack));
|
||||
if (!ir.IsFlowStackDisabled()) {
|
||||
constexpr u32 FLOW_STACK_SIZE = 20;
|
||||
for (const auto stack : std::array{MetaStackClass::Ssy, MetaStackClass::Pbk}) {
|
||||
code.AddLine("uint {}[{}];", FlowStackName(stack), FLOW_STACK_SIZE);
|
||||
code.AddLine("uint {} = 0u;", FlowStackTopName(stack));
|
||||
}
|
||||
}
|
||||
|
||||
code.AddLine("while (true) {{");
|
||||
|
@ -1555,6 +1557,14 @@ private:
|
|||
return {};
|
||||
}
|
||||
|
||||
std::string BranchIndirect(Operation operation) {
|
||||
const std::string op_a = VisitOperand(operation, 0, Type::Uint);
|
||||
|
||||
code.AddLine("jmp_to = {};", op_a);
|
||||
code.AddLine("break;");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string PushFlowStack(Operation operation) {
|
||||
const auto stack = std::get<MetaStackClass>(operation.GetMeta());
|
||||
const auto target = std::get_if<ImmediateNode>(&*operation[0]);
|
||||
|
@ -1789,6 +1799,7 @@ private:
|
|||
&GLSLDecompiler::ImageStore,
|
||||
|
||||
&GLSLDecompiler::Branch,
|
||||
&GLSLDecompiler::BranchIndirect,
|
||||
&GLSLDecompiler::PushFlowStack,
|
||||
&GLSLDecompiler::PopFlowStack,
|
||||
&GLSLDecompiler::Exit,
|
||||
|
|
|
@ -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 =
|
||||
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
|
||||
|
||||
out += program.first;
|
||||
|
||||
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 =
|
||||
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 =
|
||||
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
|
||||
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 =
|
||||
Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ struct ShaderSetup {
|
|||
ProgramCode code;
|
||||
ProgramCode code_b; // Used for dual vertex shaders
|
||||
u64 unique_identifier;
|
||||
std::size_t size_a;
|
||||
std::size_t size_b;
|
||||
} program;
|
||||
|
||||
/// Used in scenarios where we have a dual vertex shaders
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue