diff options
| -rw-r--r-- | src/video_core/renderer_vulkan/declarations.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 69 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.h | 3 | ||||
| -rw-r--r-- | 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<vk::Fence>; | |||
| 39 | using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>; | 39 | using UniqueFramebuffer = UniqueHandle<vk::Framebuffer>; |
| 40 | using UniqueImage = UniqueHandle<vk::Image>; | 40 | using UniqueImage = UniqueHandle<vk::Image>; |
| 41 | using UniqueImageView = UniqueHandle<vk::ImageView>; | 41 | using UniqueImageView = UniqueHandle<vk::ImageView>; |
| 42 | using UniqueInstance = UniqueHandle<vk::Instance>; | ||
| 42 | using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>; | 43 | using UniqueIndirectCommandsLayoutNVX = UniqueHandle<vk::IndirectCommandsLayoutNVX>; |
| 43 | using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>; | 44 | using UniqueObjectTableNVX = UniqueHandle<vk::ObjectTableNVX>; |
| 44 | using UniquePipeline = UniqueHandle<vk::Pipeline>; | 45 | using UniquePipeline = UniqueHandle<vk::Pipeline>; |
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 @@ | |||
| 9 | #include <fmt/format.h> | 9 | #include <fmt/format.h> |
| 10 | 10 | ||
| 11 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 12 | #include "common/dynamic_library.h" | ||
| 12 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 13 | #include "common/telemetry.h" | 14 | #include "common/telemetry.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| @@ -53,6 +54,45 @@ VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity_, | |||
| 53 | return VK_FALSE; | 54 | return VK_FALSE; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | Common::DynamicLibrary OpenVulkanLibrary() { | ||
| 58 | Common::DynamicLibrary library; | ||
| 59 | #ifdef __APPLE__ | ||
| 60 | // Check if a path to a specific Vulkan library has been specified. | ||
| 61 | char* libvulkan_env = getenv("LIBVULKAN_PATH"); | ||
| 62 | if (!libvulkan_env || !library.Open(libvulkan_env)) { | ||
| 63 | // Use the libvulkan.dylib from the application bundle. | ||
| 64 | std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; | ||
| 65 | library.Open(filename.c_str()); | ||
| 66 | } | ||
| 67 | #else | ||
| 68 | std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); | ||
| 69 | if (!library.Open(filename.c_str())) { | ||
| 70 | // Android devices may not have libvulkan.so.1, only libvulkan.so. | ||
| 71 | filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); | ||
| 72 | library.Open(filename.c_str()); | ||
| 73 | } | ||
| 74 | #endif | ||
| 75 | return library; | ||
| 76 | } | ||
| 77 | |||
| 78 | UniqueInstance CreateInstance(Common::DynamicLibrary& library, vk::DispatchLoaderDynamic& dld) { | ||
| 79 | PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; | ||
| 80 | if (!library.GetSymbol("vkGetInstanceProcAddr", &vkGetInstanceProcAddr)) { | ||
| 81 | return UniqueInstance{}; | ||
| 82 | } | ||
| 83 | dld.init(vkGetInstanceProcAddr); | ||
| 84 | |||
| 85 | const vk::ApplicationInfo application_info("yuzu", VK_MAKE_VERSION(0, 1, 0), "yuzu", | ||
| 86 | VK_MAKE_VERSION(0, 1, 0), VK_API_VERSION_1_1); | ||
| 87 | const vk::InstanceCreateInfo instance_ci({}, &application_info, 0, nullptr, 0, nullptr); | ||
| 88 | vk::Instance unsafe_instance; | ||
| 89 | if (vk::createInstance(&instance_ci, nullptr, &unsafe_instance, dld) != vk::Result::eSuccess) { | ||
| 90 | return UniqueInstance{}; | ||
| 91 | } | ||
| 92 | dld.init(unsafe_instance, vkGetInstanceProcAddr); | ||
| 93 | return UniqueInstance(unsafe_instance, {nullptr, dld}); | ||
| 94 | } | ||
| 95 | |||
| 56 | std::string GetReadableVersion(u32 version) { | 96 | std::string GetReadableVersion(u32 version) { |
| 57 | return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), | 97 | return fmt::format("{}.{}.{}", VK_VERSION_MAJOR(version), VK_VERSION_MINOR(version), |
| 58 | VK_VERSION_PATCH(version)); | 98 | VK_VERSION_PATCH(version)); |
| @@ -276,4 +316,33 @@ void RendererVulkan::Report() const { | |||
| 276 | telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); | 316 | telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); |
| 277 | } | 317 | } |
| 278 | 318 | ||
| 319 | std::vector<std::string> RendererVulkan::EnumerateDevices() { | ||
| 320 | Common::DynamicLibrary library = OpenVulkanLibrary(); | ||
| 321 | if (!library.IsOpen()) { | ||
| 322 | return {}; | ||
| 323 | } | ||
| 324 | vk::DispatchLoaderDynamic dld; | ||
| 325 | UniqueInstance instance = CreateInstance(library, dld); | ||
| 326 | if (!instance) { | ||
| 327 | return {}; | ||
| 328 | } | ||
| 329 | |||
| 330 | u32 num_devices; | ||
| 331 | if (instance->enumeratePhysicalDevices(&num_devices, nullptr, dld) != vk::Result::eSuccess) { | ||
| 332 | return {}; | ||
| 333 | } | ||
| 334 | std::vector<vk::PhysicalDevice> devices(num_devices); | ||
| 335 | if (instance->enumeratePhysicalDevices(&num_devices, devices.data(), dld) != | ||
| 336 | vk::Result::eSuccess) { | ||
| 337 | return {}; | ||
| 338 | } | ||
| 339 | |||
| 340 | std::vector<std::string> names; | ||
| 341 | names.reserve(num_devices); | ||
| 342 | for (auto& device : devices) { | ||
| 343 | names.push_back(device.getProperties(dld).deviceName); | ||
| 344 | } | ||
| 345 | return names; | ||
| 346 | } | ||
| 347 | |||
| 279 | } // namespace Vulkan | 348 | } // 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 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <optional> | 8 | #include <optional> |
| 9 | #include <string> | ||
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | 11 | ||
| 11 | #include "video_core/renderer_base.h" | 12 | #include "video_core/renderer_base.h" |
| @@ -44,6 +45,8 @@ public: | |||
| 44 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | 45 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; |
| 45 | bool TryPresent(int timeout_ms) override; | 46 | bool TryPresent(int timeout_ms) override; |
| 46 | 47 | ||
| 48 | static std::vector<std::string> EnumerateDevices(); | ||
| 49 | |||
| 47 | private: | 50 | private: |
| 48 | std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback( | 51 | std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback( |
| 49 | const vk::DispatchLoaderDynamic& dldi); | 52 | 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 @@ | |||
| 14 | #include "core/settings.h" | 14 | #include "core/settings.h" |
| 15 | #include "ui_configure_graphics.h" | 15 | #include "ui_configure_graphics.h" |
| 16 | #include "yuzu/configuration/configure_graphics.h" | 16 | #include "yuzu/configuration/configure_graphics.h" |
| 17 | #ifdef HAS_VULKAN | ||
| 18 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | ||
| 19 | #endif | ||
| 17 | 20 | ||
| 18 | namespace { | 21 | namespace { |
| 19 | enum class Resolution : int { | 22 | enum class Resolution : int { |
| @@ -165,41 +168,9 @@ void ConfigureGraphics::UpdateDeviceComboBox() { | |||
| 165 | 168 | ||
| 166 | void ConfigureGraphics::RetrieveVulkanDevices() { | 169 | void ConfigureGraphics::RetrieveVulkanDevices() { |
| 167 | #ifdef HAS_VULKAN | 170 | #ifdef HAS_VULKAN |
| 168 | QVulkanInstance instance; | 171 | vulkan_devices.clear(); |
| 169 | instance.setApiVersion(QVersionNumber(1, 1, 0)); | 172 | for (auto& name : Vulkan::RendererVulkan::EnumerateDevices()) { |
| 170 | if (!instance.create()) { | 173 | vulkan_devices.push_back(QString::fromStdString(name)); |
| 171 | LOG_INFO(Frontend, "Vulkan 1.1 not available"); | ||
| 172 | return; | ||
| 173 | } | ||
| 174 | const auto vkEnumeratePhysicalDevices{reinterpret_cast<PFN_vkEnumeratePhysicalDevices>( | ||
| 175 | instance.getInstanceProcAddr("vkEnumeratePhysicalDevices"))}; | ||
| 176 | if (vkEnumeratePhysicalDevices == nullptr) { | ||
| 177 | LOG_INFO(Frontend, "Failed to get pointer to vkEnumeratePhysicalDevices"); | ||
| 178 | return; | ||
| 179 | } | ||
| 180 | u32 physical_device_count; | ||
| 181 | if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count, nullptr) != | ||
| 182 | VK_SUCCESS) { | ||
| 183 | LOG_INFO(Frontend, "Failed to get physical devices count"); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | std::vector<VkPhysicalDevice> physical_devices(physical_device_count); | ||
| 187 | if (vkEnumeratePhysicalDevices(instance.vkInstance(), &physical_device_count, | ||
| 188 | physical_devices.data()) != VK_SUCCESS) { | ||
| 189 | LOG_INFO(Frontend, "Failed to get physical devices"); | ||
| 190 | return; | ||
| 191 | } | ||
| 192 | |||
| 193 | const auto vkGetPhysicalDeviceProperties{reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>( | ||
| 194 | instance.getInstanceProcAddr("vkGetPhysicalDeviceProperties"))}; | ||
| 195 | if (vkGetPhysicalDeviceProperties == nullptr) { | ||
| 196 | LOG_INFO(Frontend, "Failed to get pointer to vkGetPhysicalDeviceProperties"); | ||
| 197 | return; | ||
| 198 | } | ||
| 199 | for (const auto physical_device : physical_devices) { | ||
| 200 | VkPhysicalDeviceProperties properties; | ||
| 201 | vkGetPhysicalDeviceProperties(physical_device, &properties); | ||
| 202 | vulkan_devices.push_back(QString::fromUtf8(properties.deviceName)); | ||
| 203 | } | 174 | } |
| 204 | #endif | 175 | #endif |
| 205 | } | 176 | } |