[vulkan] Ease writing of specialization data

While using binary data objects for specialization data works for bools
(as they can be 0 or -1), they don't work so well for numeric values due
to having to get the byte order correct and thus are not portable, and
difficult to get right.

Binary data is still supported, but the data can be written as a string
with an array(...) "constructor" expression taking any number of
parameters, with each parameter itself being an expression (though
values are limited at this stage).

Due to the plist format, quotes are required around the expression
("array(...)")
This commit is contained in:
Bill Currie 2021-12-01 14:49:23 +09:00
parent bd31f40c9b
commit 02ba3da0ba
2 changed files with 78 additions and 29 deletions

View file

@ -323,32 +323,6 @@ parse_array (const plfield_t *field, const plitem_t *item,
return 1; return 1;
} }
static int
parse_data (const plfield_t *field, const plitem_t *item,
void *data, plitem_t *messages, void *context)
{
__auto_type datad = (parse_data_t *) field->data;
__auto_type value = (void **) ((byte *)data + datad->value_offset);
__auto_type size = (size_t *) ((byte *)data + datad->size_offset);
const void *bindata = PL_BinaryData (item);
size_t binsize = PL_BinarySize (item);
Sys_MaskPrintf (SYS_vulkan_parse, "parse_data: %s %zd %d %p %p %p\n",
field->name, field->offset, field->type, field->parser,
field->data, data);
Sys_MaskPrintf (SYS_vulkan_parse, " %zd %zd\n", datad->value_offset,
datad->size_offset);
Sys_MaskPrintf (SYS_vulkan_parse, " %zd %p\n", binsize, bindata);
*value = vkparse_alloc (context, binsize);
memcpy (*value, bindata, binsize);
if ((void *) size > data) {
*size = binsize;
}
return 1;
}
static int static int
parse_string (const plfield_t *field, const plitem_t *item, parse_string (const plfield_t *field, const plitem_t *item,
void *data, plitem_t *messages, void *context) void *data, plitem_t *messages, void *context)
@ -795,6 +769,80 @@ parse_BasePipeline (const plitem_t *item, void **data,
return 0; return 0;
} }
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;
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;
memcpy (data->a + offset, (*param)->value, size);
offset += size;
}
*(data_array_t **) result->value = data;
}
static exprtype_t data_array_type = {
"array",
sizeof (data_array_t *),
0,
0,
};
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,
plitem_t *messages, parsectx_t *context)
{
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);
*data_ptr = vkparse_alloc (context, binsize);
memcpy (*data_ptr, bindata, binsize);
*size_ptr = binsize;
return 1;
}
data_array_t *da= 0;
exprctx_t ectx = *((parsectx_t *)context)->ectx;
exprval_t result = { &data_array_type, &da };
ectx.symtab = &data_array_symtab;
ectx.result = &result;
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;
}
return ret;
}
#include "libs/video/renderer/vulkan/vkparse.cinc" #include "libs/video/renderer/vulkan/vkparse.cinc"
static void static void
@ -955,6 +1003,7 @@ QFV_InitParse (vulkan_ctx_t *ctx)
cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); cexpr_init_symtab (&qfv_swapchain_t_symtab, &context);
cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context);
cexpr_init_symtab (&imageviewset_symtab, &context); cexpr_init_symtab (&imageviewset_symtab, &context);
cexpr_init_symtab (&data_array_symtab, &context);
if (!ctx->setLayouts) { if (!ctx->setLayouts) {
ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); ctx->shaderModules = handlref_symtab (shaderModule_free, ctx);

View file

@ -80,9 +80,9 @@
values = pMapEntries; values = pMapEntries;
}; };
data = { data = {
type = data; type = (custom, (QFBinary, QFString),
size = dataSize; parse_specialization_data);
data = pData; fields = (dataSize, pData);
}; };
}; };
VkPipelineShaderStageCreateInfo = { VkPipelineShaderStageCreateInfo = {