Просмотр исходного кода

renderer_vulkan: Query device names from the backend

ReinUsesLisp 6 лет назад
Родитель
Сommit
bc1b4b85b0

+ 1 - 0
src/video_core/renderer_vulkan/declarations.h

@@ -39,6 +39,7 @@ using UniqueFence = UniqueHandle<vk::Fence>;
 using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>;
 using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>;
 using UniqueImage = UniqueHandle<vk::Image>;
 using UniqueImage = UniqueHandle<vk::Image>;
 using UniqueImageView = UniqueHandle<vk::ImageView>;
 using UniqueImageView = UniqueHandle<vk::ImageView>;
+using UniqueInstance = UniqueHandle<vk::Instance>;
 using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>;
 using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>;
 using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>;
 using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>;
 using UniquePipeline = UniqueHandle<vk::Pipeline>;
 using UniquePipeline = UniqueHandle<vk::Pipeline>;

+ 69 - 0
src/video_core/renderer_vulkan/renderer_vulkan.cpp

@@ -9,6 +9,7 @@
 #include <fmt/format.h>
 #include <fmt/format.h>
 
 
 #include "common/assert.h"
 #include "common/assert.h"
+#include "common/dynamic_library.h"
 #include "common/logging/log.h"
 #include "common/logging/log.h"
 #include "common/telemetry.h"
 #include "common/telemetry.h"
 #include "core/core.h"
 #include "core/core.h"
@@ -53,6 +54,45 @@ VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity_,
     return VK_FALSE;
     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) {
 std::string GetReadableVersion(u32 version) {
     return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
     return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version),
                        VK_VERSION_PATCH(version));
                        VK_VERSION_PATCH(version));
@@ -276,4 +316,33 @@ void RendererVulkan::Report() const {
     telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
     telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions);
 }
 }
 
 
+std::vector<std::string> 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<vk::PhysicalDevice> devices(num_devices);
+    if (instance->enumeratePhysicalDevices(&num_devices, devices.data(), dld) !=
+        vk::Result::eSuccess) {
+        return {};
+    }
+
+    std::vector<std::string> names;
+    names.reserve(num_devices);
+    for (auto& device : devices) {
+        names.push_back(device.getProperties(dld).deviceName);
+    }
+    return names;
+}
+
 } // namespace Vulkan
 } // namespace Vulkan

+ 3 - 0
src/video_core/renderer_vulkan/renderer_vulkan.h

@@ -6,6 +6,7 @@
 
 
 #include <memory>
 #include <memory>
 #include <optional>
 #include <optional>
+#include <string>
 #include <vector>
 #include <vector>
 
 
 #include "video_core/renderer_base.h"
 #include "video_core/renderer_base.h"
@@ -44,6 +45,8 @@ public:
     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
     bool TryPresent(int timeout_ms) override;
     bool TryPresent(int timeout_ms) override;
 
 
+    static std::vector<std::string> EnumerateDevices();
+
 private:
 private:
     std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
     std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
         const vk::DispatchLoaderDynamic& dldi);
         const vk::DispatchLoaderDynamic& dldi);

+ 6 - 35
src/yuzu/configuration/configure_graphics.cpp

@@ -14,6 +14,9 @@
 #include "core/settings.h"
 #include "core/settings.h"
 #include "ui_configure_graphics.h"
 #include "ui_configure_graphics.h"
 #include "yuzu/configuration/configure_graphics.h"
 #include "yuzu/configuration/configure_graphics.h"
+#ifdef HAS_VULKAN
+#include "video_core/renderer_vulkan/renderer_vulkan.h"
+#endif
 
 
 namespace {
 namespace {
 enum class Resolution : int {
 enum class Resolution : int {
@@ -165,41 +168,9 @@ void ConfigureGraphics::UpdateDeviceComboBox() {
 
 
 void ConfigureGraphics::RetrieveVulkanDevices() {
 void ConfigureGraphics::RetrieveVulkanDevices() {
 #ifdef HAS_VULKAN
 #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<PFN_vkEnumeratePhysicalDevices>(
-        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<VkPhysicalDevice> 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<PFN_vkGetPhysicalDeviceProperties>(
-        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
 #endif
 }
 }