340 строки
13 KiB
C++
340 строки
13 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// HLModule.h //
|
|
// Copyright (C) Microsoft Corporation. All rights reserved. //
|
|
// This file is distributed under the University of Illinois Open Source //
|
|
// License. See LICENSE.TXT for details. //
|
|
// //
|
|
// HighLevel DX IR module. //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#pragma once
|
|
|
|
#include "dxc/DXIL/DxilConstants.h"
|
|
#include "dxc/DXIL/DxilFunctionProps.h"
|
|
#include "dxc/DXIL/DxilMetadataHelper.h"
|
|
#include "dxc/DXIL/DxilResourceProperties.h"
|
|
#include "dxc/DXIL/DxilSampler.h"
|
|
#include "dxc/DXIL/DxilShaderModel.h"
|
|
#include "dxc/DXIL/DxilSignature.h"
|
|
#include "dxc/DXIL/DxilSubobject.h"
|
|
#include "dxc/HLSL/HLOperations.h"
|
|
#include "dxc/HLSL/HLResource.h"
|
|
#include "dxc/Support/Global.h"
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
template <typename T> class ArrayRef;
|
|
class LLVMContext;
|
|
class Module;
|
|
class Function;
|
|
class Instruction;
|
|
class CallInst;
|
|
class MDTuple;
|
|
class MDNode;
|
|
class GlobalVariable;
|
|
class DIGlobalVariable;
|
|
class DebugInfoFinder;
|
|
class GetElementPtrInst;
|
|
} // namespace llvm
|
|
|
|
namespace hlsl {
|
|
|
|
class ShaderModel;
|
|
class OP;
|
|
|
|
struct HLOptions {
|
|
HLOptions()
|
|
: bDefaultRowMajor(false), bIEEEStrict(false), bAllResourcesBound(false),
|
|
bDisableOptimizations(false), PackingStrategy(0),
|
|
bUseMinPrecision(false), bDX9CompatMode(false), bFXCCompatMode(false),
|
|
bLegacyResourceReservation(false), bForceZeroStoreLifetimes(false),
|
|
unused(0) {}
|
|
uint32_t GetHLOptionsRaw() const;
|
|
void SetHLOptionsRaw(uint32_t data);
|
|
unsigned bDefaultRowMajor : 1;
|
|
unsigned bIEEEStrict : 1;
|
|
unsigned bAllResourcesBound : 1;
|
|
unsigned bDisableOptimizations : 1;
|
|
unsigned PackingStrategy : 2;
|
|
static_assert((unsigned)DXIL::PackingStrategy::Invalid < 4,
|
|
"otherwise 2 bits is not enough to store PackingStrategy");
|
|
unsigned bUseMinPrecision : 1;
|
|
unsigned bDX9CompatMode : 1;
|
|
unsigned bFXCCompatMode : 1;
|
|
unsigned bLegacyResourceReservation : 1;
|
|
unsigned bForceZeroStoreLifetimes : 1;
|
|
unsigned bResMayAlias : 1;
|
|
unsigned unused : 19;
|
|
};
|
|
|
|
typedef std::unordered_map<const llvm::Function *,
|
|
std::unique_ptr<DxilFunctionProps>>
|
|
DxilFunctionPropsMap;
|
|
|
|
/// Use this class to manipulate HLDXIR of a shader.
|
|
class HLModule {
|
|
public:
|
|
HLModule(llvm::Module *pModule);
|
|
~HLModule();
|
|
using Domain = DXIL::TessellatorDomain;
|
|
// Subsystems.
|
|
llvm::LLVMContext &GetCtx() const;
|
|
llvm::Module *GetModule() const;
|
|
OP *GetOP() const;
|
|
void SetShaderModel(const ShaderModel *pSM);
|
|
const ShaderModel *GetShaderModel() const;
|
|
void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor);
|
|
void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const;
|
|
void SetForceZeroStoreLifetimes(bool ForceZeroStoreLifetimes);
|
|
bool GetForceZeroStoreLifetimes() const;
|
|
|
|
// HLOptions
|
|
void SetHLOptions(HLOptions &opts);
|
|
const HLOptions &GetHLOptions() const;
|
|
|
|
// AutoBindingSpace also enables automatic binding for libraries if set.
|
|
// UINT_MAX == unset
|
|
void SetAutoBindingSpace(uint32_t Space);
|
|
uint32_t GetAutoBindingSpace() const;
|
|
|
|
// Entry function.
|
|
llvm::Function *GetEntryFunction() const;
|
|
void SetEntryFunction(llvm::Function *pEntryFunc);
|
|
const std::string &GetEntryFunctionName() const;
|
|
void SetEntryFunctionName(const std::string &name);
|
|
llvm::Function *GetPatchConstantFunction();
|
|
|
|
// Resources.
|
|
unsigned AddCBuffer(std::unique_ptr<DxilCBuffer> pCB);
|
|
DxilCBuffer &GetCBuffer(unsigned idx);
|
|
const DxilCBuffer &GetCBuffer(unsigned idx) const;
|
|
const std::vector<std::unique_ptr<DxilCBuffer>> &GetCBuffers() const;
|
|
|
|
unsigned AddSampler(std::unique_ptr<DxilSampler> pSampler);
|
|
DxilSampler &GetSampler(unsigned idx);
|
|
const DxilSampler &GetSampler(unsigned idx) const;
|
|
const std::vector<std::unique_ptr<DxilSampler>> &GetSamplers() const;
|
|
|
|
unsigned AddSRV(std::unique_ptr<HLResource> pSRV);
|
|
HLResource &GetSRV(unsigned idx);
|
|
const HLResource &GetSRV(unsigned idx) const;
|
|
const std::vector<std::unique_ptr<HLResource>> &GetSRVs() const;
|
|
|
|
unsigned AddUAV(std::unique_ptr<HLResource> pUAV);
|
|
HLResource &GetUAV(unsigned idx);
|
|
const HLResource &GetUAV(unsigned idx) const;
|
|
const std::vector<std::unique_ptr<HLResource>> &GetUAVs() const;
|
|
|
|
void RemoveGlobal(llvm::GlobalVariable *GV);
|
|
void RemoveFunction(llvm::Function *F);
|
|
|
|
// ThreadGroupSharedMemory.
|
|
typedef std::vector<llvm::GlobalVariable *>::iterator tgsm_iterator;
|
|
tgsm_iterator tgsm_begin();
|
|
tgsm_iterator tgsm_end();
|
|
void AddGroupSharedVariable(llvm::GlobalVariable *GV);
|
|
|
|
// Signatures.
|
|
std::vector<uint8_t> &GetSerializedRootSignature();
|
|
void SetSerializedRootSignature(const uint8_t *pData, unsigned size);
|
|
|
|
// DxilFunctionProps.
|
|
bool HasDxilFunctionProps(llvm::Function *F);
|
|
DxilFunctionProps &GetDxilFunctionProps(llvm::Function *F);
|
|
void AddDxilFunctionProps(llvm::Function *F,
|
|
std::unique_ptr<DxilFunctionProps> &info);
|
|
void SetPatchConstantFunctionForHS(llvm::Function *hullShaderFunc,
|
|
llvm::Function *patchConstantFunc);
|
|
bool IsGraphicsShader(llvm::Function *F); // vs,hs,ds,gs,ps
|
|
bool IsPatchConstantShader(llvm::Function *F);
|
|
bool IsComputeShader(llvm::Function *F);
|
|
bool IsNodeShader(llvm::Function *F);
|
|
|
|
// Is an entry function that uses input/output signature conventions?
|
|
// Includes: vs/hs/ds/gs/ps/cs as well as the patch constant function.
|
|
bool IsEntryThatUsesSignatures(llvm::Function *F);
|
|
// Is F an entry?
|
|
// Includes: IsEntryThatUsesSignatures and all ray tracing shaders.
|
|
bool IsEntry(llvm::Function *F);
|
|
|
|
DxilFunctionAnnotation *GetFunctionAnnotation(llvm::Function *F);
|
|
DxilFunctionAnnotation *AddFunctionAnnotation(llvm::Function *F);
|
|
|
|
// Float Denorm mode.
|
|
void SetFloat32DenormMode(const DXIL::Float32DenormMode mode);
|
|
DXIL::Float32DenormMode GetFloat32DenormMode() const;
|
|
|
|
// Default function linkage for libraries
|
|
DXIL::DefaultLinkage GetDefaultLinkage() const;
|
|
void SetDefaultLinkage(const DXIL::DefaultLinkage linkage);
|
|
|
|
// HLDXIR metadata manipulation.
|
|
/// Serialize HLDXIR in-memory form to metadata form.
|
|
void EmitHLMetadata();
|
|
/// Deserialize HLDXIR metadata form into in-memory form.
|
|
void LoadHLMetadata();
|
|
/// Delete any HLDXIR from the specified module.
|
|
static void ClearHLMetadata(llvm::Module &M);
|
|
|
|
DxilResourceBase *
|
|
AddResourceWithGlobalVariableAndProps(llvm::Constant *GV,
|
|
DxilResourceProperties &RP);
|
|
unsigned GetBindingForResourceInCB(llvm::GetElementPtrInst *CbPtr,
|
|
llvm::GlobalVariable *CbGV,
|
|
DXIL::ResourceClass RC);
|
|
|
|
// Type related methods.
|
|
static bool IsStreamOutputPtrType(llvm::Type *Ty);
|
|
static bool IsStreamOutputType(llvm::Type *Ty);
|
|
static void GetParameterRowsAndCols(llvm::Type *Ty, unsigned &rows,
|
|
unsigned &cols,
|
|
DxilParameterAnnotation ¶mAnnotation);
|
|
|
|
// HL code gen.
|
|
static llvm::Function *GetHLOperationFunction(
|
|
HLOpcodeGroup group, unsigned opcode, llvm::Type *RetType,
|
|
llvm::ArrayRef<llvm::Value *> paramList, llvm::Module &M);
|
|
template <class BuilderTy>
|
|
static llvm::CallInst *
|
|
EmitHLOperationCall(BuilderTy &Builder, HLOpcodeGroup group, unsigned opcode,
|
|
llvm::Type *RetType,
|
|
llvm::ArrayRef<llvm::Value *> paramList, llvm::Module &M);
|
|
|
|
// Caller must handle conversions to bool and no-ops
|
|
static unsigned GetNumericCastOp(llvm::Type *SrcTy, bool SrcIsUnsigned,
|
|
llvm::Type *DstTy, bool DstIsUnsigned);
|
|
|
|
// Precise attribute.
|
|
// Note: Precise will be marked on alloca inst with metadata in code gen.
|
|
// But mem2reg will remove alloca inst, so need mark precise with
|
|
// function call before mem2reg.
|
|
static bool HasPreciseAttributeWithMetadata(llvm::Instruction *I);
|
|
static void MarkPreciseAttributeWithMetadata(llvm::Instruction *I);
|
|
static void ClearPreciseAttributeWithMetadata(llvm::Instruction *I);
|
|
template <class BuilderTy>
|
|
static void MarkPreciseAttributeOnValWithFunctionCall(llvm::Value *V,
|
|
BuilderTy &Builder,
|
|
llvm::Module &M);
|
|
static void MarkPreciseAttributeOnPtrWithFunctionCall(llvm::Value *Ptr,
|
|
llvm::Module &M);
|
|
static bool HasPreciseAttribute(llvm::Function *F);
|
|
|
|
// DXIL type system.
|
|
DxilTypeSystem &GetTypeSystem();
|
|
|
|
/// Emit llvm.used array to make sure that optimizations do not remove
|
|
/// unreferenced globals.
|
|
void EmitLLVMUsed();
|
|
std::vector<llvm::GlobalVariable *> &GetLLVMUsed();
|
|
|
|
// Release functions used to transfer ownership.
|
|
DxilTypeSystem *ReleaseTypeSystem();
|
|
OP *ReleaseOP();
|
|
DxilFunctionPropsMap &&ReleaseFunctionPropsMap();
|
|
|
|
llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder();
|
|
// Create global variable debug info for element global variable based on the
|
|
// whole global variable.
|
|
static void CreateElementGlobalVariableDebugInfo(
|
|
llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder,
|
|
llvm::GlobalVariable *EltGV, unsigned sizeInBits, unsigned alignInBits,
|
|
unsigned offsetInBits, llvm::StringRef eltName);
|
|
// Replace GV with NewGV in GlobalVariable debug info.
|
|
static void
|
|
UpdateGlobalVariableDebugInfo(llvm::GlobalVariable *GV,
|
|
llvm::DebugInfoFinder &DbgInfoFinder,
|
|
llvm::GlobalVariable *NewGV);
|
|
|
|
DxilSubobjects *GetSubobjects();
|
|
const DxilSubobjects *GetSubobjects() const;
|
|
DxilSubobjects *ReleaseSubobjects();
|
|
void ResetSubobjects(DxilSubobjects *subobjects);
|
|
|
|
// Reg binding for resource in cb.
|
|
void AddRegBinding(unsigned CbID, unsigned ConstantIdx, unsigned Srv,
|
|
unsigned Uav, unsigned Sampler);
|
|
|
|
private:
|
|
// Signatures.
|
|
std::vector<uint8_t> m_SerializedRootSignature;
|
|
|
|
// Shader resources.
|
|
std::vector<std::unique_ptr<HLResource>> m_SRVs;
|
|
std::vector<std::unique_ptr<HLResource>> m_UAVs;
|
|
std::vector<std::unique_ptr<DxilCBuffer>> m_CBuffers;
|
|
std::vector<std::unique_ptr<DxilSampler>> m_Samplers;
|
|
|
|
// ThreadGroupSharedMemory.
|
|
std::vector<llvm::GlobalVariable *> m_TGSMVariables;
|
|
|
|
// High level function info.
|
|
std::unordered_map<const llvm::Function *, std::unique_ptr<DxilFunctionProps>>
|
|
m_DxilFunctionPropsMap;
|
|
std::unordered_set<llvm::Function *> m_PatchConstantFunctions;
|
|
|
|
// Resource bindings for res in cb.
|
|
// Key = CbID << 32 | ConstantIdx. Val is reg binding.
|
|
std::unordered_map<uint64_t, unsigned> m_SrvBindingInCB;
|
|
std::unordered_map<uint64_t, unsigned> m_UavBindingInCB;
|
|
std::unordered_map<uint64_t, unsigned> m_SamplerBindingInCB;
|
|
|
|
private:
|
|
llvm::LLVMContext &m_Ctx;
|
|
llvm::Module *m_pModule;
|
|
llvm::Function *m_pEntryFunc;
|
|
std::string m_EntryName;
|
|
std::unique_ptr<DxilMDHelper> m_pMDHelper;
|
|
std::unique_ptr<llvm::DebugInfoFinder> m_pDebugInfoFinder;
|
|
const ShaderModel *m_pSM;
|
|
unsigned m_DxilMajor;
|
|
unsigned m_DxilMinor;
|
|
unsigned m_ValMajor;
|
|
unsigned m_ValMinor;
|
|
DXIL::Float32DenormMode m_Float32DenormMode;
|
|
HLOptions m_Options;
|
|
std::unique_ptr<OP> m_pOP;
|
|
size_t m_pUnused;
|
|
uint32_t m_AutoBindingSpace;
|
|
DXIL::DefaultLinkage m_DefaultLinkage;
|
|
std::unique_ptr<DxilSubobjects> m_pSubobjects;
|
|
|
|
// DXIL metadata serialization/deserialization.
|
|
llvm::MDTuple *EmitHLResources();
|
|
void LoadHLResources(const llvm::MDOperand &MDO);
|
|
llvm::MDTuple *EmitHLShaderProperties();
|
|
void LoadHLShaderProperties(const llvm::MDOperand &MDO);
|
|
llvm::MDTuple *EmitDxilShaderProperties();
|
|
// LLVM used.
|
|
std::vector<llvm::GlobalVariable *> m_LLVMUsed;
|
|
|
|
// Type annotations.
|
|
std::unique_ptr<DxilTypeSystem> m_pTypeSystem;
|
|
|
|
// Helpers.
|
|
template <typename T>
|
|
unsigned AddResource(std::vector<std::unique_ptr<T>> &Vec,
|
|
std::unique_ptr<T> pRes);
|
|
};
|
|
|
|
/// Use this class to manipulate metadata of extra metadata record properties
|
|
/// that are specific to high-level DX IR.
|
|
class HLExtraPropertyHelper : public DxilExtraPropertyHelper {
|
|
public:
|
|
HLExtraPropertyHelper(llvm::Module *pModule);
|
|
virtual ~HLExtraPropertyHelper() {}
|
|
|
|
virtual void
|
|
EmitSignatureElementProperties(const DxilSignatureElement &SE,
|
|
std::vector<llvm::Metadata *> &MDVals);
|
|
virtual void LoadSignatureElementProperties(const llvm::MDOperand &MDO,
|
|
DxilSignatureElement &SE);
|
|
};
|
|
|
|
} // namespace hlsl
|