[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -89,14 +99,57 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( RecordTypes.pop_back(); for (const auto *FD : RT->getDecl()->fields()) { - assert((!Packoffsets || Index < Packoffsets->size()) && - "number of elements in layout struct does not " - "match number of packoffset annotations"); + unsigned FieldOffset = UINT_MAX; + llvm::Type *FieldType = nullptr; + + if (Packoffsets) { +// have packoffset/register(c#) annotations +assert(Index < Packoffsets->size() && + "number of elements in layout struct does not match number of " + "packoffset annotations"); +int PO = (*Packoffsets)[Index++]; +if (PO != -1) { + if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO)) +return nullptr; +} else { + // No packoffset/register(cX) annotation on this field; + // Delay the layout until after all of the other elements + // annotated with packoffsets/register(cX) are processed. + DelayLayoutFields.emplace_back(FD, LayoutElements.size()); + // reserve space for this field in the layout vector and elements list + Layout.push_back(UINT_MAX); + LayoutElements.push_back(nullptr); + continue; +} + } else { +if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) + return nullptr; + } + + assert(FieldOffset != UINT_MAX && FieldType != nullptr); + Layout.push_back((unsigned)FieldOffset); alsepkow wrote: Left over cast from a previous revision? Layout contains unsigned ints. https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -174,21 +176,45 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) { return cast(QT.getTypePtr()); } +// Iterates over all declarations in the HLSL buffer and based on the +// packoffset or register(c#) annotations it fills outs the Layout +// vector with the user-specified layout offsets. +// The buffer offsets can be specified 2 ways: +// 1. declarations in cbuffer {} block can have a packoffset annotation +//(translates to HLSLPackOffsetAttr) +// 2. default constant buffer declarations at global scope can have +//register(c#) annotations (translates to HLSLResourceBindingAttr with +//RegisterType::C) +// It is not guaranteed that all declarations in a buffer have an annotation. +// For those where it is not specified a -1 value is added to the Layout +// vector. In the final layout these declarations will be placed at the end +// of the HLSL buffer after all of the elements with specified offset. static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl, - SmallVector &Layout) { + SmallVector &Layout) { assert(Layout.empty() && "expected empty vector for layout"); assert(BufDecl->hasValidPackoffset()); - for (Decl *D : BufDecl->decls()) { + for (Decl *D : BufDecl->buffer_decls()) { alsepkow wrote: nit: On formatting, it sounds like the llvm repo prefers 'auto *name' for for loops? https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -174,21 +176,45 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) { return cast(QT.getTypePtr()); } +// Iterates over all declarations in the HLSL buffer and based on the +// packoffset or register(c#) annotations it fills outs the Layout alsepkow wrote: Found it 🥳 [dx-graphics-hlsl-variable-register](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-register ) https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -174,21 +176,45 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) { return cast(QT.getTypePtr()); } +// Iterates over all declarations in the HLSL buffer and based on the +// packoffset or register(c#) annotations it fills outs the Layout +// vector with the user-specified layout offsets. +// The buffer offsets can be specified 2 ways: +// 1. declarations in cbuffer {} block can have a packoffset annotation +//(translates to HLSLPackOffsetAttr) +// 2. default constant buffer declarations at global scope can have +//register(c#) annotations (translates to HLSLResourceBindingAttr with +//RegisterType::C) +// It is not guaranteed that all declarations in a buffer have an annotation. +// For those where it is not specified a -1 value is added to the Layout +// vector. In the final layout these declarations will be placed at the end +// of the HLSL buffer after all of the elements with specified offset. static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl, - SmallVector &Layout) { + SmallVector &Layout) { assert(Layout.empty() && "expected empty vector for layout"); assert(BufDecl->hasValidPackoffset()); - for (Decl *D : BufDecl->decls()) { + for (Decl *D : BufDecl->buffer_decls()) { if (isa(D) || isa(D)) { continue; } VarDecl *VD = dyn_cast(D); if (!VD || VD->getType().getAddressSpace() != LangAS::hlsl_constant) continue; -assert(VD->hasAttr() && - "expected packoffset attribute on every declaration"); -size_t Offset = VD->getAttr()->getOffsetInBytes(); +size_t Offset = -1; alsepkow wrote: size_t is unsigned. You should use something like SIZE_MAX instead. Or 0? https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -89,14 +99,57 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( RecordTypes.pop_back(); for (const auto *FD : RT->getDecl()->fields()) { - assert((!Packoffsets || Index < Packoffsets->size()) && - "number of elements in layout struct does not " - "match number of packoffset annotations"); + unsigned FieldOffset = UINT_MAX; + llvm::Type *FieldType = nullptr; + + if (Packoffsets) { +// have packoffset/register(c#) annotations +assert(Index < Packoffsets->size() && + "number of elements in layout struct does not match number of " + "packoffset annotations"); +int PO = (*Packoffsets)[Index++]; alsepkow wrote: P0 should be a const, I think? I noticed we don't really use that pattern in DXC but it looks like it is used here. https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -89,14 +99,57 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( RecordTypes.pop_back(); for (const auto *FD : RT->getDecl()->fields()) { - assert((!Packoffsets || Index < Packoffsets->size()) && - "number of elements in layout struct does not " - "match number of packoffset annotations"); + unsigned FieldOffset = UINT_MAX; + llvm::Type *FieldType = nullptr; + + if (Packoffsets) { +// have packoffset/register(c#) annotations +assert(Index < Packoffsets->size() && + "number of elements in layout struct does not match number of " + "packoffset annotations"); +int PO = (*Packoffsets)[Index++]; +if (PO != -1) { + if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO)) +return nullptr; +} else { + // No packoffset/register(cX) annotation on this field; + // Delay the layout until after all of the other elements + // annotated with packoffsets/register(cX) are processed. + DelayLayoutFields.emplace_back(FD, LayoutElements.size()); + // reserve space for this field in the layout vector and elements list + Layout.push_back(UINT_MAX); + LayoutElements.push_back(nullptr); + continue; +} + } else { +if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) + return nullptr; + } + + assert(FieldOffset != UINT_MAX && FieldType != nullptr); + Layout.push_back((unsigned)FieldOffset); + LayoutElements.push_back(FieldType); +} + } - if (!layoutField(FD, EndOffset, Layout, LayoutElements, - Packoffsets ? (*Packoffsets)[Index] : -1)) + // process delayed layouts + if (!DelayLayoutFields.empty()) { +for (auto I : DelayLayoutFields) { + const FieldDecl *FD = I.first; + unsigned IndexInLayoutElements = I.second; alsepkow wrote: const? https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -89,14 +99,57 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( RecordTypes.pop_back(); for (const auto *FD : RT->getDecl()->fields()) { - assert((!Packoffsets || Index < Packoffsets->size()) && - "number of elements in layout struct does not " - "match number of packoffset annotations"); + unsigned FieldOffset = UINT_MAX; + llvm::Type *FieldType = nullptr; + + if (Packoffsets) { +// have packoffset/register(c#) annotations +assert(Index < Packoffsets->size() && + "number of elements in layout struct does not match number of " + "packoffset annotations"); +int PO = (*Packoffsets)[Index++]; +if (PO != -1) { + if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO)) +return nullptr; +} else { + // No packoffset/register(cX) annotation on this field; + // Delay the layout until after all of the other elements + // annotated with packoffsets/register(cX) are processed. + DelayLayoutFields.emplace_back(FD, LayoutElements.size()); + // reserve space for this field in the layout vector and elements list + Layout.push_back(UINT_MAX); + LayoutElements.push_back(nullptr); + continue; +} + } else { +if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) + return nullptr; + } + + assert(FieldOffset != UINT_MAX && FieldType != nullptr); + Layout.push_back((unsigned)FieldOffset); + LayoutElements.push_back(FieldType); +} + } - if (!layoutField(FD, EndOffset, Layout, LayoutElements, - Packoffsets ? (*Packoffsets)[Index] : -1)) + // process delayed layouts + if (!DelayLayoutFields.empty()) { +for (auto I : DelayLayoutFields) { + const FieldDecl *FD = I.first; + unsigned IndexInLayoutElements = I.second; + // the first item in layout vector is size, so we need to offset the index + // by 1 + unsigned IndexInLayout = IndexInLayoutElements + 1; + assert(Layout[IndexInLayout] == UINT_MAX && + LayoutElements[IndexInLayoutElements] == nullptr); + + unsigned FieldOffset = UINT_MAX; + llvm::Type *FieldType = nullptr; + if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) return nullptr; - Index++; + + Layout[IndexInLayout] = (unsigned)FieldOffset; alsepkow wrote: Cast no longer needed https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -58,9 +60,15 @@ namespace CodeGen { // classes) and calls layoutField to converts each field to its corresponding // LLVM type and to calculate its HLSL constant buffer layout. Any embedded // structs (or arrays of structs) are converted to target layout types as well. +// +// When Packoffsets are specified the elements will be placed based on the +// user-specified offsets. Not all elements must have a packoffset/register(c#) +// annotation though. For those that don't, the Packoffsets array will constain alsepkow wrote: nit: typo, 'contain' https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -174,21 +176,45 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) { return cast(QT.getTypePtr()); } +// Iterates over all declarations in the HLSL buffer and based on the +// packoffset or register(c#) annotations it fills outs the Layout alsepkow wrote: Just curious, what is 'register(c#)' annotation? I didn't get any hits trying to search it online or with copilot. https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement explicit layout for default constant buffer ($Globals) (PR #128991)
@@ -89,14 +99,57 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( RecordTypes.pop_back(); for (const auto *FD : RT->getDecl()->fields()) { - assert((!Packoffsets || Index < Packoffsets->size()) && - "number of elements in layout struct does not " - "match number of packoffset annotations"); + unsigned FieldOffset = UINT_MAX; + llvm::Type *FieldType = nullptr; + + if (Packoffsets) { +// have packoffset/register(c#) annotations +assert(Index < Packoffsets->size() && + "number of elements in layout struct does not match number of " + "packoffset annotations"); +int PO = (*Packoffsets)[Index++]; +if (PO != -1) { + if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO)) +return nullptr; +} else { + // No packoffset/register(cX) annotation on this field; + // Delay the layout until after all of the other elements + // annotated with packoffsets/register(cX) are processed. + DelayLayoutFields.emplace_back(FD, LayoutElements.size()); + // reserve space for this field in the layout vector and elements list + Layout.push_back(UINT_MAX); + LayoutElements.push_back(nullptr); + continue; +} + } else { +if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) + return nullptr; + } + + assert(FieldOffset != UINT_MAX && FieldType != nullptr); + Layout.push_back((unsigned)FieldOffset); + LayoutElements.push_back(FieldType); +} + } - if (!layoutField(FD, EndOffset, Layout, LayoutElements, - Packoffsets ? (*Packoffsets)[Index] : -1)) + // process delayed layouts + if (!DelayLayoutFields.empty()) { +for (auto I : DelayLayoutFields) { + const FieldDecl *FD = I.first; + unsigned IndexInLayoutElements = I.second; alsepkow wrote: a few other variables in this block could also be const. https://github.com/llvm/llvm-project/pull/128991 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL][NFC] Update HLSL AST tests to be more readable (PR #130910)
https://github.com/alsepkow approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/130910 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits