Skip to content

Commit deba201

Browse files
authored
[NFC][HLSL][DirectX] Move DXILRootSignature validations to RootSignatureValidations library (#147110)
Simple code movement of the verification logic in `validate` of the `DXILRootSignature` pass. Moving this code to the `RootSignatureValidations` library allows for the common verifications to be used in the frontend. - Moves all the `static` verification functions used in `DXILRootSignature` to the `RootSignatureValidations` library - Updates `DXILRootSignature` to use the moved functions Resolves: #145940
1 parent 07cc7ea commit deba201

File tree

3 files changed

+183
-165
lines changed

3 files changed

+183
-165
lines changed

llvm/include/llvm/Frontend/HLSL/RootSignatureValidations.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ namespace llvm {
2121
namespace hlsl {
2222
namespace rootsig {
2323

24+
// Basic verification of RootElements
25+
26+
bool verifyRootFlag(uint32_t Flags);
27+
bool verifyVersion(uint32_t Version);
28+
bool verifyRegisterValue(uint32_t RegisterValue);
29+
bool verifyRegisterSpace(uint32_t RegisterSpace);
30+
bool verifyDescriptorFlag(uint32_t Flags);
31+
bool verifyRangeType(uint32_t Type);
32+
bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
33+
uint32_t FlagsVal);
34+
bool verifySamplerFilter(uint32_t Value);
35+
bool verifyAddress(uint32_t Address);
36+
bool verifyMipLODBias(float MipLODBias);
37+
bool verifyMaxAnisotropy(uint32_t MaxAnisotropy);
38+
bool verifyComparisonFunc(uint32_t ComparisonFunc);
39+
bool verifyBorderColor(uint32_t BorderColor);
40+
bool verifyLOD(float LOD);
41+
2442
struct RangeInfo {
2543
const static uint32_t Unbounded = ~0u;
2644

llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,153 @@
1212

1313
#include "llvm/Frontend/HLSL/RootSignatureValidations.h"
1414

15+
#include <cmath>
16+
1517
namespace llvm {
1618
namespace hlsl {
1719
namespace rootsig {
1820

21+
bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }
22+
23+
bool verifyVersion(uint32_t Version) { return (Version == 1 || Version == 2); }
24+
25+
bool verifyRegisterValue(uint32_t RegisterValue) {
26+
return RegisterValue != ~0U;
27+
}
28+
29+
// This Range is reserverved, therefore invalid, according to the spec
30+
// https://github.com/llvm/wg-hlsl/blob/main/proposals/0002-root-signature-in-clang.md#all-the-values-should-be-legal
31+
bool verifyRegisterSpace(uint32_t RegisterSpace) {
32+
return !(RegisterSpace >= 0xFFFFFFF0 && RegisterSpace <= 0xFFFFFFFF);
33+
}
34+
35+
bool verifyDescriptorFlag(uint32_t Flags) { return (Flags & ~0xE) == 0; }
36+
37+
bool verifyRangeType(uint32_t Type) {
38+
switch (Type) {
39+
case llvm::to_underlying(dxbc::DescriptorRangeType::CBV):
40+
case llvm::to_underlying(dxbc::DescriptorRangeType::SRV):
41+
case llvm::to_underlying(dxbc::DescriptorRangeType::UAV):
42+
case llvm::to_underlying(dxbc::DescriptorRangeType::Sampler):
43+
return true;
44+
};
45+
46+
return false;
47+
}
48+
49+
bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type,
50+
uint32_t FlagsVal) {
51+
using FlagT = dxbc::DescriptorRangeFlags;
52+
FlagT Flags = FlagT(FlagsVal);
53+
54+
const bool IsSampler =
55+
(Type == llvm::to_underlying(dxbc::DescriptorRangeType::Sampler));
56+
57+
if (Version == 1) {
58+
// Since the metadata is unversioned, we expect to explicitly see the values
59+
// that map to the version 1 behaviour here.
60+
if (IsSampler)
61+
return Flags == FlagT::DescriptorsVolatile;
62+
return Flags == (FlagT::DataVolatile | FlagT::DescriptorsVolatile);
63+
}
64+
65+
// The data-specific flags are mutually exclusive.
66+
FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic |
67+
FlagT::DataStaticWhileSetAtExecute;
68+
69+
if (popcount(llvm::to_underlying(Flags & DataFlags)) > 1)
70+
return false;
71+
72+
// The descriptor-specific flags are mutually exclusive.
73+
FlagT DescriptorFlags = FlagT::DescriptorsStaticKeepingBufferBoundsChecks |
74+
FlagT::DescriptorsVolatile;
75+
if (popcount(llvm::to_underlying(Flags & DescriptorFlags)) > 1)
76+
return false;
77+
78+
// For volatile descriptors, DATA_is never valid.
79+
if ((Flags & FlagT::DescriptorsVolatile) == FlagT::DescriptorsVolatile) {
80+
FlagT Mask = FlagT::DescriptorsVolatile;
81+
if (!IsSampler) {
82+
Mask |= FlagT::DataVolatile;
83+
Mask |= FlagT::DataStaticWhileSetAtExecute;
84+
}
85+
return (Flags & ~Mask) == FlagT::None;
86+
}
87+
88+
// For "KEEPING_BUFFER_BOUNDS_CHECKS" descriptors,
89+
// the other data-specific flags may all be set.
90+
if ((Flags & FlagT::DescriptorsStaticKeepingBufferBoundsChecks) ==
91+
FlagT::DescriptorsStaticKeepingBufferBoundsChecks) {
92+
FlagT Mask = FlagT::DescriptorsStaticKeepingBufferBoundsChecks;
93+
if (!IsSampler) {
94+
Mask |= FlagT::DataVolatile;
95+
Mask |= FlagT::DataStatic;
96+
Mask |= FlagT::DataStaticWhileSetAtExecute;
97+
}
98+
return (Flags & ~Mask) == FlagT::None;
99+
}
100+
101+
// When no descriptor flag is set, any data flag is allowed.
102+
FlagT Mask = FlagT::None;
103+
if (!IsSampler) {
104+
Mask |= FlagT::DataVolatile;
105+
Mask |= FlagT::DataStaticWhileSetAtExecute;
106+
Mask |= FlagT::DataStatic;
107+
}
108+
return (Flags & ~Mask) == FlagT::None;
109+
}
110+
111+
bool verifySamplerFilter(uint32_t Value) {
112+
switch (Value) {
113+
#define FILTER(Num, Val) case llvm::to_underlying(dxbc::SamplerFilter::Val):
114+
#include "llvm/BinaryFormat/DXContainerConstants.def"
115+
return true;
116+
}
117+
return false;
118+
}
119+
120+
// Values allowed here:
121+
// https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode#syntax
122+
bool verifyAddress(uint32_t Address) {
123+
switch (Address) {
124+
#define TEXTURE_ADDRESS_MODE(Num, Val) \
125+
case llvm::to_underlying(dxbc::TextureAddressMode::Val):
126+
#include "llvm/BinaryFormat/DXContainerConstants.def"
127+
return true;
128+
}
129+
return false;
130+
}
131+
132+
bool verifyMipLODBias(float MipLODBias) {
133+
return MipLODBias >= -16.f && MipLODBias <= 15.99f;
134+
}
135+
136+
bool verifyMaxAnisotropy(uint32_t MaxAnisotropy) {
137+
return MaxAnisotropy <= 16u;
138+
}
139+
140+
bool verifyComparisonFunc(uint32_t ComparisonFunc) {
141+
switch (ComparisonFunc) {
142+
#define COMPARISON_FUNC(Num, Val) \
143+
case llvm::to_underlying(dxbc::ComparisonFunc::Val):
144+
#include "llvm/BinaryFormat/DXContainerConstants.def"
145+
return true;
146+
}
147+
return false;
148+
}
149+
150+
bool verifyBorderColor(uint32_t BorderColor) {
151+
switch (BorderColor) {
152+
#define STATIC_BORDER_COLOR(Num, Val) \
153+
case llvm::to_underlying(dxbc::StaticBorderColor::Val):
154+
#include "llvm/BinaryFormat/DXContainerConstants.def"
155+
return true;
156+
}
157+
return false;
158+
}
159+
160+
bool verifyLOD(float LOD) { return !std::isnan(LOD); }
161+
19162
std::optional<const RangeInfo *>
20163
ResourceRange::getOverlapping(const RangeInfo &Info) const {
21164
MapT::const_iterator Interval = Intervals.find(Info.LowerBound);

0 commit comments

Comments
 (0)