From 1d50940c2a61b4e1c0bed656c7c19bc511d3f167 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 13:04:56 +0900 Subject: [PATCH] [vulkan] Implement window resize support There's a problem with screenshot capture in that the image is sheared after window resize, but the screen view looks good, and vulkan is happy with the state changes. --- include/QF/Vulkan/qf_renderpass.h | 1 + include/vid_vulkan.h | 2 + libs/video/renderer/vid_render_vulkan.c | 29 ++++++++- libs/video/renderer/vulkan/swapchain.c | 2 + libs/video/renderer/vulkan/vulkan_main.c | 1 + .../video/renderer/vulkan/vulkan_renderpass.c | 65 +++++++++++++------ .../video/renderer/vulkan/vulkan_vid_common.c | 9 +++ 7 files changed, 87 insertions(+), 22 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index d459f8d99..98a178cf3 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -44,6 +44,7 @@ typedef struct qfv_renderpass_s { struct qfv_imageset_s *attachment_images; struct qfv_imageviewset_s *attachment_views; VkDeviceMemory attachmentMemory; + size_t attachmentMemory_size; qfv_framebufferset_t *framebuffers; VkViewport viewport; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 89e888d2e..709755538 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -81,6 +81,8 @@ typedef struct vulkan_ctx_s { size_t curFrame; vulkan_frameset_t frames; qfv_renderpassset_t renderPasses; + //FIXME for resize, but should be a set + struct qfv_renderpass_s *main_renderpass; struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 59a038056..3ad5d3f82 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -293,9 +293,32 @@ vulkan_begin_frame (void) __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); - QFV_AcquireNextImage (vulkan_ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex); + if (!QFV_AcquireNextImage (vulkan_ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex)) { + QFV_DeviceWaitIdle (device); + if (vulkan_ctx->capture) { + QFV_DestroyCapture (vulkan_ctx->capture); + } + Vulkan_CreateSwapchain (vulkan_ctx); + Vulkan_CreateCapture (vulkan_ctx); + + //FIXME + qfv_output_t output = { + .extent = vulkan_ctx->swapchain->extent, + .view = vulkan_ctx->swapchain->imageViews->a[0], + .format = vulkan_ctx->swapchain->format, + .view_list = vulkan_ctx->swapchain->imageViews->a, + }; + vulkan_ctx->main_renderpass->viewport.width = output.extent.width; + vulkan_ctx->main_renderpass->viewport.height = output.extent.height; + vulkan_ctx->main_renderpass->scissor.extent = output.extent; + vulkan_ctx->output = output; + Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->main_renderpass); + QFV_AcquireNextImage (vulkan_ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex); + } vulkan_ctx->swapImageIndex = imageIndex; } diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index d55c5e4eb..a2a962409 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -8,7 +8,9 @@ #include "QF/cvar.h" #include "QF/mathlib.h" +#include "QF/va.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 4098a4336..877e45d03 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -180,4 +180,5 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) &output, main_draw); rp->order = QFV_rp_main; DARRAY_APPEND (&ctx->renderPasses, rp); + ctx->main_renderpass = rp; } diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 2b53e83ae..6a72b447a 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -74,10 +74,24 @@ get_image_size (VkImage image, qfv_device_t *device) return size; } +static void +destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < rp->framebuffers->size; i++) { + dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); + } + free (rp->framebuffers); + rp->framebuffers = 0; +} + void Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; __auto_type rp = renderpass; plitem_t *item = get_rp_item (ctx, rp, "images"); @@ -85,19 +99,44 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) return; } + if (renderpass->framebuffers) { + destroy_framebuffers (ctx, renderpass); + } + if (rp->attachment_views) { + for (size_t i = 0; i < rp->attachment_views->size; i++) { + dfunc->vkDestroyImageView (device->dev, + rp->attachment_views->a[i], 0); + } + free (rp->attachment_views); + rp->attachment_views = 0; + } + if (rp->attachment_images) { + for (size_t i = 0; i < rp->attachment_images->size; i++) { + dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); + } + free (rp->attachment_images); + rp->attachment_images = 0; + } + __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); rp->attachment_images = images; size_t memSize = 0; for (size_t i = 0; i < images->size; i++) { memSize += get_image_size (images->a[i], device); } - VkDeviceMemory mem; - mem = QFV_AllocImageMemory (device, images->a[0], - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - memSize, 0); - rp->attachmentMemory = mem; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mem, "memory:framebuffers"); + VkDeviceMemory mem = rp->attachmentMemory; + if (memSize > rp->attachmentMemory_size) { + if (rp->attachmentMemory) { + dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); + } + rp->attachmentMemory_size = memSize; + mem = QFV_AllocImageMemory (device, images->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memSize, 0); + rp->attachmentMemory = mem; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, "memory:framebuffers"); + } size_t offset = 0; for (size_t i = 0; i < images->size; i++) { QFV_BindImageMemory (device, images->a[i], mem, offset); @@ -179,18 +218,6 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } } -static void -destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < rp->framebuffers->size; i++) { - dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); - } - free (rp->framebuffers); -} - qfv_renderpass_t * Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, qfv_output_t *output, qfv_draw_t draw) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index bc3036736..a62e84f58 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -280,7 +280,16 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) { VkSwapchainKHR old_swapchain = 0; if (ctx->swapchain) { + //FIXME this shouldn't be here + qfv_device_t *device = ctx->swapchain->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; old_swapchain = ctx->swapchain->swapchain; + for (size_t i = 0; i < ctx->swapchain->imageViews->size; i++) { + dfunc->vkDestroyImageView(dev, ctx->swapchain->imageViews->a[i], 0); + } + free (ctx->swapchain->images); + free (ctx->swapchain->imageViews); free (ctx->swapchain); } ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain);