diff --git a/src/d3d11/d3d11_swapchain.cpp b/src/d3d11/d3d11_swapchain.cpp index 7adcf0c9d..6a8a1ed99 100644 --- a/src/d3d11/d3d11_swapchain.cpp +++ b/src/d3d11/d3d11_swapchain.cpp @@ -387,12 +387,11 @@ namespace dxvk { return DXGI_STATUS_OCCLUDED; // Presentation semaphores and WSI swap chain image - PresenterInfo info = m_presenter->info(); PresenterSync sync; - uint32_t imageIndex = 0; + Rc backBuffer; - VkResult status = m_presenter->acquireNextImage(sync, imageIndex); + VkResult status = m_presenter->acquireNextImage(sync, backBuffer); while (status != VK_SUCCESS) { RecreateSwapChain(); @@ -400,8 +399,7 @@ namespace dxvk { if (!m_presenter->hasSwapChain()) return DXGI_STATUS_OCCLUDED; - info = m_presenter->info(); - status = m_presenter->acquireNextImage(sync, imageIndex); + status = m_presenter->acquireNextImage(sync, backBuffer); if (status == VK_SUBOPTIMAL_KHR) break; @@ -418,11 +416,21 @@ namespace dxvk { // have to synchronize with it first. m_presentStatus.result = VK_NOT_READY; + DxvkImageViewKey viewInfo = { }; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + viewInfo.format = backBuffer->info().format; + viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.mipIndex = 0u; + viewInfo.mipCount = 1u; + viewInfo.layerIndex = 0u; + viewInfo.layerCount = 1u; + immediateContext->EmitCs([ cPresentStatus = &m_presentStatus, cDevice = m_device, cBlitter = m_blitter, - cBackBuffer = m_imageViews.at(imageIndex), + cBackBuffer = backBuffer->createView(viewInfo), cSwapImage = GetBackBufferView(), cSync = sync, cHud = m_hud, @@ -507,8 +515,6 @@ namespace dxvk { if (vr) throw DxvkError(str::format("D3D11SwapChain: Failed to recreate swap chain: ", vr)); - - CreateRenderTargetViews(); } @@ -539,48 +545,6 @@ namespace dxvk { } - void D3D11SwapChain::CreateRenderTargetViews() { - PresenterInfo info = m_presenter->info(); - - m_imageViews.clear(); - m_imageViews.resize(info.imageCount); - - DxvkImageCreateInfo imageInfo; - imageInfo.type = VK_IMAGE_TYPE_2D; - imageInfo.format = info.format.format; - imageInfo.flags = 0; - imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; - imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 }; - imageInfo.numLayers = 1; - imageInfo.mipLevels = 1; - imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - imageInfo.stages = 0; - imageInfo.access = 0; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imageInfo.shared = VK_TRUE; - imageInfo.debugName = "Swap image"; - - DxvkImageViewKey viewInfo; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = info.format.format; - viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.mipIndex = 0; - viewInfo.mipCount = 1; - viewInfo.layerIndex = 0; - viewInfo.layerCount = 1; - - for (uint32_t i = 0; i < info.imageCount; i++) { - VkImage imageHandle = m_presenter->getImage(i).image; - - Rc image = m_device->importImage(imageInfo, - imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - m_imageViews[i] = image->createView(viewInfo); - } - } - - void D3D11SwapChain::CreateBackBuffers() { // Explicitly destroy current swap image before // creating a new one to free up resources diff --git a/src/d3d11/d3d11_swapchain.h b/src/d3d11/d3d11_swapchain.h index cffc60825..6766701f8 100644 --- a/src/d3d11/d3d11_swapchain.h +++ b/src/d3d11/d3d11_swapchain.h @@ -113,8 +113,6 @@ namespace dxvk { small_vector, 4> m_backBuffers; DxvkSubmitStatus m_presentStatus; - std::vector> m_imageViews; - uint64_t m_frameId = DXGI_MAX_SWAP_CHAIN_BUFFERS; uint32_t m_frameLatency = DefaultFrameLatency; uint32_t m_frameLatencyCap = 0; @@ -147,8 +145,6 @@ namespace dxvk { void CreatePresenter(); - void CreateRenderTargetViews(); - void CreateBackBuffers(); void CreateBlitter(); diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 3e2c42b00..8a08497d9 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -833,15 +833,15 @@ namespace dxvk { PresenterInfo info = m_wctx->presenter->info(); PresenterSync sync = { }; - uint32_t imageIndex = 0; + Rc backBuffer; - VkResult status = m_wctx->presenter->acquireNextImage(sync, imageIndex); + VkResult status = m_wctx->presenter->acquireNextImage(sync, backBuffer); while (status != VK_SUCCESS) { RecreateSwapChain(); info = m_wctx->presenter->info(); - status = m_wctx->presenter->acquireNextImage(sync, imageIndex); + status = m_wctx->presenter->acquireNextImage(sync, backBuffer); if (status == VK_SUBOPTIMAL_KHR) break; @@ -868,6 +868,16 @@ namespace dxvk { // have to synchronize with it first. m_presentStatus.result = VK_NOT_READY; + DxvkImageViewKey viewInfo; + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + viewInfo.format = backBuffer->info().format; + viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.mipIndex = 0u; + viewInfo.mipCount = 1u; + viewInfo.layerIndex = 0u; + viewInfo.layerCount = 1u; + m_parent->EmitCs([ cPresentStatus = &m_presentStatus, cDevice = m_device, @@ -876,7 +886,7 @@ namespace dxvk { cColorSpace = m_colorspace, cSrcView = swapImageView, cSrcRect = srcRect, - cDstView = m_wctx->imageViews.at(imageIndex), + cDstView = backBuffer->createView(viewInfo), cDstRect = dstRect, cRepeat = i, cSync = sync, @@ -948,8 +958,6 @@ namespace dxvk { if (vr) throw DxvkError(str::format("D3D9SwapChainEx: Failed to recreate swap chain: ", vr)); - - CreateRenderTargetViews(); } @@ -980,47 +988,6 @@ namespace dxvk { } - void D3D9SwapChainEx::CreateRenderTargetViews() { - PresenterInfo info = m_wctx->presenter->info(); - - m_wctx->imageViews.clear(); - m_wctx->imageViews.resize(info.imageCount); - - DxvkImageCreateInfo imageInfo; - imageInfo.type = VK_IMAGE_TYPE_2D; - imageInfo.format = info.format.format; - imageInfo.flags = 0; - imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; - imageInfo.extent = { info.imageExtent.width, info.imageExtent.height, 1 }; - imageInfo.numLayers = 1; - imageInfo.mipLevels = 1; - imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - imageInfo.stages = 0; - imageInfo.access = 0; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - imageInfo.shared = VK_TRUE; - - DxvkImageViewKey viewInfo; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = info.format.format; - viewInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - viewInfo.aspects = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.mipIndex = 0; - viewInfo.mipCount = 1; - viewInfo.layerIndex = 0; - viewInfo.layerCount = 1; - - for (uint32_t i = 0; i < info.imageCount; i++) { - VkImage imageHandle = m_wctx->presenter->getImage(i).image; - - Rc image = m_device->importImage(imageInfo, - imageHandle, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - m_wctx->imageViews[i] = image->createView(viewInfo); - } - } - - void D3D9SwapChainEx::DestroyBackBuffers() { for (auto& backBuffer : m_backBuffers) backBuffer->ClearContainer(); diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h index 9dfa56c10..1ae3c6b8a 100644 --- a/src/d3d9/d3d9_swapchain.h +++ b/src/d3d9/d3d9_swapchain.h @@ -52,7 +52,6 @@ namespace dxvk { struct D3D9WindowContext { Rc presenter; - std::vector> imageViews; uint64_t frameId = D3D9DeviceEx::MaxFrameLatency; Rc frameLatencySignal; @@ -199,8 +198,6 @@ namespace dxvk { void CreatePresenter(); - void CreateRenderTargetViews(); - HRESULT CreateBackBuffers( uint32_t NumBackBuffers, DWORD Flags); diff --git a/src/dxvk/dxvk_presenter.cpp b/src/dxvk/dxvk_presenter.cpp index 006219d65..a30f61dd6 100644 --- a/src/dxvk/dxvk_presenter.cpp +++ b/src/dxvk/dxvk_presenter.cpp @@ -51,12 +51,7 @@ namespace dxvk { } - PresenterImage Presenter::getImage(uint32_t index) const { - return m_images.at(index); - } - - - VkResult Presenter::acquireNextImage(PresenterSync& sync, uint32_t& index) { + VkResult Presenter::acquireNextImage(PresenterSync& sync, Rc& image) { PresenterSync& semaphores = m_semaphores.at(m_frameIndex); sync = semaphores; @@ -72,7 +67,7 @@ namespace dxvk { if (m_acquireStatus != VK_SUCCESS && m_acquireStatus != VK_SUBOPTIMAL_KHR) return m_acquireStatus; - index = m_imageIndex; + image = m_images.at(m_imageIndex); return m_acquireStatus; } @@ -362,25 +357,25 @@ namespace dxvk { // Update actual image count m_info.imageCount = images.size(); - m_images.resize(m_info.imageCount); for (uint32_t i = 0; i < m_info.imageCount; i++) { - m_images[i].image = images[i]; + std::string debugName = str::format("Vulkan swap image ", i); - VkImageViewCreateInfo viewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; - viewInfo.image = images[i]; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = m_info.format.format; - viewInfo.components = VkComponentMapping { - VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; - viewInfo.subresourceRange = { - VK_IMAGE_ASPECT_COLOR_BIT, - 0, 1, 0, 1 }; - - if ((status = m_vkd->vkCreateImageView(m_vkd->device(), - &viewInfo, nullptr, &m_images[i].view))) - return status; + DxvkImageCreateInfo imageInfo = { }; + imageInfo.type = VK_IMAGE_TYPE_2D; + imageInfo.format = swapInfo.imageFormat; + imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT; + imageInfo.extent = { swapInfo.imageExtent.width, swapInfo.imageExtent.height, 1u }; + imageInfo.numLayers = swapInfo.imageArrayLayers; + imageInfo.mipLevels = 1u; + imageInfo.usage = swapInfo.imageUsage; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + imageInfo.shared = VK_TRUE; + imageInfo.debugName = debugName.c_str(); + + m_images.push_back(m_device->importImage(imageInfo, images[i], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)); } // Create one set of semaphores per swap image, as well as a fence @@ -678,9 +673,6 @@ namespace dxvk { for (auto& sem : m_semaphores) waitForSwapchainFence(sem); - for (const auto& img : m_images) - m_vkd->vkDestroyImageView(m_vkd->device(), img.view, nullptr); - for (const auto& sem : m_semaphores) { m_vkd->vkDestroySemaphore(m_vkd->device(), sem.acquire, nullptr); m_vkd->vkDestroySemaphore(m_vkd->device(), sem.present, nullptr); diff --git a/src/dxvk/dxvk_presenter.h b/src/dxvk/dxvk_presenter.h index 82b9ed02d..324a8066a 100644 --- a/src/dxvk/dxvk_presenter.h +++ b/src/dxvk/dxvk_presenter.h @@ -16,6 +16,7 @@ #include "../vulkan/vulkan_loader.h" #include "dxvk_format.h" +#include "dxvk_image.h" namespace dxvk { @@ -51,14 +52,6 @@ namespace dxvk { uint32_t syncInterval; }; - /** - * \brief Swap image and view - */ - struct PresenterImage { - VkImage image = VK_NULL_HANDLE; - VkImageView view = VK_NULL_HANDLE; - }; - /** * \brief Presenter semaphores * @@ -108,16 +101,6 @@ namespace dxvk { */ PresenterInfo info() const; - /** - * \brief Retrieves image by index - * - * Can be used to create per-image objects. - * \param [in] index Image index - * \returns Image handle - */ - PresenterImage getImage( - uint32_t index) const; - /** * \brief Acquires next image * @@ -126,12 +109,12 @@ namespace dxvk { * must be recreated and a new image must * be acquired before proceeding. * \param [out] sync Synchronization semaphores - * \param [out] index Acquired image index + * \param [out] image Acquired swap chain image * \returns Status of the operation */ VkResult acquireNextImage( PresenterSync& sync, - uint32_t& index); + Rc& image); /** * \brief Presents current image @@ -222,32 +205,31 @@ namespace dxvk { private: - Rc m_device; - Rc m_signal; + Rc m_device; + Rc m_signal; - Rc m_vki; - Rc m_vkd; + Rc m_vki; + Rc m_vkd; - PresenterInfo m_info = { }; - PresenterSurfaceProc m_surfaceProc; + PresenterInfo m_info = { }; + PresenterSurfaceProc m_surfaceProc; - VkSurfaceKHR m_surface = VK_NULL_HANDLE; - VkSwapchainKHR m_swapchain = VK_NULL_HANDLE; + VkSurfaceKHR m_surface = VK_NULL_HANDLE; + VkSwapchainKHR m_swapchain = VK_NULL_HANDLE; - VkFullScreenExclusiveEXT m_fullscreenMode = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT; + VkFullScreenExclusiveEXT m_fullscreenMode = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT; - std::vector m_images; + std::vector> m_images; std::vector m_semaphores; std::vector m_dynamicModes; - uint32_t m_imageIndex = 0; - uint32_t m_frameIndex = 0; + uint32_t m_imageIndex = 0; + uint32_t m_frameIndex = 0; - VkResult m_acquireStatus = VK_NOT_READY; - - FpsLimiter m_fpsLimiter; + VkResult m_acquireStatus = VK_NOT_READY; + alignas(CACHE_LINE_SIZE) dxvk::mutex m_frameMutex; dxvk::condition_variable m_frameCond; dxvk::thread m_frameThread; @@ -255,6 +237,9 @@ namespace dxvk { std::atomic m_lastFrameId = { 0ull }; + alignas(CACHE_LINE_SIZE) + FpsLimiter m_fpsLimiter; + VkResult createSwapChain( const PresenterDesc& desc);