[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.
This commit is contained in:
Bill Currie 2022-09-26 13:04:56 +09:00
parent 22276ad356
commit 1d50940c2a
7 changed files with 87 additions and 22 deletions

View file

@ -44,6 +44,7 @@ typedef struct qfv_renderpass_s {
struct qfv_imageset_s *attachment_images; struct qfv_imageset_s *attachment_images;
struct qfv_imageviewset_s *attachment_views; struct qfv_imageviewset_s *attachment_views;
VkDeviceMemory attachmentMemory; VkDeviceMemory attachmentMemory;
size_t attachmentMemory_size;
qfv_framebufferset_t *framebuffers; qfv_framebufferset_t *framebuffers;
VkViewport viewport; VkViewport viewport;

View file

@ -81,6 +81,8 @@ typedef struct vulkan_ctx_s {
size_t curFrame; size_t curFrame;
vulkan_frameset_t frames; vulkan_frameset_t frames;
qfv_renderpassset_t renderPasses; qfv_renderpassset_t renderPasses;
//FIXME for resize, but should be a set
struct qfv_renderpass_s *main_renderpass;
struct qfv_capture_s *capture; struct qfv_capture_s *capture;
void (*capture_callback) (const byte *data, int width, int height); void (*capture_callback) (const byte *data, int width, int height);

View file

@ -293,9 +293,32 @@ vulkan_begin_frame (void)
__auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame];
dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000);
QFV_AcquireNextImage (vulkan_ctx->swapchain, if (!QFV_AcquireNextImage (vulkan_ctx->swapchain,
frame->imageAvailableSemaphore, frame->imageAvailableSemaphore,
0, &imageIndex); 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; vulkan_ctx->swapImageIndex = imageIndex;
} }

View file

@ -8,7 +8,9 @@
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/mathlib.h" #include "QF/mathlib.h"
#include "QF/va.h"
#include "QF/Vulkan/debug.h"
#include "QF/Vulkan/device.h" #include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h" #include "QF/Vulkan/image.h"
#include "QF/Vulkan/instance.h" #include "QF/Vulkan/instance.h"

View file

@ -180,4 +180,5 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx)
&output, main_draw); &output, main_draw);
rp->order = QFV_rp_main; rp->order = QFV_rp_main;
DARRAY_APPEND (&ctx->renderPasses, rp); DARRAY_APPEND (&ctx->renderPasses, rp);
ctx->main_renderpass = rp;
} }

View file

@ -74,10 +74,24 @@ get_image_size (VkImage image, qfv_device_t *device)
return size; 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 void
Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
__auto_type rp = renderpass; __auto_type rp = renderpass;
plitem_t *item = get_rp_item (ctx, rp, "images"); plitem_t *item = get_rp_item (ctx, rp, "images");
@ -85,19 +99,44 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass)
return; 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); __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef);
rp->attachment_images = images; rp->attachment_images = images;
size_t memSize = 0; size_t memSize = 0;
for (size_t i = 0; i < images->size; i++) { for (size_t i = 0; i < images->size; i++) {
memSize += get_image_size (images->a[i], device); memSize += get_image_size (images->a[i], device);
} }
VkDeviceMemory mem; VkDeviceMemory mem = rp->attachmentMemory;
mem = QFV_AllocImageMemory (device, images->a[0], if (memSize > rp->attachmentMemory_size) {
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, if (rp->attachmentMemory) {
memSize, 0); dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0);
rp->attachmentMemory = mem; }
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, rp->attachmentMemory_size = memSize;
mem, "memory:framebuffers"); 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; size_t offset = 0;
for (size_t i = 0; i < images->size; i++) { for (size_t i = 0; i < images->size; i++) {
QFV_BindImageMemory (device, images->a[i], mem, offset); 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 * qfv_renderpass_t *
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name,
qfv_output_t *output, qfv_draw_t draw) qfv_output_t *output, qfv_draw_t draw)

View file

@ -280,7 +280,16 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx)
{ {
VkSwapchainKHR old_swapchain = 0; VkSwapchainKHR old_swapchain = 0;
if (ctx->swapchain) { 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; 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); free (ctx->swapchain);
} }
ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain);