From e6d55a6692d5d9f23602277a53761554a9eca4b2 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 26 May 2017 17:10:40 +0300 Subject: [PATCH] ui/vk: Reimplement vulkan GS selection; minor fixes for broken contexts on unsupported devices --- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 19 +++++++++++++++---- rpcs3/Emu/RSX/VK/VKHelpers.h | 21 ++++++++++++++++----- rpcs3/Gui/SettingsDialog.cpp | 32 +++++++++++++++++++++++--------- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index ce8d172762..9f943c8be6 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -451,9 +451,19 @@ VKGSRender::VKGSRender() : GSRender() { shaders_cache.load(rsx::old_shaders_cache::shader_language::glsl); - m_thread_context.createInstance("RPCS3"); - m_thread_context.makeCurrentInstance(1); - m_thread_context.enable_debugging(); + u32 instance_handle = m_thread_context.createInstance("RPCS3"); + + if (instance_handle > 0) + { + m_thread_context.makeCurrentInstance(instance_handle); + m_thread_context.enable_debugging(); + } + else + { + LOG_FATAL(RSX, "Could not find a vulkan compatible GPU driver. Your GPU(s) may not support Vulkan, or you need to install the vulkan runtime and drivers"); + m_device = VK_NULL_HANDLE; + return; + } #ifdef _WIN32 HINSTANCE hInstance = NULL; @@ -462,10 +472,11 @@ VKGSRender::VKGSRender() : GSRender() std::vector& gpus = m_thread_context.enumerateDevices(); //Actually confirm that the loader found at least one compatible device + //This should not happen unless something is wrong with the driver setup on the target system if (gpus.size() == 0) { //We can't throw in Emulator::Load, so we show error and return - LOG_FATAL(RSX, "Could not find a vulkan compatible GPU driver. Your GPU(s) may not support Vulkan, or you need to install the vulkan runtime and drivers"); + LOG_FATAL(RSX, "No compatible GPU devices found"); m_device = VK_NULL_HANDLE; return; } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 2499540629..122ed65b36 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -1019,11 +1019,16 @@ namespace vk PFN_vkCreateDebugReportCallbackEXT createDebugReportCallback = nullptr; VkDebugReportCallbackEXT m_debugger = nullptr; + bool loader_exists = false; + public: context() { m_instance = nullptr; + + //Check that some critical entry-points have been loaded into memory indicating prescence of a loader + loader_exists = (vkCreateInstance != nullptr); } ~context() @@ -1066,8 +1071,10 @@ namespace vk CHECK_RESULT(createDebugReportCallback(m_instance, &dbgCreateInfo, NULL, &m_debugger)); } - uint32_t createInstance(const char *app_name) + uint32_t createInstance(const char *app_name, bool fast = false) { + if (!loader_exists) return 0; + //Initialize a vulkan instance VkApplicationInfo app = {}; @@ -1088,7 +1095,7 @@ namespace vk std::vector layers; - if (g_cfg.video.debug_output) + if (!fast && g_cfg.video.debug_output) layers.push_back("VK_LAYER_LUNARG_standard_validation"); VkInstanceCreateInfo instance_info = {}; @@ -1096,11 +1103,12 @@ namespace vk instance_info.pApplicationInfo = &app; instance_info.enabledLayerCount = static_cast(layers.size()); instance_info.ppEnabledLayerNames = layers.data(); - instance_info.enabledExtensionCount = 3; - instance_info.ppEnabledExtensionNames = requested_extensions; + instance_info.enabledExtensionCount = fast? 0: 3; + instance_info.ppEnabledExtensionNames = fast? nullptr: requested_extensions; VkInstance instance; - CHECK_RESULT(vkCreateInstance(&instance_info, nullptr, &instance)); + if (vkCreateInstance(&instance_info, nullptr, &instance) != VK_SUCCESS) + return 0; m_vk_instances.push_back(instance); return (u32)m_vk_instances.size(); @@ -1137,6 +1145,9 @@ namespace vk std::vector& enumerateDevices() { + if (!loader_exists) + return gpus; + uint32_t num_gpus; CHECK_RESULT(vkEnumeratePhysicalDevices(m_instance, &num_gpus, nullptr)); diff --git a/rpcs3/Gui/SettingsDialog.cpp b/rpcs3/Gui/SettingsDialog.cpp index 1789cf1ed4..9dca644e73 100644 --- a/rpcs3/Gui/SettingsDialog.cpp +++ b/rpcs3/Gui/SettingsDialog.cpp @@ -481,25 +481,39 @@ SettingsDialog::SettingsDialog(wxWindow* parent, const std::string& path) #endif #ifdef _WIN32 + //TODO: This is very slow. Only init once + bool vulkan_supported = false; + vk::context device_enum_context; - device_enum_context.createInstance("RPCS3"); - device_enum_context.makeCurrentInstance(1); - std::vector& gpus = device_enum_context.enumerateDevices(); - device_enum_context.close(); - if (gpus.size() > 0) + u32 instance_handle = device_enum_context.createInstance("RPCS3", true); + + if (instance_handle > 0) { - for (auto& gpu : gpus) + device_enum_context.makeCurrentInstance(instance_handle); + std::vector& gpus = device_enum_context.enumerateDevices(); + + if (gpus.size() > 0) { - cbox_gs_vk_adapter->Append(gpu.name()); + //A device with vulkan support found. Init data + vulkan_supported = true; + + for (auto& gpu : gpus) + { + cbox_gs_vk_adapter->Append(gpu.name()); + } + + pads.emplace_back(std::make_unique(cfg_location{ "Video", "Vulkan", "Adapter" }, cbox_gs_vk_adapter)); } - pads.emplace_back(std::make_unique(cfg_location{"Video", "Vulkan", "Adapter"}, cbox_gs_vk_adapter)); } - else + + if (!vulkan_supported) { // Removes Vulkan from Render list when the system doesn't support it cbox_gs_render->Delete(cbox_gs_render->FindString("Vulkan")); cbox_gs_vk_adapter->Enable(false); } + + device_enum_context.close(); #else cbox_gs_vk_adapter->Enable(false); #endif