diff options
author | bunnei <bunneidev@gmail.com> | 2018-05-26 04:28:47 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-26 04:28:47 +0200 |
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 yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.gz yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.bz2 yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.lz yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.xz yuzu-aee356bd107cb01f49595ebb177df586c505881b.tar.zst yuzu-aee356bd107cb01f49595ebb177df586c505881b.zip |
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: return variable; } + /** + * Returns the comparison string to use to compare two values in the 'set' family of + * instructions. + * @params condition The condition used in the 'set'-family instruction. + * @returns String corresponding to the GLSL operator that matches the desired comparison. + */ + std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const { + using Tegra::Shader::PredCondition; + static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = { + {PredCondition::LessThan, "<"}, + {PredCondition::Equal, "=="}, + {PredCondition::LessEqual, "<="}, + {PredCondition::GreaterThan, ">"}, + }; + + auto comparison = PredicateComparisonStrings.find(condition); + ASSERT_MSG(comparison != PredicateComparisonStrings.end(), + "Unknown predicate comparison operation"); + return comparison->second; + } + + /** + * Returns the operator string to use to combine two predicates in the 'setp' family of + * instructions. + * @params operation The operator used in the 'setp'-family instruction. + * @returns String corresponding to the GLSL operator that matches the desired operator. + */ + std::string GetPredicateCombiner(Tegra::Shader::PredOperation operation) const { + using Tegra::Shader::PredOperation; + static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = { + {PredOperation::And, "&&"}, + {PredOperation::Or, "||"}, + {PredOperation::Xor, "^^"}, + }; + + auto op = PredicateOperationStrings.find(operation); + ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation"); + return op->second; + } + /* * Returns whether the instruction at the specified offset is a 'sched' instruction. * Sched instructions always appear before a sequence of 3 instructions. @@ -888,28 +928,25 @@ private: } using Tegra::Shader::Pred; - ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) && - instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex), - "Compound predicates are not implemented"); - // We can't use the constant predicate as destination. ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); - using Tegra::Shader::PredCondition; - switch (instr.fsetp.cond) { - case PredCondition::LessThan: - SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')'); - break; - case PredCondition::Equal: - SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')'); - break; - case PredCondition::LessEqual: - SetPredicate(instr.fsetp.pred3, '(' + op_a + ") <= (" + op_b + ')'); - break; - default: - NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})", - static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b); - UNREACHABLE(); + std::string second_pred = + GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0); + + std::string comparator = GetPredicateComparison(instr.fsetp.cond); + std::string combiner = GetPredicateCombiner(instr.fsetp.op); + + std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')'; + // Set the primary predicate to the result of Predicate OP SecondPredicate + SetPredicate(instr.fsetp.pred3, + '(' + predicate + ") " + combiner + " (" + second_pred + ')'); + + if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { + // Set the secondary predicate to the result of !Predicate OP SecondPredicate, if + // enabled + SetPredicate(instr.fsetp.pred0, + "!(" + predicate + ") " + combiner + " (" + second_pred + ')'); } break; } @@ -941,35 +978,18 @@ private: op_b = "abs(" + op_b + ')'; } - using Tegra::Shader::Pred; - ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex), - "Compound predicates are not implemented"); - // The fset instruction sets a register to 1.0 if the condition is true, and to 0 // otherwise. - using Tegra::Shader::PredCondition; - switch (instr.fset.cond) { - case PredCondition::LessThan: - regs.SetRegisterToFloat(instr.gpr0, 0, - "((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1); - break; - case PredCondition::Equal: - regs.SetRegisterToFloat(instr.gpr0, 0, - "((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1); - break; - case PredCondition::LessEqual: - regs.SetRegisterToFloat(instr.gpr0, 0, - "((" + op_a + ") <= (" + op_b + ")) ? 1.0 : 0", 1, 1); - break; - case PredCondition::GreaterThan: - regs.SetRegisterToFloat(instr.gpr0, 0, - "((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1); - break; - default: - NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})", - static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b); - UNREACHABLE(); - } + std::string second_pred = + GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0); + + std::string comparator = GetPredicateComparison(instr.fset.cond); + std::string combiner = GetPredicateCombiner(instr.fset.op); + + std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " + + combiner + " (" + second_pred + "))"; + + regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); break; } default: { |