================ @@ -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); ---------------- bogner wrote:
We shouldn't/can't be creating `dx.` target types here, it needs to be in `DirectXTargetCodeGenInfo`. That way we can properly handle SPIR-V and generic handling as needed. I was thinking it would be nice if we could manufacture a buffer type here and just call `TargetCodeGenInfo::getHLSLType` in the runtime code, but if that isn't practical we may need to add another API hook instead. https://github.com/llvm/llvm-project/pull/119755 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits