From 1cbcddf4101d13d6548d28309b9ccfe0c0751b83 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 3 Jun 2024 09:24:27 +0200 Subject: [PATCH] Add `IsDebugToolAttached` to GPUDevice for detecting gpu debugger tools attached and auto-enable GPU profiler in that case --- Source/Engine/Graphics/GPUDevice.cpp | 3 +- Source/Engine/Graphics/GPUDevice.h | 5 ++ Source/Engine/Graphics/Graphics.cpp | 8 +++ .../DirectX/DX11/GPUDeviceDX11.cpp | 51 ++++++++++++------- .../DirectX/DX12/GPUDeviceDX12.cpp | 25 +++++++-- .../Vulkan/GPUDeviceVulkan.Layers.cpp | 14 +++++ .../GraphicsDevice/Vulkan/GPUDeviceVulkan.h | 11 ++-- 7 files changed, 90 insertions(+), 27 deletions(-) diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index bdacb9766..60298a513 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -321,10 +321,11 @@ GPUDevice::GPUDevice(RendererType type, ShaderProfile profile) , _res(New()) , _resources(1024) , TotalGraphicsMemory(0) + , IsDebugToolAttached(false) , QuadShader(nullptr) , CurrentTask(nullptr) { - ASSERT(_rendererType != RendererType::Unknown); + ASSERT_LOW_LAYER(_rendererType != RendererType::Unknown); } GPUDevice::~GPUDevice() diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index 081f22d03..f7ffe00a9 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -121,6 +121,11 @@ public: /// API_FIELD(ReadOnly) uint64 TotalGraphicsMemory; + /// + /// Indicates that debug tool is profiling device (eg. RenderDoc). + /// + API_FIELD(ReadOnly) bool IsDebugToolAttached; + /// /// The GPU limits. /// diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp index 954fc7c73..8483d1f6c 100644 --- a/Source/Engine/Graphics/Graphics.cpp +++ b/Source/Engine/Graphics/Graphics.cpp @@ -8,6 +8,7 @@ #include "Engine/Core/Config/GraphicsSettings.h" #include "Engine/Engine/CommandLine.h" #include "Engine/Engine/EngineService.h" +#include "Engine/Profiler/ProfilerGPU.h" #include "Engine/Render2D/Font.h" bool Graphics::UseVSync = false; @@ -186,6 +187,13 @@ bool GraphicsService::Init() ); // Initialize + if (device->IsDebugToolAttached) + { +#if COMPILE_WITH_PROFILER + // Auto-enable GPU profiler + ProfilerGPU::Enabled = true; +#endif + } if (device->LoadContent()) { return true; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 2d90b50ae..3e6d97b28 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -286,22 +286,6 @@ bool GPUDeviceDX11::Init() } UpdateOutputs(adapter); - ComPtr factory5; - _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5)); - if (factory5) - { - BOOL allowTearing; - if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) - && allowTearing -#if PLATFORM_WINDOWS - && GetModuleHandleA("renderdoc.dll") == nullptr // Disable tearing with RenderDoc (prevents crashing) -#endif - ) - { - _allowTearing = true; - } - } - // Get flags and device type base on current configuration uint32 flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #if GPU_ENABLE_DIAGNOSTICS @@ -313,13 +297,44 @@ bool GPUDeviceDX11::Init() D3D_FEATURE_LEVEL createdFeatureLevel = static_cast(0); auto targetFeatureLevel = GetD3DFeatureLevel(); VALIDATE_DIRECTX_CALL(D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, &targetFeatureLevel, 1, D3D11_SDK_VERSION, &_device, &createdFeatureLevel, &_imContext)); - - // Validate result ASSERT(_device); ASSERT(_imContext); ASSERT(createdFeatureLevel == targetFeatureLevel); _state = DeviceState::Created; +#if PLATFORM_WINDOWS + // Detect RenderDoc usage (UUID {A7AA6116-9C8D-4BBA-9083-B4D816B71B78}) + IUnknown* unknown = nullptr; + const GUID uuidRenderDoc = { 0xa7aa6116, 0x9c8d, 0x4bba, {0x90, 0x83, 0xb4, 0xd8, 0x16, 0xb7, 0x1b, 0x78}}; + HRESULT hr = _device->QueryInterface(uuidRenderDoc, (void**)&unknown); + if(SUCCEEDED(hr) && unknown) + { + IsDebugToolAttached = true; + unknown->Release(); + } + if (!IsDebugToolAttached && GetModuleHandleA("renderdoc.dll") != nullptr) + { + IsDebugToolAttached = true; + } +#endif + + // Check if can use screen tearing on a swapchain + ComPtr factory5; + _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5)); + if (factory5) + { + BOOL allowTearing; + if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) + && allowTearing +#if PLATFORM_WINDOWS + && !IsDebugToolAttached // Disable tearing with RenderDoc (prevents crashing) +#endif + ) + { + _allowTearing = true; + } + } + // Init device limits { auto& limits = Limits; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 05da7c839..9f024136a 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -304,6 +304,26 @@ bool GPUDeviceDX12::Init() } UpdateOutputs(adapter); + // Create DirectX device + VALIDATE_DIRECTX_CALL(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&_device))); + +#if PLATFORM_WINDOWS + // Detect RenderDoc usage (UUID {A7AA6116-9C8D-4BBA-9083-B4D816B71B78}) + IUnknown* unknown = nullptr; + const GUID uuidRenderDoc = { 0xa7aa6116, 0x9c8d, 0x4bba, { 0x90, 0x83, 0xb4, 0xd8, 0x16, 0xb7, 0x1b, 0x78 } }; + HRESULT hr = _device->QueryInterface(uuidRenderDoc, (void**)&unknown); + if (SUCCEEDED(hr) && unknown) + { + IsDebugToolAttached = true; + unknown->Release(); + } + if (!IsDebugToolAttached && GetModuleHandleA("renderdoc.dll") != nullptr) + { + IsDebugToolAttached = true; + } +#endif + + // Check if can use screen tearing on a swapchain ComPtr factory5; _factoryDXGI->QueryInterface(IID_PPV_ARGS(&factory5)); if (factory5) @@ -312,15 +332,12 @@ bool GPUDeviceDX12::Init() if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))) && allowTearing #if PLATFORM_WINDOWS - && GetModuleHandleA("renderdoc.dll") == nullptr // Disable tearing with RenderDoc (prevents crashing) + && !IsDebugToolAttached // Disable tearing with RenderDoc (prevents crashing) #endif ) AllowTearing = true; } - // Create DirectX device - VALIDATE_DIRECTX_CALL(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&_device))); - // Debug Layer #if GPU_ENABLE_DIAGNOSTICS ComPtr infoQueue; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp index c8ee2ccd9..3a1a34e1c 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp @@ -200,6 +200,16 @@ static bool ListContains(const Array& list, const char* name) return false; } +static bool ListContains(const Array& list, const char* name) +{ + for (const StringAnsi& element : list) + { + if (element == name) + return true; + } + return false; +} + void GPUDeviceVulkan::GetInstanceLayersAndExtensions(Array& outInstanceExtensions, Array& outInstanceLayers, bool& outDebugUtils) { VkResult result; @@ -473,6 +483,10 @@ void GPUDeviceVulkan::GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array& outInstanceExtensions, Array& outInstanceLayers, bool& outDebugUtils); - static void GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array& outDeviceExtensions, Array& outDeviceLayers); - - void ParseOptionalDeviceExtensions(const Array& deviceExtensions); static OptionalVulkanDeviceExtensions OptionalDeviceExtensions; +private: + static void GetInstanceLayersAndExtensions(Array& outInstanceExtensions, Array& outInstanceLayers, bool& outDebugUtils); + void GetDeviceExtensionsAndLayers(VkPhysicalDevice gpu, Array& outDeviceExtensions, Array& outDeviceLayers); + static void ParseOptionalDeviceExtensions(const Array& deviceExtensions); + public: /// /// The Vulkan instance.