summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp112
1 files changed, 66 insertions, 46 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..d24b1ab44 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -597,6 +597,46 @@ 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 {PredCondition::GreaterThan, ">"},
613 };
614
615 auto comparison = PredicateComparisonStrings.find(condition);
616 ASSERT_MSG(comparison != PredicateComparisonStrings.end(),
617 "Unknown predicate comparison operation");
618 return comparison->second;
619 }
620
621 /**
622 * Returns the operator string to use to combine two predicates in the 'setp' family of
623 * instructions.
624 * @params operation The operator used in the 'setp'-family instruction.
625 * @returns String corresponding to the GLSL operator that matches the desired operator.
626 */
627 std::string GetPredicateCombiner(Tegra::Shader::PredOperation operation) const {
628 using Tegra::Shader::PredOperation;
629 static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = {
630 {PredOperation::And, "&&"},
631 {PredOperation::Or, "||"},
632 {PredOperation::Xor, "^^"},
633 };
634
635 auto op = PredicateOperationStrings.find(operation);
636 ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation");
637 return op->second;
638 }
639
600 /* 640 /*
601 * Returns whether the instruction at the specified offset is a 'sched' instruction. 641 * Returns whether the instruction at the specified offset is a 'sched' instruction.
602 * Sched instructions always appear before a sequence of 3 instructions. 642 * Sched instructions always appear before a sequence of 3 instructions.
@@ -888,28 +928,25 @@ private:
888 } 928 }
889 929
890 using Tegra::Shader::Pred; 930 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. 931 // We can't use the constant predicate as destination.
896 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 932 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
897 933
898 using Tegra::Shader::PredCondition; 934 std::string second_pred =
899 switch (instr.fsetp.cond) { 935 GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
900 case PredCondition::LessThan: 936
901 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')'); 937 std::string comparator = GetPredicateComparison(instr.fsetp.cond);
902 break; 938 std::string combiner = GetPredicateCombiner(instr.fsetp.op);
903 case PredCondition::Equal: 939
904 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')'); 940 std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')';
905 break; 941 // Set the primary predicate to the result of Predicate OP SecondPredicate
906 case PredCondition::LessEqual: 942 SetPredicate(instr.fsetp.pred3,
907 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") <= (" + op_b + ')'); 943 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
908 break; 944
909 default: 945 if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
910 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})", 946 // Set the secondary predicate to the result of !Predicate OP SecondPredicate, if
911 static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b); 947 // enabled
912 UNREACHABLE(); 948 SetPredicate(instr.fsetp.pred0,
949 "!(" + predicate + ") " + combiner + " (" + second_pred + ')');
913 } 950 }
914 break; 951 break;
915 } 952 }
@@ -941,35 +978,18 @@ private:
941 op_b = "abs(" + op_b + ')'; 978 op_b = "abs(" + op_b + ')';
942 } 979 }
943 980
944 using Tegra::Shader::Pred;
945 ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex),
946 "Compound predicates are not implemented");
947
948 // The fset instruction sets a register to 1.0 if the condition is true, and to 0 981 // The fset instruction sets a register to 1.0 if the condition is true, and to 0
949 // otherwise. 982 // otherwise.
950 using Tegra::Shader::PredCondition; 983 std::string second_pred =
951 switch (instr.fset.cond) { 984 GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
952 case PredCondition::LessThan: 985
953 regs.SetRegisterToFloat(instr.gpr0, 0, 986 std::string comparator = GetPredicateComparison(instr.fset.cond);
954 "((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1); 987 std::string combiner = GetPredicateCombiner(instr.fset.op);
955 break; 988
956 case PredCondition::Equal: 989 std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " +
957 regs.SetRegisterToFloat(instr.gpr0, 0, 990 combiner + " (" + second_pred + "))";
958 "((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1); 991
959 break; 992 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
960 case PredCondition::LessEqual:
961 regs.SetRegisterToFloat(instr.gpr0, 0,
962 "((" + op_a + ") <= (" + op_b + ")) ? 1.0 : 0", 1, 1);
963 break;
964 case PredCondition::GreaterThan:
965 regs.SetRegisterToFloat(instr.gpr0, 0,
966 "((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1);
967 break;
968 default:
969 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
970 static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b);
971 UNREACHABLE();
972 }
973 break; 993 break;
974 } 994 }
975 default: { 995 default: {