From 7fce9b102e0ba2eb23210fb990210c069974d2b2 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 20 Jun 2020 03:33:49 +1000 Subject: [PATCH] FrontendCommon: Add GPU enumeration methods to D3D11/Vulkan host displays --- src/frontend-common/d3d11_host_display.cpp | 55 +++++++++++++++++++++ src/frontend-common/d3d11_host_display.h | 4 ++ src/frontend-common/vulkan_host_display.cpp | 24 +++++++++ src/frontend-common/vulkan_host_display.h | 2 + 4 files changed, 85 insertions(+) diff --git a/src/frontend-common/d3d11_host_display.cpp b/src/frontend-common/d3d11_host_display.cpp index 089b6e349..ead55ab3b 100644 --- a/src/frontend-common/d3d11_host_display.cpp +++ b/src/frontend-common/d3d11_host_display.cpp @@ -2,6 +2,7 @@ #include "common/assert.h" #include "common/d3d11/shader_compiler.h" #include "common/log.h" +#include "common/string_util.h" #include "display_ps.hlsl.h" #include "display_vs.hlsl.h" #include @@ -477,4 +478,58 @@ void D3D11HostDisplay::RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 he m_context->Draw(3, 0); } +std::vector D3D11HostDisplay::EnumerateAdapterNames() +{ + ComPtr dxgi_factory; + HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf())); + if (SUCCEEDED(hr)) + { + std::vector adapter_names; + ComPtr current_adapter; + while (SUCCEEDED( + dxgi_factory->EnumAdapters(static_cast(adapter_names.size()), current_adapter.ReleaseAndGetAddressOf()))) + { + DXGI_ADAPTER_DESC adapter_desc; + std::string adapter_name; + if (SUCCEEDED(current_adapter->GetDesc(&adapter_desc))) + { + char adapter_name_buffer[128]; + const int name_length = WideCharToMultiByte(CP_UTF8, 0, adapter_desc.Description, + static_cast(std::wcslen(adapter_desc.Description)), + adapter_name_buffer, countof(adapter_name_buffer), 0, nullptr); + if (name_length >= 0) + adapter_name.assign(adapter_name_buffer, static_cast(name_length)); + else + adapter_name.assign("(Unknown)"); + } + else + { + adapter_name.assign("(Unknown)"); + } + + // handle duplicate adapter names + if (std::any_of(adapter_names.begin(), adapter_names.end(), + [&adapter_name](const std::string& other) { return (adapter_name == other); })) + { + std::string original_adapter_name = std::move(adapter_name); + + u32 current_extra = 2; + do + { + adapter_name = StringUtil::StdStringFromFormat("%s (%u)", original_adapter_name.c_str(), current_extra); + current_extra++; + } while (std::any_of(adapter_names.begin(), adapter_names.end(), + [&adapter_name](const std::string& other) { return (adapter_name == other); })); + } + + adapter_names.push_back(std::move(adapter_name)); + } + + if (!adapter_names.empty()) + return adapter_names; + } + + return {"(Default)"}; +} + } // namespace FrontendCommon \ No newline at end of file diff --git a/src/frontend-common/d3d11_host_display.h b/src/frontend-common/d3d11_host_display.h index e086107c2..637340514 100644 --- a/src/frontend-common/d3d11_host_display.h +++ b/src/frontend-common/d3d11_host_display.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include namespace FrontendCommon { @@ -60,6 +62,8 @@ public: void RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 height, HostDisplayTexture* texture_handle); void EndRenderAndPresent(); + static std::vector EnumerateAdapterNames(); + private: static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 16; diff --git a/src/frontend-common/vulkan_host_display.cpp b/src/frontend-common/vulkan_host_display.cpp index 36ad9406c..69d22e6d5 100644 --- a/src/frontend-common/vulkan_host_display.cpp +++ b/src/frontend-common/vulkan_host_display.cpp @@ -1,6 +1,7 @@ #include "vulkan_host_display.h" #include "common/assert.h" #include "common/log.h" +#include "common/scope_guard.h" #include "common/vulkan/builders.h" #include "common/vulkan/context.h" #include "common/vulkan/shader_cache.h" @@ -489,4 +490,27 @@ void VulkanHostDisplay::RenderSoftwareCursor(s32 left, s32 top, s32 width, s32 h vkCmdDraw(cmdbuffer, 3, 1, 0, 0); } +std::vector VulkanHostDisplay::EnumerateAdapterNames() +{ + if (Vulkan::LoadVulkanLibrary()) + { + Common::ScopeGuard lib_guard([]() { Vulkan::UnloadVulkanLibrary(); }); + + VkInstance instance = Vulkan::Context::CreateVulkanInstance(false, false, false); + if (instance != VK_NULL_HANDLE) + { + Common::ScopeGuard instance_guard([&instance]() { vkDestroyInstance(instance, nullptr); }); + + if (Vulkan::LoadVulkanInstanceFunctions(instance)) + { + Vulkan::Context::GPUNameList gpus = Vulkan::Context::EnumerateGPUNames(instance); + if (!gpus.empty()) + return gpus; + } + } + } + + return {"(Default)"}; +} + } // namespace FrontendCommon \ No newline at end of file diff --git a/src/frontend-common/vulkan_host_display.h b/src/frontend-common/vulkan_host_display.h index 774c74f79..a17e2a2ec 100644 --- a/src/frontend-common/vulkan_host_display.h +++ b/src/frontend-common/vulkan_host_display.h @@ -62,6 +62,8 @@ public: void ResizeSwapChain(u32 new_width, u32 new_height); void DestroySwapChain(); + static std::vector EnumerateAdapterNames(); + private: struct PushConstants {