mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
[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:
parent
7a478b4ce7
commit
0945f30731
9 changed files with 382 additions and 41 deletions
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
53
libs/video/renderer/vulkan/vkparse.plist
Normal file
53
libs/video/renderer/vulkan/vkparse.plist
Normal 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue