brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · 95577dd Raw
323 lines · cpp
1//===- DXContainerGlobals.cpp - DXContainer global generator pass ---------===//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// DXContainerGlobalsPass implementation.10//11//===----------------------------------------------------------------------===//12 13#include "DXILRootSignature.h"14#include "DXILShaderFlags.h"15#include "DirectX.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/StringExtras.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/Analysis/DXILMetadataAnalysis.h"20#include "llvm/Analysis/DXILResource.h"21#include "llvm/BinaryFormat/DXContainer.h"22#include "llvm/CodeGen/Passes.h"23#include "llvm/IR/Constants.h"24#include "llvm/IR/Module.h"25#include "llvm/InitializePasses.h"26#include "llvm/MC/DXContainerPSVInfo.h"27#include "llvm/Pass.h"28#include "llvm/Support/MD5.h"29#include "llvm/TargetParser/Triple.h"30#include "llvm/Transforms/Utils/ModuleUtils.h"31#include <cstdint>32 33using namespace llvm;34using namespace llvm::dxil;35using namespace llvm::mcdxbc;36 37namespace {38class DXContainerGlobals : public llvm::ModulePass {39 40  GlobalVariable *buildContainerGlobal(Module &M, Constant *Content,41                                       StringRef Name, StringRef SectionName);42  GlobalVariable *getFeatureFlags(Module &M);43  GlobalVariable *computeShaderHash(Module &M);44  GlobalVariable *buildSignature(Module &M, Signature &Sig, StringRef Name,45                                 StringRef SectionName);46  void addSignature(Module &M, SmallVector<GlobalValue *> &Globals);47  void addRootSignature(Module &M, SmallVector<GlobalValue *> &Globals);48  void addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV);49  void addPipelineStateValidationInfo(Module &M,50                                      SmallVector<GlobalValue *> &Globals);51 52public:53  static char ID; // Pass identification, replacement for typeid54  DXContainerGlobals() : ModulePass(ID) {}55 56  StringRef getPassName() const override {57    return "DXContainer Global Emitter";58  }59 60  bool runOnModule(Module &M) override;61 62  void getAnalysisUsage(AnalysisUsage &AU) const override {63    AU.setPreservesAll();64    AU.addRequired<ShaderFlagsAnalysisWrapper>();65    AU.addRequired<RootSignatureAnalysisWrapper>();66    AU.addRequired<DXILMetadataAnalysisWrapperPass>();67    AU.addRequired<DXILResourceTypeWrapperPass>();68    AU.addRequired<DXILResourceWrapperPass>();69  }70};71 72} // namespace73 74bool DXContainerGlobals::runOnModule(Module &M) {75  llvm::SmallVector<GlobalValue *> Globals;76  Globals.push_back(getFeatureFlags(M));77  Globals.push_back(computeShaderHash(M));78  addSignature(M, Globals);79  addRootSignature(M, Globals);80  addPipelineStateValidationInfo(M, Globals);81  appendToCompilerUsed(M, Globals);82  return true;83}84 85GlobalVariable *DXContainerGlobals::getFeatureFlags(Module &M) {86  uint64_t CombinedFeatureFlags = getAnalysis<ShaderFlagsAnalysisWrapper>()87                                      .getShaderFlags()88                                      .getCombinedFlags()89                                      .getFeatureFlags();90 91  Constant *FeatureFlagsConstant =92      ConstantInt::get(M.getContext(), APInt(64, CombinedFeatureFlags));93  return buildContainerGlobal(M, FeatureFlagsConstant, "dx.sfi0", "SFI0");94}95 96GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) {97  auto *DXILConstant =98      cast<ConstantDataArray>(M.getNamedGlobal("dx.dxil")->getInitializer());99  MD5 Digest;100  Digest.update(DXILConstant->getRawDataValues());101  MD5::MD5Result Result = Digest.final();102 103  dxbc::ShaderHash HashData = {0, {0}};104  // The Hash's IncludesSource flag gets set whenever the hashed shader includes105  // debug information.106  if (!M.debug_compile_units().empty())107    HashData.Flags = static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);108 109  memcpy(reinterpret_cast<void *>(&HashData.Digest), Result.data(), 16);110  if (sys::IsBigEndianHost)111    HashData.swapBytes();112  StringRef Data(reinterpret_cast<char *>(&HashData), sizeof(dxbc::ShaderHash));113 114  Constant *ModuleConstant =115      ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));116  return buildContainerGlobal(M, ModuleConstant, "dx.hash", "HASH");117}118 119GlobalVariable *DXContainerGlobals::buildContainerGlobal(120    Module &M, Constant *Content, StringRef Name, StringRef SectionName) {121  auto *GV = new llvm::GlobalVariable(122      M, Content->getType(), true, GlobalValue::PrivateLinkage, Content, Name);123  GV->setSection(SectionName);124  GV->setAlignment(Align(4));125  return GV;126}127 128GlobalVariable *DXContainerGlobals::buildSignature(Module &M, Signature &Sig,129                                                   StringRef Name,130                                                   StringRef SectionName) {131  SmallString<256> Data;132  raw_svector_ostream OS(Data);133  Sig.write(OS);134  Constant *Constant =135      ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);136  return buildContainerGlobal(M, Constant, Name, SectionName);137}138 139void DXContainerGlobals::addSignature(Module &M,140                                      SmallVector<GlobalValue *> &Globals) {141  // FIXME: support graphics shader.142  //  see issue https://github.com/llvm/llvm-project/issues/90504.143 144  Signature InputSig;145  Globals.emplace_back(buildSignature(M, InputSig, "dx.isg1", "ISG1"));146 147  Signature OutputSig;148  Globals.emplace_back(buildSignature(M, OutputSig, "dx.osg1", "OSG1"));149}150 151void DXContainerGlobals::addRootSignature(Module &M,152                                          SmallVector<GlobalValue *> &Globals) {153 154  dxil::ModuleMetadataInfo &MMI =155      getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();156 157  // Root Signature in Library don't compile to DXContainer.158  if (MMI.ShaderProfile == llvm::Triple::Library)159    return;160 161  auto &RSA = getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();162  const Function *EntryFunction = nullptr;163 164  if (MMI.ShaderProfile != llvm::Triple::RootSignature) {165    assert(MMI.EntryPropertyVec.size() == 1);166    EntryFunction = MMI.EntryPropertyVec[0].Entry;167  }168 169  const mcdxbc::RootSignatureDesc *RS = RSA.getDescForFunction(EntryFunction);170  if (!RS)171    return;172 173  SmallString<256> Data;174  raw_svector_ostream OS(Data);175 176  RS->write(OS);177 178  Constant *Constant =179      ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);180  Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.rts0", "RTS0"));181}182 183void DXContainerGlobals::addResourcesForPSV(Module &M, PSVRuntimeInfo &PSV) {184  const DXILResourceMap &DRM =185      getAnalysis<DXILResourceWrapperPass>().getResourceMap();186  DXILResourceTypeMap &DRTM =187      getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();188 189  auto MakeBinding =190      [](const dxil::ResourceInfo::ResourceBinding &Binding,191         const dxbc::PSV::ResourceType Type, const dxil::ResourceKind Kind,192         const dxbc::PSV::ResourceFlags Flags = dxbc::PSV::ResourceFlags()) {193        dxbc::PSV::v2::ResourceBindInfo BindInfo;194        BindInfo.Type = Type;195        BindInfo.LowerBound = Binding.LowerBound;196        assert(197            (Binding.Size == UINT32_MAX ||198             (uint64_t)Binding.LowerBound + Binding.Size - 1 <= UINT32_MAX) &&199            "Resource range is too large");200        BindInfo.UpperBound = (Binding.Size == UINT32_MAX)201                                  ? UINT32_MAX202                                  : Binding.LowerBound + Binding.Size - 1;203        BindInfo.Space = Binding.Space;204        BindInfo.Kind = static_cast<dxbc::PSV::ResourceKind>(Kind);205        BindInfo.Flags = Flags;206        return BindInfo;207      };208 209  for (const dxil::ResourceInfo &RI : DRM.cbuffers()) {210    const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();211    PSV.Resources.push_back(MakeBinding(Binding, dxbc::PSV::ResourceType::CBV,212                                        dxil::ResourceKind::CBuffer));213  }214  for (const dxil::ResourceInfo &RI : DRM.samplers()) {215    const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();216    PSV.Resources.push_back(MakeBinding(Binding,217                                        dxbc::PSV::ResourceType::Sampler,218                                        dxil::ResourceKind::Sampler));219  }220  for (const dxil::ResourceInfo &RI : DRM.srvs()) {221    const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();222 223    dxil::ResourceTypeInfo &TypeInfo = DRTM[RI.getHandleTy()];224    dxbc::PSV::ResourceType ResType;225    if (TypeInfo.isStruct())226      ResType = dxbc::PSV::ResourceType::SRVStructured;227    else if (TypeInfo.isTyped())228      ResType = dxbc::PSV::ResourceType::SRVTyped;229    else230      ResType = dxbc::PSV::ResourceType::SRVRaw;231 232    PSV.Resources.push_back(233        MakeBinding(Binding, ResType, TypeInfo.getResourceKind()));234  }235  for (const dxil::ResourceInfo &RI : DRM.uavs()) {236    const dxil::ResourceInfo::ResourceBinding &Binding = RI.getBinding();237 238    dxil::ResourceTypeInfo &TypeInfo = DRTM[RI.getHandleTy()];239    dxbc::PSV::ResourceType ResType;240    if (RI.hasCounter())241      ResType = dxbc::PSV::ResourceType::UAVStructuredWithCounter;242    else if (TypeInfo.isStruct())243      ResType = dxbc::PSV::ResourceType::UAVStructured;244    else if (TypeInfo.isTyped())245      ResType = dxbc::PSV::ResourceType::UAVTyped;246    else247      ResType = dxbc::PSV::ResourceType::UAVRaw;248 249    dxbc::PSV::ResourceFlags Flags;250    // TODO: Add support for dxbc::PSV::ResourceFlag::UsedByAtomic64, tracking251    // with https://github.com/llvm/llvm-project/issues/104392252    Flags.Flags = 0u;253 254    PSV.Resources.push_back(255        MakeBinding(Binding, ResType, TypeInfo.getResourceKind(), Flags));256  }257}258 259void DXContainerGlobals::addPipelineStateValidationInfo(260    Module &M, SmallVector<GlobalValue *> &Globals) {261  SmallString<256> Data;262  raw_svector_ostream OS(Data);263  PSVRuntimeInfo PSV;264  PSV.BaseData.MinimumWaveLaneCount = 0;265  PSV.BaseData.MaximumWaveLaneCount = std::numeric_limits<uint32_t>::max();266 267  dxil::ModuleMetadataInfo &MMI =268      getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();269  assert(MMI.EntryPropertyVec.size() == 1 ||270         MMI.ShaderProfile == Triple::Library ||271         MMI.ShaderProfile == Triple::RootSignature);272  PSV.BaseData.ShaderStage =273      static_cast<uint8_t>(MMI.ShaderProfile - Triple::Pixel);274 275  addResourcesForPSV(M, PSV);276 277  // Hardcoded values here to unblock loading the shader into D3D.278  //279  // TODO: Lots more stuff to do here!280  //281  // See issue https://github.com/llvm/llvm-project/issues/96674.282  switch (MMI.ShaderProfile) {283  case Triple::Compute:284    PSV.BaseData.NumThreadsX = MMI.EntryPropertyVec[0].NumThreadsX;285    PSV.BaseData.NumThreadsY = MMI.EntryPropertyVec[0].NumThreadsY;286    PSV.BaseData.NumThreadsZ = MMI.EntryPropertyVec[0].NumThreadsZ;287    if (MMI.EntryPropertyVec[0].WaveSizeMin) {288      PSV.BaseData.MinimumWaveLaneCount = MMI.EntryPropertyVec[0].WaveSizeMin;289      PSV.BaseData.MaximumWaveLaneCount =290          MMI.EntryPropertyVec[0].WaveSizeMax291              ? MMI.EntryPropertyVec[0].WaveSizeMax292              : MMI.EntryPropertyVec[0].WaveSizeMin;293    }294    break;295  default:296    break;297  }298 299  if (MMI.ShaderProfile != Triple::Library &&300      MMI.ShaderProfile != Triple::RootSignature)301    PSV.EntryName = MMI.EntryPropertyVec[0].Entry->getName();302 303  PSV.finalize(MMI.ShaderProfile);304  PSV.write(OS);305  Constant *Constant =306      ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);307  Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.psv0", "PSV0"));308}309 310char DXContainerGlobals::ID = 0;311INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals",312                      "DXContainer Global Emitter", false, true)313INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper)314INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)315INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)316INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)317INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals",318                    "DXContainer Global Emitter", false, true)319 320ModulePass *llvm::createDXContainerGlobalsPass() {321  return new DXContainerGlobals();322}323