Convert the node's shape of type for the given type, as allowed by the operation involved: 'op'. Generally, the AST represents allowed GLSL shapes, so this isn't needed for GLSL. Bad shapes are caught in conversion or promotion. Return 'node' if no conversion was done. Promotion handles final shape checking.
| 1179 | // checking. |
| 1180 | // |
| 1181 | TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node) |
| 1182 | { |
| 1183 | // no conversion needed |
| 1184 | if (node->getType() == type) |
| 1185 | return node; |
| 1186 | |
| 1187 | // structures and arrays don't change shape, either to or from |
| 1188 | if (node->getType().isStruct() || node->getType().isArray() || |
| 1189 | type.isStruct() || type.isArray()) |
| 1190 | return node; |
| 1191 | |
| 1192 | // The new node that handles the conversion |
| 1193 | TOperator constructorOp = mapTypeToConstructorOp(type); |
| 1194 | |
| 1195 | if (getSource() == EShSourceHlsl) { |
| 1196 | // HLSL rules for scalar, vector and matrix conversions: |
| 1197 | // 1) scalar can become anything, initializing every component with its value |
| 1198 | // 2) vector and matrix can become scalar, first element is used (warning: truncation) |
| 1199 | // 3) matrix can become matrix with less rows and/or columns (warning: truncation) |
| 1200 | // 4) vector can become vector with less rows size (warning: truncation) |
| 1201 | // 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret) |
| 1202 | // 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret) |
| 1203 | |
| 1204 | const TType &sourceType = node->getType(); |
| 1205 | |
| 1206 | // rule 1 for scalar to matrix is special |
| 1207 | if (sourceType.isScalarOrVec1() && type.isMatrix()) { |
| 1208 | |
| 1209 | // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its |
| 1210 | // own devices, the constructor from a scalar would populate the diagonal. This forces replication |
| 1211 | // to every matrix element. |
| 1212 | |
| 1213 | // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here |
| 1214 | // repeatedly, so we copy it to a temp, then use the temp. |
| 1215 | const int matSize = type.computeNumComponents(); |
| 1216 | TIntermAggregate* rhsAggregate = new TIntermAggregate(); |
| 1217 | |
| 1218 | const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr); |
| 1219 | |
| 1220 | if (!isSimple) { |
| 1221 | assert(0); // TODO: use node replicator service when available. |
| 1222 | } |
| 1223 | |
| 1224 | for (int x = 0; x < matSize; ++x) |
| 1225 | rhsAggregate->getSequence().push_back(node); |
| 1226 | |
| 1227 | return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc()); |
| 1228 | } |
| 1229 | |
| 1230 | // rule 1 and 2 |
| 1231 | if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar())) |
| 1232 | return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); |
| 1233 | |
| 1234 | // rule 3 and 5b |
| 1235 | if (sourceType.isMatrix()) { |
| 1236 | // rule 3 |
| 1237 | if (type.isMatrix()) { |
| 1238 | if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) && |
no test coverage detected