diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index 260324da..c1a8db85 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -25,6 +25,7 @@ namespace dxvk { m_options.preferredSurfaceFormat = { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; m_options.preferredPresentMode = VK_PRESENT_MODE_FIFO_KHR; m_options.preferredBufferSize = { 0u, 0u }; + m_options.preferredBufferCount = 0; // Samplers for presentation. We'll create one with point sampling that will // be used when the back buffer resolution matches the output resolution, and @@ -293,7 +294,7 @@ namespace dxvk { } - void DxgiVkPresenter::RecreateSwapchain(DXGI_FORMAT Format, BOOL Vsync, VkExtent2D WindowSize) { + void DxgiVkPresenter::RecreateSwapchain(DXGI_FORMAT Format, BOOL Vsync, VkExtent2D WindowSize, UINT BufferCount) { if (m_surface == nullptr) m_surface = CreateSurface(); @@ -301,6 +302,7 @@ namespace dxvk { options.preferredSurfaceFormat = PickSurfaceFormat(Format); options.preferredPresentMode = PickPresentMode(Vsync); options.preferredBufferSize = WindowSize; + options.preferredBufferCount = BufferCount; const bool doRecreate = options.preferredSurfaceFormat.format != m_options.preferredSurfaceFormat.format diff --git a/src/dxgi/dxgi_presenter.h b/src/dxgi/dxgi_presenter.h index 73e4e239..ca2918f5 100644 --- a/src/dxgi/dxgi_presenter.h +++ b/src/dxgi/dxgi_presenter.h @@ -105,11 +105,13 @@ namespace dxvk { * \param [in] Format New surface format * \param [in] Vsync Enable vertical sync * \param [in] WindowSize Window size + * \param [in] BufferCount Swap image count */ void RecreateSwapchain( DXGI_FORMAT Format, BOOL Vsync, - VkExtent2D WindowSize); + VkExtent2D WindowSize, + UINT BufferCount); /** * \brief Sets gamma curve diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index a9245d7c..999b0d35 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -272,12 +272,16 @@ namespace dxvk { std::lock_guard lockWin(m_lockWindow); std::lock_guard lockBuf(m_lockBuffer); + // Retrieve the number of back buffers. If this option + // was defined by the user, it overrides app settings. + uint32_t bufferCount = m_desc.BufferCount; + // Higher values are not allowed according to the Microsoft documentation: // // "1 through 4 - Synchronize presentation after the nth vertical blank." // https://msdn.microsoft.com/en-us/library/windows/desktop/bb174576(v=vs.85).aspx SyncInterval = std::min(SyncInterval, 4); - + try { // If in fullscreen mode, apply any updated gamma curve // if it has been changed since the last present call. @@ -298,7 +302,7 @@ namespace dxvk { // up vertical synchronization properly, but also apply // changes that were made to the window size even if the // Vulkan swap chain itself remains valid. - m_presenter->RecreateSwapchain(m_desc.Format, SyncInterval != 0, GetWindowSize()); + m_presenter->RecreateSwapchain(m_desc.Format, SyncInterval != 0, GetWindowSize(), bufferCount); m_presenter->PresentImage(SyncInterval, m_device->GetFrameSyncEvent()); return S_OK; } catch (const DxvkError& err) { diff --git a/src/dxvk/dxvk_surface.cpp b/src/dxvk/dxvk_surface.cpp index 20dc456b..f9f80b1a 100644 --- a/src/dxvk/dxvk_surface.cpp +++ b/src/dxvk/dxvk_surface.cpp @@ -87,12 +87,15 @@ namespace dxvk { uint32_t DxvkSurface::pickImageCount( const VkSurfaceCapabilitiesKHR& caps, - VkPresentModeKHR mode) const { + VkPresentModeKHR mode, + uint32_t preferred) const { uint32_t count = caps.minImageCount; - if (mode == VK_PRESENT_MODE_MAILBOX_KHR - || mode == VK_PRESENT_MODE_FIFO_KHR) - count += 1; + if (mode != VK_PRESENT_MODE_IMMEDIATE_KHR) + count = caps.minImageCount + 1; + + if (count < preferred) + count = preferred; if (count > caps.maxImageCount && caps.maxImageCount != 0) count = caps.maxImageCount; diff --git a/src/dxvk/dxvk_surface.h b/src/dxvk/dxvk_surface.h index 252f29b4..683be9fb 100644 --- a/src/dxvk/dxvk_surface.h +++ b/src/dxvk/dxvk_surface.h @@ -65,11 +65,13 @@ namespace dxvk { * * \param [in] caps Surface capabilities * \param [in] mode The present mode + * \param [in] preferred Preferred image count * \returns Suitable image count */ uint32_t pickImageCount( const VkSurfaceCapabilitiesKHR& caps, - VkPresentModeKHR mode) const; + VkPresentModeKHR mode, + uint32_t preferred) const; /** * \brief Picks a suitable image size for a swap chain diff --git a/src/dxvk/dxvk_swapchain.cpp b/src/dxvk/dxvk_swapchain.cpp index 25a80956..048d9b00 100644 --- a/src/dxvk/dxvk_swapchain.cpp +++ b/src/dxvk/dxvk_swapchain.cpp @@ -117,7 +117,7 @@ namespace dxvk { swapInfo.pNext = nullptr; swapInfo.flags = 0; swapInfo.surface = m_surface->handle(); - swapInfo.minImageCount = m_surface->pickImageCount(caps, mode); + swapInfo.minImageCount = m_surface->pickImageCount(caps, mode, m_properties.preferredBufferCount); swapInfo.imageFormat = fmt.format; swapInfo.imageColorSpace = fmt.colorSpace; swapInfo.imageExtent = m_surface->pickImageExtent(caps, m_properties.preferredBufferSize); diff --git a/src/dxvk/dxvk_swapchain.h b/src/dxvk/dxvk_swapchain.h index 97661d47..cf46b3e2 100644 --- a/src/dxvk/dxvk_swapchain.h +++ b/src/dxvk/dxvk_swapchain.h @@ -28,6 +28,7 @@ namespace dxvk { VkSurfaceFormatKHR preferredSurfaceFormat; VkPresentModeKHR preferredPresentMode; VkExtent2D preferredBufferSize; + uint32_t preferredBufferCount; };