brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.9 KiB · c883282 Raw
313 lines · c
1//===----- CGHLSLRuntime.h - Interface to HLSL Runtimes -----*- C++ -*-===//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// This provides an abstract class for HLSL code generation.  Concrete10// subclasses of this implement code generation for specific HLSL11// runtime libraries.12//13//===----------------------------------------------------------------------===//14 15#ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H16#define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H17 18#include "Address.h"19#include "clang/AST/Attr.h"20#include "clang/AST/Decl.h"21#include "clang/Basic/Builtins.h"22#include "clang/Basic/HLSLRuntime.h"23#include "llvm/ADT/DenseMap.h"24#include "llvm/ADT/SmallVector.h"25#include "llvm/ADT/StringRef.h"26#include "llvm/Frontend/HLSL/HLSLResource.h"27#include "llvm/IR/IRBuilder.h"28#include "llvm/IR/Intrinsics.h"29#include "llvm/IR/IntrinsicsDirectX.h"30#include "llvm/IR/IntrinsicsSPIRV.h"31 32#include <optional>33#include <vector>34 35// A function generator macro for picking the right intrinsic36// for the target backend37#define GENERATE_HLSL_INTRINSIC_FUNCTION(FunctionName, IntrinsicPostfix)       \38  llvm::Intrinsic::ID get##FunctionName##Intrinsic() {                         \39    llvm::Triple::ArchType Arch = getArch();                                   \40    switch (Arch) {                                                            \41    case llvm::Triple::dxil:                                                   \42      return llvm::Intrinsic::dx_##IntrinsicPostfix;                           \43    case llvm::Triple::spirv:                                                  \44      return llvm::Intrinsic::spv_##IntrinsicPostfix;                          \45    default:                                                                   \46      llvm_unreachable("Intrinsic " #IntrinsicPostfix                          \47                       " not supported by target architecture");               \48    }                                                                          \49  }50 51using ResourceClass = llvm::dxil::ResourceClass;52 53namespace llvm {54class GlobalVariable;55class Function;56class StructType;57class Metadata;58} // namespace llvm59 60namespace clang {61class NamedDecl;62class VarDecl;63class ParmVarDecl;64class InitListExpr;65class HLSLBufferDecl;66class HLSLRootSignatureDecl;67class HLSLVkBindingAttr;68class HLSLResourceBindingAttr;69class Type;70class RecordType;71class DeclContext;72class HLSLPackOffsetAttr;73class ArraySubscriptExpr;74 75class FunctionDecl;76 77namespace CodeGen {78 79class CodeGenModule;80class CodeGenFunction;81class LValue;82 83class CGHLSLOffsetInfo {84  SmallVector<uint32_t> Offsets;85 86public:87  static const uint32_t Unspecified = ~0U;88 89  /// Iterates over all declarations in the HLSL buffer and based on the90  /// packoffset or register(c#) annotations it fills outs the Offsets vector91  /// with the user-specified layout offsets. The buffer offsets can be92  /// specified 2 ways: 1. declarations in cbuffer {} block can have a93  /// packoffset annotation (translates to HLSLPackOffsetAttr) 2. default94  /// constant buffer declarations at global scope can have register(c#)95  /// annotations (translates to HLSLResourceBindingAttr with RegisterType::C)96  /// It is not guaranteed that all declarations in a buffer have an annotation.97  /// For those where it is not specified a `~0U` value is added to the Offsets98  /// vector. In the final layout these declarations will be placed at the end99  /// of the HLSL buffer after all of the elements with specified offset.100  static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl);101 102  /// Comparison function for offsets received from `operator[]` suitable for103  /// use in a `stable_sort`. This will order implicit bindings after explicit104  /// offsets.105  static bool compareOffsets(uint32_t LHS, uint32_t RHS) { return LHS < RHS; }106 107  /// Get the given offset, or `~0U` if there is no offset for the member.108  uint32_t operator[](size_t I) const {109    if (Offsets.empty())110      return Unspecified;111    return Offsets[I];112  }113 114  bool empty() const { return Offsets.empty(); }115};116 117class CGHLSLRuntime {118public:119  //===----------------------------------------------------------------------===//120  // Start of reserved area for HLSL intrinsic getters.121  //===----------------------------------------------------------------------===//122 123  GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)124  GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)125  GENERATE_HLSL_INTRINSIC_FUNCTION(Cross, cross)126  GENERATE_HLSL_INTRINSIC_FUNCTION(Degrees, degrees)127  GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)128  GENERATE_HLSL_INTRINSIC_FUNCTION(FlattenedThreadIdInGroup,129                                   flattened_thread_id_in_group)130  GENERATE_HLSL_INTRINSIC_FUNCTION(IsInf, isinf)131  GENERATE_HLSL_INTRINSIC_FUNCTION(IsNaN, isnan)132  GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)133  GENERATE_HLSL_INTRINSIC_FUNCTION(Normalize, normalize)134  GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)135  GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)136  GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign)137  GENERATE_HLSL_INTRINSIC_FUNCTION(Step, step)138  GENERATE_HLSL_INTRINSIC_FUNCTION(Radians, radians)139  GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)140  GENERATE_HLSL_INTRINSIC_FUNCTION(GroupThreadId, thread_id_in_group)141  GENERATE_HLSL_INTRINSIC_FUNCTION(GroupId, group_id)142  GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)143  GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)144  GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)145  GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)146  GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddU8Packed, dot4add_u8packed)147  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAllTrue, wave_all)148  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveAnyTrue, wave_any)149  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveActiveCountBits, wave_active_countbits)150  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)151  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveGetLaneCount, wave_get_lane_count)152  GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)153  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitUHigh, firstbituhigh)154  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitSHigh, firstbitshigh)155  GENERATE_HLSL_INTRINSIC_FUNCTION(FirstBitLow, firstbitlow)156  GENERATE_HLSL_INTRINSIC_FUNCTION(NClamp, nclamp)157  GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp)158  GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)159 160  GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer,161                                   resource_getpointer)162  GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding,163                                   resource_handlefrombinding)164  GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromImplicitBinding,165                                   resource_handlefromimplicitbinding)166  GENERATE_HLSL_INTRINSIC_FUNCTION(NonUniformResourceIndex,167                                   resource_nonuniformindex)168  GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)169  GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync,170                                   group_memory_barrier_with_group_sync)171  GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x)172  GENERATE_HLSL_INTRINSIC_FUNCTION(DdxCoarse, ddx_coarse)173  GENERATE_HLSL_INTRINSIC_FUNCTION(DdyCoarse, ddy_coarse)174 175  //===----------------------------------------------------------------------===//176  // End of reserved area for HLSL intrinsic getters.177  //===----------------------------------------------------------------------===//178 179protected:180  CodeGenModule &CGM;181 182  llvm::Value *emitSystemSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,183                                      const clang::DeclaratorDecl *Decl,184                                      HLSLAppliedSemanticAttr *Semantic,185                                      std::optional<unsigned> Index);186 187  void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,188                               const clang::DeclaratorDecl *Decl,189                               HLSLAppliedSemanticAttr *Semantic,190                               std::optional<unsigned> Index);191 192  llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B,193                                        const FunctionDecl *FD,194                                        llvm::Type *Type,195                                        const clang::DeclaratorDecl *Decl,196                                        HLSLAppliedSemanticAttr *Semantic);197 198  void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,199                                 llvm::Value *Source,200                                 const clang::DeclaratorDecl *Decl,201                                 HLSLAppliedSemanticAttr *Semantic);202 203  std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>204  handleStructSemanticLoad(205      llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,206      const clang::DeclaratorDecl *Decl,207      specific_attr_iterator<HLSLAppliedSemanticAttr> begin,208      specific_attr_iterator<HLSLAppliedSemanticAttr> end);209 210  specific_attr_iterator<HLSLAppliedSemanticAttr> handleStructSemanticStore(211      llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,212      const clang::DeclaratorDecl *Decl,213      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,214      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);215 216  std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>217  handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD,218                     llvm::Type *Type, const clang::DeclaratorDecl *Decl,219                     specific_attr_iterator<HLSLAppliedSemanticAttr> begin,220                     specific_attr_iterator<HLSLAppliedSemanticAttr> end);221 222  specific_attr_iterator<HLSLAppliedSemanticAttr>223  handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,224                      llvm::Value *Source, const clang::DeclaratorDecl *Decl,225                      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,226                      specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);227 228public:229  CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}230  virtual ~CGHLSLRuntime() {}231 232  llvm::Type *convertHLSLSpecificType(const Type *T,233                                      const CGHLSLOffsetInfo &OffsetInfo);234  llvm::Type *convertHLSLSpecificType(const Type *T) {235    return convertHLSLSpecificType(T, CGHLSLOffsetInfo());236  }237 238  void generateGlobalCtorDtorCalls();239 240  void addBuffer(const HLSLBufferDecl *D);241  void addRootSignature(const HLSLRootSignatureDecl *D);242  void finishCodeGen();243 244  void setHLSLEntryAttributes(const FunctionDecl *FD, llvm::Function *Fn);245 246  void emitEntryFunction(const FunctionDecl *FD, llvm::Function *Fn);247  void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);248  void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var);249 250  llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);251 252  llvm::StructType *getHLSLBufferLayoutType(const RecordType *LayoutStructTy);253  void addHLSLBufferLayoutType(const RecordType *LayoutStructTy,254                               llvm::StructType *LayoutTy);255  void emitInitListOpaqueValues(CodeGenFunction &CGF, InitListExpr *E);256 257  std::optional<LValue>258  emitResourceArraySubscriptExpr(const ArraySubscriptExpr *E,259                                 CodeGenFunction &CGF);260 261  std::optional<LValue> emitBufferArraySubscriptExpr(262      const ArraySubscriptExpr *E, CodeGenFunction &CGF,263      llvm::function_ref<llvm::Value *(bool Promote)> EmitIdxAfterBase);264 265  bool emitBufferCopy(CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,266                      QualType CType);267 268  LValue emitBufferMemberExpr(CodeGenFunction &CGF, const MemberExpr *E);269 270private:271  void emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,272                                    llvm::GlobalVariable *BufGV,273                                    const CGHLSLOffsetInfo &OffsetInfo);274  void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,275                                   llvm::GlobalVariable *GV);276  void initializeBufferFromBinding(const HLSLBufferDecl *BufDecl,277                                   llvm::GlobalVariable *GV,278                                   HLSLResourceBindingAttr *RBA);279 280  llvm::Value *emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,281                                         HLSLAppliedSemanticAttr *Semantic,282                                         std::optional<unsigned> Index);283  llvm::Value *emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,284                                        HLSLAppliedSemanticAttr *Semantic,285                                        std::optional<unsigned> Index);286  llvm::Value *emitUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,287                                    const clang::DeclaratorDecl *Decl,288                                    HLSLAppliedSemanticAttr *Semantic,289                                    std::optional<unsigned> Index);290 291  void emitSPIRVUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,292                                  HLSLAppliedSemanticAttr *Semantic,293                                  std::optional<unsigned> Index);294  void emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,295                                 HLSLAppliedSemanticAttr *Semantic,296                                 std::optional<unsigned> Index);297  void emitUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,298                             const clang::DeclaratorDecl *Decl,299                             HLSLAppliedSemanticAttr *Semantic,300                             std::optional<unsigned> Index);301 302  llvm::Triple::ArchType getArch();303 304  llvm::DenseMap<const clang::RecordType *, llvm::StructType *> LayoutTypes;305  unsigned SPIRVLastAssignedInputSemanticLocation = 0;306  unsigned SPIRVLastAssignedOutputSemanticLocation = 0;307};308 309} // namespace CodeGen310} // namespace clang311 312#endif313