[vulkan] Use a property list to drive code gen

The property list specifies the base structures for which parser code
will be generated (along with any structures and enums upon which those
structures depend). It also defines option specialized parsers for
better control.
This commit is contained in:
Bill Currie 2020-07-05 14:59:56 +09:00
parent 7a478b4ce7
commit 0945f30731
9 changed files with 382 additions and 41 deletions

View file

@ -223,18 +223,18 @@ libs/video/renderer/vulkan/vulkan_vid_common.c: $(vkparse_src)
qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT)
vkparse_src = \
libs/video/renderer/vulkan/vkenum.inc \
libs/video/renderer/vulkan/vkstruct.inc
libs/video/renderer/vulkan/vkparse.inc
vkparse_plist = \
$(srcdir)/libs/video/renderer/vulkan/vkparse.plist
V_VKGEN = $(V_VKGEN_@AM_V@)
V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@)
V_VKGEN_0 = @echo " VKGEN " $@;
V_VKGEN_1 =
libs/video/renderer/vulkan/vkenum.inc: $(vkgen) $(qwaq_curses)
$(V_VKGEN)$(qwaq_curses) $(vkgen) -- enum $@
libs/video/renderer/vulkan/vkstruct.inc: $(vkgen) $(qwaq_curses)
$(V_VKGEN)$(qwaq_curses) $(vkgen) -- struct $@
libs/video/renderer/vulkan/vkparse.inc: $(vkgen) $(qwaq_curses) $(vkparse_plist)
$(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) $@.t &&\
$(am__mv) $@.t $@
CLEANFILES += \
libs/video/renderer/glsl/*.vc \

View file

@ -49,4 +49,58 @@
}
}
}
-(string) parseType
{
Type *alias = [Type findType:type.alias.full_type];
string name = [self name];
if ([alias name] == "VkFlags") {
if (str_mid (name, -5) == "Flags") {
string tag = str_mid (name, 0, -1) + "Bits";
id enumObj = [(id) Hash_Find (available_types, tag) resolveType];
return [enumObj parseType];
}
}
if (name == "uint32_t") {
return "QFString";
}
return [alias parseType];
}
-(string) parseFunc
{
Type *alias = [Type findType:type.alias.full_type];
string name = [self name];
if ([alias name] == "VkFlags") {
if (str_mid (name, -5) == "Flags") {
string tag = str_mid (name, 0, -1) + "Bits";
id enumObj = [(id) Hash_Find (available_types, tag) resolveType];
return [enumObj parseFunc];
}
}
if (name == "uint32_t") {
return "parse_uint32_t";
}
return [alias parseFunc];
}
-(string) parseData
{
Type *alias = [Type findType:type.alias.full_type];
string name = [self name];
if ([alias name] == "VkFlags") {
if (str_mid (name, -5) == "Flags") {
string tag = str_mid (name, 0, -1) + "Bits";
id enumObj = [(id) Hash_Find (available_types, tag) resolveType];
return [enumObj parseData];
}
}
if (name == "uint32_t") {
return "0";
}
return [alias parseData];
}
@end

View file

@ -82,4 +82,22 @@
fprintf (output_file, "\t{ }\n");
fprintf (output_file, "};\n");
}
-(string) parseType
{
return "QFString";
}
-(string) parseFunc
{
if (str_mid([self name], -8) == "FlagBits") {
return "parse_flags";
}
return "parse_enum";
}
-(string) parseData
{
return [self name] + "_values";
}
@end

View file

@ -4,11 +4,28 @@
#include <string.h>
#include <types.h>
#include <Array.h>
#include <AutoreleasePool.h>
#include <PropertyList.h>
#include "vkgen.h"
#include "vkstruct.h"
#include "vkenum.h"
static AutoreleasePool *autorelease_pool;
static void
arp_start (void)
{
autorelease_pool = [[AutoreleasePool alloc] init];
}
static void
arp_end (void)
{
[autorelease_pool release];
autorelease_pool = nil;
}
void printf (string fmt, ...) = #0;
void fprintf (QFile file, string format, ...)
@ -16,11 +33,6 @@ void fprintf (QFile file, string format, ...)
Qputs (file, vsprintf (format, va_copy (@args)));
}
string search_names[] = {
"VkGraphicsPipelineCreateInfo",
"VkComputePipelineCreateInfo",
};
#define numsearch (sizeof (search_names) / sizeof (search_names[0]))
hashtab_t *available_types;
hashtab_t *processed_types;
Array *queue;
@ -123,7 +135,7 @@ get_object_key (void *obj, void *unused)
void
usage (string name)
{
printf ("%s [struct|enum] [output file]\n", name);
printf ("%s [plist file] [output file]\n", name);
}
int
@ -131,36 +143,51 @@ main(int argc, string *argv)
{
int do_struct = 0;
int do_enum = 0;
string plist_filename;
QFile plist_file;
PLItem *plist;
PLItem *search;
PLItem *parse;
arp_start ();
if (argc != 3) {
usage (argv[0]);
return 1;
}
switch (argv[1]) {
case "struct":
do_struct = 1;
break;
case "enum":
do_enum = 1;
break;
default:
usage (argv[0]);
return 1;
plist_filename = argv[1];
plist_file = Qopen (plist_filename, "rt");
if (!plist_file) {
printf ("could not open property list file: %s\n", plist_filename);
return 1;
}
plist = [[PLItem fromFile: plist_file] retain];
if (!plist) {
printf ("error parsing: %s\n", plist_filename);
return 1;
}
Qclose (plist_file);
if ([plist class] != [PLDictionary class]) {
printf ("%s not a dictionary\n", plist_filename);
}
search = [[plist getObjectForKey: "search"] retain];
parse = [[plist getObjectForKey: "parse"] retain];
encodings = PR_FindGlobal (".type_encodings");
if (!encodings) {
printf ("Can't find encodings\n");
return 1;
}
queue = [[Array alloc] init];
output_types = [[Array alloc] init];
queue = [[Array array] retain];
output_types = [[Array array] retain];
available_types = Hash_NewTable (127, get_object_key, nil, nil);
processed_types = Hash_NewTable (127, get_string_key, nil, nil);
scan_types ();
for (int i = 0;
i < sizeof (search_names) / sizeof (search_names[0]); i++) {
id obj = (id) Hash_Find (available_types, search_names[i]);
for (int i = [search numObjects]; i-- > 0; ) {
PLString *str = (PLString *) [search getObjectAtIndex:i];
string search_name = [str string];
id obj = (id) Hash_Find (available_types, search_name);
obj = [obj resolveType];
printf("obj: %d %s\n", obj, class_get_class_name([obj class]));
if (obj && [obj class] == [Struct class]) {
@ -181,20 +208,34 @@ main(int argc, string *argv)
printf ("vkgen %d %s\n", i, argv[i]);
}
arp_end ();
output_file = Qopen (argv[2], "wt");
for (int i = [output_types count]; i-- > 0; ) {
id obj = [output_types objectAtIndex:i];
if ([obj name] == "VkStructureType") {
continue;
}
printf("obj: %d %s\n", obj, class_get_class_name([obj class]));
if (do_struct && [obj class] != [Struct class]) {
continue;
}
if (do_enum && [obj class] != [Enum class]) {
if ([obj class] != [Enum class]) {
continue;
}
arp_start ();
[obj writeTable];
arp_end ();
}
for (int i = [output_types count]; i-- > 0; ) {
id obj = [output_types objectAtIndex:i];
if ([obj name] == "VkStructureType") {
continue;
}
if ([obj class] != [Struct class]) {
continue;
}
arp_start ();
[obj writeTable:parse];
arp_end ();
}
Qclose (output_file);
return 0;

View file

@ -6,11 +6,13 @@
#include "vkgen.h"
#include "vktype.h"
@class PLItem;
@interface Struct: Type
{
}
-(void) forEachFieldCall: (varfunc) func;
-(void) writeTable;
-(void) writeTable: (PLItem *) parse;
@end
#endif//__renderer_vulkan_vkgen_vkstruct_h

View file

@ -4,6 +4,7 @@
#include <string.h>
#include <types.h>
#include <Array.h>
#include <PropertyList.h>
#include "vkgen.h"
#include "vkstruct.h"
@ -34,20 +35,144 @@
}
}
-(void) writeTable
-(qfot_var_t *)findField:(string) fieldName
{
fprintf (output_file, "structfld_t %s_fields[] = {\n", [self name]);
for (int i = 0; i < type.strct.num_fields; i++) {
qfot_var_t *var = &type.strct.fields[i];
if (var.name == "sType" || var.name == "pNext") {
continue;
if (var.name == fieldName) {
return var;
}
}
return nil;
}
-(void) writeTable: (PLItem *) parse
{
PLItem *field_dict = [parse getObjectForKey:[self name]];
PLItem *field_defs = [field_dict allKeys];
Type *field_type;
if (field_defs) {
PLItem *field_def;
qfot_var_t *field;
for (int i = [field_defs count]; i-- > 0; ) {
string field_name = [[field_defs getObjectAtIndex:i] string];
field_def = [field_dict getObjectForKey:field_name];
PLItem *type_desc = [field_def getObjectForKey:"type"];
string type_record;
string type_type;
string size_field = nil;
string value_field = nil;
if (!type_desc) {
continue;
}
type_record = [[type_desc getObjectAtIndex:0] string];
type_type = [[type_desc getObjectAtIndex:1] string];
field_type = [[Type lookup: type_type] dereference];
fprintf (output_file, "static parse_%s_t parse_%s_%s_data = {\n",
type_record, [self name], field_name);
fprintf (output_file, "\tparse_%s,\n", type_type);
if (type_record == "single") {
value_field = [[field_def getObjectForKey:"value"] string];
fprintf (output_file, "\tfield_offset (%s, %s),\n",
[self name], value_field);
} else {
value_field = [[field_def getObjectForKey:"values"] string];
size_field = [[field_def getObjectForKey:"size"] string];
fprintf (output_file, "\tfield_offset (%s, %s),\n",
[self name], value_field);
if (size_field) {
fprintf (output_file, "\tfield_offset (%s, %s),\n",
[self name], size_field);
} else {
fprintf (output_file, "\t-1,\n");
}
}
fprintf (output_file, "};\n");
}
}
fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self name]);
if (field_defs) {
PLItem *field_def;
qfot_var_t *field;
for (int i = [field_defs count]; i-- > 0; ) {
string field_name = [[field_defs getObjectAtIndex:i] string];
field_def = [field_dict getObjectForKey:field_name];
if ([field_def string] == "auto") {
field = [self findField:field_name];
if (!field) {
continue;
}
field_type = [Type findType: field.type];
fprintf (output_file,
"\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n",
field_name, [self name], field_name,
[field_type parseType], [field_type parseFunc],
[field_type parseData]);
} else {
PLItem *type_desc = [field_def getObjectForKey:"type"];
string type_record;
string type_type;
string parseType;
type_record = [[type_desc getObjectAtIndex:0] string];
type_type = [[type_desc getObjectAtIndex:1] string];
field_type = [[Type lookup: type_type] dereference];
if (type_record == "single") {
parseType = [field_type parseType];
} else {
parseType = "QFArray";
}
fprintf (output_file,
"\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n",
field_name, parseType, type_record,
[self name], field_name);
}
}
} else {
for (int i = 0; i < type.strct.num_fields; i++) {
qfot_var_t *field = &type.strct.fields[i];
if (field.name == "sType" || field.name == "pNext") {
continue;
}
field_type = [Type findType: field.type];
fprintf (output_file,
"\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n",
field.name, [self name], field.name,
[field_type parseType], [field_type parseFunc],
[field_type parseData]);
}
string type_name = var.type.encoding;
fprintf (output_file,
"\t{\"%s\", field_offset (%s, %s), %s, %s}, // %s\n",
var.name, [self name], var.name, "0", "0", type_name);
}
fprintf (output_file, "\t{ }\n");
fprintf (output_file, "};\n");
fprintf (output_file, "static int parse_%s (const plfield_t *field,"
" const plitem_t *item, void *data, plitem_t *messages)\n",
[self name]);
fprintf (output_file, "{\n");
fprintf (output_file,
"\treturn PL_ParseDictionary (%s_fields, item, data, messages);\n",
[self name]);
fprintf (output_file, "}\n");
}
-(string) parseType
{
return "QFDictionary";
}
-(string) parseFunc
{
return "fix me";
}
-(string) parseData
{
return "0";
}
@end

View file

@ -18,6 +18,13 @@
-(void) addToQueue;
-(Type *) resolveType;
+(Type *) findType: (qfot_type_t *) type;
+(Type *) lookup: (string) name;
-(string) parseType;
-(string) parseFunc;
-(string) parseData;
-(int) isPointer;
-(Type *) dereference;
@end
#endif//__renderer_vulkan_vkgen_vktype_h

View file

@ -38,6 +38,11 @@ static string get_type_key (void *type, void *unused)
return (Type *) Hash_Find (registered_types, type.encoding);
}
+(Type *) lookup: (string) name
{
return (Type *) Hash_Find (available_types, name);
}
+fromType: (qfot_type_t *) type
{
if (type.size == 0) {
@ -86,4 +91,40 @@ static string get_type_key (void *type, void *unused)
return self;
}
-(string) parseType
{
return "no parse";
}
-(string) parseFunc
{
return "0";
}
-(string) parseData
{
return "0";
}
-(int) isPointer
{
if ((type.meta == ty_basic || type.meta == ty_alias)
&& type.type == ev_pointer) {
return 1;
}
return 0;
}
-(Type *) dereference
{
qfot_type_t *t = type;
if (t.meta == ty_alias) {
t = type.alias.full_type;
}
if (t.meta == ty_basic && t.type == ev_pointer) {
t = type.fldptr.aux_type;
}
return [Type findType:t];
}
@end

View file

@ -0,0 +1,53 @@
{
search = (
VkRenderPassCreateInfo
);
parse = {
VkRenderPassCreateInfo = {
flags = auto;
attachments = {
type = (array, VkAttachmentDescription);
size = attachmentCount;
values = pAttachments;
};
subpasses = {
type = (array, VkSubpassDescription);
size = subpassCount;
values = pSubpasses;
};
dependencies = {
type = (array, VkSubpassDependency);
size = dependencyCount;
values = pDependencies;
};
};
VkSubpassDescription = {
flags = auto;
pipelineBindPoint = auto;
inputAttachments = {
type = (array, VkAttachmentReference);
size = inputAttachmentCount;
values = pInputAttachments;
};
colorAttachments = {
type = (array, VkAttachmentReference);
size = colorAttachmentCount;
values = pColorAttachments;
};
resolveAttachments = {
type = (array, VkAttachmentReference);
values = pResolveAttachments;
matchSize = colorAttachments;
};
depthStencilAttachment = {
type = (single, VkAttachmentReference);
value = pDepthStencilAttachment;
};
preserveAttachments = {
type = (array, uint32_t);
size = preserveAttachmentCount;
values = pPreserveAttachments;
};
}
}
}