diff options
| author | 2018-05-24 17:22:36 -0500 | |
|---|---|---|
| committer | 2018-05-24 17:22:36 -0500 | |
| commit | 126270d963dadd36ef30d288a680f0e0fd072a2f (patch) | |
| tree | 9f5d74910e4114f0f6bdc120a1b5a93066c3a575 /src | |
| parent | Merge pull request #464 from bunnei/fix-msvc (diff) | |
| download | yuzu-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.cpp | 74 |
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 | } |