[vulkan] Implement pipeline creation

The prototypes for handle parsers needed to be changes because it turned
out "single" was inappropriate for handles as "single" allocates memory
for the parsed object, but handles must be written directly.
This commit is contained in:
Bill Currie 2021-01-05 23:42:30 +09:00
parent 0da99bc59c
commit 5eb1afdcb3
10 changed files with 256 additions and 180 deletions

View file

@ -53,6 +53,7 @@ typedef struct vulkan_ctx_s {
VkCommandBuffer cmdbuffer;
VkFence fence; // for ctx->cmdbuffer only
vulkan_renderpass_t renderpass;
VkPipeline pipeline;
size_t curFrame;
vulkan_framebufferset_t framebuffers;

View file

@ -39,80 +39,88 @@
);
};
};
pipelines = {
something = {
stages = (
{ stage = vertex; name = main; module = passthrough; },
{ stage = fragment; name = main; module = pushcolor; },
pipeline = {
stages = (
{ stage = vertex; name = main; module = passthrough; },
{ stage = fragment; name = main; module = pushcolor; },
);
vertexInput = {
bindings = (
{
binding = 0;
stride = "4 * 4";
inputRate = vertex;
},
);
attributes = (
{
location = 0;
binding = 0;
format = r32g32b32a32_sfloat;
offset = 0;
},
);
vertexInput = {
bindings = (
{
binding = 0;
stride = "4 * 4";
inputRate = vertex;
},
);
attributes = (
{
location = 0;
binding = 0;
format = r32g32b32a32_sfloat;
offset = 0;
},
);
};
inputAssembly = {
topology = triangle_list;
primitiveRestartEnable = 0;
};
viewport = {
viewports = (
{
x = 0; y = 0;
width = 640; height = 480;
minDepth = 0; maxDepth = 1000;
}
);
scissors = (
{
offset = { x = 0; y = 0 };
extent = { width = 640; height = 480; };
},
);
};
rasterization = {
depthClampEnable = 1;
rasterizerDiscardEnable = 0;
polygonMode = fill;
cullMode = back;
frontFace = counter_clockwise;
depthBiasEnable = 0;
lineWidth = 1;
};
multisample = {
rasterizationSamples = $msaaSamples;
sampleShadingEnable = 0;
minSampleShading = 0.5;
alphaToCoverageEnable = 0;
alphaToOneEnable = 0;
};
depthStencil = {
depthTestEnable = 1;
depthWriteEnable = 1;
depthCompareOp = less;
depthBoundsTestEnable = 0;
stencilTestEnable = 0;
};
colorBlend = {
logicOpEnable = 0;
};
dymamic = {
dymamicState = ( viewport, scissor );
};
layout = something;
renderPass = renderpass;
};
inputAssembly = {
topology = triangle_list;
primitiveRestartEnable = 0;
};
viewport = {
viewports = (
{
x = 0; y = 0;
width = 640; height = 480;
minDepth = 0; maxDepth = 1;
}
);
scissors = (
{
offset = { x = 0; y = 0 };
extent = { width = 640; height = 480; };
},
);
};
rasterization = {
depthClampEnable = 0;
rasterizerDiscardEnable = 0;
polygonMode = fill;
cullMode = back;
frontFace = counter_clockwise;
depthBiasEnable = 0;
lineWidth = 1;
};
multisample = {
rasterizationSamples = $msaaSamples;
sampleShadingEnable = 0;
minSampleShading = 0.5f;
alphaToCoverageEnable = 0;
alphaToOneEnable = 0;
};
depthStencil = {
depthTestEnable = 1;
depthWriteEnable = 1;
depthCompareOp = less;
depthBoundsTestEnable = 0;
stencilTestEnable = 0;
};
colorBlend = {
logicOpEnable = 0;
attachments = ({
blendEnable = 0;
srcColorBlendFactor = src_color;
dstColorBlendFactor = zero;
colorBlendOp = add;
srcAlphaBlendFactor = src_alpha;
dstAlphaBlendFactor = zero;
alphaBlendOp = add;
colorWriteMask = r|g|b|a;
});
};
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = something;
//renderPass = renderpass;
};
renderpass = {
attachments = (

View file

@ -2,6 +2,7 @@
#include <string.h>
#include "vkfieldcustom.h"
#include "vkfieldtype.h"
#include "vkgen.h"
#include "vktype.h"
@ -15,7 +16,7 @@
}
PLItem *desc = [item getObjectForKey:"type"];
pltype = str_hold ([[desc getObjectAtIndex:1] string]);
pltype = str_hold (parseItemType ([desc getObjectAtIndex:1]));
parser = str_hold ([[desc getObjectAtIndex:2] string]);
fields = [item getObjectForKey:"fields"];

View file

@ -17,4 +17,6 @@
-(string)parseType;
@end
string parseItemType (PLItem *item);
#endif//__renderer_vulkan_vkgen_vkfieldtype_h

View file

@ -5,6 +5,21 @@
#include "vkgen.h"
#include "vktype.h"
string
parseItemType (PLItem *item)
{
string str = [item string];
if (str) {
return str;
}
string mask = "QFMultiType";
for (int i = [item count]; i-- > 0; ) {
str = [[item getObjectAtIndex:i] string];
mask = mask + " | (1 << " + str + ")";
}
return mask;
}
@implementation FieldType
+fieldType:(PLItem *)item
@ -19,21 +34,6 @@
str_free (parse_type);
}
static string
parseItemType (PLItem *item)
{
string str = [item string];
if (str) {
return str;
}
string mask = "QFMultiType";
for (int i = [item count]; i-- > 0; ) {
str = [[item getObjectAtIndex:i] string];
mask = mask + " | (1 << " + str + ")";
}
return str_hold (mask);
}
-initWithItem:(PLItem *)item
{
if (!(self = [super init])) {
@ -47,7 +47,8 @@ parseItemType (PLItem *item)
parse_type = [field_type parseType];
parser = str_hold ("parse_" + type);
} else {
parse_type = parseItemType([item getObjectForKey:"parse_type"]);
PLItem *typeItem = [item getObjectForKey:"parse_type"];
parse_type = str_hold (parseItemType(typeItem));
type = str_hold ([[item getObjectForKey:"type"] string]);
parser = str_hold ([[item getObjectForKey:"parser"] string]);
}

View file

@ -12,10 +12,10 @@ output_handle (string name, PLItem *handle)
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 plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name);
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;\n", name);
fprintf (output_file, "\tvulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;\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");
@ -47,15 +47,18 @@ output_handle (string name, PLItem *handle)
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 (field, item, &handleref->handle, messages, context);\n", custom);
fprintf (output_file, "\treturn %s (item, hrdata, messages, context);\n", custom);
} else {
fprintf (output_file, "\treturn parse_%s (field, item, &handleref->handle, messages, context);\n", name);
fprintf (output_file, "\treturn parse_%s (item, hrdata, messages, context);\n", name);
}
fprintf (output_file, "}\n");
fprintf (header_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name);
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);
str_free (custom);
str_free (symtab);

View file

@ -58,6 +58,7 @@
#include "QF/Vulkan/command.h"
#include "QF/Vulkan/instance.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/pipeline.h"
#include "QF/Vulkan/renderpass.h"
#include "QF/Vulkan/shader.h"
#include "QF/Vulkan/swapchain.h"
@ -159,6 +160,10 @@ parse_basic (const plfield_t *field, const plitem_t *item,
*(uint32_t *) data = VK_SUBPASS_EXTERNAL;
} else {
ret = !cexpr_eval_string (valstr, &ectx);
if (!ret) {
PL_Message (messages, item, "error parsing %s: %s",
field->name, valstr);
}
}
//Sys_Printf (" %x\n", *(uint32_t *)data);
@ -224,8 +229,9 @@ parse_single (const plfield_t *field, const plitem_t *item,
//Sys_Printf ("parse_single: %s %zd %d %p %p\n", field->name, field->offset,
// field->type, field->parser, field->data);
if (PL_Type (item) != single->type) {
PL_Message (messages, item, "error: wrong type");
if (!PL_CheckType (single->type, PL_Type (item))) {
PL_TypeMismatch (messages, item, field->name, single->type,
PL_Type (item));
return 0;
}
@ -309,13 +315,13 @@ parse_string (const plfield_t *field, const plitem_t *item,
__auto_type string = (parse_string_t *) field->data;
__auto_type value = (char **) ((byte *)data + string->value_offset);
const char *str = PL_BinaryData (item);
const char *str = PL_String (item);
Sys_Printf ("parse_string: %s %zd %d %p %p %p\n",
field->name, field->offset, field->type, field->parser,
field->data, data);
Sys_Printf (" %zd\n", string->value_offset);
Sys_Printf (" %s\n", str);
//Sys_Printf ("parse_string: %s %zd %d %p %p %p\n",
// field->name, field->offset, field->type, field->parser,
// field->data, data);
//Sys_Printf (" %zd\n", string->value_offset);
//Sys_Printf (" %s\n", str);
*value = strdup (str);
return 1;
@ -350,11 +356,11 @@ parse_RGBA (const plitem_t *item, void **data,
}
static int
parse_VkShaderModule (const plfield_t *field, const plitem_t *item, void *data,
plitem_t *messages, void *context)
parse_VkShaderModule (const plitem_t *item, void **data,
plitem_t *messages, parsectx_t *context)
{
__auto_type handle = (VkShaderModule *) data;
vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;
__auto_type handle = (VkShaderModule *) data[0];
vulkan_ctx_t *ctx = context->vctx;
const char *name = PL_String (item);
handleref_t *hr = Hash_Find (ctx->shaderModules, name);
@ -367,10 +373,10 @@ parse_VkShaderModule (const plfield_t *field, const plitem_t *item, void *data,
}
static int
parse_VkShaderModule_resource (const plfield_t *field, const plitem_t *item,
void *data, plitem_t *messages, void *context)
parse_VkShaderModule_resource (const plitem_t *item, void **data,
plitem_t *messages, parsectx_t *context)
{
__auto_type handle = (VkShaderModule *) data;
__auto_type handle = (VkShaderModule *) data[0];
vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;
qfv_device_t *device = ctx->device;
@ -382,6 +388,15 @@ parse_VkShaderModule_resource (const plfield_t *field, const plitem_t *item,
return 1;
}
static int
parse_VkDescriptorSetLayout_array (const plfield_t *field,
const plitem_t *item, void *data,
plitem_t *messages, void *context)
{
void *layout[] = { data };
return parse_VkDescriptorSetLayout (item, layout, messages, context);
}
static const char *
handleref_getkey (const void *hr, void *unused)
{
@ -494,57 +509,6 @@ static plfield_t renderpass_fields[] = {
{}
};
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 ();
VkRenderPass renderpass;
exprsym_t var_syms[] = {
{"swapchain", &qfv_swapchain_t_type, ctx->swapchain},
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{}
};
exprtab_t vars_tab = { var_syms, 0 };
exprctx_t exprctx = {};
parsectx_t parsectx = { &exprctx, ctx };
exprctx.external_variables = &vars_tab;
exprctx.memsuper = new_memsuper ();
exprctx.messages = messages;
exprctx.hashlinks = &ctx->hashlinks;
cexpr_init_symtab (&vars_tab, &exprctx);
if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data,
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);
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;
}
void
QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef)
{
@ -609,3 +573,95 @@ QFV_GetEnum (const char *name)
{
return Hash_Find (enum_symtab, name);
}
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 ();
VkRenderPass renderpass;
exprsym_t var_syms[] = {
{"swapchain", &qfv_swapchain_t_type, ctx->swapchain},
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{}
};
exprtab_t vars_tab = { var_syms, 0 };
exprctx_t exprctx = {};
parsectx_t parsectx = { &exprctx, ctx };
exprctx.external_variables = &vars_tab;
exprctx.memsuper = new_memsuper ();
exprctx.messages = messages;
exprctx.hashlinks = &ctx->hashlinks;
cexpr_init_symtab (&vars_tab, &exprctx);
if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data,
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);
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;
}
VkPipeline
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)));
}
return 0;
}
PL_Free (messages);
delete_memsuper (exprctx.memsuper);
cInfo->a[0].renderPass = ctx->renderpass.renderpass;
__auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo);
VkPipeline pipeline = plSet->a[0];
free (plSet);
return pipeline;
}

View file

@ -1,17 +1,17 @@
#ifndef __vkparse_h
#define __vkparse_h
typedef struct parsectx_s {
struct exprctx_s *ectx;
struct vulkan_ctx_s *vctx;
} parsectx_t;
#include "QF/cexpr.h"
#include "QF/Vulkan/renderpass.h"
#ifdef vkparse_internal
#include "libs/video/renderer/vulkan/vkparse.hinc"
#endif
typedef struct parsectx_s {
struct exprctx_s *ectx;
struct vulkan_ctx_s *vctx;
} parsectx_t;
typedef struct parseres_s {
const char *name;
plfield_t *field;
@ -23,9 +23,11 @@ typedef struct handleref_s {
uint64_t handle;
} handleref_t;
VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist);
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);
#endif//__vkparse_h

View file

@ -131,12 +131,8 @@
string = pName;
};
module = {
type = (single, {
parse_type = QFString;
type = VkShaderModule;
parser = parse_VkShaderModule;
});
value = module;
type = (custom, QFString, parse_VkShaderModule);
fields = (module);
};
specializationInfo = {
type = (single, VkSpecializationInfo);
@ -253,7 +249,7 @@
type = (array, {
parse_type = (QFDictionary, QFString);
type = VkDescriptorSetLayout;
parser = parse_VkDescriptorSetLayout;
parser = parse_VkDescriptorSetLayout_array;
});
size = setLayoutCount;
values = pSetLayouts;
@ -312,12 +308,9 @@
value = pDynamicState;
};
layout = {
type = (single, {
parse_type = (QFDictionary, QFString);
type = VkPipelineLayout;
parser = parse_VkPipelineLayout;
});
value = layout;
type = (custom, (QFDictionary, QFString),
parse_VkPipelineLayout);
fields = (layout);
};
basePipelineHandle = {
type = (custom, QFString, parse_BasePipeline);

View file

@ -417,6 +417,15 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
void
Vulkan_CreatePipelines (vulkan_ctx_t *ctx)
{
qfv_load_pipeline (ctx);
plitem_t *item = ctx->pipelineDef;
if (!item || !(item = PL_ObjectForKey (item, "pipeline"))) {
Sys_Printf ("error loading pipeline\n");
} else {
Sys_Printf ("Found pipeline def\n");
}
ctx->pipeline = QFV_ParsePipeline (ctx, item);
}
void