From 8ed9670601698ecc9c7813ab92bdd0a188b05969 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 26 Nov 2018 13:06:31 +0000 Subject: [PATCH] Add way to query for driver version info without replaying. * This lets us print what driver is available without opening a capture, useful for autotest logging. * We also print the driver version & vendor on capture as well as replay for all APIs. Previously we were only printing this reliably on replay for GL/Vulkan but it's useful everywhere for post-mortem debugging. --- renderdoc/api/replay/data_types.h | 12 +++ renderdoc/api/replay/renderdoc_replay.h | 7 ++ renderdoc/core/core.cpp | 35 ++++++++ renderdoc/core/core.h | 2 + renderdoc/core/image_viewer.cpp | 1 + renderdoc/core/replay_proxy.cpp | 32 +++++++ renderdoc/core/replay_proxy.h | 3 + renderdoc/driver/d3d11/d3d11_device.cpp | 30 +++++++ renderdoc/driver/d3d11/d3d11_replay.cpp | 36 +++++--- renderdoc/driver/d3d11/d3d11_replay.h | 5 +- renderdoc/driver/d3d12/d3d12_device.cpp | 43 +++++++++ renderdoc/driver/d3d12/d3d12_replay.cpp | 89 ++++++++++-------- renderdoc/driver/d3d12/d3d12_replay.h | 6 +- renderdoc/driver/dxgi/dxgi_common.cpp | 90 +++++++++++++++++++ renderdoc/driver/dxgi/dxgi_common.h | 2 + renderdoc/driver/gl/gl_debug.cpp | 23 +++-- renderdoc/driver/gl/gl_driver.cpp | 4 + renderdoc/driver/gl/gl_replay.cpp | 7 +- renderdoc/driver/gl/gl_replay.h | 5 +- renderdoc/driver/vulkan/vk_replay.cpp | 52 +++++++++++ renderdoc/driver/vulkan/vk_replay.h | 5 ++ .../vulkan/wrappers/vk_device_funcs.cpp | 19 +++- renderdoc/replay/entry_points.cpp | 5 ++ renderdoc/replay/renderdoc_serialise.inl | 10 +++ renderdoc/replay/replay_driver.h | 2 + 25 files changed, 459 insertions(+), 66 deletions(-) diff --git a/renderdoc/api/replay/data_types.h b/renderdoc/api/replay/data_types.h index 69bb10a31..5384dcb1d 100644 --- a/renderdoc/api/replay/data_types.h +++ b/renderdoc/api/replay/data_types.h @@ -1203,6 +1203,18 @@ worked around by re-sorting bindings. DECLARE_REFLECTION_STRUCT(APIProperties); +DOCUMENT("Gives information about the driver for this API."); +struct DriverInformation +{ + DOCUMENT("The :class:`GPUVendor` that provides this driver"); + GPUVendor vendor; + + DOCUMENT("The version string for the driver"); + char version[128]; +}; + +DECLARE_REFLECTION_STRUCT(DriverInformation); + DOCUMENT("A 128-bit Uuid."); struct Uuid { diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 1561ddcec..661f97558 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -2214,6 +2214,13 @@ This will be in the form "0123456789abcdef0123456789abcdef01234567" )"); extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetCommitHash(); +DOCUMENT(R"(Retrieves the driver information (if available) for a given graphics API. + +:return: The driver information. +:rtype: ``DriverInformation`` +)"); +extern "C" RENDERDOC_API DriverInformation RENDERDOC_CC RENDERDOC_GetDriverInformation(GraphicsAPI api); + DOCUMENT("Internal function for retrieving a config setting."); extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetConfigSetting(const char *name); diff --git a/renderdoc/core/core.cpp b/renderdoc/core/core.cpp index 2743c5ef3..baa22f5b4 100644 --- a/renderdoc/core/core.cpp +++ b/renderdoc/core/core.cpp @@ -1059,6 +1059,41 @@ map RenderDoc::GetRemoteDrivers() return ret; } +DriverInformation RenderDoc::GetDriverInformation(GraphicsAPI api) +{ + DriverInformation ret = {GPUVendor::Unknown, ""}; + + RDCDriver driverType = RDCDriver::Unknown; + switch(api) + { + case GraphicsAPI::D3D11: driverType = RDCDriver::D3D11; break; + case GraphicsAPI::D3D12: driverType = RDCDriver::D3D12; break; + case GraphicsAPI::OpenGL: driverType = RDCDriver::OpenGL; break; + case GraphicsAPI::Vulkan: driverType = RDCDriver::Vulkan; break; + } + + if(driverType == RDCDriver::Unknown || !HasReplayDriver(driverType)) + return ret; + + IReplayDriver *driver = NULL; + ReplayStatus status = CreateProxyReplayDriver(driverType, &driver); + + if(status == ReplayStatus::Succeeded) + { + ret = driver->GetDriverInfo(); + } + else + { + RDCERR("Couldn't create proxy replay driver for %s: %s", ToStr(driverType).c_str(), + ToStr(status).c_str()); + } + + if(driver) + driver->Shutdown(); + + return ret; +} + void RenderDoc::EnableVendorExtensions(VendorExtensions ext) { m_VendorExts[(int)ext] = true; diff --git a/renderdoc/core/core.h b/renderdoc/core/core.h index 9096a015b..3b4e9ebf2 100644 --- a/renderdoc/core/core.h +++ b/renderdoc/core/core.h @@ -398,6 +398,8 @@ public: void BecomeRemoteServer(const char *listenhost, uint16_t port, RENDERDOC_KillCallback killReplay, RENDERDOC_PreviewWindowCallback previewWindow); + DriverInformation GetDriverInformation(GraphicsAPI api); + // can't be disabled, only enabled then latched bool IsVendorExtensionEnabled(VendorExtensions ext) { return m_VendorExts[(int)ext]; } diff --git a/renderdoc/core/image_viewer.cpp b/renderdoc/core/image_viewer.cpp index 3f2bf15cb..81b89b680 100644 --- a/renderdoc/core/image_viewer.cpp +++ b/renderdoc/core/image_viewer.cpp @@ -170,6 +170,7 @@ public: return ret; } void SavePipelineState() {} + DriverInformation GetDriverInfo() { return {GPUVendor::Unknown, ""}; } const D3D12Pipe::State *GetD3D12PipelineState() { return NULL; } const GLPipe::State *GetGLPipelineState() { return NULL; } const VKPipe::State *GetVulkanPipelineState() { return NULL; } diff --git a/renderdoc/core/replay_proxy.cpp b/renderdoc/core/replay_proxy.cpp index 1ef64efee..80dd9ccbf 100644 --- a/renderdoc/core/replay_proxy.cpp +++ b/renderdoc/core/replay_proxy.cpp @@ -90,6 +90,8 @@ std::string DoStringise(const ReplayProxyPacket &el) STRINGISE_ENUM_NAMED(eReplayProxy_DisassembleShader, "DisassembleShader"); STRINGISE_ENUM_NAMED(eReplayProxy_GetDisassemblyTargets, "GetDisassemblyTargets"); STRINGISE_ENUM_NAMED(eReplayProxy_GetTargetShaderEncodings, "GetTargetShaderEncodings"); + + STRINGISE_ENUM_NAMED(eReplayProxy_GetDriverInfo, "GetDriverInfo"); } END_ENUM_STRINGISE(); } @@ -293,6 +295,35 @@ APIProperties ReplayProxy::GetAPIProperties() PROXY_FUNCTION(GetAPIProperties); } +template +DriverInformation ReplayProxy::Proxied_GetDriverInfo(ParamSerialiser ¶mser, + ReturnSerialiser &retser) +{ + const ReplayProxyPacket expectedPacket = eReplayProxy_GetDriverInfo; + ReplayProxyPacket packet = eReplayProxy_GetDriverInfo; + DriverInformation ret = {}; + + { + BEGIN_PARAMS(); + END_PARAMS(); + } + + { + REMOTE_EXECUTION(); + if(paramser.IsReading() && !paramser.IsErrored() && !m_IsErrored) + ret = m_Remote->GetDriverInfo(); + } + + SERIALISE_RETURN(ret); + + return ret; +} + +DriverInformation ReplayProxy::GetDriverInfo() +{ + PROXY_FUNCTION(GetDriverInfo); +} + template std::vector ReplayProxy::Proxied_GetDebugMessages(ParamSerialiser ¶mser, ReturnSerialiser &retser) @@ -2598,6 +2629,7 @@ bool ReplayProxy::Tick(int type) case eReplayProxy_DisassembleShader: DisassembleShader(ResourceId(), NULL, ""); break; case eReplayProxy_GetDisassemblyTargets: GetDisassemblyTargets(); break; case eReplayProxy_GetTargetShaderEncodings: GetTargetShaderEncodings(); break; + case eReplayProxy_GetDriverInfo: GetDriverInfo(); break; default: RDCERR("Unexpected command %u", type); return false; } diff --git a/renderdoc/core/replay_proxy.h b/renderdoc/core/replay_proxy.h index 2d2d771b9..24610fb7f 100644 --- a/renderdoc/core/replay_proxy.h +++ b/renderdoc/core/replay_proxy.h @@ -97,6 +97,8 @@ enum ReplayProxyPacket eReplayProxy_DisassembleShader, eReplayProxy_GetDisassemblyTargets, eReplayProxy_GetTargetShaderEncodings, + + eReplayProxy_GetDriverInfo, }; DECLARE_REFLECTION_ENUM(ReplayProxyPacket); @@ -447,6 +449,7 @@ public: IMPLEMENT_FUNCTION_PROXIED(TextureDescription, GetTexture, ResourceId id); IMPLEMENT_FUNCTION_PROXIED(APIProperties, GetAPIProperties); + IMPLEMENT_FUNCTION_PROXIED(DriverInformation, GetDriverInfo); IMPLEMENT_FUNCTION_PROXIED(std::vector, GetDebugMessages); diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index aa0ab7d95..b33d1a7bb 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -146,6 +146,36 @@ WrappedID3D11Device::WrappedID3D11Device(ID3D11Device *realDevice, D3D11InitPara m_DeviceRecord->SubResources = NULL; RenderDoc::Inst().AddDeviceFrameCapturer((ID3D11Device *)this, this); + + { + IDXGIDevice *pDXGIDevice = NULL; + HRESULT hr = m_pDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice); + + if(FAILED(hr)) + { + RDCERR("Couldn't get DXGI device from D3D device"); + } + else + { + IDXGIAdapter *pDXGIAdapter = NULL; + hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter); + + if(SUCCEEDED(hr)) + { + DXGI_ADAPTER_DESC desc = {}; + pDXGIAdapter->GetDesc(&desc); + + GPUVendor vendor = GPUVendorFromPCIVendor(desc.VendorId); + std::string descString = GetDriverVersion(desc); + + RDCLOG("New D3D11 device created: %s / %s", ToStr(vendor).c_str(), descString.c_str()); + + SAFE_RELEASE(pDXGIAdapter); + } + } + + SAFE_RELEASE(pDXGIDevice); + } } ID3D11DeviceContext *context = NULL; diff --git a/renderdoc/driver/d3d11/d3d11_replay.cpp b/renderdoc/driver/d3d11/d3d11_replay.cpp index 9b8896e2d..da8313ac9 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.cpp +++ b/renderdoc/driver/d3d11/d3d11_replay.cpp @@ -54,6 +54,8 @@ D3D11Replay::D3D11Replay() m_WARP = false; m_HighlightCache.driver = this; + + RDCEraseEl(m_DriverInfo); } D3D11Replay::~D3D11Replay() @@ -95,14 +97,6 @@ void D3D11Replay::CreateResources() IDXGIAdapter *pDXGIAdapter; hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter); - DXGI_ADAPTER_DESC desc = {}; - pDXGIAdapter->GetDesc(&desc); - - m_Vendor = GPUVendorFromPCIVendor(desc.VendorId); - - if(m_WARP) - m_Vendor = GPUVendor::Software; - if(FAILED(hr)) { RDCERR("Couldn't get DXGI adapter from DXGI device"); @@ -110,6 +104,22 @@ void D3D11Replay::CreateResources() } else { + DXGI_ADAPTER_DESC desc = {}; + pDXGIAdapter->GetDesc(&desc); + + RDCEraseEl(m_DriverInfo); + + m_DriverInfo.vendor = GPUVendorFromPCIVendor(desc.VendorId); + + std::string descString = GetDriverVersion(desc); + descString.resize(RDCMIN(descString.size(), ARRAY_COUNT(m_DriverInfo.version) - 1)); + memcpy(m_DriverInfo.version, descString.c_str(), descString.size()); + + RDCLOG("Running replay on %s / %s", ToStr(m_DriverInfo.vendor).c_str(), m_DriverInfo.version); + + if(m_WARP) + m_DriverInfo.vendor = GPUVendor::Software; + hr = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&m_pFactory); SAFE_RELEASE(pDXGIDevice); @@ -162,24 +172,24 @@ void D3D11Replay::CreateResources() NVCounters *countersNV = NULL; IntelCounters *countersIntel = NULL; - if(m_Vendor == GPUVendor::AMD) + if(m_DriverInfo.vendor == GPUVendor::AMD) { RDCLOG("AMD GPU detected - trying to initialise AMD counters"); countersAMD = new AMDCounters(); } - else if(m_Vendor == GPUVendor::nVidia) + else if(m_DriverInfo.vendor == GPUVendor::nVidia) { RDCLOG("nVidia GPU detected - trying to initialise nVidia counters"); countersNV = new NVCounters(); } - else if(m_Vendor == GPUVendor::Intel) + else if(m_DriverInfo.vendor == GPUVendor::Intel) { RDCLOG("Intel GPU detected - trying to initialize Intel counters"); countersIntel = new IntelCounters(); } else { - RDCLOG("%s GPU detected - no counters available", ToStr(m_Vendor).c_str()); + RDCLOG("%s GPU detected - no counters available", ToStr(m_DriverInfo.vendor).c_str()); } ID3D11Device *d3dDevice = m_pDevice->GetReal(); @@ -507,7 +517,7 @@ APIProperties D3D11Replay::GetAPIProperties() ret.pipelineType = GraphicsAPI::D3D11; ret.localRenderer = GraphicsAPI::D3D11; - ret.vendor = m_Vendor; + ret.vendor = m_DriverInfo.vendor; ret.degraded = m_WARP; ret.shadersMutable = false; diff --git a/renderdoc/driver/d3d11/d3d11_replay.h b/renderdoc/driver/d3d11/d3d11_replay.h index fa183f2c5..3c27edef5 100644 --- a/renderdoc/driver/d3d11/d3d11_replay.h +++ b/renderdoc/driver/d3d11/d3d11_replay.h @@ -104,6 +104,7 @@ public: void CreateResources(); void DestroyResources(); + DriverInformation GetDriverInfo() { return m_DriverInfo; } APIProperties GetAPIProperties(); ResourceDescription &GetResourceDesc(ResourceId id); @@ -240,8 +241,6 @@ private: bool m_WARP; bool m_Proxy; - GPUVendor m_Vendor = GPUVendor::Unknown; - D3D11DebugManager *GetDebugManager(); // shared by BuildCustomShader and BuildTargetShader void BuildShader(ShaderEncoding sourceEncoding, bytebuf source, std::string entry, @@ -303,6 +302,8 @@ private: IDXGIFactory *m_pFactory = NULL; + DriverInformation m_DriverInfo; + AMDCounters *m_pAMDCounters = NULL; NVCounters *m_pNVCounters = NULL; IntelCounters *m_pIntelCounters = NULL; diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 7345162c0..0c2d67c0e 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -221,6 +221,49 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara m_FrameCaptureRecord = NULL; ResourceIDGen::SetReplayResourceIDs(); + + // create temporary factory to print the driver version info + if(m_pDevice) + { + typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID, void **); + + PFN_CREATE_DXGI_FACTORY createFunc = (PFN_CREATE_DXGI_FACTORY)GetProcAddress( + GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1"); + + IDXGIFactory4 *tmpFactory = NULL; + HRESULT hr = createFunc(__uuidof(IDXGIFactory4), (void **)&tmpFactory); + + if(FAILED(hr)) + { + RDCERR("Couldn't create DXGI factory! HRESULT: %s", ToStr(hr).c_str()); + } + + if(tmpFactory) + { + IDXGIAdapter *pDXGIAdapter = NULL; + hr = tmpFactory->EnumAdapterByLuid(m_pDevice->GetAdapterLuid(), __uuidof(IDXGIAdapter), + (void **)&pDXGIAdapter); + + if(FAILED(hr)) + { + RDCERR("Couldn't get DXGI adapter by LUID from D3D12 device"); + } + else + { + DXGI_ADAPTER_DESC desc = {}; + pDXGIAdapter->GetDesc(&desc); + + GPUVendor vendor = GPUVendorFromPCIVendor(desc.VendorId); + std::string descString = GetDriverVersion(desc); + + RDCLOG("New D3D12 device created: %s / %s", ToStr(vendor).c_str(), descString.c_str()); + + SAFE_RELEASE(pDXGIAdapter); + } + } + + SAFE_RELEASE(tmpFactory); + } } else { diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 5377661da..9e8e4e290 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -85,6 +85,8 @@ D3D12Replay::D3D12Replay() m_Proxy = false; m_HighlightCache.driver = this; + + RDCEraseEl(m_DriverInfo); } void D3D12Replay::Shutdown() @@ -98,46 +100,57 @@ void D3D12Replay::Shutdown() m_pDevice->Release(); } +void D3D12Replay::Initialise() +{ + typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID, void **); + + PFN_CREATE_DXGI_FACTORY createFunc = + (PFN_CREATE_DXGI_FACTORY)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1"); + + HRESULT hr = createFunc(__uuidof(IDXGIFactory4), (void **)&m_pFactory); + + if(FAILED(hr)) + { + RDCERR("Couldn't create DXGI factory! HRESULT: %s", ToStr(hr).c_str()); + } + + RDCEraseEl(m_DriverInfo); + + if(m_pFactory) + { + RefCountDXGIObject::HandleWrap(__uuidof(IDXGIFactory4), (void **)&m_pFactory); + + LUID luid = m_pDevice->GetAdapterLuid(); + + IDXGIAdapter *pDXGIAdapter; + hr = m_pFactory->EnumAdapterByLuid(luid, __uuidof(IDXGIAdapter), (void **)&pDXGIAdapter); + + if(FAILED(hr)) + { + RDCERR("Couldn't get DXGI adapter by LUID from D3D device"); + } + else + { + DXGI_ADAPTER_DESC desc = {}; + pDXGIAdapter->GetDesc(&desc); + + m_DriverInfo.vendor = GPUVendorFromPCIVendor(desc.VendorId); + + std::string descString = GetDriverVersion(desc); + descString.resize(RDCMIN(descString.size(), ARRAY_COUNT(m_DriverInfo.version) - 1)); + memcpy(m_DriverInfo.version, descString.c_str(), descString.size()); + + RDCLOG("Running replay on %s / %s", ToStr(m_DriverInfo.vendor).c_str(), m_DriverInfo.version); + } + } +} + void D3D12Replay::CreateResources() { m_DebugManager = new D3D12DebugManager(m_pDevice); if(RenderDoc::Inst().IsReplayApp()) { - typedef HRESULT(WINAPI * PFN_CREATE_DXGI_FACTORY)(REFIID, void **); - - PFN_CREATE_DXGI_FACTORY createFunc = - (PFN_CREATE_DXGI_FACTORY)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1"); - - HRESULT hr = createFunc(__uuidof(IDXGIFactory4), (void **)&m_pFactory); - - if(FAILED(hr)) - { - RDCERR("Couldn't create DXGI factory! HRESULT: %s", ToStr(hr).c_str()); - } - - if(m_pFactory) - { - RefCountDXGIObject::HandleWrap(__uuidof(IDXGIFactory4), (void **)&m_pFactory); - - LUID luid = m_pDevice->GetAdapterLuid(); - - IDXGIAdapter *pDXGIAdapter; - hr = m_pFactory->EnumAdapterByLuid(luid, __uuidof(IDXGIAdapter), (void **)&pDXGIAdapter); - - if(FAILED(hr)) - { - RDCERR("Couldn't get DXGI adapter by LUID from D3D device"); - } - else - { - DXGI_ADAPTER_DESC desc = {}; - pDXGIAdapter->GetDesc(&desc); - - m_Vendor = GPUVendorFromPCIVendor(desc.VendorId); - } - } - CreateSOBuffers(); m_General.Init(m_pDevice, m_DebugManager); @@ -149,14 +162,14 @@ void D3D12Replay::CreateResources() AMDCounters *counters = NULL; - if(m_Vendor == GPUVendor::AMD) + if(m_DriverInfo.vendor == GPUVendor::AMD) { RDCLOG("AMD GPU detected - trying to initialise AMD counters"); counters = new AMDCounters(m_pDevice->IsDebugLayerEnabled()); } else { - RDCLOG("%s GPU detected - no counters available", ToStr(m_Vendor).c_str()); + RDCLOG("%s GPU detected - no counters available", ToStr(m_DriverInfo.vendor).c_str()); } ID3D12Device *d3dDevice = m_pDevice->GetReal(); @@ -211,7 +224,7 @@ APIProperties D3D12Replay::GetAPIProperties() ret.pipelineType = GraphicsAPI::D3D12; ret.localRenderer = GraphicsAPI::D3D12; - ret.vendor = m_Vendor; + ret.vendor = m_DriverInfo.vendor; ret.degraded = false; ret.shadersMutable = false; ret.rgpCapture = m_RGP != NULL && m_RGP->DriverSupportsInterop(); @@ -3658,6 +3671,8 @@ ReplayStatus D3D12_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) replay->SetProxy(rdc == NULL); replay->SetRGP(rgp); + replay->Initialise(); + *driver = (IReplayDriver *)replay; return ReplayStatus::Succeeded; } diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 6741e610f..890ff935a 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -57,11 +57,13 @@ public: void SetRGP(AMDRGPControl *rgp) { m_RGP = rgp; } void SetProxy(bool proxy) { m_Proxy = proxy; } bool IsRemoteProxy() { return m_Proxy; } + void Initialise(); void Shutdown(); void SetDevice(WrappedID3D12Device *d) { m_pDevice = d; } void CreateResources(); void DestroyResources(); + DriverInformation GetDriverInfo() { return m_DriverInfo; } APIProperties GetAPIProperties(); ResourceDescription &GetResourceDesc(ResourceId id); @@ -276,8 +278,6 @@ private: bool m_Proxy; - GPUVendor m_Vendor = GPUVendor::Unknown; - vector m_ProxyResources; struct OutputWindow @@ -411,6 +411,8 @@ private: AMDCounters *m_pAMDCounters = NULL; AMDRGPControl *m_RGP = NULL; + DriverInformation m_DriverInfo; + D3D12AMDDrawCallback *m_pAMDDrawCallback = NULL; void FillTimersAMD(uint32_t *eventStartID, uint32_t *sampleIndex, vector *eventIDs); diff --git a/renderdoc/driver/dxgi/dxgi_common.cpp b/renderdoc/driver/dxgi/dxgi_common.cpp index 87564fc9c..7cf255487 100644 --- a/renderdoc/driver/dxgi/dxgi_common.cpp +++ b/renderdoc/driver/dxgi/dxgi_common.cpp @@ -26,6 +26,11 @@ #include "common/common.h" #include "common/threading.h" #include "serialise/serialiser.h" +#include "strings/string_utils.h" + +// for GetDriverVersion() +#include +#include UINT GetFormatBPP(DXGI_FORMAT f) { @@ -1367,6 +1372,91 @@ void WarnUnknownGUID(const char *name, REFIID riid) } } +static std::string GetDeviceProperty(HDEVINFO devs, PSP_DEVINFO_DATA data, const DEVPROPKEY *key) +{ + DEVPROPTYPE type = {}; + DWORD bufSize = 0; + + // this ALWAYS fails, we need to check if the er ror was just an insufficient buffer. + SetupDiGetDevicePropertyW(devs, data, key, &type, NULL, 0, &bufSize, 0); + + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return ""; + + RDCASSERTEQUAL((uint32_t)type, DEVPROP_TYPE_STRING); + + std::wstring string; + string.resize(bufSize); + BOOL success = + SetupDiGetDevicePropertyW(devs, data, key, &type, (PBYTE)string.data(), bufSize, &bufSize, 0); + + if(!success) + return ""; + + return StringFormat::Wide2UTF8(string); +} + +std::string GetDriverVersion(DXGI_ADAPTER_DESC &desc) +{ + std::string device = StringFormat::Wide2UTF8(desc.Description); + + // fixed GUID for graphics drivers, from + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx + GUID display_class = {0x4d36e968, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; + + HDEVINFO devs = SetupDiGetClassDevs(&display_class, NULL, NULL, DIGCF_PRESENT); + + if(devs == NULL) + { + RDCERR("Couldn't enumerate graphics adapters: %d", GetLastError()); + return device; + } + + std::string pci_match = StringFormat::Fmt("pci\\ven_%04x&dev_%04x", desc.VendorId, desc.DeviceId); + + std::string driverVersion = ""; + + DWORD idx = 0; + SP_DEVINFO_DATA data = {}; + data.cbSize = sizeof(data); + while(SetupDiEnumDeviceInfo(devs, idx, &data)) + { + std::string version = GetDeviceProperty(devs, &data, &DEVPKEY_Device_DriverVersion); + + if(version.empty()) + { + SetupDiDestroyDeviceInfoList(devs); + return device; + } + + // if we got a version, and didn't have one yet, set it + if(version.empty()) + driverVersion = version; + + std::string pciid = GetDeviceProperty(devs, &data, &DEVPKEY_Device_MatchingDeviceId); + + if(version.empty()) + { + SetupDiDestroyDeviceInfoList(devs); + return device; + } + + pciid = strlower(pciid); + + // if the PCI id matches, take it + if(pciid == pci_match) + driverVersion = version; + + // move to the next device + RDCEraseEl(data); + data.cbSize = sizeof(data); + idx++; + } + + SetupDiDestroyDeviceInfoList(devs); + return device + " " + driverVersion; +} + Topology MakePrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY Topo) { switch(Topo) diff --git a/renderdoc/driver/dxgi/dxgi_common.h b/renderdoc/driver/dxgi/dxgi_common.h index dac3f5d7c..98acee568 100644 --- a/renderdoc/driver/dxgi/dxgi_common.h +++ b/renderdoc/driver/dxgi/dxgi_common.h @@ -63,6 +63,8 @@ D3D_PRIMITIVE_TOPOLOGY MakeD3DPrimitiveTopology(Topology Topo); void WarnUnknownGUID(const char *name, REFIID riid); +std::string GetDriverVersion(DXGI_ADAPTER_DESC &desc); + DECLARE_REFLECTION_STRUCT(DXGI_SAMPLE_DESC); DECLARE_REFLECTION_STRUCT(IID); DECLARE_REFLECTION_ENUM(DXGI_FORMAT); diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index 33f9d8c4e..9c3b02436 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -672,8 +672,11 @@ void GLReplay::InitDebugData() // try to identify the GPU we're running on. { + RDCEraseEl(m_DriverInfo); + const char *vendor = (const char *)drv.glGetString(eGL_VENDOR); const char *renderer = (const char *)drv.glGetString(eGL_RENDERER); + const char *version = (const char *)drv.glGetString(eGL_VERSION); // we're just doing substring searches, so combine both for ease. std::string combined = (vendor ? vendor : ""); @@ -718,24 +721,34 @@ void GLReplay::InitDebugData() { if(combined.find(p.search) != std::string::npos) { - if(m_Vendor == GPUVendor::Unknown) + if(m_DriverInfo.vendor == GPUVendor::Unknown) { - m_Vendor = p.vendor; + m_DriverInfo.vendor = p.vendor; } else { // either we already found this with another pattern, or we've identified two patterns and // it's ambiguous. Keep the first one we found, arbitrarily, but print a warning. - if(m_Vendor != p.vendor) + if(m_DriverInfo.vendor != p.vendor) { RDCWARN("Already identified '%s' as %s, but now identified as %s", combined.c_str(), - ToStr(m_Vendor).c_str(), ToStr(p.vendor).c_str()); + ToStr(m_DriverInfo.vendor).c_str(), ToStr(p.vendor).c_str()); } } } } - RDCDEBUG("Identified GPU vendor '%s'", ToStr(m_Vendor).c_str()); + RDCDEBUG("Identified GPU vendor '%s'", ToStr(m_DriverInfo.vendor).c_str()); + + std::string versionString = version; + + versionString += " / "; + versionString += renderer; + versionString += " / "; + versionString += vendor; + + versionString.resize(RDCMIN(versionString.size(), ARRAY_COUNT(m_DriverInfo.version) - 1)); + memcpy(m_DriverInfo.version, versionString.c_str(), versionString.size()); } // these below need to be made on the replay context, as they are context-specific (not shared) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 008017893..b024061b0 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -1162,6 +1162,10 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) { ctxdata.built = true; + if(IsCaptureMode(m_State)) + RDCLOG("Activating new GL context: %s / %s / %s", GL.glGetString(eGL_VENDOR), + GL.glGetString(eGL_RENDERER), GL.glGetString(eGL_VERSION)); + const vector &globalExts = IsGLES ? m_GLESExtensions : m_GLExtensions; if(HasExt[KHR_debug] && GL.glDebugMessageCallback && diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index c271a8da5..46a2cdc41 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -54,6 +54,7 @@ GLReplay::GLReplay() m_OutputWindowID = 1; RDCEraseEl(m_GetTexturePrevData); + RDCEraseEl(m_DriverInfo); } void GLReplay::Shutdown() @@ -151,7 +152,7 @@ APIProperties GLReplay::GetAPIProperties() ret.pipelineType = GraphicsAPI::OpenGL; ret.localRenderer = GraphicsAPI::OpenGL; ret.degraded = m_Degraded; - ret.vendor = m_Vendor; + ret.vendor = m_DriverInfo.vendor; ret.shadersMutable = true; return ret; @@ -259,14 +260,14 @@ void GLReplay::SetReplayData(GLWindowingData data) } else { - if(m_Vendor == GPUVendor::AMD) + if(m_DriverInfo.vendor == GPUVendor::AMD) { RDCLOG("AMD GPU detected - trying to initialise AMD counters"); counters = new AMDCounters(); } else { - RDCLOG("%s GPU detected - no counters available", ToStr(m_Vendor).c_str()); + RDCLOG("%s GPU detected - no counters available", ToStr(m_DriverInfo.vendor).c_str()); } } diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 292102c07..1b2ab3b42 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -92,6 +92,7 @@ public: void Shutdown(); void SetDriver(WrappedOpenGL *d) { m_pDriver = d; } + DriverInformation GetDriverInfo() { return m_DriverInfo; } APIProperties GetAPIProperties(); ResourceDescription &GetResourceDesc(ResourceId id); @@ -372,8 +373,6 @@ private: bool m_Degraded; - GPUVendor m_Vendor = GPUVendor::Unknown; - HighlightCache m_HighlightCache; // eventId -> data @@ -426,6 +425,8 @@ private: GLPipe::State m_CurPipelineState; + DriverInformation m_DriverInfo; + // AMD counter instance AMDCounters *m_pAMDCounters = NULL; diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index bb1df00db..99d0397d5 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -55,6 +55,8 @@ VulkanReplay::VulkanReplay() m_BindDepth = false; m_DebugWidth = m_DebugHeight = 1; + + RDCEraseEl(m_DriverInfo); } VulkanDebugManager *VulkanReplay::GetDebugManager() @@ -807,6 +809,54 @@ void VulkanReplay::FileChanged() { } +void VulkanReplay::GetInitialDriverVersion() +{ + RDCEraseEl(m_DriverInfo); + + VkInstance inst = m_pDriver->GetInstance(); + + uint32_t count; + VkResult vkr = ObjDisp(inst)->EnumeratePhysicalDevices(Unwrap(inst), &count, NULL); + + if(vkr != VK_SUCCESS) + { + RDCERR("Couldn't enumerate physical devices"); + return; + } + + if(count == 0) + { + RDCERR("No physical devices available"); + } + + count = 1; + VkPhysicalDevice firstDevice = VK_NULL_HANDLE; + + vkr = ObjDisp(inst)->EnumeratePhysicalDevices(Unwrap(inst), &count, &firstDevice); + + // incomplete is expected if multiple GPUs are present, and we're just grabbing the first + if(vkr != VK_SUCCESS && vkr != VK_INCOMPLETE) + { + RDCERR("Couldn't fetch first physical device"); + return; + } + + VkPhysicalDeviceProperties props; + ObjDisp(inst)->GetPhysicalDeviceProperties(firstDevice, &props); + + SetDriverInformation(props); +} + +void VulkanReplay::SetDriverInformation(const VkPhysicalDeviceProperties &props) +{ + VkDriverInfo info(props); + m_DriverInfo.vendor = info.Vendor(); + std::string versionString = + StringFormat::Fmt("%s %u.%u.%u", props.deviceName, info.Major(), info.Minor(), info.Patch()); + versionString.resize(RDCMIN(versionString.size(), ARRAY_COUNT(m_DriverInfo.version) - 1)); + memcpy(m_DriverInfo.version, versionString.c_str(), versionString.size()); +} + void VulkanReplay::SavePipelineState() { const VulkanRenderState &state = m_pDriver->m_RenderState; @@ -3515,6 +3565,8 @@ ReplayStatus Vulkan_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver) *driver = (IReplayDriver *)replay; + replay->GetInitialDriverVersion(); + return ReplayStatus::Succeeded; } diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index 4884950f5..5302196d4 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -196,6 +196,7 @@ public: void DestroyResources(); void SetDriver(WrappedVulkan *d) { m_pDriver = d; } + DriverInformation GetDriverInfo() { return m_DriverInfo; } APIProperties GetAPIProperties(); ResourceDescription &GetResourceDesc(ResourceId id); @@ -338,6 +339,8 @@ public: static bool CheckVulkanLayer(VulkanLayerFlags &flags, std::vector &myJSONs, std::vector &otherJSONs); static void InstallVulkanLayer(bool systemLevel); + void GetInitialDriverVersion(); + void SetDriverInformation(const VkPhysicalDeviceProperties &props); AMDCounters *GetAMDCounters() { return m_pAMDCounters; } private: @@ -606,6 +609,8 @@ private: VKPipe::State m_VulkanPipelineState; + DriverInformation m_DriverInfo; + void FillTimersAMD(uint32_t *eventStartID, uint32_t *sampleIndex, vector *eventIDs); vector FetchCountersAMD(const vector &counters); diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 1ca54793d..0c75715ba 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -309,8 +309,11 @@ ReplayStatus WrappedVulkan::Initialise(VkInitParams ¶ms, uint64_t sectionVer GetResourceManager()->AddLiveResource(params.InstanceID, m_Instance); // we'll add the chunk later when we re-process it. - AddResource(params.InstanceID, ResourceType::Device, "Instance"); - GetReplay()->GetResourceDesc(params.InstanceID).initialisationChunks.clear(); + if(params.InstanceID != ResourceId()) + { + AddResource(params.InstanceID, ResourceType::Device, "Instance"); + GetReplay()->GetResourceDesc(params.InstanceID).initialisationChunks.clear(); + } InitInstanceExtensionTables(m_Instance, &m_EnabledExtensions); @@ -919,6 +922,16 @@ VkResult WrappedVulkan::vkEnumeratePhysicalDevices(VkInstance instance, ObjDisp(devices[i])->GetPhysicalDeviceMemoryProperties(Unwrap(devices[i]), record->memProps); + VkPhysicalDeviceProperties physProps; + + ObjDisp(devices[i])->GetPhysicalDeviceProperties(Unwrap(devices[i]), &physProps); + + VkDriverInfo capturedVersion(physProps); + + RDCLOG("physical device %u: %s (ver %u.%u patch 0x%x) - %04x:%04x", i, physProps.deviceName, + capturedVersion.Major(), capturedVersion.Minor(), capturedVersion.Patch(), + physProps.vendorID, physProps.deviceID); + m_PhysicalDevices[i] = devices[i]; // we remap memory indices to discourage coherent maps as much as possible @@ -1835,6 +1848,8 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi ObjDisp(physicalDevice) ->GetPhysicalDeviceFeatures(Unwrap(physicalDevice), &m_PhysicalDeviceData.features); + m_Replay.SetDriverInformation(m_PhysicalDeviceData.props); + // MoltenVK reports 0x3fffffff for this limit so just ignore that value if it comes up RDCASSERT(m_PhysicalDeviceData.props.limits.maxBoundDescriptorSets < ARRAY_COUNT(BakedCmdBufferInfo::pushDescriptorID[0]) || diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index 2f2f7a828..409a122cf 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -180,6 +180,11 @@ extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetCommitHash() return GitVersionHash; } +extern "C" RENDERDOC_API DriverInformation RENDERDOC_CC RENDERDOC_GetDriverInformation(GraphicsAPI api) +{ + return RenderDoc::Inst().GetDriverInformation(api); +} + extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetConfigSetting(const char *name) { return RenderDoc::Inst().GetConfigSetting(name).c_str(); diff --git a/renderdoc/replay/renderdoc_serialise.inl b/renderdoc/replay/renderdoc_serialise.inl index eeb0d188f..48366a759 100644 --- a/renderdoc/replay/renderdoc_serialise.inl +++ b/renderdoc/replay/renderdoc_serialise.inl @@ -479,6 +479,15 @@ void DoSerialise(SerialiserType &ser, APIProperties &el) SIZE_CHECK(20); } +template +void DoSerialise(SerialiserType &ser, DriverInformation &el) +{ + SERIALISE_MEMBER(vendor); + SERIALISE_MEMBER(version); + + SIZE_CHECK(132); +} + template void DoSerialise(SerialiserType &ser, DebugMessage &el) { @@ -2170,6 +2179,7 @@ INSTANTIATE_SERIALISE_TYPE(ResourceDescription) INSTANTIATE_SERIALISE_TYPE(TextureDescription) INSTANTIATE_SERIALISE_TYPE(BufferDescription) INSTANTIATE_SERIALISE_TYPE(APIProperties) +INSTANTIATE_SERIALISE_TYPE(DriverInformation) INSTANTIATE_SERIALISE_TYPE(DebugMessage) INSTANTIATE_SERIALISE_TYPE(APIEvent) INSTANTIATE_SERIALISE_TYPE(DrawcallDescription) diff --git a/renderdoc/replay/replay_driver.h b/renderdoc/replay/replay_driver.h index eb8783723..a8dcb6411 100644 --- a/renderdoc/replay/replay_driver.h +++ b/renderdoc/replay/replay_driver.h @@ -170,6 +170,8 @@ public: virtual void FileChanged() = 0; virtual bool NeedRemapForFetch(const ResourceFormat &format) = 0; + + virtual DriverInformation GetDriverInfo() = 0; }; class IReplayDriver : public IRemoteDriver