diff --git a/.gitignore b/.gitignore index 26600c6f6187..5a6070d51c5f 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,5 @@ yaml-cpp.pc # ssl certificate cacert.pem + +_ReSharper.*/ \ No newline at end of file diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.cpp b/rpcs3/Emu/RSX/VK/vkutils/device.cpp index 3f9b53ceb00c..0f9ee83a7916 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/device.cpp @@ -56,8 +56,9 @@ namespace vk stencil_export_support = device_extensions.is_supported(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME); conditional_render_support = device_extensions.is_supported(VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME); - external_memory_host_support = device_extensions.is_supported(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); + external_memory_host_support = device_extensions.is_supported(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); unrestricted_depth_range_support = device_extensions.is_supported(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); + surface_capabilities_2_support = instance_extensions.is_supported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); } void physical_device::create(VkInstance context, VkPhysicalDevice pdev, bool allow_extensions) @@ -517,6 +518,12 @@ namespace vk return pgpu->external_memory_host_support; } + + bool render_device::get_surface_capabilities_2_support() const + { + return pgpu->surface_capabilities_2_support; + } + mem_allocator_base* render_device::get_allocator() const { return m_allocator.get(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/device.h b/rpcs3/Emu/RSX/VK/vkutils/device.h index e627580cd941..040ae78290b5 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/device.h +++ b/rpcs3/Emu/RSX/VK/vkutils/device.h @@ -51,6 +51,7 @@ namespace vk bool conditional_render_support = false; bool external_memory_host_support = false; bool unrestricted_depth_range_support = false; + bool surface_capabilities_2_support = false; friend class render_device; private: @@ -116,6 +117,7 @@ namespace vk bool get_conditional_render_support() const; bool get_unrestricted_depth_range_support() const; bool get_external_memory_host_support() const; + bool get_surface_capabilities_2_support() const; mem_allocator_base* get_allocator() const; diff --git a/rpcs3/Emu/RSX/VK/vkutils/instance.hpp b/rpcs3/Emu/RSX/VK/vkutils/instance.hpp index 7b88614f9dca..d2d7a4d5c38c 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/instance.hpp +++ b/rpcs3/Emu/RSX/VK/vkutils/instance.hpp @@ -154,6 +154,11 @@ namespace vk { extensions.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); } + + if (support.is_supported(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)) + { + extensions.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME); + } #ifdef _WIN32 extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); #elif defined(__APPLE__) @@ -413,7 +418,7 @@ namespace vk color_space = surfFormats[0].colorSpace; - return new swapchain_WSI(dev, presentQueueNodeIndex, graphicsQueueNodeIndex, format, m_surface, color_space, force_wm_reporting_off); + return new swapchain_WSI(dev, presentQueueNodeIndex, graphicsQueueNodeIndex, format, m_surface, window_handle, color_space, force_wm_reporting_off); } }; } diff --git a/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp b/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp index 70cc5c5f368c..810bb520052c 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp +++ b/rpcs3/Emu/RSX/VK/vkutils/swapchain.hpp @@ -493,6 +493,7 @@ namespace vk class swapchain_WSI : public WSI_swapchain_base { VkSurfaceKHR m_surface = VK_NULL_HANDLE; + display_handle_t m_window_handle = NULL; VkColorSpaceKHR m_color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; VkSwapchainKHR m_vk_swapchain = nullptr; @@ -524,7 +525,7 @@ namespace vk } public: - swapchain_WSI(vk::physical_device& gpu, u32 _present_queue, u32 _graphics_queue, VkFormat format, VkSurfaceKHR surface, VkColorSpaceKHR color_space, bool force_wm_reporting_off) + swapchain_WSI(vk::physical_device& gpu, u32 _present_queue, u32 _graphics_queue, VkFormat format, VkSurfaceKHR surface, display_handle_t window_handle, VkColorSpaceKHR color_space, bool force_wm_reporting_off) : WSI_swapchain_base(gpu, _present_queue, _graphics_queue, format) { createSwapchainKHR = reinterpret_cast(vkGetDeviceProcAddr(dev, "vkCreateSwapchainKHR")); @@ -534,6 +535,7 @@ namespace vk queuePresentKHR = reinterpret_cast(vkGetDeviceProcAddr(dev, "vkQueuePresentKHR")); m_surface = surface; + m_window_handle = window_handle; m_color_space = color_space; if (!force_wm_reporting_off) @@ -586,8 +588,49 @@ namespace vk VkSwapchainKHR old_swapchain = m_vk_swapchain; vk::physical_device& gpu = const_cast(dev.gpu()); - VkSurfaceCapabilitiesKHR surface_descriptors = {}; - CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, m_surface, &surface_descriptors)); + VkSurfaceCapabilities2KHR pSurfaceCapabilities = {}; + pSurfaceCapabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR; + + VkPhysicalDeviceSurfaceInfo2KHR pSurfaceInfo = {}; + pSurfaceInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; + pSurfaceInfo.surface = m_surface; + + VkSurfaceCapabilitiesKHR surface_descriptors; + bool init_surface_descriptors = true; + bool should_disable_exclusive_full_screen = false; + #ifdef _WIN32 + if (g_cfg.video.vk.force_disable_exclusive_fullscreen_mode && dev.get_surface_capabilities_2_support()) + { + HMONITOR hmonitor = MonitorFromWindow(window_handle, MONITOR_DEFAULTTOPRIMARY); + if (hmonitor) + { + VkSurfaceCapabilitiesFullScreenExclusiveEXT full_screen_exclusive_capabilities = {}; + VkSurfaceFullScreenExclusiveWin32InfoEXT full_screen_exclusive_win32_info = {}; + full_screen_exclusive_capabilities.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT; + + pSurfaceCapabilities.pNext = reinterpret_cast(&full_screen_exclusive_capabilities); + + full_screen_exclusive_win32_info.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT; + full_screen_exclusive_win32_info.hmonitor = hmonitor; + + pSurfaceInfo.pNext = reinterpret_cast(&full_screen_exclusive_win32_info); + + CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu, &pSurfaceInfo, &pSurfaceCapabilities)); + + surface_descriptors = pSurfaceCapabilities.surfaceCapabilities; + init_surface_descriptors = false; + should_disable_exclusive_full_screen = !!full_screen_exclusive_capabilities.fullScreenExclusiveSupported; + } + else + rsx_log.warning("Swapchain: failed to get monitor for the window"); + } + #endif + + if (init_surface_descriptors) + { + surface_descriptors = {}; + CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, m_surface, &surface_descriptors)); + } if (surface_descriptors.maxImageExtent.width < m_width || surface_descriptors.maxImageExtent.height < m_height) @@ -693,6 +736,19 @@ namespace vk swap_info.imageExtent.width = std::max(m_width, surface_descriptors.minImageExtent.width); swap_info.imageExtent.height = std::max(m_height, surface_descriptors.minImageExtent.height); + #ifdef _WIN32 + VkSurfaceFullScreenExclusiveInfoEXT full_screen_exclusive_info = {}; + if (should_disable_exclusive_full_screen) + { + full_screen_exclusive_info.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + full_screen_exclusive_info.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT; + + swap_info.pNext = reinterpret_cast(&full_screen_exclusive_info); + } + + rsx_log.success("Swapchain: requesting full screen exclusive mode %d.", static_cast(full_screen_exclusive_info.fullScreenExclusive)); + #endif + createSwapchainKHR(dev, &swap_info, nullptr, &m_vk_swapchain); if (old_swapchain) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index ec4a558b03c6..f6d943c0e54c 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -166,7 +166,8 @@ struct cfg_root : cfg::node cfg::string adapter{ this, "Adapter" }; cfg::_bool force_fifo{ this, "Force FIFO present mode" }; cfg::_bool force_primitive_restart{ this, "Force primitive restart flag" }; - + cfg::_bool force_disable_exclusive_fullscreen_mode{this, "Force Disable Exclusive Fullscreen Mode"}; + } vk{ this }; struct node_perf_overlay : cfg::node