mirror of
https://gitlab.com/suyu-emu/suyu.git
synced 2024-03-15 23:15:44 +00:00
ShaderGen: Implemented predicated instruction execution.
Each predicated instruction will be wrapped in an `if (predicate) { instruction_body; }` in the GLSL, where `predicate` is one of the predicate boolean variables previously set by fsetp.
This commit is contained in:
parent
0a5e01b710
commit
c3a8ea76f1
|
@ -331,7 +331,11 @@ union Instruction {
|
||||||
OpCode opcode;
|
OpCode opcode;
|
||||||
BitField<0, 8, Register> gpr0;
|
BitField<0, 8, Register> gpr0;
|
||||||
BitField<8, 8, Register> gpr8;
|
BitField<8, 8, Register> gpr8;
|
||||||
BitField<16, 4, Pred> pred;
|
union {
|
||||||
|
BitField<16, 4, Pred> full_pred;
|
||||||
|
BitField<16, 3, u64> pred_index;
|
||||||
|
} pred;
|
||||||
|
BitField<19, 1, u64> negate_pred;
|
||||||
BitField<20, 8, Register> gpr20;
|
BitField<20, 8, Register> gpr20;
|
||||||
BitField<20, 7, SubOp> sub_op;
|
BitField<20, 7, SubOp> sub_op;
|
||||||
BitField<28, 8, Register> gpr28;
|
BitField<28, 8, Register> gpr28;
|
||||||
|
|
|
@ -293,6 +293,25 @@ private:
|
||||||
declr_predicates.insert(std::move(variable));
|
declr_predicates.insert(std::move(variable));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the condition to use in the 'if' for a predicated instruction.
|
||||||
|
* @param instr Instruction to generate the if condition for.
|
||||||
|
* @returns string containing the predicate condition.
|
||||||
|
*/
|
||||||
|
std::string GetPredicateCondition(Instruction instr) const {
|
||||||
|
using Tegra::Shader::Pred;
|
||||||
|
ASSERT(instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex));
|
||||||
|
|
||||||
|
std::string variable =
|
||||||
|
'p' + std::to_string(static_cast<u64>(instr.pred.pred_index.Value()));
|
||||||
|
|
||||||
|
if (instr.negate_pred) {
|
||||||
|
return "!(" + variable + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
return variable;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns whether the instruction at the specified offset is a 'sched' instruction.
|
* Returns whether the instruction at the specified offset is a 'sched' instruction.
|
||||||
* Sched instructions always appear before a sequence of 3 instructions.
|
* Sched instructions always appear before a sequence of 3 instructions.
|
||||||
|
@ -320,6 +339,16 @@ private:
|
||||||
|
|
||||||
shader.AddLine("// " + std::to_string(offset) + ": " + OpCode::GetInfo(instr.opcode).name);
|
shader.AddLine("// " + std::to_string(offset) + ": " + OpCode::GetInfo(instr.opcode).name);
|
||||||
|
|
||||||
|
using Tegra::Shader::Pred;
|
||||||
|
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
|
||||||
|
"NeverExecute predicate not implemented");
|
||||||
|
|
||||||
|
if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
|
||||||
|
shader.AddLine("if (" + GetPredicateCondition(instr) + ')');
|
||||||
|
shader.AddLine('{');
|
||||||
|
++shader.scope;
|
||||||
|
}
|
||||||
|
|
||||||
switch (OpCode::GetInfo(instr.opcode).type) {
|
switch (OpCode::GetInfo(instr.opcode).type) {
|
||||||
case OpCode::Type::Arithmetic: {
|
case OpCode::Type::Arithmetic: {
|
||||||
std::string dest = GetRegister(instr.gpr0);
|
std::string dest = GetRegister(instr.gpr0);
|
||||||
|
@ -559,6 +588,12 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the predicate condition scope.
|
||||||
|
if (instr.pred != Pred::UnusedIndex) {
|
||||||
|
--shader.scope;
|
||||||
|
shader.AddLine('}');
|
||||||
|
}
|
||||||
|
|
||||||
return offset + 1;
|
return offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue