Skip to content

Commit 8f92a68

Browse files
author
joaosaffran
committed
implementation draft
2 parents dd2f7ca + 2edd215 commit 8f92a68

File tree

4 files changed

+161
-53
lines changed

4 files changed

+161
-53
lines changed

llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "DXILPostOptimizationValidation.h"
10-
#include "DXILRootSignature.h"
1110
#include "DXILShaderFlags.h"
1211
#include "DirectX.h"
13-
#include "llvm/ADT/IntervalMap.h"
1412
#include "llvm/ADT/STLForwardCompat.h"
1513
#include "llvm/ADT/SmallString.h"
1614
#include "llvm/Analysis/DXILMetadataAnalysis.h"
@@ -21,6 +19,7 @@
2119
#include "llvm/IR/IntrinsicsDirectX.h"
2220
#include "llvm/IR/Module.h"
2321
#include "llvm/InitializePasses.h"
22+
#include <optional>
2423

2524
#define DEBUG_TYPE "dxil-post-optimization-validation"
2625

@@ -87,9 +86,24 @@ static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
8786
}
8887
}
8988
}
90-
uint64_t combine_uint32_to_uint64(uint32_t high, uint32_t low) {
91-
return (static_cast<uint64_t>(high) << 32) | low;
92-
}
89+
90+
static void reportRegNotBound(Module &M,
91+
ResourceInfo::ResourceBinding Binding) {
92+
// TODO
93+
}
94+
95+
std::optional<mcdxbc::RootSignatureDesc>
96+
getRootSignature(RootSignatureBindingInfo &RSBI,
97+
dxil::ModuleMetadataInfo &MMI) {
98+
if (MMI.EntryPropertyVec.size() == 0)
99+
return std::nullopt;
100+
std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
101+
RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
102+
if (!RootSigDesc)
103+
return std::nullopt;
104+
return RootSigDesc;
105+
}
106+
93107
static void reportErrors(Module &M, DXILResourceMap &DRM,
94108
DXILResourceBindingInfo &DRBI,
95109
RootSignatureBindingInfo &RSBI,
@@ -102,54 +116,35 @@ static void reportErrors(Module &M, DXILResourceMap &DRM,
102116

103117
assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
104118
"DXILResourceImplicitBinding pass");
105-
// Assuming this is used to validate only the root signature assigned to the
106-
// entry function.
107-
//Start test stuff
108-
if(MMI.EntryPropertyVec.size() == 0)
109-
return;
110119

111-
std::optional<mcdxbc::RootSignatureDesc> RootSigDesc =
112-
RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
113-
if (!RootSigDesc)
114-
return;
120+
if (auto RSD = getRootSignature(RSBI, MMI)) {
115121

116-
using MapT = llvm::IntervalMap<uint64_t, llvm::dxil::ResourceInfo::ResourceBinding, sizeof(llvm::dxil::ResourceInfo::ResourceBinding), llvm::IntervalMapInfo<uint64_t>>;
117-
MapT::Allocator Allocator;
118-
MapT BindingsMap(Allocator);
119-
auto RSD = *RootSigDesc;
120-
for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
121-
const auto &[Type, Loc] =
122-
RootSigDesc->ParametersContainer.getTypeAndLocForParameter(I);
123-
switch (Type) {
124-
case llvm::to_underlying(dxbc::RootParameterType::CBV):{
125-
dxbc::RTS0::v2::RootDescriptor Desc =
126-
RootSigDesc->ParametersContainer.getRootDescriptor(Loc);
127-
128-
llvm::dxil::ResourceInfo::ResourceBinding Binding;
129-
Binding.LowerBound = Desc.ShaderRegister;
130-
Binding.Space = Desc.RegisterSpace;
131-
Binding.Size = 1;
132-
133-
BindingsMap.insert(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1), Binding);
134-
break;
135-
}
136-
// case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):{
137-
// mcdxbc::DescriptorTable Table =
138-
// RootSigDesc->ParametersContainer.getDescriptorTable(Loc);
139-
// for (const dxbc::RTS0::v2::DescriptorRange &Range : Table){
140-
// Range.
141-
// }
142-
143-
// break;
144-
// }
122+
RootSignatureBindingValidation Validation;
123+
Validation.addRsBindingInfo(*RSD);
124+
125+
for (const auto &CBuf : DRM.cbuffers()) {
126+
ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
127+
if (!Validation.checkCregBinding(Binding.Space, Binding.LowerBound,
128+
Binding.Space,
129+
Binding.LowerBound + Binding.Size - 1))
130+
reportRegNotBound(M, Binding);
145131
}
146132

147-
}
133+
for (const auto &CBuf : DRM.srvs()) {
134+
ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
135+
if (!Validation.checkTRegBinding(Binding.Space, Binding.LowerBound,
136+
Binding.Space,
137+
Binding.LowerBound + Binding.Size - 1))
138+
reportRegNotBound(M, Binding);
139+
}
148140

149-
for(const auto &CBuf : DRM.cbuffers()) {
150-
auto Binding = CBuf.getBinding();
151-
if(!BindingsMap.overlaps(combine_uint32_to_uint64(Binding.Space, Binding.LowerBound), combine_uint32_to_uint64(Binding.Space, Binding.LowerBound + Binding.Size -1)))
152-
auto X = 1;
141+
for (const auto &CBuf : DRM.uavs()) {
142+
ResourceInfo::ResourceBinding Binding = CBuf.getBinding();
143+
if (!Validation.checkURegBinding(Binding.Space, Binding.LowerBound,
144+
Binding.Space,
145+
Binding.LowerBound + Binding.Size - 1))
146+
reportRegNotBound(M, Binding);
147+
}
153148
}
154149
}
155150
} // namespace
@@ -174,7 +169,7 @@ class DXILPostOptimizationValidationLegacy : public ModulePass {
174169
DXILResourceBindingInfo &DRBI =
175170
getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
176171

177-
RootSignatureBindingInfo& RSBI =
172+
RootSignatureBindingInfo &RSBI =
178173
getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
179174
dxil::ModuleMetadataInfo &MMI =
180175
getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();

llvm/lib/Target/DirectX/DXILPostOptimizationValidation.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,112 @@
1414
#ifndef LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
1515
#define LLVM_LIB_TARGET_DIRECTX_DXILPOSTOPTIMIZATIONVALIDATION_H
1616

17+
#include "DXILRootSignature.h"
18+
#include "llvm/ADT/IntervalMap.h"
19+
#include "llvm/ADT/STLForwardCompat.h"
20+
#include "llvm/Analysis/DXILResource.h"
21+
#include "llvm/BinaryFormat/DXContainer.h"
1722
#include "llvm/IR/PassManager.h"
23+
#include "llvm/Support/ErrorHandling.h"
24+
#include <cstdint>
1825

1926
namespace llvm {
2027

28+
static uint64_t combineUint32ToUint64(uint32_t High, uint32_t Low) {
29+
return (static_cast<uint64_t>(High) << 32) | Low;
30+
}
31+
32+
// This should be somewhere else
33+
class RootSignatureBindingValidation {
34+
using MapT =
35+
llvm::IntervalMap<uint64_t, dxil::ResourceInfo::ResourceBinding,
36+
sizeof(llvm::dxil::ResourceInfo::ResourceBinding),
37+
llvm::IntervalMapInfo<uint64_t>>;
38+
39+
private:
40+
MapT::Allocator Allocator;
41+
MapT CRegBindingsMap;
42+
MapT TRegBindingsMap;
43+
MapT URegBindingsMap;
44+
45+
void addRange(dxbc::RTS0::v2::RootDescriptor Desc, uint32_t Type) {
46+
assert((Type == llvm::to_underlying(dxbc::RootParameterType::CBV) ||
47+
Type == llvm::to_underlying(dxbc::RootParameterType::SRV) ||
48+
Type == llvm::to_underlying(dxbc::RootParameterType::UAV)) &&
49+
"Invalid Type");
50+
51+
llvm::dxil::ResourceInfo::ResourceBinding Binding;
52+
Binding.LowerBound = Desc.ShaderRegister;
53+
Binding.Space = Desc.RegisterSpace;
54+
Binding.Size = 1;
55+
56+
uint64_t LowRange =
57+
combineUint32ToUint64(Binding.Space, Binding.LowerBound);
58+
uint64_t HighRange = combineUint32ToUint64(
59+
Binding.Space, Binding.LowerBound + Binding.Size - 1);
60+
61+
switch (Type) {
62+
63+
case llvm::to_underlying(dxbc::RootParameterType::CBV):
64+
CRegBindingsMap.insert(LowRange, HighRange, Binding);
65+
break;
66+
case llvm::to_underlying(dxbc::RootParameterType::SRV):
67+
TRegBindingsMap.insert(LowRange, HighRange, Binding);
68+
break;
69+
case llvm::to_underlying(dxbc::RootParameterType::UAV):
70+
URegBindingsMap.insert(LowRange, HighRange, Binding);
71+
break;
72+
}
73+
llvm_unreachable("Invalid Type in add Range Method");
74+
}
75+
76+
public:
77+
RootSignatureBindingValidation()
78+
: Allocator(), CRegBindingsMap(Allocator), TRegBindingsMap(Allocator),
79+
URegBindingsMap(Allocator) {}
80+
81+
void addRsBindingInfo(mcdxbc::RootSignatureDesc &RSD) {
82+
for (size_t I = 0; I < RSD.ParametersContainer.size(); I++) {
83+
const auto &[Type, Loc] =
84+
RSD.ParametersContainer.getTypeAndLocForParameter(I);
85+
86+
switch (Type) {
87+
case llvm::to_underlying(dxbc::RootParameterType::SRV):
88+
case llvm::to_underlying(dxbc::RootParameterType::UAV):
89+
case llvm::to_underlying(dxbc::RootParameterType::CBV): {
90+
dxbc::RTS0::v2::RootDescriptor Desc =
91+
RSD.ParametersContainer.getRootDescriptor(Loc);
92+
93+
addRange(Desc, Type);
94+
break;
95+
}
96+
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
97+
// TODO;
98+
break;
99+
}
100+
}
101+
}
102+
}
103+
104+
bool checkCregBinding(uint32_t StartSpace, uint32_t StartReg,
105+
uint32_t EndSpace, uint32_t EndReg) {
106+
return CRegBindingsMap.overlaps(combineUint32ToUint64(StartSpace, StartReg),
107+
combineUint32ToUint64(EndSpace, EndReg));
108+
}
109+
110+
bool checkTRegBinding(uint32_t StartSpace, uint32_t StartReg,
111+
uint32_t EndSpace, uint32_t EndReg) {
112+
return TRegBindingsMap.overlaps(combineUint32ToUint64(StartSpace, StartReg),
113+
combineUint32ToUint64(EndSpace, EndReg));
114+
}
115+
116+
bool checkURegBinding(uint32_t StartSpace, uint32_t StartReg,
117+
uint32_t EndSpace, uint32_t EndReg) {
118+
return URegBindingsMap.overlaps(combineUint32ToUint64(StartSpace, StartReg),
119+
combineUint32ToUint64(EndSpace, EndReg));
120+
}
121+
};
122+
21123
class DXILPostOptimizationValidation
22124
: public PassInfoMixin<DXILPostOptimizationValidation> {
23125
public:

llvm/lib/Target/DirectX/DXILRootSignature.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "llvm/Support/ErrorHandling.h"
2929
#include "llvm/Support/raw_ostream.h"
3030
#include <cstdint>
31+
#include <memory>
3132
#include <optional>
3233
#include <utility>
3334

@@ -554,9 +555,12 @@ analyzeModule(Module &M) {
554555

555556
AnalysisKey RootSignatureAnalysis::Key;
556557

557-
RootSignatureBindingInfo RootSignatureAnalysis::run(Module &M,
558-
ModuleAnalysisManager &AM) {
559-
return RootSignatureBindingInfo(analyzeModule(M));
558+
RootSignatureAnalysis::Result
559+
RootSignatureAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
560+
if (!AnalysisResult)
561+
AnalysisResult = std::make_unique<RootSignatureBindingInfo>(
562+
RootSignatureBindingInfo(analyzeModule(M)));
563+
return *AnalysisResult;
560564
}
561565

562566
//===----------------------------------------------------------------------===//
@@ -635,6 +639,8 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
635639

636640
//===----------------------------------------------------------------------===//
637641
bool RootSignatureAnalysisWrapper::runOnModule(Module &M) {
642+
if (HasRun)
643+
return false;
638644
FuncToRsMap = std::make_unique<RootSignatureBindingInfo>(
639645
RootSignatureBindingInfo(analyzeModule(M)));
640646
return false;

llvm/lib/Target/DirectX/DXILRootSignature.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/IR/PassManager.h"
2020
#include "llvm/MC/DXContainerRootSignature.h"
2121
#include "llvm/Pass.h"
22+
#include <memory>
2223
#include <optional>
2324

2425
namespace llvm {
@@ -70,7 +71,10 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
7071

7172
using Result = RootSignatureBindingInfo;
7273

73-
RootSignatureBindingInfo run(Module &M, ModuleAnalysisManager &AM);
74+
Result run(Module &M, ModuleAnalysisManager &AM);
75+
76+
private:
77+
std::unique_ptr<RootSignatureBindingInfo> AnalysisResult;
7478
};
7579

7680
/// Wrapper pass for the legacy pass manager.
@@ -80,6 +84,7 @@ class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
8084
class RootSignatureAnalysisWrapper : public ModulePass {
8185
private:
8286
std::unique_ptr<RootSignatureBindingInfo> FuncToRsMap;
87+
bool HasRun = false;
8388

8489
public:
8590
static char ID;

0 commit comments

Comments
 (0)