diff --git a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp index 27fa2f833..fbf09f6d6 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_disassemble.cpp @@ -463,212 +463,21 @@ void DXBCFile::MakeDisassemblyString() size_t d = 0; - vector > fileLines; - - if(m_DebugInfo) - { - vector fileNames; - - fileLines.resize(m_DebugInfo->Files.size()); - fileNames.resize(m_DebugInfo->Files.size()); - - for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) - fileNames[i] = m_DebugInfo->Files[i].first; - - // we essentially do a copy-paste out of m_DebugInfo->Files into fileLines, - // by doing a mini-preprocess to handle #line directives. This means that - // any lines that our source file declares to be in another filename via a #line - // get put in the right place for what the debug information hopefully matches. - // We also concatenate duplicate lines and display them all, to handle edge - // cases where #lines declare duplicates. - - for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) - { - vector srclines; - vector *dstFile = - &fileLines[i]; // start off writing to the corresponding output file. - - size_t dstLine = 0; - - split(m_DebugInfo->Files[i].second, srclines, '\n'); - srclines.push_back(""); - - // handle #line directives by inserting empty lines or erasing as necessary - - for(size_t srcLine = 0; srcLine < srclines.size(); srcLine++) - { - if(srclines[srcLine].empty()) - { - dstLine++; - continue; - } - - char *c = &srclines[srcLine][0]; - char *end = c + srclines[srcLine].size(); - - while(*c == '\t' || *c == ' ' || *c == '\r') - c++; - - if(c == end) - { - // blank line, just advance line counter - dstLine++; - continue; - } - - if(c + 5 > end || strncmp(c, "#line", 5)) - { - // resize up to account for the current line, if necessary - dstFile->resize(RDCMAX(dstLine + 1, dstFile->size())); - - // if non-empty, append this line (to allow multiple lines on the same line - // number to be concatenated) - if((*dstFile)[dstLine].empty()) - (*dstFile)[dstLine] = srclines[srcLine]; - else - (*dstFile)[dstLine] += "\n" + srclines[srcLine]; - - // advance line counter - dstLine++; - - continue; - } - - // we have a #line directive - c += 5; - - if(c >= end) - { - // invalid #line, just advance line counter - dstLine++; - continue; - } - - while(*c == '\t' || *c == ' ') - c++; - - if(c >= end) - { - // invalid #line, just advance line counter - dstLine++; - continue; - } - - // invalid #line, no line number. Skip/ignore and just advance line counter - if(*c < '0' || *c > '9') - { - dstLine++; - continue; - } - - size_t newLineNum = 0; - while(*c >= '0' && *c <= '9') - { - newLineNum *= 10; - newLineNum += int((*c) - '0'); - c++; - } - - // convert to 0-indexed line number - if(newLineNum > 0) - newLineNum--; - - while(*c == '\t' || *c == ' ') - c++; - - // no filename - if(*c == 0) - { - // set the next line number, and continue processing - dstLine = newLineNum; - continue; - } - else if(*c == '"') - { - c++; - - char *filename = c; - - // parse out filename - while(*c != '"' && *c != 0) - { - if(*c == '\\') - { - // skip escaped characters - c += 2; - } - else - { - c++; - } - } - - // parsed filename successfully - if(*c == '"') - { - *c = 0; - - // find the new destination file - bool found = false; - size_t dstFileIdx = 0; - - for(size_t f = 0; f < fileNames.size(); f++) - { - if(fileNames[f] == filename) - { - found = true; - dstFileIdx = f; - break; - } - } - - if(found) - { - dstFile = &fileLines[dstFileIdx]; - } - else - { - RDCWARN("Couldn't find filename '%s' in #line directive in debug info", filename); - - // make a dummy file to write into that won't be used. - fileNames.push_back(filename); - fileLines.push_back(vector()); - - dstFile = &fileLines.back(); - } - - // set the next line number, and continue processing - dstLine = newLineNum; - - continue; - } - else - { - // invalid #line, ignore - continue; - } - } - else - { - // invalid #line, ignore - continue; - } - } - } - - for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) - { - if(m_DebugInfo->Files[i].second.empty()) - { - merge(fileLines[i], m_DebugInfo->Files[i].second, '\n'); - } - } - } - LineColumnInfo prevLineInfo; size_t debugInst = 0; + std::vector> fileLines; + + // generate fileLines by splitting each file in the debug info + if(m_DebugInfo) + { + fileLines.resize(m_DebugInfo->Files.size()); + + for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) + split(m_DebugInfo->Files[i].second, fileLines[i], '\n'); + } + for(size_t i = 0; i < m_Instructions.size(); i++) { for(; d < m_Declarations.size(); d++) @@ -3209,4 +3018,4 @@ char *SystemValueToString(SVSemantic name) return ""; } -}; // namespace DXBC +}; // namespace DXBC \ No newline at end of file diff --git a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp index 2da21d76e..5b1702b70 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_inspect.cpp @@ -1069,6 +1069,205 @@ DXBCFile::DXBCFile(const void *ByteCode, size_t ByteCodeLength) else if(*fourcc == FOURCC_SPDB) { m_DebugInfo = new SPDBChunk(fourcc); + // we do a mini-preprocess of the files from the debug info to handle #line directives. + // This means that any lines that our source file declares to be in another filename via a #line + // get put in the right place for what the debug information hopefully matches. + // We also concatenate duplicate lines and display them all, to handle edge cases where #lines + // declare duplicates. + + if(m_DebugInfo) + { + std::vector> fileLines; + + std::vector fileNames; + + fileLines.resize(m_DebugInfo->Files.size()); + fileNames.resize(m_DebugInfo->Files.size()); + + for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) + fileNames[i] = m_DebugInfo->Files[i].first; + + for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) + { + std::vector srclines; + std::vector *dstFile = + &fileLines[i]; // start off writing to the corresponding output file. + + size_t dstLine = 0; + + split(m_DebugInfo->Files[i].second, srclines, '\n'); + srclines.push_back(""); + + // handle #line directives by inserting empty lines or erasing as necessary + + for(size_t srcLine = 0; srcLine < srclines.size(); srcLine++) + { + if(srclines[srcLine].empty()) + { + dstLine++; + continue; + } + + char *c = &srclines[srcLine][0]; + char *end = c + srclines[srcLine].size(); + + while(*c == '\t' || *c == ' ' || *c == '\r') + c++; + + if(c == end) + { + // blank line, just advance line counter + dstLine++; + continue; + } + + if(c + 5 > end || strncmp(c, "#line", 5)) + { + // resize up to account for the current line, if necessary + dstFile->resize(RDCMAX(dstLine + 1, dstFile->size())); + + // if non-empty, append this line (to allow multiple lines on the same line + // number to be concatenated). To avoid screwing up line numbers we have to append with a + // comment and not a newline. + if((*dstFile)[dstLine].empty()) + (*dstFile)[dstLine] = srclines[srcLine]; + else + (*dstFile)[dstLine] += " /* multiple #lines overlapping */ " + srclines[srcLine]; + + // advance line counter + dstLine++; + + continue; + } + + // we have a #line directive + c += 5; + + if(c >= end) + { + // invalid #line, just advance line counter + dstLine++; + continue; + } + + while(*c == '\t' || *c == ' ') + c++; + + if(c >= end) + { + // invalid #line, just advance line counter + dstLine++; + continue; + } + + // invalid #line, no line number. Skip/ignore and just advance line counter + if(*c < '0' || *c > '9') + { + dstLine++; + continue; + } + + size_t newLineNum = 0; + while(*c >= '0' && *c <= '9') + { + newLineNum *= 10; + newLineNum += int((*c) - '0'); + c++; + } + + // convert to 0-indexed line number + if(newLineNum > 0) + newLineNum--; + + while(*c == '\t' || *c == ' ') + c++; + + // no filename + if(*c == 0) + { + // set the next line number, and continue processing + dstLine = newLineNum; + continue; + } + else if(*c == '"') + { + c++; + + char *filename = c; + + // parse out filename + while(*c != '"' && *c != 0) + { + if(*c == '\\') + { + // skip escaped characters + c += 2; + } + else + { + c++; + } + } + + // parsed filename successfully + if(*c == '"') + { + *c = 0; + + // find the new destination file + bool found = false; + size_t dstFileIdx = 0; + + for(size_t f = 0; f < fileNames.size(); f++) + { + if(fileNames[f] == filename) + { + found = true; + dstFileIdx = f; + break; + } + } + + if(found) + { + dstFile = &fileLines[dstFileIdx]; + } + else + { + RDCWARN("Couldn't find filename '%s' in #line directive in debug info", filename); + + // make a dummy file to write into that won't be used. + fileNames.push_back(filename); + fileLines.push_back(vector()); + + dstFile = &fileLines.back(); + } + + // set the next line number, and continue processing + dstLine = newLineNum; + + continue; + } + else + { + // invalid #line, ignore + continue; + } + } + else + { + // invalid #line, ignore + continue; + } + } + } + + for(size_t i = 0; i < m_DebugInfo->Files.size(); i++) + { + if(m_DebugInfo->Files[i].second.empty()) + { + merge(fileLines[i], m_DebugInfo->Files[i].second, '\n'); + } } } }