brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 3ebd7a2 Raw
130 lines · cpp
1//===- Target/DirectX/CBufferDataLayout.cpp - Cbuffer layout helper -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Utils to help cbuffer layout.10//11//===----------------------------------------------------------------------===//12 13#include "CBufferDataLayout.h"14 15#include "llvm/IR/DerivedTypes.h"16#include "llvm/IR/IRBuilder.h"17 18namespace llvm {19namespace dxil {20 21// Implement cbuffer layout in22// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules23class LegacyCBufferLayout {24  struct LegacyStructLayout {25    StructType *ST;26    SmallVector<uint32_t> Offsets;27    TypeSize Size = {0, false};28    std::pair<uint32_t, uint32_t> getElementLegacyOffset(unsigned Idx) const {29      assert(Idx < Offsets.size() && "Invalid element idx!");30      uint32_t Offset = Offsets[Idx];31      uint32_t Ch = Offset & (RowAlign - 1);32      return std::make_pair((Offset - Ch) / RowAlign, Ch);33    }34  };35 36public:37  LegacyCBufferLayout(const DataLayout &DL) : DL(DL) {}38  TypeSize getTypeAllocSizeInBytes(Type *Ty);39 40private:41  TypeSize applyRowAlign(TypeSize Offset, Type *EltTy);42  TypeSize getTypeAllocSize(Type *Ty);43  LegacyStructLayout &getStructLayout(StructType *ST);44  const DataLayout &DL;45  SmallDenseMap<StructType *, LegacyStructLayout> StructLayouts;46  // 4 Dwords align.47  static const uint32_t RowAlign = 16;48  static TypeSize alignTo4Dwords(TypeSize Offset) {49    return alignTo(Offset, RowAlign);50  }51};52 53TypeSize LegacyCBufferLayout::getTypeAllocSizeInBytes(Type *Ty) {54  return getTypeAllocSize(Ty);55}56 57TypeSize LegacyCBufferLayout::applyRowAlign(TypeSize Offset, Type *EltTy) {58  TypeSize AlignedOffset = alignTo4Dwords(Offset);59 60  if (AlignedOffset == Offset)61    return Offset;62 63  if (isa<StructType>(EltTy) || isa<ArrayType>(EltTy))64    return AlignedOffset;65  TypeSize Size = DL.getTypeStoreSize(EltTy);66  if ((Offset + Size) > AlignedOffset)67    return AlignedOffset;68  else69    return Offset;70}71 72TypeSize LegacyCBufferLayout::getTypeAllocSize(Type *Ty) {73  if (auto *ST = dyn_cast<StructType>(Ty)) {74    LegacyStructLayout &Layout = getStructLayout(ST);75    return Layout.Size;76  } else if (auto *AT = dyn_cast<ArrayType>(Ty)) {77    unsigned NumElts = AT->getNumElements();78    if (NumElts == 0)79      return TypeSize::getFixed(0);80 81    TypeSize EltSize = getTypeAllocSize(AT->getElementType());82    TypeSize AlignedEltSize = alignTo4Dwords(EltSize);83    // Each new element start 4 dwords aligned.84    return TypeSize::getFixed(AlignedEltSize * (NumElts - 1) + EltSize);85  } else {86    // NOTE: Use type store size, not align to ABI on basic types for legacy87    // layout.88    return DL.getTypeStoreSize(Ty);89  }90}91 92LegacyCBufferLayout::LegacyStructLayout &93LegacyCBufferLayout::getStructLayout(StructType *ST) {94  auto it = StructLayouts.find(ST);95  if (it != StructLayouts.end())96    return it->second;97 98  TypeSize Offset = TypeSize::getFixed(0);99  LegacyStructLayout Layout;100  Layout.ST = ST;101  for (Type *EltTy : ST->elements()) {102    TypeSize EltSize = getTypeAllocSize(EltTy);103    if (TypeSize ScalarSize = EltTy->getScalarType()->getPrimitiveSizeInBits())104      Offset = alignTo(Offset, ScalarSize >> 3);105    Offset = applyRowAlign(Offset, EltTy);106    Layout.Offsets.emplace_back(Offset);107    Offset = Offset.getWithIncrement(EltSize);108  }109  Layout.Size = Offset;110  StructLayouts[ST] = Layout;111  return StructLayouts[ST];112}113 114CBufferDataLayout::CBufferDataLayout(const DataLayout &DL, const bool IsLegacy)115    : DL(DL), IsLegacyLayout(IsLegacy),116      LegacyDL(IsLegacy ? std::make_unique<LegacyCBufferLayout>(DL) : nullptr) {117}118 119CBufferDataLayout::~CBufferDataLayout() = default;120 121llvm::TypeSize CBufferDataLayout::getTypeAllocSizeInBytes(Type *Ty) {122  if (IsLegacyLayout)123    return LegacyDL->getTypeAllocSizeInBytes(Ty);124  else125    return DL.getTypeAllocSize(Ty);126}127 128} // namespace dxil129} // namespace llvm130