Skip to content

Commit 155a5e3

Browse files
author
joaosaffran
committed
Extracting Root flags root signature element from llvm ir metadata
1 parent bb27d5e commit 155a5e3

File tree

13 files changed

+373
-0
lines changed

13 files changed

+373
-0
lines changed

llvm/include/llvm/Analysis/DXILMetadataAnalysis.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_ANALYSIS_DXILMETADATA_H
1111

1212
#include "llvm/ADT/SmallVector.h"
13+
#include "llvm/Analysis/DXILRootSignature.h"
1314
#include "llvm/IR/PassManager.h"
1415
#include "llvm/Pass.h"
1516
#include "llvm/Support/VersionTuple.h"
@@ -37,6 +38,7 @@ struct ModuleMetadataInfo {
3738
Triple::EnvironmentType ShaderProfile{Triple::UnknownEnvironment};
3839
VersionTuple ValidatorVersion{};
3940
SmallVector<EntryProperties> EntryPropertyVec{};
41+
root_signature::VersionedRootSignatureDesc RootSignatureDesc;
4042
void print(raw_ostream &OS) const;
4143
};
4244

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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 "llvm/Support/ScopedPrinter.h"
19+
namespace llvm {
20+
namespace dxil {
21+
namespace root_signature {
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 class RootSignatureVersion {
33+
Version_1 = 1,
34+
Version_1_0 = 1,
35+
Version_1_1 = 2,
36+
Version_1_2 = 3
37+
};
38+
39+
enum RootSignatureFlags : uint32_t {
40+
None = 0,
41+
AllowInputAssemblerInputLayout = 0x1,
42+
DenyVertexShaderRootAccess = 0x2,
43+
DenyHullShaderRootAccess = 0x4,
44+
DenyDomainShaderRootAccess = 0x8,
45+
DenyGeometryShaderRootAccess = 0x10,
46+
DenyPixelShaderRootAccess = 0x20,
47+
AllowStreamOutput = 0x40,
48+
LocalRootSignature = 0x80,
49+
DenyAmplificationShaderRootAccess = 0x100,
50+
DenyMeshShaderRootAccess = 0x200,
51+
CBVSRVUAVHeapDirectlyIndexed = 0x400,
52+
SamplerHeapDirectlyIndexed = 0x800,
53+
AllowLowTierReservedHwCbLimit = 0x80000000,
54+
ValidFlags = 0x80000fff
55+
};
56+
57+
struct DxilRootSignatureDesc1_0 {
58+
RootSignatureFlags Flags;
59+
};
60+
61+
struct VersionedRootSignatureDesc {
62+
RootSignatureVersion Version;
63+
union {
64+
DxilRootSignatureDesc1_0 Desc_1_0;
65+
};
66+
67+
bool isPopulated();
68+
69+
void swapBytes();
70+
};
71+
72+
class MetadataParser {
73+
public:
74+
NamedMDNode *Root;
75+
MetadataParser(NamedMDNode *Root) : Root(Root) {}
76+
77+
bool Parse(RootSignatureVersion Version, VersionedRootSignatureDesc *Desc);
78+
79+
private:
80+
bool ParseRootFlags(MDNode *RootFlagRoot, VersionedRootSignatureDesc *Desc);
81+
bool ParseRootSignatureElement(MDNode *Element,
82+
VersionedRootSignatureDesc *Desc);
83+
};
84+
} // namespace root_signature
85+
} // namespace dxil
86+
} // namespace llvm
87+
88+
#endif // LLVM_DIRECTX_HLSLROOTSIGNATURE_H

llvm/include/llvm/BinaryFormat/DXContainerConstants.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CONTAINER_PART(DXIL)
44
CONTAINER_PART(SFI0)
55
CONTAINER_PART(HASH)
66
CONTAINER_PART(PSV0)
7+
CONTAINER_PART(RTS0)
78
CONTAINER_PART(ISG1)
89
CONTAINER_PART(OSG1)
910
CONTAINER_PART(PSG1)

llvm/include/llvm/Object/DXContainer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "llvm/ADT/SmallVector.h"
1919
#include "llvm/ADT/StringRef.h"
20+
#include "llvm/Analysis/DXILRootSignature.h"
2021
#include "llvm/BinaryFormat/DXContainer.h"
2122
#include "llvm/Support/Error.h"
2223
#include "llvm/Support/MemoryBufferRef.h"
@@ -287,6 +288,7 @@ class DXContainer {
287288
std::optional<uint64_t> ShaderFeatureFlags;
288289
std::optional<dxbc::ShaderHash> Hash;
289290
std::optional<DirectX::PSVRuntimeInfo> PSVInfo;
291+
std::optional<dxil::root_signature::VersionedRootSignatureDesc> RootSignature;
290292
DirectX::Signature InputSignature;
291293
DirectX::Signature OutputSignature;
292294
DirectX::Signature PatchConstantSignature;
@@ -296,6 +298,7 @@ class DXContainer {
296298
Error parseDXILHeader(StringRef Part);
297299
Error parseShaderFeatureFlags(StringRef Part);
298300
Error parseHash(StringRef Part);
301+
Error parseRootSignature(StringRef Part);
299302
Error parsePSVInfo(StringRef Part);
300303
Error parseSignature(StringRef Part, DirectX::Signature &Array);
301304
friend class PartIterator;
@@ -382,6 +385,11 @@ class DXContainer {
382385

383386
std::optional<dxbc::ShaderHash> getShaderHash() const { return Hash; }
384387

388+
std::optional<dxil::root_signature::VersionedRootSignatureDesc>
389+
getRootSignature() const {
390+
return RootSignature;
391+
}
392+
385393
const std::optional<DirectX::PSVRuntimeInfo> &getPSVInfo() const {
386394
return PSVInfo;
387395
};

llvm/include/llvm/ObjectYAML/DXContainerYAML.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define LLVM_OBJECTYAML_DXCONTAINERYAML_H
1717

1818
#include "llvm/ADT/StringRef.h"
19+
#include "llvm/Analysis/DXILRootSignature.h"
1920
#include "llvm/BinaryFormat/DXContainer.h"
2021
#include "llvm/ObjectYAML/YAML.h"
2122
#include "llvm/Support/YAMLTraits.h"
@@ -149,6 +150,13 @@ struct Signature {
149150
llvm::SmallVector<SignatureParameter> Parameters;
150151
};
151152

153+
struct RootSignature {
154+
RootSignature() = default;
155+
156+
dxil::root_signature::RootSignatureVersion Version;
157+
dxil::root_signature::RootSignatureFlags Flags;
158+
};
159+
152160
struct Part {
153161
Part() = default;
154162
Part(std::string N, uint32_t S) : Name(N), Size(S) {}
@@ -159,6 +167,7 @@ struct Part {
159167
std::optional<ShaderHash> Hash;
160168
std::optional<PSVInfo> Info;
161169
std::optional<DXContainerYAML::Signature> Signature;
170+
std::optional<DXContainerYAML::RootSignature> RootSignature;
162171
};
163172

164173
struct Object {
@@ -241,6 +250,11 @@ template <> struct MappingTraits<DXContainerYAML::Signature> {
241250
static void mapping(IO &IO, llvm::DXContainerYAML::Signature &El);
242251
};
243252

253+
template <> struct MappingTraits<DXContainerYAML::RootSignature> {
254+
static void mapping(IO &IO,
255+
llvm::DXContainerYAML::RootSignature &RootSignature);
256+
};
257+
244258
} // namespace yaml
245259

246260
} // namespace llvm

llvm/lib/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ add_llvm_component_library(LLVMAnalysis
6262
DominanceFrontier.cpp
6363
DXILResource.cpp
6464
DXILMetadataAnalysis.cpp
65+
DXILRootSignature.cpp
6566
FunctionPropertiesAnalysis.cpp
6667
GlobalsModRef.cpp
6768
GuardUtils.cpp

llvm/lib/Analysis/DXILMetadataAnalysis.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
#include "llvm/ADT/APInt.h"
1111
#include "llvm/ADT/StringExtras.h"
1212
#include "llvm/ADT/StringRef.h"
13+
#include "llvm/Analysis/DXILRootSignature.h"
1314
#include "llvm/IR/Constants.h"
1415
#include "llvm/IR/Instructions.h"
1516
#include "llvm/IR/Metadata.h"
1617
#include "llvm/IR/Module.h"
1718
#include "llvm/InitializePasses.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

@@ -28,6 +31,7 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
2831
MMDAI.DXILVersion = TT.getDXILVersion();
2932
MMDAI.ShaderModelVersion = TT.getOSVersion();
3033
MMDAI.ShaderProfile = TT.getEnvironment();
34+
3135
NamedMDNode *ValidatorVerNode = M.getNamedMetadata("dx.valver");
3236
if (ValidatorVerNode) {
3337
auto *ValVerMD = cast<MDNode>(ValidatorVerNode->getOperand(0));
@@ -37,6 +41,19 @@ static ModuleMetadataInfo collectMetadataInfo(Module &M) {
3741
VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
3842
}
3943

44+
NamedMDNode *RootSignatureNode = M.getNamedMetadata("dx.rootsignatures");
45+
if (RootSignatureNode) {
46+
auto RootSignatureParser =
47+
root_signature::MetadataParser(RootSignatureNode);
48+
49+
root_signature::VersionedRootSignatureDesc Desc;
50+
51+
RootSignatureParser.Parse(root_signature::RootSignatureVersion::Version_1,
52+
&Desc);
53+
54+
MMDAI.RootSignatureDesc = Desc;
55+
}
56+
4057
// For all HLSL Shader functions
4158
for (auto &F : M.functions()) {
4259
if (!F.hasFnAttribute("hlsl.shader"))
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//===- DXILRootSignature.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/Analysis/DXILRootSignature.h"
16+
#include "llvm/ADT/StringSwitch.h"
17+
#include "llvm/IR/Constants.h"
18+
#include "llvm/IR/Metadata.h"
19+
#include "llvm/Support/ErrorHandling.h"
20+
#include <cassert>
21+
22+
namespace llvm {
23+
namespace dxil {
24+
25+
bool root_signature::MetadataParser::Parse(RootSignatureVersion Version,
26+
VersionedRootSignatureDesc *Desc) {
27+
Desc->Version = Version;
28+
bool HasError = false;
29+
30+
for (unsigned int Sid = 0; Sid < Root->getNumOperands(); Sid++) {
31+
// This should be an if, for error handling
32+
MDNode *Node = cast<MDNode>(Root->getOperand(Sid));
33+
34+
// Not sure what use this for...
35+
Metadata *Func = Node->getOperand(0).get();
36+
37+
// This should be an if, for error handling
38+
MDNode *Elements = cast<MDNode>(Node->getOperand(1).get());
39+
40+
for (unsigned int Eid = 0; Eid < Elements->getNumOperands(); Eid++) {
41+
MDNode *Element = cast<MDNode>(Elements->getOperand(Eid));
42+
43+
HasError = HasError || ParseRootSignatureElement(Element, Desc);
44+
}
45+
}
46+
return HasError;
47+
}
48+
49+
bool root_signature::MetadataParser::ParseRootFlags(
50+
MDNode *RootFlagNode, VersionedRootSignatureDesc *Desc) {
51+
52+
assert(RootFlagNode->getNumOperands() == 2 &&
53+
"Invalid format for RootFlag Element");
54+
auto *Flag = mdconst::extract<ConstantInt>(RootFlagNode->getOperand(1));
55+
auto Value = (RootSignatureFlags)Flag->getZExtValue();
56+
57+
if ((Value & ~RootSignatureFlags::ValidFlags) != RootSignatureFlags::None)
58+
return true;
59+
60+
switch (Desc->Version) {
61+
62+
case RootSignatureVersion::Version_1:
63+
Desc->Desc_1_0.Flags = (RootSignatureFlags)Value;
64+
break;
65+
case RootSignatureVersion::Version_1_1:
66+
case RootSignatureVersion::Version_1_2:
67+
llvm_unreachable("Not implemented yet");
68+
break;
69+
}
70+
return false;
71+
}
72+
73+
bool root_signature::MetadataParser::ParseRootSignatureElement(
74+
MDNode *Element, VersionedRootSignatureDesc *Desc) {
75+
MDString *ElementText = cast<MDString>(Element->getOperand(0));
76+
77+
assert(ElementText != nullptr && "First preoperty of element is not ");
78+
79+
RootSignatureElementKind ElementKind =
80+
StringSwitch<RootSignatureElementKind>(ElementText->getString())
81+
.Case("RootFlags", RootSignatureElementKind::RootFlags)
82+
.Case("RootConstants", RootSignatureElementKind::RootConstants)
83+
.Case("RootCBV", RootSignatureElementKind::RootDescriptor)
84+
.Case("RootSRV", RootSignatureElementKind::RootDescriptor)
85+
.Case("RootUAV", RootSignatureElementKind::RootDescriptor)
86+
.Case("Sampler", RootSignatureElementKind::RootDescriptor)
87+
.Case("DescriptorTable", RootSignatureElementKind::DescriptorTable)
88+
.Case("StaticSampler", RootSignatureElementKind::StaticSampler)
89+
.Default(RootSignatureElementKind::None);
90+
91+
switch (ElementKind) {
92+
93+
case RootSignatureElementKind::RootFlags: {
94+
return ParseRootFlags(Element, Desc);
95+
break;
96+
}
97+
98+
case RootSignatureElementKind::RootConstants:
99+
case RootSignatureElementKind::RootDescriptor:
100+
case RootSignatureElementKind::DescriptorTable:
101+
case RootSignatureElementKind::StaticSampler:
102+
case RootSignatureElementKind::None:
103+
llvm_unreachable("Not Implemented yet");
104+
break;
105+
}
106+
107+
return true;
108+
}
109+
} // namespace dxil
110+
} // namespace llvm

llvm/lib/Object/DXContainer.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/Object/DXContainer.h"
10+
#include "llvm/Analysis/DXILRootSignature.h"
1011
#include "llvm/BinaryFormat/DXContainer.h"
1112
#include "llvm/Object/Error.h"
1213
#include "llvm/Support/Alignment.h"
14+
#include "llvm/Support/ErrorHandling.h"
1315
#include "llvm/Support/FormatVariadic.h"
1416

1517
using namespace llvm;
@@ -92,6 +94,14 @@ Error DXContainer::parseHash(StringRef Part) {
9294
return Error::success();
9395
}
9496

97+
Error DXContainer::parseRootSignature(StringRef Part) {
98+
dxil::root_signature::VersionedRootSignatureDesc Desc;
99+
if (Error Err = readStruct(Part, Part.begin(), Desc))
100+
return Err;
101+
RootSignature = Desc;
102+
return Error::success();
103+
}
104+
95105
Error DXContainer::parsePSVInfo(StringRef Part) {
96106
if (PSVInfo)
97107
return parseFailed("More than one PSV0 part is present in the file");
@@ -192,6 +202,11 @@ Error DXContainer::parsePartOffsets() {
192202
return Err;
193203
break;
194204
case dxbc::PartType::Unknown:
205+
break;
206+
case dxbc::PartType::RTS0:
207+
if (Error Err = parseRootSignature(PartData))
208+
return Err;
209+
195210
break;
196211
}
197212
}

0 commit comments

Comments
 (0)