[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.
This commit is contained in:
Bill Currie 2022-04-02 11:42:36 +09:00
parent 88343d73ea
commit b2d4fa0ccf
5 changed files with 66 additions and 111 deletions

View file

@ -9,6 +9,13 @@
#include "QF/darray.h" #include "QF/darray.h"
#include "QF/simd/types.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 { typedef struct vulkan_frame_s {
VkFramebuffer framebuffer; VkFramebuffer framebuffer;
VkFence fence; VkFence fence;
@ -91,6 +98,9 @@ typedef struct vulkan_ctx_s {
VkViewport viewport; VkViewport viewport;
VkRect2D scissor; 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 EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname;
#include "QF/Vulkan/funclist.h" #include "QF/Vulkan/funclist.h"

View file

@ -5,8 +5,8 @@
format = x8_d24_unorm_pack32; format = x8_d24_unorm_pack32;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -20,8 +20,8 @@
format = r8g8b8a8_unorm; format = r8g8b8a8_unorm;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -35,8 +35,8 @@
format = r16g16b16a16_sfloat; format = r16g16b16a16_sfloat;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -50,8 +50,8 @@
format = r16g16b16a16_sfloat; format = r16g16b16a16_sfloat;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -65,8 +65,8 @@
format = r32g32b32a32_sfloat; format = r32g32b32a32_sfloat;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -80,8 +80,8 @@
format = r8g8b8a8_unorm; format = r8g8b8a8_unorm;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -95,8 +95,8 @@
format = r8g8b8a8_unorm; format = r8g8b8a8_unorm;
samples = 1; samples = 1;
extent = { extent = {
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
depth = 1; depth = 1;
}; };
mipLevels = 1; mipLevels = 1;
@ -223,9 +223,9 @@
framebuffer = { framebuffer = {
renderPass = $properties.renderpass; renderPass = $properties.renderpass;
attachments = (depth, color, emission, normal, position, opaque, attachments = (depth, color, emission, normal, position, opaque,
translucent, "$swapchain.views[$swapImageIndex]"); translucent, $output.view);
width = $swapchain.extent.width; width = $output.extent.width;
height = $swapchain.extent.height; height = $output.extent.height;
layers = 1; layers = 1;
}; };
clearValues = ( clearValues = (
@ -236,7 +236,7 @@
{ color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // position
{ color = "[0, 0, 0, 1]"; }, // opaque { color = "[0, 0, 0, 1]"; }, // opaque
{ color = "[0, 0, 0, 0]"; }, // translucent { color = "[0, 0, 0, 0]"; }, // translucent
{ color = "[0, 0, 0, 1]"; }, // swapchain { color = "[0, 0, 0, 1]"; }, // output
); );
renderpass = { renderpass = {
attachments = ( attachments = (
@ -311,7 +311,7 @@
finalLayout = color_attachment_optimal; finalLayout = color_attachment_optimal;
}, },
{ {
format = $swapchain.format; format = $output.format;
samples = 1; samples = 1;
loadOp = clear; loadOp = clear;
storeOp = store; storeOp = store;
@ -414,7 +414,7 @@
}, },
); );
colorAttachments = ( colorAttachments = (
{ // swapchain { // output
attachment = 7; attachment = 7;
layout = color_attachment_optimal; layout = color_attachment_optimal;
}, },

View file

@ -42,8 +42,8 @@
#include "QF/Vulkan/instance.h" #include "QF/Vulkan/instance.h"
#include "QF/Vulkan/image.h" #include "QF/Vulkan/image.h"
#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/pipeline.h"
#include "QF/Vulkan/renderpass.h"
#include "QF/Vulkan/shader.h" #include "QF/Vulkan/shader.h"
#include "QF/Vulkan/swapchain.h"
#include "vid_vulkan.h" #include "vid_vulkan.h"
@ -51,6 +51,17 @@
#include "vkparse.h" #include "vkparse.h"
#undef vkparse_internal #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, static void flag_or (const exprval_t *val1, const exprval_t *val2,
exprval_t *result, exprctx_t *ctx) exprval_t *result, exprctx_t *ctx)
{ {
@ -577,7 +588,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages,
return ret; return ret;
} }
static exprtype_t imageview_type = { exprtype_t VkImageView_type = {
"VkImageView", "VkImageView",
sizeof (VkImageView), sizeof (VkImageView),
0, 0, 0 0, 0, 0
@ -610,7 +621,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data,
plitem_t *imageViewItem = 0; plitem_t *imageViewItem = 0;
if (ret) { if (ret) {
VkImageView imageView; VkImageView imageView;
if (value->type == &imageview_type) { if (value->type == &VkImageView_type) {
imageView = *(VkImageView *) value->value; imageView = *(VkImageView *) value->value;
} else if (value->type == &cexpr_plitem) { } else if (value->type == &cexpr_plitem) {
imageView = QFV_ParseImageView (ctx, imageViewItem, 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" #include "libs/video/renderer/vulkan/vkparse.cinc"
static void static exprsym_t qfv_output_t_symbols[] = {
imageviewset_index (const exprval_t *a, size_t index, exprval_t *c, {"format", &VkFormat_type, (void *)field_offset (qfv_output_t, format)},
exprctx_t *ctx) {"extent", &VkExtent2D_type, (void *)field_offset (qfv_output_t, extent)},
{ {"view", &VkImageView_type, (void *)field_offset (qfv_output_t, view)},
__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 exprtab_t imageviewset_symtab = { static exprtab_t qfv_output_t_symtab = {
imageviewset_symbols, qfv_output_t_symbols,
}; };
exprtype_t imageviewset_type = { exprtype_t qfv_output_t_type = {
"imageviewset", "qfv_output_t",
sizeof (qfv_imageviewset_t *), sizeof (qfv_output_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),
cexpr_struct_binops, cexpr_struct_binops,
0, 0,
&qfv_swapchain_t_symtab, &qfv_output_t_symtab,
}; };
static exprsym_t vulkan_frameset_t_symbols[] = { static exprsym_t vulkan_frameset_t_symbols[] = {
@ -1023,9 +973,8 @@ QFV_InitParse (vulkan_ctx_t *ctx)
&ctx->hashlinks); &ctx->hashlinks);
context.hashlinks = &ctx->hashlinks; context.hashlinks = &ctx->hashlinks;
vkgen_init_symtabs (&context); 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 (&vulkan_frameset_t_symtab, &context);
cexpr_init_symtab (&imageviewset_symtab, &context);
cexpr_init_symtab (&data_array_symtab, &context); cexpr_init_symtab (&data_array_symtab, &context);
if (!ctx->setLayouts) { 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 }; exprctx_t exprctx = { .symtab = &root_symtab };
parsectx_t parsectx = { &exprctx, ctx, properties }; parsectx_t parsectx = { &exprctx, ctx, properties };
exprsym_t var_syms[] = { 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}, {"frames", &vulkan_frameset_t_type, &ctx->frames},
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex},
{"physDevLimits", &VkPhysicalDeviceLimits_type, {"physDevLimits", &VkPhysicalDeviceLimits_type,
&ctx->device->physDev->properties.limits }, &ctx->device->physDev->properties.limits },
{QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties},

View file

@ -10,24 +10,12 @@ typedef struct parsectx_s {
#include "QF/cexpr.h" #include "QF/cexpr.h"
#include "QF/plist.h" #include "QF/plist.h"
#include "QF/Vulkan/renderpass.h"
#ifdef vkparse_internal #ifdef vkparse_internal
#include "libs/video/renderer/vulkan/vkparse.hinc" #include "libs/video/renderer/vulkan/vkparse.hinc"
#endif #endif
#define QFV_PROPERTIES "properties" #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); void QFV_InitParse (vulkan_ctx_t *ctx);
exprenum_t *QFV_GetEnum (const char *name); exprenum_t *QFV_GetEnum (const char *name);

View file

@ -388,7 +388,11 @@ create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp)
rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages,
malloc); malloc);
for (size_t i = 0; i < rp->framebuffers->size; i++) { 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->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
rp->renderpassDef); rp->renderpassDef);
} }
@ -424,6 +428,11 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
if (renderpass) { if (renderpass) {
rp->renderpass = renderpass; rp->renderpass = renderpass;
} else { } 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); item = qfv_load_renderpass (ctx, rp, name);
rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef); rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef);
QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); QFV_AddHandle (tab, path, (uint64_t) rp->renderpass);