summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-05-24 17:22:36 -0500
committerGravatar Subv2018-05-24 17:22:36 -0500
commit126270d963dadd36ef30d288a680f0e0fd072a2f (patch)
tree9f5d74910e4114f0f6bdc120a1b5a93066c3a575 /src
parentMerge pull request #464 from bunnei/fix-msvc (diff)
downloadyuzu-126270d963dadd36ef30d288a680f0e0fd072a2f.tar.gz
yuzu-126270d963dadd36ef30d288a680f0e0fd072a2f.tar.xz
yuzu-126270d963dadd36ef30d288a680f0e0fd072a2f.zip
Shader: Implemented compound predicates in fsetp.
You can specify three predicates in an fsetp instruction: P1 = (Value1 Comp Value2) OP P0; P2 = !(Value1 Comp Value2) OP P0;
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp74
1 files changed, 55 insertions, 19 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 1aa24da46..434bbade6 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -597,6 +597,45 @@ private:
597 return variable; 597 return variable;
598 } 598 }
599 599
600 /**
601 * Returns the comparison string to use to compare two values in the 'set' family of
602 * instructions.
603 * @params condition The condition used in the 'set'-family instruction.
604 * @returns String corresponding to the GLSL operator that matches the desired comparison.
605 */
606 std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const {
607 using Tegra::Shader::PredCondition;
608 static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = {
609 {PredCondition::LessThan, "<"},
610 {PredCondition::Equal, "=="},
611 {PredCondition::LessEqual, "<="},
612 };
613
614 auto comparison = PredicateComparisonStrings.find(condition);
615 ASSERT_MSG(comparison != PredicateComparisonStrings.end(),
616 "Unknown predicate comparison operation");
617 return comparison->second;
618 }
619
620 /**
621 * Returns the operator string to use to combine two predicates in the 'setp' family of
622 * instructions.
623 * @params operation The operator used in the 'setp'-family instruction.
624 * @returns String corresponding to the GLSL operator that matches the desired operator.
625 */
626 std::string GetPredicateCombiner(Tegra::Shader::PredOperation operation) const {
627 using Tegra::Shader::PredOperation;
628 static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = {
629 {PredOperation::And, "&&"},
630 {PredOperation::Or, "||"},
631 {PredOperation::Xor, "^"},
632 };
633
634 auto op = PredicateOperationStrings.find(operation);
635 ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation");
636 return op->second;
637 }
638
600 /* 639 /*
601 * Returns whether the instruction at the specified offset is a 'sched' instruction. 640 * Returns whether the instruction at the specified offset is a 'sched' instruction.
602 * Sched instructions always appear before a sequence of 3 instructions. 641 * Sched instructions always appear before a sequence of 3 instructions.
@@ -888,28 +927,25 @@ private:
888 } 927 }
889 928
890 using Tegra::Shader::Pred; 929 using Tegra::Shader::Pred;
891 ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) &&
892 instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex),
893 "Compound predicates are not implemented");
894
895 // We can't use the constant predicate as destination. 930 // We can't use the constant predicate as destination.
896 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 931 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
897 932
898 using Tegra::Shader::PredCondition; 933 std::string second_pred =
899 switch (instr.fsetp.cond) { 934 GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
900 case PredCondition::LessThan: 935
901 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')'); 936 std::string comparator = GetPredicateComparison(instr.fsetp.cond);
902 break; 937 std::string combiner = GetPredicateCombiner(instr.fsetp.op);
903 case PredCondition::Equal: 938
904 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')'); 939 std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')';
905 break; 940 // Set the primary predicate to the result of Predicate OP SecondPredicate
906 case PredCondition::LessEqual: 941 SetPredicate(instr.fsetp.pred3,
907 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") <= (" + op_b + ')'); 942 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
908 break; 943
909 default: 944 if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
910 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})", 945 // Set the secondary predicate to the result of !Predicate OP SecondPredicate, if
911 static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b); 946 // enabled
912 UNREACHABLE(); 947 SetPredicate(instr.fsetp.pred0,
948 "!(" + predicate + ") " + combiner + " (" + second_pred + ')');
913 } 949 }
914 break; 950 break;
915 } 951 }