diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/shader/decode/predicate_set_predicate.cpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/video_core/shader/decode/predicate_set_predicate.cpp b/src/video_core/shader/decode/predicate_set_predicate.cpp index 1ad853fda..24352170d 100644 --- a/src/video_core/shader/decode/predicate_set_predicate.cpp +++ b/src/video_core/shader/decode/predicate_set_predicate.cpp @@ -11,12 +11,32 @@ namespace VideoCommon::Shader { using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; +using Tegra::Shader::Pred; u32 ShaderIR::DecodePredicateSetPredicate(BasicBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); - UNIMPLEMENTED(); + const Node op_a = GetPredicate(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); + const Node op_b = GetPredicate(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); + + // We can't use the constant predicate as destination. + ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); + + const Node second_pred = GetPredicate(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); + + const OperationCode combiner = GetPredicateCombiner(instr.psetp.op); + const Node predicate = Operation(combiner, op_a, op_b); + + // Set the primary predicate to the result of Predicate OP SecondPredicate + SetPredicate(bb, instr.psetp.pred3, Operation(combiner, predicate, second_pred)); + + if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { + // Set the secondary predicate to the result of !Predicate OP SecondPredicate, if enabled + SetPredicate( + bb, instr.psetp.pred0, + Operation(combiner, Operation(OperationCode::LogicalNegate, predicate), second_pred)); + } return pc; } |