|
@@ -1339,6 +1339,13 @@ SpirvEvalInfo SPIRVEmitter::doCastExpr(const CastExpr *expr) {
|
|
|
switch (expr->getCastKind()) {
|
|
|
case CastKind::CK_LValueToRValue: {
|
|
|
auto info = doExpr(subExpr);
|
|
|
+
|
|
|
+ // There are cases where the AST includes incorrect LValueToRValue nodes in
|
|
|
+ // the tree where not necessary. To make sure we emit the correct SPIR-V, we
|
|
|
+ // should bypass such casts.
|
|
|
+ if (subExpr->IgnoreParenNoopCasts(astContext)->isRValue())
|
|
|
+ return info;
|
|
|
+
|
|
|
if (isVectorShuffle(subExpr) || isa<ExtMatrixElementExpr>(subExpr) ||
|
|
|
isBufferTextureIndexing(dyn_cast<CXXOperatorCallExpr>(subExpr)) ||
|
|
|
isTextureMipsSampleIndexing(dyn_cast<CXXOperatorCallExpr>(subExpr))) {
|
|
@@ -1466,6 +1473,57 @@ SpirvEvalInfo SPIRVEmitter::doCastExpr(const CastExpr *expr) {
|
|
|
return theBuilder.createCompositeConstruct(matType, vectors);
|
|
|
}
|
|
|
}
|
|
|
+ case CastKind::CK_HLSLMatrixTruncationCast: {
|
|
|
+ const QualType srcType = subExpr->getType();
|
|
|
+ const uint32_t srcId = doExpr(subExpr);
|
|
|
+ const QualType elemType = hlsl::GetHLSLMatElementType(srcType);
|
|
|
+ const uint32_t dstTypeId = typeTranslator.translateType(toType);
|
|
|
+ llvm::SmallVector<uint32_t, 4> indexes;
|
|
|
+
|
|
|
+ // It is possible that the source matrix is in fact a vector.
|
|
|
+ // For example: Truncate float1x3 --> float1x2.
|
|
|
+ // The front-end disallows float1x3 --> float2x1.
|
|
|
+ {
|
|
|
+ uint32_t srcVecSize = 0, dstVecSize = 0;
|
|
|
+ if (TypeTranslator::isVectorType(srcType, nullptr, &srcVecSize) &&
|
|
|
+ TypeTranslator::isVectorType(toType, nullptr, &dstVecSize)) {
|
|
|
+ for (uint32_t i = 0; i < dstVecSize; ++i)
|
|
|
+ indexes.push_back(i);
|
|
|
+ return theBuilder.createVectorShuffle(dstTypeId, srcId, srcId, indexes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ uint32_t srcRows = 0, srcCols = 0, dstRows = 0, dstCols = 0;
|
|
|
+ hlsl::GetHLSLMatRowColCount(srcType, srcRows, srcCols);
|
|
|
+ hlsl::GetHLSLMatRowColCount(toType, dstRows, dstCols);
|
|
|
+ const uint32_t elemTypeId = typeTranslator.translateType(elemType);
|
|
|
+ const uint32_t srcRowType = theBuilder.getVecType(elemTypeId, srcCols);
|
|
|
+
|
|
|
+ // Indexes to pass to OpVectorShuffle
|
|
|
+ for (uint32_t i = 0; i < dstCols; ++i)
|
|
|
+ indexes.push_back(i);
|
|
|
+
|
|
|
+ llvm::SmallVector<uint32_t, 4> extractedVecs;
|
|
|
+ for (uint32_t row = 0; row < dstRows; ++row) {
|
|
|
+ // Extract a row
|
|
|
+ uint32_t rowId =
|
|
|
+ theBuilder.createCompositeExtract(srcRowType, srcId, {row});
|
|
|
+ // Extract the necessary columns from that row.
|
|
|
+ // The front-end ensures dstCols <= srcCols.
|
|
|
+ // If dstCols equals srcCols, we can use the whole row directly.
|
|
|
+ if (dstCols == 1) {
|
|
|
+ rowId = theBuilder.createCompositeExtract(elemTypeId, rowId, {0});
|
|
|
+ } else if (dstCols < srcCols) {
|
|
|
+ rowId = theBuilder.createVectorShuffle(
|
|
|
+ theBuilder.getVecType(elemTypeId, dstCols), rowId, rowId, indexes);
|
|
|
+ }
|
|
|
+ extractedVecs.push_back(rowId);
|
|
|
+ }
|
|
|
+ if (extractedVecs.size() == 1)
|
|
|
+ return extractedVecs.front();
|
|
|
+ return theBuilder.createCompositeConstruct(
|
|
|
+ typeTranslator.translateType(toType), extractedVecs);
|
|
|
+ }
|
|
|
case CastKind::CK_HLSLMatrixToScalarCast: {
|
|
|
// The underlying should already be a matrix of 1x1.
|
|
|
assert(TypeTranslator::is1x1Matrix(subExpr->getType()));
|