quakeforge/libs/video/renderer/vulkan/vkgen/vkstruct.r
Bill Currie e5932d1f92 [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).
2022-09-22 09:35:56 +09:00

270 lines
6.8 KiB
R

#include <hash.h>
#include <qfile.h>
#include <runtime.h>
#include <string.h>
#include <types.h>
#include <Array.h>
#include <PropertyList.h>
#include "vkfielddef.h"
#include "vkgen.h"
#include "vkstruct.h"
@implementation Struct
-(string) name
{
return str_mid(type.strct.tag, 4);
}
-(void) addToQueue
{
string name = [self name];
if (!Hash_Find (processed_types, name)) {
//printf (" +%s\n", name);
Hash_Add (processed_types, (void *) name);
[queue addObject: self];
}
}
-(void) queueFieldTypes
{
qfot_struct_t *strct =&type.strct;
PLItem *field_dict = [parse getObjectForKey:[self name]];
for (int i = 0; i < strct.num_fields; i++) {
qfot_var_t *var = &strct.fields[i];
if (field_dict) {
PLItem *item = [field_dict getObjectForKey:var.name];
FieldDef *def = [FieldDef fielddef:item
struct:self
field:var.name];
if (![def searchType]) {
continue;
}
}
Type *type = [Type findType:var.type];
[type addToQueue];
}
}
-(qfot_var_t *)findField:(string) fieldName
{
for (int i = 0; i < type.strct.num_fields; i++) {
qfot_var_t *var = &type.strct.fields[i];
if (var.name == fieldName) {
return var;
}
}
return nil;
}
-(string)sTypeName
{
string s = "VK_STRUCTURE_TYPE";
string name = str_hold ([self outname]);
int length = strlen (name);
int start, end, c;
for (start = 2; start < length; start = end) {
for (end = start + 1; end < length; end++) {
c = str_char (name, end);
if (c >= 'A' && c <= 'Z') {
break;
}
}
s += "_" + str_mid (name, start, end);
}
str_free (name);
return str_upper (s);
}
-(void) writeTable
{
PLItem *field_dict = [parse getObjectForKey:[self name]];
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;
}
if (new_name) {
outname = str_hold ([new_name string]);
}
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;
}
}
if (field_dict) {
PLItem *field_keys = [field_dict allKeys];
for (int i = [field_keys count]; i-- > 0; ) {
string field_name = [[field_keys getObjectAtIndex:i] string];
if (str_mid(field_name, 0, 1) == ".") {
continue;
}
PLItem *field_item = [field_dict getObjectForKey:field_name];
FieldDef *field_def = [FieldDef fielddef:field_item
struct:self
field:field_name];
[field_defs addObject: field_def];
}
} 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;
}
FieldDef *field_def = [FieldDef fielddef:nil
struct:self
field:field.name];
[field_defs addObject: field_def];
}
}
for (int i = [field_defs count]; i-- > 0; ) {
FieldDef *field_def = [field_defs objectAtIndex:i];
[field_def writeParseData];
}
fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]);
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");
fprintf (header_file, "int %s (const plfield_t *field,"
" const plitem_t *item, void *data, plitem_t *messages,"
" void *context);\n",
[self parseFunc]);
fprintf (output_file, "int %s (const plfield_t *field,"
" const plitem_t *item, void *data, plitem_t *messages,"
" void *context)\n",
[self parseFunc]);
fprintf (output_file, "{\n");
if (have_sType) {
fprintf (output_file, "\t((%s *) data)->sType", [self outname]);
fprintf (output_file, " = %s;\n", [self sTypeName]);
}
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]);
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) {
PLItem *field_def;
qfot_var_t *field;
for (int i = [field_defs count]; i-- > 0; ) {
FieldDef *field_def = [field_defs objectAtIndex:i];
[field_def writeSymbol];
}
} 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;
}
Type *field_type = [Type findType: field.type];
fprintf (output_file,
"\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n",
field.name, [field_type cexprType], [self outname], field.name);
}
}
fprintf (output_file, "\t{ }\n");
fprintf (output_file, "};\n");
fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self outname]);
fprintf (output_file, "\t%s_symbols,\n", [self outname]);
fprintf (output_file, "};\n");
fprintf (output_file, "exprtype_t %s_type = {\n", [self outname]);
fprintf (output_file, "\t.name = \"%s\",\n", [self outname]);
fprintf (output_file, "\t.size = sizeof (%s),\n", [self outname]);
fprintf (output_file, "\t.binops = cexpr_struct_binops,\n");
fprintf (output_file, "\t.unops = 0,\n");
fprintf (output_file, "\t.data = &%s_symtab,\n", [self outname]);
fprintf (output_file, "};\n");
fprintf (output_file, "\n");
fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]);
}
-(void) writeSymtabInit
{
PLItem *field_dict = [parse getObjectForKey:[self outname]];
if ([parse string] == "skip") {
return;
}
fprintf (output_file, "\tcexpr_init_symtab (&%s_symtab, context);\n",
[self outname]);
}
-(void) writeSymtabEntry
{
if (!write_symtab || [parse string] == "skip") {
return;
}
fprintf (output_file,
"\tHash_Add (parser_table, &%s_parser);\n",
[self outname]);
}
-(string) outname
{
if (outname) {
return outname;
}
return [self name];
}
-(string) cexprType
{
return [self outname] + "_type";
}
-(string) parseType
{
return "QFMultiType | (1 << QFString) | (1 << QFDictionary)";
}
-(string) parseFunc
{
return "parse_" + [self outname];
}
-(string) parseData
{
return "0";
}
@end