39
39
#include " llvm/ADT/StringExtras.h"
40
40
#include " llvm/ADT/StringRef.h"
41
41
#include " llvm/ADT/Twine.h"
42
+ #include " llvm/Frontend/HLSL/HLSLRootSignature.h"
42
43
#include " llvm/Support/Casting.h"
43
44
#include " llvm/Support/DXILABI.h"
44
45
#include " llvm/Support/ErrorHandling.h"
@@ -951,6 +952,101 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS,
951
952
<< NewFnName << FixItHint::CreateReplacement (FullRange, OS.str ());
952
953
}
953
954
955
+ namespace {
956
+
957
+ // A resource range overlaps with another resource range if they have:
958
+ // - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
959
+ // - equivalent resource space
960
+ // - overlapping visbility
961
+ class ResourceRanges {
962
+ public:
963
+ // KeyT: 32-lsb denotes resource space, and 32-msb denotes resource type enum
964
+ using KeyT = uint64_t ;
965
+
966
+ constexpr static KeyT getKey (const llvm::hlsl::rootsig::RangeInfo &Info) {
967
+ uint64_t SpacePacked = (uint64_t )Info.Space ;
968
+ uint64_t ClassPacked = (uint64_t )llvm::to_underlying (Info.Class );
969
+ return (ClassPacked << 32 ) | SpacePacked;
970
+ }
971
+
972
+ static const unsigned NumVisEnums = 8 ;
973
+ // (unsigned)llvm::hlsl::rootsig::ShaderVisibility::NumEnums;
974
+
975
+ private:
976
+ llvm::hlsl::rootsig::ResourceRange::IMap::Allocator Allocator;
977
+
978
+ using MapT = llvm::SmallDenseMap<KeyT, llvm::hlsl::rootsig::ResourceRange>;
979
+
980
+ MapT RangeMaps[NumVisEnums];
981
+
982
+ public:
983
+ // Returns std::nullopt if there was no collision. Otherwise, it will
984
+ // return the RangeInfo of the collision
985
+ std::optional<const llvm::hlsl::rootsig::RangeInfo *> addRange (const llvm::hlsl::rootsig::RangeInfo &Info) {
986
+ MapT &VisRangeMap = RangeMaps[llvm::to_underlying (Info.Vis )];
987
+ auto [It, _] = VisRangeMap.insert ({getKey (Info), llvm::hlsl::rootsig::ResourceRange (Allocator)});
988
+ auto Res = It->second .insert (Info);
989
+ if (Res.has_value ())
990
+ return Res;
991
+
992
+ MutableArrayRef<MapT> Maps =
993
+ Info.Vis == llvm::hlsl::rootsig::ShaderVisibility::All
994
+ ? MutableArrayRef<MapT>{RangeMaps}.drop_front ()
995
+ : MutableArrayRef<MapT>{RangeMaps}.take_front ();
996
+
997
+ for (MapT &CurMap : Maps) {
998
+ auto CurIt = CurMap.find (getKey (Info));
999
+ if (CurIt != CurMap.end ())
1000
+ if (auto Overlapping = CurIt->second .getOverlapping (Info))
1001
+ return Overlapping;
1002
+ }
1003
+
1004
+ return std::nullopt;
1005
+ }
1006
+ };
1007
+
1008
+ } // namespace
1009
+
1010
+ bool SemaHLSL::handleRootSignatureDecl (HLSLRootSignatureDecl *D,
1011
+ SourceLocation Loc) {
1012
+ auto Elements = D->getRootElements ();
1013
+
1014
+ // First we will go through and collect our range info
1015
+ llvm::SmallVector<llvm::hlsl::rootsig::RangeInfo> Infos;
1016
+ for (const auto &Elem : Elements) {
1017
+ if (const auto *Param =
1018
+ std::get_if<llvm::hlsl::rootsig::RootParam>(&Elem)) {
1019
+ llvm::hlsl::rootsig::RangeInfo Info;
1020
+ Info.LowerBound = Param->Reg .Number ;
1021
+ Info.UpperBound = Info.LowerBound ; // use inclusive ranges []
1022
+
1023
+ Info.Class = Param->Type ;
1024
+ Info.Space = Param->Space ;
1025
+ Info.Vis = Param->Visibility ;
1026
+ Infos.push_back (Info);
1027
+ }
1028
+ }
1029
+
1030
+ // Iterate through info and attempt to insert corresponding range
1031
+ ResourceRanges Ranges;
1032
+ bool HadOverlap = false ;
1033
+ for (const llvm::hlsl::rootsig::RangeInfo &Info : Infos)
1034
+ if (auto MaybeOverlappingInfo = Ranges.addRange (Info)) {
1035
+ const llvm::hlsl::rootsig::RangeInfo *OInfo = MaybeOverlappingInfo.value ();
1036
+ auto CommonVis = Info.Vis == llvm::hlsl::rootsig::ShaderVisibility::All
1037
+ ? OInfo->Vis : Info.Vis ;
1038
+
1039
+ Diag (Loc, diag::err_hlsl_resource_range_overlap)
1040
+ << llvm::to_underlying (Info.Class ) << Info.LowerBound << Info.UpperBound
1041
+ << llvm::to_underlying (OInfo->Class ) << OInfo->LowerBound << OInfo->UpperBound
1042
+ << Info.Space << CommonVis;
1043
+
1044
+ HadOverlap = true ;
1045
+ }
1046
+
1047
+ return HadOverlap;
1048
+ }
1049
+
954
1050
void SemaHLSL::handleRootSignatureAttr (Decl *D, const ParsedAttr &AL) {
955
1051
if (AL.getNumArgs () != 1 ) {
956
1052
Diag (AL.getLoc (), diag::err_attribute_wrong_number_arguments) << AL << 1 ;
@@ -973,6 +1069,8 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
973
1069
if (auto *SignatureDecl =
974
1070
dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl ())) {
975
1071
// Perform validation of constructs here
1072
+ if (handleRootSignatureDecl (SignatureDecl, AL.getLoc ()))
1073
+ return ;
976
1074
D->addAttr (::new (getASTContext ()) RootSignatureAttr (
977
1075
getASTContext (), AL, Ident, SignatureDecl));
978
1076
}
0 commit comments