diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index e115e0b1b..0e2ed845c 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -75,6 +75,7 @@ typedef struct qfv_taskinfo_s { typedef struct qfv_attachmentrefinfo_s { const char *name; VkImageLayout layout; + VkPipelineColorBlendAttachmentState blend; } qfv_attachmentrefinfo_t; typedef struct qfv_attachmentsetinfo_s { @@ -94,6 +95,20 @@ typedef struct qfv_pipelineinfo_s { qfv_reference_t pipeline; uint32_t num_tasks; qfv_taskinfo_t *tasks; + + VkPipelineCreateFlags flags; + uint32_t num_graph_stages; + const VkPipelineShaderStageCreateInfo *graph_stages; + const VkPipelineVertexInputStateCreateInfo *vertexInput; + const VkPipelineInputAssemblyStateCreateInfo *inputAssembly; + const VkPipelineTessellationStateCreateInfo *tessellation; + const VkPipelineViewportStateCreateInfo *viewport; + const VkPipelineRasterizationStateCreateInfo *rasterization; + const VkPipelineMultisampleStateCreateInfo *multisample; + const VkPipelineDepthStencilStateCreateInfo *depthStencil; + const VkPipelineColorBlendStateCreateInfo *colorBlend; + const VkPipelineDynamicStateCreateInfo *dynamic; + qfv_reference_t *layout; } qfv_pipelineinfo_t; typedef struct qfv_subpassinfo_s { @@ -105,6 +120,7 @@ typedef struct qfv_subpassinfo_s { qfv_attachmentrefinfo_t *attachments; uint32_t num_pipelines; qfv_pipelineinfo_t *pipelines; + qfv_pipelineinfo_t *base_pipeline; } qfv_subpassinfo_t; typedef struct qfv_framebufferinfo_s { @@ -137,6 +153,7 @@ typedef struct qfv_renderinfo_s { typedef struct qfv_renderctx_s { struct hashctx_s *hashctx; exprtab_t task_functions; + qfv_renderinfo_t *renderinfo; } qfv_renderctx_t; typedef struct qfv_label_s { diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 729ebf01f..ec70028ac 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1034,16 +1034,6 @@ }, ); vertexInput = $properties.vertexInput.iqm; - /*vertexInput = { - bindings = ( - "$properties.vertexInput.iqm.bindings[0]", - ); - attributes = ( - "$properties.vertexInput.iqm.attributes[0]", - "$properties.vertexInput.iqm.attributes[1]", - "$properties.vertexInput.iqm.attributes[2]", - ); - };*/ inputAssembly = $properties.inputAssembly.iqm; layout = iqm_layout; }; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index d183016e3..488db0eb8 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -131,7 +131,7 @@ QFV_LoadRenderPass (vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); - QFV_ParseRenderInfo (ctx, item, rctx); + rctx->renderinfo = QFV_ParseRenderInfo (ctx, item, rctx); } void diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 7890652bc..09e7652d3 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -69,6 +69,431 @@ properties = { finalLayout = color_attachment_optimal; clearValue = { color = "[0, 0, 0, 1]"; }; }; + + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + depth_test_and_write = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + depth_test_only = { + depthTestEnable = true; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + depth_disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + blend_disable = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + pipeline_base = { + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0; }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = $cw_cull_back; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = $depth_test_only; + colorBlend = { + logicOpEnable = false; + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + }; + compose_base = { + @inherit = $pipeline_base; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + }; + + brush = { + shader = { + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/bsp_depth.vert; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/bsp_gbuf.vert; + }; + gbuf_geometry = { + stage = geometry; + name = main; + module = $builtin/bsp_gbuf.geom; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_gbuf.frag; + }; + quake_vertex = { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }; + sky_specialization = { + mapEntries = ( + // doSkyBox + { size = 4; offset = 0; constantID = 0; }, + // doSkySheet + { size = 4; offset = 4; constantID = 1; }, + ); + }; + skybox_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + @inherit = $brush.shader.sky_specialization; + // doSkyBox, doSkySheet + data = "array(1, 0)"; + }; + }; + skysheet_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + @inherit = $brush.shader.sky_specialization; + // doSkyBox, doSkySheet + data = "array(0, 1)"; + }; + }; + turb_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_turb.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32_uint; offset = 0; }, + ); + }; + inputAssembly = { + topology = triangle_fan; + primitiveRestartEnable = true; + }; + layout = { + setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4 * 4 + 4 + 4 + 4"; + }, + ); + }; + }; + alias = { + shader = { + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/alias_depth.vert; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/alias.vert; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/alias_gbuf.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 2; stride = "2 * 4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, texture_set, texture_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4"; + }, + ); + }; + }; + iqm = { + shader = { + specialization = { + mapEntries = ( + // IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + }; + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + @inherit = $iqm.shader.specialization; + // IQMDepthOnly + data = "array(1)"; + }; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + @inherit = $iqm.shader.specialization; + // IQMDepthOnly + data = "array(0)"; + }; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/iqm.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = 20; inputRate = vertex; }, + { binding = 1; stride = 40; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position + { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices + { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights + + { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord + { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal + { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent + { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color + + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, texture_set, bone_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4 + 4"; + }, + ); + }; + }; + sprite = { + shader = { + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/sprite_depth.vert; + }; + depth_fragment = { + stage = fragment; + name = main; + module = $builtin/sprite_depth.frag; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/sprite_gbuf.vert; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/sprite_gbuf.frag; + }; + }; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_strip; + // never draw more than 4 verts + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, sprite_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + // note: overlap with fragment is for the frame number + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 64; + // note: overlap with vertex to share frame number + size = "2 * 4 + 2 * 4 + 4"; + }, + ); + }; + }; + particle = { + shader = { + vertex = { + stage = vertex; + name = main; + module = $builtin/particle.vert; + }; + geometry = { + stage = geometry; + name = main; + module = $builtin/particle.geom; + }; + fragment = { + stage = fragment; + name = main; + module = $builtin/particle.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "4 * 4 * 4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 32; }, + { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, + ); + }; + inputAssembly = { + topology = point_list; + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, texture_set, oit_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + ); + }; + }; + fstriangle = { + shader = { + vertex = { + stage = vertex; + name = main; + module = $builtin/fstriangle.vert; + }; + }; + }; + lighting = { + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/lighting.frag; + }; + }; + }; + compose = { + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/compose.frag; + }; + }; + } }; images = { depth = { @@ -194,37 +619,88 @@ renderpasses = { }; preserve = (color, emission, normal, position, output); }; + + base_pipeline = { + @inherit = $pipeline_base; + depthStencil = $depth_test_and_write; + }; pipelines = { bsp:depth = { color = $color.bsp; - pipeline = bsp_depth; tasks = ( { func = bsp_draw_queue; params = (main, solid); }, { func = bsp_draw_queue; params = (main, sky); }, ); + + stages = ( + $brush.shader.depth_vertex, + ); + vertexInput = { + bindings = ( + "$brush.vertexInput.bindings[0]", + "$brush.vertexInput.bindings[1]", + ); + attributes = ( + "$brush.vertexInput.attributes[0]", + "$brush.vertexInput.attributes[1]", + ); + }; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; alias:depth = { color = $color.alias; - pipeline = alias_depth; tasks = ( { func = "alias_draw"; }, ); + + stages = ( + $alias.shader.depth_vertex, + ); + vertexInput = { + // depth pass doesn't use UVs + bindings = ( + "$alias.vertexInput.bindings[0]", + "$alias.vertexInput.bindings[1]", + ); + attributes = ( + "$alias.vertexInput.attributes[0]", + "$alias.vertexInput.attributes[1]", + "$alias.vertexInput.attributes[2]", + "$alias.vertexInput.attributes[3]", + ); + }; + inputAssembly = $alias.inputAssembly; + layout = $alias.layout; }; iqm:depth = { color = $color.iqm; - pipeline = iqm_depth; tasks = ( { func = "iqm_draw"; }, ); + + stages = ( + $iqm.shader.depth_vertex, + ); + vertexInput = $iqm.vertexInput; + inputAssembly = $iqm.inputAssembly; + layout = $iqm.layout; }; sprite:depth = { color = $color.sprite; - pipeline = sprite_depth; tasks = ( { func = "sprite_draw"; }, ); + + stages = ( + $sprite.shader.depth_vertex, + $sprite.shader.depth_fragment, + ); + vertexInput = $sprite.vertexInput; + inputAssembly = $sprite.inputAssembly; + layout = $sprite.layout; }; }; }; @@ -239,32 +715,71 @@ renderpasses = { }; preserve = (color, emission, normal, position, output); }; + base_pipeline = $pipeline_base; pipelines = { - bsp:sky = { + bsp:skybox = { color = $color.bsp; - pipeline = $bsp_sky_pipeline; tasks = ( // FIXME sky should not use OIT { func = bsp_draw_queue; params = (main, sky); }, ); + + stages = ( + $brush.shader.quake_vertex, + $brush.shader.skybox_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; + }; + bsp:skysheet = { + color = $color.bsp; + tasks = ( + // FIXME sky should not use OIT + { func = bsp_draw_queue; + params = (main, sky); }, + ); + + stages = ( + $brush.shader.quake_vertex, + $brush.shader.skysheet_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; bsp:trans = { color = $color.bsp; - pipeline = bsp_turb; tasks = ( { func = bsp_draw_queue; params = (main, translucent); }, { func = bsp_draw_queue; params = (main, turbulent); }, ); + + stages = ( + $brush.shader.quake_vertex, + $brush.shader.turb_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; particles:trans = { color = $color.particles; - pipeline = partdraw; tasks = ( { func = particles_draw; }, ); + + stages = ( + $particle.shader.vertex, + $particle.shader.geometry, + $particle.shader.fragment, + ); + vertexInput = $particle.vertexInput; + inputAssembly = $particle.inputAssembly; + layout = $particle.layout; }; }; }; @@ -275,47 +790,89 @@ renderpasses = { }; attachments = { color = { - color = color_attachment_optimal; - emission = color_attachment_optimal; - normal = color_attachment_optimal; - position = color_attachment_optimal; + color = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; + emission = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; + normal = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; + position = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; }; depth = { depth = depth_stencil_read_only_optimal; }; preserve = (output); }; + base_pipeline = $pipeline_base; pipelines = { bsp:gbuffer = { color = $color.bsp; - pipeline = bsp_gbuf; tasks = ( { func = bsp_draw_queue; params = (main, solid); }, { func = bsp_draw_queue; params = (main, sky); }, ); + + stages = ( + $brush.shader.gbuf_vertex, + $brush.shader.gbuf_geometry, + $brush.shader.gbuf_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; alias:gbuffer = { color = $color.alias; - pipeline = alias_gbuf; tasks = ( { func = "alias_draw"; }, ); + + stages = ( + $alias.shader.gbuf_vertex, + $alias.shader.gbuf_fragment, + ); + vertexInput = $alias.vertexInput; + inputAssembly = $alias.inputAssembly; + layout = $alias.layout; }; iqm:gbuffer = { color = $color.iqm; - pipeline = iqm_gbuf; tasks = ( { func = "iqm_draw"; }, ); + + stages = ( + $iqm.shader.gbuf_vertex, + $iqm.shader.gbuf_fragment, + ); + vertexInput = $iqm.vertexInput; + inputAssembly = $iqm.inputAssembly; + layout = $iqm.layout; }; sprite:gbuffer = { color = $color.sprite; - pipeline = sprite_gbuf; tasks = ( { func = "sprite_draw"; }, ); + + stages = ( + $sprite.shader.gbuf_vertex, + $sprite.shader.gbuf_fragment, + ); + vertexInput = $sprite.vertexInput; + inputAssembly = $sprite.inputAssembly; + layout = $sprite.layout; }; }; }; @@ -333,17 +890,27 @@ renderpasses = { position = shader_read_only_optimal; }; color = { - opaque = color_attachment_optimal; + opaque = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; }; preserve = (output); }; pipelines = { lights = { + @inherit = $compose_base; + color = $color.lights; - pipeline = lighting; tasks = ( { func = "lights_draw"; }, ); + + stages = ( + $fstriangle.shader.vertex, + $lighting.shader.fragment, + ); + layout = lighting.layout; }; }; }; @@ -363,17 +930,24 @@ renderpasses = { }; pipelines = { compose = { + @inherit = $compose_base; + color = $color.compose; - pipeline = compose; tasks = ( { func = "compose_draw"; }, ); + + stages = ( + $fstriangle.shader.vertex, + $compose.shader.fragment, + ); + layout = compose.layout; }; }; }; }; }; -/* deferred_cube = { + /*deferred_cube = { @inherit = $renderpasses.deferred; @next = (VkRenderPassMultiviewCreateInfo, { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 5b00d1026..cacd19acc 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -123,6 +123,57 @@ write_function_tail (Struct *self) fprintf (output_file, "}\n"); } +static void +write_parse_type (Struct *self) +{ + fprintf (output_file, "\t\treturn PL_ParseStruct (%s_fields, item, data, " + "messages, context);\n", [self outname]); +} + +static void +write_auto_parse (Struct *self, string field) +{ + fprintf (output_file, "\t\tdo {\n"); + fprintf (output_file, "\t\t\tplfield_t *f = find_field (%s_fields, %s, " + "item, messages);\n", [self outname], sprintf ("\"%s\"", field)); + fprintf (output_file, "\t\t\tif (!f) {\n"); + fprintf (output_file, "\t\t\t\treturn 0;"); + fprintf (output_file, "\t\t\t};\n"); + fprintf (output_file, "\t\t\tf->parser (f, item, &%s, messages, context);\n", + sprintf ("((%s *) data)->%s", [self outname], field)); + fprintf (output_file, "\t\t} while (0);\n"); +} + +static int +check_need_table (Struct *self, PLItem *field_dict, string type) +{ + string key = nil; + switch (type) { + case "QFDictionary": key = ".dictionary"; break; + case "QFArray": key = ".array"; break; + case "QFBinary": key = ".binary"; break; + case "QFString": key = ".string"; break; + } + PLItem *type_obj = [field_dict getObjectForKey:key]; + int count = [type_obj numKeys]; + if (!count) { + return 0; + } + for (int i = 0; i < count; i++) { + string field = [type_obj keyAtIndex:i]; + PLItem *item = [type_obj getObjectForKey:field]; + string str = [item string]; + + if (field == ".parse") { + return 1; + } + if (str == "$auto") { + return 1; + } + } + return 0; +} + static void write_type (Struct *self, PLItem *field_dict, string type) { @@ -145,6 +196,11 @@ write_type (Struct *self, PLItem *field_dict, string type) PLItem *item = [type_obj getObjectForKey:field]; string str = [item string]; + if (field == ".parse") { + write_parse_type (self); + continue; + } + switch (str) { case "$item.string": str = "vkstrdup (context, PL_String (item))"; @@ -158,6 +214,9 @@ write_type (Struct *self, PLItem *field_dict, string type) case "$index": str = "field->offset"; break; + case "$auto": + write_auto_parse (self, field); + continue; } fprintf (output_file, "\t\t((%s *) data)->%s = %s;\n", [self outname], field, str); @@ -166,6 +225,45 @@ write_type (Struct *self, PLItem *field_dict, string type) fprintf (output_file, "\t}\n"); } +static void +write_parser (Struct *self, int have_sType, PLItem *only) +{ + write_function_head (self); + if (have_sType) { + fprintf (output_file, "\t((%s *) data)->sType", [self outname]); + fprintf (output_file, " = %s;\n", [self sTypeName]); + } + if (self.label_field) { + fprintf (output_file, "\t((%s *) data)->%s", [self outname], + self.label_field); + fprintf (output_file, " = vkstrdup (context, field->name);\n"); + } + if (only) { + fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", + [self outname]); + fprintf (output_file, + "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" + "\t\tPL_TypeMismatch (messages, item, " + "f->name, f->type, PL_Type (item));\n" + "\t\treturn 0;\n" + "\t}\n" + "\tvoid *flddata = (byte *)data + f->offset;\n" + "\treturn f->parser (f, item, flddata, messages, " + "context);\n"); + } else { + fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", " + "messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" + "\treturn PL_ParseStruct (%s_fields, item, data, " + "messages, context);\n", + [self outname], [self outname]); + } + write_function_tail (self); +} + static void write_cexpr (Struct *self, Array *field_defs) { @@ -210,6 +308,61 @@ write_cexpr (Struct *self, Array *field_defs) fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]); } +static void +write_table (Struct *self, PLItem *field_dict, Array *field_defs, + PLItem *only, int need_parser) +{ + qfot_type_t *type = self.type; + int have_sType = 0; + int have_pNext = 0; + int readonly = [field_dict string] == "readonly"; + + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *field = &type.strct.fields[i]; + if (field.name == "sType") { + have_sType = 1; + } + if (field.name == "pNext") { + have_pNext = 1; + self.write_symtab = 1; + } + } + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeParseData]; + } + if (!readonly) { + fprintf (output_file, "static plfield_t %s_fields[] = {\n", + [self outname]); + if (!only) { + 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]; + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); + + if (need_parser) { + write_parser (self, have_sType, only); + } + 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]); + } + } +} + -(void) writeTable { if ([parse string] == "skip") { @@ -278,7 +431,19 @@ write_cexpr (Struct *self, Array *field_defs) if ([field_dict getObjectForKey:".type"]) { PLItem *type = [field_dict getObjectForKey:".type"]; string str = [type string]; + int need_table = 0; + if (str) { + need_table |= check_need_table (self, field_dict, str); + } else { + for (int i = [type count]; i-- > 0; ) { + string str = [[type getObjectAtIndex:i] string]; + need_table |= check_need_table (self, field_dict, str); + } + } + if (need_table) { + write_table (self, field_dict, field_defs, only, 0); + } write_function_head (self); fprintf (output_file, "\tpltype_t type = PL_Type (item);\n"); if (str) { @@ -298,85 +463,7 @@ write_cexpr (Struct *self, Array *field_defs) return; } - int have_sType = 0; - int have_pNext = 0; - int readonly = [field_dict string] == "readonly"; - - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *field = &type.strct.fields[i]; - if (field.name == "sType") { - have_sType = 1; - } - if (field.name == "pNext") { - have_pNext = 1; - write_symtab = 1; - } - } - for (int i = [field_defs count]; i-- > 0; ) { - FieldDef *field_def = [field_defs objectAtIndex:i]; - [field_def writeParseData]; - } - if (!readonly) { - fprintf (output_file, "static plfield_t %s_fields[] = {\n", - [self outname]); - if (!only) { - 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]; - } - fprintf (output_file, "\t{ }\n"); - fprintf (output_file, "};\n"); - - write_function_head (self); - if (have_sType) { - fprintf (output_file, "\t((%s *) data)->sType", [self outname]); - fprintf (output_file, " = %s;\n", [self sTypeName]); - } - if (label_field) { - fprintf (output_file, "\t((%s *) data)->%s", [self outname], - label_field); - fprintf (output_file, " = vkstrdup (context, field->name);\n"); - } - if (only) { - fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", - [self outname]); - fprintf (output_file, - "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" - "\t\tPL_TypeMismatch (messages, item, " - "f->name, f->type, PL_Type (item));\n" - "\t\treturn 0;\n" - "\t}\n" - "\tvoid *flddata = (byte *)data + f->offset;\n" - "\treturn f->parser (f, item, flddata, messages, " - "context);\n"); - } else { - fprintf (output_file, - "\tif (PL_Type (item) == QFString\n" - "\t\t&& !(item = parse_reference (item, \"%s\", " - "messages, context))) {\n" - "\t\treturn 0;\n" - "\t}\n" - "\treturn PL_ParseStruct (%s_fields, item, data, " - "messages, context);\n", - [self outname], [self outname]); - } - write_function_tail (self); - 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]); - } - } + write_table (self, field_dict, field_defs, only, 1); write_cexpr (self, field_defs); } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index b0b256446..bfda002e5 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -152,6 +152,19 @@ typedef struct parse_custom_s { size_t num_offsets; } parse_custom_t; +static plfield_t *__attribute__((used)) +find_field (plfield_t *fields, const char *field_name, + const plitem_t *item, plitem_t *messages) +{ + for (plfield_t *f = fields; f->name; f++) { + if (strcmp (f->name, field_name) == 0) { + return f; + } + } + PL_Message (messages, item, "error: unknown field %s", field_name); + return 0; +} + static int parse_basic (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -355,7 +368,7 @@ parse_single (const plfield_t *field, const plitem_t *item, return 0; } - plfield_t f = { 0, 0, single->type, single->parser, 0 }; + plfield_t f = { field->name, 0, single->type, single->parser, 0 }; void *value = vkparse_alloc (context, single->stride); memset (value, 0, single->stride); if (!single->parser (&f, item, value, messages, context)) { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 49fc3ca6a..45afa14ab 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -46,6 +46,7 @@ qfv_framebufferinfo_t, qfv_renderpassinfo_t, qfv_renderinfo_t, + qfv_pipelinespec_t, ); parse = { VkSubpassDescription = { @@ -436,7 +437,16 @@ }; qfv_attachmentrefinfo_s = { .name = qfv_attachmentrefinfo_t; - .only = layout; + .type = (QFString, QFDictionary); + .string = { + name = $name; + layout = $auto; + }; + .dictionary = { + .parse = auto; + }; + layout = auto; + blend = auto; }; qfv_attachmentsetinfo_s = { .name = qfv_attachmentsetinfo_t; @@ -477,12 +487,58 @@ type = string; string = name; }; - pipeline = auto; tasks = { type = (array, qfv_taskinfo_t); size = num_tasks; values = tasks; - } + }; + + flags = auto; + stages = { + type = (array, VkPipelineShaderStageCreateInfo); + size = num_graph_stages; + values = graph_stages; + }; + vertexInput = { + type = (single, VkPipelineVertexInputStateCreateInfo); + value = vertexInput; + }; + inputAssembly = { + type = (single, VkPipelineInputAssemblyStateCreateInfo); + value = inputAssembly; + }; + tessellation = { + type = (single, VkPipelineTessellationStateCreateInfo); + value = tessellation; + }; + viewport = { + type = (single, VkPipelineViewportStateCreateInfo); + value = viewport; + }; + rasterization = { + type = (single, VkPipelineRasterizationStateCreateInfo); + value = rasterization; + }; + multisample = { + type = (single, VkPipelineMultisampleStateCreateInfo); + value = multisample; + }; + depthStencil = { + type = (single, VkPipelineDepthStencilStateCreateInfo); + value = depthStencil; + }; + colorBlend = { + type = (single, VkPipelineColorBlendStateCreateInfo); + value = colorBlend; + }; + dynamic = { + type = (single, VkPipelineDynamicStateCreateInfo); + value = dynamic; + }; + layout = { + type = (single, qfv_reference_t); + value = layout; + }; }; qfv_subpassinfo_s = { .name = qfv_subpassinfo_t; @@ -505,6 +561,11 @@ size = num_pipelines; values = pipelines; }; + base_pipeline = { + //type = (labeledsingle, qfv_pipelineinfo_t, name); + type = (single, qfv_pipelineinfo_t, name); + value = base_pipeline; + }; }; qfv_framebufferinfo_s = { .name = qfv_framebufferinfo_t; @@ -557,6 +618,6 @@ size = num_renderpasses; values = renderpasses; }; - } + }; }; }