[vulkan] Rework pipeline parsing for better reuse

It's not entirely there yet, but the basics are working. Work is still
needed for avoiding duplication of objects (different threads will have
different contexts and thus different tables, so necessary per-thread
duplication should not become a problem) and general access to arbitrary
fields (mostly just parsing the strings)
This commit is contained in:
Bill Currie 2021-02-04 17:03:49 +09:00
parent d2536e584f
commit 8179c44042
16 changed files with 388 additions and 431 deletions

View file

@ -40,7 +40,6 @@ void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx);
void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx);
void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx);
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx);
VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name);
void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx);
void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx);
void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx, float aspect);
@ -51,4 +50,13 @@ void Vulkan_Init_Common (struct vulkan_ctx_s *ctx);
void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx);
void Vulkan_CreateStagingBuffers (struct vulkan_ctx_s *ctx);
VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name);
VkDescriptorPool Vulkan_CreateDescriptorPool (struct vulkan_ctx_s *ctx,
const char *name);
VkPipelineLayout Vulkan_CreatePipelineLayout (struct vulkan_ctx_s *ctx,
const char *name);
VkSampler Vulkan_CreateSampler (struct vulkan_ctx_s *ctx, const char *name);
VkDescriptorSetLayout Vulkan_CreateDescriptorSetLayout(struct vulkan_ctx_s*ctx,
const char *name);
#endif // __QF_Vulkan_vid_h

View file

@ -58,6 +58,7 @@ typedef struct vulkan_ctx_s {
struct hashlink_s *hashlinks; //FIXME want per thread
VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain
struct plitem_s *pipelineDef;
struct hashtab_s *shaderModules;
struct hashtab_s *setLayouts;
struct hashtab_s *pipelineLayouts;

View file

@ -1,19 +1,4 @@
{
shaderModules = {
// specify shader modules to load into memory
// key is the name of the module for referecy by the pipeline
// value the path to the spv file to load
// $shader refers to the shader install path
// $builtin refers to compiled-in shaders
passthrough = $builtin/passthrough.vert;
pushcolor = $builtin/pushcolor.frag;
twodv = $builtin/twod.vert;
twodf = $builtin/twod.frag;
quakebspv = $builtin/quakebsp.vert;
quakebspf = $builtin/quakebsp.frag;
aliasv = $builtin/alias.vert;
aliasf = $builtin/alias.frag;
};
samplers = {
quakepic = {
magFilter = nearest;
@ -32,7 +17,7 @@
borderColor = float_transparent_black;
unnormalizedCoordinates = false;
};
quakebsp.sampler = {
quakebsp_sampler = {
magFilter = linear;
minFilter = linear;
mipmapMode = linear;
@ -49,7 +34,7 @@
borderColor = float_transparent_black;
unnormalizedCoordinates = false;
};
alias.sampler = {
alias_sampler = {
magFilter = linear;
minFilter = linear;
mipmapMode = linear;
@ -68,7 +53,7 @@
};
};
descriptorPools = {
twod.pool = {
twod_pool = {
flags = 0;
maxSets = $framebuffers.size;
bindings = (
@ -82,7 +67,7 @@
},
);
};
alias.pool = {
alias_pool = {
flags = 0;
maxSets = "2z * $framebuffers.size";
bindings = (
@ -94,7 +79,7 @@
};
};
setLayouts = {
twod.set = {
twod_set = {
bindings = (
{
binding = 0;
@ -110,7 +95,7 @@
},
);
};
quakebsp.set = {
quakebsp_set = {
flags = push_descriptor;
bindings = (
{
@ -151,7 +136,7 @@
},
);
};
alias.set = {
alias_set = {
flags = push_descriptor;
bindings = (
{
@ -174,7 +159,7 @@
},
);
};
alias.matrices = {
alias_matrices = {
bindings = (
{
binding = 0;
@ -184,7 +169,7 @@
},
);
};
alias.textures = {
alias_textures = {
flags = push_descriptor;
bindings = (
{
@ -213,7 +198,7 @@
},
);
};
alias.lights = {
alias_lights = {
bindings = (
{
binding = 0;
@ -242,11 +227,11 @@
};
};
pipelineLayouts = {
twod.layout = {
setLayouts = (twod.set);
twod_layout = {
setLayouts = (twod_set);
};
quakebsp.layout = {
setLayouts = (quakebsp.set);
quakebsp_layout = {
setLayouts = (quakebsp_set);
pushConstantRanges = (
{
stageFlags = vertex;
@ -260,9 +245,9 @@
},
);
};
alias.layout = {
//setLayouts = (alias.matrices, alias.lights, alias.textures);
setLayouts = (alias.set);
alias_layout = {
//setLayouts = (alias_matrices, alias_lights, alias_textures);
setLayouts = (alias_set);
pushConstantRanges = (
{
stageFlags = vertex;
@ -290,11 +275,15 @@
pipelines = {
alias = {
stages = (
{ stage = vertex; name = main; module = aliasv; },
{
stage = vertex;
name = main;
module = $builtin/alias.vert;
},
{
stage = fragment;
name = main;
module = aliasf;
module = $builtin/alias.frag;
specializationInfo = {
mapEntries = (
{ size = 4; offset = 0; constantID = 0; },
@ -412,13 +401,21 @@
dynamic = {
dynamicState = ( viewport, scissor, blend_constants );
};
layout = alias.layout;
layout = alias_layout;
//renderPass = renderpass;
};
quakebsp.main = {
quakebsp_main = {
stages = (
{ stage = vertex; name = main; module = quakebspv; },
{ stage = fragment; name = main; module = quakebspf; },
{
stage = vertex;
name = main;
module = $builtin/quakebsp.vert;
},
{
stage = fragment;
name = main;
module = $builtin/quakebsp.frag;
},
);
vertexInput = {
bindings = (
@ -501,16 +498,20 @@
dynamic = {
dynamicState = ( viewport, scissor, blend_constants );
};
layout = quakebsp.layout;
layout = quakebsp_layout;
//renderPass = renderpass;
};
quakebsp.skysheet = {
quakebsp_skysheet = {
stages = (
{ stage = vertex; name = main; module = quakebspv; },
{
stage = vertex;
name = main;
module = $builtin/quakebsp.vert;
},
{
stage = fragment;
name = main;
module = quakebspf;
module = $builtin/quakebsp.frag;
specializationInfo = {
mapEntries = (
{ size = 4; offset = 0; constantID = 0; },
@ -603,13 +604,21 @@
dynamic = {
dynamicState = ( viewport, scissor, blend_constants );
};
layout = quakebsp.layout;
layout = quakebsp_layout;
//renderPass = renderpass;
};
twod = {
stages = (
{ stage = vertex; name = main; module = twodv; },
{ stage = fragment; name = main; module = twodf; },
{
stage = vertex;
name = main;
module = $builtin/twod.vert;
},
{
stage = fragment;
name = main;
module = $builtin/twod.frag;
},
);
vertexInput = {
bindings = (
@ -698,7 +707,7 @@
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = twod.layout;
layout = twod_layout;
//renderPass = renderpass;
};
};
@ -764,7 +773,7 @@
},
);
};
renderpass.msaa = {
renderpass_msaa = {
attachments = (
{
flags = 0;

View file

@ -13,8 +13,6 @@ vkgen_dat_src= \
libs/video/renderer/vulkan/vkgen/vkfieldstring.r \
libs/video/renderer/vulkan/vkgen/vkfieldtype.r \
libs/video/renderer/vulkan/vkgen/vkgen.r \
libs/video/renderer/vulkan/vkgen/vkhandle.r \
libs/video/renderer/vulkan/vkgen/vkresource.r \
libs/video/renderer/vulkan/vkgen/vkstruct.r \
libs/video/renderer/vulkan/vkgen/vktype.r \
libs/video/renderer/vulkan/vkgen/vulkan.r

View file

@ -10,8 +10,6 @@
#include "vkgen.h"
#include "vkstruct.h"
#include "vkenum.h"
#include "vkhandle.h"
#include "vkresource.h"
static AutoreleasePool *autorelease_pool;
static void
@ -154,7 +152,6 @@ main(int argc, string *argv)
PLItem *plist;
PLItem *search;
PLItem *handles;
PLItem *resources;
arp_start ();
@ -179,7 +176,6 @@ main(int argc, string *argv)
}
search = [[plist getObjectForKey: "search"] retain];
handles = [[plist getObjectForKey: "handles"] retain];
resources = [[plist getObjectForKey: "resources"] retain];
parse = [[plist getObjectForKey: "parse"] retain];
encodings = PR_FindGlobal (".type_encodings");
@ -204,17 +200,6 @@ main(int argc, string *argv)
}
}
PLItem *handle_keys = [[handles allKeys] retain];
for (int i = [handle_keys count]; i-- > 0; ) {
string search_name = [[handle_keys getObjectAtIndex:i] string];
id obj = (id) Hash_Find (available_types, search_name);
obj = [obj resolveType];
printf("handle: %d %s\n", obj, class_get_class_name([obj class]));
if (obj && [obj class] == [Struct class]) {
[obj addToQueue];
}
}
while ([queue count]) {
id obj = [queue objectAtIndex:0];
[queue removeObjectAtIndex:0];
@ -261,23 +246,6 @@ main(int argc, string *argv)
[obj writeTable];
arp_end ();
}
for (int i = [handle_keys count]; i-- > 0; ) {
string key = [[handle_keys getObjectAtIndex:i] string];
output_handle (key, [handles getObjectForKey: key]);
}
for (int i = [resources count]; i-- > 0; ) {
PLItem *res = [resources getObjectAtIndex:i];
output_resource_data (res);
}
// keep the order intuitive (since it matters)
fprintf (output_file, "static parseres_t parse_resources[] = {\n");
for (int i = 0; i < [resources count]; i++) {
PLItem *res = [resources getObjectAtIndex:i];
output_resource_entry (res);
}
fprintf (output_file, "\t{}\n");
fprintf (output_file, "};\n");
fprintf (output_file, "static void\n");
fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n");
fprintf (output_file, "{\n");

View file

@ -1,8 +0,0 @@
#ifndef __renderer_vulkan_vkgen_vkhandle_h
#define __renderer_vulkan_vkgen_vkhandle_h
@class PLItem;
void output_handle (string name, PLItem *handle);
#endif//__renderer_vulkan_vkgen_vkhandle_h

View file

@ -1,74 +0,0 @@
#include <string.h>
#include <PropertyList.h>
#include "vkgen.h"
#include "vkhandle.h"
void
output_handle (string name, PLItem *handle)
{
string symtab = str_hold ([[handle getObjectForKey:"symtab"] string]);
string class = str_hold ([[handle getObjectForKey:"class"] string]);
string create = str_hold ([[handle getObjectForKey:"create"] string]);
string custom = str_hold ([[handle getObjectForKey:"custom"] string]);
if (!custom) {
fprintf (output_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context)\n", name);
fprintf (output_file, "{\n");
fprintf (output_file, "\t__auto_type handle = (%s *) data[0];\n", name);
fprintf (output_file, "\tvulkan_ctx_t *ctx = context->vctx;\n");
fprintf (output_file, "\tqfv_device_t *device = ctx->device;\n");
fprintf (output_file, "\tqfv_devfuncs_t *dfunc = device->funcs;\n");
fprintf (output_file, "\tif (PL_Type (item) == QFString) {\n");
fprintf (output_file, "\t\tconst char *name = PL_String (item);\n");
fprintf (output_file, "\t\thandleref_t *hr = Hash_Find (ctx->%s, name);\n", symtab);
fprintf (output_file, "\t\tif (!hr) {\n");
fprintf (output_file, "\t\t\tPL_Message (messages, item, \"undefined %s %%s\", name);\n", class);
fprintf (output_file, "\t\t\treturn 0;\n");
fprintf (output_file, "\t\t}\n");
fprintf (output_file, "\t\t*handle = (%s) hr->handle;\n", name);
fprintf (output_file, "\t\treturn 1;\n");
fprintf (output_file, "\t}\n");
fprintf (output_file, "\t%sCreateInfo createInfo = {};\n", name);
fprintf (output_file, "\tif (!parse_%sCreateInfo (0, item, &createInfo, messages, context)) {\n", name);
fprintf (output_file, "\t\treturn 0;\n");
fprintf (output_file, "\t}\n");
fprintf (output_file, "\tVkResult res;\n");
fprintf (output_file, "\tres = dfunc->%s (device->dev, &createInfo, 0, handle);\n", create);
fprintf (output_file, "\tif (res != VK_SUCCESS) {\n");
fprintf (output_file, "\t\tPL_Message (messages, item, \"could not create %s\");\n", class);
fprintf (output_file, "\t\treturn 0;\n");
fprintf (output_file, "\t}\n");
fprintf (output_file, "\treturn 1;\n");
fprintf (output_file, "}\n");
}
fprintf (output_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name);
fprintf (output_file, "{\n");
fprintf (output_file, "\thandleref_t *handleref = data;\n");
fprintf (output_file, "\tvoid *hrdata[] = { &handleref->handle };\n");
fprintf (output_file, "\thandleref->name = strdup (field->name);\n");
if (custom) {
fprintf (output_file, "\treturn %s (item, hrdata, messages, context);\n", custom);
} else {
fprintf (output_file, "\treturn parse_%s (item, hrdata, messages, context);\n", name);
}
fprintf (output_file, "}\n");
fprintf (output_file, "%s QFV_Get%s (vulkan_ctx_t *ctx, const char *name)\n", name, str_mid (name, 2));
fprintf (output_file, "{\n");
fprintf (output_file, "\thandleref_t *handleref = Hash_Find (ctx->%s, name);\n", symtab);
fprintf (output_file, "\treturn handleref ? (%s) handleref->handle : 0;\n", name);
fprintf (output_file, "}\n");
if (!custom) {
fprintf (header_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context);\n", name);
}
fprintf (header_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name);
fprintf (output_file, "%s QFV_Get%s (vulkan_ctx_t *ctx, const char *name);\n", name, str_mid (name, 2));
str_free (custom);
str_free (symtab);
str_free (class);
str_free (create);
}

View file

@ -1,9 +0,0 @@
#ifndef __renderer_vulkan_vkgen_vkresource_h
#define __renderer_vulkan_vkgen_vkresource_h
@class PLItem;
void output_resource_data (PLItem *resource);
void output_resource_entry (PLItem *resource);
#endif//__renderer_vulkan_vkgen_vkresource_h

View file

@ -1,44 +0,0 @@
#include <string.h>
#include <PropertyList.h>
#include "vkgen.h"
#include "vkresource.h"
void
output_resource_data (PLItem *resource)
{
string name = str_hold ([[resource getObjectForKey:"name"] string]);
string parse_type = str_hold ([[resource getObjectForKey:"parse_type"] string]);
string parser = str_hold ([[resource getObjectForKey:"parser"] string]);
string type = str_hold ([[resource getObjectForKey:"type"] string]);
fprintf (output_file, "static plelement_t resource_%s_data = {\n", name);
fprintf (output_file, "\t%s,\n", parse_type);
fprintf (output_file, "\tsizeof (%s),\n", type);
fprintf (output_file, "\tmalloc,\n");
fprintf (output_file, "\t%s,\n", parser);
fprintf (output_file, "\t0,\n");
fprintf (output_file, "};\n");
fprintf (output_file, "static plfield_t resource_%s_field = {\n", name);
fprintf (output_file, "\t0, 0, %s, 0, &resource_%s_data\n",
parse_type, name);
fprintf (output_file, "};\n");
str_free (name);
str_free (parse_type);
str_free (parser);
str_free (type);
}
void
output_resource_entry (PLItem *resource)
{
string name = str_hold ([[resource getObjectForKey:"name"] string]);
string table = str_hold ([[resource getObjectForKey:"table"] string]);
fprintf (output_file,
"\t{\"%s\", &resource_%s_field, field_offset (vulkan_ctx_t, %s) },\n",
name, name, table);
str_free (name);
str_free (table);
}

View file

@ -362,48 +362,103 @@ parse_RGBA (const plitem_t *item, void **data,
return ret;
}
static void
add_handle (hashtab_t *tab, const char *name, uint64_t handle)
{
handleref_t *hr = malloc (sizeof (handleref_t));
hr->name = strdup (name);
hr->handle = handle;
Hash_Add (tab, hr);
}
static int
parse_VkShaderModule (const plitem_t *item, void **data,
plitem_t *messages, parsectx_t *context)
{
__auto_type handle = (VkShaderModule *) data[0];
vulkan_ctx_t *ctx = context->vctx;
qfv_device_t *device = ctx->device;
const char *name = PL_String (item);
handleref_t *hr = Hash_Find (ctx->shaderModules, name);
if (!hr) {
PL_Message (messages, item, "undefined shader module %s", name);
if (hr) {
*handle = (VkShaderModule) hr->handle;
return 1;
}
if (!(*handle = QFV_CreateShaderModule (device, name))) {
PL_Message (messages, item, "could not find shader %s", name);
return 0;
}
*handle = (VkShaderModule) hr->handle;
add_handle (ctx->shaderModules, name, (uint64_t) *handle);
return 1;
}
static int
parse_VkShaderModule_resource (const plitem_t *item, void **data,
plitem_t *messages, parsectx_t *context)
parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item,
void *data, plitem_t *messages, void *context)
{
__auto_type handle = (VkShaderModule *) data[0];
__auto_type handle = (VkDescriptorSetLayout *) data;
int ret = 1;
exprctx_t ectx = *((parsectx_t *) context)->ectx;
vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;
qfv_device_t *device = ctx->device;
const char *shader_path = PL_String (item);
if (!(*handle = QFV_CreateShaderModule (device, shader_path))) {
PL_Message (messages, item, "could not find shader %s", shader_path);
return 0;
const char *name = PL_String (item);
Sys_Printf ("parse_VkDescriptorSetLayout: %s\n", name);
name = va (ctx->va_ctx, "$properties.setLayouts.%s", name);
handleref_t *hr = Hash_Find (ctx->setLayouts, name);
if (hr) {
*handle = (VkDescriptorSetLayout) hr->handle;
return 1;
}
QFV_duSetObjectName (device, VK_OBJECT_TYPE_SHADER_MODULE, *handle,
va (ctx->va_ctx, "shader:%s", shader_path));
return 1;
plitem_t *setItem = 0;
exprval_t result = { &cexpr_plitem, &setItem };
ectx.symtab = 0;
ectx.result = &result;
ret = !cexpr_eval_string (name, &ectx);
if (ret) {
VkDescriptorSetLayout setLayout;
setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem);
*handle = (VkDescriptorSetLayout) setLayout;
add_handle (ctx->setLayouts, name, (uint64_t) setLayout);
}
return ret;
}
static int
parse_VkDescriptorSetLayout_array (const plfield_t *field,
const plitem_t *item, void *data,
plitem_t *messages, void *context)
parse_VkPipelineLayout (const plitem_t *item, void **data,
plitem_t *messages, parsectx_t *context)
{
void *layout[] = { data };
return parse_VkDescriptorSetLayout (item, layout, messages, context);
__auto_type handle = (VkPipelineLayout *) data[0];
int ret = 1;
exprctx_t ectx = *((parsectx_t *) context)->ectx;
vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;
const char *name = PL_String (item);
Sys_Printf ("parse_VkPipelineLayout: %s\n", name);
name = va (ctx->va_ctx, "$properties.pipelineLayouts.%s", name);
handleref_t *hr = Hash_Find (ctx->pipelineLayouts, name);
if (hr) {
*handle = (VkPipelineLayout) hr->handle;
return 1;
}
plitem_t *setItem = 0;
exprval_t result = { &cexpr_plitem, &setItem };
ectx.symtab = 0;
ectx.result = &result;
ret = !cexpr_eval_string (name, &ectx);
if (ret) {
VkPipelineLayout layout;
layout = QFV_ParsePipelineLayout (ctx, setItem);
*handle = (VkPipelineLayout) layout;
add_handle (ctx->pipelineLayouts, name, (uint64_t) layout);
}
return ret;
}
static const char *
@ -600,54 +655,6 @@ handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx)
ctx, &ctx->hashlinks);
}
void
QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef)
{
plitem_t *messages = PL_NewArray ();
exprsym_t var_syms[] = {
{"swapchain", &qfv_swapchain_t_type, ctx->swapchain},
{"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers},
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{}
};
exprtab_t vars_tab = { var_syms, 0 };
exprctx_t exprctx = {};
parsectx_t parsectx = { &exprctx, ctx };
int ret = 1;
exprctx.memsuper = new_memsuper ();
exprctx.messages = messages;
exprctx.hashlinks = &ctx->hashlinks;
exprctx.external_variables = &vars_tab;
cexpr_init_symtab (&vars_tab, &exprctx);
if (!ctx->setLayouts) {
ctx->shaderModules = handlref_symtab (shaderModule_free, ctx);
ctx->setLayouts = handlref_symtab (setLayout_free, ctx);
ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx);
ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx);
ctx->samplers = handlref_symtab (sampler_free, ctx);
}
for (parseres_t *res = parse_resources; res->name; res++) {
plitem_t *item = PL_ObjectForKey (pipelinedef, res->name);
if (item) {
__auto_type table = *(hashtab_t **) ((size_t) ctx + res->offset);
Sys_Printf ("found %s\n", res->name);
ret &= PL_ParseSymtab (res->field, item, table, messages,
&parsectx);
}
}
if (!ret || developer->int_val & SYS_VULKAN) {
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
}
}
PL_Free (messages);
delete_memsuper (exprctx.memsuper);
}
static const char *
enum_symtab_getkey (const void *e, void *unused)
{
@ -666,6 +673,14 @@ QFV_InitParse (vulkan_ctx_t *ctx)
cexpr_init_symtab (&qfv_swapchain_t_symtab, &context);
cexpr_init_symtab (&vulkan_framebufferset_t_symtab, &context);
cexpr_init_symtab (&imageset_symtab, &context);
if (!ctx->setLayouts) {
ctx->shaderModules = handlref_symtab (shaderModule_free, ctx);
ctx->setLayouts = handlref_symtab (setLayout_free, ctx);
ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx);
ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx);
ctx->samplers = handlref_symtab (sampler_free, ctx);
}
}
exprenum_t *
@ -674,13 +689,79 @@ QFV_GetEnum (const char *name)
return Hash_Find (enum_symtab, name);
}
static int
parse_object (vulkan_ctx_t *ctx, plitem_t *plist,
plparser_t parser, void *object)
{
plitem_t *messages = PL_NewArray ();
exprctx_t exprctx = {};
parsectx_t parsectx = { &exprctx, ctx };
exprsym_t var_syms[] = {
{"swapchain", &qfv_swapchain_t_type, ctx->swapchain},
{"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers},
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{"properties", &cexpr_plitem, &ctx->pipelineDef},
{}
};
exprtab_t vars_tab = { var_syms, 0 };
exprctx.external_variables = &vars_tab;
exprctx.memsuper = new_memsuper ();
exprctx.messages = messages;
exprctx.hashlinks = &ctx->hashlinks;
cexpr_init_symtab (&vars_tab, &exprctx);
if (!parser (0, plist, object, messages, &parsectx)) {
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
}
return 0;
}
PL_Free (messages);
delete_memsuper (exprctx.memsuper);
return 1;
}
static int
parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data,
plitem_t *messages, void *context)
{
return PL_ParseStruct (renderpass_fields, item, data, messages, context);
}
VkRenderPass
QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist)
{
qfv_device_t *device = ctx->device;
qfv_renderpass_t renderpass_data = {};
plitem_t *messages = PL_NewArray ();
if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data)) {
return 0;
}
VkRenderPass renderpass;
renderpass = QFV_CreateRenderPass (device,
renderpass_data.attachments,
renderpass_data.subpasses,
renderpass_data.dependencies);
free (renderpass_data.attachments);
for (size_t i = 0; i < renderpass_data.subpasses->size; i++) {
free ((void *) renderpass_data.subpasses->a[i].pInputAttachments);
free ((void *) renderpass_data.subpasses->a[i].pColorAttachments);
free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments);
free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment);
free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments);
}
free (renderpass_data.subpasses);
free (renderpass_data.dependencies);
return renderpass;
/* plitem_t *messages = PL_NewArray ();
exprsym_t var_syms[] = {
{"swapchain", &qfv_swapchain_t_type, ctx->swapchain},
{"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers},
@ -707,11 +788,6 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist)
PL_Free (messages);
delete_memsuper (exprctx.memsuper);
renderpass = QFV_CreateRenderPass (device,
renderpass_data.attachments,
renderpass_data.subpasses,
renderpass_data.dependencies);
free (renderpass_data.attachments);
for (size_t i = 0; i < renderpass_data.subpasses->size; i++) {
free ((void *) renderpass_data.subpasses->a[i].pInputAttachments);
@ -722,7 +798,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist)
}
free (renderpass_data.subpasses);
free (renderpass_data.dependencies);
return renderpass;
return renderpass;*/
}
VkPipeline
@ -730,34 +806,13 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist)
{
qfv_device_t *device = ctx->device;
plitem_t *messages = PL_NewArray ();
exprctx_t exprctx = {};
parsectx_t parsectx = { &exprctx, ctx };
exprsym_t var_syms[] = {
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{}
};
exprtab_t vars_tab = { var_syms, 0 };
exprctx.external_variables = &vars_tab;
exprctx.memsuper = new_memsuper ();
exprctx.messages = messages;
exprctx.hashlinks = &ctx->hashlinks;
cexpr_init_symtab (&vars_tab, &exprctx);
__auto_type cInfo = QFV_AllocGraphicsPipelineCreateInfoSet (1, alloca);
memset (&cInfo->a[0], 0, sizeof (cInfo->a[0]));
if (!parse_VkGraphicsPipelineCreateInfo (0, plist, &cInfo->a[0],
messages, &parsectx)) {
for (int i = 0; i < PL_A_NumObjects (messages); i++) {
Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i)));
}
if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo,
&cInfo->a[0])) {
return 0;
}
PL_Free (messages);
delete_memsuper (exprctx.memsuper);
cInfo->a[0].renderPass = ctx->renderpass.renderpass;
__auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo);
@ -765,3 +820,77 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist)
free (plSet);
return pipeline;
}
VkDescriptorPool
QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkDescriptorPoolCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo)) {
return 0;
}
VkDescriptorPool pool;
dfunc->vkCreateDescriptorPool (device->dev, &cInfo, 0, &pool);
return pool;
}
VkDescriptorSetLayout
QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkDescriptorSetLayoutCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo,
&cInfo)) {
return 0;
}
VkDescriptorSetLayout setLayout;
dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout);
return setLayout;
}
VkPipelineLayout
QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkPipelineLayoutCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo,
&cInfo)) {
return 0;
}
VkPipelineLayout layout;
dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout);
return layout;
}
VkSampler
QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkSamplerCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo)) {
return 0;
}
VkSampler sampler;
dfunc->vkCreateSampler (device->dev, &cInfo, 0, &sampler);
return sampler;
}

View file

@ -24,18 +24,15 @@ typedef struct handleref_s {
uint64_t handle;
} handleref_t;
VkShaderModule QFV_GetShaderModule (vulkan_ctx_t *ctx, const char *name);
VkDescriptorPool QFV_GetDescriptorPool (vulkan_ctx_t *ctx, const char *name);
VkDescriptorSetLayout QFV_GetDescriptorSetLayout (vulkan_ctx_t *ctx,
const char *name);
VkPipelineLayout QFV_GetPipelineLayout (vulkan_ctx_t *ctx, const char *name);
VkSampler QFV_GetSampler (vulkan_ctx_t *ctx, const char *name);
void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *plist);
void QFV_InitParse (vulkan_ctx_t *ctx);
exprenum_t *QFV_GetEnum (const char *name);
VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist);
VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist);
VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist);
VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx,
plitem_t *plist);
VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist);
VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist);
#endif//__vkparse_h

View file

@ -21,70 +21,6 @@
VkDescriptorPoolCreateInfo,
VkSamplerCreateInfo,
);
handles = {
VkShaderModule = {
symtab = shaderModules;
class = "shader module";
custom = parse_VkShaderModule_resource;
};
VkDescriptorPool = {
symtab = descriptorPools;
class = "descriptor pool";
create = vkCreateDescriptorPool;
};
VkDescriptorSetLayout = {
symtab = setLayouts;
class = "set layout";
create = vkCreateDescriptorSetLayout;
};
VkPipelineLayout = {
symtab = pipelineLayouts;
class = "pipeline layout";
create = vkCreatePipelineLayout;
};
VkSampler = {
symtab = samplers;
class = "sampler";
create = vkCreateSampler;
};
};
resources = (
{
name = shaderModules;
parse_type = QFString;
parser = parse_VkShaderModule_handleref;
type = handleref_t;
table = shaderModules;
},
{
name = setLayouts;
parse_type = QFDictionary;
parser = parse_VkDescriptorSetLayout_handleref;
type = handleref_t;
table = setLayouts;
},
{
name = pipelineLayouts;
parse_type = QFDictionary;
parser = parse_VkPipelineLayout_handleref;
type = handleref_t;
table = pipelineLayouts;
},
{
name = descriptorPools;
parse_type = QFDictionary;
parser = parse_VkDescriptorPool_handleref;
type = handleref_t;
table = descriptorPools;
},
{
name = samplers;
parse_type = QFDictionary;
parser = parse_VkSampler_handleref;
type = handleref_t;
table = samplers;
},
);
parse = {
VkSubpassDescription = {
flags = auto;
@ -279,7 +215,7 @@
type = (array, {
parse_type = (QFDictionary, QFString);
type = VkDescriptorSetLayout;
parser = parse_VkDescriptorSetLayout_array;
parser = parse_VkDescriptorSetLayout;
});
size = setLayoutCount;
values = pSetLayouts;
@ -338,8 +274,7 @@
value = pDynamicState;
};
layout = {
type = (custom, (QFDictionary, QFString),
parse_VkPipelineLayout);
type = (custom, QFString, parse_VkPipelineLayout);
fields = (layout);
};
basePipelineHandle = {

View file

@ -63,7 +63,6 @@
#include "r_internal.h"
#include "vid_vulkan.h"
#include "vkparse.h"
void
Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx)
@ -259,12 +258,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx)
actx->frames.grow = 0;
actx->pipeline = Vulkan_CreatePipeline (ctx, "alias");
actx->layout = QFV_GetPipelineLayout (ctx, "alias.layout");
QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, actx->layout,
va (ctx->va_ctx, "layout:%s", "alias.layout"));
actx->sampler = QFV_GetSampler (ctx, "alias.sampler");
QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, actx->sampler,
va (ctx->va_ctx, "sampler:%s", "alias.sampler"));
actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout");
actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler");
/*__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca);
for (size_t i = 0; i < layouts->size / 2; i++) {

View file

@ -68,7 +68,6 @@
#include "r_internal.h"
#include "vid_vulkan.h"
#include "vkparse.h"
static float identity[] = {
1, 0, 0, 0,
@ -1449,14 +1448,10 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
DARRAY_RESIZE (&bctx->frames, frames);
bctx->frames.grow = 0;
bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main");
bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp.skysheet");
bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp.layout");
QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, bctx->layout,
va (ctx->va_ctx, "layout:%s", "quakebsp.layout"));
bctx->sampler = QFV_GetSampler (ctx, "quakebsp.sampler");
QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, bctx->sampler,
va (ctx->va_ctx, "sampler:%s", "quakebsp.sampler"));
bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp_main");
bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp_skysheet");
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
__auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca);
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers);

View file

@ -64,7 +64,6 @@
#include "r_internal.h"
#include "vid_vulkan.h"
#include "vkparse.h"
typedef struct {
float xy[2];
@ -371,7 +370,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
ctx->cmdpool);
dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba,
dctx->stage);
dctx->sampler = QFV_GetSampler (ctx, "quakepic");
dctx->sampler = Vulkan_CreateSampler (ctx, "quakepic");
qpic_t *charspic = Draw_Font8x8Pic ();
@ -384,13 +383,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
dctx->pipeline = Vulkan_CreatePipeline (ctx, "twod");
dctx->layout = QFV_GetPipelineLayout (ctx, "twod.layout");
dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout");
__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca);
for (size_t i = 0; i < layouts->size; i++) {
layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod.set");
layouts->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set");
}
__auto_type pool = QFV_GetDescriptorPool (ctx, "twod.pool");
__auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool");
VkDescriptorBufferInfo bufferInfo = {
ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE

View file

@ -224,21 +224,25 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx)
}
}
static void
qfv_load_pipeline (vulkan_ctx_t *ctx)
static plitem_t *
qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name)
{
if (!ctx->pipelineDef) {
ctx->pipelineDef = PL_GetPropertyList (quakeforge_pipeline);
if (ctx->pipelineDef) {
QFV_ParseResources (ctx, ctx->pipelineDef);
}
}
plitem_t *item = ctx->pipelineDef;
if (!item || !(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading %s\n", name);
} else {
Sys_Printf ("Found %s def\n", name);
}
return item;
}
void
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
{
qfv_load_pipeline (ctx);
const char *name = "renderpass";//FIXME
qfv_device_t *device = ctx->device;
VkDevice dev = device->dev;
@ -249,15 +253,13 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val,
QFV_GetMaxSampleCount (device->physDev));
if (ctx->msaaSamples > 1) {
name = "renderpass.msaa";
name = "renderpass_msaa";
}
plitem_t *item = ctx->pipelineDef;
if (!item || !(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading renderpass: %s\n", name);
//FIXME a tad inconsistent
plitem_t *item = qfv_load_pipeline (ctx, name);
if (!item) {
return;
} else {
Sys_Printf ("Found renderpass def: %s\n", name);
}
qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage));
@ -375,15 +377,7 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
VkPipeline
Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name)
{
qfv_load_pipeline (ctx);
plitem_t *item = ctx->pipelineDef;
if (!item || !(item = PL_ObjectForKey (item, "pipelines"))) {
Sys_Printf ("error loading pipelines\n");
return 0;
} else {
Sys_Printf ("Found pipelines def\n");
}
plitem_t *item = qfv_load_pipeline (ctx, "pipelines");
if (!(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading pipeline %s\n", name);
return 0;
@ -396,6 +390,70 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name)
return pipeline;
}
VkDescriptorPool
Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name)
{
plitem_t *item = qfv_load_pipeline (ctx, "descriptorPools");
if (!(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading descriptor pool %s\n", name);
return 0;
} else {
Sys_Printf ("Found descriptor pool def %s\n", name);
}
VkDescriptorPool pool = QFV_ParseDescriptorPool (ctx, item);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool,
va (ctx->va_ctx, "descriptor_pool:%s", name));
return pool;
}
VkPipelineLayout
Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name)
{
plitem_t *item = qfv_load_pipeline (ctx, "pipelineLayouts");
if (!(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading pipeline layout %s\n", name);
return 0;
} else {
Sys_Printf ("Found pipeline layout def %s\n", name);
}
VkPipelineLayout layout = QFV_ParsePipelineLayout (ctx, item);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout,
va (ctx->va_ctx, "pipeline_layout:%s", name));
return layout;
}
VkSampler
Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name)
{
plitem_t *item = qfv_load_pipeline (ctx, "samplers");
if (!(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading sampler %s\n", name);
return 0;
} else {
Sys_Printf ("Found sampler def %s\n", name);
}
VkSampler sampler = QFV_ParseSampler (ctx, item);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler,
va (ctx->va_ctx, "sampler:%s", name));
return sampler;
}
VkDescriptorSetLayout
Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name)
{
plitem_t *item = qfv_load_pipeline (ctx, "setLayouts");
if (!(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading descriptor set %s\n", name);
return 0;
} else {
Sys_Printf ("Found descriptor set def %s\n", name);
}
VkDescriptorSetLayout set = QFV_ParseDescriptorSetLayout (ctx, item);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,
set, va (ctx->va_ctx, "descriptor_set:%s", name));
return set;
}
void
Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx)
{