quakeforge/libs/video/renderer/vulkan/vkgen/vkgen.r
Bill Currie 6d5e8922a5 [qfcc] Add a handle type for engine resources
I never liked the various hacks I had come up with for representing
resource handles in Ruamoko. Structs with an int were awkward to test,
pointers and ints could be modified, etc etc. The new @handle keyword (@
used to keep handle free for use) works just like struct, union and
enum in syntax, but creates an opaque type suitable for a 32-bit handle.
The backing type is a function so v6 progs can use it without (all the
necessary opcodes exist) and no modifications were needed for
type-checking in binary expressions, but only assignment and comparisons
are supported, and (of course) nil. Tested using cbuf_t and QFile: seems
to work as desired.

I had considered 64-bit handles, but really, if more than 4G resource
objects are needed, I'm not sure QF can handle the game. However, that
limit is per resource manager, not total.
2023-05-25 10:41:28 +09:00

276 lines
5.9 KiB
R

#include <hash.h>
#include <qfile.h>
#include <runtime.h>
#include <string.h>
#include <types.h>
#include <Array.h>
#include <AutoreleasePool.h>
#include <PropertyList.h>
#include "vkgen.h"
#include "vkstruct.h"
#include "vkfixedarray.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, ...)
{
Qputs (file, vsprintf (format, va_copy (@args)));
}
hashtab_t *available_types;
hashtab_t *processed_types;
Array *queue;
Array *output_types;
PLItem *parse;
QFile output_file;
QFile header_file;
qfot_type_encodings_t *encodings;
qfot_type_t *
next_type (qfot_type_t *type)
{
int size = type.size;
if (!size)
size = 4;
return (qfot_type_t *) ((int *) type + size);
}
int
type_is_null (qfot_type_t *type)
{
return type.size == 0;
}
void print_type (qfot_type_t *type)
{
//printf ("type: %p %d %d %s", type, type.meta, type.size, type.encoding);
switch (type.meta) {
case ty_basic:
//printf (" %d", type.type);
switch (type.type) {
case ev_ptr:
case ev_field:
//printf (" ");
print_type (type.fldptr.aux_type);
break;
case ev_func:
//printf (" %p %d\n", type.func.return_type,
// type.func.num_params);
default:
//printf ("\n");
break;
}
break;
case ty_struct:
case ty_union:
case ty_enum:
//printf (" %s %d\n", type.strct.tag, type.strct.num_fields);
break;
case ty_array:
//printf (" %p %d %d\n", type.array.type, type.array.base,
// type.array.size);
break;
case ty_class:
//printf (" %s\n", type.class);
break;
case ty_alias:
//printf (" %d %s ", type.alias.type, type.alias.name);
print_type (type.alias.aux_type);
break;
case ty_handle:
//printf (" %s\n", type.handle.tag);
break;
}
}
void
scan_types (void)
{
qfot_type_t *type;
for (type = encodings.types;
((int *)type - (int *) encodings.types) < encodings.size;
type = next_type (type)) {
if (type.size) {
string tag = str_mid(type.strct.tag, 4);
Type *avail_type = [Type fromType: type];
if (avail_type) {
if (!Hash_Find (available_types, [avail_type name])) {
//printf ("scan: %s %s\n", tag, [avail_type name]);
Hash_Add (available_types, avail_type);
}
}
}
}
}
static string
get_string_key (void *str, void *unused)
{
return (string) str;
}
static string
get_object_key (void *obj, void *unused)
{
return [(id)obj name];
}
static void
free_object (void *obj, void *unused)
{
[(id)obj release];
}
void
usage (string name)
{
printf ("%s [plist file] [output file] [header file]\n", name);
}
int
main(int argc, string *argv)
{
int do_struct = 0;
int do_enum = 0;
string plist_filename;
QFile plist_file;
PLItem *plist;
PLItem *search;
PLItem *handles;
arp_start ();
if (argc != 4) {
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 = [[PLDictionary 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);
return 1;
}
search = [[plist getObjectForKey: "search"] retain];
handles = [[plist getObjectForKey: "handles"] retain];
parse = [[plist getObjectForKey: "parse"] retain];
encodings = PR_FindGlobal (".type_encodings");
if (!encodings) {
printf ("Can't find encodings\n");
return 1;
}
queue = [[Array array] retain];
output_types = [[Array array] retain];
available_types = Hash_NewTable (127, get_object_key, free_object, nil);
processed_types = Hash_NewTable (127, get_string_key, nil, nil);
scan_types ();
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]
|| [obj class] == [Enum class])) {
[obj addToQueue];
}
}
while ([queue count]) {
id obj = [queue objectAtIndex:0];
[queue removeObjectAtIndex:0];
if ([obj class] == [Struct class]) {
string name = [obj name];
if (name == "char" // char type faked via a struct
|| [[parse getObjectForKey:name] string] == "skip") {
continue;
}
[obj queueFieldTypes];
}
[output_types addObject:obj];
}
for (int i = 0; i < argc; i++) {
//printf ("vkgen %d %s\n", i, argv[i]);
}
arp_end ();
output_file = Qopen (argv[2], "wt");
header_file = Qopen (argv[3], "wt");
for (int i = [output_types count]; i-- > 0; ) {
id obj = [output_types objectAtIndex:i];
if ([obj name] == "VkStructureType") {
continue;
}
arp_start ();
[obj writeForward];
[obj initParse:[parse getObjectForKey:[obj name]]];
arp_end ();
}
for (int i = [output_types count]; i-- > 0; ) {
id obj = [output_types objectAtIndex:i];
if ([obj name] == "VkStructureType") {
continue;
}
arp_start ();
[obj writeTable];
arp_end ();
}
fprintf (output_file, "static void\n");
fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n");
fprintf (output_file, "{\n");
for (int i = [output_types count]; i-- > 0; ) {
id obj = [output_types objectAtIndex:i];
if ([obj name] == "VkStructureType") {
continue;
}
arp_start ();
[obj writeSymtabInit];
[obj writeSymtabEntry];
arp_end ();
}
fprintf (output_file, "}\n");
Qclose (output_file);
Qclose (header_file);
Hash_DelTable (available_types);
[plist release];
[search release];
[handles release];
[parse release];
[queue release];
[output_types release];
return 0;
}