From 336057887524f5efdf8eafc758765ee0d9c8c9e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Nov 2022 22:23:59 +0900 Subject: [PATCH] [vulkan] Rework render pass setup This splits up render pass creation so that the creation of the various resources can be tailored to the needs of the actual render pass sub-system. In addition, it gets window resizing mostly working (just some problems with incorrect rendering). --- include/QF/Vulkan/qf_output.h | 6 +- include/QF/Vulkan/qf_renderpass.h | 32 ++- include/QF/Vulkan/qf_vid.h | 9 - libs/video/renderer/vid_render_vulkan.c | 17 +- libs/video/renderer/vulkan/rp_deferred.plist | 20 +- libs/video/renderer/vulkan/rp_output.plist | 41 --- libs/video/renderer/vulkan/swapchain.c | 6 + libs/video/renderer/vulkan/vulkan_lighting.c | 5 +- libs/video/renderer/vulkan/vulkan_main.c | 13 +- libs/video/renderer/vulkan/vulkan_output.c | 49 ++-- .../video/renderer/vulkan/vulkan_renderpass.c | 233 +++++++++++------- .../video/renderer/vulkan/vulkan_vid_common.c | 2 +- 12 files changed, 228 insertions(+), 205 deletions(-) diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index 478aae67a..94b969d42 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -36,7 +36,7 @@ typedef struct outputframe_s { VkCommandBuffer cmd; - VkImageView view; + VkImageView input; VkDescriptorSet set; } outputframe_t; @@ -48,7 +48,7 @@ typedef struct outputctx_s { VkPipeline pipeline; VkPipelineLayout layout; VkSampler sampler; - qfv_output_t output; + VkImageView input; } outputctx_t; struct vulkan_ctx_s; @@ -56,6 +56,6 @@ struct vulkan_ctx_s; void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx); -qfv_output_t *Vulkan_Output_Get (struct vulkan_ctx_s *ctx)__attribute__((pure)); +void Vulkan_Output_SetInput (struct vulkan_ctx_s *ctx, VkImageView input); #endif//__QF_Vulkan_qf_output_h diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 8dc95fdb2..e0acf580e 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -36,7 +36,18 @@ typedef struct clearvalueset_s typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame); +typedef struct qfv_output_s { + VkExtent2D extent; + VkImage image; // only if owned + VkImageView view; + VkFormat format; + uint32_t frames; + VkImageView *view_list; // per frame + VkImageLayout finalLayout; +} qfv_output_t; + typedef struct qfv_renderpass_s { + struct vulkan_ctx_s *vulkan_ctx; vec4f_t color; // for debugging const char *name; // for debugging struct plitem_s *renderpassDef; @@ -47,9 +58,11 @@ typedef struct qfv_renderpass_s { VkDeviceMemory attachmentMemory; size_t attachmentMemory_size; + qfv_output_t output; qfv_framebufferset_t *framebuffers; VkViewport viewport; VkRect2D scissor; + VkRect2D renderArea; int order; int primary_commands; size_t subpassCount; @@ -59,17 +72,12 @@ typedef struct qfv_renderpass_s { qfv_draw_t draw; } qfv_renderpass_t; -struct qfv_output_s; -qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx, - const char *name, - struct qfv_output_s *output, - qfv_draw_t draw); -qfv_renderpass_t *Vulkan_CreateFunctionPass (struct vulkan_ctx_s *ctx, - const char *name, - qfv_draw_t function); -void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx, - qfv_renderpass_t *renderpass); -void Vulkan_CreateAttachments (struct vulkan_ctx_s *ctx, - qfv_renderpass_t *renderpass); +qfv_renderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx, + const char *name, qfv_draw_t draw); +void QFV_RenderPass_Delete (qfv_renderpass_t *renderpass); +void QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass); +void QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass); +void QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass); + #endif//__QF_Vulkan_renderpass_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 35023f1ca..fed5e4928 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -67,15 +67,6 @@ enum { QFV_attachSwapchain, }; -//FIXME name -typedef struct qfv_output_s { - VkExtent2D extent; - VkImageView view; - VkFormat format; - uint32_t frames; - VkImageView *view_list; // per frame -} qfv_output_t; - struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 35c17481e..0c572e001 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -367,11 +367,6 @@ vulkan_end_frame (void) VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VkRenderPassBeginInfo renderPassInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, - }; - __auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4); DARRAY_APPEND (&cmdBufs, frame->cmdBuffer); @@ -393,10 +388,14 @@ vulkan_end_frame (void) QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); if (rpFrame->renderpass && rp->renderpass) { - renderPassInfo.framebuffer = rp->framebuffers->a[imageIndex]; - renderPassInfo.renderPass = rp->renderpass; - renderPassInfo.clearValueCount = rp->clearValues->size; - renderPassInfo.pClearValues = rp->clearValues->a; + VkRenderPassBeginInfo renderPassInfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = rp->renderpass, + .framebuffer = rp->framebuffers->a[imageIndex], + .renderArea = rp->renderArea, + .clearValueCount = rp->clearValues->size, + .pClearValues = rp->clearValues->a, + }; dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, rpFrame->subpassContents); diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index 632cef496..008cb6b5a 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -98,6 +98,20 @@ format = $properties.images.translucent.format; }; }; + output = { + image = { + @inherit = $properties.flat_color_image_template; + usage = color_attachment|input_attachment|sampled; + format = $output.format; + }; + view = { + @inherit = $properties.flat_color_view_template; + image = $output.image; + format = $output.format; + }; + format = r16g16b16a16_sfloat; + finalLayout = shader_read_only_optimal; + }; framebuffer = { renderPass = deferred; attachments = (depth, color, emission, normal, position, opaque, @@ -175,7 +189,7 @@ format = $output.format; loadOp = clear; storeOp = store; - finalLayout = shader_read_only_optimal; + finalLayout = $output.finalLayout; }, ); subpasses = ( @@ -289,14 +303,14 @@ dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dependencyFlags = by_region; }, - { + /*{ srcSubpass = ~0u; // external dstSubpass = 1; // translucent srcStageMask = compute_shader; dstStageMask = vertex_input|draw_indirect; srcAccessMask = shader_write; dstAccessMask = vertex_attribute_read|indirect_command_read; - }, + },*/ { srcSubpass = 0; // depth dstSubpass = 2; // g-buffer diff --git a/libs/video/renderer/vulkan/rp_output.plist b/libs/video/renderer/vulkan/rp_output.plist index 940ab0579..f36286299 100644 --- a/libs/video/renderer/vulkan/rp_output.plist +++ b/libs/video/renderer/vulkan/rp_output.plist @@ -1,45 +1,4 @@ { - flat_color_image_template = { - imageType = `2d; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|sampled; - initialLayout = undefined; - }; - images = { - ocolor = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - }; - flat_color_view_template = { - viewType = VK_IMAGE_VIEW_TYPE_2D; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; - }; - imageViews = { - ocolor = { - @inherit = $properties.flat_color_view_template; - image = ocolor; - format = $properties.images.ocolor.format; - }; - }; framebuffer = { renderPass = output; attachments = ($output.view); diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index c8eff4768..c29606893 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -148,10 +148,16 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) sc->imageViews = DARRAY_ALLOCFIXED (qfv_imageviewset_t, numImages, malloc); dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a); for (uint32_t i = 0; i < numImages; i++) { + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE, + sc->images->a[i], + va (ctx->va_ctx, "image:swapchain:%d", i)); sc->imageViews->a[i] = QFV_CreateImageView (ctx->device, sc->images->a[i], VK_IMAGE_VIEW_TYPE_2D, sc->format, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW, + sc->imageViews->a[i], + va (ctx->va_ctx, "iview:swapchain:%d", i)); } return sc; } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 192faa38b..59c43b09c 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -283,9 +283,8 @@ Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx) // extents are dynamic and filled in for each light // frame buffers are highly dynamic - qfv_output_t output = {}; - __auto_type rp = Vulkan_CreateRenderPass (ctx, "shadow", - &output, lighting_draw_maps); + __auto_type rp = QFV_RenderPass_New (ctx, "shadow", lighting_draw_maps); + QFV_RenderPass_CreateRenderPass (rp); rp->primary_commands = 1; rp->order = QFV_rp_shadowmap; DARRAY_APPEND (&ctx->renderPasses, rp); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index e5c509179..e4b783db3 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -176,9 +176,16 @@ main_draw (qfv_renderframe_t *rFrame) void Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) { - qfv_output_t *output = Vulkan_Output_Get (ctx); - __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", - output, main_draw); + __auto_type rp = QFV_RenderPass_New (ctx, "deferred", main_draw); + rp->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .frames = ctx->swapchain->numImages, + }; + QFV_RenderPass_CreateAttachments (rp); + QFV_RenderPass_CreateRenderPass (rp); + QFV_RenderPass_CreateFramebuffer (rp); rp->order = QFV_rp_main; DARRAY_APPEND (&ctx->renderPasses, rp); + + Vulkan_Output_SetInput (ctx, rp->output.view); } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 2add01e15..3266a5bd2 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -80,18 +80,17 @@ acquire_image (qfv_renderframe_t *rFrame) Vulkan_CreateSwapchain (ctx); Vulkan_CreateCapture (ctx); - //FIXME - qfv_output_t output = { + __auto_type out = ctx->output_renderpass; + out->output = (qfv_output_t) { .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], .format = ctx->swapchain->format, + .frames = ctx->swapchain->numImages, .view_list = ctx->swapchain->imageViews->a, }; - ctx->output_renderpass->viewport.width = output.extent.width; - ctx->output_renderpass->viewport.height = output.extent.height; - ctx->output_renderpass->scissor.extent = output.extent; - Vulkan_Script_SetOutput (ctx, &output); - Vulkan_CreateAttachments (ctx, ctx->output_renderpass); + out->viewport.width = out->output.extent.width; + out->viewport.height = out->output.extent.height; + out->scissor.extent = out->output.extent; + QFV_RenderPass_CreateFramebuffer (out); dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, 0); @@ -109,15 +108,14 @@ update_input (qfv_renderframe_t *rFrame) outputctx_t *octx = ctx->output_context; uint32_t curFrame = ctx->curFrame; outputframe_t *oframe = &octx->frames.a[curFrame]; - qfv_renderpass_t *rp = ctx->output_renderpass; - if (rp->attachment_views->a[0] == oframe->view) { + if (oframe->input == octx->input) { return; } - oframe->view = rp->attachment_views->a[0]; + oframe->input = octx->input; VkDescriptorImageInfo imageInfo = { - octx->sampler, oframe->view, + octx->sampler, oframe->input, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkWriteDescriptorSet write[] = { @@ -189,33 +187,22 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) outputctx_t *octx = calloc (1, sizeof (outputctx_t)); ctx->output_context = octx; - qfv_output_t output = { + __auto_type out = QFV_RenderPass_New (ctx, "output", output_draw); + out->output = (qfv_output_t) { .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], .format = ctx->swapchain->format, .frames = ctx->swapchain->numImages, .view_list = ctx->swapchain->imageViews->a, }; - __auto_type out = Vulkan_CreateRenderPass (ctx, "output", - &output, output_draw); + QFV_RenderPass_CreateRenderPass (out); + QFV_RenderPass_CreateFramebuffer (out); ctx->output_renderpass = out; out->order = QFV_rp_output; - octx->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .view = out->attachment_views->a[0], - .format = VK_FORMAT_R16G16B16A16_SFLOAT,//FIXME - .frames = ctx->swapchain->numImages, - .view_list = malloc (sizeof (VkImageView) * ctx->swapchain->numImages), - }; - for (int i = 0; i < ctx->swapchain->numImages; i++) { - octx->output.view_list[i] = octx->output.view; - } DARRAY_APPEND (&ctx->renderPasses, out); - __auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput", - preoutput_draw); + __auto_type pre = QFV_RenderPass_New (ctx, "preoutput", preoutput_draw); pre->order = QFV_rp_preoutput; DARRAY_APPEND (&ctx->renderPasses, pre); } @@ -279,9 +266,9 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) free (octx); } -qfv_output_t * -Vulkan_Output_Get (vulkan_ctx_t *ctx) +void +Vulkan_Output_SetInput (vulkan_ctx_t *ctx, VkImageView input) { outputctx_t *octx = ctx->output_context; - return &octx->output; + octx->input = input; } diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 6df766bd9..e7bc13fca 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -45,9 +45,7 @@ static plitem_t * get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) { - if (!rp->renderpassDef) { - rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); - } + rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); plitem_t *item = rp->renderpassDef; if (!item) { @@ -87,20 +85,21 @@ destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } void -Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) +QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass) { + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rp = renderpass; - scriptctx_t *sctx = ctx->script_context; - plitem_t *item = get_rp_item (ctx, rp, "images"); - if (!item) { - return; - } - - if (renderpass->framebuffers) { - destroy_framebuffers (ctx, renderpass); + if (rp->output.image) { + // if output has an image, then the view is owned by the renderpass + dfunc->vkDestroyImageView (device->dev, rp->output.view, 0); + dfunc->vkDestroyImage (device->dev, rp->output.image, 0); + free (rp->output.view_list); + rp->output.view_list = 0; + rp->output.view = 0; + rp->output.image = 0; } if (rp->attachment_views) { for (size_t i = 0; i < rp->attachment_views->size; i++) { @@ -118,11 +117,35 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) rp->attachment_images = 0; } - __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); - rp->attachment_images = images; + plitem_t *output_def = get_rp_item (ctx, rp, "output"); + plitem_t *images_def = get_rp_item (ctx, rp, "images"); + plitem_t *views_def = get_rp_item (ctx, rp, "imageViews"); + + plitem_t *rp_def = rp->renderpassDef; + size_t memSize = 0; - for (size_t i = 0; i < images->size; i++) { - memSize += get_image_size (images->a[i], device); + VkImage ref_image = 0; + if (output_def) { + // QFV_ParseOutput clears the structure, but extent and frames need to + // be preserved + qfv_output_t output = rp->output; + QFV_ParseOutput (ctx, &output, output_def, rp_def); + rp->output.format = output.format; + rp->output.finalLayout = output.finalLayout; + + plitem_t *image = PL_ObjectForKey (output_def, "image"); + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->output.image = QFV_ParseImage (ctx, image, rp_def); + memSize += get_image_size (rp->output.image, device); + ref_image = rp->output.image; + } + if (images_def) { + __auto_type images = QFV_ParseImageSet (ctx, images_def, rp_def); + rp->attachment_images = images; + ref_image = images->a[0]; + for (size_t i = 0; i < images->size; i++) { + memSize += get_image_size (images->a[i], device); + } } VkDeviceMemory mem = rp->attachmentMemory; if (memSize > rp->attachmentMemory_size) { @@ -130,7 +153,7 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); } rp->attachmentMemory_size = memSize; - mem = QFV_AllocImageMemory (device, images->a[0], + mem = QFV_AllocImageMemory (device, ref_image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memSize, 0); rp->attachmentMemory = mem; @@ -138,40 +161,110 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) mem, "memory:framebuffers"); } size_t offset = 0; - for (size_t i = 0; i < images->size; i++) { - QFV_BindImageMemory (device, images->a[i], mem, offset); - offset += get_image_size (images->a[i], device); + if (rp->output.image) { + QFV_BindImageMemory (device, rp->output.image, mem, offset); + offset += get_image_size (rp->output.image, device); + + plitem_t *view = PL_ObjectForKey (output_def, "view"); + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->output.view = QFV_ParseImageView (ctx, view, rp_def); + rp->output.view_list = malloc (rp->output.frames + * sizeof (VkImageView)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, + rp->output.image, + va (ctx->va_ctx, "image:%s:output", rp->name)); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW, + rp->output.view, + va (ctx->va_ctx, "iview:%s:output", rp->name)); + for (uint32_t i = 0; i < rp->output.frames; i++) { + rp->output.view_list[i] = rp->output.view; + } + } + if (rp->attachment_images) { + __auto_type images = rp->attachment_images; + for (size_t i = 0; i < images->size; i++) { + QFV_BindImageMemory (device, images->a[i], mem, offset); + offset += get_image_size (images->a[i], device); + } } - item = get_rp_item (ctx, rp, "imageViews"); - if (!item) { - return; + if (views_def) { + __auto_type views = QFV_ParseImageViewSet (ctx, views_def, rp_def); + rp->attachment_views = views; + } +} + +void +QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass) +{ + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; + __auto_type rp = renderpass; + + plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); + if (rp_cfg) { + hashtab_t *tab = ctx->script_context->renderpasses; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", rp->name); + __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); + if (renderpass) { + rp->renderpass = renderpass; + } else { + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, + rp->renderpassDef); + QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, + rp->renderpass, va (ctx->va_ctx, + "renderpass:%s", + rp->name)); + } + rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, + "subpasses")); } - __auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef); - rp->attachment_views = views; - item = get_rp_item (ctx, rp, "framebuffer"); - if (!item) { - return; + plitem_t *item = get_rp_item (ctx, rp, "clearValues"); + rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); +} + +void +QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass) +{ + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; + __auto_type rp = renderpass; + + if (renderpass->framebuffers) { + destroy_framebuffers (ctx, renderpass); } - rp->framebuffers = QFV_AllocFrameBuffers (sctx->output.frames, malloc); - for (size_t i = 0; i < rp->framebuffers->size; i++) { - sctx->output.view = sctx->output.view_list[i]; - rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, - rp->renderpassDef); + plitem_t *fb_def = get_rp_item (ctx, rp, "framebuffer"); + plitem_t *rp_def = rp->renderpassDef; + if (fb_def) { + rp->framebuffers = QFV_AllocFrameBuffers (rp->output.frames, malloc); + for (size_t i = 0; i < rp->framebuffers->size; i++) { + rp->output.view = rp->output.view_list[i]; + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, fb_def, rp_def); + } } + + int width = rp->output.extent.width; + int height = rp->output.extent.height; + rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; + rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; + rp->renderArea = (VkRect2D) { {0, 0}, {width, height} }; } static void init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, qfv_renderframe_t *rFrame) { - rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; rFrame->vulkan_ctx = ctx; rFrame->renderpass = rp; + rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; + rFrame->framebuffer = 0; rFrame->subpassCount = rp->subpassCount; + rFrame->subpassInfo = 0; if (rp->subpass_info) { rFrame->subpassInfo = rp->subpass_info->a; } @@ -188,6 +281,15 @@ destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + if (rp->output.image) { + // if output has an image, then the view is owned by the renderpass + dfunc->vkDestroyImageView (device->dev, rp->output.view, 0); + dfunc->vkDestroyImage (device->dev, rp->output.image, 0); + free (rp->output.view_list); + rp->output.view_list = 0; + rp->output.view = 0; + rp->output.image = 0; + } if (rp->attachment_views) { for (size_t i = 0; i < rp->attachment_views->size; i++) { dfunc->vkDestroyImageView (device->dev, @@ -218,35 +320,14 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } qfv_renderpass_t * -Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, - qfv_output_t *output, qfv_draw_t draw) +QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) { - plitem_t *item; - qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); - + rp->vulkan_ctx = ctx; rp->name = name; + rp->draw = function; + rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); - plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); - if (rp_cfg) { - hashtab_t *tab = ctx->script_context->renderpasses; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); - __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); - if (renderpass) { - rp->renderpass = renderpass; - } else { - Vulkan_Script_SetOutput (ctx, output); - rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, - rp->renderpassDef); - QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - rp->renderpass, va (ctx->va_ctx, - "renderpass:%s", name)); - } - rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, - "subpasses")); - } plitem_t *rp_info = get_rp_item (ctx, rp, "info"); if (rp_info) { plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info"); @@ -255,7 +336,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, rp->renderpassDef); if (rp->subpass_info->size < rp->subpassCount) { Sys_Printf ("warning:%s:%d: insufficient entries in " - "subpass_info\n", name, PL_Line (subpass_info)); + "subpass_info\n", rp->name, PL_Line (subpass_info)); } if (!rp->subpassCount) { rp->subpassCount = rp->subpass_info->size; @@ -268,35 +349,6 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, } } - int width = output->extent.width; - int height = output->extent.height; - rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; - rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; - - DARRAY_INIT (&rp->frames, 4); - DARRAY_RESIZE (&rp->frames, ctx->frames.size); - for (size_t i = 0; i < rp->frames.size; i++) { - init_renderframe (ctx, rp, &rp->frames.a[i]); - } - - item = get_rp_item (ctx, rp, "clearValues"); - rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); - - rp->draw = draw; - - Vulkan_CreateAttachments (ctx, rp); - - return rp; -} - -qfv_renderpass_t * -Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name, - qfv_draw_t function) -{ - qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); - rp->name = name; - rp->draw = function; - DARRAY_INIT (&rp->frames, 4); DARRAY_RESIZE (&rp->frames, ctx->frames.size); for (size_t i = 0; i < rp->frames.size; i++) { @@ -306,8 +358,9 @@ Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name, } void -Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) +QFV_RenderPass_Delete (qfv_renderpass_t *renderpass) { + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 0f129bf03..9466fc92f 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -176,7 +176,7 @@ void Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) { for (size_t i = 0; i < ctx->renderPasses.size; i++) { - Vulkan_DestroyRenderPass (ctx, ctx->renderPasses.a[i]); + QFV_RenderPass_Delete (ctx->renderPasses.a[i]); } }