From d1ec8ad622412b136fa05b02455f1fe4b0809f8e Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 16 Feb 2026 15:45:13 +0000 Subject: [PATCH] Store and lookup shader data for aftermath dumps --- renderdoc/driver/d3d12/d3d12_device_wrap.cpp | 7 ++ renderdoc/driver/d3d12/d3d12_device_wrap2.cpp | 4 ++ renderdoc/driver/ihv/nv/nv_aftermath.cpp | 69 +++++++++++++++---- renderdoc/driver/ihv/nv/nv_aftermath.h | 1 + .../vulkan/wrappers/vk_shader_funcs.cpp | 5 ++ 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index e2976af85..4e6e9c49e 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -27,6 +27,7 @@ #include "driver/dxgi/dxgi_common.h" #include "driver/ihv/amd/official/DXExt/AmdExtD3D.h" #include "driver/ihv/amd/official/DXExt/AmdExtD3DCommandListMarkerApi.h" +#include "driver/ihv/nv/nv_aftermath.h" #include "d3d12_command_list.h" #include "d3d12_command_queue.h" #include "d3d12_replay.h" @@ -596,6 +597,9 @@ bool WrappedID3D12Device::Serialise_CreateGraphicsPipelineState( WrappedID3D12Shader::AddShader(InlineShaderIDs[i], *shaders[i], this); entry->AddRef(); + NVAftermath_Shader(ShaderEncoding::DXBC, shaders[i]->pShaderBytecode, + shaders[i]->BytecodeLength); + shaders[i]->pShaderBytecode = entry; if(m_GlobalEXTUAV != ~0U) @@ -894,6 +898,9 @@ bool WrappedID3D12Device::Serialise_CreateComputePipelineState( WrappedID3D12Shader::AddShader(InlineShaderID, wrapped->compute->CS, this); entry->AddRef(); + NVAftermath_Shader(ShaderEncoding::DXBC, wrapped->compute->CS.pShaderBytecode, + wrapped->compute->CS.BytecodeLength); + if(m_GlobalEXTUAV != ~0U) entry->SetShaderExtSlot(m_GlobalEXTUAV, m_GlobalEXTUAVSpace); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp index 7f6379cc7..4ae1b2e66 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp @@ -25,6 +25,7 @@ #include "d3d12_device.h" #include "core/settings.h" #include "driver/dxgi/dxgi_common.h" +#include "driver/ihv/nv/nv_aftermath.h" #include "d3d12_resources.h" RDOC_EXTERN_CONFIG(bool, Replay_Debug_SingleThreadedCompilation); @@ -164,6 +165,9 @@ bool WrappedID3D12Device::Serialise_CreatePipelineState(SerialiserType &ser, WrappedID3D12Shader::AddShader(InlineShaderIDs[i], *shaders[i], this); entry->AddRef(); + NVAftermath_Shader(ShaderEncoding::DXBC, shaders[i]->pShaderBytecode, + shaders[i]->BytecodeLength); + shaders[i]->pShaderBytecode = entry; if(m_GlobalEXTUAV != ~0U) diff --git a/renderdoc/driver/ihv/nv/nv_aftermath.cpp b/renderdoc/driver/ihv/nv/nv_aftermath.cpp index 58776d21b..7e05dacb1 100644 --- a/renderdoc/driver/ihv/nv/nv_aftermath.cpp +++ b/renderdoc/driver/ihv/nv/nv_aftermath.cpp @@ -24,6 +24,7 @@ #include "nv_aftermath.h" +#include #include #include "common/formatting.h" #include "common/threading.h" @@ -46,6 +47,8 @@ RDOC_CONFIG(bool, Replay_Debug_EnableNVRTValidation, false, #endif +#include "driver/vulkan/official/vulkan.h" + #include "driver/ihv/nv/official/aftermath/GFSDK_Aftermath.h" #include "driver/ihv/nv/official/aftermath/GFSDK_Aftermath_GpuCrashDump.h" #include "driver/ihv/nv/official/aftermath/GFSDK_Aftermath_GpuCrashDumpDecoding.h" @@ -55,8 +58,6 @@ RDOC_CONFIG(bool, Replay_Debug_EnableNVRTValidation, false, #include "official/nvapi/nvapi.h" -#include "driver/vulkan/official/vulkan_core.h" - namespace { #include "official/nvapi/nvapi_interface.h" @@ -78,12 +79,14 @@ typedef void *(*PFN_nvapi_QueryInterface)(NvU32 id); namespace { -#define AFTERMATH_FUNCS(x) \ - x(DX12_Initialize); \ - x(DisableGpuCrashDumps); \ - x(EnableGpuCrashDumps); \ - x(GetCrashDumpStatus); \ - x(GetShaderDebugInfoIdentifier); +#define AFTERMATH_FUNCS(x) \ + x(DX12_Initialize); \ + x(DisableGpuCrashDumps); \ + x(EnableGpuCrashDumps); \ + x(GetCrashDumpStatus); \ + x(GetShaderDebugInfoIdentifier); \ + x(GetShaderHashSpirv); \ + x(GetShaderHash); struct aftermath_table { @@ -105,24 +108,39 @@ struct aftermath_table aftermath_table table = {}; uint32_t dumpNumber = 0; +std::unordered_map spvShaders; +std::unordered_map dxShaders; + void GpuCrashDumpCallback(const void *pGpuCrashDump, const uint32_t gpuCrashDumpSize, void *) { - FileIO::WriteAll(StringFormat::sntimef(Timing::GetUTCTime(), "aftermath_dump-%y%m%d%H%M%S-") + - StringFormat::Fmt("%u-%u.nv-gpudmp", Process::GetCurrentPID(), dumpNumber++), - pGpuCrashDump, gpuCrashDumpSize); + rdcstr outName = StringFormat::sntimef(Timing::GetUTCTime(), "aftermath_dump-%y%m%d%H%M%S-") + + StringFormat::Fmt("%u-%u", Process::GetCurrentPID(), dumpNumber++); + FileIO::WriteAll(outName + ".nv-gpudmp", pGpuCrashDump, gpuCrashDumpSize); } void GpuShaderDebugInfoCallback(const void *pShaderDebugInfo, const uint32_t shaderDebugInfoSize, void *) { - RDCLOG("shader info %p %zu", pShaderDebugInfo, shaderDebugInfoSize); - GFSDK_Aftermath_ShaderDebugInfoIdentifier ident; table.GetShaderDebugInfoIdentifier(GFSDK_Aftermath_Version_API, pShaderDebugInfo, shaderDebugInfoSize, &ident); - FileIO::WriteAll(StringFormat::Fmt("shader-%08x-%08x.nvdbg", ident.id[0], ident.id[1]), + FileIO::WriteAll(StringFormat::Fmt("shader-%016llx-%016llx.nvdbg", ident.id[0], ident.id[1]), pShaderDebugInfo, shaderDebugInfoSize); + + { + auto it = spvShaders.find(ident.id[0]); + if(it != spvShaders.end()) + FileIO::WriteAll(StringFormat::Fmt("shader-%016llx.spv", ident.id[0]), it->second.data(), + it->second.size()); + } + + { + auto it = dxShaders.find(ident.id[0]); + if(it != dxShaders.end()) + FileIO::WriteAll(StringFormat::Fmt("shader-%016llx.cso", ident.id[0]), it->second.data(), + it->second.size()); + } } void DescriptionCB(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, void *pUserData) @@ -187,6 +205,25 @@ void NVAftermath_Init() } // on shutdown we could call GFSDK_Aftermath_DisableGpuCrashDumps +void NVAftermath_Shader(ShaderEncoding encoding, const void *shader, size_t len) +{ + GFSDK_Aftermath_ShaderBinaryHash shaderHash; + + if(encoding == ShaderEncoding::SPIRV && table.GetShaderHashSpirv) + { + GFSDK_Aftermath_SpirvCode spv_data = {shader, (uint32_t)len}; + table.GetShaderHashSpirv(GFSDK_Aftermath_Version_API, &spv_data, &shaderHash); + + spvShaders[shaderHash.hash] = bytebuf((const byte *)shader, len); + } + else if(table.GetShaderHash) + { + D3D12_SHADER_BYTECODE shad_data = {shader, (uint32_t)len}; + table.GetShaderHash(GFSDK_Aftermath_Version_API, &shad_data, &shaderHash); + + dxShaders[shaderHash.hash] = bytebuf((const byte *)shader, len); + } +} void NVAftermath_EnableVK(const std::set &supportedExtensions, rdcarray &Extensions, const void **deviceCreateNext) @@ -463,6 +500,10 @@ void NVAftermath_Init() } } +void NVAftermath_Shader(ShaderEncoding encoding, const void *shader, size_t len) +{ +} + void NVAftermath_EnableVK(const std::set &supportedExtensions, rdcarray &Extensions, const void **deviceCreateNext) { diff --git a/renderdoc/driver/ihv/nv/nv_aftermath.h b/renderdoc/driver/ihv/nv/nv_aftermath.h index f5903fd0f..b2e272fef 100644 --- a/renderdoc/driver/ihv/nv/nv_aftermath.h +++ b/renderdoc/driver/ihv/nv/nv_aftermath.h @@ -34,5 +34,6 @@ void NVAftermath_Init(); void NVAftermath_EnableVK(const std::set &supportedExtensions, rdcarray &Extensions, const void **deviceCreateNext); void NVAftermath_EnableD3D12(ID3D12Device *dev); +void NVAftermath_Shader(ShaderEncoding encoding, const void *shader, size_t len); void NVAftermath_DumpCrash(); void NVAftermath_DumpRTValidation(ID3D12Device5 *dev5); diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index 3517a6233..abf4b03cd 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -25,6 +25,7 @@ #include "../vk_core.h" #include "../vk_replay.h" #include "core/settings.h" +#include "driver/ihv/nv/nv_aftermath.h" #include "driver/shaders/spirv/spirv_reflect.h" RDOC_EXTERN_CONFIG(bool, Replay_Debug_SingleThreadedCompilation); @@ -401,6 +402,8 @@ bool WrappedVulkan::Serialise_vkCreateShaderModule(SerialiserType &ser, VkDevice VkShaderModuleCreateInfo patched = CreateInfo; + NVAftermath_Shader(ShaderEncoding::SPIRV, CreateInfo.pCode, CreateInfo.codeSize); + byte *tempMem = GetTempMemory(GetNextPatchSize(patched.pNext)); UnwrapNextChain(m_State, "VkShaderModuleCreateInfo", tempMem, (VkBaseInStructure *)&patched); @@ -698,6 +701,8 @@ VkShaderModule WrappedVulkan::CreateFakeInlineShaderModule(ResourceId id, VkDevi { RDCASSERT(IsLoading(m_State)); + NVAftermath_Shader(ShaderEncoding::SPIRV, pCreateInfo->pCode, pCreateInfo->codeSize); + VkShaderModule module = VK_NULL_HANDLE; VkResult ret = ObjDisp(device)->CreateShaderModule(Unwrap(device), pCreateInfo, NULL, &module);