shader_ir: Add comparison helpers

This commit is contained in:
ReinUsesLisp 2018-12-20 23:01:03 -03:00
parent 60f044df56
commit bf07272695
2 changed files with 106 additions and 0 deletions

View file

@ -212,6 +212,103 @@ Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
return value; 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) { void ShaderIR::SetRegister(BasicBlock& bb, Register dest, Node src) {
bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src)); bb.push_back(Operation(OperationCode::Assign, GetRegister(dest), src));
} }

View file

@ -660,6 +660,15 @@ private:
/// Conditionally absolute/negated half float pair. Absolute is applied first /// Conditionally absolute/negated half float pair. Absolute is applied first
Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate); 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> template <typename... T>
inline Node Operation(OperationCode code, const T*... operands) { inline Node Operation(OperationCode code, const T*... operands) {
return StoreNode(OperationNode(code, operands...)); return StoreNode(OperationNode(code, operands...));