From dbb0e4702e34694d2448b924f9554c522e9926dc Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 20 Sep 2016 17:28:18 +0200 Subject: [PATCH] Create DXBC reflection data for shaders in pipelines --- renderdoc/driver/d3d12/d3d12_common.cpp | 34 +++- renderdoc/driver/d3d12/d3d12_common.h | 8 + renderdoc/driver/d3d12/d3d12_device_wrap.cpp | 45 +++++ renderdoc/driver/d3d12/d3d12_resources.cpp | 2 + renderdoc/driver/d3d12/d3d12_resources.h | 159 +++++++++++++++++- .../driver/shaders/dxbc/dxbc_inspect.cpp | 13 ++ renderdoc/driver/shaders/dxbc/dxbc_inspect.h | 2 + 7 files changed, 255 insertions(+), 8 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index de981a35e..c2fcc26b2 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -287,13 +287,6 @@ void Serialiser::Serialise(const char *name, D3D12_SHADER_BYTECODE &el) SerialiseBuffer("pShaderBytecode", (byte *&)el.pShaderBytecode, sz); } -template <> -void Serialiser::Deserialise(const D3D12_SHADER_BYTECODE *const el) const -{ - if(m_Mode == READING) - delete[](byte *)(el->pShaderBytecode); -} - template <> void Serialiser::Serialise(const char *name, D3D12_SO_DECLARATION_ENTRY &el) { @@ -569,6 +562,19 @@ void Serialiser::Serialise(const char *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC } } +template <> +void Serialiser::Deserialise(const D3D12_GRAPHICS_PIPELINE_STATE_DESC *const el) const +{ + if(m_Mode == READING) + { + delete[](byte *)(el->VS.pShaderBytecode); + delete[](byte *)(el->PS.pShaderBytecode); + delete[](byte *)(el->DS.pShaderBytecode); + delete[](byte *)(el->HS.pShaderBytecode); + delete[](byte *)(el->GS.pShaderBytecode); + } +} + template <> void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC &el) { @@ -586,6 +592,13 @@ void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC & } } +template <> +void Serialiser::Deserialise(const D3D12_COMPUTE_PIPELINE_STATE_DESC *const el) const +{ + if(m_Mode == READING) + delete[](byte *)(el->CS.pShaderBytecode); +} + template <> void Serialiser::Serialise(const char *name, D3D12_VERTEX_BUFFER_VIEW &el) { @@ -1032,6 +1045,13 @@ void Serialiser::Serialise(const char *name, D3D12_DISCARD_REGION &el) SerialiseComplexArray("pRects", (D3D12_RECT *&)el.pRects, el.NumRects); } +template <> +void Serialiser::Deserialise(const D3D12_DISCARD_REGION *const el) const +{ + if(m_Mode == READING) + delete[] el->pRects; +} + template <> void Serialiser::Serialise(const char *name, D3D12_SAMPLER_DESC &el) { diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index 430e0e3d8..5ad4d39d9 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -33,6 +33,8 @@ #include "driver/shaders/dxbc/dxbc_compile.h" #include "serialise/serialiser.h" +ShaderReflection *MakeShaderReflection(DXBC::DXBCFile *dxbc); + // similar to RDCUNIMPLEMENTED but for things that are hit often so we don't want to fire the // debugbreak. #define D3D12NOTIMP(...) \ @@ -167,8 +169,12 @@ void Serialiser::Serialise(const char *name, D3D12_SHADER_BYTECODE &el); template <> void Serialiser::Serialise(const char *name, D3D12_GRAPHICS_PIPELINE_STATE_DESC &el); template <> +void Serialiser::Deserialise(const D3D12_GRAPHICS_PIPELINE_STATE_DESC *const el) const; +template <> void Serialiser::Serialise(const char *name, D3D12_COMPUTE_PIPELINE_STATE_DESC &el); template <> +void Serialiser::Deserialise(const D3D12_COMPUTE_PIPELINE_STATE_DESC *const el) const; +template <> void Serialiser::Serialise(const char *name, D3D12_INDEX_BUFFER_VIEW &el); template <> void Serialiser::Serialise(const char *name, D3D12_VERTEX_BUFFER_VIEW &el); @@ -206,6 +212,8 @@ template <> void Serialiser::Serialise(const char *name, D3D12_TEXTURE_COPY_LOCATION &el); template <> void Serialiser::Serialise(const char *name, D3D12_DISCARD_REGION &el); +template <> +void Serialiser::Deserialise(const D3D12_DISCARD_REGION *const el) const; struct D3D12Descriptor; template <> diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index dff893b8f..3829e9284 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -278,6 +278,36 @@ bool WrappedID3D12Device::Serialise_CreateGraphicsPipelineState( { ret = new WrappedID3D12PipelineState(ret, this); + WrappedID3D12PipelineState *wrapped = (WrappedID3D12PipelineState *)ret; + + wrapped->graphics = new D3D12_GRAPHICS_PIPELINE_STATE_DESC(Descriptor); + + D3D12_SHADER_BYTECODE *shaders[] = { + &wrapped->graphics->VS, &wrapped->graphics->HS, &wrapped->graphics->DS, + &wrapped->graphics->GS, &wrapped->graphics->PS, + }; + + for(size_t i = 0; i < ARRAY_COUNT(shaders); i++) + { + if(shaders[i]->BytecodeLength == 0) + { + shaders[i]->pShaderBytecode = NULL; + } + else + { + WrappedID3D12PipelineState::DXBCKey *key = + new WrappedID3D12PipelineState::DXBCKey(*shaders[i]); + + if(WrappedID3D12PipelineState::m_Shaders[*key] == NULL) + WrappedID3D12PipelineState::m_Shaders[*key] = + new WrappedID3D12PipelineState::ShaderEntry(*shaders[i]); + else + WrappedID3D12PipelineState::m_Shaders[*key]->AddRef(); + + shaders[i]->pShaderBytecode = key; + } + } + GetResourceManager()->AddLiveResource(Pipe, ret); } } @@ -352,6 +382,21 @@ bool WrappedID3D12Device::Serialise_CreateComputePipelineState( { ret = new WrappedID3D12PipelineState(ret, this); + WrappedID3D12PipelineState *wrapped = (WrappedID3D12PipelineState *)ret; + + wrapped->compute = new D3D12_COMPUTE_PIPELINE_STATE_DESC(Descriptor); + + WrappedID3D12PipelineState::DXBCKey *key = + new WrappedID3D12PipelineState::DXBCKey(wrapped->compute->CS); + + if(WrappedID3D12PipelineState::m_Shaders[*key] == NULL) + WrappedID3D12PipelineState::m_Shaders[*key] = + new WrappedID3D12PipelineState::ShaderEntry(wrapped->compute->CS); + else + WrappedID3D12PipelineState::m_Shaders[*key]->AddRef(); + + wrapped->compute->CS.pShaderBytecode = key; + GetResourceManager()->AddLiveResource(Pipe, ret); } } diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index f7997b817..d5e5113a3 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -28,6 +28,8 @@ std::vector WrappedID3D12Resource::m_Addresses; std::map WrappedID3D12Resource::m_List; +std::map + WrappedID3D12PipelineState::m_Shaders; #undef D3D12_TYPE_MACRO #define D3D12_TYPE_MACRO(iface) WRAPPED_POOL_INST(CONCAT(Wrapped, iface)); diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 580215699..cf388da22 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -416,6 +416,114 @@ class WrappedID3D12PipelineState : public WrappedDeviceChild12 *searchPaths, const std::string &path) + { + m_DebugInfoSearchPaths = searchPaths; + m_DebugInfoPath = path; + } + + DXBC::DXBCFile *GetDXBC() + { + if(m_DXBCFile == NULL && !m_Bytecode.empty()) + { + TryReplaceOriginalByteCode(); + m_DXBCFile = new DXBC::DXBCFile((const void *)&m_Bytecode[0], m_Bytecode.size()); + } + return m_DXBCFile; + } + ShaderReflection *GetDetails() + { + if(m_Details == NULL && GetDXBC() != NULL) + m_Details = MakeShaderReflection(m_DXBCFile); + return m_Details; + } + + private: + ShaderEntry(const ShaderEntry &e); + void TryReplaceOriginalByteCode(); + ShaderEntry &operator=(const ShaderEntry &e); + + int m_RefCount; + + std::string m_DebugInfoPath; + vector *m_DebugInfoSearchPaths; + + vector m_Bytecode; + + DXBC::DXBCFile *m_DXBCFile; + ShaderReflection *m_Details; + }; + + static map m_Shaders; + enum { TypeEnum = Resource_PipelineState, @@ -424,8 +532,57 @@ public: WrappedID3D12PipelineState(ID3D12PipelineState *real, WrappedID3D12Device *device) : WrappedDeviceChild12(real, device) { + graphics = NULL; } - virtual ~WrappedID3D12PipelineState() { Shutdown(); } + virtual ~WrappedID3D12PipelineState() + { + Shutdown(); + + if(graphics) + { + DXBCKey *vs = (DXBCKey *)graphics->VS.pShaderBytecode; + DXBCKey *hs = (DXBCKey *)graphics->HS.pShaderBytecode; + DXBCKey *ds = (DXBCKey *)graphics->DS.pShaderBytecode; + DXBCKey *gs = (DXBCKey *)graphics->GS.pShaderBytecode; + DXBCKey *ps = (DXBCKey *)graphics->PS.pShaderBytecode; + + if(m_Shaders[*vs]->Release()) + m_Shaders.erase(*vs); + + if(m_Shaders[*hs]->Release()) + m_Shaders.erase(*hs); + + if(m_Shaders[*ds]->Release()) + m_Shaders.erase(*ds); + + if(m_Shaders[*gs]->Release()) + m_Shaders.erase(*gs); + + if(m_Shaders[*ps]->Release()) + m_Shaders.erase(*ps); + + SAFE_DELETE(vs); + SAFE_DELETE(hs); + SAFE_DELETE(ds); + SAFE_DELETE(gs); + SAFE_DELETE(ps); + + SAFE_DELETE(graphics); + } + + if(compute) + { + DXBCKey *cs = (DXBCKey *)compute->CS.pShaderBytecode; + + if(m_Shaders[*cs]->Release()) + m_Shaders.erase(*cs); + + SAFE_DELETE(cs); + + SAFE_DELETE(compute); + } + } + ////////////////////////////// // implement ID3D12PipelineState diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp index 8886a902b..bdf420c81 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp @@ -448,6 +448,19 @@ CBufferVariableType DXBCFile::ParseRDEFType(RDEFHeader *h, char *chunkContents, return ret; } +void DXBCFile::GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength) +{ + if(BytecodeLength < sizeof(FileHeader)) + { + memset(hash, 0, sizeof(uint32_t) * 4); + return; + } + + FileHeader *header = (FileHeader *)ByteCode; + + memcmp(hash, header->hashValue, sizeof(header->hashValue)); +} + bool DXBCFile::CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength) { FileHeader *header = (FileHeader *)ByteCode; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h index ede8abd09..ca23638f4 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h @@ -370,6 +370,8 @@ public: const ASMOperation &GetInstruction(size_t i) { return m_Instructions[i]; } size_t NumOperands(OpcodeType op); + static void GetHash(uint32_t hash[4], const void *ByteCode, size_t BytecodeLength); + static bool CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength); static string GetDebugBinaryPath(const void *ByteCode, size_t ByteCodeLength);