diff --git a/renderdoc/driver/d3d11/d3d11_resources.cpp b/renderdoc/driver/d3d11/d3d11_resources.cpp index d92337246..576918a93 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.cpp +++ b/renderdoc/driver/d3d11/d3d11_resources.cpp @@ -62,6 +62,39 @@ map WrappedID3D11Buffer::m_BufferLi map WrappedShader::m_ShaderList; Threading::CriticalSection WrappedShader::m_ShaderListLock; +void WrappedShader::ShaderEntry::TryReplaceOriginalByteCode() +{ + if(!DXBC::DXBCFile::CheckForDebugInfo((const void *)&m_Bytecode[0], m_Bytecode.size())) + { + string originalPath = DXBC::DXBCFile::GetDebugBinaryPath((const void *)&m_Bytecode[0], m_Bytecode.size()); + if(!originalPath.empty()) + { + FILE* originalShaderFile = FileIO::fopen(originalPath.c_str(), "rb"); + if(originalShaderFile != nullptr) + { + FileIO::fseek64(originalShaderFile, 0L, SEEK_END); + uint64_t originalShaderSize = FileIO::ftell64(originalShaderFile); + FileIO::fseek64(originalShaderFile, 0, SEEK_SET); + + if(originalShaderSize >= m_Bytecode.size()) + { + vector originalBytecode; + + originalBytecode.resize(originalShaderSize); + FileIO::fread(&originalBytecode[0], sizeof(byte), originalShaderSize, originalShaderFile); + + if(DXBC::DXBCFile::CheckForDebugInfo((const void *)&originalBytecode[0], originalBytecode.size())) + { + m_Bytecode.swap(originalBytecode); + } + } + + FileIO::fclose(originalShaderFile); + } + } + } +} + UINT GetMipForSubresource(ID3D11Resource *res, int Subresource) { D3D11_RESOURCE_DIMENSION dim; diff --git a/renderdoc/driver/d3d11/d3d11_resources.h b/renderdoc/driver/d3d11/d3d11_resources.h index 01dd1c84d..94c494833 100644 --- a/renderdoc/driver/d3d11/d3d11_resources.h +++ b/renderdoc/driver/d3d11/d3d11_resources.h @@ -1089,7 +1089,10 @@ public: 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() @@ -1100,6 +1103,7 @@ public: } private: ShaderEntry(const ShaderEntry &e); + void TryReplaceOriginalByteCode(); ShaderEntry &operator =(const ShaderEntry &e); vector m_Bytecode; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp index 77d4005ee..83712c450 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp @@ -156,6 +156,14 @@ struct SIGNHeader // for OSG5 you should use SIGNElement7 }; +struct PRIVHeader +{ + uint32_t fourcc; // "ISGN", "OSGN, "OSG5", "PCSG" + uint32_t chunkLength; // length of this chunk + + void* data; +}; + struct SIGNElement { uint32_t nameOffset; // relative to the same offset base position as others in similar chunks - after FourCC and chunk length. @@ -192,6 +200,7 @@ static const uint32_t FOURCC_OSGN = MAKE_FOURCC('O', 'S', 'G', 'N'); static const uint32_t FOURCC_OSG5 = MAKE_FOURCC('O', 'S', 'G', '5'); static const uint32_t FOURCC_PCSG = MAKE_FOURCC('P', 'C', 'S', 'G'); static const uint32_t FOURCC_Aon9 = MAKE_FOURCC('A', 'o', 'n', '9'); +static const uint32_t FOURCC_PRIV = MAKE_FOURCC('P', 'R', 'I', 'V'); int TypeByteSize(VariableType t) { @@ -455,6 +464,75 @@ CBufferVariableType DXBCFile::ParseRDEFType(RDEFHeader *h, char *chunkContents, return ret; } +bool DXBCFile::CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength) +{ + FileHeader *header = (FileHeader *)ByteCode; + + char *data = (char *)ByteCode; // just for convenience + + if(header->fourcc != FOURCC_DXBC) + return false; + + if(header->fileLength != (uint32_t)ByteCodeLength) + return false; + + uint32_t *chunkOffsets = (uint32_t *)(header+1); // right after the header + + for (uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++) + { + uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]); + + if(*fourcc == FOURCC_SDBG) + { + return true; + } + else if(*fourcc == FOURCC_SPDB) + { + return true; + } + } + + return false; +} + +string DXBCFile::GetDebugBinaryPath(const void *ByteCode, size_t ByteCodeLength) +{ + string debugPath; + FileHeader *header = (FileHeader *)ByteCode; + + char *data = (char *)ByteCode; // just for convenience + + if(header->fourcc != FOURCC_DXBC) + return debugPath; + + if(header->fileLength != (uint32_t)ByteCodeLength) + return debugPath; + + uint32_t *chunkOffsets = (uint32_t *)(header+1); // right after the header + + static char* dbgData = nullptr; + for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++) + { + uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]); + dbgData = (char*)fourcc; + + if(*fourcc == FOURCC_PRIV) + { + PRIVHeader *privHeader = (PRIVHeader *)fourcc; + const char* pathData = (char*)&privHeader->data; + size_t pathLength = strlen(pathData); + + if(privHeader->chunkLength == (pathLength + 1)) + { + debugPath.append(pathData, pathData + pathLength); + return debugPath; + } + } + } + + return debugPath; +} + DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) { m_DebugInfo = NULL; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h index 14868e705..d027f045a 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.h @@ -372,6 +372,10 @@ class DXBCFile const ASMOperation &GetInstruction(size_t i) { return m_Instructions[i]; } size_t NumOperands(OpcodeType op); + + static bool CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength); + static string GetDebugBinaryPath(const void *ByteCode, size_t ByteCodeLength); + private: DXBCFile(const DXBCFile &o); DXBCFile &operator =(const DXBCFile &o);