shader_ir: Add comparison helpers
This commit is contained in:
parent
60f044df56
commit
bf07272695
2 changed files with 106 additions and 0 deletions
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...));
|
||||||
|
|
Loading…
Reference in a new issue