Skip to content

Commit 71f6d8b

Browse files
author
joaosaffran
committed
adding metadata extraction
1 parent 6aaa0a5 commit 71f6d8b

File tree

6 files changed

+227
-0
lines changed

6 files changed

+227
-0
lines changed

llvm/include/llvm/Analysis/DXILMetadataAnalysis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
#include "llvm/ADT/SmallVector.h"
1313
#include "llvm/IR/PassManager.h"
14+
#include "llvm/MC/DXContainerRootSignature.h"
1415
#include "llvm/Pass.h"
1516
#include "llvm/Support/VersionTuple.h"
1617
#include "llvm/TargetParser/Triple.h"
18+
#include <optional>
1719

1820
namespace llvm {
1921

@@ -37,6 +39,7 @@ struct ModuleMetadataInfo {
3739
Triple::EnvironmentType ShaderProfile{Triple::UnknownEnvironment};
3840
VersionTuple ValidatorVersion{};
3941
SmallVector<EntryProperties> EntryPropertyVec{};
42+
std::optional<mcdxbc::RootSignatureDesc> RootSignatureDesc;
4043
void print(raw_ostream &OS) const;
4144
};
4245

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===- DXILRootSignature.h - DXIL Root Signature helper objects -----------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file This file contains helper objects for working with DXIL Root
10+
/// Signatures.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_DIRECTX_HLSLROOTSIGNATURE_H
15+
#define LLVM_DIRECTX_HLSLROOTSIGNATURE_H
16+
17+
#include "llvm/IR/Metadata.h"
18+
#include <memory>
19+
20+
namespace llvm {
21+
namespace mcdxbc {
22+
23+
enum class RootSignatureElementKind {
24+
None = 0,
25+
RootFlags = 1,
26+
RootConstants = 2,
27+
RootDescriptor = 3,
28+
DescriptorTable = 4,
29+
StaticSampler = 5
30+
};
31+
32+
enum RootSignatureFlags : uint32_t {
33+
None = 0,
34+
AllowInputAssemblerInputLayout = 0x1,
35+
DenyVertexShaderRootAccess = 0x2,
36+
DenyHullShaderRootAccess = 0x4,
37+
DenyDomainShaderRootAccess = 0x8,
38+
DenyGeometryShaderRootAccess = 0x10,
39+
DenyPixelShaderRootAccess = 0x20,
40+
AllowStreamOutput = 0x40,
41+
LocalRootSignature = 0x80,
42+
DenyAmplificationShaderRootAccess = 0x100,
43+
DenyMeshShaderRootAccess = 0x200,
44+
CBVSRVUAVHeapDirectlyIndexed = 0x400,
45+
SamplerHeapDirectlyIndexed = 0x800,
46+
AllowLowTierReservedHwCbLimit = 0x80000000,
47+
ValidFlags = 0x80000fff
48+
};
49+
50+
struct RootSignatureDesc {
51+
uint32_t Version;
52+
RootSignatureFlags Flags;
53+
54+
void swapBytes() {
55+
sys::swapByteOrder(Version);
56+
sys::swapByteOrder(Flags);
57+
}
58+
};
59+
60+
class RootSignatureDescWriter {
61+
private:
62+
RootSignatureDesc *Desc;
63+
64+
public:
65+
RootSignatureDescWriter(RootSignatureDesc *Desc) : Desc(Desc) {}
66+
67+
void write(raw_ostream &OS,
68+
uint32_t Version = std::numeric_limits<uint32_t>::max());
69+
};
70+
71+
} // namespace mcdxbc
72+
} // namespace llvm
73+
74+
#endif // LLVM_DIRECTX_HLSLROOTSIGNATURE_H

llvm/lib/Analysis/DXILMetadataAnalysis.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,99 @@
1515
#include "llvm/IR/Metadata.h"
1616
#include "llvm/IR/Module.h"
1717
#include "llvm/InitializePasses.h"
18+
#include "llvm/MC/DXContainerRootSignature.h"
19+
#include "llvm/Support/Casting.h"
1820
#include "llvm/Support/ErrorHandling.h"
21+
#include <memory>
1922

2023
#define DEBUG_TYPE "dxil-metadata-analysis"
2124

2225
using namespace llvm;
2326
using namespace dxil;
27+
using namespace llvm::mcdxbc;
28+
29+
static bool parseRootFlags(MDNode *RootFlagNode, RootSignatureDesc *Desc) {
30+
31+
assert(RootFlagNode->getNumOperands() == 2 &&
32+
"Invalid format for RootFlag Element");
33+
auto *Flag = mdconst::extract<ConstantInt>(RootFlagNode->getOperand(1));
34+
auto Value = (RootSignatureFlags)Flag->getZExtValue();
35+
36+
if ((Value & ~RootSignatureFlags::ValidFlags) != RootSignatureFlags::None)
37+
return true;
38+
39+
Desc->Flags = Value;
40+
return false;
41+
}
42+
43+
static bool parseRootSignatureElement(MDNode *Element,
44+
RootSignatureDesc *Desc) {
45+
MDString *ElementText = cast<MDString>(Element->getOperand(0));
46+
47+
assert(ElementText != nullptr && "First preoperty of element is not ");
48+
49+
RootSignatureElementKind ElementKind =
50+
StringSwitch<RootSignatureElementKind>(ElementText->getString())
51+
.Case("RootFlags", RootSignatureElementKind::RootFlags)
52+
.Case("RootConstants", RootSignatureElementKind::RootConstants)
53+
.Case("RootCBV", RootSignatureElementKind::RootDescriptor)
54+
.Case("RootSRV", RootSignatureElementKind::RootDescriptor)
55+
.Case("RootUAV", RootSignatureElementKind::RootDescriptor)
56+
.Case("Sampler", RootSignatureElementKind::RootDescriptor)
57+
.Case("DescriptorTable", RootSignatureElementKind::DescriptorTable)
58+
.Case("StaticSampler", RootSignatureElementKind::StaticSampler)
59+
.Default(RootSignatureElementKind::None);
60+
61+
switch (ElementKind) {
62+
63+
case RootSignatureElementKind::RootFlags: {
64+
return parseRootFlags(Element, Desc);
65+
break;
66+
}
67+
68+
case RootSignatureElementKind::RootConstants:
69+
case RootSignatureElementKind::RootDescriptor:
70+
case RootSignatureElementKind::DescriptorTable:
71+
case RootSignatureElementKind::StaticSampler:
72+
case RootSignatureElementKind::None:
73+
llvm_unreachable("Not Implemented yet");
74+
break;
75+
}
76+
77+
return true;
78+
}
79+
80+
bool parseRootSignature(RootSignatureDesc *Desc, int32_t Version,
81+
NamedMDNode *Root) {
82+
Desc->Version = Version;
83+
bool HasError = false;
84+
85+
for (unsigned int Sid = 0; Sid < Root->getNumOperands(); Sid++) {
86+
// This should be an if, for error handling
87+
MDNode *Node = cast<MDNode>(Root->getOperand(Sid));
88+
89+
// Not sure what use this for...
90+
Metadata *Func = Node->getOperand(0).get();
91+
92+
// This should be an if, for error handling
93+
MDNode *Elements = cast<MDNode>(Node->getOperand(1).get());
94+
95+
for (unsigned int Eid = 0; Eid < Elements->getNumOperands(); Eid++) {
96+
MDNode *Element = cast<MDNode>(Elements->getOperand(Eid));
97+
98+
HasError = HasError || parseRootSignatureElement(Element, Desc);
99+
}
100+
}
101+
return HasError;
102+
}
24103

25104
static ModuleMetadataInfo collectMetadataInfo(Module &M) {
26105
ModuleMetadataInfo MMDAI;
27106
Triple TT(Triple(M.getTargetTriple()));
28107
MMDAI.DXILVersion = TT.getDXILVersion();
29108
MMDAI.ShaderModelVersion = TT.getOSVersion();
30109
MMDAI.ShaderProfile = TT.getEnvironment();
110+
31111
NamedMDNode *ValidatorVerNode = M.getNamedMetadata("dx.valver");
32112
if (ValidatorVerNode) {
33113
auto *ValVerMD = cast<MDNode>(ValidatorVerNode->getOperand(0));
@@ -37,6 +117,15 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
37117
VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
38118
}
39119

120+
NamedMDNode *RootSignatureNode = M.getNamedMetadata("dx.rootsignatures");
121+
if (RootSignatureNode) {
122+
mcdxbc::RootSignatureDesc Desc;
123+
124+
parseRootSignature(&Desc, 1, RootSignatureNode);
125+
126+
MMDAI.RootSignatureDesc = Desc;
127+
}
128+
40129
// For all HLSL Shader functions
41130
for (auto &F : M.functions()) {
42131
if (!F.hasFnAttribute("hlsl.shader"))

llvm/lib/MC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_llvm_component_library(LLVMMC
22
ConstantPools.cpp
33
DXContainerPSVInfo.cpp
4+
DXContainerRootSignature.cpp
45
ELFObjectWriter.cpp
56
GOFFObjectWriter.cpp
67
MCAsmBackend.cpp
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===- DXContainerRootSignature.cpp - DXIL Root Signature helper objects
2+
//-----------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file This file contains the parsing logic to extract root signature data
11+
/// from LLVM IR metadata.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "llvm/MC/DXContainerRootSignature.h"
16+
#include "llvm/ADT/StringSwitch.h"
17+
#include "llvm/BinaryFormat/DXContainer.h"
18+
#include "llvm/IR/Constants.h"
19+
#include "llvm/IR/Metadata.h"
20+
#include "llvm/Support/ErrorHandling.h"
21+
#include "llvm/Support/SwapByteOrder.h"
22+
#include <cassert>
23+
#include <cstdint>
24+
25+
using namespace llvm;
26+
using namespace llvm::mcdxbc;
27+
28+
void RootSignatureDescWriter::write(raw_ostream &OS, uint32_t Version) {
29+
dxbc::RootSignatureDesc Out{Desc->Version, Desc->Flags};
30+
31+
if (sys::IsBigEndianHost) {
32+
Out.swapBytes();
33+
}
34+
35+
OS.write(reinterpret_cast<const char *>(&Out), sizeof(RootSignatureDesc));
36+
}

llvm/lib/Target/DirectX/DXContainerGlobals.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
#include "llvm/IR/Module.h"
2424
#include "llvm/InitializePasses.h"
2525
#include "llvm/MC/DXContainerPSVInfo.h"
26+
#include "llvm/MC/DXContainerRootSignature.h"
2627
#include "llvm/Pass.h"
2728
#include "llvm/Support/MD5.h"
2829
#include "llvm/Transforms/Utils/ModuleUtils.h"
30+
#include <optional>
2931

3032
using namespace llvm;
3133
using namespace llvm::dxil;
@@ -41,6 +43,7 @@ class DXContainerGlobals : public llvm::ModulePass {
4143
GlobalVariable *buildSignature(Module &M, Signature &Sig, StringRef Name,
4244
StringRef SectionName);
4345
void addSignature(Module &M, SmallVector<GlobalValue *> &Globals);
46+
void addRootSignature(Module &M, SmallVector<GlobalValue *> &Globals);
4447
void addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV);
4548
void addPipelineStateValidationInfo(Module &M,
4649
SmallVector<GlobalValue *> &Globals);
@@ -73,6 +76,7 @@ bool DXContainerGlobals::runOnModule(Module &M) {
7376
Globals.push_back(getFeatureFlags(M));
7477
Globals.push_back(computeShaderHash(M));
7578
addSignature(M, Globals);
79+
addRootSignature(M, Globals);
7680
addPipelineStateValidationInfo(M, Globals);
7781
appendToCompilerUsed(M, Globals);
7882
return true;
@@ -144,6 +148,26 @@ void DXContainerGlobals::addSignature(Module &M,
144148
Globals.emplace_back(buildSignature(M, OutputSig, "dx.osg1", "OSG1"));
145149
}
146150

151+
void DXContainerGlobals::addRootSignature(Module &M,
152+
SmallVector<GlobalValue *> &Globals) {
153+
154+
std::optional<RootSignatureDesc> Desc =
155+
getAnalysis<DXILMetadataAnalysisWrapperPass>()
156+
.getModuleMetadata()
157+
.RootSignatureDesc;
158+
if (!Desc.has_value())
159+
return;
160+
161+
SmallString<256> Data;
162+
raw_svector_ostream OS(Data);
163+
RootSignatureDescWriter writer(&Desc.value());
164+
writer.write(OS);
165+
166+
Constant *Constant =
167+
ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);
168+
Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.rts0", "RTS0"));
169+
}
170+
147171
void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {
148172
const DXILBindingMap &DBM =
149173
getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();

0 commit comments

Comments
 (0)