brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · 1735751 Raw
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