mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-18 09:51:40 +00:00
[vulkan] Implement pipeline layout creation
It seems to work when parsing the layouts. They can be created in-line (in theory) or in a "setLayouts" node and then referenced by name.
This commit is contained in:
parent
e4f75791ce
commit
d919a85c8e
6 changed files with 302 additions and 1 deletions
|
@ -45,6 +45,7 @@ typedef struct vulkan_ctx_s {
|
||||||
struct hashlink_s *hashlinks; //FIXME want per thread
|
struct hashlink_s *hashlinks; //FIXME want per thread
|
||||||
VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain
|
VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain
|
||||||
struct hashtab_s *shadermodules;
|
struct hashtab_s *shadermodules;
|
||||||
|
struct hashtab_s *setLayouts;
|
||||||
struct shadermodule_s *shadermodule_freelist;
|
struct shadermodule_s *shadermodule_freelist;
|
||||||
|
|
||||||
VkCommandPool cmdpool;
|
VkCommandPool cmdpool;
|
||||||
|
|
|
@ -14,6 +14,37 @@
|
||||||
file = $builtin/pushcolor.frag;
|
file = $builtin/pushcolor.frag;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
setLayouts = {
|
||||||
|
something = {
|
||||||
|
flags = 0;
|
||||||
|
bindings = (
|
||||||
|
{
|
||||||
|
binding = 0;
|
||||||
|
descriptorType = sampled_image;
|
||||||
|
descriptorCount = 1;
|
||||||
|
stageFlags = fragment;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
binding = 1;
|
||||||
|
descriptorType = uniform_buffer;
|
||||||
|
descriptorCount = 1;
|
||||||
|
stageFlags = vertex;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
pipelineLayouts = {
|
||||||
|
something = {
|
||||||
|
setLayouts = (something);
|
||||||
|
pushConstantRanges = (
|
||||||
|
{
|
||||||
|
stageFlags = fragment;
|
||||||
|
offset = 0;
|
||||||
|
size = "4 * 4";
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
renderpass = {
|
renderpass = {
|
||||||
attachments = (
|
attachments = (
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "QF/vid.h"
|
#include "QF/vid.h"
|
||||||
#include "QF/simd/vec4f.h"
|
#include "QF/simd/vec4f.h"
|
||||||
#include "QF/Vulkan/qf_vid.h"
|
#include "QF/Vulkan/qf_vid.h"
|
||||||
|
#include "QF/Vulkan/descriptor.h"
|
||||||
#include "QF/Vulkan/device.h"
|
#include "QF/Vulkan/device.h"
|
||||||
#include "QF/Vulkan/command.h"
|
#include "QF/Vulkan/command.h"
|
||||||
#include "QF/Vulkan/instance.h"
|
#include "QF/Vulkan/instance.h"
|
||||||
|
@ -329,6 +330,21 @@ parse_custom (const plfield_t *field, const plitem_t *item,
|
||||||
return custom->parse (item, offsets, messages, context);
|
return custom->parse (item, offsets, messages, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.symtab = 0;
|
||||||
|
ectx.result = &result;
|
||||||
|
const char *valstr = PL_String (item);
|
||||||
|
Sys_Printf ("parse_RGBA: %s\n", valstr);
|
||||||
|
ret = !cexpr_eval_string (valstr, &ectx);
|
||||||
|
Sys_Printf (" "VEC4F_FMT"\n", VEC4_EXP (*(vec4f_t *)data[0]));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_VkShaderModule (const plitem_t *item, void **data,
|
parse_VkShaderModule (const plitem_t *item, void **data,
|
||||||
|
@ -344,6 +360,79 @@ parse_VkShaderModule (const plitem_t *item, void **data,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct setlayout_s {
|
||||||
|
char *name;
|
||||||
|
VkDescriptorSetLayout layout;
|
||||||
|
} setlayout_t;
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
setLayout_getkey (const void *sl, void *unused)
|
||||||
|
{
|
||||||
|
return ((setlayout_t *)sl)->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setLayout_free (void *sl, void *_ctx)
|
||||||
|
{
|
||||||
|
__auto_type setLayout = (setlayout_t *) sl;
|
||||||
|
__auto_type ctx = (vulkan_ctx_t *) _ctx;
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
|
|
||||||
|
dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout->layout, 0);
|
||||||
|
free (setLayout->name);
|
||||||
|
free (setLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item,
|
||||||
|
void *data, plitem_t *messages, void *context)
|
||||||
|
{
|
||||||
|
__auto_type layout = (setlayout_t *) data;
|
||||||
|
vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
|
|
||||||
|
if (PL_Type (item) == QFString) {
|
||||||
|
// accessing a named set layout
|
||||||
|
const char *name = PL_String (item);
|
||||||
|
setlayout_t *l = Hash_Find (ctx->setLayouts, name);
|
||||||
|
if (!l) {
|
||||||
|
PL_Message (messages, item, "undefined set layout %s", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*layout = *l;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayoutCreateInfo createInfo = {};
|
||||||
|
|
||||||
|
if (!parse_VkDescriptorSetLayoutCreateInfo (0, item, &createInfo,
|
||||||
|
messages, context)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
layout->name = strdup (field->name);
|
||||||
|
VkResult res;
|
||||||
|
res = dfunc->vkCreateDescriptorSetLayout (device->dev, &createInfo, 0,
|
||||||
|
&layout->layout);
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
PL_Message (messages, item, "could not create set layout");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plelement_t setLayout_data = {
|
||||||
|
QFDictionary,
|
||||||
|
sizeof (setlayout_t),
|
||||||
|
malloc,
|
||||||
|
parse_VkDescriptorSetLayout,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static plfield_t setLayout_field = { 0, 0, QFDictionary, 0, &setLayout_data };
|
||||||
|
|
||||||
static hashtab_t *enum_symtab;
|
static hashtab_t *enum_symtab;
|
||||||
|
|
||||||
#include "libs/video/renderer/vulkan/vkparse.cinc"
|
#include "libs/video/renderer/vulkan/vkparse.cinc"
|
||||||
|
@ -440,6 +529,33 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist)
|
||||||
return renderpass;
|
return renderpass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets)
|
||||||
|
{
|
||||||
|
plitem_t *messages = PL_NewArray ();
|
||||||
|
exprctx_t exprctx = {};
|
||||||
|
parsectx_t parsectx = { &exprctx, ctx };
|
||||||
|
|
||||||
|
exprctx.memsuper = new_memsuper ();
|
||||||
|
exprctx.messages = messages;
|
||||||
|
exprctx.hashlinks = ctx->hashlinks;
|
||||||
|
|
||||||
|
if (!ctx->setLayouts) {
|
||||||
|
ctx->setLayouts = Hash_NewTable (23, setLayout_getkey, setLayout_free,
|
||||||
|
ctx, &exprctx.hashlinks);
|
||||||
|
}
|
||||||
|
int res = PL_ParseSymtab (&setLayout_field, sets, ctx->setLayouts,
|
||||||
|
messages, &parsectx);
|
||||||
|
if (!res || 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);
|
||||||
|
ctx->hashlinks = exprctx.hashlinks;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
enum_symtab_getkey (const void *e, void *unused)
|
enum_symtab_getkey (const void *e, void *unused)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,8 @@ typedef struct parsectx_s {
|
||||||
struct vulkan_ctx_s *vctx;
|
struct vulkan_ctx_s *vctx;
|
||||||
} parsectx_t;
|
} parsectx_t;
|
||||||
|
|
||||||
|
|
||||||
|
void QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets);
|
||||||
VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist);
|
VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist);
|
||||||
void QFV_InitParse (void);
|
void QFV_InitParse (void);
|
||||||
exprenum_t *QFV_GetEnum (const char *name);
|
exprenum_t *QFV_GetEnum (const char *name);
|
||||||
|
|
|
@ -5,6 +5,18 @@
|
||||||
VkSubpassDependency,
|
VkSubpassDependency,
|
||||||
VkSpecializationInfo,
|
VkSpecializationInfo,
|
||||||
VkPipelineShaderStageCreateInfo,
|
VkPipelineShaderStageCreateInfo,
|
||||||
|
VkPipelineVertexInputStateCreateInfo,
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo,
|
||||||
|
VkPipelineViewportStateCreateInfo,
|
||||||
|
VkPipelineRasterizationStateCreateInfo,
|
||||||
|
VkPipelineMultisampleStateCreateInfo,
|
||||||
|
VkPipelineDepthStencilStateCreateInfo,
|
||||||
|
VkPipelineColorBlendStateCreateInfo,
|
||||||
|
VkPipelineDynamicStateCreateInfo,
|
||||||
|
VkDescriptorSetLayoutBinding,
|
||||||
|
VkDescriptorSetLayoutCreateInfo,
|
||||||
|
VkPushConstantRange,
|
||||||
|
VkPipelineLayoutCreateInfo,
|
||||||
qfv_swapchain_t,
|
qfv_swapchain_t,
|
||||||
);
|
);
|
||||||
parse = {
|
parse = {
|
||||||
|
@ -69,5 +81,125 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
VkShaderModuleCreateInfo = skip;
|
VkShaderModuleCreateInfo = skip;
|
||||||
|
VkDescriptorSetLayoutBinding = {
|
||||||
|
binding = auto;
|
||||||
|
descriptorType = auto;
|
||||||
|
descriptorCount = auto;
|
||||||
|
stageFlags = auto;
|
||||||
|
// skip pImmutableSamplers (default to 0) until I know how it works
|
||||||
|
};
|
||||||
|
VkDescriptorSetLayoutCreateInfo = {
|
||||||
|
flags = auto;
|
||||||
|
bindings = {
|
||||||
|
type = (array, VkDescriptorSetLayoutBinding);
|
||||||
|
size = bindingCount;
|
||||||
|
values = pBindings;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VkPipelineVertexInputStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
bindings = {
|
||||||
|
type = (array, VkVertexInputBindingDescription);
|
||||||
|
size = vertexBindingDescriptionCount;
|
||||||
|
values = pVertexBindingDescriptions;
|
||||||
|
};
|
||||||
|
attributes = {
|
||||||
|
type = (array, VkVertexInputAttributeDescription);
|
||||||
|
size = vertexAttributeDescriptionCount;
|
||||||
|
values = pVertexAttributeDescriptions;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
topology = auto;
|
||||||
|
primitiveRestartEnable = auto;
|
||||||
|
};
|
||||||
|
VkPipelineViewportStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
//FIXME redo as one array
|
||||||
|
viewports = {
|
||||||
|
type = (array, VkViewport);
|
||||||
|
size = viewportCount;
|
||||||
|
values = pViewports;
|
||||||
|
};
|
||||||
|
scissors = {
|
||||||
|
type = (array, VkRect2D);
|
||||||
|
size = scissorCount;
|
||||||
|
values = pScissors;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VkPipelineRasterizationStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
depthClampEnable = auto;
|
||||||
|
rasterizerDiscardEnable = auto;
|
||||||
|
polygonMode = auto;
|
||||||
|
cullMode = auto;
|
||||||
|
frontFace = auto;
|
||||||
|
depthBiasEnable = auto;
|
||||||
|
depthBiasConstantFactor = auto;
|
||||||
|
depthBiasClamp = auto;
|
||||||
|
depthBiasSlopeFactor = auto;
|
||||||
|
lineWidth = auto;
|
||||||
|
};
|
||||||
|
VkPipelineMultisampleStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
rasterizationSamples = auto;
|
||||||
|
sampleShadingEnable = auto;
|
||||||
|
minSampleShading = auto;
|
||||||
|
//pSampleMask = auto; FIXME disabled until correct size is known
|
||||||
|
alphaToCoverageEnable = auto;
|
||||||
|
alphaToOneEnable = auto;
|
||||||
|
};
|
||||||
|
VkPipelineDepthStencilStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
depthTestEnable = auto;
|
||||||
|
depthWriteEnable = auto;
|
||||||
|
depthCompareOp = auto;
|
||||||
|
depthBoundsTestEnable = auto;
|
||||||
|
stencilTestEnable = auto;
|
||||||
|
front = auto;
|
||||||
|
back = auto;
|
||||||
|
minDepthBounds = auto;
|
||||||
|
maxDepthBounds = auto;
|
||||||
|
};
|
||||||
|
VkPipelineColorBlendStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
logicOpEnable = auto;
|
||||||
|
logicOp = auto;
|
||||||
|
attachments = {
|
||||||
|
type = (array, VkPipelineColorBlendAttachmentState);
|
||||||
|
size = attachmentCount;
|
||||||
|
values = pAttachments;
|
||||||
|
};
|
||||||
|
blendConstants = {
|
||||||
|
type = (custom, QFString, parse_RGBA);
|
||||||
|
fields = (blendConstants);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VkPipelineDynamicStateCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
dynamicState = {
|
||||||
|
type = (array, VkDynamicState);
|
||||||
|
size = dynamicStateCount;
|
||||||
|
values = pDynamicStates;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
VkPipelineLayoutCreateInfo = {
|
||||||
|
//flags = auto; reserved for future use (Bits enum does not exist)
|
||||||
|
setLayouts = {
|
||||||
|
type = (array, {
|
||||||
|
parse_type = (QFDictionary, QFString);
|
||||||
|
type = VkDescriptorSetLayout;
|
||||||
|
parser = parse_VkDescriptorSetLayout;
|
||||||
|
});
|
||||||
|
size = setLayoutCount;
|
||||||
|
values = pSetLayouts;
|
||||||
|
};
|
||||||
|
pushConstantRanges = {
|
||||||
|
type = (array, VkPushConstantRange);
|
||||||
|
size = pushConstantRangeCount;
|
||||||
|
values = pPushConstantRanges;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "QF/va.h"
|
#include "QF/va.h"
|
||||||
#include "QF/vid.h"
|
#include "QF/vid.h"
|
||||||
#include "QF/Vulkan/qf_vid.h"
|
#include "QF/Vulkan/qf_vid.h"
|
||||||
|
#include "QF/Vulkan/descriptor.h"
|
||||||
#include "QF/Vulkan/device.h"
|
#include "QF/Vulkan/device.h"
|
||||||
#include "QF/Vulkan/command.h"
|
#include "QF/Vulkan/command.h"
|
||||||
#include "QF/Vulkan/instance.h"
|
#include "QF/Vulkan/instance.h"
|
||||||
|
@ -401,8 +402,10 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
|
||||||
void
|
void
|
||||||
Vulkan_CreatePipelines (vulkan_ctx_t *ctx)
|
Vulkan_CreatePipelines (vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
plitem_t *item = qfv_load_pipeline ();
|
plitem_t *pipeline_def = qfv_load_pipeline ();
|
||||||
|
plitem_t *item;
|
||||||
|
|
||||||
|
item = pipeline_def;
|
||||||
if (!item || !(item = PL_ObjectForKey (item, "modules"))) {
|
if (!item || !(item = PL_ObjectForKey (item, "modules"))) {
|
||||||
Sys_Printf ("error loading modules\n");
|
Sys_Printf ("error loading modules\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -424,6 +427,22 @@ Vulkan_CreatePipelines (vulkan_ctx_t *ctx)
|
||||||
QFV_RegisterShaderModule (ctx, name, module);
|
QFV_RegisterShaderModule (ctx, name, module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item = pipeline_def;
|
||||||
|
if (!item || !(item = PL_ObjectForKey (item, "setLayouts"))) {
|
||||||
|
Sys_Printf ("error loading setLayouts\n");
|
||||||
|
} else {
|
||||||
|
Sys_Printf ("Found setLayouts\n");
|
||||||
|
QFV_ParseDescriptorSetLayouts (ctx, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*item = pipeline_def;
|
||||||
|
if (!item || !(item = PL_ObjectForKey (item, "pipelineLayouts"))) {
|
||||||
|
Sys_Printf ("error loading pipelineLayouts\n");
|
||||||
|
} else {
|
||||||
|
Sys_Printf ("Found pipelineLayouts\n");
|
||||||
|
QFV_ParsePipelineLayouts (ctx, item);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue