summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-12-21 03:01:03 +0100
committerReinUsesLisp <reinuseslisp@airmail.cc>2019-01-15 21:54:49 +0100
commitbf07272695b718d09f8ef532539ba625dab01d3c (patch)
tree756b0848eb8b0e94b4e650a2b3371a32e46b63a4 /src/video_core
parentshader_ir: Add half float helpers (diff)
downloadyuzu-bf07272695b718d09f8ef532539ba625dab01d3c.tar
yuzu-bf07272695b718d09f8ef532539ba625dab01d3c.tar.gz
yuzu-bf07272695b718d09f8ef532539ba625dab01d3c.tar.bz2
yuzu-bf07272695b718d09f8ef532539ba625dab01d3c.tar.lz
yuzu-bf07272695b718d09f8ef532539ba625dab01d3c.tar.xz
yuzu-bf07272695b718d09f8ef532539ba625dab01d3c.tar.zst
yuzu-bf07272695b718d09f8ef532539ba625dab01d3c.zip
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/shader/shader_ir.cpp97
-rw-r--r--src/video_core/shader/shader_ir.h9
2 files changed, 106 insertions, 0 deletions
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 5951bdc7b..20a1a50ef 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -212,6 +212,103 @@ Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
return value;
}
+Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
+ static const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
+ {PredCondition::LessThan, OperationCode::LogicalFLessThan},
+ {PredCondition::Equal, OperationCode::LogicalFEqual},
+ {PredCondition::LessEqual, OperationCode::LogicalFLessEqual},
+ {PredCondition::GreaterThan, OperationCode::LogicalFGreaterThan},
+ {PredCondition::NotEqual, OperationCode::LogicalFNotEqual},
+ {PredCondition::GreaterEqual, OperationCode::LogicalFGreaterEqual},
+ {PredCondition::LessThanWithNan, OperationCode::LogicalFLessThan},
+ {PredCondition::NotEqualWithNan, OperationCode::LogicalFNotEqual},
+ {PredCondition::LessEqualWithNan, OperationCode::LogicalFLessEqual},
+ {PredCondition::GreaterThanWithNan, OperationCode::LogicalFGreaterThan},
+ {PredCondition::GreaterEqualWithNan, OperationCode::LogicalFGreaterEqual}};
+
+ const auto comparison{PredicateComparisonTable.find(condition)};
+ UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
+ "Unknown predicate comparison operation");
+
+ Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b);
+
+ if (condition == PredCondition::LessThanWithNan ||
+ condition == PredCondition::NotEqualWithNan ||
+ condition == PredCondition::LessEqualWithNan ||
+ condition == PredCondition::GreaterThanWithNan ||
+ condition == PredCondition::GreaterEqualWithNan) {
+
+ predicate = Operation(OperationCode::LogicalOr, predicate,
+ Operation(OperationCode::LogicalFIsNan, op_a));
+ predicate = Operation(OperationCode::LogicalOr, predicate,
+ Operation(OperationCode::LogicalFIsNan, op_b));
+ }
+
+ return predicate;
+}
+
+Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_signed, Node op_a,
+ Node op_b) {
+ static const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
+ {PredCondition::LessThan, OperationCode::LogicalILessThan},
+ {PredCondition::Equal, OperationCode::LogicalIEqual},
+ {PredCondition::LessEqual, OperationCode::LogicalILessEqual},
+ {PredCondition::GreaterThan, OperationCode::LogicalIGreaterThan},
+ {PredCondition::NotEqual, OperationCode::LogicalINotEqual},
+ {PredCondition::GreaterEqual, OperationCode::LogicalIGreaterEqual},
+ {PredCondition::LessThanWithNan, OperationCode::LogicalILessThan},
+ {PredCondition::NotEqualWithNan, OperationCode::LogicalINotEqual},
+ {PredCondition::LessEqualWithNan, OperationCode::LogicalILessEqual},
+ {PredCondition::GreaterThanWithNan, OperationCode::LogicalIGreaterThan},
+ {PredCondition::GreaterEqualWithNan, OperationCode::LogicalIGreaterEqual}};
+
+ const auto comparison{PredicateComparisonTable.find(condition)};
+ UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
+ "Unknown predicate comparison operation");
+
+ Node predicate = SignedOperation(comparison->second, is_signed, NO_PRECISE, op_a, op_b);
+
+ UNIMPLEMENTED_IF_MSG(condition == PredCondition::LessThanWithNan ||
+ condition == PredCondition::NotEqualWithNan ||
+ condition == PredCondition::LessEqualWithNan ||
+ condition == PredCondition::GreaterThanWithNan ||
+ condition == PredCondition::GreaterEqualWithNan,
+ "NaN comparisons for integers are not implemented");
+ return predicate;
+}
+
+Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition,
+ const MetaHalfArithmetic& meta, Node op_a, Node op_b) {
+
+ UNIMPLEMENTED_IF_MSG(condition == PredCondition::LessThanWithNan ||
+ condition == PredCondition::NotEqualWithNan ||
+ condition == PredCondition::LessEqualWithNan ||
+ condition == PredCondition::GreaterThanWithNan ||
+ condition == PredCondition::GreaterEqualWithNan,
+ "Unimplemented NaN comparison for half floats");
+
+ static const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
+ {PredCondition::LessThan, OperationCode::LogicalHLessThan},
+ {PredCondition::Equal, OperationCode::LogicalHEqual},
+ {PredCondition::LessEqual, OperationCode::LogicalHLessEqual},
+ {PredCondition::GreaterThan, OperationCode::LogicalHGreaterThan},
+ {PredCondition::NotEqual, OperationCode::LogicalHNotEqual},
+ {PredCondition::GreaterEqual, OperationCode::LogicalHGreaterEqual},
+ {PredCondition::LessThanWithNan, OperationCode::LogicalHLessThan},
+ {PredCondition::NotEqualWithNan, OperationCode::LogicalHNotEqual},
+ {PredCondition::LessEqualWithNan, OperationCode::LogicalHLessEqual},
+ {PredCondition::GreaterThanWithNan, OperationCode::LogicalHGreaterThan},
+ {PredCondition::GreaterEqualWithNan, OperationCode::LogicalHGreaterEqual}};
+
+ const auto comparison{PredicateComparisonTable.find(condition)};
+ UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
+ "Unknown predicate comparison operation");
+
+ const Node predicate = Operation(comparison->second, meta, op_a, op_b);
+
+ return predicate;
+}
+
void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) {
bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src));
}
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index f3b17d2eb..372ed10da 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -660,6 +660,15 @@ private:
/// Conditionally absolute/negated half float pair. Absolute is applied first
Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate);
+ /// Returns a predicate comparing two floats
+ Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b);
+ /// Returns a predicate comparing two integers
+ Node GetPredicateComparisonInteger(Tegra::Shader::PredCondition condition, bool is_signed,
+ Node op_a, Node op_b);
+ /// Returns a predicate comparing two half floats. meta consumes how both pairs will be compared
+ Node GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition,
+ const MetaHalfArithmetic& meta, Node op_a, Node op_b);
+
template <typename... T>
inline Node Operation(OperationCode code, const T*... operands) {
return StoreNode(OperationNode(code, operands...));