summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-06-08 05:12:49 -0700
committerGitHub <noreply@github.com>2024-06-08 05:12:49 -0700
commit9a23a9aab3721828526c921db1e779008e133e8f (patch)
treeb49448075cdffe278fd6760e2879bc061eb8e0af /source/slang/slang-check-decl.cpp
parentbc680e74bd8a0c415cab5ed6fe00b762c26b8b8d (diff)
SPIRV `Block` decoration fixes. (#4303)
* SPIRV `Block` decoration fixes. - SPIRV does not allow duplicate `Block` decorations. So we shouldn't be generating them. - Also fixes duplication of OpName. - SPIRV and HLSL do not allow ConstantBuffer with trailing unsized arrays. Added a check in the front-end against such code. * Convert failing cross-compile tests to filecheck. --------- Co-authored-by: Jay Kwak <82421531+jkwak-work@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 95528b185..bf61a6c2e 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2101,6 +2101,19 @@ namespace Slang
{
getSink()->diagnose(varDecl->type.exp->loc, Diagnostics::incompleteTypeCannotBeUsedInBuffer, elementType);
}
+ if (doesTypeHaveTag(elementType, TypeTag::Unsized))
+ {
+ // If the element type is unsized, it can only be an array of resource types that we can legalize out.
+ // Ordinary unsized arrays are not allowed in a constant buffer since we cannot translate it to
+ // valid HLSL or SPIRV.
+ ArrayExpressionType* trailingArrayType = nullptr;
+ VarDeclBase* trailingArrayField = getTrailingUnsizedArrayElement(elementType, varDecl, trailingArrayType);
+ if (trailingArrayField && !isOpaqueHandleType(trailingArrayType->getElementType()))
+ {
+ getSink()->diagnose(trailingArrayField->loc, Diagnostics::cannotUseUnsizedTypeInConstantBuffer, trailingArrayType);
+ getSink()->diagnose(varDecl->loc, Diagnostics::seeConstantBufferDefinition);
+ }
+ }
}
else if (varDecl->findModifier<HLSLUniformModifier>())
{
@@ -10420,6 +10433,80 @@ namespace Slang
return defaultVis;
}
+ VarDeclBase* getTrailingUnsizedArrayElement(Type* type, VarDeclBase* parentVar, ArrayExpressionType*& outArrayType)
+ {
+ while (auto modifiedType = as<ModifiedType>(type))
+ type = modifiedType->getBase();
+ HashSet<Type*> seenTypes;
+ for (;;)
+ {
+ if (auto arrayType = as<ArrayExpressionType>(type))
+ {
+ if (arrayType->isUnsized())
+ {
+ outArrayType = arrayType;
+ return parentVar;
+ }
+ else
+ return nullptr;
+ }
+ else if (auto declRefType = as<DeclRefType>(type))
+ {
+ if (auto aggTypeDecl = declRefType->getDeclRef().as<AggTypeDecl>())
+ {
+ auto varDecls = aggTypeDecl.getDecl()->getMembersOfType<VarDeclBase>();
+ if (varDecls.getCount() == 0)
+ return nullptr;
+ VarDeclBase* lastVarDecl = nullptr;
+ for (auto varDecl : varDecls)
+ {
+ if (isEffectivelyStatic(varDecl))
+ continue;
+ lastVarDecl = varDecl;
+ }
+ auto lastMember = _getMemberDeclRef(
+ getCurrentASTBuilder(), aggTypeDecl, lastVarDecl).as<VarDeclBase>();
+ auto varType = getType(getCurrentASTBuilder(), lastMember);
+ if (!varType)
+ return nullptr;
+ if (!seenTypes.add(type))
+ return nullptr;
+ type = varType;
+ parentVar = lastMember.getDecl();
+ continue;
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ bool isOpaqueHandleType(Type* type)
+ {
+ while (auto modifiedType = as<ModifiedType>(type))
+ type = modifiedType->getBase();
+ if (as<ResourceType>(type))
+ return true;
+ if (as<SamplerStateType>(type))
+ return true;
+ if (as<UniformParameterGroupType>(type))
+ return true;
+ if (as<HLSLStructuredBufferTypeBase>(type))
+ return true;
+ if (as<UntypedBufferResourceType>(type))
+ return true;
+ if (as<GLSLShaderStorageBufferType>(type))
+ return true;
+ if (as<FeedbackType>(type))
+ return true;
+ if (as<HLSLPatchType>(type))
+ return true;
+ if (as<HLSLStreamOutputType>(type))
+ return true;
+ if (as<MeshOutputType>(type))
+ return true;
+ return false;
+ }
+
void diagnoseCapabilityProvenance(CompilerOptionSet& optionSet, DiagnosticSink* sink, Decl* decl, CapabilityAtom atomToFind, bool optionallyNeverPrintDecl)
{
HashSet<Decl*> printedDecls;