Skip to content

Commit cbc334a

Browse files
author
joaosaffran
committed
adding root parameter view
1 parent 4fe30df commit cbc334a

File tree

5 files changed

+160
-85
lines changed

5 files changed

+160
-85
lines changed

llvm/include/llvm/Object/DXContainer.h

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/SmallVector.h"
1919
#include "llvm/ADT/StringRef.h"
2020
#include "llvm/BinaryFormat/DXContainer.h"
21+
#include "llvm/Object/Error.h"
2122
#include "llvm/Support/Error.h"
2223
#include "llvm/Support/MemoryBufferRef.h"
2324
#include "llvm/TargetParser/Triple.h"
@@ -122,7 +123,107 @@ struct RootParameter {
122123
union {
123124
dxbc::RootConstants Constants;
124125
};
126+
127+
RootParameter() = default;
128+
};
129+
130+
struct ViewRootParameter {
131+
ViewArray<dxbc::RootParameterHeader> HeaderView;
132+
StringRef Data;
133+
134+
ViewRootParameter() = default;
135+
ViewRootParameter(ViewArray<dxbc::RootParameterHeader> HV, StringRef D)
136+
: HeaderView(HV), Data(D) {}
137+
138+
using value_type = DirectX::RootParameter;
139+
struct iterator {
140+
const ViewArray<dxbc::RootParameterHeader> HeaderView;
141+
ViewArray<dxbc::RootParameterHeader>::iterator Current;
142+
StringRef Data;
143+
144+
iterator(const ViewRootParameter &VRP,
145+
ViewArray<dxbc::RootParameterHeader>::iterator C)
146+
: HeaderView(VRP.HeaderView), Current(C), Data(VRP.Data) {}
147+
iterator(const iterator &) = default;
148+
149+
template <typename T>
150+
static Error readParameter(StringRef Buffer, const char *Src, T &Struct) {
151+
// Don't read before the beginning or past the end of the file
152+
if (Src < Buffer.begin() || Src + sizeof(T) > Buffer.end())
153+
return make_error<GenericBinaryError>(
154+
"Reading structure out of file bounds", object_error::parse_failed);
155+
156+
memcpy(&Struct, Src, sizeof(T));
157+
// DXContainer is always little endian
158+
if (sys::IsBigEndianHost)
159+
Struct.swapBytes();
160+
return Error::success();
161+
}
162+
163+
static Error validationFailed(const Twine &Msg) {
164+
return make_error<StringError>(Msg.str(), inconvertibleErrorCode());
165+
}
166+
167+
llvm::Expected<value_type> operator*() {
168+
value_type Parameter;
169+
std::memset(&Parameter.Header, 0, sizeof(dxbc::RootParameterHeader));
170+
memcpy(&Parameter.Header, Current.Current,
171+
sizeof(dxbc::RootParameterHeader));
172+
173+
switch (Parameter.Header.ParameterType) {
174+
case dxbc::RootParameterType::Constants32Bit:
175+
std::memset(&Parameter.Constants, 0, sizeof(dxbc::RootConstants));
176+
if (Error Err = readParameter(
177+
Data, Data.begin() + Parameter.Header.ParameterOffset,
178+
Parameter.Constants))
179+
return Err;
180+
break;
181+
case dxbc::RootParameterType::Empty:
182+
break;
183+
}
184+
185+
return Parameter;
186+
}
187+
188+
iterator operator++() {
189+
if (Current != HeaderView.end())
190+
Current++;
191+
return *this;
192+
}
193+
194+
iterator operator++(int I) {
195+
iterator Tmp = *this;
196+
for (; I > 0; I--)
197+
++Tmp;
198+
return Tmp;
199+
}
200+
201+
iterator operator--() {
202+
if (Current != HeaderView.begin())
203+
Current--;
204+
return *this;
205+
}
206+
207+
iterator operator--(int I) {
208+
iterator Tmp = *this;
209+
for (; I > 0; I--)
210+
--Tmp;
211+
return Tmp;
212+
}
213+
214+
bool operator==(iterator I) { return I.Current == Current; }
215+
bool operator!=(const iterator I) { return !(*this == I); }
216+
};
217+
218+
iterator begin() const { return iterator(*this, this->HeaderView.begin()); }
219+
220+
iterator end() const { return iterator(*this, this->HeaderView.end()); }
221+
222+
size_t size() const { return HeaderView.size(); }
223+
224+
bool isEmpty() const { return HeaderView.isEmpty(); }
125225
};
226+
126227
class RootSignature {
127228
private:
128229
uint32_t Version = 2;
@@ -132,9 +233,9 @@ class RootSignature {
132233
uint32_t StaticSamplersOffset = 0;
133234
uint32_t Flags = 0;
134235

135-
SmallVector<DirectX::RootParameter> Parameters;
236+
ViewRootParameter Parameters;
136237

137-
using param_iterator = SmallVector<DirectX::RootParameter>::iterator;
238+
using param_iterator = ViewRootParameter::iterator;
138239

139240
public:
140241
RootSignature() {}
@@ -145,7 +246,7 @@ class RootSignature {
145246
uint32_t getRootParametersOffset() const { return RootParametersOffset; }
146247
uint32_t getNumStaticSamplers() const { return NumStaticSamplers; }
147248
uint32_t getStaticSamplersOffset() const { return StaticSamplersOffset; }
148-
llvm::iterator_range<const RootParameter *> params() const {
249+
llvm::iterator_range<param_iterator> params() const {
149250
return llvm::make_range(Parameters.begin(), Parameters.end());
150251
}
151252
param_iterator param_begin() { return Parameters.begin(); }

llvm/include/llvm/ObjectYAML/DXContainerYAML.h

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,24 +87,7 @@ struct RootParameterYamlDesc {
8787
uint32_t Offset;
8888

8989
RootParameterYamlDesc() = default;
90-
RootParameterYamlDesc(const object::DirectX::RootParameter &Parameter) {
91-
92-
Type = Parameter.Header.ParameterType;
93-
Visibility = Parameter.Header.ShaderVisibility;
94-
Offset = Parameter.Header.ParameterOffset;
95-
switch (Parameter.Header.ParameterType) {
96-
97-
case dxbc::RootParameterType::Constants32Bit:
98-
Constants.NumOfConstants = Parameter.Constants.NumOfConstants;
99-
Constants.Space = Parameter.Constants.Space;
100-
Constants.Register = Parameter.Constants.Register;
101-
break;
102-
case dxbc::RootParameterType::Empty:
103-
llvm_unreachable("Invalid Root Parameter Type. It should be verified "
104-
"before reaching here.");
105-
break;
106-
}
107-
}
90+
10891
union {
10992
RootConstantsYaml Constants;
11093
};

llvm/lib/Object/DXContainer.cpp

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -305,58 +305,26 @@ Error DirectX::RootSignature::parse(StringRef Data) {
305305
Flags = FValue;
306306

307307
assert(Current == Begin + RootParametersOffset);
308-
for (uint32_t I = 0; I < NumParameters; I++) {
309-
DirectX::RootParameter NewParam;
310308

311-
uint32_t MaybeParamType =
312-
support::endian::read<uint32_t, llvm::endianness::little>(Current);
309+
Parameters.HeaderView.Data = Data.substr(
310+
RootParametersOffset, NumParameters * sizeof(dxbc::RootParameterHeader));
311+
Parameters.Data = Data;
313312

314-
if (Error Err =
315-
safeConvertEnum(MaybeParamType, NewParam.Header.ParameterType))
316-
return Err;
313+
for (auto P : params()) {
314+
if (!P)
315+
return P.takeError();
317316

318317
if (!dxbc::RootSignatureValidations::isValidParameterType(
319-
NewParam.Header.ParameterType))
320-
return validationFailed(
321-
"unsupported parameter type value read: " +
322-
llvm::Twine((uint32_t)NewParam.Header.ParameterType));
323-
324-
Current += sizeof(dxbc::RootParameterType);
325-
326-
uint32_t MaybeVisibility =
327-
support::endian::read<uint32_t, llvm::endianness::little>(Current);
328-
329-
if (Error Err =
330-
safeConvertEnum(MaybeVisibility, NewParam.Header.ShaderVisibility))
331-
return Err;
318+
P->Header.ParameterType))
319+
return validationFailed("unsupported parameter type value read: " +
320+
llvm::Twine((uint32_t)P->Header.ParameterType));
332321

333322
if (!dxbc::RootSignatureValidations::isValidShaderVisibility(
334-
NewParam.Header.ShaderVisibility))
323+
P->Header.ShaderVisibility))
335324
return validationFailed(
336325
"unsupported shader visility flag value read: " +
337-
llvm::Twine((uint32_t)NewParam.Header.ShaderVisibility));
338-
339-
Current += sizeof(dxbc::ShaderVisibility);
340-
341-
NewParam.Header.ParameterOffset =
342-
support::endian::read<uint32_t, llvm::endianness::little>(Current);
343-
Current += sizeof(uint32_t);
344-
345-
switch (NewParam.Header.ParameterType) {
346-
347-
case dxbc::RootParameterType::Constants32Bit:
348-
if (Error Err = readStruct(Data, Begin + NewParam.Header.ParameterOffset,
349-
NewParam.Constants))
350-
return Err;
351-
break;
352-
case dxbc::RootParameterType::Empty:
353-
// unreachable because it was validated and assigned before this point.
354-
llvm_unreachable("Invalid value for RootParameterType");
355-
}
356-
357-
Parameters.push_back(NewParam);
326+
llvm::Twine((uint32_t)P->Header.ShaderVisibility));
358327
}
359-
360328
return Error::success();
361329
}
362330

llvm/lib/ObjectYAML/DXContainerYAML.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/ObjectYAML/DXContainerYAML.h"
1515
#include "llvm/ADT/ScopeExit.h"
1616
#include "llvm/BinaryFormat/DXContainer.h"
17+
#include "llvm/Support/ErrorHandling.h"
1718
#include "llvm/Support/ScopedPrinter.h"
1819

1920
namespace llvm {
@@ -35,9 +36,27 @@ DXContainerYAML::RootSignatureYamlDesc::RootSignatureYamlDesc(
3536
NumStaticSamplers(Data.getNumStaticSamplers()),
3637
StaticSamplersOffset(Data.getStaticSamplersOffset()) {
3738
uint32_t Flags = Data.getFlags();
38-
for (auto const &P : Data.params()) {
39-
40-
Parameters.push_back(RootParameterYamlDesc(P));
39+
for (auto P : Data.params()) {
40+
if (!P)
41+
llvm_unreachable("Parameters are validated on read.");
42+
43+
auto NewP = RootParameterYamlDesc();
44+
NewP.Offset = P->Header.ParameterOffset;
45+
NewP.Type = P->Header.ParameterType;
46+
NewP.Visibility = P->Header.ShaderVisibility;
47+
48+
switch (NewP.Type) {
49+
50+
case dxbc::RootParameterType::Constants32Bit:
51+
NewP.Constants.NumOfConstants = P->Constants.NumOfConstants;
52+
NewP.Constants.Register = P->Constants.Register;
53+
NewP.Constants.Space = P->Constants.Space;
54+
break;
55+
case dxbc::RootParameterType::Empty:
56+
llvm_unreachable("Invalid RootParameterType");
57+
break;
58+
}
59+
Parameters.push_back(NewP);
4160
}
4261
#define ROOT_ELEMENT_FLAG(Num, Val) \
4362
Val = (Flags & (uint32_t)dxbc::RootElementFlag::Val) > 0;

llvm/unittests/Object/DXContainerTest.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -909,22 +909,26 @@ TEST(RootSignature, ParseRootConstant) {
909909
DXContainer C =
910910
llvm::cantFail(DXContainer::create(getMemoryBuffer<133>(Buffer)));
911911

912-
auto RS = C.getRootSignature();
913-
ASSERT_TRUE(RS.has_value());
914-
ASSERT_EQ(RS->getVersion(), 2u);
915-
ASSERT_EQ(RS->getNumParameters(), 1u);
916-
ASSERT_EQ(RS->getRootParametersOffset(), 24u);
917-
ASSERT_EQ(RS->getNumStaticSamplers(), 0u);
918-
ASSERT_EQ(RS->getStaticSamplersOffset(), 44u);
919-
ASSERT_EQ(RS->getFlags(), 17u);
920-
921-
for (auto const &RootParam : RS->params()) {
922-
ASSERT_EQ((uint32_t)RootParam.Header.ParameterType, 1u);
923-
ASSERT_EQ((uint32_t)RootParam.Header.ShaderVisibility, 2u);
924-
ASSERT_EQ(RootParam.Constants.Register, 15u);
925-
ASSERT_EQ(RootParam.Constants.Space, 14u);
926-
ASSERT_EQ(RootParam.Constants.NumOfConstants, 16u);
927-
}
912+
auto MaybeRS = C.getRootSignature();
913+
ASSERT_TRUE(MaybeRS.has_value());
914+
const auto &RS = MaybeRS.value();
915+
ASSERT_EQ(RS.getVersion(), 2u);
916+
ASSERT_EQ(RS.getNumParameters(), 1u);
917+
ASSERT_EQ(RS.getRootParametersOffset(), 24u);
918+
ASSERT_EQ(RS.getNumStaticSamplers(), 0u);
919+
ASSERT_EQ(RS.getStaticSamplersOffset(), 44u);
920+
ASSERT_EQ(RS.getFlags(), 17u);
921+
922+
auto RootParam = *RS.params().begin();
923+
ASSERT_FALSE(!RootParam);
924+
auto X = (unsigned)RootParam->Header.ParameterType;
925+
auto Y = (unsigned)RootParam->Header.ShaderVisibility;
926+
927+
ASSERT_EQ(X, 1u);
928+
ASSERT_EQ(Y, 2u);
929+
ASSERT_EQ(RootParam->Constants.Register, 15u);
930+
ASSERT_EQ(RootParam->Constants.Space, 14u);
931+
ASSERT_EQ(RootParam->Constants.NumOfConstants, 16u);
928932
}
929933
{
930934
// ParameterType has been set to an invalid value
@@ -943,7 +947,7 @@ TEST(RootSignature, ParseRootConstant) {
943947
0x00};
944948
EXPECT_THAT_EXPECTED(
945949
DXContainer::create(getMemoryBuffer<133>(Buffer)),
946-
FailedWithMessage("Value is not within range for enum"));
950+
FailedWithMessage("unsupported parameter type value read: 255"));
947951
}
948952
{
949953
// ShaderVisibility has been set to an invalid value
@@ -962,7 +966,7 @@ TEST(RootSignature, ParseRootConstant) {
962966
0x00};
963967
EXPECT_THAT_EXPECTED(
964968
DXContainer::create(getMemoryBuffer<133>(Buffer)),
965-
FailedWithMessage("Value is not within range for enum"));
969+
FailedWithMessage("unsupported shader visility flag value read: 255"));
966970
}
967971
{
968972
// Offset has been set to an invalid value

0 commit comments

Comments
 (0)