-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[DirectX] Implement metadata lowering for resources #104447
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
[DirectX] Implement metadata lowering for resources #104447
Conversation
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-backend-directx Author: Justin Bogner (bogner) ChangesGenerate metadata from target extension type based resources. Part of #91366 Full diff: https://github.com/llvm/llvm-project/pull/104447.diff 3 Files Affected:
diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
index 007af0b46b9f3..f8621eea23448 100644
--- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
+++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
@@ -13,27 +13,52 @@
#include "DXILShaderFlags.h"
#include "DirectX.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/Analysis/DXILResource.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/TargetParser/Triple.h"
using namespace llvm;
using namespace llvm::dxil;
-static void emitResourceMetadata(Module &M,
+static void emitResourceMetadata(Module &M, const DXILResourceMap &DRM,
const dxil::Resources &MDResources) {
- Metadata *SRVMD = nullptr, *UAVMD = nullptr, *CBufMD = nullptr,
- *SmpMD = nullptr;
- bool HasResources = false;
+ LLVMContext &Context = M.getContext();
+
+ SmallVector<Metadata *> SRVs, UAVs, CBufs, Smps;
+ for (auto [_, RI] : DRM) {
+ switch (RI.getResourceClass()) {
+ case dxil::ResourceClass::SRV:
+ SRVs.push_back(RI.getAsMetadata(Context));
+ break;
+ case dxil::ResourceClass::UAV:
+ UAVs.push_back(RI.getAsMetadata(Context));
+ break;
+ case dxil::ResourceClass::CBuffer:
+ CBufs.push_back(RI.getAsMetadata(Context));
+ break;
+ case dxil::ResourceClass::Sampler:
+ Smps.push_back(RI.getAsMetadata(Context));
+ break;
+ }
+ }
+ Metadata *SRVMD = SRVs.empty() ? nullptr : MDNode::get(Context, SRVs);
+ Metadata *UAVMD = UAVs.empty() ? nullptr : MDNode::get(Context, UAVs);
+ Metadata *CBufMD = CBufs.empty() ? nullptr : MDNode::get(Context, CBufs);
+ Metadata *SmpMD = Smps.empty() ? nullptr : MDNode::get(Context, Smps);
+ bool HasResources = !DRM.empty();
if (MDResources.hasUAVs()) {
+ assert(!UAVMD && "Old and new UAV representations can't coexist");
UAVMD = MDResources.writeUAVs(M);
HasResources = true;
}
if (MDResources.hasCBuffers()) {
+ assert(!CBufMD && "Old and new cbuffer representations can't coexist");
CBufMD = MDResources.writeCBuffers(M);
HasResources = true;
}
@@ -46,7 +71,8 @@ static void emitResourceMetadata(Module &M,
MDNode::get(M.getContext(), {SRVMD, UAVMD, CBufMD, SmpMD}));
}
-static void translateMetadata(Module &M, const dxil::Resources &MDResources,
+static void translateMetadata(Module &M, const DXILResourceMap &DRM,
+ const dxil::Resources &MDResources,
const ComputedShaderFlags &ShaderFlags) {
dxil::ValidatorVersionMD ValVerMD(M);
if (ValVerMD.isEmpty())
@@ -54,18 +80,19 @@ static void translateMetadata(Module &M, const dxil::Resources &MDResources,
dxil::createShaderModelMD(M);
dxil::createDXILVersionMD(M);
- emitResourceMetadata(M, MDResources);
+ emitResourceMetadata(M, DRM, MDResources);
dxil::createEntryMD(M, static_cast<uint64_t>(ShaderFlags));
}
PreservedAnalyses DXILTranslateMetadata::run(Module &M,
ModuleAnalysisManager &MAM) {
+ const DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
const dxil::Resources &MDResources = MAM.getResult<DXILResourceMDAnalysis>(M);
const ComputedShaderFlags &ShaderFlags =
MAM.getResult<ShaderFlagsAnalysis>(M);
- translateMetadata(M, MDResources, ShaderFlags);
+ translateMetadata(M, DRM, MDResources, ShaderFlags);
return PreservedAnalyses::all();
}
@@ -80,17 +107,20 @@ class DXILTranslateMetadataLegacy : public ModulePass {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
+ AU.addRequired<DXILResourceWrapperPass>();
AU.addRequired<DXILResourceMDWrapper>();
AU.addRequired<ShaderFlagsAnalysisWrapper>();
}
bool runOnModule(Module &M) override {
+ const DXILResourceMap &DRM =
+ getAnalysis<DXILResourceWrapperPass>().getResourceMap();
const dxil::Resources &MDResources =
getAnalysis<DXILResourceMDWrapper>().getDXILResource();
const ComputedShaderFlags &ShaderFlags =
getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags();
- translateMetadata(M, MDResources, ShaderFlags);
+ translateMetadata(M, DRM, MDResources, ShaderFlags);
return true;
}
};
@@ -105,6 +135,7 @@ ModulePass *llvm::createDXILTranslateMetadataLegacyPass() {
INITIALIZE_PASS_BEGIN(DXILTranslateMetadataLegacy, "dxil-translate-metadata",
"DXIL Translate Metadata", false, false)
+INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper)
INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper)
INITIALIZE_PASS_END(DXILTranslateMetadataLegacy, "dxil-translate-metadata",
diff --git a/llvm/test/CodeGen/DirectX/CreateHandle.ll b/llvm/test/CodeGen/DirectX/CreateHandle.ll
index 1fad869ab4305..f0d1c8da5a425 100644
--- a/llvm/test/CodeGen/DirectX/CreateHandle.ll
+++ b/llvm/test/CodeGen/DirectX/CreateHandle.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower %s | FileCheck %s
+; RUN: opt -S -passes=dxil-op-lower,dxil-translate-metadata %s | FileCheck %s
target triple = "dxil-pc-shadermodel6.0-compute"
@@ -40,6 +40,14 @@ define void @test_buffers() {
ret void
}
+; Just check that we have the right types and number of metadata nodes, the
+; contents of the metadata are tested elsewhere.
+;
+; CHECK: !dx.resources = !{[[RESMD:![0-9]+]]}
+; CHECK: [[RESMD]] = !{[[SRVMD:![0-9]+]], [[UAVMD:![0-9]+]], null, null}
+; CHECK-DAG: [[SRVMD]] = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
+; CHECK-DAG: [[UAVMD]] = !{!{{[0-9]+}}, !{{[0-9]+}}}
+
; Note: We need declarations for each handle.fromBinding in the same order as
; they appear in source to force a deterministic ordering of record IDs.
declare target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
diff --git a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
index e8bd8fe89132d..345459a60c5ab 100644
--- a/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
+++ b/llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -dxil-op-lower %s | FileCheck %s
+; RUN: opt -S -passes=dxil-op-lower,dxil-translate-metadata %s | FileCheck %s
target triple = "dxil-pc-shadermodel6.6-compute"
@@ -44,6 +44,14 @@ define void @test_bindings() {
ret void
}
+; Just check that we have the right types and number of metadata nodes, the
+; contents of the metadata are tested elsewhere.
+;
+; CHECK: !dx.resources = !{[[RESMD:![0-9]+]]}
+; CHECK: [[RESMD]] = !{[[SRVMD:![0-9]+]], [[UAVMD:![0-9]+]], null, null}
+; CHECK-DAG: [[SRVMD]] = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}}
+; CHECK-DAG: [[UAVMD]] = !{!{{[0-9]+}}, !{{[0-9]+}}}
+
; Note: We need declarations for each handle.fromBinding in the same order as
; they appear in source to force a deterministic ordering of record IDs.
declare target("dx.TypedBuffer", <4 x float>, 1, 0, 0)
|
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.
Looks good.
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!
|
||
SmallVector<Metadata *> SRVs, UAVs, CBufs, Smps; | ||
for (auto [_, RI] : DRM) { | ||
switch (RI.getResourceClass()) { |
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.
For a resource array like Buffer<float4> B[10]
which used B[2]
and B[5]
. Will B[2]
and B[5]
both in DRM and get same RI?
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.
I've updated the API in #105602 - you can now iterate over the unique resources, and there are helpers to just iterate .srvs()
, .uavs()
, etc.
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
If a resources is used multiple times, we should only have one resource record for it. This comes up most prominantly with arrays of resources like so: ```hlsl RWBuffer<float4> BufferArray[10] : register(u0, space4); RWBuffer<float4> B1 = BufferArray[0]; RWBuffer<float4> B2 = BufferArray[SomeIndex]; RWBuffer<float4> B3 = BufferArray[3]; ``` In this case, there's only one resource, but we'll generate 3 different `dx.handle.fromBinding` calls to access different slices. Note that this adds some API that won't be used until #104447 later in the stack. Trying to avoid that results in unnecessary churn. Fixes #105143 Pull Request: #105602
Created using spr 1.3.5-bogner [skip ci]
Created using spr 1.3.5-bogner
Generate metadata from target extension type based resources.
Part of #91366