From bc1b4b85b01aee30a14c234143e72ef3435f9660 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Tue, 17 Mar 2020 01:39:38 -0300 Subject: [PATCH] renderer_vulkan: Query device names from the backend --- src/video_core/renderer_vulkan/declarations.h | 1 + .../renderer_vulkan/renderer_vulkan.cpp | 69 +++++++++++++++++++ .../renderer_vulkan/renderer_vulkan.h | 3 + src/yuzu/configuration/configure_graphics.cpp | 41 ++--------- 4 files changed, 79 insertions(+), 35 deletions(-) diff --git a/src/video_core/renderer_vulkan/declarations.h b/src/video_core/renderer_vulkan/declarations.h index 323bf6b39..d2a1140c1 100644 --- a/src/video_core/renderer_vulkan/declarations.h +++ b/src/video_core/renderer_vulkan/declarations.h @@ -39,6 +39,7 @@ using UniqueFence = UniqueHandle; using UniqueFramebuffer = UniqueHandle; using UniqueImage = UniqueHandle; using UniqueImageView = UniqueHandle; +using UniqueInstance = UniqueHandle; using UniqueIndirectCommandsLayoutNVX = UniqueHandle; using UniqueObjectTableNVX = UniqueHandle; using UniquePipeline = UniqueHandle; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 6953aaafe..9c323a1aa 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -9,6 +9,7 @@ #include #include "common/assert.h" +#include "common/dynamic_library.h" #include "common/logging/log.h" #include "common/telemetry.h" #include "core/core.h" @@ -53,6 +54,45 @@ VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity_, return VK_FALSE; } +Common::DynamicLibrary OpenVulkanLibrary() { + Common::DynamicLibrary library; +#ifdef __APPLE__ + // Check if a path to a specific Vulkan library has been specified. + char* libvulkan_env = getenv("LIBVULKAN_PATH"); + if (!libvulkan_env || !library.Open(libvulkan_env)) { + // Use the libvulkan.dylib from the application bundle. + std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; + library.Open(filename.c_str()); + } +#else + std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); + if (!library.Open(filename.c_str())) { + // Android devices may not have libvulkan.so.1, only libvulkan.so. + filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); + library.Open(filename.c_str()); + } +#endif + return library; +} + +UniqueInstance CreateInstance(Common::DynamicLibrary& library, vk::DispatchLoaderDynamic& dld) { + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + if (!library.GetSymbol("vkGetInstanceProcAddr", &vkGetInstanceProcAddr)) { + return UniqueInstance{}; + } + dld.init(vkGetInstanceProcAddr); + + const vk::ApplicationInfo application_info("yuzu", VK_MAKE_VERSION(0, 1, 0), "yuzu", + VK_MAKE_VERSION(0, 1, 0), VK_API_VERSION_1_1); + const vk::InstanceCreateInfo instance_ci({}, &application_info, 0, nullptr, 0, nullptr); + vk::Instance unsafe_instance; + if (vk::createInstance(&instance_ci, nullptr, &unsafe_instance, dld) != vk::Result::eSuccess) { + return UniqueInstance{}; + } + dld.init(unsafe_instance, vkGetInstanceProcAddr); + return UniqueInstance(unsafe_instance, {nullptr, dld}); +} + std::string GetReadableVersion(u32 version) { return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), VK_VERSION_PATCH(version)); @@ -276,4 +316,33 @@ void RendererVulkan::Report() const { telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); } +std::vector RendererVulkan::EnumerateDevices() { + Common::DynamicLibrary library = OpenVulkanLibrary(); + if (!library.IsOpen()) { + return {}; + } + vk::DispatchLoaderDynamic dld; + UniqueInstance instance = CreateInstance(library, dld); + if (!instance) { + return {}; + } + + u32 num_devices; + if (instance->enumeratePhysicalDevices(&num_devices, nullptr, dld) != vk::Result::eSuccess) { + return {}; + } + std::vector devices(num_devices); + if (instance->enumeratePhysicalDevices(&num_devices, devices.data(), dld) != + vk::Result::eSuccess) { + return {}; + } + + std::vector names; + names.reserve(num_devices); + for (auto& device : devices) { + names.push_back(device.getProperties(dld).deviceName); + } + return names; +} + } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index d14384e79..7a17c546d 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -6,6 +6,7 @@ #include #include +#include #include #include "video_core/renderer_base.h" @@ -44,6 +45,8 @@ public: void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; bool TryPresent(int timeout_ms) override; + static std::vector EnumerateDevices(); + private: std::optional CreateDebugCallback( const vk::DispatchLoaderDynamic& dldi); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index a821c7b3c..d29332033 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -14,6 +14,9 @@ #include "core/settings.h" #include "ui_configure_graphics.h" #include "yuzu/configuration/configure_graphics.h" +#ifdef HAS_VULKAN +#include "video_core/renderer_vulkan/renderer_vulkan.h" +#endif namespace { enum class Resolution : int { @@ -165,41 +168,9 @@ void ConfigureGraphics::UpdateDeviceComboBox() { void ConfigureGraphics::RetrieveVulkanDevices() { #ifdef HAS_VULKAN - QVulkanInstance instance; - instance.setApiVersion(QVersionNumber(1, 1, 0)); - if (!instance.create()) { - LOG_INFO(Frontend, "Vulkan 1.1 not available"); - return; - } - const auto vkEnumeratePhysicalDevices{reinterpret_cast( - instance.getInstanceProcAddr("vkEnumeratePhysicalDevices"))}; - if (vkEnumeratePhysicalDevices == nullptr) { - LOG_INFO(Frontend, "Failed to get pointer to vkEnumeratePhysicalDevices"); - return; - } - u32 physical_device_count; - if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count, nullptr) != - VK_SUCCESS) { - LOG_INFO(Frontend, "Failed to get physical devices count"); - return; - } - std::vector physical_devices(physical_device_count); - if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count, - physical_devices.data()) != VK_SUCCESS) { - LOG_INFO(Frontend, "Failed to get physical devices"); - return; - } - - const auto vkGetPhysicalDeviceProperties{reinterpret_cast( - instance.getInstanceProcAddr("vkGetPhysicalDeviceProperties"))}; - if (vkGetPhysicalDeviceProperties == nullptr) { - LOG_INFO(Frontend, "Failed to get pointer to vkGetPhysicalDeviceProperties"); - return; - } - for (const auto physical_device : physical_devices) { - VkPhysicalDeviceProperties properties; - vkGetPhysicalDeviceProperties(physical_device, &properties); - vulkan_devices.push_back(QString::fromUtf8(properties.deviceName)); + vulkan_devices.clear(); + for (auto& name : Vulkan::RendererVulkan::EnumerateDevices()) { + vulkan_devices.push_back(QString::fromStdString(name)); } #endif }