From 631c859c1015b995c4459080d661283da90ebd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= Date: Wed, 3 Dec 2025 15:14:36 +0100 Subject: [PATCH] [SPIR-V] Normalize inline SPIR-V for builtins Inline SPIR-V provides mutliple attributes with overlapping capabilities: - vk::builtin - vk::ext_input_builtin - vk::ext_output_builtin - vk::storage_class - vk::decorate The issue is that what should be syntactic sugar was not implemented as such: ext_input_builtin should be sugar for decorate + storage_class. This meant codegen has different paths depending on the attributes used, even if they should in the end have the same effect. As expected, those paths have different behaviors, and some are buggy. This commits adds a new step in sema: attribute normalization. The target idea is to `desugar` some attributes into a more basic format, but it requires large changes in CG. As of now, this commits normalizes a bit the attributes in sema, but might lift decoration+storage into ext_input_builtin. Properly doing de-sugar will require additional changes, especially around parameters & builtin through decorations which works only because codegen checks are not complete. --- .../clang/Basic/DiagnosticSemaKinds.td | 13 ++ tools/clang/include/clang/Sema/SemaHLSL.h | 2 + tools/clang/lib/SPIRV/DeclResultIdMapper.cpp | 4 + tools/clang/lib/Sema/SemaDeclAttr.cpp | 5 + tools/clang/lib/Sema/SemaHLSL.cpp | 164 ++++++++++++++++++ .../spv.inline.builtin.both.error.hlsl | 9 - .../inline-spirv/spv.raytracing.hlsl | 4 + .../spv.inline.builtin.bad.storage.hlsl | 9 + .../spv.inline.builtin.both.error.hlsl | 9 + .../spv.inline.builtin.location.hlsl | 10 ++ .../spv.inline.builtin.missing.hlsl | 8 + .../spv.inline.builtin.multiple.error.hlsl | 10 ++ .../spv.inline.builtin.multiple.input.hlsl | 9 + ....inline.builtin.multiple.input.manual.hlsl | 11 ++ ...iltin.multiple.input.storage.conflict.hlsl | 9 + ...inline.builtin.multiple.input.storage.hlsl | 10 ++ ...nline.builtin.multiple.input.storage2.hlsl | 10 ++ .../spv.inline.builtin.multiple.output.hlsl | 9 + ...inline.builtin.multiple.output.manual.hlsl | 11 ++ ...ltin.multiple.output.storage.conflict.hlsl | 10 ++ ...nline.builtin.multiple.output.storage.hlsl | 10 ++ ...line.builtin.multiple.output.storage2.hlsl | 10 ++ .../spv.inline.builtin.multiple.same.hlsl | 12 ++ .../spv.inline.location.error.hlsl | 8 + .../spv.inline.location.error2.hlsl | 8 + .../spv.inline.location.error3.hlsl | 8 + .../inline-spirv/spv.inline.location.hlsl | 9 + .../spv.inline.location.multiple.hlsl | 10 ++ 28 files changed, 392 insertions(+), 9 deletions(-) delete mode 100644 tools/clang/test/CodeGenSPIRV/inline-spirv/spv.inline.builtin.both.error.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.bad.storage.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.both.error.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.location.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.missing.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.error.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.manual.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.conflict.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage2.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.manual.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.conflict.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage2.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.same.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error2.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error3.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.hlsl create mode 100644 tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.multiple.hlsl diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 34a2195cbc..04f9788190 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8066,6 +8066,19 @@ def err_hlsl_vk_static_pointer_cast_type: Error< "vk::static_pointer_cast() content type must be base class of argument's content type">; def warn_spirv_node_shaders_experimental : Warning< "SPIR-V implementation of node shaders is experimental and subject to change">; + +def err_hlsl_spv_inline_builtin_redefinition + : Error<"%0 cannot be used on a variable already associated with the " + "built-in %1">; +def err_hlsl_spv_inline_builtin_incompatible + : Error<"%0 incompatible with the BuiltIn %1">; +def err_hlsl_spv_inline_location_redefinition + : Error<"invalid %0 : target already associated with another location %1">; +def err_hlsl_spv_inline_invalid_decoration_single_operand_missing + : Error<"decoration %0 requires 1 operand">; +def err_hlsl_spv_inline_storage_class_redefinition + : Error<"%0 cannot be used on a variable already associated to another " + "storage class %1">; // SPIRV Change Ends let CategoryName = "OpenMP Issue" in { diff --git a/tools/clang/include/clang/Sema/SemaHLSL.h b/tools/clang/include/clang/Sema/SemaHLSL.h index 80ce8ddd7d..f52d6686b7 100644 --- a/tools/clang/include/clang/Sema/SemaHLSL.h +++ b/tools/clang/include/clang/Sema/SemaHLSL.h @@ -139,6 +139,8 @@ GetBestViableFunction(clang::Sema &S, clang::SourceLocation Loc, bool ShouldSkipNRVO(clang::Sema &sema, clang::QualType returnType, clang::VarDecl *VD, clang::FunctionDecl *FD); +void NormalizeInlineSPIRVAttributes(clang::Sema &S, clang::Decl *D); + /// Processes an attribute for a declaration. /// Sema with context. /// Annotated declaration. diff --git a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp index 136b864288..54a55dc481 100644 --- a/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp +++ b/tools/clang/lib/SPIRV/DeclResultIdMapper.cpp @@ -1298,6 +1298,10 @@ SpirvVariable *DeclResultIdMapper::createExternVar(const VarDecl *var, return varInstr; const auto *bindingAttr = var->getAttr(); + + if (var->hasAttr() && !bindingAttr) + return varInstr; + resourceVars.emplace_back(varInstr, var, loc, getResourceBinding(var), bindingAttr, var->getAttr()); diff --git a/tools/clang/lib/Sema/SemaDeclAttr.cpp b/tools/clang/lib/Sema/SemaDeclAttr.cpp index 085874a0ed..f5029a2fa9 100644 --- a/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -5326,6 +5326,11 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { D->addAttr(*i); } // HLSL Change Ends + + // SPIR-V Change Starts + if (LangOpts.HLSL) + hlsl::NormalizeInlineSPIRVAttributes(*this, D); + // SPIR-V Change Ends } /// Is the given declaration allowed to use a forbidden type? diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index e9c8c90a2d..e4c6ff068d 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -48,10 +48,18 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" + +#ifdef ENABLE_SPIRV_CODEGEN +// Enables functions like spv::BuiltInToString() +#define SPV_ENABLE_UTILITY_CODE +#include "spirv/unified1/spirv.hpp11" +#endif + #include #include #include #include +#include enum ArBasicKind { AR_BASIC_BOOL, @@ -14593,6 +14601,162 @@ void ValidateDispatchGridValues(DiagnosticsEngine &Diags, << A.getName() << A.getRange(); } +void hlsl::NormalizeInlineSPIRVAttributes(Sema &S, Decl *D) { +#ifdef ENABLE_SPIRV_CODEGEN + // Collecting the values that can be set across multiple attributes. + std::optional> StorageClass; + std::optional> Location; + std::optional> BuiltIn; + + // Vector collecting all the other attributes. + clang::AttrVec NewAttrs; + + for (auto *A : D->attrs()) { + if (auto *DA = dyn_cast(A)) { + spv::Decoration Decoration = spv::Decoration(DA->getDecorate()); + if (Decoration == spv::Decoration::Location) { + if (DA->literals_size() != 1) { + S.Diags.Report( + A->getLocation(), + diag:: + err_hlsl_spv_inline_invalid_decoration_single_operand_missing) + << "Location"; + return; + } + unsigned Index = *DA->literals_begin(); + if (Location.has_value() && Location->first != Index) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_location_redefinition) + << DA << Location->first; + return; + } + Location = {Index, DA->getLocation()}; + } else if (Decoration == spv::Decoration::BuiltIn) { + if (DA->literals_size() != 1) { + S.Diags.Report( + A->getLocation(), + diag:: + err_hlsl_spv_inline_invalid_decoration_single_operand_missing) + << "BuiltIn"; + return; + } + spv::BuiltIn ID = spv::BuiltIn(*DA->literals_begin()); + if (BuiltIn.has_value() && ID != BuiltIn->first) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_builtin_redefinition) + << DA << spv::BuiltInToString(BuiltIn->first); + return; + } + BuiltIn = {ID, DA->getLocation()}; + } else { + NewAttrs.push_back(A); + } + } else if (auto *SCA = dyn_cast(A)) { + spv::StorageClass SC = spv::StorageClass(SCA->getStclass()); + if (StorageClass.has_value() && StorageClass->first != SC) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_storage_class_redefinition) + << SCA << spv::StorageClassToString(StorageClass->first); + return; + } + StorageClass = {SC, SCA->getLocation()}; + } else if (auto *LA = dyn_cast(A)) { + if (Location.has_value() && + Location->first != static_cast(LA->getNumber())) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_location_redefinition) + << LA << Location->first; + return; + } + Location = {LA->getNumber(), LA->getLocation()}; + } else if (auto *BA = dyn_cast(A)) { + if (StorageClass.has_value() && + StorageClass->first != spv::StorageClass::Output) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_storage_class_redefinition) + << BA << spv::StorageClassToString(StorageClass->first); + return; + } + StorageClass = {spv::StorageClass::Output, BA->getLocation()}; + + spv::BuiltIn ID = spv::BuiltIn(BA->getBuiltInID()); + if (BuiltIn.has_value() && ID != BuiltIn->first) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_builtin_redefinition) + << BA << spv::BuiltInToString(BuiltIn->first); + return; + } + BuiltIn = {ID, BA->getLocation()}; + + } else if (auto *BA = dyn_cast(A)) { + if (StorageClass.has_value() && + StorageClass->first != spv::StorageClass::Input) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_storage_class_redefinition) + << BA << spv::StorageClassToString(StorageClass->first); + return; + } + StorageClass = {spv::StorageClass::Input, BA->getLocation()}; + + spv::BuiltIn ID = spv::BuiltIn(BA->getBuiltInID()); + if (BuiltIn.has_value() && ID != BuiltIn->first) { + S.Diags.Report(A->getLocation(), + diag::err_hlsl_spv_inline_builtin_redefinition) + << BA << spv::BuiltInToString(BuiltIn->first); + return; + } + BuiltIn = {ID, BA->getLocation()}; + } else { + NewAttrs.push_back(A); + } + } + + if (BuiltIn.has_value()) { + // Location should not be set if a BuiltIn is requested. + if (Location.has_value()) { + S.Diags.Report(D->getLocation(), + diag::err_hlsl_spv_inline_builtin_incompatible) + << "Location" << spv::BuiltInToString(BuiltIn->first); + return; + } + + // BuiltIn requires either Input or Output storage class. + if (StorageClass.has_value() && + StorageClass->first == spv::StorageClass::Input) + NewAttrs.push_back(new (S.Context) VKExtBuiltinInputAttr( + BuiltIn->second, S.Context, static_cast(BuiltIn->first), + 0)); + else if (StorageClass.has_value() && + StorageClass->first == spv::StorageClass::Output) + NewAttrs.push_back(new (S.Context) VKExtBuiltinOutputAttr( + BuiltIn->second, S.Context, static_cast(BuiltIn->first), + 0)); + else if (isa(D) || isa(D)) { + unsigned BuiltInID = static_cast(BuiltIn->first); + NewAttrs.push_back(new (S.Context) VKDecorateExtAttr( + BuiltIn->second, S.Context, /* BuiltIn */ 11, &BuiltInID, 1, 0)); + } else + S.Diags.Report(D->getLocation(), + diag::err_hlsl_spv_inline_builtin_incompatible) + << std::string("StorageClass ") + + spv::StorageClassToString(StorageClass->first) + << spv::BuiltInToString(BuiltIn->first); + } else { + if (Location.has_value()) + NewAttrs.push_back(new (S.Context) VKLocationAttr( + Location->second, S.Context, static_cast(Location->first), + 0)); + if (StorageClass.has_value()) + NewAttrs.push_back(new (S.Context) VKStorageClassExtAttr( + StorageClass->second, S.Context, + static_cast(StorageClass->first), 0)); + } + + D->dropAttrs(); + D->setAttrs(NewAttrs); +#endif // ENABLE_SPIRV_CODEGEN +} + void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A, bool &Handled) { DXASSERT_NOMSG(D != nullptr); diff --git a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.inline.builtin.both.error.hlsl b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.inline.builtin.both.error.hlsl deleted file mode 100644 index f7983678db..0000000000 --- a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.inline.builtin.both.error.hlsl +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: not %dxc -T ps_6_0 -E main -fcgl %s -spirv 2>&1 | FileCheck %s - -// CHECK: error: vk::ext_builtin_input cannot be used together with vk::ext_builtin_output -[[vk::ext_builtin_input(/* NumWorkgroups */ 24)]] -[[vk::ext_builtin_output(/* NumWorkgroups */ 24)]] -static uint3 invalid; - -void main() { -} diff --git a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.raytracing.hlsl b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.raytracing.hlsl index d01cd39fea..2aa502708e 100644 --- a/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.raytracing.hlsl +++ b/tools/clang/test/CodeGenSPIRV/inline-spirv/spv.raytracing.hlsl @@ -2,6 +2,8 @@ // CHECK-DAG: OpCapability RuntimeDescriptorArray // CHECK-DAG: OpCapability RayQueryKHR +// CHECK-DAG: OpDecorate %MyScene DescriptorSet 3 +// CHECK-DAG: OpDecorate %MyScene Binding 2 using A = vk::SpirvOpaqueType; // CHECK: %[[name:[^ ]+]] = OpTypeAccelerationStructureKHR @@ -12,6 +14,8 @@ using RA [[vk::ext_capability(/* RuntimeDescriptorArray */ 5302)]] = vk::SpirvOp // CHECK: %[[ptr:[^ ]+]] = OpTypePointer UniformConstant %[[rarr]] // CHECK: %MyScene = OpVariable %[[ptr]] UniformConstant [[vk::ext_storage_class(0)]] +[[vk::ext_decorate(/* Binding */ 33, 2)]] +[[vk::ext_decorate(/* DescriptorSet */ 34, 3)]] RA MyScene; [numthreads(1, 1, 1)] diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.bad.storage.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.bad.storage.hlsl new file mode 100644 index 0000000000..4abd608074 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.bad.storage.hlsl @@ -0,0 +1,9 @@ +// RUN: %dxc -T cs_6_0 -E main -fcgl %s -spirv -verify + +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_storage_class(/* UniformConstant */ 0)]] +// expected-error@+1{{StorageClass UniformConstant incompatible with the BuiltIn WorkgroupId}} +static uint3 input; + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.both.error.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.both.error.hlsl new file mode 100644 index 0000000000..89d2b873cc --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.both.error.hlsl @@ -0,0 +1,9 @@ +// RUN: %dxc -T ps_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{'ext_builtin_input' cannot be used on a variable already associated to another storage class Output}} +[[vk::ext_builtin_input(/* NumWorkgroups */ 24)]] +[[vk::ext_builtin_output(/* NumWorkgroups */ 24)]] +static uint3 invalid; + +void main() { +} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.location.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.location.hlsl new file mode 100644 index 0000000000..3db779ed1e --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.location.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T cs_6_0 -E main -fcgl %s -spirv -verify + +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_builtin_input(/* WorkgroupId */ 26)]] +[[vk::ext_decorate(/* Location */ 30, 0)]] +// expected-error@+1{{Location incompatible with the BuiltIn WorkgroupId}} +static uint3 input; + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.missing.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.missing.hlsl new file mode 100644 index 0000000000..caa0fcb91f --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.missing.hlsl @@ -0,0 +1,8 @@ +// RUN: %dxc -T cs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{decoration BuiltIn requires 1 operand}} +[[vk::ext_decorate(/* BuiltIn */ 11)]] +static uint3 input; + +[numthreads(1, 1, 1)] +void main() {} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.error.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.error.hlsl new file mode 100644 index 0000000000..6d9e4b00fd --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.error.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T cs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{'ext_decorate' cannot be used on a variable already associated with the built-in LocalInvocationId}} +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_decorate(/* BuiltIn */ 11, /* LocalInvocationId */ 27)]] +[[vk::ext_storage_class(/* Input */ 1)]] +static uint3 invalid; + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.hlsl new file mode 100644 index 0000000000..b156c4ff09 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.hlsl @@ -0,0 +1,9 @@ +// RUN: %dxc -T cs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{'ext_builtin_input' cannot be used on a variable already associated with the built-in WorkgroupId}} +[[vk::ext_builtin_input(/* NumWorkgroups */ 24)]] +[[vk::ext_builtin_input(/* WorkgroupId */ 26)]] +static uint3 invalid; + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.manual.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.manual.hlsl new file mode 100644 index 0000000000..215b1ef590 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.manual.hlsl @@ -0,0 +1,11 @@ +// RUN: %dxc -T cs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_builtin_input(/* WorkgroupId */ 26)]] +static uint3 input; + +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:14 input 'uint3':'vector' static +// CHECK-NEXT: VKExtBuiltinInputAttr 0x{{.+}} 26 + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.conflict.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.conflict.hlsl new file mode 100644 index 0000000000..f6fd2bbfea --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.conflict.hlsl @@ -0,0 +1,9 @@ +// RUN: %dxc -T cs_6_9 -E main -spirv %s -verify + +// expected-error@+1{{'ext_storage_class' cannot be used on a variable already associated to another storage class Input}} +[[vk::ext_storage_class(/* Output */ 3)]] +[[vk::ext_builtin_input(/* WorkgroupId */ 26)]] +static uint3 input; + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.hlsl new file mode 100644 index 0000000000..cacba6c564 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T cs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_storage_class(/* Input */ 1)]] +[[vk::ext_builtin_input(/* WorkgroupId */ 26)]] +static uint3 input; +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:14 input 'uint3':'vector' static +// CHECK-NEXT: VKExtBuiltinInputAttr 0x{{.+}} 26 + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage2.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage2.hlsl new file mode 100644 index 0000000000..958bac4dec --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.input.storage2.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T cs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_builtin_input(/* WorkgroupId */ 26)]] +[[vk::ext_storage_class(/* Input */ 1)]] +static uint3 input; +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:14 input 'uint3':'vector' static +// CHECK-NEXT: VKExtBuiltinInputAttr 0x{{.+}} 26 + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.hlsl new file mode 100644 index 0000000000..087ead35d0 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.hlsl @@ -0,0 +1,9 @@ +// RUN: %dxc -T cs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{'ext_builtin_output' cannot be used on a variable already associated with the built-in WorkgroupId}} +[[vk::ext_builtin_output(/* NumWorkgroups */ 24)]] +[[vk::ext_builtin_output(/* WorkgroupId */ 26)]] +static uint3 invalid; + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.manual.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.manual.hlsl new file mode 100644 index 0000000000..8d380b2b50 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.manual.hlsl @@ -0,0 +1,11 @@ +// RUN: %dxc -T cs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_builtin_output(/* WorkgroupId */ 26)]] +static uint3 input; + +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:14 input 'uint3':'vector' static +// CHECK-NEXT: VKExtBuiltinOutputAttr 0x{{.+}} 26 + +[numthreads(1, 1, 1)] +void main() { } diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.conflict.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.conflict.hlsl new file mode 100644 index 0000000000..02884ae65f --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.conflict.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T vs_6_9 -E main -spirv %s -verify + +// expected-error@+1{{'ext_storage_class' cannot be used on a variable already associated to another storage class Output}} +[[vk::ext_storage_class(/* Input */ 1)]] +[[vk::ext_builtin_output(/* Position */ 0)]] +static float4 output; + +void main() { +} + diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.hlsl new file mode 100644 index 0000000000..6ff9dfb552 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T vs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_storage_class(/* Output */ 3)]] +[[vk::ext_builtin_output(/* Position */ 0)]] +static float4 output; +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:15 output 'float4':'vector' static +// CHECK-NEXT: VKExtBuiltinOutputAttr 0x{{.+}} 0 + +void main() { +} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage2.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage2.hlsl new file mode 100644 index 0000000000..2ed27bfc10 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.output.storage2.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T vs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_builtin_output(/* Position */ 0)]] +[[vk::ext_storage_class(/* Output */ 3)]] +static float4 output; +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:15 output 'float4':'vector' static +// CHECK-NEXT: VKExtBuiltinOutputAttr 0x{{.+}} 0 + +void main() { +} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.same.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.same.hlsl new file mode 100644 index 0000000000..709b9d5322 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.builtin.multiple.same.hlsl @@ -0,0 +1,12 @@ +// RUN: %dxc -T cs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_decorate(/* BuiltIn */ 11, /* WorkgroupId */ 26)]] +[[vk::ext_storage_class(/* Input */ 1)]] +static uint3 input; + +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:14 input 'uint3':'vector' static +// CHECK-NEXT: VKExtBuiltinInputAttr 0x{{.+}} 26 + +[numthreads(1, 1, 1)] +void main() {} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error.hlsl new file mode 100644 index 0000000000..caf17f07fb --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error.hlsl @@ -0,0 +1,8 @@ +// RUN: %dxc -T vs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{invalid 'ext_decorate' : target already associated with another location 1}} +[[vk::ext_decorate(/* Location */ 30, 0)]] +[[vk::ext_decorate(/* Location */ 30, 1)]] +static float4 output; + +void main() {} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error2.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error2.hlsl new file mode 100644 index 0000000000..acb9820f75 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error2.hlsl @@ -0,0 +1,8 @@ +// RUN: %dxc -T vs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{'location' attribute only applies to functions, parameters, and fields}} +[[vk::location(0)]] +[[vk::ext_decorate(/* Location */ 30, 1)]] +static float4 output; + +void main() {} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error3.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error3.hlsl new file mode 100644 index 0000000000..a236db2ab8 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.error3.hlsl @@ -0,0 +1,8 @@ +// RUN: %dxc -T vs_6_0 -E main -fcgl %s -spirv -verify + +// expected-error@+1{{decoration Location requires 1 operand}} +[[vk::ext_decorate(/* Location */ 30)]] +[[vk::ext_decorate(/* Location */ 30, 1)]] +static float4 output; + +void main() {} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.hlsl new file mode 100644 index 0000000000..2e9e2393fa --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.hlsl @@ -0,0 +1,9 @@ +// RUN: %dxc -T vs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_decorate(/* Location */ 30, 0)]] +static float4 output; + +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:15 output 'float4':'vector' static +// CHECK-NEXT: VKLocationAttr 0x{{.+}} 0 + +void main() {} diff --git a/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.multiple.hlsl b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.multiple.hlsl new file mode 100644 index 0000000000..85c43f1ddb --- /dev/null +++ b/tools/clang/test/SemaHLSL/inline-spirv/spv.inline.location.multiple.hlsl @@ -0,0 +1,10 @@ +// RUN: %dxc -T vs_6_9 -E main -ast-dump -spirv %s | FileCheck %s + +[[vk::ext_decorate(/* Location */ 30, 1)]] +[[vk::ext_decorate(/* Location */ 30, 1)]] +static float4 output; + +// CHECK: VarDecl 0x{{.+}} <{{.+}}> col:15 output 'float4':'vector' static +// CHECK-NEXT: VKLocationAttr 0x{{.+}} 1 + +void main() {}