-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[DirectX] Create symbols for resource handles #119775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-directx Author: Justin Bogner (bogner) ChangesWe need to create symbols with "the original shape of resource and element type" to put in the resource metadata in order to generate valid DXIL. Note that DXC generally doesn't emit an actual symbol outside of library shaders (it emits an undef of a pointer to the type), but since we have to deal with opaque pointers we would need a way to smuggle the type through to match that. Instead, we simply emit symbols for now. Fixed #116849 Patch is 21.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/119775.diff 5 Files Affected:
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 2f5dded46538ea..b59798a3d64a47 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -270,6 +270,7 @@ class ResourceTypeInfo {
GloballyCoherent, HasCounter) {}
TargetExtType *getHandleTy() const { return HandleTy; }
+ StructType *createElementStruct();
// Conditions to check before accessing specific views.
bool isUAV() const;
@@ -325,21 +326,23 @@ class ResourceBindingInfo {
private:
ResourceBinding Binding;
TargetExtType *HandleTy;
+ GlobalVariable *Symbol = nullptr;
public:
ResourceBindingInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound,
- uint32_t Size, TargetExtType *HandleTy)
- : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy) {}
+ uint32_t Size, TargetExtType *HandleTy,
+ GlobalVariable *Symbol = nullptr)
+ : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy),
+ Symbol(Symbol) {}
void setBindingID(unsigned ID) { Binding.RecordID = ID; }
const ResourceBinding &getBinding() const { return Binding; }
TargetExtType *getHandleTy() const { return HandleTy; }
- const StringRef getName() const {
- // TODO: Get the name from the symbol once we include one here.
- return "";
- }
+ const StringRef getName() const { return Symbol ? Symbol->getName() : ""; }
+ bool hasSymbol() const { return Symbol; }
+ GlobalVariable *createSymbol(Module &M, StructType *Ty, StringRef Name = "");
MDTuple *getAsMetadata(Module &M, DXILResourceTypeMap &DRTM) const;
MDTuple *getAsMetadata(Module &M, dxil::ResourceTypeInfo RTI) const;
@@ -349,7 +352,8 @@ class ResourceBindingInfo {
getAnnotateProps(Module &M, dxil::ResourceTypeInfo RTI) const;
bool operator==(const ResourceBindingInfo &RHS) const {
- return std::tie(Binding, HandleTy) == std::tie(RHS.Binding, RHS.HandleTy);
+ return std::tie(Binding, HandleTy, Symbol) ==
+ std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol);
}
bool operator!=(const ResourceBindingInfo &RHS) const {
return !(*this == RHS);
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index e1942a0c4930cd..793929e0e40dfa 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -216,6 +216,81 @@ ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy,
llvm_unreachable("Unknown handle type");
}
+static void formatTypeName(SmallString<64> &Dest, StringRef Name,
+ bool isWriteable, bool isROV) {
+ Dest = isWriteable ? (isROV ? "RasterizerOrdered" : "RW") : "";
+ Dest += Name;
+}
+
+StructType *ResourceTypeInfo::createElementStruct() {
+ SmallString<64> TypeName;
+
+ switch (Kind) {
+ case ResourceKind::Texture1D:
+ case ResourceKind::Texture2D:
+ case ResourceKind::Texture3D:
+ case ResourceKind::TextureCube:
+ case ResourceKind::Texture1DArray:
+ case ResourceKind::Texture2DArray:
+ case ResourceKind::TextureCubeArray: {
+ auto *RTy = cast<TextureExtType>(HandleTy);
+ formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::Texture2DMS:
+ case ResourceKind::Texture2DMSArray: {
+ auto *RTy = cast<MSTextureExtType>(HandleTy);
+ formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
+ /*IsROV=*/false);
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::TypedBuffer: {
+ auto *RTy = cast<TypedBufferExtType>(HandleTy);
+ formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::RawBuffer: {
+ auto *RTy = cast<RawBufferExtType>(HandleTy);
+ formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
+ TypeName);
+ }
+ case ResourceKind::StructuredBuffer: {
+ auto *RTy = cast<RawBufferExtType>(HandleTy);
+ formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::FeedbackTexture2D:
+ case ResourceKind::FeedbackTexture2DArray: {
+ auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
+ TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
+ llvm::to_underlying(RTy->getFeedbackType()));
+ return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
+ TypeName);
+ }
+ case ResourceKind::CBuffer:
+ return StructType::create(HandleTy->getContext(), "cbuffer");
+ case ResourceKind::Sampler: {
+ auto *RTy = cast<SamplerExtType>(HandleTy);
+ TypeName = formatv("SamplerState<{0}>",
+ llvm::to_underlying(RTy->getSamplerType()));
+ return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
+ TypeName);
+ }
+ case ResourceKind::TBuffer:
+ case ResourceKind::RTAccelerationStructure:
+ llvm_unreachable("Unhandled resource kind");
+ case ResourceKind::Invalid:
+ case ResourceKind::NumEntries:
+ llvm_unreachable("Invalid resource kind");
+ }
+ llvm_unreachable("Unhandled ResourceKind enum");
+}
+
bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
bool ResourceTypeInfo::isCBuffer() const {
@@ -450,6 +525,15 @@ void ResourceTypeInfo::print(raw_ostream &OS, const DataLayout &DL) const {
}
}
+GlobalVariable *ResourceBindingInfo::createSymbol(Module &M, StructType *Ty,
+ StringRef Name) {
+ assert(!Symbol && "Symbol has already been created");
+ Symbol = new GlobalVariable(M, Ty, /*isConstant=*/true,
+ GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, Name);
+ return Symbol;
+}
+
MDTuple *ResourceBindingInfo::getAsMetadata(Module &M,
DXILResourceTypeMap &DRTM) const {
return getAsMetadata(M, DRTM[getHandleTy()]);
@@ -474,13 +558,9 @@ MDTuple *ResourceBindingInfo::getAsMetadata(Module &M,
};
MDVals.push_back(getIntMD(Binding.RecordID));
-
- // TODO: We need API to create a symbol of the appropriate type to emit here.
- // See https://github.com/llvm/llvm-project/issues/116849
- MDVals.push_back(
- ValueAsMetadata::get(UndefValue::get(PointerType::getUnqual(Ctx))));
- MDVals.push_back(MDString::get(Ctx, ""));
-
+ assert(Symbol && "Cannot yet create useful resource metadata without symbol");
+ MDVals.push_back(ValueAsMetadata::get(Symbol));
+ MDVals.push_back(MDString::get(Ctx, Symbol->getName()));
MDVals.push_back(getIntMD(Binding.Space));
MDVals.push_back(getIntMD(Binding.LowerBound));
MDVals.push_back(getIntMD(Binding.Size));
@@ -590,6 +670,12 @@ void ResourceBindingInfo::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
void ResourceBindingInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo RTI,
const DataLayout &DL) const {
+ if (Symbol) {
+ OS << " Symbol: ";
+ Symbol->printAsOperand(OS);
+ OS << "\n";
+ }
+
OS << " Binding:\n"
<< " Record ID: " << Binding.RecordID << "\n"
<< " Space: " << Binding.Space << "\n"
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index 9763fe6a8a3455..9443ccd9c82a53 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -77,6 +77,10 @@ static NamedMDNode *emitResourceMetadata(Module &M, DXILBindingMap &DBM,
const dxil::Resources &MDResources) {
LLVMContext &Context = M.getContext();
+ for (ResourceBindingInfo &RI : DBM)
+ if (!RI.hasSymbol())
+ RI.createSymbol(M, DRTM[RI.getHandleTy()].createElementStruct());
+
SmallVector<Metadata *> SRVs, UAVs, CBufs, Smps;
for (const ResourceBindingInfo &RI : DBM.srvs())
SRVs.push_back(RI.getAsMetadata(M, DRTM));
diff --git a/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll b/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll
new file mode 100644
index 00000000000000..5ac4baa96c6599
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -passes=dxil-translate-metadata %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%struct.S = type { <4 x float>, <4 x i32> }
+
+define void @test() {
+ ; Buffer<float4>
+ %float4 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 0, i32 1, i32 0, i1 false)
+ ; CHECK: %TypedBuffer = type { <4 x float> }
+
+ ; Buffer<int>
+ %int = call target("dx.TypedBuffer", i32, 0, 0, 1)
+ @llvm.dx.handle.fromBinding(i32 0, i32 1, i32 1, i32 0, i1 false)
+ ; CHECK: %TypedBuffer.0 = type { i32 }
+
+ ; Buffer<uint3>
+ %uint3 = call target("dx.TypedBuffer", <3 x i32>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 2, i32 1, i32 0, i1 false)
+ ; CHECK: %TypedBuffer.1 = type { <3 x i32> }
+
+ ; StructuredBuffer<S>
+ %struct0 = call target("dx.RawBuffer", %struct.S, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 10, i32 1, i32 0, i1 true)
+ ; CHECK: %StructuredBuffer = type { %struct.S }
+
+ ; ByteAddressBuffer
+ %byteaddr = call target("dx.RawBuffer", i8, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 20, i32 1, i32 0, i1 false)
+ ; CHECK: %ByteAddressBuffer = type { i32 }
+
+ ret void
+}
+
+; CHECK: @[[T0:.*]] = external constant %TypedBuffer
+; CHECK-NEXT: @[[T1:.*]] = external constant %TypedBuffer.0
+; CHECK-NEXT: @[[T2:.*]] = external constant %TypedBuffer.1
+; CHECK-NEXT: @[[S0:.*]] = external constant %StructuredBuffer
+; CHECK-NEXT: @[[B0:.*]] = external constant %ByteAddressBuffer
+
+; CHECK: !{i32 0, ptr @[[T0]], !""
+; CHECK: !{i32 1, ptr @[[T1]], !""
+; CHECK: !{i32 2, ptr @[[T2]], !""
+; CHECK: !{i32 3, ptr @[[S0]], !""
+; CHECK: !{i32 4, ptr @[[B0]], !""
+
+attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp
index 784ea7702c0d5f..4c005f817af59d 100644
--- a/llvm/unittests/Analysis/DXILResourceTest.cpp
+++ b/llvm/unittests/Analysis/DXILResourceTest.cpp
@@ -120,7 +120,6 @@ TEST(DXILResource, AnnotationsAndMetadata) {
Type *Int32x2Ty = FixedVectorType::get(Int32Ty, 2);
MDBuilder TestMD(Context, Int32Ty, Int1Ty);
- Value *DummyGV = UndefValue::get(PointerType::getUnqual(Context));
// ByteAddressBuffer Buffer;
ResourceTypeInfo RTI(llvm::TargetExtType::get(
@@ -131,11 +130,12 @@ TEST(DXILResource, AnnotationsAndMetadata) {
ResourceBindingInfo RBI(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GlobalVariable *GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer");
std::pair<uint32_t, uint32_t> Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000000bU);
EXPECT_EQ(Props.second, 0U);
MDTuple *MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 11, 0, nullptr));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "Buffer", 0, 0, 1, 11, 0, nullptr));
// RWByteAddressBuffer BufferOut : register(u3, space2);
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -149,12 +149,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/1, /*Space=*/2, /*LowerBound=*/3, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "BufferOut");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000100bU);
EXPECT_EQ(Props.second, 0U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(1, DummyGV, "", 2, 3, 1, 11, false, false, false,
- nullptr));
+ EXPECT_MDEQ(MD, TestMD.get(1, GV, "BufferOut", 2, 3, 1, 11, false, false,
+ false, nullptr));
// struct BufType0 { int i; float f; double d; };
// StructuredBuffer<BufType0> Buffer0 : register(t0);
@@ -171,12 +172,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer0");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000030cU);
EXPECT_EQ(Props.second, 0x00000010U);
MD = RBI.getAsMetadata(M, RTI);
EXPECT_MDEQ(MD,
- TestMD.get(0, DummyGV, "", 0, 0, 1, 12, 0, TestMD.get(1, 16)));
+ TestMD.get(0, GV, "Buffer0", 0, 0, 1, 12, 0, TestMD.get(1, 16)));
// StructuredBuffer<float3> Buffer1 : register(t1);
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -190,12 +192,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/1, /*Space=*/0, /*LowerBound=*/1, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer1");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000000cU);
EXPECT_EQ(Props.second, 0x0000000cU);
MD = RBI.getAsMetadata(M, RTI);
EXPECT_MDEQ(MD,
- TestMD.get(1, DummyGV, "", 0, 1, 1, 12, 0, TestMD.get(1, 12)));
+ TestMD.get(1, GV, "Buffer1", 0, 1, 1, 12, 0, TestMD.get(1, 12)));
// Texture2D<float4> ColorMapTexture : register(t2);
RTI = ResourceTypeInfo(
@@ -211,11 +214,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/2, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "ColorMapTexture");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00000002U);
EXPECT_EQ(Props.second, 0x00000409U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(2, DummyGV, "", 0, 2, 1, 2, 0, TestMD.get(0, 9)));
+ EXPECT_MDEQ(MD, TestMD.get(2, GV, "ColorMapTexture", 0, 2, 1, 2, 0,
+ TestMD.get(0, 9)));
// Texture2DMS<float, 8> DepthBuffer : register(t0);
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -233,11 +238,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "DepthBuffer");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00000003U);
EXPECT_EQ(Props.second, 0x00080109U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 3, 8, TestMD.get(0, 9)));
+ EXPECT_MDEQ(
+ MD, TestMD.get(0, GV, "DepthBuffer", 0, 0, 1, 3, 8, TestMD.get(0, 9)));
// FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -252,12 +259,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "feedbackMinMip");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00001011U);
EXPECT_EQ(Props.second, 0U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 17, false, false, false,
- TestMD.get(2, 0)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "feedbackMinMip", 0, 0, 1, 17, false, false,
+ false, TestMD.get(2, 0)));
// FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegion;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -272,12 +280,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "feedbackMipRegion");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00001012U);
EXPECT_EQ(Props.second, 0x00000001U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 18, false, false, false,
- TestMD.get(2, 1)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "feedbackMipRegion", 0, 0, 1, 18, false,
+ false, false, TestMD.get(2, 1)));
// globallycoherent RWTexture2D<int2> OutputTexture : register(u0, space2);
RTI = ResourceTypeInfo(
@@ -296,12 +305,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "OutputTexture");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00005002U);
EXPECT_EQ(Props.second, 0x00000204U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 2, 0, 1, 2, true, false, false,
- TestMD.get(0, 4)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "OutputTexture", 2, 0, 1, 2, true, false,
+ false, TestMD.get(0, 4)));
// RasterizerOrderedBuffer<float4> ROB;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -319,11 +329,12 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "ROB");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000300aU);
EXPECT_EQ(Props.second, 0x00000409U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 10, false, false, true,
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "ROB", 0, 0, 1, 10, false, false, true,
TestMD.get(0, 9)));
// RWStructuredBuffer<ParticleMotion> g_OutputBuffer : register(u2);
@@ -345,12 +356,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "g_OutputBuffer");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000920cU);
EXPECT_EQ(Props.second, 0x00000014U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 2, 1, 12, false, true, false,
- TestMD.get(1, 20)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "g_OutputBuffer", 0, 2, 1, 12, false, true,
+ false, TestMD.get(1, 20)));
// RWTexture2DMSArray<uint, 8> g_rw_t2dmsa;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -371,12 +383,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "g_rw_t2dmsa");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00001008U);
EXPECT_EQ(Props.second, 0x00080105U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 8, false, false, false,
- TestMD.get(0, 5)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "g_rw_t2dmsa", 0, 0, 1, 8, false, false,
+ false, TestMD.get(0, 5)));
// cbuffer cb0 { float4 g_X; float4 g_Y; }
StructType *CBufType0 =
@@ -390,11 +403,12 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000000dU);
EXPECT_EQ(Props.second, 0x00000020U);
MD = RB...
[truncated]
|
@llvm/pr-subscribers-llvm-analysis Author: Justin Bogner (bogner) ChangesWe need to create symbols with "the original shape of resource and element type" to put in the resource metadata in order to generate valid DXIL. Note that DXC generally doesn't emit an actual symbol outside of library shaders (it emits an undef of a pointer to the type), but since we have to deal with opaque pointers we would need a way to smuggle the type through to match that. Instead, we simply emit symbols for now. Fixed #116849 Patch is 21.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/119775.diff 5 Files Affected:
diff --git a/llvm/include/llvm/Analysis/DXILResource.h b/llvm/include/llvm/Analysis/DXILResource.h
index 2f5dded46538ea..b59798a3d64a47 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -270,6 +270,7 @@ class ResourceTypeInfo {
GloballyCoherent, HasCounter) {}
TargetExtType *getHandleTy() const { return HandleTy; }
+ StructType *createElementStruct();
// Conditions to check before accessing specific views.
bool isUAV() const;
@@ -325,21 +326,23 @@ class ResourceBindingInfo {
private:
ResourceBinding Binding;
TargetExtType *HandleTy;
+ GlobalVariable *Symbol = nullptr;
public:
ResourceBindingInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound,
- uint32_t Size, TargetExtType *HandleTy)
- : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy) {}
+ uint32_t Size, TargetExtType *HandleTy,
+ GlobalVariable *Symbol = nullptr)
+ : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy),
+ Symbol(Symbol) {}
void setBindingID(unsigned ID) { Binding.RecordID = ID; }
const ResourceBinding &getBinding() const { return Binding; }
TargetExtType *getHandleTy() const { return HandleTy; }
- const StringRef getName() const {
- // TODO: Get the name from the symbol once we include one here.
- return "";
- }
+ const StringRef getName() const { return Symbol ? Symbol->getName() : ""; }
+ bool hasSymbol() const { return Symbol; }
+ GlobalVariable *createSymbol(Module &M, StructType *Ty, StringRef Name = "");
MDTuple *getAsMetadata(Module &M, DXILResourceTypeMap &DRTM) const;
MDTuple *getAsMetadata(Module &M, dxil::ResourceTypeInfo RTI) const;
@@ -349,7 +352,8 @@ class ResourceBindingInfo {
getAnnotateProps(Module &M, dxil::ResourceTypeInfo RTI) const;
bool operator==(const ResourceBindingInfo &RHS) const {
- return std::tie(Binding, HandleTy) == std::tie(RHS.Binding, RHS.HandleTy);
+ return std::tie(Binding, HandleTy, Symbol) ==
+ std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol);
}
bool operator!=(const ResourceBindingInfo &RHS) const {
return !(*this == RHS);
diff --git a/llvm/lib/Analysis/DXILResource.cpp b/llvm/lib/Analysis/DXILResource.cpp
index e1942a0c4930cd..793929e0e40dfa 100644
--- a/llvm/lib/Analysis/DXILResource.cpp
+++ b/llvm/lib/Analysis/DXILResource.cpp
@@ -216,6 +216,81 @@ ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy,
llvm_unreachable("Unknown handle type");
}
+static void formatTypeName(SmallString<64> &Dest, StringRef Name,
+ bool isWriteable, bool isROV) {
+ Dest = isWriteable ? (isROV ? "RasterizerOrdered" : "RW") : "";
+ Dest += Name;
+}
+
+StructType *ResourceTypeInfo::createElementStruct() {
+ SmallString<64> TypeName;
+
+ switch (Kind) {
+ case ResourceKind::Texture1D:
+ case ResourceKind::Texture2D:
+ case ResourceKind::Texture3D:
+ case ResourceKind::TextureCube:
+ case ResourceKind::Texture1DArray:
+ case ResourceKind::Texture2DArray:
+ case ResourceKind::TextureCubeArray: {
+ auto *RTy = cast<TextureExtType>(HandleTy);
+ formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::Texture2DMS:
+ case ResourceKind::Texture2DMSArray: {
+ auto *RTy = cast<MSTextureExtType>(HandleTy);
+ formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
+ /*IsROV=*/false);
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::TypedBuffer: {
+ auto *RTy = cast<TypedBufferExtType>(HandleTy);
+ formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::RawBuffer: {
+ auto *RTy = cast<RawBufferExtType>(HandleTy);
+ formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
+ TypeName);
+ }
+ case ResourceKind::StructuredBuffer: {
+ auto *RTy = cast<RawBufferExtType>(HandleTy);
+ formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
+ RTy->isROV());
+ return StructType::create(RTy->getResourceType(), TypeName);
+ }
+ case ResourceKind::FeedbackTexture2D:
+ case ResourceKind::FeedbackTexture2DArray: {
+ auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
+ TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
+ llvm::to_underlying(RTy->getFeedbackType()));
+ return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
+ TypeName);
+ }
+ case ResourceKind::CBuffer:
+ return StructType::create(HandleTy->getContext(), "cbuffer");
+ case ResourceKind::Sampler: {
+ auto *RTy = cast<SamplerExtType>(HandleTy);
+ TypeName = formatv("SamplerState<{0}>",
+ llvm::to_underlying(RTy->getSamplerType()));
+ return StructType::create(Type::getInt32Ty(HandleTy->getContext()),
+ TypeName);
+ }
+ case ResourceKind::TBuffer:
+ case ResourceKind::RTAccelerationStructure:
+ llvm_unreachable("Unhandled resource kind");
+ case ResourceKind::Invalid:
+ case ResourceKind::NumEntries:
+ llvm_unreachable("Invalid resource kind");
+ }
+ llvm_unreachable("Unhandled ResourceKind enum");
+}
+
bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
bool ResourceTypeInfo::isCBuffer() const {
@@ -450,6 +525,15 @@ void ResourceTypeInfo::print(raw_ostream &OS, const DataLayout &DL) const {
}
}
+GlobalVariable *ResourceBindingInfo::createSymbol(Module &M, StructType *Ty,
+ StringRef Name) {
+ assert(!Symbol && "Symbol has already been created");
+ Symbol = new GlobalVariable(M, Ty, /*isConstant=*/true,
+ GlobalValue::ExternalLinkage,
+ /*Initializer=*/nullptr, Name);
+ return Symbol;
+}
+
MDTuple *ResourceBindingInfo::getAsMetadata(Module &M,
DXILResourceTypeMap &DRTM) const {
return getAsMetadata(M, DRTM[getHandleTy()]);
@@ -474,13 +558,9 @@ MDTuple *ResourceBindingInfo::getAsMetadata(Module &M,
};
MDVals.push_back(getIntMD(Binding.RecordID));
-
- // TODO: We need API to create a symbol of the appropriate type to emit here.
- // See https://github.com/llvm/llvm-project/issues/116849
- MDVals.push_back(
- ValueAsMetadata::get(UndefValue::get(PointerType::getUnqual(Ctx))));
- MDVals.push_back(MDString::get(Ctx, ""));
-
+ assert(Symbol && "Cannot yet create useful resource metadata without symbol");
+ MDVals.push_back(ValueAsMetadata::get(Symbol));
+ MDVals.push_back(MDString::get(Ctx, Symbol->getName()));
MDVals.push_back(getIntMD(Binding.Space));
MDVals.push_back(getIntMD(Binding.LowerBound));
MDVals.push_back(getIntMD(Binding.Size));
@@ -590,6 +670,12 @@ void ResourceBindingInfo::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
void ResourceBindingInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo RTI,
const DataLayout &DL) const {
+ if (Symbol) {
+ OS << " Symbol: ";
+ Symbol->printAsOperand(OS);
+ OS << "\n";
+ }
+
OS << " Binding:\n"
<< " Record ID: " << Binding.RecordID << "\n"
<< " Space: " << Binding.Space << "\n"
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index 9763fe6a8a3455..9443ccd9c82a53 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -77,6 +77,10 @@ static NamedMDNode *emitResourceMetadata(Module &M, DXILBindingMap &DBM,
const dxil::Resources &MDResources) {
LLVMContext &Context = M.getContext();
+ for (ResourceBindingInfo &RI : DBM)
+ if (!RI.hasSymbol())
+ RI.createSymbol(M, DRTM[RI.getHandleTy()].createElementStruct());
+
SmallVector<Metadata *> SRVs, UAVs, CBufs, Smps;
for (const ResourceBindingInfo &RI : DBM.srvs())
SRVs.push_back(RI.getAsMetadata(M, DRTM));
diff --git a/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll b/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll
new file mode 100644
index 00000000000000..5ac4baa96c6599
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/Metadata/resource-symbols.ll
@@ -0,0 +1,48 @@
+; RUN: opt -S -passes=dxil-translate-metadata %s | FileCheck %s
+
+target triple = "dxil-pc-shadermodel6.6-compute"
+
+%struct.S = type { <4 x float>, <4 x i32> }
+
+define void @test() {
+ ; Buffer<float4>
+ %float4 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 0, i32 1, i32 0, i1 false)
+ ; CHECK: %TypedBuffer = type { <4 x float> }
+
+ ; Buffer<int>
+ %int = call target("dx.TypedBuffer", i32, 0, 0, 1)
+ @llvm.dx.handle.fromBinding(i32 0, i32 1, i32 1, i32 0, i1 false)
+ ; CHECK: %TypedBuffer.0 = type { i32 }
+
+ ; Buffer<uint3>
+ %uint3 = call target("dx.TypedBuffer", <3 x i32>, 0, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 2, i32 1, i32 0, i1 false)
+ ; CHECK: %TypedBuffer.1 = type { <3 x i32> }
+
+ ; StructuredBuffer<S>
+ %struct0 = call target("dx.RawBuffer", %struct.S, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 10, i32 1, i32 0, i1 true)
+ ; CHECK: %StructuredBuffer = type { %struct.S }
+
+ ; ByteAddressBuffer
+ %byteaddr = call target("dx.RawBuffer", i8, 0, 0)
+ @llvm.dx.handle.fromBinding(i32 0, i32 20, i32 1, i32 0, i1 false)
+ ; CHECK: %ByteAddressBuffer = type { i32 }
+
+ ret void
+}
+
+; CHECK: @[[T0:.*]] = external constant %TypedBuffer
+; CHECK-NEXT: @[[T1:.*]] = external constant %TypedBuffer.0
+; CHECK-NEXT: @[[T2:.*]] = external constant %TypedBuffer.1
+; CHECK-NEXT: @[[S0:.*]] = external constant %StructuredBuffer
+; CHECK-NEXT: @[[B0:.*]] = external constant %ByteAddressBuffer
+
+; CHECK: !{i32 0, ptr @[[T0]], !""
+; CHECK: !{i32 1, ptr @[[T1]], !""
+; CHECK: !{i32 2, ptr @[[T2]], !""
+; CHECK: !{i32 3, ptr @[[S0]], !""
+; CHECK: !{i32 4, ptr @[[B0]], !""
+
+attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
diff --git a/llvm/unittests/Analysis/DXILResourceTest.cpp b/llvm/unittests/Analysis/DXILResourceTest.cpp
index 784ea7702c0d5f..4c005f817af59d 100644
--- a/llvm/unittests/Analysis/DXILResourceTest.cpp
+++ b/llvm/unittests/Analysis/DXILResourceTest.cpp
@@ -120,7 +120,6 @@ TEST(DXILResource, AnnotationsAndMetadata) {
Type *Int32x2Ty = FixedVectorType::get(Int32Ty, 2);
MDBuilder TestMD(Context, Int32Ty, Int1Ty);
- Value *DummyGV = UndefValue::get(PointerType::getUnqual(Context));
// ByteAddressBuffer Buffer;
ResourceTypeInfo RTI(llvm::TargetExtType::get(
@@ -131,11 +130,12 @@ TEST(DXILResource, AnnotationsAndMetadata) {
ResourceBindingInfo RBI(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GlobalVariable *GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer");
std::pair<uint32_t, uint32_t> Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000000bU);
EXPECT_EQ(Props.second, 0U);
MDTuple *MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 11, 0, nullptr));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "Buffer", 0, 0, 1, 11, 0, nullptr));
// RWByteAddressBuffer BufferOut : register(u3, space2);
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -149,12 +149,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/1, /*Space=*/2, /*LowerBound=*/3, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "BufferOut");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000100bU);
EXPECT_EQ(Props.second, 0U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(1, DummyGV, "", 2, 3, 1, 11, false, false, false,
- nullptr));
+ EXPECT_MDEQ(MD, TestMD.get(1, GV, "BufferOut", 2, 3, 1, 11, false, false,
+ false, nullptr));
// struct BufType0 { int i; float f; double d; };
// StructuredBuffer<BufType0> Buffer0 : register(t0);
@@ -171,12 +172,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer0");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000030cU);
EXPECT_EQ(Props.second, 0x00000010U);
MD = RBI.getAsMetadata(M, RTI);
EXPECT_MDEQ(MD,
- TestMD.get(0, DummyGV, "", 0, 0, 1, 12, 0, TestMD.get(1, 16)));
+ TestMD.get(0, GV, "Buffer0", 0, 0, 1, 12, 0, TestMD.get(1, 16)));
// StructuredBuffer<float3> Buffer1 : register(t1);
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -190,12 +192,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/1, /*Space=*/0, /*LowerBound=*/1, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer1");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000000cU);
EXPECT_EQ(Props.second, 0x0000000cU);
MD = RBI.getAsMetadata(M, RTI);
EXPECT_MDEQ(MD,
- TestMD.get(1, DummyGV, "", 0, 1, 1, 12, 0, TestMD.get(1, 12)));
+ TestMD.get(1, GV, "Buffer1", 0, 1, 1, 12, 0, TestMD.get(1, 12)));
// Texture2D<float4> ColorMapTexture : register(t2);
RTI = ResourceTypeInfo(
@@ -211,11 +214,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/2, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "ColorMapTexture");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00000002U);
EXPECT_EQ(Props.second, 0x00000409U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(2, DummyGV, "", 0, 2, 1, 2, 0, TestMD.get(0, 9)));
+ EXPECT_MDEQ(MD, TestMD.get(2, GV, "ColorMapTexture", 0, 2, 1, 2, 0,
+ TestMD.get(0, 9)));
// Texture2DMS<float, 8> DepthBuffer : register(t0);
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -233,11 +238,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "DepthBuffer");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00000003U);
EXPECT_EQ(Props.second, 0x00080109U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 3, 8, TestMD.get(0, 9)));
+ EXPECT_MDEQ(
+ MD, TestMD.get(0, GV, "DepthBuffer", 0, 0, 1, 3, 8, TestMD.get(0, 9)));
// FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -252,12 +259,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "feedbackMinMip");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00001011U);
EXPECT_EQ(Props.second, 0U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 17, false, false, false,
- TestMD.get(2, 0)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "feedbackMinMip", 0, 0, 1, 17, false, false,
+ false, TestMD.get(2, 0)));
// FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegion;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -272,12 +280,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "feedbackMipRegion");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00001012U);
EXPECT_EQ(Props.second, 0x00000001U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 18, false, false, false,
- TestMD.get(2, 1)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "feedbackMipRegion", 0, 0, 1, 18, false,
+ false, false, TestMD.get(2, 1)));
// globallycoherent RWTexture2D<int2> OutputTexture : register(u0, space2);
RTI = ResourceTypeInfo(
@@ -296,12 +305,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "OutputTexture");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00005002U);
EXPECT_EQ(Props.second, 0x00000204U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 2, 0, 1, 2, true, false, false,
- TestMD.get(0, 4)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "OutputTexture", 2, 0, 1, 2, true, false,
+ false, TestMD.get(0, 4)));
// RasterizerOrderedBuffer<float4> ROB;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -319,11 +329,12 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "ROB");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000300aU);
EXPECT_EQ(Props.second, 0x00000409U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 10, false, false, true,
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "ROB", 0, 0, 1, 10, false, false, true,
TestMD.get(0, 9)));
// RWStructuredBuffer<ParticleMotion> g_OutputBuffer : register(u2);
@@ -345,12 +356,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "g_OutputBuffer");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000920cU);
EXPECT_EQ(Props.second, 0x00000014U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 2, 1, 12, false, true, false,
- TestMD.get(1, 20)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "g_OutputBuffer", 0, 2, 1, 12, false, true,
+ false, TestMD.get(1, 20)));
// RWTexture2DMSArray<uint, 8> g_rw_t2dmsa;
RTI = ResourceTypeInfo(llvm::TargetExtType::get(
@@ -371,12 +383,13 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "g_rw_t2dmsa");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x00001008U);
EXPECT_EQ(Props.second, 0x00080105U);
MD = RBI.getAsMetadata(M, RTI);
- EXPECT_MDEQ(MD, TestMD.get(0, DummyGV, "", 0, 0, 1, 8, false, false, false,
- TestMD.get(0, 5)));
+ EXPECT_MDEQ(MD, TestMD.get(0, GV, "g_rw_t2dmsa", 0, 0, 1, 8, false, false,
+ false, TestMD.get(0, 5)));
// cbuffer cb0 { float4 g_X; float4 g_Y; }
StructType *CBufType0 =
@@ -390,11 +403,12 @@ TEST(DXILResource, AnnotationsAndMetadata) {
RBI = ResourceBindingInfo(
/*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
RTI.getHandleTy());
+ GV = RBI.createSymbol(M, RTI.createElementStruct(), "");
Props = RBI.getAnnotateProps(M, RTI);
EXPECT_EQ(Props.first, 0x0000000dU);
EXPECT_EQ(Props.second, 0x00000020U);
MD = RB...
[truncated]
|
If there already is a global variable for the resource in the module, shouldn't we be using that instead of creating a new symbol? |
The only global variables in the module before this point are the globals for the resource handles. These are (1) the wrong type (they're the handle object itself) and (2) it isn't clear what's happening with them long term. The mechanism here creates a global of the type that DXIL wants in the final output. |
f8291d2
to
4f018d3
Compare
612bd2f
to
c668ae9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
We need to create symbols with "the original shape of resource and element type" to put in the resource metadata in order to generate valid DXIL. Note that DXC generally doesn't emit an actual symbol outside of library shaders (it emits an undef of a pointer to the type), but since we have to deal with opaque pointers we would need a way to smuggle the type through to match that. Instead, we simply emit symbols for now. Fixed llvm#116849
c668ae9
to
4e5ac01
Compare
We need to create symbols with "the original shape of resource and element type" to put in the resource metadata in order to generate valid DXIL.
Note that DXC generally doesn't emit an actual symbol outside of library shaders (it emits an undef of a pointer to the type), but since we have to deal with opaque pointers we would need a way to smuggle the type through to match that. Instead, we simply emit symbols for now.
Fixed #116849