|
@@ -15,10 +15,12 @@
|
|
|
|
|
|
#include "AlignmentSizeCalculator.h"
|
|
#include "AlignmentSizeCalculator.h"
|
|
#include "InitListHandler.h"
|
|
#include "InitListHandler.h"
|
|
|
|
+#include "LowerTypeVisitor.h"
|
|
#include "RawBufferMethods.h"
|
|
#include "RawBufferMethods.h"
|
|
#include "dxc/DXIL/DxilConstants.h"
|
|
#include "dxc/DXIL/DxilConstants.h"
|
|
#include "dxc/HlslIntrinsicOp.h"
|
|
#include "dxc/HlslIntrinsicOp.h"
|
|
#include "spirv-tools/optimizer.hpp"
|
|
#include "spirv-tools/optimizer.hpp"
|
|
|
|
+#include "clang/AST/RecordLayout.h"
|
|
#include "clang/SPIRV/AstTypeProbe.h"
|
|
#include "clang/SPIRV/AstTypeProbe.h"
|
|
#include "clang/SPIRV/String.h"
|
|
#include "clang/SPIRV/String.h"
|
|
#include "clang/Sema/Sema.h"
|
|
#include "clang/Sema/Sema.h"
|
|
@@ -542,6 +544,45 @@ bool isVkRawBufferLoadIntrinsic(const clang::FunctionDecl *FD) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Takes an AST member type, and determines its index in the equivalent SPIR-V
|
|
|
|
+// struct type. This is required as the struct layout might change between the
|
|
|
|
+// AST representation and SPIR-V representation.
|
|
|
|
+uint32_t getFieldIndexInStruct(const StructType *spirvStructType,
|
|
|
|
+ const QualType &astStructType,
|
|
|
|
+ const FieldDecl *fieldDecl) {
|
|
|
|
+ assert(fieldDecl);
|
|
|
|
+ const uint32_t indexAST =
|
|
|
|
+ getNumBaseClasses(astStructType) + fieldDecl->getFieldIndex();
|
|
|
|
+
|
|
|
|
+ const auto &fields = spirvStructType->getFields();
|
|
|
|
+ assert(indexAST <= fields.size());
|
|
|
|
+ return fields[indexAST].fieldIndex;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Takes an AST struct type, and lowers is to the equivalent SPIR-V type.
|
|
|
|
+const StructType *lowerStructType(const SpirvCodeGenOptions &spirvOptions,
|
|
|
|
+ LowerTypeVisitor &lowerTypeVisitor,
|
|
|
|
+ const QualType &structType) {
|
|
|
|
+ // If we are accessing a derived struct, we need to account for the number
|
|
|
|
+ // of base structs, since they are placed as fields at the beginning of the
|
|
|
|
+ // derived struct.
|
|
|
|
+ auto baseType = structType;
|
|
|
|
+ if (baseType->isPointerType()) {
|
|
|
|
+ baseType = baseType->getPointeeType();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // The AST type index is not representative of the SPIR-V type index
|
|
|
|
+ // because we might squash some fields (bitfields by ex.).
|
|
|
|
+ // What we need is to match each AST node with the squashed field and then,
|
|
|
|
+ // determine the real index.
|
|
|
|
+ const SpirvType *spvType = lowerTypeVisitor.lowerType(
|
|
|
|
+ baseType, spirvOptions.sBufferLayoutRule, llvm::None, SourceLocation());
|
|
|
|
+
|
|
|
|
+ const StructType *output = dyn_cast<StructType>(spvType);
|
|
|
|
+ assert(output != nullptr);
|
|
|
|
+ return output;
|
|
|
|
+}
|
|
|
|
+
|
|
} // namespace
|
|
} // namespace
|
|
|
|
|
|
SpirvEmitter::SpirvEmitter(CompilerInstance &ci)
|
|
SpirvEmitter::SpirvEmitter(CompilerInstance &ci)
|
|
@@ -2584,12 +2625,12 @@ SpirvEmitter::doArraySubscriptExpr(const ArraySubscriptExpr *expr,
|
|
SourceRange range =
|
|
SourceRange range =
|
|
(rangeOverride != SourceRange()) ? rangeOverride : expr->getSourceRange();
|
|
(rangeOverride != SourceRange()) ? rangeOverride : expr->getSourceRange();
|
|
|
|
|
|
- if (!indices.empty()) {
|
|
|
|
- info = turnIntoElementPtr(base->getType(), info, expr->getType(), indices,
|
|
|
|
- base->getExprLoc(), range);
|
|
|
|
|
|
+ if (indices.empty()) {
|
|
|
|
+ return info;
|
|
}
|
|
}
|
|
|
|
|
|
- return info;
|
|
|
|
|
|
+ return derefOrCreatePointerToValue(base->getType(), info, expr->getType(),
|
|
|
|
+ indices, base->getExprLoc(), range);
|
|
}
|
|
}
|
|
|
|
|
|
SpirvInstruction *SpirvEmitter::doBinaryOperator(const BinaryOperator *expr) {
|
|
SpirvInstruction *SpirvEmitter::doBinaryOperator(const BinaryOperator *expr) {
|
|
@@ -3281,9 +3322,9 @@ SpirvInstruction *SpirvEmitter::doCastExpr(const CastExpr *expr,
|
|
astContext.UnsignedIntTy, llvm::APInt(32, baseIndices[i]));
|
|
astContext.UnsignedIntTy, llvm::APInt(32, baseIndices[i]));
|
|
|
|
|
|
auto *derivedInfo = doExpr(subExpr);
|
|
auto *derivedInfo = doExpr(subExpr);
|
|
- return turnIntoElementPtr(subExpr->getType(), derivedInfo, expr->getType(),
|
|
|
|
- baseIndexInstructions, subExpr->getExprLoc(),
|
|
|
|
- range);
|
|
|
|
|
|
+ return derefOrCreatePointerToValue(subExpr->getType(), derivedInfo,
|
|
|
|
+ expr->getType(), baseIndexInstructions,
|
|
|
|
+ subExpr->getExprLoc(), range);
|
|
}
|
|
}
|
|
case CastKind::CK_ArrayToPointerDecay: {
|
|
case CastKind::CK_ArrayToPointerDecay: {
|
|
// Literal string to const string conversion falls under this category.
|
|
// Literal string to const string conversion falls under this category.
|
|
@@ -4355,8 +4396,9 @@ SpirvEmitter::processStructuredBufferLoad(const CXXMemberCallExpr *expr) {
|
|
auto *zero = spvBuilder.getConstantInt(astContext.IntTy, llvm::APInt(32, 0));
|
|
auto *zero = spvBuilder.getConstantInt(astContext.IntTy, llvm::APInt(32, 0));
|
|
auto *index = doExpr(expr->getArg(0));
|
|
auto *index = doExpr(expr->getArg(0));
|
|
|
|
|
|
- return turnIntoElementPtr(buffer->getType(), info, structType, {zero, index},
|
|
|
|
- buffer->getExprLoc(), range);
|
|
|
|
|
|
+ return derefOrCreatePointerToValue(buffer->getType(), info, structType,
|
|
|
|
+ {zero, index}, buffer->getExprLoc(),
|
|
|
|
+ range);
|
|
}
|
|
}
|
|
|
|
|
|
SpirvInstruction *
|
|
SpirvInstruction *
|
|
@@ -4574,7 +4616,8 @@ SpirvEmitter::processACSBufferAppendConsume(const CXXMemberCallExpr *expr) {
|
|
}
|
|
}
|
|
|
|
|
|
const auto range = expr->getSourceRange();
|
|
const auto range = expr->getSourceRange();
|
|
- bufferInfo = turnIntoElementPtr(object->getType(), bufferInfo, bufferElemTy,
|
|
|
|
|
|
+ bufferInfo =
|
|
|
|
+ derefOrCreatePointerToValue(object->getType(), bufferInfo, bufferElemTy,
|
|
{zero, index}, object->getExprLoc(), range);
|
|
{zero, index}, object->getExprLoc(), range);
|
|
|
|
|
|
if (isAppend) {
|
|
if (isAppend) {
|
|
@@ -5598,8 +5641,8 @@ SpirvEmitter::doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr,
|
|
SourceRange range =
|
|
SourceRange range =
|
|
(rangeOverride != SourceRange()) ? rangeOverride : expr->getSourceRange();
|
|
(rangeOverride != SourceRange()) ? rangeOverride : expr->getSourceRange();
|
|
|
|
|
|
- return turnIntoElementPtr(baseExpr->getType(), base, expr->getType(), indices,
|
|
|
|
- baseExpr->getExprLoc(), range);
|
|
|
|
|
|
+ return derefOrCreatePointerToValue(baseExpr->getType(), base, expr->getType(),
|
|
|
|
+ indices, baseExpr->getExprLoc(), range);
|
|
}
|
|
}
|
|
|
|
|
|
SpirvInstruction *
|
|
SpirvInstruction *
|
|
@@ -5794,16 +5837,50 @@ SpirvInstruction *SpirvEmitter::doMemberExpr(const MemberExpr *expr,
|
|
llvm::SmallVector<SpirvInstruction *, 4> indices;
|
|
llvm::SmallVector<SpirvInstruction *, 4> indices;
|
|
const Expr *base = collectArrayStructIndices(
|
|
const Expr *base = collectArrayStructIndices(
|
|
expr, /*rawIndex*/ false, /*rawIndices*/ nullptr, &indices);
|
|
expr, /*rawIndex*/ false, /*rawIndices*/ nullptr, &indices);
|
|
- SourceRange range =
|
|
|
|
|
|
+ const SourceRange &range =
|
|
(rangeOverride != SourceRange()) ? rangeOverride : expr->getSourceRange();
|
|
(rangeOverride != SourceRange()) ? rangeOverride : expr->getSourceRange();
|
|
auto *instr = loadIfAliasVarRef(base, range);
|
|
auto *instr = loadIfAliasVarRef(base, range);
|
|
|
|
+ const auto &loc = base->getExprLoc();
|
|
|
|
|
|
- if (instr && !indices.empty()) {
|
|
|
|
- instr = turnIntoElementPtr(base->getType(), instr, expr->getType(), indices,
|
|
|
|
- base->getExprLoc(), range);
|
|
|
|
|
|
+ if (!instr || indices.empty()) {
|
|
|
|
+ return instr;
|
|
}
|
|
}
|
|
|
|
|
|
- return instr;
|
|
|
|
|
|
+ const auto *fieldDecl = dyn_cast<FieldDecl>(expr->getMemberDecl());
|
|
|
|
+ if (!fieldDecl || !fieldDecl->isBitField()) {
|
|
|
|
+ return derefOrCreatePointerToValue(base->getType(), instr, expr->getType(),
|
|
|
|
+ indices, loc, range);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ auto baseType = expr->getBase()->getType();
|
|
|
|
+ if (baseType->isPointerType()) {
|
|
|
|
+ baseType = baseType->getPointeeType();
|
|
|
|
+ }
|
|
|
|
+ const uint32_t indexAST =
|
|
|
|
+ getNumBaseClasses(baseType) + fieldDecl->getFieldIndex();
|
|
|
|
+ LowerTypeVisitor lowerTypeVisitor(astContext, spvContext, spirvOptions);
|
|
|
|
+ const StructType *spirvStructType =
|
|
|
|
+ lowerStructType(spirvOptions, lowerTypeVisitor, baseType);
|
|
|
|
+ assert(spirvStructType);
|
|
|
|
+
|
|
|
|
+ const uint32_t bitfieldOffset =
|
|
|
|
+ spirvStructType->getFields()[indexAST].bitfield->offsetInBits;
|
|
|
|
+ const uint32_t bitfieldSize =
|
|
|
|
+ spirvStructType->getFields()[indexAST].bitfield->sizeInBits;
|
|
|
|
+ BitfieldInfo bitfieldInfo{bitfieldOffset, bitfieldSize};
|
|
|
|
+
|
|
|
|
+ if (instr->isRValue()) {
|
|
|
|
+ SpirvVariable *variable = turnIntoLValue(base->getType(), instr, loc);
|
|
|
|
+ SpirvInstruction *chain = spvBuilder.createAccessChain(
|
|
|
|
+ expr->getType(), variable, indices, loc, range);
|
|
|
|
+ chain->setBitfieldInfo(bitfieldInfo);
|
|
|
|
+ return spvBuilder.createLoad(expr->getType(), chain, loc);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SpirvInstruction *chain =
|
|
|
|
+ spvBuilder.createAccessChain(expr->getType(), instr, indices, loc, range);
|
|
|
|
+ chain->setBitfieldInfo(bitfieldInfo);
|
|
|
|
+ return chain;
|
|
}
|
|
}
|
|
|
|
|
|
SpirvVariable *SpirvEmitter::createTemporaryVar(QualType type,
|
|
SpirvVariable *SpirvEmitter::createTemporaryVar(QualType type,
|
|
@@ -6833,23 +6910,42 @@ void SpirvEmitter::splitVecLastElement(QualType vecType, SpirvInstruction *vec,
|
|
spvBuilder.createCompositeExtract(elemType, vec, {count - 1}, loc);
|
|
spvBuilder.createCompositeExtract(elemType, vec, {count - 1}, loc);
|
|
}
|
|
}
|
|
|
|
|
|
-SpirvInstruction *SpirvEmitter::convertVectorToStruct(QualType structType,
|
|
|
|
|
|
+SpirvInstruction *SpirvEmitter::convertVectorToStruct(QualType astStructType,
|
|
QualType elemType,
|
|
QualType elemType,
|
|
SpirvInstruction *vector,
|
|
SpirvInstruction *vector,
|
|
SourceLocation loc,
|
|
SourceLocation loc,
|
|
SourceRange range) {
|
|
SourceRange range) {
|
|
- assert(structType->isStructureType());
|
|
|
|
|
|
+ assert(astStructType->isStructureType());
|
|
|
|
+
|
|
|
|
+ const auto *structDecl = astStructType->getAsStructureType()->getDecl();
|
|
|
|
+ LowerTypeVisitor lowerTypeVisitor(astContext, spvContext, spirvOptions);
|
|
|
|
+ const StructType *spirvStructType =
|
|
|
|
+ lowerStructType(spirvOptions, lowerTypeVisitor, astStructType);
|
|
|
|
|
|
- const auto *structDecl = structType->getAsStructureType()->getDecl();
|
|
|
|
uint32_t vectorIndex = 0;
|
|
uint32_t vectorIndex = 0;
|
|
uint32_t elemCount = 1;
|
|
uint32_t elemCount = 1;
|
|
|
|
+ uint32_t lastConvertedIndex = 0;
|
|
llvm::SmallVector<SpirvInstruction *, 4> members;
|
|
llvm::SmallVector<SpirvInstruction *, 4> members;
|
|
|
|
+ for (auto field = structDecl->field_begin(); field != structDecl->field_end();
|
|
|
|
+ field++) {
|
|
|
|
+ // Multiple bitfields can share the same storing type. In such case, we only
|
|
|
|
+ // want to append the whole storage once.
|
|
|
|
+ const size_t astFieldIndex =
|
|
|
|
+ std::distance(structDecl->field_begin(), field);
|
|
|
|
+ const uint32_t currentFieldIndex =
|
|
|
|
+ spirvStructType->getFields()[astFieldIndex].fieldIndex;
|
|
|
|
+ if (astFieldIndex > 0 && currentFieldIndex == lastConvertedIndex) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ lastConvertedIndex = currentFieldIndex;
|
|
|
|
|
|
- for (const auto *field : structDecl->fields()) {
|
|
|
|
if (isScalarType(field->getType())) {
|
|
if (isScalarType(field->getType())) {
|
|
members.push_back(spvBuilder.createCompositeExtract(
|
|
members.push_back(spvBuilder.createCompositeExtract(
|
|
elemType, vector, {vectorIndex++}, loc, range));
|
|
elemType, vector, {vectorIndex++}, loc, range));
|
|
- } else if (isVectorType(field->getType(), nullptr, &elemCount)) {
|
|
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (isVectorType(field->getType(), nullptr, &elemCount)) {
|
|
llvm::SmallVector<uint32_t, 4> indices;
|
|
llvm::SmallVector<uint32_t, 4> indices;
|
|
for (uint32_t i = 0; i < elemCount; ++i)
|
|
for (uint32_t i = 0; i < elemCount; ++i)
|
|
indices.push_back(vectorIndex++);
|
|
indices.push_back(vectorIndex++);
|
|
@@ -6857,13 +6953,14 @@ SpirvInstruction *SpirvEmitter::convertVectorToStruct(QualType structType,
|
|
members.push_back(spvBuilder.createVectorShuffle(
|
|
members.push_back(spvBuilder.createVectorShuffle(
|
|
astContext.getExtVectorType(elemType, elemCount), vector, vector,
|
|
astContext.getExtVectorType(elemType, elemCount), vector, vector,
|
|
indices, loc, range));
|
|
indices, loc, range));
|
|
- } else {
|
|
|
|
- assert(false && "unhandled type");
|
|
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ assert(false && "unhandled type");
|
|
}
|
|
}
|
|
|
|
|
|
return spvBuilder.createCompositeConstruct(
|
|
return spvBuilder.createCompositeConstruct(
|
|
- structType, members, vector->getSourceLocation(), range);
|
|
|
|
|
|
+ astStructType, members, vector->getSourceLocation(), range);
|
|
}
|
|
}
|
|
|
|
|
|
SpirvInstruction *
|
|
SpirvInstruction *
|
|
@@ -7614,23 +7711,24 @@ const Expr *SpirvEmitter::collectArrayStructIndices(
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Append the index of the current level
|
|
|
|
- const auto *fieldDecl = cast<FieldDecl>(indexing->getMemberDecl());
|
|
|
|
- assert(fieldDecl);
|
|
|
|
- // If we are accessing a derived struct, we need to account for the number
|
|
|
|
- // of base structs, since they are placed as fields at the beginning of the
|
|
|
|
- // derived struct.
|
|
|
|
- auto baseType = indexing->getBase()->getType();
|
|
|
|
- if (baseType->isPointerType()) {
|
|
|
|
- baseType = baseType->getPointeeType();
|
|
|
|
- }
|
|
|
|
- const uint32_t index =
|
|
|
|
- getNumBaseClasses(baseType) + fieldDecl->getFieldIndex();
|
|
|
|
- if (rawIndex) {
|
|
|
|
- rawIndices->push_back(index);
|
|
|
|
- } else {
|
|
|
|
- indices->push_back(spvBuilder.getConstantInt(
|
|
|
|
- astContext.IntTy, llvm::APInt(32, index, true)));
|
|
|
|
|
|
+ {
|
|
|
|
+ LowerTypeVisitor lowerTypeVisitor(astContext, spvContext, spirvOptions);
|
|
|
|
+ const auto &astStructType =
|
|
|
|
+ /* structType */ indexing->getBase()->getType();
|
|
|
|
+ const StructType *spirvStructType =
|
|
|
|
+ lowerStructType(spirvOptions, lowerTypeVisitor, astStructType);
|
|
|
|
+ assert(spirvStructType != nullptr);
|
|
|
|
+ const uint32_t fieldIndex = getFieldIndexInStruct(
|
|
|
|
+ spirvStructType, astStructType,
|
|
|
|
+ /* fieldDecl */
|
|
|
|
+ dyn_cast<FieldDecl>(indexing->getMemberDecl()));
|
|
|
|
+
|
|
|
|
+ if (rawIndex) {
|
|
|
|
+ rawIndices->push_back(fieldIndex);
|
|
|
|
+ } else {
|
|
|
|
+ indices->push_back(spvBuilder.getConstantInt(
|
|
|
|
+ astContext.IntTy, llvm::APInt(32, fieldIndex, true)));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
return base;
|
|
return base;
|
|
@@ -7758,26 +7856,31 @@ const Expr *SpirvEmitter::collectArrayStructIndices(
|
|
return expr;
|
|
return expr;
|
|
}
|
|
}
|
|
|
|
|
|
-SpirvInstruction *SpirvEmitter::turnIntoElementPtr(
|
|
|
|
|
|
+SpirvVariable *SpirvEmitter::turnIntoLValue(QualType type,
|
|
|
|
+ SpirvInstruction *source,
|
|
|
|
+ SourceLocation loc) {
|
|
|
|
+ assert(source->isRValue());
|
|
|
|
+ const auto varName = getAstTypeName(type);
|
|
|
|
+ const auto var = createTemporaryVar(type, varName, source, loc);
|
|
|
|
+ var->setLayoutRule(SpirvLayoutRule::Void);
|
|
|
|
+ var->setStorageClass(spv::StorageClass::Function);
|
|
|
|
+ var->setContainsAliasComponent(source->containsAliasComponent());
|
|
|
|
+ return var;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+SpirvInstruction *SpirvEmitter::derefOrCreatePointerToValue(
|
|
QualType baseType, SpirvInstruction *base, QualType elemType,
|
|
QualType baseType, SpirvInstruction *base, QualType elemType,
|
|
const llvm::SmallVector<SpirvInstruction *, 4> &indices, SourceLocation loc,
|
|
const llvm::SmallVector<SpirvInstruction *, 4> &indices, SourceLocation loc,
|
|
SourceRange range) {
|
|
SourceRange range) {
|
|
- // If this is a rvalue, we need a temporary object to hold it
|
|
|
|
- // so that we can get access chain from it.
|
|
|
|
- const bool needTempVar = base->isRValue();
|
|
|
|
- SpirvInstruction *accessChainBase = base;
|
|
|
|
-
|
|
|
|
- if (needTempVar) {
|
|
|
|
- auto varName = getAstTypeName(baseType);
|
|
|
|
- const auto var = createTemporaryVar(baseType, varName, base, loc);
|
|
|
|
- var->setLayoutRule(SpirvLayoutRule::Void);
|
|
|
|
- var->setStorageClass(spv::StorageClass::Function);
|
|
|
|
- var->setContainsAliasComponent(base->containsAliasComponent());
|
|
|
|
- accessChainBase = var;
|
|
|
|
|
|
+ if (base->isLValue()) {
|
|
|
|
+ return spvBuilder.createAccessChain(elemType, base, indices, loc, range);
|
|
}
|
|
}
|
|
|
|
|
|
- base = spvBuilder.createAccessChain(elemType, accessChainBase, indices, loc,
|
|
|
|
- range);
|
|
|
|
|
|
+ // If this is a rvalue, we need a temporary object to hold it
|
|
|
|
+ // so that we can get access chain from it.
|
|
|
|
+ SpirvVariable *variable = turnIntoLValue(baseType, base, loc);
|
|
|
|
+ SpirvInstruction *chain =
|
|
|
|
+ spvBuilder.createAccessChain(elemType, variable, indices, loc, range);
|
|
|
|
|
|
// Okay, this part seems weird, but it is intended:
|
|
// Okay, this part seems weird, but it is intended:
|
|
// If the base is originally a rvalue, the whole AST involving the base
|
|
// If the base is originally a rvalue, the whole AST involving the base
|
|
@@ -7788,11 +7891,7 @@ SpirvInstruction *SpirvEmitter::turnIntoElementPtr(
|
|
// to rely on to load the access chain if a rvalue is expected. Therefore,
|
|
// to rely on to load the access chain if a rvalue is expected. Therefore,
|
|
// we must do the load here. Otherwise, it's up to the consumer of this
|
|
// we must do the load here. Otherwise, it's up to the consumer of this
|
|
// access chain to do the load, and that can be everywhere.
|
|
// access chain to do the load, and that can be everywhere.
|
|
- if (needTempVar) {
|
|
|
|
- base = spvBuilder.createLoad(elemType, base, loc);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return base;
|
|
|
|
|
|
+ return spvBuilder.createLoad(elemType, chain, loc);
|
|
}
|
|
}
|
|
|
|
|
|
SpirvInstruction *SpirvEmitter::castToBool(SpirvInstruction *fromVal,
|
|
SpirvInstruction *SpirvEmitter::castToBool(SpirvInstruction *fromVal,
|
|
@@ -11342,7 +11441,7 @@ void SpirvEmitter::processDispatchMesh(const CallExpr *callExpr) {
|
|
/*isDevice*/ false,
|
|
/*isDevice*/ false,
|
|
/*groupSync*/ true,
|
|
/*groupSync*/ true,
|
|
/*isAllBarrier*/ false);
|
|
/*isAllBarrier*/ false);
|
|
-
|
|
|
|
|
|
+
|
|
// 2) create PerTaskNV out attribute block and store MeshPayload info.
|
|
// 2) create PerTaskNV out attribute block and store MeshPayload info.
|
|
const auto *sigPoint =
|
|
const auto *sigPoint =
|
|
hlsl::SigPoint::GetSigPoint(hlsl::DXIL::SigPointKind::MSOut);
|
|
hlsl::SigPoint::GetSigPoint(hlsl::DXIL::SigPointKind::MSOut);
|
|
@@ -13476,7 +13575,9 @@ SpirvEmitter::loadDataFromRawAddress(SpirvInstruction *addressInUInt64,
|
|
spv::Op::OpBitcast, bufferPtrType, addressInUInt64, loc);
|
|
spv::Op::OpBitcast, bufferPtrType, addressInUInt64, loc);
|
|
address->setStorageClass(spv::StorageClass::PhysicalStorageBuffer);
|
|
address->setStorageClass(spv::StorageClass::PhysicalStorageBuffer);
|
|
|
|
|
|
- SpirvLoad *loadInst = spvBuilder.createLoad(bufferType, address, loc);
|
|
|
|
|
|
+ SpirvLoad *loadInst = dyn_cast<SpirvLoad>(
|
|
|
|
+ spvBuilder.createLoad(bufferType, address, loc));
|
|
|
|
+ assert(loadInst);
|
|
loadInst->setAlignment(alignment);
|
|
loadInst->setAlignment(alignment);
|
|
loadInst->setRValue();
|
|
loadInst->setRValue();
|
|
return loadInst;
|
|
return loadInst;
|