Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/CBufferDataLayout.cpp
35266 views
//===- Target/DirectX/CBufferDataLayout.cpp - Cbuffer layout helper -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Utils to help cbuffer layout.9//10//===----------------------------------------------------------------------===//1112#include "CBufferDataLayout.h"1314#include "llvm/IR/DerivedTypes.h"15#include "llvm/IR/IRBuilder.h"1617namespace llvm {18namespace dxil {1920// Implement cbuffer layout in21// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules22class LegacyCBufferLayout {23struct LegacyStructLayout {24StructType *ST;25SmallVector<uint32_t> Offsets;26TypeSize Size = {0, false};27std::pair<uint32_t, uint32_t> getElementLegacyOffset(unsigned Idx) const {28assert(Idx < Offsets.size() && "Invalid element idx!");29uint32_t Offset = Offsets[Idx];30uint32_t Ch = Offset & (RowAlign - 1);31return std::make_pair((Offset - Ch) / RowAlign, Ch);32}33};3435public:36LegacyCBufferLayout(const DataLayout &DL) : DL(DL) {}37TypeSize getTypeAllocSizeInBytes(Type *Ty);3839private:40TypeSize applyRowAlign(TypeSize Offset, Type *EltTy);41TypeSize getTypeAllocSize(Type *Ty);42LegacyStructLayout &getStructLayout(StructType *ST);43const DataLayout &DL;44SmallDenseMap<StructType *, LegacyStructLayout> StructLayouts;45// 4 Dwords align.46static const uint32_t RowAlign = 16;47static TypeSize alignTo4Dwords(TypeSize Offset) {48return alignTo(Offset, RowAlign);49}50};5152TypeSize LegacyCBufferLayout::getTypeAllocSizeInBytes(Type *Ty) {53return getTypeAllocSize(Ty);54}5556TypeSize LegacyCBufferLayout::applyRowAlign(TypeSize Offset, Type *EltTy) {57TypeSize AlignedOffset = alignTo4Dwords(Offset);5859if (AlignedOffset == Offset)60return Offset;6162if (isa<StructType>(EltTy) || isa<ArrayType>(EltTy))63return AlignedOffset;64TypeSize Size = DL.getTypeStoreSize(EltTy);65if ((Offset + Size) > AlignedOffset)66return AlignedOffset;67else68return Offset;69}7071TypeSize LegacyCBufferLayout::getTypeAllocSize(Type *Ty) {72if (auto *ST = dyn_cast<StructType>(Ty)) {73LegacyStructLayout &Layout = getStructLayout(ST);74return Layout.Size;75} else if (auto *AT = dyn_cast<ArrayType>(Ty)) {76unsigned NumElts = AT->getNumElements();77if (NumElts == 0)78return TypeSize::getFixed(0);7980TypeSize EltSize = getTypeAllocSize(AT->getElementType());81TypeSize AlignedEltSize = alignTo4Dwords(EltSize);82// Each new element start 4 dwords aligned.83return TypeSize::getFixed(AlignedEltSize * (NumElts - 1) + EltSize);84} else {85// NOTE: Use type store size, not align to ABI on basic types for legacy86// layout.87return DL.getTypeStoreSize(Ty);88}89}9091LegacyCBufferLayout::LegacyStructLayout &92LegacyCBufferLayout::getStructLayout(StructType *ST) {93auto it = StructLayouts.find(ST);94if (it != StructLayouts.end())95return it->second;9697TypeSize Offset = TypeSize::getFixed(0);98LegacyStructLayout Layout;99Layout.ST = ST;100for (Type *EltTy : ST->elements()) {101TypeSize EltSize = getTypeAllocSize(EltTy);102if (TypeSize ScalarSize = EltTy->getScalarType()->getPrimitiveSizeInBits())103Offset = alignTo(Offset, ScalarSize >> 3);104Offset = applyRowAlign(Offset, EltTy);105Layout.Offsets.emplace_back(Offset);106Offset = Offset.getWithIncrement(EltSize);107}108Layout.Size = Offset;109StructLayouts[ST] = Layout;110return StructLayouts[ST];111}112113CBufferDataLayout::CBufferDataLayout(const DataLayout &DL, const bool IsLegacy)114: DL(DL), IsLegacyLayout(IsLegacy),115LegacyDL(IsLegacy ? std::make_unique<LegacyCBufferLayout>(DL) : nullptr) {116}117118CBufferDataLayout::~CBufferDataLayout() = default;119120llvm::TypeSize CBufferDataLayout::getTypeAllocSizeInBytes(Type *Ty) {121if (IsLegacyLayout)122return LegacyDL->getTypeAllocSizeInBytes(Ty);123else124return DL.getTypeAllocSize(Ty);125}126127} // namespace dxil128} // namespace llvm129130131