154 lines · cpp
1//===- HLSLRootSignatureValidations.cpp - 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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file This file contains helpers for working with HLSL Root Signatures.10///11//===----------------------------------------------------------------------===//12 13#include "llvm/Frontend/HLSL/RootSignatureValidations.h"14 15#include <cmath>16 17namespace llvm {18namespace hlsl {19namespace rootsig {20 21bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }22 23bool verifyVersion(uint32_t Version) {24 return (Version == 1 || Version == 2 || Version == 3);25}26 27bool verifyRegisterValue(uint32_t RegisterValue) {28 return RegisterValue != ~0U;29}30 31// This Range is reserverved, therefore invalid, according to the spec32// https://github.com/llvm/wg-hlsl/blob/main/proposals/0002-root-signature-in-clang.md#all-the-values-should-be-legal33bool verifyRegisterSpace(uint32_t RegisterSpace) {34 return !(RegisterSpace >= 0xFFFFFFF0);35}36 37bool verifyRootDescriptorFlag(uint32_t Version,38 dxbc::RootDescriptorFlags FlagsVal) {39 using FlagT = dxbc::RootDescriptorFlags;40 FlagT Flags = FlagT(FlagsVal);41 if (Version == 1)42 return Flags == FlagT::DataVolatile;43 44 // The data-specific flags are mutually exclusive.45 FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic |46 FlagT::DataStaticWhileSetAtExecute;47 48 if (popcount(llvm::to_underlying(Flags & DataFlags)) > 1)49 return false;50 51 // Only a data flag or no flags is valid52 return (Flags | DataFlags) == DataFlags;53}54 55bool verifyDescriptorRangeFlag(uint32_t Version, dxil::ResourceClass Type,56 dxbc::DescriptorRangeFlags Flags) {57 using FlagT = dxbc::DescriptorRangeFlags;58 const bool IsSampler = (Type == dxil::ResourceClass::Sampler);59 60 if (Version == 1) {61 // Since the metadata is unversioned, we expect to explicitly see the values62 // that map to the version 1 behaviour here.63 if (IsSampler)64 return Flags == FlagT::DescriptorsVolatile;65 return Flags == (FlagT::DataVolatile | FlagT::DescriptorsVolatile);66 }67 68 // The data-specific flags are mutually exclusive.69 FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic |70 FlagT::DataStaticWhileSetAtExecute;71 72 if (popcount(llvm::to_underlying(Flags & DataFlags)) > 1)73 return false;74 75 // The descriptor-specific flags are mutually exclusive.76 FlagT DescriptorFlags = FlagT::DescriptorsStaticKeepingBufferBoundsChecks |77 FlagT::DescriptorsVolatile;78 if (popcount(llvm::to_underlying(Flags & DescriptorFlags)) > 1)79 return false;80 81 // For volatile descriptors, DATA_is never valid.82 if ((Flags & FlagT::DescriptorsVolatile) == FlagT::DescriptorsVolatile) {83 FlagT Mask = FlagT::DescriptorsVolatile;84 if (!IsSampler) {85 Mask |= FlagT::DataVolatile;86 Mask |= FlagT::DataStaticWhileSetAtExecute;87 }88 return (Flags & ~Mask) == FlagT::None;89 }90 91 // For "KEEPING_BUFFER_BOUNDS_CHECKS" descriptors,92 // the other data-specific flags may all be set.93 if ((Flags & FlagT::DescriptorsStaticKeepingBufferBoundsChecks) ==94 FlagT::DescriptorsStaticKeepingBufferBoundsChecks) {95 FlagT Mask = FlagT::DescriptorsStaticKeepingBufferBoundsChecks;96 if (!IsSampler) {97 Mask |= FlagT::DataVolatile;98 Mask |= FlagT::DataStatic;99 Mask |= FlagT::DataStaticWhileSetAtExecute;100 }101 return (Flags & ~Mask) == FlagT::None;102 }103 104 // When no descriptor flag is set, any data flag is allowed.105 FlagT Mask = FlagT::None;106 if (!IsSampler) {107 Mask |= FlagT::DataVolatile;108 Mask |= FlagT::DataStaticWhileSetAtExecute;109 Mask |= FlagT::DataStatic;110 }111 return (Flags & ~Mask) == FlagT::None;112}113 114bool verifyStaticSamplerFlags(uint32_t Version,115 dxbc::StaticSamplerFlags Flags) {116 if (Version <= 2)117 return Flags == dxbc::StaticSamplerFlags::None;118 119 dxbc::StaticSamplerFlags Mask =120 dxbc::StaticSamplerFlags::NonNormalizedCoordinates |121 dxbc::StaticSamplerFlags::UintBorderColor |122 dxbc::StaticSamplerFlags::None;123 return (Flags | Mask) == Mask;124}125 126bool verifyNumDescriptors(uint32_t NumDescriptors) {127 return NumDescriptors > 0;128}129 130bool verifyMipLODBias(float MipLODBias) {131 return MipLODBias >= -16.f && MipLODBias <= 15.99f;132}133 134bool verifyMaxAnisotropy(uint32_t MaxAnisotropy) {135 return MaxAnisotropy <= 16u;136}137 138bool verifyLOD(float LOD) { return !std::isnan(LOD); }139 140bool verifyNoOverflowedOffset(uint64_t Offset) {141 return Offset <= std::numeric_limits<uint32_t>::max();142}143 144uint64_t computeRangeBound(uint64_t Offset, uint32_t Size) {145 assert(0 < Size && "Must be a non-empty range");146 if (Size == NumDescriptorsUnbounded)147 return NumDescriptorsUnbounded;148 149 return Offset + uint64_t(Size) - 1;150}151} // namespace rootsig152} // namespace hlsl153} // namespace llvm154