Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/DXContainerGlobals.cpp
35266 views
//===- DXContainerGlobals.cpp - DXContainer global generator pass ---------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// DXContainerGlobalsPass implementation.9//10//===----------------------------------------------------------------------===//1112#include "DXILShaderFlags.h"13#include "DirectX.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/BinaryFormat/DXContainer.h"18#include "llvm/CodeGen/Passes.h"19#include "llvm/IR/Constants.h"20#include "llvm/IR/Module.h"21#include "llvm/InitializePasses.h"22#include "llvm/MC/DXContainerPSVInfo.h"23#include "llvm/Pass.h"24#include "llvm/Support/MD5.h"25#include "llvm/Transforms/Utils/ModuleUtils.h"2627using namespace llvm;28using namespace llvm::dxil;29using namespace llvm::mcdxbc;3031namespace {32class DXContainerGlobals : public llvm::ModulePass {3334GlobalVariable *buildContainerGlobal(Module &M, Constant *Content,35StringRef Name, StringRef SectionName);36GlobalVariable *getFeatureFlags(Module &M);37GlobalVariable *computeShaderHash(Module &M);38GlobalVariable *buildSignature(Module &M, Signature &Sig, StringRef Name,39StringRef SectionName);40void addSignature(Module &M, SmallVector<GlobalValue *> &Globals);41void addPipelineStateValidationInfo(Module &M,42SmallVector<GlobalValue *> &Globals);4344public:45static char ID; // Pass identification, replacement for typeid46DXContainerGlobals() : ModulePass(ID) {47initializeDXContainerGlobalsPass(*PassRegistry::getPassRegistry());48}4950StringRef getPassName() const override {51return "DXContainer Global Emitter";52}5354bool runOnModule(Module &M) override;5556void getAnalysisUsage(AnalysisUsage &AU) const override {57AU.setPreservesAll();58AU.addRequired<ShaderFlagsAnalysisWrapper>();59}60};6162} // namespace6364bool DXContainerGlobals::runOnModule(Module &M) {65llvm::SmallVector<GlobalValue *> Globals;66Globals.push_back(getFeatureFlags(M));67Globals.push_back(computeShaderHash(M));68addSignature(M, Globals);69addPipelineStateValidationInfo(M, Globals);70appendToCompilerUsed(M, Globals);71return true;72}7374GlobalVariable *DXContainerGlobals::getFeatureFlags(Module &M) {75const uint64_t FeatureFlags =76static_cast<uint64_t>(getAnalysis<ShaderFlagsAnalysisWrapper>()77.getShaderFlags()78.getFeatureFlags());7980Constant *FeatureFlagsConstant =81ConstantInt::get(M.getContext(), APInt(64, FeatureFlags));82return buildContainerGlobal(M, FeatureFlagsConstant, "dx.sfi0", "SFI0");83}8485GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) {86auto *DXILConstant =87cast<ConstantDataArray>(M.getNamedGlobal("dx.dxil")->getInitializer());88MD5 Digest;89Digest.update(DXILConstant->getRawDataValues());90MD5::MD5Result Result = Digest.final();9192dxbc::ShaderHash HashData = {0, {0}};93// The Hash's IncludesSource flag gets set whenever the hashed shader includes94// debug information.95if (M.debug_compile_units_begin() != M.debug_compile_units_end())96HashData.Flags = static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);9798memcpy(reinterpret_cast<void *>(&HashData.Digest), Result.data(), 16);99if (sys::IsBigEndianHost)100HashData.swapBytes();101StringRef Data(reinterpret_cast<char *>(&HashData), sizeof(dxbc::ShaderHash));102103Constant *ModuleConstant =104ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));105return buildContainerGlobal(M, ModuleConstant, "dx.hash", "HASH");106}107108GlobalVariable *DXContainerGlobals::buildContainerGlobal(109Module &M, Constant *Content, StringRef Name, StringRef SectionName) {110auto *GV = new llvm::GlobalVariable(111M, Content->getType(), true, GlobalValue::PrivateLinkage, Content, Name);112GV->setSection(SectionName);113GV->setAlignment(Align(4));114return GV;115}116117GlobalVariable *DXContainerGlobals::buildSignature(Module &M, Signature &Sig,118StringRef Name,119StringRef SectionName) {120SmallString<256> Data;121raw_svector_ostream OS(Data);122Sig.write(OS);123Constant *Constant =124ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);125return buildContainerGlobal(M, Constant, Name, SectionName);126}127128void DXContainerGlobals::addSignature(Module &M,129SmallVector<GlobalValue *> &Globals) {130// FIXME: support graphics shader.131// see issue https://github.com/llvm/llvm-project/issues/90504.132133Signature InputSig;134Globals.emplace_back(buildSignature(M, InputSig, "dx.isg1", "ISG1"));135136Signature OutputSig;137Globals.emplace_back(buildSignature(M, OutputSig, "dx.osg1", "OSG1"));138}139140void DXContainerGlobals::addPipelineStateValidationInfo(141Module &M, SmallVector<GlobalValue *> &Globals) {142SmallString<256> Data;143raw_svector_ostream OS(Data);144PSVRuntimeInfo PSV;145Triple TT(M.getTargetTriple());146PSV.BaseData.MinimumWaveLaneCount = 0;147PSV.BaseData.MaximumWaveLaneCount = std::numeric_limits<uint32_t>::max();148PSV.BaseData.ShaderStage =149static_cast<uint8_t>(TT.getEnvironment() - Triple::Pixel);150151// Hardcoded values here to unblock loading the shader into D3D.152//153// TODO: Lots more stuff to do here!154//155// See issue https://github.com/llvm/llvm-project/issues/96674.156PSV.BaseData.NumThreadsX = 1;157PSV.BaseData.NumThreadsY = 1;158PSV.BaseData.NumThreadsZ = 1;159PSV.EntryName = "main";160161PSV.finalize(TT.getEnvironment());162PSV.write(OS);163Constant *Constant =164ConstantDataArray::getString(M.getContext(), Data, /*AddNull*/ false);165Globals.emplace_back(buildContainerGlobal(M, Constant, "dx.psv0", "PSV0"));166}167168char DXContainerGlobals::ID = 0;169INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals",170"DXContainer Global Emitter", false, true)171INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper)172INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals",173"DXContainer Global Emitter", false, true)174175ModulePass *llvm::createDXContainerGlobalsPass() {176return new DXContainerGlobals();177}178179180