/////////////////////////////////////////////////////////////////////////////// // // // DxilModule.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. // // // // The main class to work with DXIL, similar to LLVM module. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/DXIL/DxilConstants.h" #include "dxc/DXIL/DxilMetadataHelper.h" #include "dxc/DXIL/DxilCBuffer.h" #include "dxc/DXIL/DxilResource.h" #include "dxc/DXIL/DxilSampler.h" #include "dxc/DXIL/DxilShaderFlags.h" #include "dxc/DXIL/DxilSignature.h" #include "dxc/DXIL/DxilSubobject.h" #include "dxc/DXIL/DxilTypeSystem.h" #include #include #include #include #include namespace llvm { class LLVMContext; class Module; class Function; class Instruction; class MDTuple; class MDOperand; class DebugInfoFinder; } namespace hlsl { class ShaderModel; class OP; struct DxilFunctionProps; class DxilEntryProps; using DxilEntryPropsMap = std::unordered_map>; /// Use this class to manipulate DXIL of a shader. class DxilModule { public: DxilModule(llvm::Module *pModule); ~DxilModule(); // Subsystems. llvm::LLVMContext &GetCtx() const; llvm::Module *GetModule() const; OP *GetOP() const; void SetShaderModel(const ShaderModel *pSM, bool bUseMinPrecision = true); const ShaderModel *GetShaderModel() const; void GetDxilVersion(unsigned &DxilMajor, unsigned &DxilMinor) const; void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor); bool UpgradeValidatorVersion(unsigned ValMajor, unsigned ValMinor); void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const; // Return true on success, requires valid shader model and CollectShaderFlags to have been set bool GetMinValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const; // Update validator version to minimum if higher than current (ex: after CollectShaderFlags) bool UpgradeToMinValidatorVersion(); // Entry functions. llvm::Function *GetEntryFunction(); const llvm::Function *GetEntryFunction() const; void SetEntryFunction(llvm::Function *pEntryFunc); const std::string &GetEntryFunctionName() const; void SetEntryFunctionName(const std::string &name); llvm::Function *GetPatchConstantFunction(); const llvm::Function *GetPatchConstantFunction() const; void SetPatchConstantFunction(llvm::Function *pFunc); bool IsEntryOrPatchConstantFunction(const llvm::Function* pFunc) const; // Flags. unsigned GetGlobalFlags() const; void CollectShaderFlagsForModule(); // Resources. unsigned AddCBuffer(std::unique_ptr pCB); DxilCBuffer &GetCBuffer(unsigned idx); const DxilCBuffer &GetCBuffer(unsigned idx) const; const std::vector > &GetCBuffers() const; unsigned AddSampler(std::unique_ptr pSampler); DxilSampler &GetSampler(unsigned idx); const DxilSampler &GetSampler(unsigned idx) const; const std::vector > &GetSamplers() const; unsigned AddSRV(std::unique_ptr pSRV); DxilResource &GetSRV(unsigned idx); const DxilResource &GetSRV(unsigned idx) const; const std::vector > &GetSRVs() const; unsigned AddUAV(std::unique_ptr pUAV); DxilResource &GetUAV(unsigned idx); const DxilResource &GetUAV(unsigned idx) const; const std::vector > &GetUAVs() const; void LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD, DxilResourceBase &R); void LoadDxilResourceFromMDNode(llvm::MDNode *MD, DxilResource &R); void LoadDxilSamplerFromMDNode(llvm::MDNode *MD, DxilSampler &S); void RemoveUnusedResources(); void RemoveResourcesWithUnusedSymbols(); void RemoveFunction(llvm::Function *F); // Signatures. DxilSignature &GetInputSignature(); const DxilSignature &GetInputSignature() const; DxilSignature &GetOutputSignature(); const DxilSignature &GetOutputSignature() const; DxilSignature &GetPatchConstOrPrimSignature(); const DxilSignature &GetPatchConstOrPrimSignature() const; const std::vector &GetSerializedRootSignature() const; std::vector &GetSerializedRootSignature(); bool HasDxilEntrySignature(const llvm::Function *F) const; DxilEntrySignature &GetDxilEntrySignature(const llvm::Function *F); // Move DxilEntryProps of F to NewF. void ReplaceDxilEntryProps(llvm::Function *F, llvm::Function *NewF); // Clone DxilEntryProps of F to NewF. void CloneDxilEntryProps(llvm::Function *F, llvm::Function *NewF); bool HasDxilEntryProps(const llvm::Function *F) const; DxilEntryProps &GetDxilEntryProps(const llvm::Function *F); const DxilEntryProps &GetDxilEntryProps(const llvm::Function *F) const; // DxilFunctionProps. bool HasDxilFunctionProps(const llvm::Function *F) const; DxilFunctionProps &GetDxilFunctionProps(const llvm::Function *F); const DxilFunctionProps &GetDxilFunctionProps(const llvm::Function *F) const; // Move DxilFunctionProps of F to NewF. void SetPatchConstantFunctionForHS(llvm::Function *hullShaderFunc, llvm::Function *patchConstantFunc); bool IsGraphicsShader(const llvm::Function *F) const; // vs,hs,ds,gs,ps bool IsPatchConstantShader(const llvm::Function *F) const; bool IsComputeShader(const llvm::Function *F) const; // 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(const llvm::Function *F) const ; // Remove Root Signature from module metadata, return true if changed bool StripRootSignatureFromMetadata(); // Remove Subobjects from module metadata, return true if changed bool StripSubobjectsFromMetadata(); // Update validator version metadata to current setting void UpdateValidatorVersionMetadata(); // DXIL type system. DxilTypeSystem &GetTypeSystem(); /// Emit llvm.used array to make sure that optimizations do not remove unreferenced globals. void EmitLLVMUsed(); std::vector &GetLLVMUsed(); void ClearLLVMUsed(); // ViewId state. std::vector &GetSerializedViewIdState(); const std::vector &GetSerializedViewIdState() const; // DXIL metadata manipulation. /// Clear all DXIL data that exists in in-memory form. static void ClearDxilMetadata(llvm::Module &M); /// Serialize DXIL in-memory form to metadata form. void EmitDxilMetadata(); /// Update resource metadata. /// Note: this method not update Metadata for ViewIdState. void ReEmitDxilResources(); /// Deserialize DXIL metadata form into in-memory form. void LoadDxilMetadata(); /// Return true if non-fatal metadata error was detected. bool HasMetadataErrors(); /// Check if a Named meta data node is known by dxil module. static bool IsKnownNamedMetaData(llvm::NamedMDNode &Node); // Reset functions used to transfer ownership. void ResetEntrySignature(DxilEntrySignature *pValue); void ResetSerializedRootSignature(std::vector &Value); void ResetTypeSystem(DxilTypeSystem *pValue); void ResetOP(hlsl::OP *hlslOP); void ResetEntryPropsMap(DxilEntryPropsMap &&PropMap); bool StripReflection(); void StripDebugRelatedCode(); llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder(); static DxilModule *TryGetDxilModule(llvm::Module *pModule); // Helpers for working with precise. // Return true if the instruction should be considered precise. // // An instruction can be marked precise in the following ways: // // 1. Global refactoring is disabled. // 2. The instruction has a precise metadata annotation. // 3. The instruction has precise fast math flags set. // bool IsPrecise(const llvm::Instruction *inst) const; // Check if the instruction has fast math flags configured to indicate // the instruction is precise. static bool HasPreciseFastMathFlags(const llvm::Instruction *inst); // Set fast math flags configured to indicate the instruction is precise. static void SetPreciseFastMathFlags(llvm::Instruction *inst); // True if fast math flags are preserved across serialize/deserialize. static bool PreservesFastMathFlags(const llvm::Instruction *inst); public: ShaderFlags m_ShaderFlags; void CollectShaderFlagsForModule(ShaderFlags &Flags); // Check if DxilModule contains multi component UAV Loads. // This funciton must be called after unused resources are removed from DxilModule bool ModuleHasMulticomponentUAVLoads(); // Compute/Mesh/Amplification shader. void SetNumThreads(unsigned x, unsigned y, unsigned z); unsigned GetNumThreads(unsigned idx) const; // Geometry shader. DXIL::InputPrimitive GetInputPrimitive() const; void SetInputPrimitive(DXIL::InputPrimitive IP); unsigned GetMaxVertexCount() const; void SetMaxVertexCount(unsigned Count); DXIL::PrimitiveTopology GetStreamPrimitiveTopology() const; void SetStreamPrimitiveTopology(DXIL::PrimitiveTopology Topology); bool HasMultipleOutputStreams() const; unsigned GetOutputStream() const; unsigned GetGSInstanceCount() const; void SetGSInstanceCount(unsigned Count); bool IsStreamActive(unsigned Stream) const; void SetStreamActive(unsigned Stream, bool bActive); void SetActiveStreamMask(unsigned Mask); unsigned GetActiveStreamMask() const; // Language options // UseMinPrecision must be set at SetShaderModel time. bool GetUseMinPrecision() const; void SetDisableOptimization(bool disableOptimization); bool GetDisableOptimization() const; void SetAllResourcesBound(bool resourcesBound); bool GetAllResourcesBound() const; // Intermediate options that do not make it to DXIL void SetLegacyResourceReservation(bool legacyResourceReservation); bool GetLegacyResourceReservation() const; void ClearIntermediateOptions(); // Hull and Domain shaders. unsigned GetInputControlPointCount() const; void SetInputControlPointCount(unsigned NumICPs); DXIL::TessellatorDomain GetTessellatorDomain() const; void SetTessellatorDomain(DXIL::TessellatorDomain TessDomain); // Hull shader. unsigned GetOutputControlPointCount() const; void SetOutputControlPointCount(unsigned NumOCPs); DXIL::TessellatorPartitioning GetTessellatorPartitioning() const; void SetTessellatorPartitioning(DXIL::TessellatorPartitioning TessPartitioning); DXIL::TessellatorOutputPrimitive GetTessellatorOutputPrimitive() const; void SetTessellatorOutputPrimitive(DXIL::TessellatorOutputPrimitive TessOutputPrimitive); float GetMaxTessellationFactor() const; void SetMaxTessellationFactor(float MaxTessellationFactor); // Mesh shader unsigned GetMaxOutputVertices() const; void SetMaxOutputVertices(unsigned NumOVs); unsigned GetMaxOutputPrimitives() const; void SetMaxOutputPrimitives(unsigned NumOPs); DXIL::MeshOutputTopology GetMeshOutputTopology() const; void SetMeshOutputTopology(DXIL::MeshOutputTopology MeshOutputTopology); unsigned GetPayloadSizeInBytes() const; void SetPayloadSizeInBytes(unsigned Size); // AutoBindingSpace also enables automatic binding for libraries if set. // UINT_MAX == unset void SetAutoBindingSpace(uint32_t Space); uint32_t GetAutoBindingSpace() const; void SetShaderProperties(DxilFunctionProps *props); DxilSubobjects *GetSubobjects(); const DxilSubobjects *GetSubobjects() const; DxilSubobjects *ReleaseSubobjects(); void ResetSubobjects(DxilSubobjects *subobjects); private: // Signatures. std::vector m_SerializedRootSignature; // Shader resources. std::vector > m_SRVs; std::vector > m_UAVs; std::vector > m_CBuffers; std::vector > m_Samplers; // Geometry shader. DXIL::PrimitiveTopology m_StreamPrimitiveTopology; unsigned m_ActiveStreamMask; private: enum IntermediateFlags : uint32_t { LegacyResourceReservation = 1 << 0, }; private: llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; llvm::Function *m_pEntryFunc; std::string m_EntryName; std::unique_ptr m_pMDHelper; std::unique_ptr m_pDebugInfoFinder; const ShaderModel *m_pSM; unsigned m_DxilMajor; unsigned m_DxilMinor; unsigned m_ValMajor; unsigned m_ValMinor; std::unique_ptr m_pOP; size_t m_pUnused; // LLVM used. std::vector m_LLVMUsed; // Type annotations. std::unique_ptr m_pTypeSystem; // EntryProps for shader functions. DxilEntryPropsMap m_DxilEntryPropsMap; // Keeps track of patch constant functions used by hull shaders std::unordered_set m_PatchConstantFunctions; // Serialized ViewId state. std::vector m_SerializedState; // DXIL metadata serialization/deserialization. llvm::MDTuple *EmitDxilResources(); void LoadDxilResources(const llvm::MDOperand &MDO); // Helpers. template unsigned AddResource(std::vector > &Vec, std::unique_ptr pRes); void LoadDxilSignature(const llvm::MDTuple *pSigTuple, DxilSignature &Sig, bool bInput); // properties from HLModule preserved as ShaderFlags bool m_bDisableOptimizations; bool m_bUseMinPrecision; bool m_bAllResourcesBound; // properties from HLModule that should not make it to the final DXIL uint32_t m_IntermediateFlags; uint32_t m_AutoBindingSpace; std::unique_ptr m_pSubobjects; // m_bMetadataErrors is true if non-fatal metadata errors were encountered. // Validator will fail in this case, but should not block module load. bool m_bMetadataErrors; }; } // namespace hlsl