From 575a267f076226977f4a006ac21ed39ed2e6e2db Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 3 Dec 2019 01:54:32 +0100 Subject: [PATCH] [vulkan] Support exclusive fullscreen control in presenter --- src/d3d11/d3d11_swapchain.cpp | 2 + src/vulkan/vulkan_presenter.cpp | 89 ++++++++++++++++++++++++++++----- src/vulkan/vulkan_presenter.h | 8 +-- 3 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index 71ae61744..7065136e6 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -389,6 +389,7 @@ namespace dxvk { presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1); presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats); presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes); + presenterDesc.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT; if (m_presenter->recreateSwapChain(presenterDesc) != VK_SUCCESS) throw DxvkError("D3D11SwapChain: Failed to recreate swap chain"); @@ -419,6 +420,7 @@ namespace dxvk { presenterDesc.imageCount = PickImageCount(m_desc.BufferCount + 1); presenterDesc.numFormats = PickFormats(m_desc.Format, presenterDesc.formats); presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes); + presenterDesc.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT; m_presenter = new vk::Presenter(m_window, m_device->adapter()->vki(), diff --git a/src/vulkan/vulkan_presenter.cpp b/src/vulkan/vulkan_presenter.cpp index fe247f291..ab604bd4b 100644 --- a/src/vulkan/vulkan_presenter.cpp +++ b/src/vulkan/vulkan_presenter.cpp @@ -119,10 +119,10 @@ namespace dxvk::vk { return status; } - if ((status = getSupportedFormats(formats)) != VK_SUCCESS) + if ((status = getSupportedFormats(formats, desc)) != VK_SUCCESS) return status; - if ((status = getSupportedPresentModes(modes)) != VK_SUCCESS) + if ((status = getSupportedPresentModes(modes, desc)) != VK_SUCCESS) return status; // Select actual swap chain properties and create swap chain @@ -131,6 +131,11 @@ namespace dxvk::vk { m_info.imageExtent = pickImageExtent(caps, desc.imageExtent); m_info.imageCount = pickImageCount(caps, m_info.presentMode, desc.imageCount); + VkSurfaceFullScreenExclusiveInfoEXT fullScreenInfo; + fullScreenInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + fullScreenInfo.pNext = nullptr; + fullScreenInfo.fullScreenExclusive = desc.fullScreenExclusive; + VkSwapchainCreateInfoKHR swapInfo; swapInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapInfo.pNext = nullptr; @@ -152,12 +157,16 @@ namespace dxvk::vk { swapInfo.clipped = VK_TRUE; swapInfo.oldSwapchain = VK_NULL_HANDLE; + if (m_device.features.fullScreenExclusive) + swapInfo.pNext = &fullScreenInfo; + Logger::info(str::format( "Presenter: Actual swap chain properties:" "\n Format: ", m_info.format.format, "\n Present mode: ", m_info.presentMode, "\n Buffer size: ", m_info.imageExtent.width, "x", m_info.imageExtent.height, - "\n Image count: ", m_info.imageCount)); + "\n Image count: ", m_info.imageCount, + "\n Exclusive FS: ", desc.fullScreenExclusive)); if ((status = m_vkd->vkCreateSwapchainKHR(m_vkd->device(), &swapInfo, nullptr, &m_swapchain)) != VK_SUCCESS) @@ -229,35 +238,89 @@ namespace dxvk::vk { } - VkResult Presenter::getSupportedFormats(std::vector& formats) { + VkResult Presenter::getSupportedFormats(std::vector& formats, const PresenterDesc& desc) { uint32_t numFormats = 0; - VkResult status = m_vki->vkGetPhysicalDeviceSurfaceFormatsKHR( - m_device.adapter, m_surface, &numFormats, nullptr); + VkSurfaceFullScreenExclusiveInfoEXT fullScreenInfo; + fullScreenInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + fullScreenInfo.pNext = nullptr; + fullScreenInfo.fullScreenExclusive = desc.fullScreenExclusive; + + VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo; + surfaceInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; + surfaceInfo.pNext = &fullScreenInfo; + surfaceInfo.surface = m_surface; + + VkResult status; + + if (m_device.features.fullScreenExclusive) { + status = m_vki->vkGetPhysicalDeviceSurfaceFormats2KHR( + m_device.adapter, &surfaceInfo, &numFormats, nullptr); + } else { + status = m_vki->vkGetPhysicalDeviceSurfaceFormatsKHR( + m_device.adapter, m_surface, &numFormats, nullptr); + } if (status != VK_SUCCESS) return status; formats.resize(numFormats); - return m_vki->vkGetPhysicalDeviceSurfaceFormatsKHR( - m_device.adapter, m_surface, &numFormats, formats.data()); + if (m_device.features.fullScreenExclusive) { + std::vector tmpFormats(numFormats, + { VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR, nullptr, VkSurfaceFormatKHR() }); + + status = m_vki->vkGetPhysicalDeviceSurfaceFormats2KHR( + m_device.adapter, &surfaceInfo, &numFormats, tmpFormats.data()); + + for (uint32_t i = 0; i < numFormats; i++) + formats[i] = tmpFormats[i].surfaceFormat; + } else { + status = m_vki->vkGetPhysicalDeviceSurfaceFormatsKHR( + m_device.adapter, m_surface, &numFormats, formats.data()); + } + + return status; } - VkResult Presenter::getSupportedPresentModes(std::vector& modes) { + VkResult Presenter::getSupportedPresentModes(std::vector& modes, const PresenterDesc& desc) { uint32_t numModes = 0; - VkResult status = m_vki->vkGetPhysicalDeviceSurfacePresentModesKHR( - m_device.adapter, m_surface, &numModes, nullptr); + VkSurfaceFullScreenExclusiveInfoEXT fullScreenInfo; + fullScreenInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT; + fullScreenInfo.pNext = nullptr; + fullScreenInfo.fullScreenExclusive = desc.fullScreenExclusive; + + VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo; + surfaceInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; + surfaceInfo.pNext = &fullScreenInfo; + surfaceInfo.surface = m_surface; + + VkResult status; + + if (m_device.features.fullScreenExclusive) { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModes2EXT( + m_device.adapter, &surfaceInfo, &numModes, nullptr); + } else { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModesKHR( + m_device.adapter, m_surface, &numModes, nullptr); + } if (status != VK_SUCCESS) return status; modes.resize(numModes); - return m_vki->vkGetPhysicalDeviceSurfacePresentModesKHR( - m_device.adapter, m_surface, &numModes, modes.data()); + if (m_device.features.fullScreenExclusive) { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModes2EXT( + m_device.adapter, &surfaceInfo, &numModes, modes.data()); + } else { + status = m_vki->vkGetPhysicalDeviceSurfacePresentModesKHR( + m_device.adapter, m_surface, &numModes, modes.data()); + } + + return status; } diff --git a/src/vulkan/vulkan_presenter.h b/src/vulkan/vulkan_presenter.h index f3b0d7b95..3211c075e 100644 --- a/src/vulkan/vulkan_presenter.h +++ b/src/vulkan/vulkan_presenter.h @@ -26,7 +26,7 @@ namespace dxvk::vk { VkSurfaceFormatKHR formats[4]; uint32_t numPresentModes; VkPresentModeKHR presentModes[4]; - VkFullScreenExclusiveEXT fullscreenExclusive; + VkFullScreenExclusiveEXT fullScreenExclusive; }; /** @@ -196,10 +196,12 @@ namespace dxvk::vk { uint32_t m_frameIndex = 0; VkResult getSupportedFormats( - std::vector& formats); + std::vector& formats, + const PresenterDesc& desc); VkResult getSupportedPresentModes( - std::vector& modes); + std::vector& modes, + const PresenterDesc& desc); VkResult getSwapImages( std::vector& images);