
DXIL shader bitcode is hashed and the hash is placed into the final output object file in its own data part. This change modifies the DXContainerGlobals pass to compute the shader hash (just an MD5 of the bitcode) and put the shader hash data into a global for the HASH part. This also sets the hash flag as appropriate for if the hashed shader contained debug information. There is additional handling required to get debug information in shaders working correctly with our tooling, but that will be addressed in subsequent patches. Reviewed By: python3kgae Differential Revision: https://reviews.llvm.org/D139357
113 lines
3.8 KiB
C++
113 lines
3.8 KiB
C++
//===- DXContainerGlobals.cpp - DXContainer global generator pass ---------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// DXContainerGlobalsPass implementation.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "DXILShaderFlags.h"
|
|
#include "DirectX.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/BinaryFormat/DXContainer.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/MD5.h"
|
|
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::dxil;
|
|
|
|
namespace {
|
|
class DXContainerGlobals : public llvm::ModulePass {
|
|
|
|
GlobalVariable *getShaderFlags(Module &M);
|
|
GlobalVariable *computeShaderHash(Module &M);
|
|
|
|
public:
|
|
static char ID; // Pass identification, replacement for typeid
|
|
DXContainerGlobals() : ModulePass(ID) {
|
|
initializeDXContainerGlobalsPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
StringRef getPassName() const override {
|
|
return "DXContainer Global Emitter";
|
|
}
|
|
|
|
bool runOnModule(Module &M) override;
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
AU.setPreservesAll();
|
|
AU.addRequired<ShaderFlagsAnalysisWrapper>();
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
bool DXContainerGlobals::runOnModule(Module &M) {
|
|
llvm::SmallVector<GlobalValue *> Globals;
|
|
Globals.push_back(getShaderFlags(M));
|
|
Globals.push_back(computeShaderHash(M));
|
|
|
|
appendToCompilerUsed(M, Globals);
|
|
return true;
|
|
}
|
|
|
|
GlobalVariable *DXContainerGlobals::getShaderFlags(Module &M) {
|
|
const uint64_t Flags =
|
|
(uint64_t)(getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags());
|
|
|
|
Constant *FlagsConstant = ConstantInt::get(M.getContext(), APInt(64, Flags));
|
|
auto *GV = new llvm::GlobalVariable(M, FlagsConstant->getType(), true,
|
|
GlobalValue::PrivateLinkage,
|
|
FlagsConstant, "dx.sfi0");
|
|
GV->setSection("SFI0");
|
|
GV->setAlignment(Align(4));
|
|
return GV;
|
|
}
|
|
|
|
GlobalVariable *DXContainerGlobals::computeShaderHash(Module &M) {
|
|
auto *DXILConstant =
|
|
cast<ConstantDataArray>(M.getNamedGlobal("dx.dxil")->getInitializer());
|
|
MD5 Digest;
|
|
Digest.update(DXILConstant->getRawDataValues());
|
|
MD5::MD5Result Result = Digest.final();
|
|
|
|
dxbc::ShaderHash HashData = {0, {0}};
|
|
// The Hash's IncludesSource flag gets set whenever the hashed shader includes
|
|
// debug information.
|
|
if (M.debug_compile_units_begin() != M.debug_compile_units_end())
|
|
HashData.Flags = static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);
|
|
|
|
memcpy(reinterpret_cast<void *>(&HashData.Digest), Result.data(), 16);
|
|
if (sys::IsBigEndianHost)
|
|
HashData.swapBytes();
|
|
StringRef Data(reinterpret_cast<char *>(&HashData), sizeof(dxbc::ShaderHash));
|
|
|
|
Constant *ModuleConstant =
|
|
ConstantDataArray::get(M.getContext(), arrayRefFromStringRef(Data));
|
|
auto *GV = new llvm::GlobalVariable(M, ModuleConstant->getType(), true,
|
|
GlobalValue::PrivateLinkage,
|
|
ModuleConstant, "dx.hash");
|
|
GV->setSection("HASH");
|
|
GV->setAlignment(Align(4));
|
|
return GV;
|
|
}
|
|
|
|
char DXContainerGlobals::ID = 0;
|
|
INITIALIZE_PASS_BEGIN(DXContainerGlobals, "dxil-globals",
|
|
"DXContainer Global Emitter", false, true)
|
|
INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper)
|
|
INITIALIZE_PASS_END(DXContainerGlobals, "dxil-globals",
|
|
"DXContainer Global Emitter", false, true)
|
|
|
|
ModulePass *llvm::createDXContainerGlobalsPass() {
|
|
return new DXContainerGlobals();
|
|
}
|