gl_shader_decompiler: Use FlowCondition field in EXIT instruction.

This commit is contained in:
bunnei 2018-07-12 20:00:37 -04:00
parent 274d1fb0fc
commit 4757ffdcce
2 changed files with 34 additions and 8 deletions

View File

@ -201,6 +201,11 @@ enum class IMinMaxExchange : u64 {
XHi = 3, XHi = 3,
}; };
enum class FlowCondition : u64 {
Always = 0xF,
Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
};
union Instruction { union Instruction {
Instruction& operator=(const Instruction& instr) { Instruction& operator=(const Instruction& instr) {
value = instr.value; value = instr.value;
@ -315,6 +320,10 @@ union Instruction {
} }
} bfe; } bfe;
union {
BitField<0, 5, FlowCondition> cond;
} flow;
union { union {
BitField<48, 1, u64> negate_b; BitField<48, 1, u64> negate_b;
BitField<49, 1, u64> negate_c; BitField<49, 1, u64> negate_c;

View File

@ -1639,16 +1639,32 @@ private:
shader.AddLine("color.a = " + regs.GetRegisterAsFloat(3) + ';'); shader.AddLine("color.a = " + regs.GetRegisterAsFloat(3) + ';');
} }
shader.AddLine("return true;"); switch (instr.flow.cond) {
if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { case Tegra::Shader::FlowCondition::Always:
// If this is an unconditional exit then just end processing here, otherwise shader.AddLine("return true;");
// we have to account for the possibility of the condition not being met, so if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
// continue processing the next instruction. // If this is an unconditional exit then just end processing here,
offset = PROGRAM_END - 1; // otherwise we have to account for the possibility of the condition
// not being met, so continue processing the next instruction.
offset = PROGRAM_END - 1;
}
break;
case Tegra::Shader::FlowCondition::Fcsm_Tr:
// TODO(bunnei): What is this used for? If we assume this conditon is not
// satisifed, dual vertex shaders in Farming Simulator make more sense
LOG_CRITICAL(HW_GPU, "Skipping unknown FlowCondition::Fcsm_Tr");
break;
default:
LOG_CRITICAL(HW_GPU, "Unhandled flow condition: {}",
static_cast<u32>(instr.flow.cond.Value()));
UNREACHABLE();
} }
break; break;
} }
case OpCode::Id::KIL: { case OpCode::Id::KIL: {
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
shader.AddLine("discard;"); shader.AddLine("discard;");
break; break;
} }
@ -1669,8 +1685,9 @@ private:
// can ignore this when generating GLSL code. // can ignore this when generating GLSL code.
break; break;
} }
case OpCode::Id::DEPBAR: case OpCode::Id::SYNC:
case OpCode::Id::SYNC: { ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
case OpCode::Id::DEPBAR: {
// TODO(Subv): Find out if we actually have to care about these instructions or if // TODO(Subv): Find out if we actually have to care about these instructions or if
// the GLSL compiler takes care of that for us. // the GLSL compiler takes care of that for us.
LOG_WARNING(HW_GPU, "DEPBAR/SYNC instruction is stubbed"); LOG_WARNING(HW_GPU, "DEPBAR/SYNC instruction is stubbed");