-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[DirectX] adding support to read/write descriptor table data using obj2yaml/yaml2obj #138315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 69 commits
0abacfc
8b8c02a
7ac9641
c105458
efe76aa
a928e9d
a38f10b
9a7c359
d6c2b55
93e4cf2
b45b1b6
f804a23
44bd13a
ac51bf6
97fb003
93e04bd
2f6d579
76b1b75
b2bfb02
9ee2964
2527580
c3a46da
15eb6f5
3e26364
b9d7f07
46cc8c1
1b3e10a
1f31957
e8fbfce
a31e5a5
a394ad0
ad415a7
8ff4845
98c6a5f
d67f7d3
5453ad0
836a8a8
5bd57a6
960cb9c
a60c7a3
2a4c2cb
c29d3f2
1513dab
95f3e99
eb97f1b
a9b87c2
28be2f8
76a2b07
b891126
2a93252
d616b65
6eac7c4
df194b0
0136cfc
b589d10
c7042b2
70a9b7f
e3489a4
f1dd0ce
6aa895e
f8080c4
aabd424
e655315
3094a75
984baf6
3979151
e65f850
f5bffca
a585134
08c5207
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
#include "llvm/ADT/Twine.h" | ||
#include "llvm/BinaryFormat/DXContainer.h" | ||
#include "llvm/Object/Error.h" | ||
#include "llvm/Support/Endian.h" | ||
#include "llvm/Support/Error.h" | ||
#include "llvm/Support/MemoryBufferRef.h" | ||
#include "llvm/TargetParser/Triple.h" | ||
|
@@ -177,6 +178,50 @@ struct RootDescriptorView : RootParameterView { | |
} | ||
}; | ||
|
||
struct DescriptorTable { | ||
uint32_t NumRanges; | ||
uint32_t RangesOffset; | ||
ViewArray<dxbc::RTS0::v2::DescriptorRange> Ranges; | ||
|
||
typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator begin() const { | ||
return Ranges.begin(); | ||
} | ||
|
||
typename ViewArray<dxbc::RTS0::v2::DescriptorRange>::iterator end() const { | ||
return Ranges.end(); | ||
} | ||
}; | ||
|
||
struct DescriptorTableView : RootParameterView { | ||
static bool classof(const RootParameterView *V) { | ||
return (V->Header.ParameterType == | ||
llvm::to_underlying(dxbc::RootParameterType::DescriptorTable)); | ||
} | ||
|
||
// Define a type alias to access the template parameter from inside classof | ||
llvm::Expected<DescriptorTable> read(uint32_t Version) { | ||
const char *Current = ParamData.begin(); | ||
DescriptorTable Table; | ||
|
||
Table.NumRanges = | ||
support::endian::read<uint32_t, llvm::endianness::little>(Current); | ||
Current += sizeof(uint32_t); | ||
|
||
Table.RangesOffset = | ||
support::endian::read<uint32_t, llvm::endianness::little>(Current); | ||
Current += sizeof(uint32_t); | ||
|
||
size_t RangeSize = sizeof(dxbc::RTS0::v1::DescriptorRange); | ||
if (Version > 1) | ||
RangeSize = sizeof(dxbc::RTS0::v2::DescriptorRange); | ||
|
||
Table.Ranges.Stride = RangeSize; | ||
Table.Ranges.Data = | ||
ParamData.substr(2 * sizeof(uint32_t), Table.NumRanges * RangeSize); | ||
return Table; | ||
} | ||
}; | ||
|
||
static Error parseFailed(const Twine &Msg) { | ||
return make_error<GenericBinaryError>(Msg.str(), object_error::parse_failed); | ||
} | ||
|
@@ -213,6 +258,9 @@ class RootSignature { | |
llvm::Expected<RootParameterView> | ||
getParameter(const dxbc::RTS0::v1::RootParameterHeader &Header) const { | ||
size_t DataSize; | ||
size_t EndOfSectionByte = getNumStaticSamplers() == 0 | ||
? PartData.size() | ||
: getStaticSamplersOffset(); | ||
|
||
if (!dxbc::isValidParameterType(Header.ParameterType)) | ||
return parseFailed("invalid parameter type"); | ||
|
@@ -229,10 +277,24 @@ class RootSignature { | |
else | ||
DataSize = sizeof(dxbc::RTS0::v2::RootDescriptor); | ||
break; | ||
case dxbc::RootParameterType::DescriptorTable: | ||
if (Header.ParameterOffset + sizeof(uint32_t) > EndOfSectionByte) | ||
return parseFailed("Reading structure out of file bounds"); | ||
|
||
uint32_t NumRanges = | ||
support::endian::read<uint32_t, llvm::endianness::little>( | ||
PartData.begin() + Header.ParameterOffset); | ||
Comment on lines
+284
to
+286
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bit unfortunate that we need to read the data here in order to parse it. Do we do anything elsewhere to make sure that corrupted data doesn't bite us here? That is, does this do something reasonable for an absurdly large incorrect size or does it fall over? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't handle this case while reading the root signature part, not sure if there is validation process before reading the parts. What will happen is: in case of absurdly larger numbers, invalid data would be read, since this would overflow the section containing descriptor ranges, and it would likely crash due to access out of bounds sections. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The DXContainer reader really needs to be hardened against crashing since this code may be used in drivers and/or runtime libraries. We should at least validate that the offset is within the part's range and error appropriately. |
||
if (Version == 1) | ||
DataSize = sizeof(dxbc::RTS0::v1::DescriptorRange) * NumRanges; | ||
else | ||
DataSize = sizeof(dxbc::RTS0::v2::DescriptorRange) * NumRanges; | ||
|
||
// 4 bytes for the number of ranges in table and | ||
// 4 bytes for the ranges offset | ||
DataSize += 2 * sizeof(uint32_t); | ||
break; | ||
} | ||
size_t EndOfSectionByte = getNumStaticSamplers() == 0 | ||
? PartData.size() | ||
: getStaticSamplersOffset(); | ||
|
||
|
||
if (Header.ParameterOffset + DataSize > EndOfSectionByte) | ||
return parseFailed("Reading structure out of file bounds"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values are wrong - when we turn these into an enum in DXContainer.h, we do
Val = 1ull << Num
, so we get NONE equal to 1 and DESCRIPTORS_VOLATILE equal to 2, even though DESCRIPTORS_VOLATILE should be 1 AFAICTThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, will fix that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As noted here: #143041 (review).
Maybe reusing the values will address this as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix PR: #143201