Updated type conversion rules for HLSL frontend
This commit is contained in:
parent
7274bbc27c
commit
8279f0728a
6 changed files with 3443 additions and 7 deletions
|
|
@ -1119,9 +1119,12 @@ void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, T
|
|||
rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode);
|
||||
return;
|
||||
|
||||
case EOpMul:
|
||||
// matrix multiply does not change shapes
|
||||
if (lhsNode->isMatrix() && rhsNode->isMatrix())
|
||||
return;
|
||||
case EOpAdd:
|
||||
case EOpSub:
|
||||
case EOpMul:
|
||||
case EOpDiv:
|
||||
// want to support vector * scalar native ops in AST and lower, not smear, similarly for
|
||||
// matrix * vector, etc.
|
||||
|
|
@ -1194,9 +1197,19 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
|
|||
// The new node that handles the conversion
|
||||
TOperator constructorOp = mapTypeToConstructorOp(type);
|
||||
|
||||
// HLSL has custom semantics for scalar->mat shape conversions.
|
||||
if (source == EShSourceHlsl) {
|
||||
if (node->getType().isScalarOrVec1() && type.isMatrix()) {
|
||||
// HLSL rules for scalar, vector and matrix conversions:
|
||||
// 1) scalar can become anything, initializing every component with its value
|
||||
// 2) vector and matrix can become scalar, first element is used (warning: truncation)
|
||||
// 3) matrix can become matrix with less rows and/or columns (warning: truncation)
|
||||
// 4) vector can become vector with less rows size (warning: truncation)
|
||||
// 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret)
|
||||
// 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret)
|
||||
|
||||
const TType &sourceType = node->getType();
|
||||
|
||||
// rule 1 for scalar to matrix is special
|
||||
if (sourceType.isScalarOrVec1() && type.isMatrix()) {
|
||||
|
||||
// HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its
|
||||
// own devices, the constructor from a scalar would populate the diagonal. This forces replication
|
||||
|
|
@ -1204,7 +1217,7 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
|
|||
|
||||
// Note that if the node is complex (e.g, a function call), we don't want to duplicate it here
|
||||
// repeatedly, so we copy it to a temp, then use the temp.
|
||||
const int matSize = type.getMatrixRows() * type.getMatrixCols();
|
||||
const int matSize = type.computeNumComponents();
|
||||
TIntermAggregate* rhsAggregate = new TIntermAggregate();
|
||||
|
||||
const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr);
|
||||
|
|
@ -1212,12 +1225,44 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
|
|||
if (!isSimple) {
|
||||
assert(0); // TODO: use node replicator service when available.
|
||||
}
|
||||
|
||||
for (int x=0; x<matSize; ++x)
|
||||
|
||||
for (int x = 0; x < matSize; ++x)
|
||||
rhsAggregate->getSequence().push_back(node);
|
||||
|
||||
return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc());
|
||||
}
|
||||
|
||||
// rule 1 and 2
|
||||
if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar()))
|
||||
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
|
||||
|
||||
// rule 3 and 5b
|
||||
if (sourceType.isMatrix()) {
|
||||
// rule 3
|
||||
if (type.isMatrix()) {
|
||||
if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) &&
|
||||
sourceType.getMatrixCols() >= type.getMatrixCols() && sourceType.getMatrixRows() >= type.getMatrixRows())
|
||||
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
|
||||
// rule 5b
|
||||
} else if (type.isVector()) {
|
||||
if (type.getVectorSize() == 4 && sourceType.getMatrixCols() == 2 && sourceType.getMatrixRows() == 2)
|
||||
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
|
||||
}
|
||||
}
|
||||
|
||||
// rule 4 and 5a
|
||||
if (sourceType.isVector()) {
|
||||
// rule 4
|
||||
if (type.isVector())
|
||||
{
|
||||
if (sourceType.getVectorSize() > type.getVectorSize())
|
||||
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
|
||||
// rule 5a
|
||||
} else if (type.isMatrix()) {
|
||||
if (sourceType.getVectorSize() == 4 && type.getMatrixCols() == 2 && type.getMatrixRows() == 2)
|
||||
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scalar -> vector or vec1 -> vector or
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue