- move swapchain and the presentation related synchronization objects out of VulkanDevice

This commit is contained in:
Magnus Norddahl 2019-03-14 23:33:19 +01:00
parent 9b207b8fe6
commit 836938440c
7 changed files with 57 additions and 93 deletions

View file

@ -408,7 +408,7 @@ void VkPostprocess::RenderEffect(const FString &name)
if (step.Output.Type == PPTextureType::PPTexture) if (step.Output.Type == PPTextureType::PPTexture)
key.OutputFormat = mTextures[step.Output.Texture]->Format; key.OutputFormat = mTextures[step.Output.Texture]->Format;
else if (step.Output.Type == PPTextureType::SwapChain) else if (step.Output.Type == PPTextureType::SwapChain)
key.OutputFormat = GetVulkanFrameBuffer()->device->swapChain->swapChainFormat.format; key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format;
else else
key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT; key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
@ -516,9 +516,9 @@ VulkanFramebuffer *VkPostprocess::GetOutput(VkPPRenderPassSetup *passSetup, cons
} }
else else
{ {
view = fb->device->swapChain->swapChainImageViews[fb->device->presentImageIndex]; view = fb->swapChain->swapChainImageViews[fb->presentImageIndex];
w = fb->device->swapChain->actualExtent.width; w = fb->swapChain->actualExtent.width;
h = fb->device->swapChain->actualExtent.height; h = fb->swapChain->actualExtent.height;
} }
auto &framebuffer = passSetup->Framebuffers[view]; auto &framebuffer = passSetup->Framebuffers[view];

View file

@ -43,7 +43,6 @@
#include "doomerrors.h" #include "doomerrors.h"
#include "gamedata/fonts/v_text.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_GetVulkanPlatformExtensions(unsigned int *count, const char **names);
bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface); bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface);
@ -51,8 +50,6 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface);
static std::vector<VulkanPhysicalDevice> AvailableDevices; static std::vector<VulkanPhysicalDevice> AvailableDevices;
static std::vector<VulkanCompatibleDevice> SupportedDevices; static std::vector<VulkanCompatibleDevice> SupportedDevices;
EXTERN_CVAR(Bool, vid_vsync);
CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{ {
Printf("This won't take effect until " GAMENAME " is restarted.\n"); Printf("This won't take effect until " GAMENAME " is restarted.\n");
@ -88,12 +85,6 @@ VulkanDevice::VulkanDevice()
SelectPhysicalDevice(); SelectPhysicalDevice();
CreateDevice(); CreateDevice();
CreateAllocator(); CreateAllocator();
int width, height;
I_GetVulkanDrawableSize(&width, &height);
swapChain = std::make_unique<VulkanSwapChain>(this, width, height, vid_vsync);
CreateSemaphores();
} }
catch (...) catch (...)
{ {
@ -202,44 +193,6 @@ void VulkanDevice::SelectPhysicalDevice()
transferFamily = SupportedDevices[selected].transferFamily; transferFamily = SupportedDevices[selected].transferFamily;
} }
void VulkanDevice::WindowResized()
{
int width, height;
I_GetVulkanDrawableSize(&width, &height);
swapChain.reset();
swapChain = std::make_unique<VulkanSwapChain>(this, width, height, vid_vsync);
}
void VulkanDevice::WaitPresent()
{
vkWaitForFences(device, 1, &renderFinishedFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
vkResetFences(device, 1, &renderFinishedFence->fence);
}
void VulkanDevice::BeginFrame()
{
VkResult result = vkAcquireNextImageKHR(device, swapChain->swapChain, std::numeric_limits<uint64_t>::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() void VulkanDevice::CreateAllocator()
{ {
VmaAllocatorCreateInfo allocinfo = {}; VmaAllocatorCreateInfo allocinfo = {};
@ -251,13 +204,6 @@ void VulkanDevice::CreateAllocator()
throw std::runtime_error("Unable to create allocator"); 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() void VulkanDevice::CreateDevice()
{ {
float queuePriority = 1.0f; float queuePriority = 1.0f;
@ -531,11 +477,6 @@ void VulkanDevice::ReleaseResources()
if (device) if (device)
vkDeviceWaitIdle(device); vkDeviceWaitIdle(device);
imageAvailableSemaphore.reset();
renderFinishedSemaphore.reset();
renderFinishedFence.reset();
swapChain.reset();
if (allocator) if (allocator)
vmaDestroyAllocator(allocator); vmaDestroyAllocator(allocator);

View file

@ -38,12 +38,6 @@ public:
VulkanDevice(); VulkanDevice();
~VulkanDevice(); ~VulkanDevice();
void WindowResized();
void WaitPresent();
void BeginFrame();
void PresentFrame();
void SetDebugObjectName(const char *name, uint64_t handle, VkObjectType type) void SetDebugObjectName(const char *name, uint64_t handle, VkObjectType type)
{ {
if (!DebugLayerActive) return; if (!DebugLayerActive) return;
@ -85,20 +79,12 @@ public:
int transferFamily = -1; int transferFamily = -1;
int presentFamily = -1; int presentFamily = -1;
std::unique_ptr<VulkanSwapChain> swapChain;
uint32_t presentImageIndex = 0;
std::unique_ptr<VulkanSemaphore> imageAvailableSemaphore;
std::unique_ptr<VulkanSemaphore> renderFinishedSemaphore;
std::unique_ptr<VulkanFence> renderFinishedFence;
private: private:
void CreateInstance(); void CreateInstance();
void CreateSurface(); void CreateSurface();
void SelectPhysicalDevice(); void SelectPhysicalDevice();
void CreateDevice(); void CreateDevice();
void CreateAllocator(); void CreateAllocator();
void CreateSemaphores();
void ReleaseResources(); void ReleaseResources();
static bool CheckFeatures(const VkPhysicalDeviceFeatures &f); static bool CheckFeatures(const VkPhysicalDeviceFeatures &f);

View file

@ -74,6 +74,12 @@ VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevi
Super(hMonitor, fullscreen) Super(hMonitor, fullscreen)
{ {
device = dev; device = dev;
swapChain = std::make_unique<VulkanSwapChain>(device);
mSwapChainImageAvailableSemaphore.reset(new VulkanSemaphore(device));
mRenderFinishedSemaphore.reset(new VulkanSemaphore(device));
mRenderFinishedFence.reset(new VulkanFence(device));
InitPalette(); InitPalette();
} }
@ -150,12 +156,16 @@ void VulkanFrameBuffer::Update()
int newHeight = GetClientHeight(); int newHeight = GetClientHeight();
if (lastSwapWidth != newWidth || lastSwapHeight != newHeight) if (lastSwapWidth != newWidth || lastSwapHeight != newHeight)
{ {
device->WindowResized(); swapChain.reset();
swapChain = std::make_unique<VulkanSwapChain>(device);
lastSwapWidth = newWidth; lastSwapWidth = newWidth;
lastSwapHeight = newHeight; lastSwapHeight = newHeight;
} }
device->BeginFrame(); VkResult result = vkAcquireNextImageKHR(device->device, swapChain->swapChain, std::numeric_limits<uint64_t>::max(), mSwapChainImageAvailableSemaphore->semaphore, VK_NULL_HANDLE, &presentImageIndex);
if (result != VK_SUCCESS)
throw std::runtime_error("Failed to acquire next image!");
GetPostprocess()->SetActiveRenderTarget(); GetPostprocess()->SetActiveRenderTarget();
@ -173,8 +183,21 @@ void VulkanFrameBuffer::Update()
Finish.Reset(); Finish.Reset();
Finish.Clock(); 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<uint64_t>::max());
vkResetFences(device->device, 1, &mRenderFinishedFence->fence);
mDrawCommands.reset(); mDrawCommands.reset();
mUploadCommands.reset(); mUploadCommands.reset();
@ -205,7 +228,7 @@ void VulkanFrameBuffer::SubmitCommands(bool finish)
I_FatalError("Failed to submit command buffer! Error %d\n", result); I_FatalError("Failed to submit command buffer! Error %d\n", result);
// Wait for upload commands to finish, then submit render commands // 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 }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = finish ? 2 : 1; submitInfo.waitSemaphoreCount = finish ? 2 : 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
@ -213,14 +236,14 @@ void VulkanFrameBuffer::SubmitCommands(bool finish)
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &mDrawCommands->buffer; submitInfo.pCommandBuffers = &mDrawCommands->buffer;
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &device->renderFinishedSemaphore->semaphore; submitInfo.pSignalSemaphores = &mRenderFinishedSemaphore->semaphore;
result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, device->renderFinishedFence->fence); result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, mRenderFinishedFence->fence);
if (result < VK_SUCCESS) if (result < VK_SUCCESS)
I_FatalError("Failed to submit command buffer! Error %d\n", result); I_FatalError("Failed to submit command buffer! Error %d\n", result);
} }
else else
{ {
VkSemaphore waitSemaphores[] = { device->imageAvailableSemaphore->semaphore }; VkSemaphore waitSemaphores[] = { mSwapChainImageAvailableSemaphore->semaphore };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
VkSubmitInfo submitInfo = {}; VkSubmitInfo submitInfo = {};
@ -231,16 +254,16 @@ void VulkanFrameBuffer::SubmitCommands(bool finish)
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &mDrawCommands->buffer; submitInfo.pCommandBuffers = &mDrawCommands->buffer;
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &device->renderFinishedSemaphore->semaphore; submitInfo.pSignalSemaphores = &mRenderFinishedSemaphore->semaphore;
VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, device->renderFinishedFence->fence); VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, mRenderFinishedFence->fence);
if (result < VK_SUCCESS) if (result < VK_SUCCESS)
I_FatalError("Failed to submit command buffer! Error %d\n", result); I_FatalError("Failed to submit command buffer! Error %d\n", result);
} }
if (!finish) if (!finish)
{ {
vkWaitForFences(device->device, 1, &device->renderFinishedFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max()); vkWaitForFences(device->device, 1, &mRenderFinishedFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
vkResetFences(device->device, 1, &device->renderFinishedFence->fence); vkResetFences(device->device, 1, &mRenderFinishedFence->fence);
mDrawCommands.reset(); mDrawCommands.reset();
mUploadCommands.reset(); mUploadCommands.reset();
mFrameDeleteList.clear(); mFrameDeleteList.clear();
@ -570,9 +593,10 @@ uint32_t VulkanFrameBuffer::GetCaps()
void VulkanFrameBuffer::SetVSync(bool vsync) void VulkanFrameBuffer::SetVSync(bool vsync)
{ {
if (device->swapChain->vsync != vsync) if (swapChain->vsync != vsync)
{ {
device->WindowResized(); swapChain.reset();
swapChain = std::make_unique<VulkanSwapChain>(device);
} }
} }

View file

@ -22,6 +22,8 @@ class VulkanFrameBuffer : public SystemBaseFrameBuffer
public: public:
VulkanDevice *device; VulkanDevice *device;
std::unique_ptr<VulkanSwapChain> swapChain;
uint32_t presentImageIndex = 0;
VulkanCommandBuffer *GetUploadCommands(); VulkanCommandBuffer *GetUploadCommands();
VulkanCommandBuffer *GetDrawCommands(); VulkanCommandBuffer *GetDrawCommands();
@ -101,6 +103,10 @@ private:
std::unique_ptr<VulkanSemaphore> mUploadSemaphore; std::unique_ptr<VulkanSemaphore> mUploadSemaphore;
std::unique_ptr<VkRenderState> mRenderState; std::unique_ptr<VkRenderState> mRenderState;
std::unique_ptr<VulkanSemaphore> mSwapChainImageAvailableSemaphore;
std::unique_ptr<VulkanSemaphore> mRenderFinishedSemaphore;
std::unique_ptr<VulkanFence> mRenderFinishedFence;
VkRenderBuffers *mActiveRenderBuffers = nullptr; VkRenderBuffers *mActiveRenderBuffers = nullptr;
int lastSwapWidth = 0; int lastSwapWidth = 0;

View file

@ -3,13 +3,20 @@
#include "c_cvars.h" #include "c_cvars.h"
#include "version.h" #include "version.h"
EXTERN_CVAR(Bool, vid_vsync);
CUSTOM_CVAR(Bool, vk_hdr, false, /*CVAR_ARCHIVE | CVAR_GLOBALCONFIG |*/ CVAR_NOINITCALL) CUSTOM_CVAR(Bool, vk_hdr, false, /*CVAR_ARCHIVE | CVAR_GLOBALCONFIG |*/ CVAR_NOINITCALL)
{ {
Printf("This won't take effect until " GAMENAME " is restarted.\n"); 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; VkSurfaceCapabilitiesKHR surfaceCapabilities;
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities); VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)

View file

@ -5,7 +5,7 @@
class VulkanSwapChain class VulkanSwapChain
{ {
public: public:
VulkanSwapChain(VulkanDevice *device, int width, int height, bool vsync); VulkanSwapChain(VulkanDevice *device);
~VulkanSwapChain(); ~VulkanSwapChain();
bool vsync; bool vsync;