diff options
| author | 2018-05-25 22:28:47 -0400 | |
|---|---|---|
| committer | 2018-05-25 22:28:47 -0400 | |
| commit | aee356bd107cb01f49595ebb177df586c505881b (patch) | |
| tree | 5020da5da32aad0170520ada2a30b6809b2ce3d0 /src | |
| parent | Merge pull request #469 from Subv/channel_rebind (diff) | |
| parent | Shader: Implemented compound predicates in fset. (diff) | |
| download | yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.gz yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.xz yuzu-aee356bd107cb01f49595ebb177df586c505881b.zip | |
Merge pull request #468 from Subv/compound_preds
Shader: Implemented compound predicates in the fset and fsetp instructions
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 112 |
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: { |