diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/include/clang/Basic/Attr.td index 446f6c12b..8a7e6a60b 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -914,6 +914,13 @@ def VKPushConstant : InheritableAttr { let Documentation = [Undocumented]; } +def VKOffset : InheritableAttr { + let Spellings = [CXX11<"vk", "offset">]; + let Args = [IntArgument<"Offset">]; + let LangOpts = [SPIRV]; + let Documentation = [Undocumented]; +} + // SPIRV Change Ends def C11NoReturn : InheritableAttr { diff --git a/tools/clang/lib/SPIRV/TypeTranslator.cpp b/tools/clang/lib/SPIRV/TypeTranslator.cpp index 1773fbda8..3042d2420 100644 --- a/tools/clang/lib/SPIRV/TypeTranslator.cpp +++ b/tools/clang/lib/SPIRV/TypeTranslator.cpp @@ -619,7 +619,11 @@ TypeTranslator::getLayoutDecorations(const DeclContext *decl, LayoutRule rule) { getAlignmentAndSize(fieldType, rule, isRowMajor, &stride); // Each structure-type member must have an Offset Decoration. - roundToPow2(&offset, memberAlignment); + const auto *offsetAttr = field->getAttr(); + if (offsetAttr) + offset = offsetAttr->getOffset(); + else + roundToPow2(&offset, memberAlignment); decorations.push_back(Decoration::getOffset(*spirvContext, offset, index)); offset += memberSize; diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index abd8c263f..ff65d88dd 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -10381,6 +10381,10 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A, declAttr = ::new (S.Context) VKPushConstantAttr(A.getRange(), S.Context, A.getAttributeSpellingListIndex()); break; + case AttributeList::AT_VKOffset: + declAttr = ::new (S.Context) VKOffsetAttr(A.getRange(), S.Context, + ValidateAttributeIntArg(S, A), A.getAttributeSpellingListIndex()); + break; default: Handled = false; return; diff --git a/tools/clang/test/CodeGenSPIRV/vk.push-constant.offset.hlsl b/tools/clang/test/CodeGenSPIRV/vk.push-constant.offset.hlsl new file mode 100644 index 000000000..582ca59ba --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/vk.push-constant.offset.hlsl @@ -0,0 +1,20 @@ +// Run: %dxc -T vs_6_0 -E main + +// CHECK: OpMemberDecorate %type_PushConstant_S 0 Offset 0 +// CHECK: OpMemberDecorate %type_PushConstant_S 1 Offset 8 +// CHECK: OpMemberDecorate %type_PushConstant_S 2 Offset 32 + +struct S { + float a; + [[vk::offset(8)]] + float2 b; + [[vk::offset(32)]] + float4 f; +}; + +[[vk::push_constant]] +S pcs1; + +float main() : A { + return 1.0; +} diff --git a/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp index 18165698f..aa3818658 100644 --- a/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp +++ b/tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp @@ -1035,6 +1035,7 @@ TEST_F(FileTest, VulkanStructuredBufferCounter) { } TEST_F(FileTest, VulkanPushConstant) { runFileTest("vk.push-constant.hlsl"); } +TEST_F(FileTest, VulkanPushConstantOffset) { runFileTest("vk.push-constant.offset.hlsl"); } TEST_F(FileTest, VulkanMultiplePushConstant) { runFileTest("vk.push-constant.multiple.hlsl", FileTest::Expect::Failure); }