[vkgen] Improve .type parse spec handling

.dictionary can ask for standard parsing via a .parse key (value is
ignored currently).

Fields can use $auto to use standard parsing for that field.

If either is used, the plist field descriptors are written.
This commit is contained in:
Bill Currie 2023-02-18 17:00:52 +09:00
parent d89ad6b00f
commit 868db37461
7 changed files with 857 additions and 115 deletions

View file

@ -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 {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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