From b2d4fa0ccf96995c83e2fd6354e10e03000facd7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Apr 2022 11:42:36 +0900 Subject: [PATCH] [vulkan] Break render pass parsing away from swapchain This allows a single render pass description to be used for both on-screen and off-screen targets. While Vulkan does allow a VkRenderPass to be used with any compatible frame buffer, and vkparse caches a VkRenderPass created from the same description, this allows the same description to be used for a compatible off-screen target without any dependence on the swapchain. However, there is a problem in the caching when it comes to targeting outputs with different formats. --- include/vid_vulkan.h | 10 ++ libs/video/renderer/vulkan/deferred.plist | 40 +++---- libs/video/renderer/vulkan/vkparse.c | 104 +++++------------- libs/video/renderer/vulkan/vkparse.h | 12 -- .../video/renderer/vulkan/vulkan_vid_common.c | 11 +- 5 files changed, 66 insertions(+), 111 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 56aa8c3f3..def07b666 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -9,6 +9,13 @@ #include "QF/darray.h" #include "QF/simd/types.h" +//FIXME name +typedef struct qfv_output_s { + VkExtent2D extent; + VkImageView view; + VkFormat format; +} qfv_output_t; + typedef struct vulkan_frame_s { VkFramebuffer framebuffer; VkFence fence; @@ -91,6 +98,9 @@ typedef struct vulkan_ctx_s { VkViewport viewport; VkRect2D scissor; + //FIXME not sure I like it being here (also, type name) + qfv_output_t output; + #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 1eade9e2e..c5ce13c0f 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -5,8 +5,8 @@ format = x8_d24_unorm_pack32; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -20,8 +20,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -35,8 +35,8 @@ format = r16g16b16a16_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -50,8 +50,8 @@ format = r16g16b16a16_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -65,8 +65,8 @@ format = r32g32b32a32_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -80,8 +80,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -95,8 +95,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -223,9 +223,9 @@ framebuffer = { renderPass = $properties.renderpass; attachments = (depth, color, emission, normal, position, opaque, - translucent, "$swapchain.views[$swapImageIndex]"); - width = $swapchain.extent.width; - height = $swapchain.extent.height; + translucent, $output.view); + width = $output.extent.width; + height = $output.extent.height; layers = 1; }; clearValues = ( @@ -236,7 +236,7 @@ { color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // opaque { color = "[0, 0, 0, 0]"; }, // translucent - { color = "[0, 0, 0, 1]"; }, // swapchain + { color = "[0, 0, 0, 1]"; }, // output ); renderpass = { attachments = ( @@ -311,7 +311,7 @@ finalLayout = color_attachment_optimal; }, { - format = $swapchain.format; + format = $output.format; samples = 1; loadOp = clear; storeOp = store; @@ -414,7 +414,7 @@ }, ); colorAttachments = ( - { // swapchain + { // output attachment = 7; layout = color_attachment_optimal; }, diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 79c6811e3..97fdd813d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -42,8 +42,8 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" -#include "QF/Vulkan/swapchain.h" #include "vid_vulkan.h" @@ -51,6 +51,17 @@ #include "vkparse.h" #undef vkparse_internal +typedef struct parseres_s { + const char *name; + plfield_t *field; + size_t offset; +} parseres_t; + +typedef struct handleref_s { + char *name; + uint64_t handle; +} handleref_t; + static void flag_or (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { @@ -577,7 +588,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, return ret; } -static exprtype_t imageview_type = { +exprtype_t VkImageView_type = { "VkImageView", sizeof (VkImageView), 0, 0, 0 @@ -610,7 +621,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, plitem_t *imageViewItem = 0; if (ret) { VkImageView imageView; - if (value->type == &imageview_type) { + if (value->type == &VkImageView_type) { imageView = *(VkImageView *) value->value; } else if (value->type == &cexpr_plitem) { imageView = QFV_ParseImageView (ctx, imageViewItem, @@ -856,82 +867,21 @@ parse_specialization_data (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static void -imageviewset_index (const exprval_t *a, size_t index, exprval_t *c, - exprctx_t *ctx) -{ - __auto_type set = *(qfv_imageviewset_t **) a->value; - exprval_t *val = 0; - if (index >= set->size) { - cexpr_error (ctx, "invalid index: %zd", index); - } else { - val = cexpr_value (&imageview_type, ctx); - *(VkImageView *) val->value = set->a[index]; - } - *(exprval_t **) c->value = val; -} - -static void -imageviewset_int (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(int *) b->value; - imageviewset_index (a, index, c, ctx); -} - -static void -imageviewset_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(unsigned *) b->value; - imageviewset_index (a, index, c, ctx); -} - -static void -imageviewset_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(size_t *) b->value; - imageviewset_index (a, index, c, ctx); -} - -binop_t imageviewset_binops[] = { - { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield }, - { '[', &cexpr_int, &imageview_type, imageviewset_int }, - { '[', &cexpr_uint, &imageview_type, imageviewset_uint }, - { '[', &cexpr_size_t, &imageview_type, imageviewset_size_t }, - {} -}; - -static exprsym_t imageviewset_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (qfv_imageviewset_t, size)}, +static exprsym_t qfv_output_t_symbols[] = { + {"format", &VkFormat_type, (void *)field_offset (qfv_output_t, format)}, + {"extent", &VkExtent2D_type, (void *)field_offset (qfv_output_t, extent)}, + {"view", &VkImageView_type, (void *)field_offset (qfv_output_t, view)}, { } }; -static exprtab_t imageviewset_symtab = { - imageviewset_symbols, +static exprtab_t qfv_output_t_symtab = { + qfv_output_t_symbols, }; -exprtype_t imageviewset_type = { - "imageviewset", - sizeof (qfv_imageviewset_t *), - imageviewset_binops, - 0, - &imageviewset_symtab, -}; -static exprsym_t qfv_swapchain_t_symbols[] = { - {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, - {"extent", &VkExtent2D_type, (void *)field_offset (qfv_swapchain_t, extent)}, - {"views", &imageviewset_type, (void *)field_offset (qfv_swapchain_t, imageViews)}, - { } -}; -static exprtab_t qfv_swapchain_t_symtab = { - qfv_swapchain_t_symbols, -}; -exprtype_t qfv_swapchain_t_type = { - "qfv_swapchain_t", - sizeof (qfv_swapchain_t), +exprtype_t qfv_output_t_type = { + "qfv_output_t", + sizeof (qfv_output_t), cexpr_struct_binops, 0, - &qfv_swapchain_t_symtab, + &qfv_output_t_symtab, }; static exprsym_t vulkan_frameset_t_symbols[] = { @@ -1023,9 +973,8 @@ QFV_InitParse (vulkan_ctx_t *ctx) &ctx->hashlinks); context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); - cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); + cexpr_init_symtab (&qfv_output_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); - cexpr_init_symtab (&imageviewset_symtab, &context); cexpr_init_symtab (&data_array_symtab, &context); if (!ctx->setLayouts) { @@ -1054,10 +1003,9 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { - {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"output", &qfv_output_t_type, &ctx->output}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex}, {"physDevLimits", &VkPhysicalDeviceLimits_type, &ctx->device->physDev->properties.limits }, {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 6f2ea6357..730094e3b 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -10,24 +10,12 @@ typedef struct parsectx_s { #include "QF/cexpr.h" #include "QF/plist.h" -#include "QF/Vulkan/renderpass.h" #ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" #endif #define QFV_PROPERTIES "properties" -typedef struct parseres_s { - const char *name; - plfield_t *field; - size_t offset; -} parseres_t; - -typedef struct handleref_s { - char *name; - uint64_t handle; -} handleref_t; - void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d5cbcfaf6..e429f688b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -388,7 +388,11 @@ create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, malloc); for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->swapImageIndex = i; // for $swapImageIndex in the config + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[i], + .format = ctx->swapchain->format, + }; rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->renderpassDef); } @@ -424,6 +428,11 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) if (renderpass) { rp->renderpass = renderpass; } else { + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + }; item = qfv_load_renderpass (ctx, rp, name); rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef); QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);