[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/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"

View file

@ -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;
},

View file

@ -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},

View file

@ -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);

View file

@ -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);