Skip to content

Commit 8e19573

Browse files
joaosaffranjoaosaffran
and
joaosaffran
authored
[DirectX] adding support to read/write descriptor table data using obj2yaml/yaml2obj (#138315)
Closes: https://github.com/orgs/llvm/projects/4/views/22?sliceBy%5Bvalue%5D=joaosaffran&pane=issue&itemId=97332852&issue=llvm%7Cllvm-project%7C126635 --------- Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
1 parent 7625d2e commit 8e19573

13 files changed

+657
-7
lines changed

llvm/include/llvm/BinaryFormat/DXContainer.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,25 @@ enum class RootDescriptorFlag : uint32_t {
163163
#include "DXContainerConstants.def"
164164
};
165165

166+
#define DESCRIPTOR_RANGE_FLAG(Num, Val) Val = 1ull << Num,
167+
enum class DescriptorRangeFlag : uint32_t {
168+
#include "DXContainerConstants.def"
169+
};
170+
166171
#define ROOT_PARAMETER(Val, Enum) Enum = Val,
167172
enum class RootParameterType : uint32_t {
168173
#include "DXContainerConstants.def"
169174
};
170175

171176
ArrayRef<EnumEntry<RootParameterType>> getRootParameterTypes();
172177

178+
#define DESCRIPTOR_RANGE(Val, Enum) Enum = Val,
179+
enum class DescriptorRangeType : uint32_t {
180+
#include "DXContainerConstants.def"
181+
};
182+
183+
ArrayRef<EnumEntry<DescriptorRangeType>> getDescriptorRangeTypes();
184+
173185
#define ROOT_PARAMETER(Val, Enum) \
174186
case Val: \
175187
return true;
@@ -588,6 +600,21 @@ static_assert(sizeof(ProgramSignatureElement) == 32,
588600

589601
namespace RTS0 {
590602
namespace v1 {
603+
struct DescriptorRange {
604+
uint32_t RangeType;
605+
uint32_t NumDescriptors;
606+
uint32_t BaseShaderRegister;
607+
uint32_t RegisterSpace;
608+
uint32_t OffsetInDescriptorsFromTableStart;
609+
void swapBytes() {
610+
sys::swapByteOrder(RangeType);
611+
sys::swapByteOrder(NumDescriptors);
612+
sys::swapByteOrder(BaseShaderRegister);
613+
sys::swapByteOrder(RegisterSpace);
614+
sys::swapByteOrder(OffsetInDescriptorsFromTableStart);
615+
}
616+
};
617+
591618
struct RootDescriptor {
592619
uint32_t ShaderRegister;
593620
uint32_t RegisterSpace;
@@ -655,6 +682,14 @@ struct RootDescriptor : public v1::RootDescriptor {
655682
sys::swapByteOrder(Flags);
656683
}
657684
};
685+
686+
struct DescriptorRange : public v1::DescriptorRange {
687+
uint32_t Flags;
688+
void swapBytes() {
689+
v1::DescriptorRange::swapBytes();
690+
sys::swapByteOrder(Flags);
691+
}
692+
};
658693
} // namespace v2
659694
} // namespace RTS0
660695

llvm/include/llvm/BinaryFormat/DXContainerConstants.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,21 @@ ROOT_DESCRIPTOR_FLAG(3, DATA_STATIC)
8686
#endif // ROOT_DESCRIPTOR_FLAG
8787

8888

89+
// DESCRIPTOR_RANGE_FLAG(bit offset for the flag, name).
90+
#ifdef DESCRIPTOR_RANGE_FLAG
91+
92+
DESCRIPTOR_RANGE_FLAG(0, NONE)
93+
DESCRIPTOR_RANGE_FLAG(1, DESCRIPTORS_VOLATILE)
94+
DESCRIPTOR_RANGE_FLAG(2, DATA_VOLATILE)
95+
DESCRIPTOR_RANGE_FLAG(3, DATA_STATIC_WHILE_SET_AT_EXECUTE)
96+
DESCRIPTOR_RANGE_FLAG(4, DATA_STATIC)
97+
DESCRIPTOR_RANGE_FLAG(16, DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS)
98+
#undef DESCRIPTOR_RANGE_FLAG
99+
#endif // DESCRIPTOR_RANGE_FLAG
100+
89101
#ifdef ROOT_PARAMETER
90102

103+
ROOT_PARAMETER(0, DescriptorTable)
91104
ROOT_PARAMETER(1, Constants32Bit)
92105
ROOT_PARAMETER(2, CBV)
93106
ROOT_PARAMETER(3, SRV)

llvm/include/llvm/MC/DXContainerRootSignature.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,22 @@ struct RootParameterInfo {
2525
: Header(Header), Location(Location) {}
2626
};
2727

28+
struct DescriptorTable {
29+
SmallVector<dxbc::RTS0::v2::DescriptorRange> Ranges;
30+
SmallVector<dxbc::RTS0::v2::DescriptorRange>::const_iterator begin() const {
31+
return Ranges.begin();
32+
}
33+
SmallVector<dxbc::RTS0::v2::DescriptorRange>::const_iterator end() const {
34+
return Ranges.end();
35+
}
36+
};
37+
2838
struct RootParametersContainer {
2939
SmallVector<RootParameterInfo> ParametersInfo;
3040

3141
SmallVector<dxbc::RTS0::v1::RootConstants> Constants;
3242
SmallVector<dxbc::RTS0::v2::RootDescriptor> Descriptors;
43+
SmallVector<DescriptorTable> Tables;
3344

3445
void addInfo(dxbc::RTS0::v1::RootParameterHeader Header, size_t Location) {
3546
ParametersInfo.push_back(RootParameterInfo(Header, Location));
@@ -51,6 +62,12 @@ struct RootParametersContainer {
5162
Descriptors.push_back(Descriptor);
5263
}
5364

65+
void addParameter(dxbc::RTS0::v1::RootParameterHeader Header,
66+
DescriptorTable Table) {
67+
addInfo(Header, Tables.size());
68+
Tables.push_back(Table);
69+
}
70+
5471
const std::pair<uint32_t, uint32_t>
5572
getTypeAndLocForParameter(uint32_t Location) const {
5673
const RootParameterInfo &Info = ParametersInfo[Location];
@@ -70,6 +87,10 @@ struct RootParametersContainer {
7087
return Descriptors[Index];
7188
}
7289

90+
const DescriptorTable &getDescriptorTable(size_t Index) const {
91+
return Tables[Index];
92+
}
93+
7394
size_t size() const { return ParametersInfo.size(); }
7495

7596
SmallVector<RootParameterInfo>::const_iterator begin() const {

llvm/include/llvm/Object/DXContainer.h

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/Twine.h"
2121
#include "llvm/BinaryFormat/DXContainer.h"
2222
#include "llvm/Object/Error.h"
23+
#include "llvm/Support/Endian.h"
2324
#include "llvm/Support/Error.h"
2425
#include "llvm/Support/MemoryBufferRef.h"
2526
#include "llvm/TargetParser/Triple.h"
@@ -177,6 +178,50 @@ struct RootDescriptorView : RootParameterView {
177178
}
178179
};
179180

181+
struct DescriptorTable {
182+
uint32_t NumRanges;
183+
uint32_t RangesOffset;
184+
ViewArray<dxbc::RTS0::v2::DescriptorRange> Ranges;
185+
186+
typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator begin() const {
187+
return Ranges.begin();
188+
}
189+
190+
typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator end() const {
191+
return Ranges.end();
192+
}
193+
};
194+
195+
struct DescriptorTableView : RootParameterView {
196+
static bool classof(const RootParameterView *V) {
197+
return (V->Header.ParameterType ==
198+
llvm::to_underlying(dxbc::RootParameterType::DescriptorTable));
199+
}
200+
201+
// Define a type alias to access the template parameter from inside classof
202+
llvm::Expected<DescriptorTable> read(uint32_t Version) {
203+
const char *Current = ParamData.begin();
204+
DescriptorTable Table;
205+
206+
Table.NumRanges =
207+
support::endian::read<uint32_t, llvm::endianness::little>(Current);
208+
Current += sizeof(uint32_t);
209+
210+
Table.RangesOffset =
211+
support::endian::read<uint32_t, llvm::endianness::little>(Current);
212+
Current += sizeof(uint32_t);
213+
214+
size_t RangeSize = sizeof(dxbc::RTS0::v1::DescriptorRange);
215+
if (Version > 1)
216+
RangeSize = sizeof(dxbc::RTS0::v2::DescriptorRange);
217+
218+
Table.Ranges.Stride = RangeSize;
219+
Table.Ranges.Data =
220+
ParamData.substr(2 * sizeof(uint32_t), Table.NumRanges * RangeSize);
221+
return Table;
222+
}
223+
};
224+
180225
static Error parseFailed(const Twine &Msg) {
181226
return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed);
182227
}
@@ -213,6 +258,9 @@ class RootSignature {
213258
llvm::Expected<RootParameterView>
214259
getParameter(const dxbc::RTS0::v1::RootParameterHeader &Header) const {
215260
size_t DataSize;
261+
size_t EndOfSectionByte = getNumStaticSamplers() == 0
262+
? PartData.size()
263+
: getStaticSamplersOffset();
216264

217265
if (!dxbc::isValidParameterType(Header.ParameterType))
218266
return parseFailed("invalid parameter type");
@@ -229,11 +277,23 @@ class RootSignature {
229277
else
230278
DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor);
231279
break;
232-
}
233-
size_t EndOfSectionByte = getNumStaticSamplers() == 0
234-
? PartData.size()
235-
: getStaticSamplersOffset();
280+
case dxbc::RootParameterType::DescriptorTable:
281+
if (Header.ParameterOffset + sizeof(uint32_t) > EndOfSectionByte)
282+
return parseFailed("Reading structure out of file bounds");
236283

284+
uint32_t NumRanges =
285+
support::endian::read<uint32_t, llvm::endianness::little>(
286+
PartData.begin() + Header.ParameterOffset);
287+
if (Version == 1)
288+
DataSize = sizeof(dxbc::RTS0::v1::DescriptorRange) * NumRanges;
289+
else
290+
DataSize = sizeof(dxbc::RTS0::v2::DescriptorRange) * NumRanges;
291+
292+
// 4 bytes for the number of ranges in table and
293+
// 4 bytes for the ranges offset
294+
DataSize += 2 * sizeof(uint32_t);
295+
break;
296+
}
237297
if (Header.ParameterOffset + DataSize > EndOfSectionByte)
238298
return parseFailed("Reading structure out of file bounds");
239299

llvm/include/llvm/ObjectYAML/DXContainerYAML.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,25 @@ struct RootDescriptorYaml {
9090
#include "llvm/BinaryFormat/DXContainerConstants.def"
9191
};
9292

93+
struct DescriptorRangeYaml {
94+
uint32_t RangeType;
95+
uint32_t NumDescriptors;
96+
uint32_t BaseShaderRegister;
97+
uint32_t RegisterSpace;
98+
uint32_t OffsetInDescriptorsFromTableStart;
99+
100+
uint32_t getEncodedFlags() const;
101+
102+
#define DESCRIPTOR_RANGE_FLAG(Num, Val) bool Val = false;
103+
#include "llvm/BinaryFormat/DXContainerConstants.def"
104+
};
105+
106+
struct DescriptorTableYaml {
107+
uint32_t NumRanges;
108+
uint32_t RangesOffset;
109+
SmallVector<DescriptorRangeYaml> Ranges;
110+
};
111+
93112
struct RootParameterHeaderYaml {
94113
uint32_t Type;
95114
uint32_t Visibility;
@@ -113,6 +132,7 @@ struct RootParameterYamlDesc {
113132

114133
SmallVector<RootConstantsYaml> Constants;
115134
SmallVector<RootDescriptorYaml> Descriptors;
135+
SmallVector<DescriptorTableYaml> Tables;
116136

117137
template <typename T>
118138
T &getOrInsertImpl(RootParameterLocationYaml &ParamDesc,
@@ -134,6 +154,10 @@ struct RootParameterYamlDesc {
134154
return getOrInsertImpl(ParamDesc, Descriptors);
135155
}
136156

157+
DescriptorTableYaml &getOrInsertTable(RootParameterLocationYaml &ParamDesc) {
158+
return getOrInsertImpl(ParamDesc, Tables);
159+
}
160+
137161
void insertLocation(RootParameterLocationYaml &Location) {
138162
Locations.push_back(Location);
139163
}
@@ -263,6 +287,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureElement)
263287
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::PSVInfo::MaskVector)
264288
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::SignatureParameter)
265289
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::RootParameterLocationYaml)
290+
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DXContainerYAML::DescriptorRangeYaml)
266291
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::SemanticKind)
267292
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::ComponentType)
268293
LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::dxbc::PSV::InterpolationMode)
@@ -351,6 +376,14 @@ template <> struct MappingTraits<llvm::DXContainerYAML::RootDescriptorYaml> {
351376
static void mapping(IO &IO, llvm::DXContainerYAML::RootDescriptorYaml &D);
352377
};
353378

379+
template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorTableYaml> {
380+
static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorTableYaml &D);
381+
};
382+
383+
template <> struct MappingTraits<llvm::DXContainerYAML::DescriptorRangeYaml> {
384+
static void mapping(IO &IO, llvm::DXContainerYAML::DescriptorRangeYaml &D);
385+
};
386+
354387
} // namespace yaml
355388

356389
} // namespace llvm

llvm/lib/MC/DXContainerRootSignature.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ size_t RootSignatureDesc::getSize() const {
4747
Size += sizeof(dxbc::RTS0::v2::RootDescriptor);
4848

4949
break;
50+
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable):
51+
const DescriptorTable &Table =
52+
ParametersContainer.getDescriptorTable(I.Location);
53+
54+
// 4 bytes for the number of ranges in table and
55+
// 4 bytes for the ranges offset
56+
Size += 2 * sizeof(uint32_t);
57+
if (Version == 1)
58+
Size += sizeof(dxbc::RTS0::v1::DescriptorRange) * Table.Ranges.size();
59+
else
60+
Size += sizeof(dxbc::RTS0::v2::DescriptorRange) * Table.Ranges.size();
61+
break;
5062
}
5163
}
5264
return Size;
@@ -106,6 +118,27 @@ void RootSignatureDesc::write(raw_ostream &OS) const {
106118
support::endian::write(BOS, Descriptor.Flags, llvm::endianness::little);
107119
break;
108120
}
121+
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
122+
const DescriptorTable &Table =
123+
ParametersContainer.getDescriptorTable(Loc);
124+
support::endian::write(BOS, (uint32_t)Table.Ranges.size(),
125+
llvm::endianness::little);
126+
rewriteOffsetToCurrentByte(BOS, writePlaceholder(BOS));
127+
for (const auto &Range : Table) {
128+
support::endian::write(BOS, Range.RangeType, llvm::endianness::little);
129+
support::endian::write(BOS, Range.NumDescriptors,
130+
llvm::endianness::little);
131+
support::endian::write(BOS, Range.BaseShaderRegister,
132+
llvm::endianness::little);
133+
support::endian::write(BOS, Range.RegisterSpace,
134+
llvm::endianness::little);
135+
support::endian::write(BOS, Range.OffsetInDescriptorsFromTableStart,
136+
llvm::endianness::little);
137+
if (Version > 1)
138+
support::endian::write(BOS, Range.Flags, llvm::endianness::little);
139+
}
140+
break;
141+
}
109142
}
110143
}
111144
assert(Storage.size() == getSize());

llvm/lib/ObjectYAML/DXContainerEmitter.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,26 @@ void DXContainerWriter::writeParts(raw_ostream &OS) {
303303
RS.ParametersContainer.addParameter(Header, Descriptor);
304304
break;
305305
}
306+
case llvm::to_underlying(dxbc::RootParameterType::DescriptorTable): {
307+
const DXContainerYAML::DescriptorTableYaml &TableYaml =
308+
P.RootSignature->Parameters.getOrInsertTable(L);
309+
mcdxbc::DescriptorTable Table;
310+
for (const auto &R : TableYaml.Ranges) {
311+
312+
dxbc::RTS0::v2::DescriptorRange Range;
313+
Range.RangeType = R.RangeType;
314+
Range.NumDescriptors = R.NumDescriptors;
315+
Range.BaseShaderRegister = R.BaseShaderRegister;
316+
Range.RegisterSpace = R.RegisterSpace;
317+
Range.OffsetInDescriptorsFromTableStart =
318+
R.OffsetInDescriptorsFromTableStart;
319+
if (RS.Version > 1)
320+
Range.Flags = R.getEncodedFlags();
321+
Table.Ranges.push_back(Range);
322+
}
323+
RS.ParametersContainer.addParameter(Header, Table);
324+
break;
325+
}
306326
default:
307327
// Handling invalid parameter type edge case. We intentionally let
308328
// obj2yaml/yaml2obj parse and emit invalid dxcontainer data, in order

0 commit comments

Comments
 (0)