gl_shader_decompiler: Implement PBK and BRK
This commit is contained in:
parent
78f2a6a9e1
commit
41fb25349a
|
@ -1095,11 +1095,13 @@ public:
|
||||||
KIL,
|
KIL,
|
||||||
SSY,
|
SSY,
|
||||||
SYNC,
|
SYNC,
|
||||||
|
BRK,
|
||||||
DEPBAR,
|
DEPBAR,
|
||||||
BFE_C,
|
BFE_C,
|
||||||
BFE_R,
|
BFE_R,
|
||||||
BFE_IMM,
|
BFE_IMM,
|
||||||
BRA,
|
BRA,
|
||||||
|
PBK,
|
||||||
LD_A,
|
LD_A,
|
||||||
LD_C,
|
LD_C,
|
||||||
ST_A,
|
ST_A,
|
||||||
|
@ -1239,7 +1241,7 @@ public:
|
||||||
/// conditionally executed).
|
/// conditionally executed).
|
||||||
static bool IsPredicatedInstruction(Id opcode) {
|
static bool IsPredicatedInstruction(Id opcode) {
|
||||||
// TODO(Subv): Add the rest of unpredicated instructions.
|
// TODO(Subv): Add the rest of unpredicated instructions.
|
||||||
return opcode != Id::SSY;
|
return opcode != Id::SSY && opcode != Id::PBK;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Matcher {
|
class Matcher {
|
||||||
|
@ -1335,9 +1337,11 @@ private:
|
||||||
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
|
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
|
||||||
INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
|
INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
|
||||||
INST("111000101001----", Id::SSY, Type::Flow, "SSY"),
|
INST("111000101001----", Id::SSY, Type::Flow, "SSY"),
|
||||||
|
INST("111000101010----", Id::PBK, Type::Flow, "PBK"),
|
||||||
INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
|
INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
|
||||||
|
INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"),
|
||||||
|
INST("111000110100---", Id::BRK, Type::Flow, "BRK"),
|
||||||
INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"),
|
INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"),
|
||||||
INST("1111000011111---", Id::SYNC, Type::Synch, "SYNC"),
|
|
||||||
INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
|
INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
|
||||||
INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
|
INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
|
||||||
INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
|
INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
|
||||||
|
@ -1463,4 +1467,4 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tegra::Shader
|
} // namespace Tegra::Shader
|
|
@ -165,10 +165,11 @@ private:
|
||||||
const ExitMethod jmp = Scan(target, end, labels);
|
const ExitMethod jmp = Scan(target, end, labels);
|
||||||
return exit_method = ParallelExit(no_jmp, jmp);
|
return exit_method = ParallelExit(no_jmp, jmp);
|
||||||
}
|
}
|
||||||
case OpCode::Id::SSY: {
|
case OpCode::Id::SSY:
|
||||||
// The SSY instruction uses a similar encoding as the BRA instruction.
|
case OpCode::Id::PBK: {
|
||||||
|
// The SSY and PBK use a similar encoding as the BRA instruction.
|
||||||
ASSERT_MSG(instr.bra.constant_buffer == 0,
|
ASSERT_MSG(instr.bra.constant_buffer == 0,
|
||||||
"Constant buffer SSY is not supported");
|
"Constant buffer branching is not supported");
|
||||||
const u32 target = offset + instr.bra.GetBranchTarget();
|
const u32 target = offset + instr.bra.GetBranchTarget();
|
||||||
labels.insert(target);
|
labels.insert(target);
|
||||||
// Continue scanning for an exit method.
|
// Continue scanning for an exit method.
|
||||||
|
@ -1153,27 +1154,27 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emits code to push the input target address to the SSY address stack, incrementing the stack
|
* Emits code to push the input target address to the flow address stack, incrementing the stack
|
||||||
* top.
|
* top.
|
||||||
*/
|
*/
|
||||||
void EmitPushToSSYStack(u32 target) {
|
void EmitPushToFlowStack(u32 target) {
|
||||||
shader.AddLine('{');
|
shader.AddLine('{');
|
||||||
++shader.scope;
|
++shader.scope;
|
||||||
shader.AddLine("ssy_stack[ssy_stack_top] = " + std::to_string(target) + "u;");
|
shader.AddLine("flow_stack[flow_stack_top] = " + std::to_string(target) + "u;");
|
||||||
shader.AddLine("ssy_stack_top++;");
|
shader.AddLine("flow_stack_top++;");
|
||||||
--shader.scope;
|
--shader.scope;
|
||||||
shader.AddLine('}');
|
shader.AddLine('}');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emits code to pop an address from the SSY address stack, setting the jump address to the
|
* Emits code to pop an address from the flow address stack, setting the jump address to the
|
||||||
* popped address and decrementing the stack top.
|
* popped address and decrementing the stack top.
|
||||||
*/
|
*/
|
||||||
void EmitPopFromSSYStack() {
|
void EmitPopFromFlowStack() {
|
||||||
shader.AddLine('{');
|
shader.AddLine('{');
|
||||||
++shader.scope;
|
++shader.scope;
|
||||||
shader.AddLine("ssy_stack_top--;");
|
shader.AddLine("flow_stack_top--;");
|
||||||
shader.AddLine("jmp_to = ssy_stack[ssy_stack_top];");
|
shader.AddLine("jmp_to = flow_stack[flow_stack_top];");
|
||||||
shader.AddLine("break;");
|
shader.AddLine("break;");
|
||||||
--shader.scope;
|
--shader.scope;
|
||||||
shader.AddLine('}');
|
shader.AddLine('}');
|
||||||
|
@ -2933,16 +2934,32 @@ private:
|
||||||
// The SSY opcode tells the GPU where to re-converge divergent execution paths, it
|
// The SSY opcode tells the GPU where to re-converge divergent execution paths, it
|
||||||
// sets the target of the jump that the SYNC instruction will make. The SSY opcode
|
// sets the target of the jump that the SYNC instruction will make. The SSY opcode
|
||||||
// has a similar structure to the BRA opcode.
|
// has a similar structure to the BRA opcode.
|
||||||
ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported");
|
ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer flow is not supported");
|
||||||
|
|
||||||
const u32 target = offset + instr.bra.GetBranchTarget();
|
const u32 target = offset + instr.bra.GetBranchTarget();
|
||||||
EmitPushToSSYStack(target);
|
EmitPushToFlowStack(target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpCode::Id::PBK: {
|
||||||
|
// PBK pushes to a stack the address where BRK will jump to. This shares stack with
|
||||||
|
// SSY but using SYNC on a PBK address will kill the shader execution. We don't
|
||||||
|
// emulate this because it's very unlikely a driver will emit such invalid shader.
|
||||||
|
ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer PBK is not supported");
|
||||||
|
|
||||||
|
const u32 target = offset + instr.bra.GetBranchTarget();
|
||||||
|
EmitPushToFlowStack(target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::SYNC: {
|
case OpCode::Id::SYNC: {
|
||||||
// The SYNC opcode jumps to the address previously set by the SSY opcode
|
// The SYNC opcode jumps to the address previously set by the SSY opcode
|
||||||
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
|
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
|
||||||
EmitPopFromSSYStack();
|
EmitPopFromFlowStack();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpCode::Id::BRK: {
|
||||||
|
// The BRK opcode jumps to the address previously set by the PBK opcode
|
||||||
|
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
|
||||||
|
EmitPopFromFlowStack();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::DEPBAR: {
|
case OpCode::Id::DEPBAR: {
|
||||||
|
@ -3096,11 +3113,11 @@ private:
|
||||||
labels.insert(subroutine.begin);
|
labels.insert(subroutine.begin);
|
||||||
shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
|
shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
|
||||||
|
|
||||||
// TODO(Subv): Figure out the actual depth of the SSY stack, for now it seems
|
// TODO(Subv): Figure out the actual depth of the flow stack, for now it seems
|
||||||
// unlikely that shaders will use 20 nested SSYs.
|
// unlikely that shaders will use 20 nested SSYs and PBKs.
|
||||||
constexpr u32 SSY_STACK_SIZE = 20;
|
constexpr u32 FLOW_STACK_SIZE = 20;
|
||||||
shader.AddLine("uint ssy_stack[" + std::to_string(SSY_STACK_SIZE) + "];");
|
shader.AddLine("uint flow_stack[" + std::to_string(FLOW_STACK_SIZE) + "];");
|
||||||
shader.AddLine("uint ssy_stack_top = 0u;");
|
shader.AddLine("uint flow_stack_top = 0u;");
|
||||||
|
|
||||||
shader.AddLine("while (true) {");
|
shader.AddLine("while (true) {");
|
||||||
++shader.scope;
|
++shader.scope;
|
||||||
|
|
Reference in New Issue