[clang] [HLSL] Codegen for `cbuffer` declarations without embedded arrays or structs (PR #119755)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 17 12:14:04 PST 2024
================
@@ -54,69 +54,110 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey);
DXILValMD->addOperand(Val);
}
+
void addDisableOptimizations(llvm::Module &M) {
StringRef Key = "dx.disable_optimizations";
M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1);
}
-// cbuffer will be translated into global variable in special address space.
-// If translate into C,
-// cbuffer A {
-// float a;
-// float b;
-// }
-// float foo() { return a + b; }
-//
-// will be translated into
-//
-// struct A {
-// float a;
-// float b;
-// } cbuffer_A __attribute__((address_space(4)));
-// float foo() { return cbuffer_A.a + cbuffer_A.b; }
-//
-// layoutBuffer will create the struct A type.
-// replaceBuffer will replace use of global variable a and b with cbuffer_A.a
-// and cbuffer_A.b.
-//
-void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) {
- if (Buf.Constants.empty())
- return;
+
+// Creates the LLVM struct type representing the shape of the constant buffer,
+// which will be included in the LLVM target type, and calculates the memory
+// layout and constant buffer layout offsets of each constant.
+static void layoutBuffer(CGHLSLRuntime::Buffer &Buf, const DataLayout &DL) {
+ assert(!Buf.Constants.empty() &&
+ "empty constant buffer should not be created");
std::vector<llvm::Type *> EltTys;
- for (auto &Const : Buf.Constants) {
- GlobalVariable *GV = Const.first;
- Const.second = EltTys.size();
+ unsigned MemOffset = 0, CBufOffset = 0, Size = 0;
+
+ for (auto &C : Buf.Constants) {
+ GlobalVariable *GV = C.GlobalVar;
llvm::Type *Ty = GV->getValueType();
+
+ assert(!Ty->isArrayTy() && !Ty->isStructTy() &&
+ "arrays and structs in cbuffer are not yet implemened");
+
+ // scalar type, vector or matrix
EltTys.emplace_back(Ty);
+ unsigned FieldSize = Ty->getScalarSizeInBits() / 8;
+ if (Ty->isVectorTy())
+ FieldSize *= cast<FixedVectorType>(Ty)->getNumElements();
+ assert(FieldSize <= 16 && "field side larger than constant buffer row");
+
+ // set memory layout offset (no padding)
+ C.MemOffset = MemOffset;
+ MemOffset += FieldSize;
+
+ // calculate cbuffer layout offset or update total cbuffer size from
+ // packoffset annotations
+ if (Buf.HasPackoffset) {
+ assert(C.CBufferOffset != UINT_MAX &&
+ "cbuffer offset should have been set from packoffset attribute");
+ unsigned OffsetAfterField = C.CBufferOffset + FieldSize;
+ if (Size < OffsetAfterField)
+ Size = OffsetAfterField;
+ } else {
+ // allign to the size of the field
+ CBufOffset = llvm::alignTo(CBufOffset, FieldSize);
+ C.CBufferOffset = CBufOffset;
+ CBufOffset += FieldSize;
+ Size = CBufOffset;
+ }
}
Buf.LayoutStruct = llvm::StructType::get(EltTys[0]->getContext(), EltTys);
+ Buf.Size = Size;
}
-GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
- // Create global variable for CB.
- GlobalVariable *CBGV = new GlobalVariable(
- Buf.LayoutStruct, /*isConstant*/ true,
- GlobalValue::LinkageTypes::ExternalLinkage, nullptr,
- llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb." : ".tb."),
- GlobalValue::NotThreadLocal);
+// Creates LLVM target type target("dx.CBuffer",..) for the constant buffer.
+// The target type includes the LLVM struct type representing the shape
+// of the constant buffer, size, and a list of offsets for each fields
+// in cbuffer layout.
+static llvm::Type *getBufferTargetType(LLVMContext &Ctx,
+ CGHLSLRuntime::Buffer &Buf) {
+ assert(Buf.LayoutStruct != nullptr && Buf.Size != UINT_MAX &&
+ "the buffer layout has not been calculated yet");
+ llvm::SmallVector<unsigned> SizeAndOffsets;
+ SizeAndOffsets.reserve(Buf.Constants.size() + 1);
+ SizeAndOffsets.push_back(Buf.Size);
+ for (CGHLSLRuntime::BufferConstant &C : Buf.Constants) {
+ SizeAndOffsets.push_back(C.CBufferOffset);
+ }
+ return llvm::TargetExtType::get(Ctx, "dx.CBuffer", {Buf.LayoutStruct},
+ SizeAndOffsets);
----------------
hekota wrote:
Maybe we could just manufacture the type `hlsl_resource_t [[hlsl::contained_type(CB)]] [[hlsl::resource_class(CBuffer)]]` and call `TargetCodeGenInfo::getHLSLType()` on that.
https://github.com/llvm/llvm-project/pull/119755
More information about the cfe-commits
mailing list