Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/CBufferDataLayout.cpp
35266 views
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-exception
6
//
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
18
namespace llvm {
19
namespace dxil {
20
21
// Implement cbuffer layout in
22
// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
23
class 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
36
public:
37
LegacyCBufferLayout(const DataLayout &DL) : DL(DL) {}
38
TypeSize getTypeAllocSizeInBytes(Type *Ty);
39
40
private:
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
53
TypeSize LegacyCBufferLayout::getTypeAllocSizeInBytes(Type *Ty) {
54
return getTypeAllocSize(Ty);
55
}
56
57
TypeSize 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
else
69
return Offset;
70
}
71
72
TypeSize 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 legacy
87
// layout.
88
return DL.getTypeStoreSize(Ty);
89
}
90
}
91
92
LegacyCBufferLayout::LegacyStructLayout &
93
LegacyCBufferLayout::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
114
CBufferDataLayout::CBufferDataLayout(const DataLayout &DL, const bool IsLegacy)
115
: DL(DL), IsLegacyLayout(IsLegacy),
116
LegacyDL(IsLegacy ? std::make_unique<LegacyCBufferLayout>(DL) : nullptr) {
117
}
118
119
CBufferDataLayout::~CBufferDataLayout() = default;
120
121
llvm::TypeSize CBufferDataLayout::getTypeAllocSizeInBytes(Type *Ty) {
122
if (IsLegacyLayout)
123
return LegacyDL->getTypeAllocSizeInBytes(Ty);
124
else
125
return DL.getTypeAllocSize(Ty);
126
}
127
128
} // namespace dxil
129
} // namespace llvm
130
131