HLSL: Enable component-wise vector comparisons from operators
This PR only changes a few lines of code, but is subtle. In HLSL, comparison operators (<,>,<=,>=,==,!=) operate component-wise when given a vector operand. If a whole vector equality or inequality is desired, then all() or any() can be used on the resulting bool vector. This PR enables this change. Existing shape conversion is used when one of the two arguments is a vector and one is a scalar. Some existing HLSL tests had assumed == and != meant vector-wise instead of component-wise comparisons. These tests have been changed to add an explicit any() or all() to the test source. This verifably does not change the final SPIR-V binary relative to the old behavior for == and !=. The AST does change for the (now explicit, formerly implicit) any() and all(). Also, a few tests changes where they previously had the return type wrong, e.g, from a vec < vec comparison in hlsl.shapeConv.frag. Promotion of comparison opcodes to vector forms (EOpEqual->EOpVectorEqual) is handled in promoteBinary(), as is setting the proper vector type of the result. EOpVectorEqual and EOpVectorNotEqual are now accepted as either aggregate or binary nodes, similar to how the other operators are handled. Partial support already existed for this: it has been fleshed out in the printing functions in intermOut.cpp. There is an existing defect around shape conversion with 1-vectors, but that is orthogonal to this PR and not addressed by it.
This commit is contained in:
parent
0d628c179d
commit
85244d7486
15 changed files with 635 additions and 155 deletions
|
|
@ -1892,13 +1892,26 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
|
|||
// Relational comparisons need numeric types and will promote to scalar Boolean.
|
||||
if (left->getBasicType() == EbtBool)
|
||||
return false;
|
||||
node.setType(TType(EbtBool));
|
||||
|
||||
node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize()));
|
||||
break;
|
||||
|
||||
case EOpEqual:
|
||||
case EOpNotEqual:
|
||||
// All the above comparisons result in a bool (but not the vector compares)
|
||||
node.setType(TType(EbtBool));
|
||||
if (getSource() == EShSourceHlsl) {
|
||||
const int resultWidth = std::max(left->getVectorSize(), right->getVectorSize());
|
||||
|
||||
// In HLSL, == or != on vectors means component-wise comparison.
|
||||
if (resultWidth > 1) {
|
||||
op = (op == EOpEqual) ? EOpVectorEqual : EOpVectorNotEqual;
|
||||
node.setOp(op);
|
||||
}
|
||||
|
||||
node.setType(TType(EbtBool, EvqTemporary, resultWidth));
|
||||
} else {
|
||||
// All the above comparisons result in a bool (but not the vector compares)
|
||||
node.setType(TType(EbtBool));
|
||||
}
|
||||
break;
|
||||
|
||||
case EOpLogicalAnd:
|
||||
|
|
@ -1973,6 +1986,8 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
|
|||
|
||||
case EOpEqual:
|
||||
case EOpNotEqual:
|
||||
case EOpVectorEqual:
|
||||
case EOpVectorNotEqual:
|
||||
|
||||
case EOpLogicalAnd:
|
||||
case EOpLogicalOr:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue