Skip to content

[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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions llvm/include/llvm/Analysis/DXILResource.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,46 @@ class DXILResourceMap {
: (Resources.begin() + Pos->second);
}

iterator srv_begin() { return begin(); }
const_iterator srv_begin() const { return begin(); }
iterator srv_end() { return begin() + FirstUAV; }
const_iterator srv_end() const { return begin() + FirstUAV; }
iterator_range<iterator> srvs() { return make_range(srv_begin(), srv_end()); }
iterator_range<const_iterator> srvs() const {
return make_range(srv_begin(), srv_end());
}

iterator uav_begin() { return begin() + FirstUAV; }
const_iterator uav_begin() const { return begin() + FirstUAV; }
iterator uav_end() { return begin() + FirstCBuffer; }
const_iterator uav_end() const { return begin() + FirstCBuffer; }
iterator_range<iterator> uavs() { return make_range(uav_begin(), uav_end()); }
iterator_range<const_iterator> uavs() const {
return make_range(uav_begin(), uav_end());
}

iterator cbuffer_begin() { return begin() + FirstCBuffer; }
const_iterator cbuffer_begin() const { return begin() + FirstCBuffer; }
iterator cbuffer_end() { return begin() + FirstSampler; }
const_iterator cbuffer_end() const { return begin() + FirstSampler; }
iterator_range<iterator> cbuffers() {
return make_range(cbuffer_begin(), cbuffer_end());
}
iterator_range<const_iterator> cbuffers() const {
return make_range(cbuffer_begin(), cbuffer_end());
}

iterator sampler_begin() { return begin() + FirstSampler; }
const_iterator sampler_begin() const { return begin() + FirstSampler; }
iterator sampler_end() { return end(); }
const_iterator sampler_end() const { return end(); }
iterator_range<iterator> samplers() {
return make_range(sampler_begin(), sampler_end());
}
iterator_range<const_iterator> samplers() const {
return make_range(sampler_begin(), sampler_end());
}

void print(raw_ostream &OS) const;
};

Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/DirectX/DXILMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ void dxil::createEntryMD(Module &M, const uint64_t ShaderFlags) {
EntryList.emplace_back(&F);
}

// If there are no entries, do nothing. This is mostly to allow for writing
// tests with no actual entry functions.
if (EntryList.empty())
return;

auto &Ctx = M.getContext();
// FIXME: generate metadata for resource.
// See https://github.com/llvm/llvm-project/issues/57926.
Expand Down
40 changes: 32 additions & 8 deletions llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,45 @@
#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 (const ResourceInfo &RI : DRM.srvs())
SRVs.push_back(RI.getAsMetadata(Context));
for (const ResourceInfo &RI : DRM.uavs())
UAVs.push_back(RI.getAsMetadata(Context));
for (const ResourceInfo &RI : DRM.cbuffers())
CBufs.push_back(RI.getAsMetadata(Context));
for (const ResourceInfo &RI : DRM.samplers())
Smps.push_back(RI.getAsMetadata(Context));

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;
}
Expand All @@ -46,26 +64,28 @@ 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())
ValVerMD.update(VersionTuple(1, 0));
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();
}
Expand All @@ -80,17 +100,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;
}
};
Expand All @@ -105,6 +128,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",
Expand Down
10 changes: 9 additions & 1 deletion llvm/test/CodeGen/DirectX/CreateHandle.ll
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -50,4 +50,12 @@ 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]+}}, !{{[0-9]+}}}
; CHECK-DAG: [[UAVMD]] = !{!{{[0-9]+}}, !{{[0-9]+}}}

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
10 changes: 9 additions & 1 deletion llvm/test/CodeGen/DirectX/CreateHandleFromBinding.ll
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -55,4 +55,12 @@ 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]+}}, !{{[0-9]+}}}
; CHECK-DAG: [[UAVMD]] = !{!{{[0-9]+}}, !{{[0-9]+}}}

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(none) }
Loading