[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.
This commit is contained in:
Bill Currie 2023-03-10 19:47:40 +09:00
parent 374ca602a7
commit 4cf1c167bd
6 changed files with 256 additions and 2 deletions

View file

@ -123,6 +123,9 @@ typedef struct qfv_pipelineinfo_s {
qfv_taskinfo_t *tasks;
VkPipelineCreateFlags flags;
VkPipelineShaderStageCreateInfo *compute_stage;
uint32_t dispatch[3];
uint32_t num_graph_stages;
const VkPipelineShaderStageCreateInfo *graph_stages;
const VkPipelineVertexInputStateCreateInfo *vertexInput;
@ -167,7 +170,18 @@ typedef struct qfv_renderpassinfo_s {
qfv_subpassinfo_t *subpasses;
} qfv_renderpassinfo_t;
typedef struct qfv_computeinfo_s {
vec4f_t color;
const char *name;
uint32_t num_pipelines;
qfv_pipelineinfo_t *pipelines;
} qfv_computeinfo_t;
typedef struct qfv_renderinfo_s {
vec4f_t color;
const char *name;
struct memsuper_s *memsuper;
struct plitem_s *plitem;
uint32_t num_images;
@ -183,6 +197,33 @@ typedef struct qfv_renderinfo_s {
qfv_layoutinfo_t *layouts;
} qfv_renderinfo_t;
typedef struct qfv_processinfo_s {
vec4f_t color;
const char *name;
uint32_t num_tasks;
qfv_taskinfo_t *tasks;
} qfv_processinfo_t;
typedef struct qfv_stepinfo_s {
vec4f_t color;
const char *name;
uint32_t num_dependencies;
qfv_reference_t *dependencies;
qfv_renderinfo_t *render;
qfv_computeinfo_t *compute;
qfv_processinfo_t *process;
} qfv_stepinfo_t;
typedef struct qfv_jobinfo_s {
struct memsuper_s *memsuper;
uint32_t num_steps;
qfv_stepinfo_t *steps;
} qfv_jobinfo_t;
typedef struct qfv_label_s {
vec4f_t color;
const char *name;

View file

@ -196,7 +196,15 @@ count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts)
if (spi->attachments) {
count_as_stuff (spi->attachments, counts);
}
counts->num_pipelines += spi->num_pipelines;
for (uint32_t i = 0; i < spi->num_pipelines; i++) {
__auto_type pli = &spi->pipelines[i];
if (pli->num_graph_stages && !pli->compute_stage) {
counts->num_pipelines++;
} else {
Sys_Error ("%s:%s: invalid graphics pipeline",
spi->name, pli->name);
}
}
}
static void

View file

@ -0,0 +1,91 @@
properties = {
partphysics_layout = {
setLayouts = (particle_set);
pushConstantRanges = (
{
stageFlags = compute;
offset = 0;
size = "4 * 4 + 4";
},
);
};
partupdate_layout = {
setLayouts = (particle_set, particle_set, particle_set);
};
};
descriptorSetLayouts = {
particle_set = {
bindings = (
{
binding = 0;
descriptorType = storage_buffer;
descriptorCount = 1;
stageFlags = compute;
},
{
binding = 1;
descriptorType = storage_buffer;
descriptorCount = 1;
stageFlags = compute;
},
{
binding = 2;
descriptorType = storage_buffer;
descriptorCount = 1;
stageFlags = compute;
},
);
};
};
tasks = {
particles = {
compute = {
pipelines = {
part:update = {
color = "[0.3, 0.8, 0.9]";
tasks = (
{ func = "update_particles"; }
);
stage = {
name = main;
module = $builtin/partupdate.comp;
};
layout = partupdate_layout;
};
part:physics = {
color = "[0.6, 0.8, 0.9]";
tasks = (
{ func = "particle_physics"; }
);
stage = {
name = main;
module = $builtin/partphysics.comp;
};
layout = partphysics_layout;
};
};
};
};
shadow = {
//currently empty
};
translucent = {
tasks = (
{ func = "clear_translucent"; },
)
};
main = {
depenencies = (particles, shadow, translucent);
renderpass = main_def;
};
preoutput = {
tasks = (
{ func = "acquire_output"; },
{ func = "update_input"; },
);
};
output = {
depenencies = (main, preoutput);
renderpass = output;
};
};

View file

@ -2362,6 +2362,62 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx)
return ri;
}
struct qfv_jobinfo_s *
QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx)
{
memsuper_t *memsuper = new_memsuper ();
qfv_jobinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_jobinfo_t));
*ri = (qfv_jobinfo_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,
};
static const char *extra_items[] = {
"images",
"views",
"renderpasses",
0
};
exprsym_t var_syms[] = {
{"output", &qfv_output_t_type, &sctx->output},
{"frames", &vulkan_frameset_t_type, &ctx->frames},
{"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;
if (!(ret = parse_qfv_jobinfo_t (0, item, ri, 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_Free (messages);
if (!ret) {
delete_memsuper (memsuper);
ri = 0;
}
return ri;
}
int
QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, memsuper_t *memsuper,
exprtab_t *symtab, const char *ref,

View file

@ -90,4 +90,6 @@ struct memsuper_s;
int QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, struct memsuper_s *memsuper,
exprtab_t *symtab, const char *ref,
qfv_layoutinfo_t *layout);
struct qfv_jobinfo_s *QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item,
struct qfv_renderctx_s *rctx);
#endif//__vkparse_h

View file

@ -48,7 +48,10 @@
qfv_framebufferinfo_t,
qfv_renderpassinfo_t,
qfv_renderinfo_t,
qfv_pipelinespec_t,
qfv_computeinfo_t,
qfv_processinfo_t,
qfv_stepinfo_t,
qfv_jobinfo_t,
);
parse = {
VkSubpassDescription = {
@ -513,6 +516,11 @@
size = num_graph_stages;
values = graph_stages;
};
stage = {
type = (single, VkPipelineShaderStageCreateInfo);
value = compute_stage;
};
dispatch = auto;
vertexInput = {
type = (single, VkPipelineVertexInputStateCreateInfo);
value = vertexInput;
@ -616,8 +624,18 @@
values = bindings;
};
};
qfv_computeinfo_s = {
.name = qfv_computeinfo_t;
color = auto;
pipelines = {
type = (labeledarray, qfv_pipelineinfo_t, name);
size = num_pipelines;
values = pipelines;
};
};
qfv_renderinfo_s = {
.name = qfv_renderinfo_t;
color = auto;
properties = ignore;
output = ignore;
images = {
@ -641,5 +659,43 @@
values = descriptorsets;
};
};
qfv_processinfo_s = {
.name = qfv_processinfo_t;
color = auto;
tasks = {
type = (array, qfv_taskinfo_t);
size = num_tasks;
values = tasks;
};
};
qfv_stepinfo_s = {
.name = qfv_stepinfo_t;
color = auto;
dependencies = {
type = (array, qfv_reference_t);
size = num_dependencies;
values = dependencies;
};
render = {
type = (single, qfv_renderinfo_t);
value = render;
};
compute = {
type = (single, qfv_computeinfo_t);
value = compute;
};
process = {
type = (single, qfv_processinfo_t);
value = process;
};
};
qfv_jobinfo_s = {
.name = qfv_jobinfo_t;
steps = {
type = (array, qfv_stepinfo_t);
size = num_steps;
values = steps;
};
};
};
}