2020-07-16 06:42:49 +00:00
|
|
|
/*
|
|
|
|
vkparse.c
|
|
|
|
|
|
|
|
Parser for scripted vulkan structs
|
|
|
|
|
|
|
|
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2022-03-30 06:54:07 +00:00
|
|
|
#include <string.h>
|
2020-07-16 06:42:49 +00:00
|
|
|
|
2020-12-21 09:38:31 +00:00
|
|
|
#include "QF/cmem.h"
|
2020-07-16 06:42:49 +00:00
|
|
|
#include "QF/cvar.h"
|
2022-11-24 14:44:07 +00:00
|
|
|
#include "QF/dstring.h"
|
2021-01-04 08:26:39 +00:00
|
|
|
#include "QF/hash.h"
|
2020-07-16 06:42:49 +00:00
|
|
|
#include "QF/mathlib.h"
|
|
|
|
#include "QF/va.h"
|
2022-03-30 06:54:07 +00:00
|
|
|
|
2021-01-31 10:58:55 +00:00
|
|
|
#include "QF/Vulkan/debug.h"
|
2020-07-16 06:42:49 +00:00
|
|
|
#include "QF/Vulkan/device.h"
|
|
|
|
#include "QF/Vulkan/instance.h"
|
|
|
|
#include "QF/Vulkan/image.h"
|
2021-01-05 14:42:30 +00:00
|
|
|
#include "QF/Vulkan/pipeline.h"
|
2023-02-09 05:52:43 +00:00
|
|
|
#include "QF/Vulkan/render.h"
|
2020-12-23 16:36:17 +00:00
|
|
|
#include "QF/Vulkan/shader.h"
|
2020-07-16 06:42:49 +00:00
|
|
|
|
|
|
|
#include "vid_vulkan.h"
|
|
|
|
|
|
|
|
#include "vkparse.h"
|
2022-05-30 03:22:34 +00:00
|
|
|
#include "libs/video/renderer/vulkan/vkparse.hinc"
|
2020-07-16 06:42:49 +00:00
|
|
|
|
2022-04-02 02:42:36 +00:00
|
|
|
typedef struct parseres_s {
|
|
|
|
const char *name;
|
|
|
|
plfield_t *field;
|
|
|
|
size_t offset;
|
|
|
|
} parseres_t;
|
|
|
|
|
2022-05-29 12:53:38 +00:00
|
|
|
typedef struct parseref_s {
|
|
|
|
const char *name;
|
|
|
|
plparser_t parse;
|
|
|
|
size_t size;
|
|
|
|
} parserref_t;
|
|
|
|
|
2022-04-02 02:42:36 +00:00
|
|
|
typedef struct handleref_s {
|
|
|
|
char *name;
|
|
|
|
uint64_t handle;
|
|
|
|
} handleref_t;
|
|
|
|
|
2020-12-21 09:38:31 +00:00
|
|
|
static void flag_or (const exprval_t *val1, const exprval_t *val2,
|
|
|
|
exprval_t *result, exprctx_t *ctx)
|
|
|
|
{
|
|
|
|
*(int *) (result->value) = *(int *) (val1->value) | *(int *) (val2->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flag_and (const exprval_t *val1, const exprval_t *val2,
|
|
|
|
exprval_t *result, exprctx_t *ctx)
|
|
|
|
{
|
|
|
|
*(int *) (result->value) = *(int *) (val1->value) & *(int *) (val2->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flag_cast_int (const exprval_t *val1, const exprval_t *val2,
|
|
|
|
exprval_t *result, exprctx_t *ctx)
|
|
|
|
{
|
|
|
|
// FIXME should check value is valid
|
|
|
|
*(int *) (result->value) = *(int *) (val2->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void flag_not (const exprval_t *val, exprval_t *result, exprctx_t *ctx)
|
|
|
|
{
|
|
|
|
*(int *) (result->value) = ~(*(int *) (val->value));
|
|
|
|
}
|
|
|
|
|
|
|
|
binop_t flag_binops[] = {
|
|
|
|
{ '|', 0, 0, flag_or },
|
|
|
|
{ '&', 0, 0, flag_and },
|
|
|
|
{ '=', &cexpr_int, 0, flag_cast_int },
|
2021-02-04 13:37:20 +00:00
|
|
|
{ '=', &cexpr_plitem, 0, cexpr_cast_plitem },
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
binop_t enum_binops[] = {
|
|
|
|
{ '=', &cexpr_plitem, 0, cexpr_cast_plitem },
|
2020-12-21 09:38:31 +00:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
unop_t flag_unops[] = {
|
|
|
|
{ '~', 0, flag_not },
|
|
|
|
{}
|
|
|
|
};
|
2020-07-16 06:42:49 +00:00
|
|
|
|
|
|
|
typedef struct parse_single_s {
|
2020-07-16 15:29:53 +00:00
|
|
|
pltype_t type;
|
|
|
|
size_t stride;
|
2020-07-16 06:42:49 +00:00
|
|
|
plparser_t parser;
|
2023-02-10 10:33:10 +00:00
|
|
|
void *data;
|
2020-07-16 06:42:49 +00:00
|
|
|
size_t value_offset;
|
|
|
|
} parse_single_t;
|
|
|
|
|
|
|
|
typedef struct parse_array_s {
|
2020-07-16 15:29:53 +00:00
|
|
|
pltype_t type;
|
|
|
|
size_t stride;
|
2020-07-16 06:42:49 +00:00
|
|
|
plparser_t parser;
|
2023-02-10 10:33:10 +00:00
|
|
|
void *data;
|
2020-07-16 06:42:49 +00:00
|
|
|
size_t value_offset;
|
2020-07-16 15:29:53 +00:00
|
|
|
size_t size_offset;
|
2020-07-16 06:42:49 +00:00
|
|
|
} parse_array_t;
|
|
|
|
|
2021-12-04 01:08:27 +00:00
|
|
|
typedef struct parse_fixed_array_s {
|
|
|
|
pltype_t type;
|
|
|
|
size_t stride;
|
|
|
|
plparser_t parser;
|
2023-02-10 10:33:10 +00:00
|
|
|
void *data;
|
2021-12-04 01:08:27 +00:00
|
|
|
size_t size;
|
|
|
|
} parse_fixed_array_t;
|
|
|
|
|
2020-12-23 05:08:53 +00:00
|
|
|
typedef struct parse_data_s {
|
|
|
|
size_t value_offset;
|
|
|
|
size_t size_offset;
|
|
|
|
} parse_data_t;
|
|
|
|
|
2020-12-23 13:13:50 +00:00
|
|
|
typedef struct parse_string_s {
|
|
|
|
size_t value_offset;
|
|
|
|
} parse_string_t;
|
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
typedef struct parse_custom_s {
|
|
|
|
int (*parse) (const plitem_t *item, void **data,
|
|
|
|
plitem_t *messages, parsectx_t *context);
|
|
|
|
size_t *offsets;
|
|
|
|
size_t num_offsets;
|
|
|
|
} parse_custom_t;
|
|
|
|
|
2023-02-18 08:00:52 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2023-06-16 09:47:24 +00:00
|
|
|
PL_Message (messages, item, "error: unknown field '%s'", field_name);
|
2023-02-18 08:00:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-12-24 00:58:27 +00:00
|
|
|
static int
|
|
|
|
parse_basic (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
2022-11-23 02:34:20 +00:00
|
|
|
parsectx_t *pctx = context;
|
2020-12-24 00:58:27 +00:00
|
|
|
__auto_type etype = (exprtype_t *) field->data;
|
2022-11-23 02:34:20 +00:00
|
|
|
exprctx_t ectx = *pctx->ectx;
|
2020-12-24 00:58:27 +00:00
|
|
|
exprval_t result = { etype, data };
|
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2020-12-24 00:58:27 +00:00
|
|
|
const char *valstr = PL_String (item);
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_basic: %s %zd %d %p %p: %s\n",
|
2021-03-23 04:04:22 +00:00
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, valstr);
|
2020-12-24 00:58:27 +00:00
|
|
|
if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) {
|
|
|
|
//FIXME handle subpass in a separate parser?
|
|
|
|
*(uint32_t *) data = VK_SUBPASS_EXTERNAL;
|
|
|
|
} else {
|
|
|
|
ret = !cexpr_eval_string (valstr, &ectx);
|
2021-01-05 14:42:30 +00:00
|
|
|
if (!ret) {
|
|
|
|
PL_Message (messages, item, "error parsing %s: %s",
|
|
|
|
field->name, valstr);
|
|
|
|
}
|
2020-12-24 00:58:27 +00:00
|
|
|
}
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %x\n", *(uint32_t *)data);
|
2020-12-24 00:58:27 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-05-29 12:53:38 +00:00
|
|
|
static int
|
|
|
|
parse_int32_t (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
2023-06-29 18:31:52 +00:00
|
|
|
int val = 0;
|
2022-11-23 02:34:20 +00:00
|
|
|
parsectx_t *pctx = context;
|
2023-06-29 18:31:52 +00:00
|
|
|
exprval_t result = { &cexpr_int, &val };
|
2022-11-23 02:34:20 +00:00
|
|
|
exprctx_t ectx = *pctx->ectx;
|
2022-05-29 12:53:38 +00:00
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2022-05-29 12:53:38 +00:00
|
|
|
const char *valstr = PL_String (item);
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse,
|
|
|
|
// "parse_int32_t: %s %zd %d %p %p %s\n",
|
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, valstr);
|
|
|
|
ret = !cexpr_eval_string (valstr, &ectx);
|
|
|
|
if (!ret) {
|
|
|
|
PL_Message (messages, item, "error parsing %s: %s",
|
|
|
|
field->name, valstr);
|
|
|
|
}
|
|
|
|
*(int32_t *) data = val;
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(int32_t *)data);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
static int
|
|
|
|
parse_uint32_t (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
2020-07-16 06:42:49 +00:00
|
|
|
{
|
2020-07-16 15:29:53 +00:00
|
|
|
int ret = 1;
|
2021-02-17 04:32:04 +00:00
|
|
|
// use size_t (and cexpr_size_t) for val so references to array sizes
|
|
|
|
// can be used
|
2021-01-10 06:29:47 +00:00
|
|
|
size_t val = 0;
|
2022-11-23 02:34:20 +00:00
|
|
|
parsectx_t *pctx = context;
|
2021-01-10 06:29:47 +00:00
|
|
|
exprval_t result = { &cexpr_size_t, &val };
|
2022-11-23 02:34:20 +00:00
|
|
|
exprctx_t ectx = *pctx->ectx;
|
2020-12-24 00:58:27 +00:00
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2020-07-16 15:29:53 +00:00
|
|
|
const char *valstr = PL_String (item);
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_uint32_t: %s %zd %d %p %p: %s\n",
|
2021-03-23 04:04:22 +00:00
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, valstr);
|
2020-07-16 15:29:53 +00:00
|
|
|
if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) {
|
2020-12-24 00:58:27 +00:00
|
|
|
//FIXME handle subpass in a separate parser?
|
2020-07-16 15:29:53 +00:00
|
|
|
*(uint32_t *) data = VK_SUBPASS_EXTERNAL;
|
|
|
|
} else {
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse,
|
2021-03-23 04:04:22 +00:00
|
|
|
// "parse_uint32_t: %s %zd %d %p %p %s\n",
|
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, valstr);
|
2020-12-24 00:58:27 +00:00
|
|
|
ret = !cexpr_eval_string (valstr, &ectx);
|
2021-01-10 06:29:47 +00:00
|
|
|
if (!ret) {
|
|
|
|
PL_Message (messages, item, "error parsing %s: %s",
|
|
|
|
field->name, valstr);
|
|
|
|
}
|
|
|
|
*(uint32_t *) data = val;
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(uint32_t *)data);
|
2020-07-16 15:29:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2020-07-16 06:42:49 +00:00
|
|
|
}
|
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
static int
|
|
|
|
parse_enum (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
2020-07-16 06:42:49 +00:00
|
|
|
{
|
2020-07-16 15:29:53 +00:00
|
|
|
int ret = 1;
|
2020-12-21 09:38:31 +00:00
|
|
|
__auto_type enm = (exprenum_t *) field->data;
|
2022-11-23 02:34:20 +00:00
|
|
|
parsectx_t *pctx = context;
|
|
|
|
exprctx_t ectx = *pctx->ectx;
|
2020-12-21 09:38:31 +00:00
|
|
|
exprval_t result = { enm->type, data };
|
2022-11-23 02:34:20 +00:00
|
|
|
ectx.parent = pctx->ectx;
|
2020-12-21 09:38:31 +00:00
|
|
|
ectx.symtab = enm->symtab;
|
|
|
|
ectx.result = &result;
|
2020-07-16 15:29:53 +00:00
|
|
|
const char *valstr = PL_String (item);
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_enum: %s %zd %d %p %p %s\n",
|
2021-03-23 04:04:22 +00:00
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, valstr);
|
2020-12-21 09:38:31 +00:00
|
|
|
ret = !cexpr_parse_enum (enm, valstr, &ectx, data);
|
2021-01-05 05:15:35 +00:00
|
|
|
if (!ret) {
|
|
|
|
PL_Message (messages, item, "error parsing enum: %s", valstr);
|
|
|
|
}
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(int *)data);
|
2020-07-16 15:29:53 +00:00
|
|
|
return ret;
|
2020-07-16 06:42:49 +00:00
|
|
|
}
|
|
|
|
|
2021-02-14 02:20:54 +00:00
|
|
|
static const plitem_t *
|
|
|
|
parse_reference (const plitem_t *item, const char *type, plitem_t *messages,
|
|
|
|
parsectx_t *pctx)
|
|
|
|
{
|
|
|
|
exprctx_t ectx = *pctx->ectx;
|
|
|
|
plitem_t *refItem = 0;
|
|
|
|
exprval_t result = { &cexpr_plitem, &refItem };
|
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2021-02-14 02:20:54 +00:00
|
|
|
const char *name = PL_String (item);
|
|
|
|
if (cexpr_eval_string (name, &ectx)) {
|
2021-03-29 08:27:06 +00:00
|
|
|
PL_Message (messages, item, "not a %s reference", type);
|
2021-02-14 02:20:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return refItem;
|
|
|
|
}
|
|
|
|
|
2021-03-21 10:56:17 +00:00
|
|
|
static void *
|
|
|
|
vkparse_alloc (void *context, size_t size)
|
|
|
|
{
|
|
|
|
parsectx_t *pctx = context;
|
|
|
|
return cmemalloc (pctx->ectx->memsuper, size);
|
|
|
|
}
|
|
|
|
|
2022-11-26 13:22:22 +00:00
|
|
|
static int
|
|
|
|
parse_ignore (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-02-10 10:36:53 +00:00
|
|
|
static int __attribute__((used))
|
|
|
|
parse_labeledsingle (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
__auto_type single = (parse_single_t *) field->data;
|
|
|
|
void *flddata = (byte *)data + single->value_offset;
|
|
|
|
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse,"parse_labeledsingle: %s %zd %d %p %p\n",
|
|
|
|
// field->name, field->offset,
|
|
|
|
// field->type, field->parser, field->data);
|
|
|
|
|
2023-02-10 16:15:19 +00:00
|
|
|
const char *key = PL_KeyAtIndex (item, 0);
|
|
|
|
if (!key) {
|
|
|
|
PL_Message (messages, item, "missing item");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
item = PL_ObjectForKey (item, key);
|
|
|
|
|
2023-02-10 10:36:53 +00:00
|
|
|
if (!PL_CheckType (single->type, PL_Type (item))) {
|
|
|
|
PL_TypeMismatch (messages, item, field->name, single->type,
|
|
|
|
PL_Type (item));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-02-10 16:15:19 +00:00
|
|
|
plfield_t f = { field->name, 0, single->type, single->parser, 0 };
|
2023-02-10 10:36:53 +00:00
|
|
|
void *value = vkparse_alloc (context, single->stride);
|
|
|
|
memset (value, 0, single->stride);
|
|
|
|
if (!single->parser (&f, item, value, messages, context)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(void **) flddata = value;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
static int
|
|
|
|
parse_single (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
2020-07-16 06:42:49 +00:00
|
|
|
{
|
2020-07-16 15:29:53 +00:00
|
|
|
__auto_type single = (parse_single_t *) field->data;
|
|
|
|
void *flddata = (byte *)data + single->value_offset;
|
|
|
|
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_single: %s %zd %d %p %p\n",
|
2021-03-23 04:04:22 +00:00
|
|
|
// field->name, field->offset,
|
|
|
|
// field->type, field->parser, field->data);
|
2020-07-16 15:29:53 +00:00
|
|
|
|
2021-01-05 14:42:30 +00:00
|
|
|
if (!PL_CheckType (single->type, PL_Type (item))) {
|
|
|
|
PL_TypeMismatch (messages, item, field->name, single->type,
|
|
|
|
PL_Type (item));
|
2020-07-16 15:29:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-02-18 08:00:52 +00:00
|
|
|
plfield_t f = { field->name, 0, single->type, single->parser, 0 };
|
2021-03-21 10:56:17 +00:00
|
|
|
void *value = vkparse_alloc (context, single->stride);
|
|
|
|
memset (value, 0, single->stride);
|
2020-12-21 09:38:31 +00:00
|
|
|
if (!single->parser (&f, item, value, messages, context)) {
|
2020-07-16 15:29:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*(void **) flddata = value;
|
|
|
|
return 1;
|
2020-07-16 06:42:49 +00:00
|
|
|
}
|
|
|
|
|
2023-02-10 10:36:53 +00:00
|
|
|
static int __attribute__((used))
|
|
|
|
parse_labeledarray (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
__auto_type array = (parse_array_t *) field->data;
|
|
|
|
__auto_type value = (void **) ((byte *)data + array->value_offset);
|
|
|
|
__auto_type size = (uint32_t *) ((byte *)data + array->size_offset);
|
|
|
|
|
|
|
|
plelement_t element = {
|
|
|
|
array->type,
|
|
|
|
array->stride,
|
|
|
|
vkparse_alloc,
|
|
|
|
array->parser,
|
|
|
|
array->data,
|
|
|
|
};
|
|
|
|
plfield_t f = { 0, 0, 0, 0, &element };
|
|
|
|
|
|
|
|
typedef struct arr_s DARRAY_TYPE(byte) arr_t;
|
|
|
|
arr_t *arr;
|
|
|
|
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_array: %s %zd %d %p %p %p\n",
|
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, data);
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %d %zd %p %zd %zd\n", array->type,
|
|
|
|
// array->stride, array->parser, array->value_offset,
|
|
|
|
// array->size_offset);
|
|
|
|
if (!PL_ParseLabeledArray (&f, item, &arr, messages, context)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*value = vkparse_alloc (context, array->stride * arr->size);
|
|
|
|
memcpy (*value, arr->a, array->stride * arr->size);
|
|
|
|
if ((void *) size >= data) {
|
|
|
|
*size = arr->size;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
static int
|
|
|
|
parse_array (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
2020-07-16 06:42:49 +00:00
|
|
|
{
|
2020-07-16 15:29:53 +00:00
|
|
|
__auto_type array = (parse_array_t *) field->data;
|
|
|
|
__auto_type value = (void **) ((byte *)data + array->value_offset);
|
|
|
|
__auto_type size = (uint32_t *) ((byte *)data + array->size_offset);
|
|
|
|
|
|
|
|
plelement_t element = {
|
|
|
|
array->type,
|
|
|
|
array->stride,
|
2021-03-21 10:56:17 +00:00
|
|
|
vkparse_alloc,
|
2020-07-16 15:29:53 +00:00
|
|
|
array->parser,
|
2023-02-10 10:33:10 +00:00
|
|
|
array->data,
|
2020-07-16 15:29:53 +00:00
|
|
|
};
|
|
|
|
plfield_t f = { 0, 0, 0, 0, &element };
|
|
|
|
|
|
|
|
typedef struct arr_s DARRAY_TYPE(byte) arr_t;
|
|
|
|
arr_t *arr;
|
|
|
|
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_array: %s %zd %d %p %p %p\n",
|
2021-03-23 04:04:22 +00:00
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, data);
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %d %zd %p %zd %zd\n", array->type,
|
2021-03-23 04:04:22 +00:00
|
|
|
// array->stride, array->parser, array->value_offset,
|
|
|
|
// array->size_offset);
|
2020-12-21 09:38:31 +00:00
|
|
|
if (!PL_ParseArray (&f, item, &arr, messages, context)) {
|
2020-07-16 15:29:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2021-03-21 10:56:17 +00:00
|
|
|
*value = vkparse_alloc (context, array->stride * arr->size);
|
2020-07-16 15:29:53 +00:00
|
|
|
memcpy (*value, arr->a, array->stride * arr->size);
|
2021-01-23 11:40:11 +00:00
|
|
|
if ((void *) size >= data) {
|
2020-07-16 15:29:53 +00:00
|
|
|
*size = arr->size;
|
|
|
|
}
|
|
|
|
return 1;
|
2020-07-16 06:42:49 +00:00
|
|
|
}
|
|
|
|
|
2023-02-09 12:17:04 +00:00
|
|
|
static int __attribute__((used))
|
2021-12-04 01:08:27 +00:00
|
|
|
parse_fixed_array (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
__auto_type array = (parse_fixed_array_t *) field->data;
|
|
|
|
|
|
|
|
plelement_t element = {
|
|
|
|
array->type,
|
|
|
|
array->stride,
|
|
|
|
vkparse_alloc,
|
|
|
|
array->parser,
|
2023-02-10 10:33:10 +00:00
|
|
|
array->data,
|
2021-12-04 01:08:27 +00:00
|
|
|
};
|
|
|
|
plfield_t f = { 0, 0, 0, 0, &element };
|
|
|
|
|
|
|
|
typedef struct arr_s DARRAY_TYPE(byte) arr_t;
|
|
|
|
arr_t *arr;
|
|
|
|
|
|
|
|
if (!PL_ParseArray (&f, item, &arr, messages, context)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memset (data, 0, array->stride * array->size);
|
|
|
|
size_t size = min (array->size, arr->size);
|
|
|
|
memcpy (data, arr->a, array->stride * size);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-02-10 10:36:53 +00:00
|
|
|
static char *
|
|
|
|
vkstrdup (parsectx_t *context, const char *str)
|
|
|
|
{
|
|
|
|
size_t len = strlen (str) + 1;
|
|
|
|
char *dup = vkparse_alloc (context, len);
|
|
|
|
memcpy (dup, str, len);
|
|
|
|
return dup;
|
|
|
|
}
|
|
|
|
|
2023-02-20 15:44:26 +00:00
|
|
|
static __attribute__((used)) parse_string_t parse_string_array = { 0 };
|
2023-02-10 16:15:19 +00:00
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
static int
|
|
|
|
parse_string (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
2020-12-23 13:13:50 +00:00
|
|
|
{
|
|
|
|
__auto_type string = (parse_string_t *) field->data;
|
|
|
|
__auto_type value = (char **) ((byte *)data + string->value_offset);
|
|
|
|
|
2021-01-05 14:42:30 +00:00
|
|
|
const char *str = PL_String (item);
|
2020-12-23 13:13:50 +00:00
|
|
|
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_string: %s %zd %d %p %p %p\n",
|
2021-03-23 04:04:22 +00:00
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, data);
|
2021-03-29 10:58:00 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %zd\n", string->value_offset);
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " %s\n", str);
|
2020-12-23 13:13:50 +00:00
|
|
|
|
2023-02-10 10:36:53 +00:00
|
|
|
*value = vkstrdup (context, str);
|
2020-12-23 13:13:50 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-23 16:36:17 +00:00
|
|
|
static int
|
|
|
|
parse_custom (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
__auto_type custom = (parse_custom_t *) field->data;
|
|
|
|
void **offsets = alloca (custom->num_offsets * sizeof (void *));
|
|
|
|
for (size_t i = 0; i < custom->num_offsets; i++) {
|
|
|
|
offsets[i] = data + custom->offsets[i];
|
|
|
|
}
|
|
|
|
return custom->parse (item, offsets, messages, context);
|
|
|
|
}
|
|
|
|
|
2022-04-03 02:11:28 +00:00
|
|
|
static int
|
|
|
|
parse_inherit (const plfield_t *field, const plitem_t *item,
|
|
|
|
void *data, plitem_t *messages, void *context)
|
|
|
|
{
|
2022-11-23 02:34:20 +00:00
|
|
|
parsectx_t *pctx = context;
|
|
|
|
exprctx_t ectx = *pctx->ectx;
|
2022-04-03 02:11:28 +00:00
|
|
|
plitem_t *inheritItem = 0;
|
|
|
|
exprval_t result = { &cexpr_plitem, &inheritItem };
|
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2022-04-03 02:11:28 +00:00
|
|
|
const char *inheritstr = PL_String (item);
|
2023-02-12 16:43:17 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_inherit: %s\n", inheritstr);
|
2022-04-03 02:11:28 +00:00
|
|
|
int ret = !cexpr_eval_string (inheritstr, &ectx);
|
|
|
|
if (ret) {
|
|
|
|
ret = PL_ParseStruct (field->data, inheritItem, data, messages,
|
|
|
|
context);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-05-29 12:53:38 +00:00
|
|
|
static hashtab_t *parser_table;
|
|
|
|
|
|
|
|
static int
|
|
|
|
parse_next (const plfield_t *field, const plitem_t *item, void *data,
|
|
|
|
plitem_t *messages, void *context)
|
|
|
|
{
|
|
|
|
const char *type_name = PL_String (PL_ObjectAtIndex (item, 0));
|
|
|
|
plitem_t *next_def = PL_ObjectAtIndex (item, 1);
|
|
|
|
|
|
|
|
if (!type_name || PL_Type (next_def) != QFDictionary) {
|
|
|
|
PL_Message (messages, item, "invalid @next");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
parserref_t *parser = Hash_Find (parser_table, type_name);
|
|
|
|
if (!parser) {
|
|
|
|
PL_Message (messages, item, "Invalid type for @next: %s", type_name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void *data_ptr = vkparse_alloc (context, parser->size);
|
|
|
|
memset (data_ptr, 0, parser->size);
|
|
|
|
if (!parser->parse (field, next_def, data_ptr, messages, context)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*(void **) data = data_ptr;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-01-04 08:36:11 +00:00
|
|
|
static int
|
|
|
|
parse_RGBA (const plitem_t *item, void **data,
|
|
|
|
plitem_t *messages, parsectx_t *context)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
exprctx_t ectx = *context->ectx;
|
|
|
|
exprval_t result = { &cexpr_vector, data[0] };
|
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2021-01-04 08:36:11 +00:00
|
|
|
const char *valstr = PL_String (item);
|
2023-02-12 16:43:17 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr);
|
2021-01-04 08:36:11 +00:00
|
|
|
ret = !cexpr_eval_string (valstr, &ectx);
|
2023-02-12 16:43:17 +00:00
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse, " "VEC4F_FMT"\n",
|
|
|
|
// VEC4_EXP (*(vec4f_t *)data[0]));
|
2021-01-04 08:36:11 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2021-01-04 08:26:39 +00:00
|
|
|
|
2021-02-04 11:40:28 +00:00
|
|
|
uint64_t
|
|
|
|
QFV_GetHandle (hashtab_t *tab, const char *name)
|
|
|
|
{
|
|
|
|
handleref_t *hr = Hash_Find (tab, name);
|
|
|
|
if (hr) {
|
|
|
|
return hr->handle;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
QFV_AddHandle (hashtab_t *tab, const char *name, uint64_t handle)
|
2021-02-04 08:03:49 +00:00
|
|
|
{
|
|
|
|
handleref_t *hr = malloc (sizeof (handleref_t));
|
|
|
|
hr->name = strdup (name);
|
|
|
|
hr->handle = handle;
|
|
|
|
Hash_Add (tab, hr);
|
|
|
|
}
|
|
|
|
|
2021-01-04 08:26:39 +00:00
|
|
|
static int
|
2021-01-05 14:42:30 +00:00
|
|
|
parse_VkShaderModule (const plitem_t *item, void **data,
|
2022-11-23 02:34:20 +00:00
|
|
|
plitem_t *messages, parsectx_t *pctx)
|
2021-01-04 08:26:39 +00:00
|
|
|
{
|
2021-01-05 14:42:30 +00:00
|
|
|
__auto_type handle = (VkShaderModule *) data[0];
|
2022-11-23 02:34:20 +00:00
|
|
|
vulkan_ctx_t *ctx = pctx->vctx;
|
2021-02-04 08:03:49 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
2021-01-05 05:15:35 +00:00
|
|
|
|
2021-01-04 08:26:39 +00:00
|
|
|
const char *name = PL_String (item);
|
2022-11-24 14:44:07 +00:00
|
|
|
*handle = (VkShaderModule) QFV_GetHandle (sctx->shaderModules, name);
|
2021-02-04 11:40:28 +00:00
|
|
|
if (*handle) {
|
2021-02-04 08:03:49 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2021-11-30 03:24:45 +00:00
|
|
|
qfvPushDebug (ctx, va (ctx->va_ctx, "parse_VkShaderModule: %d", PL_Line (item)));
|
|
|
|
*handle = QFV_CreateShaderModule (device, name);
|
|
|
|
qfvPopDebug (ctx);
|
|
|
|
if (!*handle) {
|
2021-02-04 08:03:49 +00:00
|
|
|
PL_Message (messages, item, "could not find shader %s", name);
|
2021-01-05 05:15:35 +00:00
|
|
|
return 0;
|
2021-01-04 08:26:39 +00:00
|
|
|
}
|
2022-11-24 14:44:07 +00:00
|
|
|
QFV_AddHandle (sctx->shaderModules, name, (uint64_t) *handle);
|
2021-01-05 05:15:35 +00:00
|
|
|
return 1;
|
2021-01-04 08:26:39 +00:00
|
|
|
}
|
2021-01-04 08:36:11 +00:00
|
|
|
|
2022-11-26 13:22:22 +00:00
|
|
|
exprtype_t VkImage_type = {
|
|
|
|
.name = "VkImage",
|
|
|
|
.size = sizeof (VkImage),
|
|
|
|
.binops = 0,
|
|
|
|
.unops = 0,
|
|
|
|
.data = 0
|
|
|
|
};
|
|
|
|
|
|
|
|
exprtype_t VkImageView_type = {
|
|
|
|
.name = "VkImageView",
|
|
|
|
.size = sizeof (VkImageView),
|
|
|
|
.binops = 0,
|
|
|
|
.unops = 0,
|
|
|
|
.data = 0
|
|
|
|
};
|
|
|
|
|
2021-01-04 08:36:11 +00:00
|
|
|
static const char *
|
2021-01-04 23:38:35 +00:00
|
|
|
handleref_getkey (const void *hr, void *unused)
|
2021-01-04 08:36:11 +00:00
|
|
|
{
|
2021-01-04 23:38:35 +00:00
|
|
|
return ((handleref_t *)hr)->name;
|
2021-01-04 08:36:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-01-04 23:38:35 +00:00
|
|
|
handleref_free (void *hr, void *_ctx)
|
2021-01-04 08:36:11 +00:00
|
|
|
{
|
2021-01-04 23:38:35 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
free (handleref->name);
|
|
|
|
free (handleref);
|
2021-01-04 08:36:11 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 23:38:35 +00:00
|
|
|
static void
|
|
|
|
setLayout_free (void *hr, void *_ctx)
|
2021-01-04 08:36:11 +00:00
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-01-04 23:38:35 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type layout = (VkDescriptorSetLayout) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-01-04 08:36:11 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
2021-01-05 08:48:00 +00:00
|
|
|
if (layout) {
|
|
|
|
dfunc->vkDestroyDescriptorSetLayout (device->dev, layout, 0);
|
|
|
|
}
|
2021-01-04 23:38:35 +00:00
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
2021-01-04 08:36:11 +00:00
|
|
|
|
2021-01-05 05:15:35 +00:00
|
|
|
static void
|
|
|
|
shaderModule_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-01-05 05:15:35 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type module = (VkShaderModule) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-01-05 05:15:35 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
2021-01-05 08:48:00 +00:00
|
|
|
if (module) {
|
|
|
|
dfunc->vkDestroyShaderModule (device->dev, module, 0);
|
|
|
|
}
|
2021-01-05 05:15:35 +00:00
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pipelineLayout_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-01-05 05:15:35 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type layout = (VkPipelineLayout) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-01-05 05:15:35 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
2021-01-05 08:48:00 +00:00
|
|
|
if (layout) {
|
|
|
|
dfunc->vkDestroyPipelineLayout (device->dev, layout, 0);
|
|
|
|
};
|
2021-01-05 05:15:35 +00:00
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
2021-01-09 16:53:15 +00:00
|
|
|
static void
|
|
|
|
descriptorPool_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-01-09 16:53:15 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type pool = (VkDescriptorPool) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-01-09 16:53:15 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
|
|
|
if (pool) {
|
|
|
|
dfunc->vkDestroyDescriptorPool (device->dev, pool, 0);
|
|
|
|
};
|
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
2021-01-10 06:50:24 +00:00
|
|
|
static void
|
|
|
|
sampler_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-01-10 06:50:24 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type sampler = (VkSampler) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-01-10 06:50:24 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
|
|
|
if (sampler) {
|
|
|
|
dfunc->vkDestroySampler (device->dev, sampler, 0);
|
|
|
|
};
|
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
2021-02-14 02:35:06 +00:00
|
|
|
static void
|
|
|
|
image_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-02-14 02:35:06 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type image = (VkImage) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-02-14 02:35:06 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
|
|
|
if (image) {
|
|
|
|
dfunc->vkDestroyImage (device->dev, image, 0);
|
|
|
|
};
|
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
imageView_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-02-14 02:35:06 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type imageView = (VkImageView) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-02-14 02:35:06 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
|
|
|
if (imageView) {
|
|
|
|
dfunc->vkDestroyImageView (device->dev, imageView, 0);
|
|
|
|
};
|
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
2021-02-23 05:37:48 +00:00
|
|
|
static void
|
|
|
|
renderpass_free (void *hr, void *_ctx)
|
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = _ctx;
|
2021-02-23 05:37:48 +00:00
|
|
|
__auto_type handleref = (handleref_t *) hr;
|
|
|
|
__auto_type renderpass = (VkRenderPass) handleref->handle;
|
2022-11-24 14:44:07 +00:00
|
|
|
__auto_type ctx = sctx->vctx;
|
2021-02-23 05:37:48 +00:00
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
|
|
|
|
if (renderpass) {
|
|
|
|
dfunc->vkDestroyRenderPass (device->dev, renderpass, 0);
|
|
|
|
};
|
|
|
|
handleref_free (handleref, ctx);
|
|
|
|
}
|
|
|
|
|
2021-01-04 23:38:35 +00:00
|
|
|
static hashtab_t *enum_symtab;
|
2021-01-04 08:36:11 +00:00
|
|
|
|
2021-12-01 05:49:23 +00:00
|
|
|
typedef struct data_array_s DARRAY_TYPE(byte) data_array_t;
|
|
|
|
static void
|
|
|
|
data_array (const exprval_t **params, exprval_t *result, exprctx_t *context)
|
|
|
|
{
|
|
|
|
size_t offset = 0;
|
2021-12-06 10:29:37 +00:00
|
|
|
// params are in reverse order, but this works for calculating the size
|
|
|
|
// of the buffer
|
2021-12-01 05:49:23 +00:00
|
|
|
for (const exprval_t **param = params; *param; param++) {
|
|
|
|
offset += (*param)->type->size;
|
|
|
|
}
|
|
|
|
__auto_type data = DARRAY_ALLOCFIXED_OBJ (data_array_t, offset,
|
|
|
|
cmemalloc, context->memsuper);
|
|
|
|
for (const exprval_t **param = params; *param; param++) {
|
|
|
|
size_t size = (*param)->type->size;
|
2021-12-06 10:29:37 +00:00
|
|
|
// pre-decrement offset because params are in reverse order
|
|
|
|
offset -= size;
|
2021-12-01 05:49:23 +00:00
|
|
|
memcpy (data->a + offset, (*param)->value, size);
|
|
|
|
}
|
|
|
|
*(data_array_t **) result->value = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static exprtype_t data_array_type = {
|
2022-04-24 05:55:35 +00:00
|
|
|
.name = "array",
|
|
|
|
.size = sizeof (data_array_t *),
|
|
|
|
.binops = 0,
|
|
|
|
.unops = 0,
|
2021-12-01 05:49:23 +00:00
|
|
|
};
|
|
|
|
static exprfunc_t data_array_func[] = {
|
|
|
|
{ &data_array_type, -1, 0, data_array },
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
static exprsym_t data_array_symbols[] = {
|
|
|
|
{ "array", &cexpr_function, data_array_func },
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
static exprtab_t data_array_symtab = {
|
|
|
|
data_array_symbols,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
parse_specialization_data (const plitem_t *item, void **data,
|
2022-11-23 02:34:20 +00:00
|
|
|
plitem_t *messages, parsectx_t *pctx)
|
2021-12-01 05:49:23 +00:00
|
|
|
{
|
|
|
|
size_t *size_ptr = (size_t *) data[0];
|
|
|
|
void **data_ptr = (void **) data[1];
|
|
|
|
|
|
|
|
if (PL_Type (item) == QFBinary) {
|
|
|
|
const void *bindata = PL_BinaryData (item);
|
|
|
|
size_t binsize = PL_BinarySize (item);
|
|
|
|
|
2022-11-23 02:34:20 +00:00
|
|
|
*data_ptr = vkparse_alloc (pctx, binsize);
|
2021-12-01 05:49:23 +00:00
|
|
|
memcpy (*data_ptr, bindata, binsize);
|
|
|
|
*size_ptr = binsize;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
data_array_t *da= 0;
|
2022-11-23 02:34:20 +00:00
|
|
|
exprctx_t ectx = *pctx->ectx;
|
2021-12-01 05:49:23 +00:00
|
|
|
exprval_t result = { &data_array_type, &da };
|
2022-11-23 02:34:20 +00:00
|
|
|
ectx.parent = pctx->ectx;
|
2021-12-01 05:49:23 +00:00
|
|
|
ectx.symtab = &data_array_symtab;
|
|
|
|
ectx.result = &result;
|
2022-05-30 07:12:42 +00:00
|
|
|
ectx.item = item;
|
2021-12-01 05:49:23 +00:00
|
|
|
const char *valstr = PL_String (item);
|
|
|
|
//Sys_MaskPrintf (SYS_vulkan_parse,
|
|
|
|
// "parse_specialization_data: %s %zd %d %p %p %s\n",
|
|
|
|
// field->name, field->offset, field->type, field->parser,
|
|
|
|
// field->data, valstr);
|
|
|
|
int ret = !cexpr_eval_string (valstr, &ectx);
|
|
|
|
if (!ret) {
|
|
|
|
PL_Message (messages, item, "error parsing specialization data: %s",
|
|
|
|
valstr);
|
|
|
|
} else {
|
|
|
|
*size_ptr = da->size;
|
|
|
|
*data_ptr = da->a;
|
2021-12-06 10:29:37 +00:00
|
|
|
//for (size_t i = 0; i < da->size; i++) {
|
|
|
|
// Sys_Printf (" %02x", da->a[i]);
|
|
|
|
//}
|
|
|
|
//Sys_Printf ("\n");
|
2021-12-01 05:49:23 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-02-09 05:52:43 +00:00
|
|
|
static int
|
|
|
|
parse_task_function (const plitem_t *item, void **data,
|
|
|
|
plitem_t *messages, parsectx_t *pctx)
|
|
|
|
{
|
2023-02-12 16:43:17 +00:00
|
|
|
qfv_renderctx_t *rctx = pctx->data;
|
|
|
|
const char *fname = PL_String (item);
|
2023-02-13 08:45:36 +00:00
|
|
|
exprsym_t *fsym = Hash_Find (rctx->task_functions.tab, fname);
|
2023-02-12 16:43:17 +00:00
|
|
|
|
|
|
|
if (!fsym) {
|
|
|
|
PL_Message (messages, item, "undefined task function %s", fname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (fsym->type != &cexpr_function) {
|
|
|
|
PL_Message (messages, item, "not a function type %s", fname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
exprfunc_t *func;
|
|
|
|
for (func = fsym->value; func->func; func++) {
|
|
|
|
if (!func->result) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!func->func) {
|
|
|
|
PL_Message (messages, item, "%s does not have a void implementation",
|
|
|
|
fname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
size_t size = func->num_params * sizeof (exprval_t);
|
|
|
|
size += func->num_params * sizeof (exprval_t *);
|
|
|
|
size_t base = size;
|
|
|
|
for (int i = 0; i < func->num_params; i++) {
|
|
|
|
exprtype_t *type = func->param_types[i];
|
|
|
|
size = ((size + type->size - 1) & ~(type->size - 1));
|
|
|
|
if (i == 0) {
|
|
|
|
base = size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exprval_t **param_ptrs = vkparse_alloc (pctx, size);
|
|
|
|
exprval_t *params = (exprval_t *) ¶m_ptrs[func->num_params];
|
|
|
|
byte *param_data = (byte *) param_ptrs + base;
|
|
|
|
memset (params, 0, size);
|
|
|
|
size_t offs = 0;
|
|
|
|
for (int i = 0; i < func->num_params; i++) {
|
|
|
|
exprtype_t *type = func->param_types[i];
|
|
|
|
param_ptrs[i] = ¶ms[i];
|
|
|
|
params[i] = (exprval_t) {
|
|
|
|
.type = type,
|
|
|
|
.value = param_data + offs,
|
|
|
|
};
|
|
|
|
offs = ((offs + type->size - 1) & ~(type->size - 1));
|
|
|
|
offs += type->size;
|
|
|
|
}
|
|
|
|
*(exprfunc_t **) data[0] = func;
|
|
|
|
*(exprval_t ***) data[1] = param_ptrs;
|
|
|
|
*(void **) data[2] = param_data;
|
|
|
|
return 1;
|
2023-02-09 05:52:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
parse_task_params (const plitem_t *item, void **data,
|
|
|
|
plitem_t *messages, parsectx_t *pctx)
|
|
|
|
{
|
2023-02-13 02:30:14 +00:00
|
|
|
exprfunc_t *func = *(exprfunc_t **) data[0];
|
|
|
|
exprval_t **params = *(exprval_t ***) data[1];
|
2023-02-13 08:45:36 +00:00
|
|
|
if (!func) {
|
|
|
|
PL_Message (messages, item, "task function not set");
|
|
|
|
return 0;
|
|
|
|
}
|
2023-02-13 02:30:14 +00:00
|
|
|
if (PL_A_NumObjects (item) != func->num_params) {
|
|
|
|
PL_Message (messages, item, "incorrect number of parameters");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < func->num_params; i++) {
|
|
|
|
const char *paramstr = PL_String (PL_ObjectAtIndex (item, i));
|
|
|
|
exprval_t *param = params[func->num_params - i - 1];
|
|
|
|
exprctx_t ectx = *pctx->ectx;
|
|
|
|
if (param->type->data) {
|
|
|
|
ectx.parent = pctx->ectx;
|
|
|
|
ectx.symtab = ((exprenum_t *) param->type->data)->symtab;
|
|
|
|
}
|
|
|
|
// cexpr params are in reverse order
|
|
|
|
ectx.result = param;
|
|
|
|
|
|
|
|
if (cexpr_eval_string (paramstr, &ectx)) {
|
|
|
|
PL_Message (messages, item, "error parsing param %d", i);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
2023-02-09 05:52:43 +00:00
|
|
|
}
|
|
|
|
|
2021-01-04 23:38:35 +00:00
|
|
|
#include "libs/video/renderer/vulkan/vkparse.cinc"
|
|
|
|
|
2023-06-22 07:44:05 +00:00
|
|
|
static exprsym_t qfv_renderframeset_t_symbols[] = {
|
|
|
|
{"size", &cexpr_size_t, (void *)field_offset (qfv_renderframeset_t, size)},
|
2021-01-16 12:03:36 +00:00
|
|
|
{ }
|
|
|
|
};
|
2023-06-22 07:44:05 +00:00
|
|
|
static exprtab_t qfv_renderframeset_t_symtab = {
|
|
|
|
qfv_renderframeset_t_symbols,
|
2021-01-16 12:03:36 +00:00
|
|
|
};
|
2023-06-22 07:44:05 +00:00
|
|
|
exprtype_t qfv_renderframeset_t_type = {
|
2022-04-24 05:55:35 +00:00
|
|
|
.name = "frameset",
|
2023-06-22 07:44:05 +00:00
|
|
|
.size = sizeof (qfv_renderframeset_t *),
|
2022-04-24 05:55:35 +00:00
|
|
|
.binops = cexpr_struct_binops,
|
|
|
|
.unops = 0,
|
2023-06-22 07:44:05 +00:00
|
|
|
.data = &qfv_renderframeset_t_symtab,
|
2021-01-16 12:03:36 +00:00
|
|
|
};
|
|
|
|
|
2021-01-10 06:50:24 +00:00
|
|
|
static hashtab_t *
|
2022-11-24 14:44:07 +00:00
|
|
|
handlref_symtab (void (*free_func)(void*,void*), scriptctx_t *sctx)
|
2021-01-10 06:50:24 +00:00
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
return Hash_NewTable (23, handleref_getkey, free_func, sctx,
|
|
|
|
&sctx->hashctx);
|
2021-01-10 06:50:24 +00:00
|
|
|
}
|
|
|
|
|
2021-01-05 14:42:30 +00:00
|
|
|
static const char *
|
|
|
|
enum_symtab_getkey (const void *e, void *unused)
|
|
|
|
{
|
|
|
|
__auto_type enm = (const exprenum_t *) e;
|
|
|
|
return enm->type->name;
|
|
|
|
}
|
|
|
|
|
2022-05-29 12:53:38 +00:00
|
|
|
static const char *
|
|
|
|
parser_getkey (const void *e, void *unused)
|
|
|
|
{
|
|
|
|
__auto_type parser = (const parserref_t *) e;
|
|
|
|
return parser->name;
|
|
|
|
}
|
|
|
|
|
2021-12-04 05:09:57 +00:00
|
|
|
static exprtab_t root_symtab = {
|
|
|
|
.symbols = cexpr_lib_symbols,
|
|
|
|
};
|
2023-03-05 09:19:54 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
root_symtab_shutdown (void *data)
|
|
|
|
{
|
|
|
|
Hash_DelTable (root_symtab.tab);
|
|
|
|
}
|
|
|
|
|
2021-12-04 05:09:57 +00:00
|
|
|
static void __attribute__((constructor))
|
|
|
|
root_symtab_init (void)
|
|
|
|
{
|
2022-05-12 08:54:23 +00:00
|
|
|
// using a null hashctx here is safe because this function is run before
|
2021-12-04 05:09:57 +00:00
|
|
|
// main and thus before any possibility of threading.
|
|
|
|
exprctx_t root_context = { .symtab = &root_symtab };
|
|
|
|
cexpr_init_symtab (&root_symtab, &root_context);
|
2023-03-05 09:19:54 +00:00
|
|
|
Sys_RegisterShutdown (root_symtab_shutdown, 0);
|
2021-12-04 05:09:57 +00:00
|
|
|
}
|
|
|
|
|
2021-01-05 14:42:30 +00:00
|
|
|
exprenum_t *
|
|
|
|
QFV_GetEnum (const char *name)
|
|
|
|
{
|
|
|
|
return Hash_Find (enum_symtab, name);
|
|
|
|
}
|
|
|
|
|
2021-02-04 08:03:49 +00:00
|
|
|
static int
|
2021-03-21 10:56:17 +00:00
|
|
|
parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist,
|
2021-02-14 02:35:06 +00:00
|
|
|
plparser_t parser, void *object, plitem_t *properties)
|
2020-07-16 06:42:49 +00:00
|
|
|
{
|
2022-11-24 14:44:07 +00:00
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
2020-07-16 06:42:49 +00:00
|
|
|
plitem_t *messages = PL_NewArray ();
|
2021-12-04 05:09:57 +00:00
|
|
|
exprctx_t exprctx = { .symtab = &root_symtab };
|
2021-02-14 02:35:06 +00:00
|
|
|
parsectx_t parsectx = { &exprctx, ctx, properties };
|
2023-06-22 07:44:05 +00:00
|
|
|
auto rctx = ctx->render_context;
|
2020-12-21 09:38:31 +00:00
|
|
|
exprsym_t var_syms[] = {
|
2022-11-24 14:44:07 +00:00
|
|
|
{"output", &qfv_output_t_type, &sctx->output},
|
2023-06-22 07:44:05 +00:00
|
|
|
{"frames", &qfv_renderframeset_t_type, &rctx->frames},
|
2020-12-21 11:17:27 +00:00
|
|
|
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
|
2021-12-04 05:31:39 +00:00
|
|
|
{"physDevLimits", &VkPhysicalDeviceLimits_type,
|
2022-05-29 13:13:36 +00:00
|
|
|
&ctx->device->physDev->properties->limits },
|
2021-02-14 02:35:06 +00:00
|
|
|
{QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties},
|
2020-12-21 09:38:31 +00:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
exprtab_t vars_tab = { var_syms, 0 };
|
|
|
|
|
2021-02-04 08:03:49 +00:00
|
|
|
exprctx.external_variables = &vars_tab;
|
2020-12-21 09:38:31 +00:00
|
|
|
exprctx.messages = messages;
|
2022-11-24 14:44:07 +00:00
|
|
|
exprctx.hashctx = &sctx->hashctx;
|
2021-03-21 10:56:17 +00:00
|
|
|
exprctx.memsuper = memsuper;
|
2021-02-04 08:03:49 +00:00
|
|
|
|
2020-12-21 09:38:31 +00:00
|
|
|
cexpr_init_symtab (&vars_tab, &exprctx);
|
2020-07-16 06:42:49 +00:00
|
|
|
|
2021-02-04 08:03:49 +00:00
|
|
|
|
|
|
|
if (!parser (0, plist, object, messages, &parsectx)) {
|
2020-07-16 06:42:49 +00:00
|
|
|
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
|
2021-04-18 11:41:08 +00:00
|
|
|
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
|
2020-07-16 06:42:49 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2021-03-21 10:56:17 +00:00
|
|
|
Hash_DelTable (vars_tab.tab);
|
2023-03-12 06:17:28 +00:00
|
|
|
PL_Release (messages);
|
2020-12-21 09:38:31 +00:00
|
|
|
|
2021-02-04 08:03:49 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-02-14 02:35:06 +00:00
|
|
|
typedef struct {
|
|
|
|
uint32_t count;
|
|
|
|
VkImageCreateInfo *info;
|
|
|
|
} imagecreate_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
uint32_t count;
|
|
|
|
VkImageViewCreateInfo *info;
|
|
|
|
} imageviewcreate_t;
|
|
|
|
|
2022-11-26 13:22:22 +00:00
|
|
|
int
|
|
|
|
QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist,
|
|
|
|
plitem_t *properties)
|
|
|
|
{
|
|
|
|
memsuper_t *memsuper = new_memsuper ();
|
|
|
|
int ret = 0;
|
|
|
|
qfv_output_t op = {};
|
|
|
|
|
|
|
|
if (parse_object (ctx, memsuper, plist, parse_qfv_output_t, &op,
|
|
|
|
properties)) {
|
|
|
|
memcpy (output, &op, sizeof (*output));
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
delete_memsuper (memsuper);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-11-24 14:44:07 +00:00
|
|
|
int vulkan_frame_count;
|
|
|
|
static cvar_t vulkan_frame_count_cvar = {
|
|
|
|
.name = "vulkan_frame_count",
|
|
|
|
.description =
|
|
|
|
"Number of frames to render in the background. More frames can "
|
|
|
|
"increase performance, but at the cost of latency. The default of 3 is"
|
|
|
|
" recommended.",
|
|
|
|
.default_value = "3",
|
|
|
|
.flags = CVAR_NONE,
|
|
|
|
.value = { .type = &cexpr_int, .value = &vulkan_frame_count },
|
|
|
|
};
|
|
|
|
int vulkan_presentation_mode;
|
|
|
|
static cvar_t vulkan_presentation_mode_cvar = {
|
|
|
|
.name = "vulkan_presentation_mode",
|
|
|
|
.description =
|
|
|
|
"desired presentation mode (may fall back to fifo).",
|
|
|
|
.default_value = "mailbox",
|
|
|
|
.flags = CVAR_NONE,
|
|
|
|
.value = {
|
|
|
|
.type = &VkPresentModeKHR_type,
|
|
|
|
.value = &vulkan_presentation_mode,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
int msaaSamples;
|
|
|
|
static cvar_t msaaSamples_cvar = {
|
|
|
|
.name = "msaaSamples",
|
|
|
|
.description =
|
|
|
|
"desired MSAA sample size.",
|
|
|
|
.default_value = "VK_SAMPLE_COUNT_1_BIT",
|
|
|
|
.flags = CVAR_NONE,
|
|
|
|
.value = { .type = &VkSampleCountFlagBits_type, .value = &msaaSamples },
|
|
|
|
};
|
|
|
|
static exprenum_t validation_enum;
|
|
|
|
static exprtype_t validation_type = {
|
|
|
|
.name = "vulkan_use_validation",
|
|
|
|
.size = sizeof (int),
|
|
|
|
.binops = cexpr_flag_binops,
|
|
|
|
.unops = cexpr_flag_unops,
|
|
|
|
.data = &validation_enum,
|
|
|
|
.get_string = cexpr_flags_get_string,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int validation_values[] = {
|
|
|
|
0,
|
|
|
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT,
|
|
|
|
};
|
|
|
|
static exprsym_t validation_symbols[] = {
|
|
|
|
{"none", &validation_type, validation_values + 0},
|
|
|
|
{"all", &validation_type, validation_values + 1},
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
static exprtab_t validation_symtab = {
|
|
|
|
validation_symbols,
|
|
|
|
};
|
|
|
|
static exprenum_t validation_enum = {
|
|
|
|
&validation_type,
|
|
|
|
&validation_symtab,
|
|
|
|
};
|
|
|
|
static cvar_t vulkan_use_validation_cvar = {
|
|
|
|
.name = "vulkan_use_validation",
|
|
|
|
.description =
|
|
|
|
"enable KRONOS Validation Layer if available (requires instance "
|
|
|
|
"restart).",
|
|
|
|
.default_value = "error|warning",
|
|
|
|
.flags = CVAR_NONE,
|
|
|
|
.value = { .type = &validation_type, .value = &vulkan_use_validation },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
vulkan_frame_count_f (void *data, const cvar_t *cvar)
|
|
|
|
{
|
|
|
|
if (vulkan_frame_count < 1) {
|
|
|
|
Sys_Printf ("Invalid frame count: %d. Setting to 1\n",
|
|
|
|
vulkan_frame_count);
|
|
|
|
vulkan_frame_count = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Vulkan_Init_Cvars (void)
|
|
|
|
{
|
|
|
|
int num_syms = 0;
|
|
|
|
for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols;
|
|
|
|
sym->name; sym++, num_syms++) {
|
|
|
|
}
|
|
|
|
for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) {
|
|
|
|
}
|
|
|
|
validation_symtab.symbols = calloc (num_syms + 1, sizeof (exprsym_t));
|
|
|
|
num_syms = 0;
|
|
|
|
for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols;
|
|
|
|
sym->name; sym++, num_syms++) {
|
|
|
|
validation_symtab.symbols[num_syms] = *sym;
|
|
|
|
validation_symtab.symbols[num_syms].type = &validation_type;
|
|
|
|
}
|
|
|
|
for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) {
|
|
|
|
validation_symtab.symbols[num_syms] = *sym;
|
|
|
|
}
|
|
|
|
Cvar_Register (&vulkan_use_validation_cvar, 0, 0);
|
|
|
|
// FIXME implement fallback choices (instead of just fifo)
|
|
|
|
Cvar_Register (&vulkan_presentation_mode_cvar, 0, 0);
|
|
|
|
Cvar_Register (&vulkan_frame_count_cvar, vulkan_frame_count_f, 0);
|
|
|
|
Cvar_Register (&msaaSamples_cvar, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static exprsym_t builtin_plist_syms[] = {
|
2023-02-10 02:04:11 +00:00
|
|
|
{ .name = "main_def",
|
|
|
|
.value = (void *)
|
|
|
|
#include "libs/video/renderer/vulkan/rp_main_def.plc"
|
|
|
|
},
|
2023-07-02 09:31:22 +00:00
|
|
|
{ .name = "main_fwd",
|
|
|
|
.value = (void *)
|
|
|
|
#include "libs/video/renderer/vulkan/rp_main_fwd.plc"
|
|
|
|
},
|
2023-06-25 14:33:47 +00:00
|
|
|
{ .name = "smp_quake",
|
|
|
|
.value = (void *)
|
|
|
|
#include "libs/video/renderer/vulkan/smp_quake.plc"
|
|
|
|
},
|
2022-11-24 14:44:07 +00:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
static plitem_t **builtin_plists;
|
|
|
|
static exprtab_t builtin_configs = { .symbols = builtin_plist_syms };
|
|
|
|
|
|
|
|
static void
|
|
|
|
build_configs (scriptctx_t *sctx)
|
|
|
|
{
|
|
|
|
int num_plists = 0;
|
|
|
|
for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) {
|
|
|
|
num_plists++;
|
|
|
|
}
|
|
|
|
builtin_plists = malloc (num_plists * sizeof (plitem_t *));
|
|
|
|
num_plists = 0;
|
|
|
|
for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) {
|
2023-03-12 05:48:14 +00:00
|
|
|
plitem_t *item = PL_GetDictionary (sym->value, &sctx->hashctx);
|
2022-11-24 14:44:07 +00:00
|
|
|
if (!item) {
|
|
|
|
// Syntax errors in the compiled-in plists are unrecoverable
|
|
|
|
Sys_Error ("Error parsing plist for %s", sym->name);
|
|
|
|
}
|
|
|
|
builtin_plists[num_plists] = item;
|
|
|
|
sym->value = &builtin_plists[num_plists];
|
|
|
|
sym->type = &cexpr_plitem;
|
|
|
|
num_plists++;
|
|
|
|
}
|
|
|
|
exprctx_t ectx = { .hashctx = &sctx->hashctx };
|
|
|
|
cexpr_init_symtab (&builtin_configs, &ectx);
|
|
|
|
}
|
|
|
|
|
2023-03-05 09:19:54 +00:00
|
|
|
static void
|
|
|
|
delete_configs (void)
|
|
|
|
{
|
|
|
|
int num_plists = 0;
|
|
|
|
for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) {
|
2023-03-12 06:17:28 +00:00
|
|
|
PL_Release (builtin_plists[num_plists]);
|
2023-03-05 09:19:54 +00:00
|
|
|
num_plists++;
|
|
|
|
}
|
|
|
|
free (builtin_plists);
|
|
|
|
}
|
|
|
|
|
2022-11-24 14:44:07 +00:00
|
|
|
plitem_t *
|
|
|
|
Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name)
|
|
|
|
{
|
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
|
|
|
if (!builtin_configs.tab) {
|
|
|
|
build_configs (sctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
plitem_t *config = 0;
|
|
|
|
exprval_t result = { .type = &cexpr_plitem, .value = &config };
|
|
|
|
exprctx_t ectx = {
|
|
|
|
.result = &result,
|
|
|
|
.symtab = &builtin_configs,
|
|
|
|
.memsuper = new_memsuper (),
|
|
|
|
.hashctx = &sctx->hashctx,
|
|
|
|
.messages = PL_NewArray (),
|
|
|
|
};
|
|
|
|
if (cexpr_eval_string (name, &ectx)) {
|
|
|
|
dstring_t *msg = dstring_newstr ();
|
|
|
|
|
|
|
|
for (int i = 0; i < PL_A_NumObjects (ectx.messages); i++) {
|
|
|
|
dasprintf (msg, "%s\n",
|
|
|
|
PL_String (PL_ObjectAtIndex (ectx.messages, i)));
|
|
|
|
}
|
|
|
|
Sys_Printf ("%s", msg->str);
|
|
|
|
dstring_delete (msg);
|
|
|
|
config = 0;
|
|
|
|
}
|
2023-03-12 06:17:28 +00:00
|
|
|
PL_Release (ectx.messages);
|
2022-11-24 14:44:07 +00:00
|
|
|
delete_memsuper (ectx.memsuper);
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Vulkan_Script_Init (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
scriptctx_t *sctx = calloc (1, sizeof (scriptctx_t));
|
|
|
|
sctx->vctx = ctx;
|
|
|
|
ctx->script_context = sctx;
|
|
|
|
|
|
|
|
exprctx_t ectx = {};
|
|
|
|
enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &sctx->hashctx);
|
|
|
|
parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &sctx->hashctx);
|
2023-03-05 09:19:54 +00:00
|
|
|
//FIXME using the script context's hashctx causes the cvar system to access
|
|
|
|
//freed hash links due to shutdown order issues. The proper fix would be to
|
|
|
|
//create a symtabs shutdown (for thread safety), but this works for now.
|
|
|
|
ectx.hashctx = 0;//&sctx->hashctx;
|
2022-11-24 14:44:07 +00:00
|
|
|
vkgen_init_symtabs (&ectx);
|
|
|
|
cexpr_init_symtab (&qfv_output_t_symtab, &ectx);
|
2023-06-22 07:44:05 +00:00
|
|
|
cexpr_init_symtab (&qfv_renderframeset_t_symtab, &ectx);
|
2022-11-24 14:44:07 +00:00
|
|
|
cexpr_init_symtab (&data_array_symtab, &ectx);
|
|
|
|
|
|
|
|
sctx->shaderModules = handlref_symtab (shaderModule_free, sctx);
|
|
|
|
sctx->setLayouts = handlref_symtab (setLayout_free, sctx);
|
|
|
|
sctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, sctx);
|
|
|
|
sctx->descriptorPools = handlref_symtab (descriptorPool_free, sctx);
|
|
|
|
sctx->samplers = handlref_symtab (sampler_free, sctx);
|
|
|
|
sctx->images = handlref_symtab (image_free, sctx);
|
|
|
|
sctx->imageViews = handlref_symtab (imageView_free, sctx);
|
|
|
|
sctx->renderpasses = handlref_symtab (renderpass_free, sctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clear_table (hashtab_t **table)
|
|
|
|
{
|
|
|
|
if (*table) {
|
|
|
|
hashtab_t *tab = *table;
|
|
|
|
*table = 0;
|
|
|
|
Hash_DelTable (tab);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Vulkan_Script_Shutdown (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
|
|
|
|
|
|
|
clear_table (&sctx->pipelineLayouts);
|
|
|
|
clear_table (&sctx->setLayouts);
|
|
|
|
clear_table (&sctx->shaderModules);
|
|
|
|
clear_table (&sctx->descriptorPools);
|
|
|
|
clear_table (&sctx->samplers);
|
|
|
|
|
2023-03-05 09:19:54 +00:00
|
|
|
delete_configs ();
|
|
|
|
|
|
|
|
Hash_DelContext (sctx->hashctx);
|
|
|
|
|
2022-11-24 14:44:07 +00:00
|
|
|
free (sctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Vulkan_Script_SetOutput (vulkan_ctx_t *ctx, qfv_output_t *output)
|
|
|
|
{
|
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
|
|
|
sctx->output = *output;
|
|
|
|
}
|
|
|
|
|
2023-02-26 04:51:24 +00:00
|
|
|
exprtab_t *
|
|
|
|
QFV_CreateSymtab (plitem_t *dict, const char *properties,
|
|
|
|
const char **extra_items, exprsym_t *extra_syms,
|
|
|
|
exprctx_t *ectx)
|
|
|
|
{
|
|
|
|
plitem_t *props = PL_ObjectForKey (dict, properties);
|
|
|
|
int num_keys = PL_D_NumKeys (props);
|
|
|
|
int num_extra = 0;
|
|
|
|
int num_syms = 0;
|
|
|
|
|
2023-02-26 17:53:03 +00:00
|
|
|
if (extra_items) {
|
|
|
|
for (const char **e = extra_items; *e; e++) {
|
|
|
|
if (PL_ObjectForKey (dict, *e)) {
|
|
|
|
num_extra++;
|
|
|
|
}
|
2023-02-26 04:51:24 +00:00
|
|
|
}
|
|
|
|
}
|
2023-02-26 17:53:03 +00:00
|
|
|
if (extra_syms) {
|
|
|
|
for (exprsym_t *sym = extra_syms; sym->name; sym++, num_syms++) { }
|
|
|
|
}
|
2023-02-26 04:51:24 +00:00
|
|
|
|
|
|
|
int total_items = num_keys + num_extra;
|
|
|
|
int total_syms = total_items + num_syms;
|
|
|
|
size_t size = (sizeof (exprtab_t)
|
|
|
|
+ (total_syms + 1) * sizeof (exprsym_t)
|
|
|
|
+ total_items * sizeof (plitem_t *));
|
|
|
|
exprtab_t *symtab = malloc (size);
|
|
|
|
*symtab = (exprtab_t) {
|
|
|
|
.symbols = (exprsym_t *) &symtab[1],
|
|
|
|
};
|
|
|
|
plitem_t **items = (plitem_t **) &symtab->symbols[total_syms + 1];
|
|
|
|
for (int i = 0; i < num_keys; i++) {
|
|
|
|
symtab->symbols[i] = (exprsym_t) {
|
|
|
|
.name = PL_KeyAtIndex (props, i),
|
|
|
|
.type = &cexpr_plitem,
|
|
|
|
.value = items + i,
|
|
|
|
};
|
|
|
|
items[i] = PL_ObjectForKey (props, symtab->symbols[i].name);
|
|
|
|
}
|
2023-02-26 17:53:03 +00:00
|
|
|
for (int i = 0, j = 0; num_extra && extra_items[i]; i++) {
|
2023-02-26 04:51:24 +00:00
|
|
|
plitem_t *val = PL_ObjectForKey (dict, extra_items[i]);
|
|
|
|
if (val) {
|
|
|
|
symtab->symbols[num_keys + j] = (exprsym_t) {
|
|
|
|
.name = extra_items[i],
|
|
|
|
.type = &cexpr_plitem,
|
2023-02-27 06:00:40 +00:00
|
|
|
.value = items + num_keys + j,
|
2023-02-26 04:51:24 +00:00
|
|
|
};
|
|
|
|
items[num_keys + j] = val;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < num_syms; i++) {
|
|
|
|
symtab->symbols[total_items + i] = extra_syms[i];
|
|
|
|
}
|
|
|
|
symtab->symbols[total_syms] = (exprsym_t) { };
|
|
|
|
|
|
|
|
cexpr_init_symtab (symtab, ectx);
|
|
|
|
return symtab;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
QFV_DestroySymtab (exprtab_t *tab)
|
|
|
|
{
|
|
|
|
Hash_DelTable (tab->tab);
|
|
|
|
free (tab);
|
|
|
|
}
|
|
|
|
|
[vulkan] Start work on a render job system
The jobs will become the core of the renderer, with each job step being
one of a render pass, compute pass, or processor (CPU-only) task. The
steps support dependencies, which will allow for threading the system in
the future.
Currently, just the structures, parse support, and prototype job
specification (render.plist) have been implemented. No conversion to
working data is done yet, and many things, in particular resources, will
need to be reworked, but this gets the basic design in.
2023-03-10 10:47:40 +00:00
|
|
|
struct qfv_jobinfo_s *
|
|
|
|
QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx)
|
|
|
|
{
|
|
|
|
memsuper_t *memsuper = new_memsuper ();
|
2023-06-25 14:33:47 +00:00
|
|
|
qfv_jobinfo_t *ji = cmemalloc (memsuper, sizeof (qfv_jobinfo_t));
|
|
|
|
*ji = (qfv_jobinfo_t) { .memsuper = memsuper };
|
[vulkan] Start work on a render job system
The jobs will become the core of the renderer, with each job step being
one of a render pass, compute pass, or processor (CPU-only) task. The
steps support dependencies, which will allow for threading the system in
the future.
Currently, just the structures, parse support, and prototype job
specification (render.plist) have been implemented. No conversion to
working data is done yet, and many things, in particular resources, will
need to be reworked, but this gets the basic design in.
2023-03-10 10:47:40 +00:00
|
|
|
|
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
|
|
|
plitem_t *messages = PL_NewArray ();
|
|
|
|
|
|
|
|
exprctx_t exprctx = {
|
|
|
|
.symtab = &root_symtab,
|
|
|
|
.messages = messages,
|
|
|
|
.hashctx = &sctx->hashctx,
|
|
|
|
.memsuper = memsuper,
|
|
|
|
};
|
|
|
|
parsectx_t parsectx = {
|
|
|
|
.ectx = &exprctx,
|
|
|
|
.vctx = ctx,
|
|
|
|
.data = rctx,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *extra_items[] = {
|
|
|
|
"images",
|
2023-06-26 02:55:15 +00:00
|
|
|
"imageviews",
|
[vulkan] Start work on a render job system
The jobs will become the core of the renderer, with each job step being
one of a render pass, compute pass, or processor (CPU-only) task. The
steps support dependencies, which will allow for threading the system in
the future.
Currently, just the structures, parse support, and prototype job
specification (render.plist) have been implemented. No conversion to
working data is done yet, and many things, in particular resources, will
need to be reworked, but this gets the basic design in.
2023-03-10 10:47:40 +00:00
|
|
|
"renderpasses",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
exprsym_t var_syms[] = {
|
2023-03-22 10:32:49 +00:00
|
|
|
{"render_output", &qfv_output_t_type, &sctx->output},
|
2023-06-22 07:44:05 +00:00
|
|
|
{"frames", &qfv_renderframeset_t_type, &rctx->frames},
|
[vulkan] Start work on a render job system
The jobs will become the core of the renderer, with each job step being
one of a render pass, compute pass, or processor (CPU-only) task. The
steps support dependencies, which will allow for threading the system in
the future.
Currently, just the structures, parse support, and prototype job
specification (render.plist) have been implemented. No conversion to
working data is done yet, and many things, in particular resources, will
need to be reworked, but this gets the basic design in.
2023-03-10 10:47:40 +00:00
|
|
|
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
|
|
|
|
{"physDevLimits", &VkPhysicalDeviceLimits_type,
|
|
|
|
&ctx->device->physDev->properties->limits },
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
exprctx.external_variables = QFV_CreateSymtab (item, "properties",
|
|
|
|
extra_items, var_syms,
|
|
|
|
&exprctx);
|
|
|
|
|
|
|
|
int ret;
|
2023-06-25 14:33:47 +00:00
|
|
|
if (!(ret = parse_qfv_jobinfo_t (0, item, ji, messages, &parsectx))) {
|
|
|
|
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
|
|
|
|
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QFV_DestroySymtab (exprctx.external_variables);
|
|
|
|
PL_Release (messages);
|
|
|
|
if (!ret) {
|
|
|
|
delete_memsuper (memsuper);
|
|
|
|
ji = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ji;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct qfv_samplerinfo_s *
|
|
|
|
QFV_ParseSamplerInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx)
|
|
|
|
{
|
|
|
|
memsuper_t *memsuper = new_memsuper ();
|
|
|
|
qfv_samplerinfo_t *si = cmemalloc (memsuper, sizeof (qfv_samplerinfo_t));
|
|
|
|
*si = (qfv_samplerinfo_t) { .memsuper = memsuper };
|
|
|
|
|
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
|
|
|
plitem_t *messages = PL_NewArray ();
|
|
|
|
|
|
|
|
exprctx_t exprctx = {
|
|
|
|
.symtab = &root_symtab,
|
|
|
|
.messages = messages,
|
|
|
|
.hashctx = &sctx->hashctx,
|
|
|
|
.memsuper = memsuper,
|
|
|
|
};
|
|
|
|
parsectx_t parsectx = {
|
|
|
|
.ectx = &exprctx,
|
|
|
|
.vctx = ctx,
|
|
|
|
.data = rctx,
|
|
|
|
};
|
|
|
|
|
|
|
|
exprsym_t var_syms[] = {
|
|
|
|
{"physDevLimits", &VkPhysicalDeviceLimits_type,
|
|
|
|
&ctx->device->physDev->properties->limits },
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
exprctx.external_variables = QFV_CreateSymtab (item, "properties",
|
|
|
|
0, var_syms, &exprctx);
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
if (!(ret = parse_qfv_samplerinfo_t (0, item, si, messages, &parsectx))) {
|
[vulkan] Start work on a render job system
The jobs will become the core of the renderer, with each job step being
one of a render pass, compute pass, or processor (CPU-only) task. The
steps support dependencies, which will allow for threading the system in
the future.
Currently, just the structures, parse support, and prototype job
specification (render.plist) have been implemented. No conversion to
working data is done yet, and many things, in particular resources, will
need to be reworked, but this gets the basic design in.
2023-03-10 10:47:40 +00:00
|
|
|
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
|
|
|
|
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
|
2023-02-09 12:17:04 +00:00
|
|
|
}
|
|
|
|
}
|
2023-02-26 04:51:24 +00:00
|
|
|
QFV_DestroySymtab (exprctx.external_variables);
|
2023-03-12 06:17:28 +00:00
|
|
|
PL_Release (messages);
|
2023-02-12 16:43:17 +00:00
|
|
|
if (!ret) {
|
2023-02-11 17:43:38 +00:00
|
|
|
delete_memsuper (memsuper);
|
2023-06-25 14:33:47 +00:00
|
|
|
si = 0;
|
2023-02-11 17:43:38 +00:00
|
|
|
}
|
2023-02-09 12:17:04 +00:00
|
|
|
|
2023-06-25 14:33:47 +00:00
|
|
|
return si;
|
2023-02-09 12:17:04 +00:00
|
|
|
}
|
2023-02-26 17:54:51 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, memsuper_t *memsuper,
|
|
|
|
exprtab_t *symtab, const char *ref,
|
|
|
|
qfv_layoutinfo_t *layout)
|
|
|
|
{
|
|
|
|
*layout = (qfv_layoutinfo_t) {};
|
|
|
|
|
|
|
|
scriptctx_t *sctx = ctx->script_context;
|
|
|
|
plitem_t *messages = PL_NewArray ();
|
|
|
|
|
|
|
|
exprctx_t exprctx = {
|
|
|
|
.symtab = &root_symtab,
|
|
|
|
.messages = messages,
|
|
|
|
.hashctx = &sctx->hashctx,
|
|
|
|
.memsuper = memsuper,
|
|
|
|
.external_variables = symtab,
|
|
|
|
};
|
|
|
|
parsectx_t parsectx = {
|
|
|
|
.ectx = &exprctx,
|
|
|
|
.vctx = ctx,
|
|
|
|
};
|
|
|
|
|
|
|
|
plitem_t *item = PL_NewString (ref);
|
|
|
|
int ret;
|
|
|
|
if (!(ret = parse_qfv_layoutinfo_t (0, item, layout, messages,
|
|
|
|
&parsectx))) {
|
|
|
|
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
|
|
|
|
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
|
|
|
|
}
|
|
|
|
}
|
2023-03-12 06:17:28 +00:00
|
|
|
PL_Release (messages);
|
|
|
|
PL_Release (item);
|
2023-02-26 17:54:51 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|