1 //===- RootSignatureValidations.h - HLSL Root Signature helpers -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file This file contains helper obejcts for working with HLSL Root 10 /// Signatures. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H 15 #define LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H 16 17 #include "llvm/ADT/IntervalMap.h" 18 #include "llvm/Frontend/HLSL/HLSLRootSignature.h" 19 #include "llvm/Support/Compiler.h" 20 21 namespace llvm { 22 namespace hlsl { 23 namespace rootsig { 24 25 // Basic verification of RootElements 26 27 LLVM_ABI bool verifyRootFlag(uint32_t Flags); 28 LLVM_ABI bool verifyVersion(uint32_t Version); 29 LLVM_ABI bool verifyRegisterValue(uint32_t RegisterValue); 30 LLVM_ABI bool verifyRegisterSpace(uint32_t RegisterSpace); 31 LLVM_ABI bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal); 32 LLVM_ABI bool verifyRangeType(uint32_t Type); 33 LLVM_ABI bool verifyDescriptorRangeFlag(uint32_t Version, uint32_t Type, 34 uint32_t FlagsVal); 35 LLVM_ABI bool verifyNumDescriptors(uint32_t NumDescriptors); 36 LLVM_ABI bool verifySamplerFilter(uint32_t Value); 37 LLVM_ABI bool verifyAddress(uint32_t Address); 38 LLVM_ABI bool verifyMipLODBias(float MipLODBias); 39 LLVM_ABI bool verifyMaxAnisotropy(uint32_t MaxAnisotropy); 40 LLVM_ABI bool verifyComparisonFunc(uint32_t ComparisonFunc); 41 LLVM_ABI bool verifyBorderColor(uint32_t BorderColor); 42 LLVM_ABI bool verifyLOD(float LOD); 43 44 struct RangeInfo { 45 const static uint32_t Unbounded = ~0u; 46 47 // Interval information 48 uint32_t LowerBound; 49 uint32_t UpperBound; 50 51 // Information retained for determining overlap 52 llvm::dxil::ResourceClass Class; 53 uint32_t Space; 54 llvm::dxbc::ShaderVisibility Visibility; 55 56 bool operator==(const RangeInfo &RHS) const { 57 return std::tie(LowerBound, UpperBound, Class, Space, Visibility) == 58 std::tie(RHS.LowerBound, RHS.UpperBound, RHS.Class, RHS.Space, 59 RHS.Visibility); 60 } 61 62 bool operator<(const RangeInfo &RHS) const { 63 return std::tie(Class, Space, LowerBound, UpperBound, Visibility) < 64 std::tie(RHS.Class, RHS.Space, RHS.LowerBound, RHS.UpperBound, 65 RHS.Visibility); 66 } 67 }; 68 69 class ResourceRange { 70 public: 71 using MapT = llvm::IntervalMap<uint32_t, const RangeInfo *, 16, 72 llvm::IntervalMapInfo<uint32_t>>; 73 74 private: 75 MapT Intervals; 76 77 public: ResourceRange(MapT::Allocator & Allocator)78 ResourceRange(MapT::Allocator &Allocator) : Intervals(MapT(Allocator)) {} 79 80 // Returns a reference to the first RangeInfo that overlaps with 81 // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap 82 LLVM_ABI std::optional<const RangeInfo *> 83 getOverlapping(const RangeInfo &Info) const; 84 85 // Return the mapped RangeInfo at X or nullptr if no mapping exists 86 LLVM_ABI const RangeInfo *lookup(uint32_t X) const; 87 88 // Removes all entries of the ResourceRange 89 LLVM_ABI void clear(); 90 91 // Insert the required (sub-)intervals such that the interval of [a;b] = 92 // [Info.LowerBound, Info.UpperBound] is covered and points to a valid 93 // RangeInfo &. 94 // 95 // For instance consider the following chain of inserting RangeInfos with the 96 // intervals denoting the Lower/Upper-bounds: 97 // 98 // A = [0;2] 99 // insert(A) -> false 100 // intervals: [0;2] -> &A 101 // B = [5;7] 102 // insert(B) -> false 103 // intervals: [0;2] -> &A, [5;7] -> &B 104 // C = [4;7] 105 // insert(C) -> true 106 // intervals: [0;2] -> &A, [4;7] -> &C 107 // D = [1;5] 108 // insert(D) -> true 109 // intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C 110 // E = [0;unbounded] 111 // insert(E) -> true 112 // intervals: [0;unbounded] -> E 113 // 114 // Returns a reference to the first RangeInfo that overlaps with 115 // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap 116 // (equivalent to getOverlapping) 117 LLVM_ABI std::optional<const RangeInfo *> insert(const RangeInfo &Info); 118 }; 119 120 struct OverlappingRanges { 121 const RangeInfo *A; 122 const RangeInfo *B; 123 OverlappingRangesOverlappingRanges124 OverlappingRanges(const RangeInfo *A, const RangeInfo *B) : A(A), B(B) {} 125 }; 126 127 /// The following conducts analysis on resource ranges to detect and report 128 /// any overlaps in resource ranges. 129 /// 130 /// A resource range overlaps with another resource range if they have: 131 /// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler) 132 /// - equivalent resource space 133 /// - overlapping visbility 134 /// 135 /// The algorithm is implemented in the following steps: 136 /// 137 /// 1. The user will collect RangeInfo from relevant RootElements: 138 /// - RangeInfo will retain the interval, ResourceClass, Space and Visibility 139 /// - It will also contain an index so that it can be associated to 140 /// additional diagnostic information 141 /// 2. The user is required to sort the RangeInfo's such that they are grouped 142 /// together by ResourceClass and Space 143 /// 3. Iterate through the collected RangeInfos by their groups 144 /// - For each group we will have a ResourceRange for each visibility 145 /// - As we iterate through we will: 146 /// A: Insert the current RangeInfo into the corresponding Visibility 147 /// ResourceRange 148 /// B: Check for overlap with any overlapping Visibility ResourceRange 149 LLVM_ABI llvm::SmallVector<OverlappingRanges> 150 findOverlappingRanges(ArrayRef<RangeInfo> Infos); 151 152 } // namespace rootsig 153 } // namespace hlsl 154 } // namespace llvm 155 156 #endif // LLVM_FRONTEND_HLSL_ROOTSIGNATUREVALIDATIONS_H 157