mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-13 17:25:54 +00:00
Implemented support for separate unstripped shader debug info
It works this way: The GameEngine stored the original shader blob on disk. Than we add the path to that file to the D3D_BLOB_PRIVATE_DATA section of the shader blob. After that we can strip the Debug information with D3DCOMPILER_STRIP_DEBUG_INFO. Renderdoc will first check if the shader already has debug information. If it cannot find the PDB in the shader blob it will try to look for a PrivateDataSection. If there is a valid file path in the PrivateDataSection it will search for debug information in there. If it finds valid debug information it will replace the entire shader blob with the one loaded from disk.
This commit is contained in:
@@ -62,6 +62,39 @@ map<ResourceId,WrappedID3D11Buffer::BufferEntry> WrappedID3D11Buffer::m_BufferLi
|
||||
map<ResourceId,WrappedShader::ShaderEntry*> 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<byte> 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;
|
||||
|
||||
@@ -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<byte> m_Bytecode;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user