|
@@ -191,7 +191,7 @@ bool CounterVarFields::assign(const CounterVarFields &srcFields,
|
|
|
}
|
|
|
|
|
|
DeclResultIdMapper::SemanticInfo
|
|
|
-DeclResultIdMapper::getStageVarSemantic(const ValueDecl *decl) {
|
|
|
+DeclResultIdMapper::getStageVarSemantic(const NamedDecl *decl) {
|
|
|
for (auto *annotation : decl->getUnusualAnnotations()) {
|
|
|
if (auto *sema = dyn_cast<hlsl::SemanticDecl>(annotation)) {
|
|
|
llvm::StringRef semanticStr = sema->SemanticName;
|
|
@@ -1080,11 +1080,13 @@ bool DeclResultIdMapper::decorateResourceBindings() {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool DeclResultIdMapper::createStageVars(
|
|
|
- const hlsl::SigPoint *sigPoint, const DeclaratorDecl *decl, bool asInput,
|
|
|
- QualType type, uint32_t arraySize, const llvm::StringRef namePrefix,
|
|
|
- llvm::Optional<uint32_t> invocationId, uint32_t *value, bool noWriteBack,
|
|
|
- SemanticInfo *inheritSemantic) {
|
|
|
+bool DeclResultIdMapper::createStageVars(const hlsl::SigPoint *sigPoint,
|
|
|
+ const NamedDecl *decl, bool asInput,
|
|
|
+ QualType type, uint32_t arraySize,
|
|
|
+ const llvm::StringRef namePrefix,
|
|
|
+ llvm::Optional<uint32_t> invocationId,
|
|
|
+ uint32_t *value, bool noWriteBack,
|
|
|
+ SemanticInfo *inheritSemantic) {
|
|
|
// invocationId should only be used for handling HS per-vertex output.
|
|
|
if (invocationId.hasValue()) {
|
|
|
assert(shaderModel.IsHS() && arraySize != 0 && !asInput);
|
|
@@ -1221,7 +1223,9 @@ bool DeclResultIdMapper::createStageVars(
|
|
|
stageVar.setSpirvId(varId);
|
|
|
stageVar.setLocationAttr(decl->getAttr<VKLocationAttr>());
|
|
|
stageVars.push_back(stageVar);
|
|
|
- stageVarIds[decl] = varId;
|
|
|
+ // We have semantics attached to this decl, which means it must be a
|
|
|
+ // function/parameter/variable. All are DeclaratorDecls.
|
|
|
+ stageVarIds[cast<DeclaratorDecl>(decl)] = varId;
|
|
|
|
|
|
// Mark that we have used one index for this semantic
|
|
|
++semanticToUse->index;
|
|
@@ -1388,6 +1392,18 @@ bool DeclResultIdMapper::createStageVars(
|
|
|
// load their values into a composite.
|
|
|
llvm::SmallVector<uint32_t, 4> subValues;
|
|
|
|
|
|
+ // If we have base classes, we need to handle them first.
|
|
|
+ if (const auto *cxxDecl = type->getAsCXXRecordDecl())
|
|
|
+ for (auto base : cxxDecl->bases()) {
|
|
|
+ uint32_t subValue = 0;
|
|
|
+ if (!createStageVars(sigPoint, base.getType()->getAsCXXRecordDecl(),
|
|
|
+ asInput, base.getType(), arraySize, namePrefix,
|
|
|
+ invocationId, &subValue, noWriteBack,
|
|
|
+ semanticToUse))
|
|
|
+ return false;
|
|
|
+ subValues.push_back(subValue);
|
|
|
+ }
|
|
|
+
|
|
|
for (const auto *field : structDecl->fields()) {
|
|
|
uint32_t subValue = 0;
|
|
|
if (!createStageVars(sigPoint, field, asInput, field->getType(),
|
|
@@ -1432,6 +1448,24 @@ bool DeclResultIdMapper::createStageVars(
|
|
|
|
|
|
*value = theBuilder.createCompositeConstruct(arrayType, arrayElements);
|
|
|
} else {
|
|
|
+ // If we have base classes, we need to handle them first.
|
|
|
+ if (const auto *cxxDecl = type->getAsCXXRecordDecl()) {
|
|
|
+ uint32_t baseIndex = 0;
|
|
|
+ for (auto base : cxxDecl->bases()) {
|
|
|
+ uint32_t subValue = 0;
|
|
|
+ if (!noWriteBack)
|
|
|
+ subValue = theBuilder.createCompositeExtract(
|
|
|
+ typeTranslator.translateType(base.getType()), *value,
|
|
|
+ {baseIndex++});
|
|
|
+
|
|
|
+ if (!createStageVars(sigPoint, base.getType()->getAsCXXRecordDecl(),
|
|
|
+ asInput, base.getType(), arraySize, namePrefix,
|
|
|
+ invocationId, &subValue, noWriteBack,
|
|
|
+ semanticToUse))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Unlike reading, which may require us to read stand-alone builtins and
|
|
|
// stage input variables and compose an array of structs out of them,
|
|
|
// it happens that we don't need to write an array of structs in a bunch
|
|
@@ -1535,7 +1569,7 @@ bool DeclResultIdMapper::writeBackOutputStream(const ValueDecl *decl,
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-void DeclResultIdMapper::decoratePSInterpolationMode(const DeclaratorDecl *decl,
|
|
|
+void DeclResultIdMapper::decoratePSInterpolationMode(const NamedDecl *decl,
|
|
|
QualType type,
|
|
|
uint32_t varId) {
|
|
|
const QualType elemType = typeTranslator.getElementType(type);
|
|
@@ -1569,7 +1603,7 @@ void DeclResultIdMapper::decoratePSInterpolationMode(const DeclaratorDecl *decl,
|
|
|
}
|
|
|
|
|
|
uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
|
|
|
- const DeclaratorDecl *decl,
|
|
|
+ const NamedDecl *decl,
|
|
|
const llvm::StringRef name,
|
|
|
SourceLocation srcLoc) {
|
|
|
using spv::BuiltIn;
|
|
@@ -1924,12 +1958,14 @@ uint32_t DeclResultIdMapper::createSpirvStageVar(StageVar *stageVar,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-bool DeclResultIdMapper::validateVKBuiltins(const DeclaratorDecl *decl,
|
|
|
+bool DeclResultIdMapper::validateVKBuiltins(const NamedDecl *decl,
|
|
|
const hlsl::SigPoint *sigPoint) {
|
|
|
bool success = true;
|
|
|
|
|
|
if (const auto *builtinAttr = decl->getAttr<VKBuiltInAttr>()) {
|
|
|
- const auto declType = getTypeOrFnRetType(decl);
|
|
|
+ // The front end parsing only allows vk::builtin to be attached to a
|
|
|
+ // function/parameter/variable; all of them are DeclaratorDecls.
|
|
|
+ const auto declType = getTypeOrFnRetType(cast<DeclaratorDecl>(decl));
|
|
|
const auto loc = builtinAttr->getLocation();
|
|
|
|
|
|
if (decl->hasAttr<VKLocationAttr>()) {
|