From 836938440c735c48c2bb5425b33e6a33d087369a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 14 Mar 2019 23:33:19 +0100 Subject: [PATCH] - move swapchain and the presentation related synchronization objects out of VulkanDevice --- .../vulkan/renderer/vk_postprocess.cpp | 8 +-- src/rendering/vulkan/system/vk_device.cpp | 59 ------------------- src/rendering/vulkan/system/vk_device.h | 14 ----- .../vulkan/system/vk_framebuffer.cpp | 52 +++++++++++----- src/rendering/vulkan/system/vk_framebuffer.h | 6 ++ src/rendering/vulkan/system/vk_swapchain.cpp | 9 ++- src/rendering/vulkan/system/vk_swapchain.h | 2 +- 7 files changed, 57 insertions(+), 93 deletions(-) diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index a0089afe00..7c061a95c7 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -408,7 +408,7 @@ void VkPostprocess::RenderEffect(const FString &name) if (step.Output.Type == PPTextureType::PPTexture) key.OutputFormat = mTextures[step.Output.Texture]->Format; else if (step.Output.Type == PPTextureType::SwapChain) - key.OutputFormat = GetVulkanFrameBuffer()->device->swapChain->swapChainFormat.format; + key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format; else key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT; @@ -516,9 +516,9 @@ VulkanFramebuffer *VkPostprocess::GetOutput(VkPPRenderPassSetup *passSetup, cons } else { - view = fb->device->swapChain->swapChainImageViews[fb->device->presentImageIndex]; - w = fb->device->swapChain->actualExtent.width; - h = fb->device->swapChain->actualExtent.height; + view = fb->swapChain->swapChainImageViews[fb->presentImageIndex]; + w = fb->swapChain->actualExtent.width; + h = fb->swapChain->actualExtent.height; } auto &framebuffer = passSetup->Framebuffers[view]; diff --git a/src/rendering/vulkan/system/vk_device.cpp b/src/rendering/vulkan/system/vk_device.cpp index 57877ac0a7..30aeeda7bd 100644 --- a/src/rendering/vulkan/system/vk_device.cpp +++ b/src/rendering/vulkan/system/vk_device.cpp @@ -43,7 +43,6 @@ #include "doomerrors.h" #include "gamedata/fonts/v_text.h" -void I_GetVulkanDrawableSize(int *width, int *height); bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names); bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface); @@ -51,8 +50,6 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface); static std::vector AvailableDevices; static std::vector SupportedDevices; -EXTERN_CVAR(Bool, vid_vsync); - CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { Printf("This won't take effect until " GAMENAME " is restarted.\n"); @@ -88,12 +85,6 @@ VulkanDevice::VulkanDevice() SelectPhysicalDevice(); CreateDevice(); CreateAllocator(); - - int width, height; - I_GetVulkanDrawableSize(&width, &height); - swapChain = std::make_unique(this, width, height, vid_vsync); - - CreateSemaphores(); } catch (...) { @@ -202,44 +193,6 @@ void VulkanDevice::SelectPhysicalDevice() transferFamily = SupportedDevices[selected].transferFamily; } -void VulkanDevice::WindowResized() -{ - int width, height; - I_GetVulkanDrawableSize(&width, &height); - - swapChain.reset(); - swapChain = std::make_unique(this, width, height, vid_vsync); -} - -void VulkanDevice::WaitPresent() -{ - vkWaitForFences(device, 1, &renderFinishedFence->fence, VK_TRUE, std::numeric_limits::max()); - vkResetFences(device, 1, &renderFinishedFence->fence); -} - -void VulkanDevice::BeginFrame() -{ - VkResult result = vkAcquireNextImageKHR(device, swapChain->swapChain, std::numeric_limits::max(), imageAvailableSemaphore->semaphore, VK_NULL_HANDLE, &presentImageIndex); - if (result != VK_SUCCESS) - throw std::runtime_error("Failed to acquire next image!"); -} - -void VulkanDevice::PresentFrame() -{ - VkSemaphore waitSemaphores[] = { renderFinishedSemaphore->semaphore }; - VkSwapchainKHR swapChains[] = { swapChain->swapChain }; - - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = waitSemaphores; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = swapChains; - presentInfo.pImageIndices = &presentImageIndex; - presentInfo.pResults = nullptr; - vkQueuePresentKHR(presentQueue, &presentInfo); -} - void VulkanDevice::CreateAllocator() { VmaAllocatorCreateInfo allocinfo = {}; @@ -251,13 +204,6 @@ void VulkanDevice::CreateAllocator() throw std::runtime_error("Unable to create allocator"); } -void VulkanDevice::CreateSemaphores() -{ - imageAvailableSemaphore.reset(new VulkanSemaphore(this)); - renderFinishedSemaphore.reset(new VulkanSemaphore(this)); - renderFinishedFence.reset(new VulkanFence(this)); -} - void VulkanDevice::CreateDevice() { float queuePriority = 1.0f; @@ -531,11 +477,6 @@ void VulkanDevice::ReleaseResources() if (device) vkDeviceWaitIdle(device); - imageAvailableSemaphore.reset(); - renderFinishedSemaphore.reset(); - renderFinishedFence.reset(); - swapChain.reset(); - if (allocator) vmaDestroyAllocator(allocator); diff --git a/src/rendering/vulkan/system/vk_device.h b/src/rendering/vulkan/system/vk_device.h index 9f880d33e3..ce158332e3 100644 --- a/src/rendering/vulkan/system/vk_device.h +++ b/src/rendering/vulkan/system/vk_device.h @@ -38,12 +38,6 @@ public: VulkanDevice(); ~VulkanDevice(); - void WindowResized(); - void WaitPresent(); - - void BeginFrame(); - void PresentFrame(); - void SetDebugObjectName(const char *name, uint64_t handle, VkObjectType type) { if (!DebugLayerActive) return; @@ -85,20 +79,12 @@ public: int transferFamily = -1; int presentFamily = -1; - std::unique_ptr swapChain; - uint32_t presentImageIndex = 0; - - std::unique_ptr imageAvailableSemaphore; - std::unique_ptr renderFinishedSemaphore; - std::unique_ptr renderFinishedFence; - private: void CreateInstance(); void CreateSurface(); void SelectPhysicalDevice(); void CreateDevice(); void CreateAllocator(); - void CreateSemaphores(); void ReleaseResources(); static bool CheckFeatures(const VkPhysicalDeviceFeatures &f); diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 5001abe274..a876cec1e4 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -74,6 +74,12 @@ VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevi Super(hMonitor, fullscreen) { device = dev; + + swapChain = std::make_unique(device); + mSwapChainImageAvailableSemaphore.reset(new VulkanSemaphore(device)); + mRenderFinishedSemaphore.reset(new VulkanSemaphore(device)); + mRenderFinishedFence.reset(new VulkanFence(device)); + InitPalette(); } @@ -150,12 +156,16 @@ void VulkanFrameBuffer::Update() int newHeight = GetClientHeight(); if (lastSwapWidth != newWidth || lastSwapHeight != newHeight) { - device->WindowResized(); + swapChain.reset(); + swapChain = std::make_unique(device); + lastSwapWidth = newWidth; lastSwapHeight = newHeight; } - device->BeginFrame(); + VkResult result = vkAcquireNextImageKHR(device->device, swapChain->swapChain, std::numeric_limits::max(), mSwapChainImageAvailableSemaphore->semaphore, VK_NULL_HANDLE, &presentImageIndex); + if (result != VK_SUCCESS) + throw std::runtime_error("Failed to acquire next image!"); GetPostprocess()->SetActiveRenderTarget(); @@ -173,8 +183,21 @@ void VulkanFrameBuffer::Update() Finish.Reset(); Finish.Clock(); - device->PresentFrame(); - device->WaitPresent(); + + VkSemaphore waitSemaphores[] = { mRenderFinishedSemaphore->semaphore }; + VkSwapchainKHR swapChains[] = { swapChain->swapChain }; + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = waitSemaphores; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &presentImageIndex; + presentInfo.pResults = nullptr; + vkQueuePresentKHR(device->presentQueue, &presentInfo); + + vkWaitForFences(device->device, 1, &mRenderFinishedFence->fence, VK_TRUE, std::numeric_limits::max()); + vkResetFences(device->device, 1, &mRenderFinishedFence->fence); mDrawCommands.reset(); mUploadCommands.reset(); @@ -205,7 +228,7 @@ void VulkanFrameBuffer::SubmitCommands(bool finish) I_FatalError("Failed to submit command buffer! Error %d\n", result); // Wait for upload commands to finish, then submit render commands - VkSemaphore waitSemaphores[] = { mUploadSemaphore->semaphore, device->imageAvailableSemaphore->semaphore }; + VkSemaphore waitSemaphores[] = { mUploadSemaphore->semaphore, mSwapChainImageAvailableSemaphore->semaphore }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = finish ? 2 : 1; submitInfo.pWaitSemaphores = waitSemaphores; @@ -213,14 +236,14 @@ void VulkanFrameBuffer::SubmitCommands(bool finish) submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &mDrawCommands->buffer; submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &device->renderFinishedSemaphore->semaphore; - result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, device->renderFinishedFence->fence); + submitInfo.pSignalSemaphores = &mRenderFinishedSemaphore->semaphore; + result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, mRenderFinishedFence->fence); if (result < VK_SUCCESS) I_FatalError("Failed to submit command buffer! Error %d\n", result); } else { - VkSemaphore waitSemaphores[] = { device->imageAvailableSemaphore->semaphore }; + VkSemaphore waitSemaphores[] = { mSwapChainImageAvailableSemaphore->semaphore }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkSubmitInfo submitInfo = {}; @@ -231,16 +254,16 @@ void VulkanFrameBuffer::SubmitCommands(bool finish) submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &mDrawCommands->buffer; submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = &device->renderFinishedSemaphore->semaphore; - VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, device->renderFinishedFence->fence); + submitInfo.pSignalSemaphores = &mRenderFinishedSemaphore->semaphore; + VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, mRenderFinishedFence->fence); if (result < VK_SUCCESS) I_FatalError("Failed to submit command buffer! Error %d\n", result); } if (!finish) { - vkWaitForFences(device->device, 1, &device->renderFinishedFence->fence, VK_TRUE, std::numeric_limits::max()); - vkResetFences(device->device, 1, &device->renderFinishedFence->fence); + vkWaitForFences(device->device, 1, &mRenderFinishedFence->fence, VK_TRUE, std::numeric_limits::max()); + vkResetFences(device->device, 1, &mRenderFinishedFence->fence); mDrawCommands.reset(); mUploadCommands.reset(); mFrameDeleteList.clear(); @@ -570,9 +593,10 @@ uint32_t VulkanFrameBuffer::GetCaps() void VulkanFrameBuffer::SetVSync(bool vsync) { - if (device->swapChain->vsync != vsync) + if (swapChain->vsync != vsync) { - device->WindowResized(); + swapChain.reset(); + swapChain = std::make_unique(device); } } diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 565012aa7f..68ea006ee0 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -22,6 +22,8 @@ class VulkanFrameBuffer : public SystemBaseFrameBuffer public: VulkanDevice *device; + std::unique_ptr swapChain; + uint32_t presentImageIndex = 0; VulkanCommandBuffer *GetUploadCommands(); VulkanCommandBuffer *GetDrawCommands(); @@ -101,6 +103,10 @@ private: std::unique_ptr mUploadSemaphore; std::unique_ptr mRenderState; + std::unique_ptr mSwapChainImageAvailableSemaphore; + std::unique_ptr mRenderFinishedSemaphore; + std::unique_ptr mRenderFinishedFence; + VkRenderBuffers *mActiveRenderBuffers = nullptr; int lastSwapWidth = 0; diff --git a/src/rendering/vulkan/system/vk_swapchain.cpp b/src/rendering/vulkan/system/vk_swapchain.cpp index 1b10cfdc9b..22473b9eeb 100644 --- a/src/rendering/vulkan/system/vk_swapchain.cpp +++ b/src/rendering/vulkan/system/vk_swapchain.cpp @@ -3,13 +3,20 @@ #include "c_cvars.h" #include "version.h" +EXTERN_CVAR(Bool, vid_vsync); + CUSTOM_CVAR(Bool, vk_hdr, false, /*CVAR_ARCHIVE | CVAR_GLOBALCONFIG |*/ CVAR_NOINITCALL) { Printf("This won't take effect until " GAMENAME " is restarted.\n"); } -VulkanSwapChain::VulkanSwapChain(VulkanDevice *device, int width, int height, bool vsync) : vsync(vsync), device(device) +void I_GetVulkanDrawableSize(int *width, int *height); + +VulkanSwapChain::VulkanSwapChain(VulkanDevice *device) : vsync(vid_vsync), device(device) { + int width, height; + I_GetVulkanDrawableSize(&width, &height); + VkSurfaceCapabilitiesKHR surfaceCapabilities; VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities); if (result != VK_SUCCESS) diff --git a/src/rendering/vulkan/system/vk_swapchain.h b/src/rendering/vulkan/system/vk_swapchain.h index 39fb9dfb63..ef33054221 100644 --- a/src/rendering/vulkan/system/vk_swapchain.h +++ b/src/rendering/vulkan/system/vk_swapchain.h @@ -5,7 +5,7 @@ class VulkanSwapChain { public: - VulkanSwapChain(VulkanDevice *device, int width, int height, bool vsync); + VulkanSwapChain(VulkanDevice *device); ~VulkanSwapChain(); bool vsync;