From e5932d1f92ebb131ba4110ac2bf1e109189354f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 May 2022 21:53:38 +0900 Subject: [PATCH] [vulkan] Support Vulkan's pNext in vkparse/vkgen The real reason for the delay in implementing support for pNext is I didn't know how to approach it at the time, but with the experience I've gained using and modifying vkparse, the solution turned out to be fairly simple. This allows for the use of various extensions (eg, multiview, which was used for testing, though none of the hookup is in this commit). No checking is done on the struct type being valid other than it must be of a chainable type (ie, have its own pNext). --- libs/video/renderer/Makemodule.am | 15 ++-- libs/video/renderer/vulkan/shader.c | 3 - libs/video/renderer/vulkan/shadow.plist | 12 ++-- libs/video/renderer/vulkan/vkgen/vkstruct.h | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 30 ++++++-- libs/video/renderer/vulkan/vkparse.c | 68 +++++++++++++++++++ libs/video/renderer/vulkan/vkparse.plist | 19 ++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 4 ++ 8 files changed, 134 insertions(+), 18 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 6a52b1af4..41a940649 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -183,6 +183,8 @@ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc deferred_src = libs/video/renderer/vulkan/deferred.plist deferred_gen = libs/video/renderer/vulkan/deferred.plc +shadow_src = libs/video/renderer/vulkan/shadow.plist +shadow_gen = libs/video/renderer/vulkan/shadow.plc forward_src = libs/video/renderer/vulkan/forward.plist forward_gen = libs/video/renderer/vulkan/forward.plc @@ -236,7 +238,13 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${deferred_gen} $(forward_gen) +libs/video/renderer/vulkan/vulkan_vid_common.lo: \ + libs/video/renderer/vulkan/vulkan_vid_common.c \ + $(vkparse_src) \ + $(pipeline_gen) \ + ${deferred_gen} \ + ${shadow_gen} \ + $(forward_gen) qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) @@ -315,8 +323,6 @@ fstriangle_src = $(vkshaderpath)/fstriangle.vert fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc -shadow_src = $(vkshaderpath)/shadow.geom -shadow_c = $(vkshaderpath)/shadow.geom.spvc $(partphysicsc_c): $(partphysicsc_src) $(partupdatec_c): $(partupdatec_src) @@ -378,8 +384,6 @@ $(fstriangle_c): $(fstriangle_src) $(pushcolor_c): $(pushcolor_src) -$(shadow_c): $(shadow_src) - vkshader_c = \ $(partphysicsc_c) \ $(partupdatec_c) \ @@ -446,6 +450,7 @@ BUILT_SOURCES += $(shader_gen) EXTRA_DIST += \ $(deferred_src) \ + $(shadow_src) \ $(forward_src) \ $(pipeline_src) \ libs/video/renderer/vulkan/vkparse.plist \ diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 0f7e19a7b..a567b735c 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -102,8 +102,6 @@ static #include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" -static -#include "libs/video/renderer/vulkan/shader/shadow.geom.spvc" typedef struct shaderdata_s { const char *name; @@ -144,7 +142,6 @@ static shaderdata_t builtin_shaders[] = { { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, - { "shadow.geom", shadow_geom, sizeof (shadow_geom) }, {} }; diff --git a/libs/video/renderer/vulkan/shadow.plist b/libs/video/renderer/vulkan/shadow.plist index 93eb8da31..5db23260c 100644 --- a/libs/video/renderer/vulkan/shadow.plist +++ b/libs/video/renderer/vulkan/shadow.plist @@ -23,10 +23,7 @@ viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; format = $properties.images.shadow.format; components = { - r = identity; - g = identity; - b = identity; - a = identity; + r = identity; g = identity; b = identity; a = identity; }; subresourceRange = { aspectMask = depth; @@ -37,7 +34,7 @@ }; framebuffer = { renderPass = $properties.renderpass; - attachments = (shadown); + attachments = (shadow); width = $properties.images.shadow.extent.width; height = $properties.images.shadow.extent.height; layers = $properties.images.shadow.arrayLayers; @@ -46,9 +43,12 @@ { depthStencil = { depth = 1; stencil = 0; }; }, ); renderpass = { + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0xffffffff); + }); attachments = ( { - format = $properties.images.depth.format; + format = $properties.images.shadow.format; samples = 1; loadOp = dont_care; storeOp = store; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 445c9fc34..5ed901e9e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -11,6 +11,7 @@ @interface Struct: Type { string outname; + int write_symtab; } -(void) queueFieldTypes; -(qfot_var_t *)findField:(string) fieldName; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 077b19cfb..ec6530b5e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -84,6 +84,7 @@ PLItem *new_name = [field_dict getObjectForKey:".name"]; Array *field_defs = [Array array]; int have_sType = 0; + int have_pNext = 0; if ([parse string] == "skip") { return; @@ -97,6 +98,10 @@ if (field.name == "sType") { have_sType = 1; } + if (field.name == "pNext") { + have_pNext = 1; + write_symtab = 1; + } } if (field_dict) { PLItem *field_keys = [field_dict allKeys]; @@ -133,6 +138,11 @@ fprintf (output_file, "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", [self outname]); + if (have_pNext) { + fprintf (output_file, + "\t{\"@next\", field_offset (%s, pNext), " + "QFArray, parse_next, 0},", [self outname]); + } for (int i = [field_defs count]; i-- > 0; ) { FieldDef *field_def = [field_defs objectAtIndex:i]; [field_def writeField]; @@ -140,14 +150,14 @@ fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (header_file, "int parse_%s (const plfield_t *field," + fprintf (header_file, "int %s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context);\n", - [self outname]); - fprintf (output_file, "int parse_%s (const plfield_t *field," + [self parseFunc]); + fprintf (output_file, "int %s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context)\n", - [self outname]); + [self parseFunc]); fprintf (output_file, "{\n"); if (have_sType) { fprintf (output_file, "\t((%s *) data)->sType", [self outname]); @@ -162,6 +172,12 @@ " context);\n", [self outname], [self outname]); fprintf (output_file, "}\n"); + if (have_pNext) { + fprintf (output_file, "static parserref_t %s_parser = ", + [self outname]); + fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", + [self outname], [self parseFunc], [self outname]); + } fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); if (field_defs) { @@ -216,6 +232,12 @@ -(void) writeSymtabEntry { + if (!write_symtab || [parse string] == "skip") { + return; + } + fprintf (output_file, + "\tHash_Add (parser_table, &%s_parser);\n", + [self outname]); } -(string) outname diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 9ae5d8b40..c75681f8b 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -56,6 +56,12 @@ typedef struct parseres_s { size_t offset; } parseres_t; +typedef struct parseref_s { + const char *name; + plparser_t parse; + size_t size; +} parserref_t; + typedef struct handleref_s { char *name; uint64_t handle; @@ -169,6 +175,33 @@ parse_basic (const plfield_t *field, const plitem_t *item, return ret; } +static int +parse_int32_t (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + int ret = 1; + // use size_t (and cexpr_size_t) for val so references to array sizes + // can be used + size_t val = 0; + exprval_t result = { &cexpr_size_t, &val }; + exprctx_t ectx = *((parsectx_t *) context)->ectx; + ectx.result = &result; + const char *valstr = PL_String (item); + //Sys_MaskPrintf (SYS_vulkan_parse, + // "parse_int32_t: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + ret = !cexpr_eval_string (valstr, &ectx); + if (!ret) { + PL_Message (messages, item, "error parsing %s: %s", + field->name, valstr); + } + *(int32_t *) data = val; + //Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(int32_t *)data); + + return ret; +} + static int parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -393,6 +426,33 @@ parse_inherit (const plfield_t *field, const plitem_t *item, return ret; } +static hashtab_t *parser_table; + +static int +parse_next (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + const char *type_name = PL_String (PL_ObjectAtIndex (item, 0)); + plitem_t *next_def = PL_ObjectAtIndex (item, 1); + + if (!type_name || PL_Type (next_def) != QFDictionary) { + PL_Message (messages, item, "invalid @next"); + return 0; + } + parserref_t *parser = Hash_Find (parser_table, type_name); + if (!parser) { + PL_Message (messages, item, "Invalid type for @next: %s", type_name); + return 0; + } + void *data_ptr = vkparse_alloc (context, parser->size); + memset (data_ptr, 0, parser->size); + if (!parser->parse (field, next_def, data_ptr, messages, context)) { + return 0; + } + *(void **) data = data_ptr; + return 1; +} + static int parse_RGBA (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context) @@ -971,6 +1031,13 @@ enum_symtab_getkey (const void *e, void *unused) return enm->type->name; } +static const char * +parser_getkey (const void *e, void *unused) +{ + __auto_type parser = (const parserref_t *) e; + return parser->name; +} + static exprtab_t root_symtab = { .symbols = cexpr_lib_symbols, }; @@ -988,6 +1055,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) { exprctx_t context = {}; enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &ctx->hashctx); + parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &ctx->hashctx); context.hashctx = &ctx->hashctx; vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_output_t_symtab, &context); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 4379d39c4..e2d622940 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -28,6 +28,8 @@ VkFramebufferCreateInfo, VkClearValue, VkPhysicalDeviceLimits, + VkRenderPassCreateInfo, + VkRenderPassMultiviewCreateInfo, ); parse = { VkSubpassDescription = { @@ -359,5 +361,22 @@ }; depthStencil = auto; }; + VkRenderPassMultiviewCreateInfo = { + viewMasks = { + type = (array, uint32_t); + size = subpassCount; + values = pViewMasks; + }; + viewOffsets = { + type = (array, int32_t); + size = dependencyCount; + values = pViewOffsets; + }; + correlationMasks = { + type = (array, uint32_t); + size = correlationMaskCount; + values = pCorrelationMasks; + }; + } } } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a3d299001..2cd5fa1fe 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -75,6 +75,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/deferred.plc" }, + { .name = "shadow", + .value = (void *) +#include "libs/video/renderer/vulkan/shadow.plc" + }, { .name = "forward", .value = (void *) #include "libs/video/renderer/vulkan/forward.plc"