diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 7b9a60ddc..9316bc26b 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -38,6 +38,8 @@ #include "data/hlsl/debugcbuffers.h" +static const char *LiveDriverDisassemblyTarget = "Live driver disassembly"; + extern "C" __declspec(dllexport) HRESULT __cdecl RENDERDOC_CreateWrappedDXGIFactory1(REFIID riid, void **ppFactory); extern "C" __declspec(dllexport) HRESULT @@ -383,6 +385,32 @@ vector D3D12Replay::GetDisassemblyTargets() // DXBC is always first ret.insert(ret.begin(), DXBCDisassemblyTarget); + if(!m_ISAChecked && m_TexRender.BlendPipe) + { + m_ISAChecked = true; + + UINT size = 0; + m_TexRender.BlendPipe->GetPrivateData(WKPDID_CommentStringW, &size, NULL); + + if(size > 0) + { + byte *isa = new byte[size + 1]; + m_TexRender.BlendPipe->GetPrivateData(WKPDID_CommentStringW, &size, isa); + + if(strstr((const char *)isa, "disassembly requires a participating driver") == NULL && + wcsstr((const wchar_t *)isa, L"disassembly requires a participating driver") == NULL) + { + m_ISAAvailable = + strstr((const char *)isa, "GetDisassembly(); + if(target == LiveDriverDisassemblyTarget) + { + if(pipeline == ResourceId()) + { + return "; No pipeline specified, live driver disassembly is not available\n" + "; Shader must be disassembled with a specific pipeline to get live driver assembly."; + } + + WrappedID3D12PipelineState *pipe = + m_pDevice->GetResourceManager()->GetLiveAs(pipeline); + + UINT size = 0; + pipe->GetPrivateData(WKPDID_CommentStringW, &size, NULL); + + if(size == 0) + return "; Unknown error fetching disassembly, empty string returned\n"; + + byte *data = new byte[size + 1]; + memset(data, 0, size); + pipe->GetPrivateData(WKPDID_CommentStringW, &size, data); + + byte *iter = data; + + // need to handle wide and ascii strings to some extent. We assume that it doesn't change from + // character to character, we just handle the initial being either one, then assume + // the xml within is all consistent. + if(!strncmp((char *)iter, "') + 1; + + if(*(char *)iter == '\n') + iter++; + } + else if(!wcsncmp((wchar_t *)iter, L"') + sizeof(wchar_t); + + if(*(wchar_t *)iter == L'\n') + iter += sizeof(wchar_t); + } + else + return "; Unknown error fetching disassembly, invalid string returned\n\n\n" + + std::string(data, data + size); + + std::string contents; + + // decode the tags + if(!strncmp((char *)iter, "stage) + { + case ShaderStage::Vertex: search = "stage=\"VS\""; break; + case ShaderStage::Hull: search = "stage=\"HS\""; break; + case ShaderStage::Domain: search = "stage=\"DS\""; break; + case ShaderStage::Geometry: search = "stage=\"GS\""; break; + case ShaderStage::Pixel: search = "stage=\"PS\""; break; + case ShaderStage::Compute: search = "stage=\"CS\""; break; + default: return "; Unknown shader stage in shader reflection\n"; + } + + size_t idx = contents.find(search); + + if(idx == std::string::npos) + return "; Couldn't find disassembly for given shader stage in returned string\n\n\n" + contents; + + idx += 11; // stage=".S"> + + if(strncmp(contents.c_str() + idx, "", 9)) + return "; Unknown error fetching disassembly, invalid string returned\n\n\n" + contents; + + idx += 9; // + + if(strncmp(contents.c_str() + idx, "", idx); + + if(end == std::string::npos) + return "; Unknown error fetching disassembly, invalid string returned\n\n\n" + contents; + + return contents.substr(idx, end - idx); + } + return StringFormat::Fmt("; Invalid disassembly target %s", target.c_str()); } diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 89222225f..6ff363533 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -388,6 +388,9 @@ private: std::vector m_Resources; std::map m_ResourceIdx; + bool m_ISAChecked = false; + bool m_ISAAvailable = false; + D3D12Pipe::State m_PipelineState; D3D11Pipe::State m_D3D11State; VKPipe::State m_VKState;