pipeline construction?
[vktest3] / src / vk.c
index 5480fc1..8b12108 100644 (file)
--- a/src/vk.c
+++ b/src/vk.c
@@ -43,9 +43,37 @@ struct framebuf {
        VkFramebuffer vkobj;
 };
 
+struct pipeline {
+       int used;
+       VkViewport vport;
+       VkRect2D scissor;
+       VkShaderModule sdr[VKSDR_MAX];
+       VkPrimitiveTopology prim;
+       VkPolygonMode polymode;
+       float line_width;
+       VkCullModeFlags cull;
+       VkFrontFace     frontface;
+       VkColorComponentFlags colorwr;
+       int zbuf, depthwr;
+       VkCompareOp zop;
+       int stencil, stencilwr;
+       VkStencilOp sfail, szfail, szpass;
+       VkCompareOp sop;
+       unsigned int sref, smask;
+       int blend;
+       VkBlendFactor srcblend, dstblend, srcblend_a, dstblend_a;
+
+       VkRenderPass rpass;
+
+       int vkobj_valid;
+       VkPipeline vkobj;
+       VkPipelineLayout vkobj_layout;  /* TODO probably best to split this */
+};
+
 
 static struct rpass *rpasses;
 static struct framebuf *framebufs;
+static struct pipeline *pipelines;
 
 
 static int create_instance(void);
@@ -565,6 +593,344 @@ VkFramebuffer vk_fb(int fb)
 }
 
 
+int vk_create_pipeln(void)
+{
+       int i;
+       struct pipeline pipeln = {0}, *pp = &pipeln;
+
+       if(!pipelines) {
+               pipelines = darr_alloc(0, sizeof *pipelines);
+               darr_push(pipelines, &pipeln);  /* add dummy pipeline */
+       }
+
+       for(i=1; i<darr_size(pipelines); i++) {
+               if(!pipelines[i].used) {
+                       pp = pipelines + i;
+               }
+       }
+
+       /* init pipeline defaults */
+       memset(pp, 0, sizeof *pp);
+       pp->used = 1;
+       pp->vport.width = pp->scissor.extent.width = 640;
+       pp->vport.height = pp->scissor.extent.height = 480;
+       pp->vport.minDepth = 0.0f;
+       pp->vport.maxDepth = 1.0f;
+       pp->prim = VKPRIM_TRIANGLES;
+       pp->polymode = VK_POLYGON_MODE_FILL;
+       pp->cull = VK_CULL_MODE_BACK_BIT;
+       pp->frontface = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+       pp->line_width = 1.0f;
+       pp->colorwr = 0xf;      /* RGBA */
+       pp->zbuf = 1;
+       pp->zop = VK_COMPARE_OP_LESS;
+       pp->depthwr = 1;
+       pp->stencil = 0;
+       pp->stencilwr = 1;
+       pp->sop = VK_COMPARE_OP_ALWAYS;
+       pp->smask = 0xffffffff;
+       pp->blend = 0;
+       pp->srcblend = pp->srcblend_a = VK_BLEND_FACTOR_ONE;
+       pp->dstblend = pp->dstblend_a = VK_BLEND_FACTOR_ZERO;
+
+       if(pp == &pipeln) {
+               darr_push(pipelines, pp);
+               return darr_size(pipelines) - 1;
+       }
+       return pp - pipelines;
+}
+
+void vk_free_pipeln(int pp)
+{
+       if(!pipelines || pp < 1 || pp >= darr_size(pipelines)) {
+               return;
+       }
+
+       if(pipelines[pp].used && pipelines[pp].vkobj) {
+               vkDestroyPipeline(vkdev, pipelines[pp].vkobj, 0);
+       }
+       pipelines[pp].used = 0;
+}
+
+void vk_pipeln_rpass(int pp, VkRenderPass rp)
+{
+       struct pipeline *p = pipelines + pp;
+       p->rpass = rp;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_viewport(int pp, int x, int y, int width, int height)
+{
+       struct pipeline *p = pipelines + pp;
+       p->vport.x = x;
+       p->vport.y = y;
+       p->vport.width = width;
+       p->vport.height = height;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_scissor(int pp, int x, int y, int width, int height)
+{
+       struct pipeline *p = pipelines + pp;
+       p->scissor.offset.x = x;
+       p->scissor.offset.y = y;
+       p->scissor.extent.width = width;
+       p->scissor.extent.height = height;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_shader(int pp, int type, VkShaderModule sdr)
+{
+       struct pipeline *p = pipelines + pp;
+       p->sdr[type] = sdr;
+       p->vkobj_valid = 0;
+}
+
+/* TODO: vertex input */
+void vk_pipeln_prim(int pp, int prim)
+{
+       struct pipeline *p = pipelines + pp;
+       p->prim = prim;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_polymode(int pp, int mode)
+{
+       struct pipeline *p = pipelines + pp;
+       p->polymode = mode;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_cull(int pp, int cull)
+{
+       struct pipeline *p = pipelines + pp;
+       p->cull = cull;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_frontface(int pp, int ff)
+{
+       struct pipeline *p = pipelines + pp;
+       p->frontface = ff;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_linewidth(int pp, int w)
+{
+       struct pipeline *p = pipelines + pp;
+       p->line_width = w;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_multisample(int pp, int nsamples)
+{
+       /* TODO */
+}
+
+void vk_pipeln_colormask(int pp, int r, int g, int b, int a)
+{
+       struct pipeline *p = pipelines + pp;
+       p->colorwr = 0;
+       if(r) p->colorwr |= VK_COLOR_COMPONENT_R_BIT;
+       if(g) p->colorwr |= VK_COLOR_COMPONENT_G_BIT;
+       if(b) p->colorwr |= VK_COLOR_COMPONENT_B_BIT;
+       if(a) p->colorwr |= VK_COLOR_COMPONENT_A_BIT;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_depthmask(int pp, int z)
+{
+       struct pipeline *p = pipelines + pp;
+       p->depthwr = z;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_stencilmask(int pp, int s)
+{
+       struct pipeline *p = pipelines + pp;
+       p->stencilwr = s;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_zbuffer(int pp, int enable)
+{
+       struct pipeline *p = pipelines + pp;
+       p->zbuf = enable;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_zbuffer_op(int pp, int op)
+{
+       struct pipeline *p = pipelines + pp;
+       p->zop = op;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_stencil(int pp, int enable)
+{
+       struct pipeline *p = pipelines + pp;
+       p->stencil = enable;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_stencil_op(int pp, int sfail, int zfail, int zpass)
+{
+       struct pipeline *p = pipelines + pp;
+       p->sfail = sfail;
+       p->szfail = zfail;
+       p->szpass = zpass;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_stencil_func(int pp, int op, unsigned int ref, unsigned int mask)
+{
+       struct pipeline *p = pipelines + pp;
+       p->sop = op;
+       p->sref = ref;
+       p->smask = mask;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_blend(int pp, int enable)
+{
+       struct pipeline *p = pipelines + pp;
+       p->blend = enable;
+       p->vkobj_valid = 0;
+}
+
+void vk_pipeln_blendfunc(int pp, int src, int dst)
+{
+       struct pipeline *p = pipelines + pp;
+       p->srcblend = src;
+       p->dstblend = dst;
+       p->vkobj_valid = 0;
+}
+
+VkPipeline vk_pipeln(int pp)
+{
+       int i, idx, num_sdr;
+       struct pipeline *p = pipelines + pp;
+       VkPipelineShaderStageCreateInfo ssinf[VKSDR_MAX];
+       VkPipelineVertexInputStateCreateInfo vinp;
+       VkPipelineInputAssemblyStateCreateInfo vasm;
+       VkPipelineViewportStateCreateInfo vp;
+       VkPipelineRasterizationStateCreateInfo rast;
+       VkPipelineMultisampleStateCreateInfo msaa;
+       VkPipelineDepthStencilStateCreateInfo zst;
+       VkPipelineColorBlendAttachmentState bat;
+       VkPipelineColorBlendStateCreateInfo blend;
+       VkPipelineLayoutCreateInfo lay;
+       VkGraphicsPipelineCreateInfo pinf;
+
+
+       if(p->vkobj_valid) {
+               return p->vkobj;
+       }
+
+       if(p->vkobj) {
+               vkDestroyPipeline(vkdev, p->vkobj, 0);
+               p->vkobj = 0;
+       }
+
+       memset(ssinf, 0, sizeof ssinf);
+       idx = 0;
+       for(i=0; i<VKSDR_MAX; i++) {
+               if(p->sdr[idx]) {
+                       ssinf[idx].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+                       ssinf[idx].stage = VKSDR_STAGE(i);
+                       ssinf[idx].module = p->sdr[idx];
+                       ssinf[idx].pName = "main";
+                       idx++;
+               }
+       }
+       num_sdr = idx;
+
+       memset(&vinp, 0, sizeof vinp);
+       vinp.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+
+       memset(&vasm, 0, sizeof vasm);
+       vasm.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+       vasm.topology = p->prim;
+
+       memset(&vp, 0, sizeof vp);
+       vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+       vp.viewportCount = 1;
+       vp.pViewports = &p->vport;
+       vp.scissorCount = 1;
+       vp.pScissors = &p->scissor;
+
+       memset(&rast, 0, sizeof rast);
+       rast.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+       rast.polygonMode = p->polymode;
+       rast.lineWidth = p->line_width;
+       rast.cullMode = p->cull;
+       rast.frontFace = p->frontface;
+
+       /* TODO */
+       memset(&msaa, 0, sizeof msaa);
+       msaa.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+       msaa.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+       msaa.minSampleShading = 1.0f;
+
+       memset(&zst, 0, sizeof zst);
+       zst.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+       zst.depthTestEnable = p->zbuf;
+       zst.depthWriteEnable = p->depthwr;
+       zst.depthCompareOp = p->zop;
+       zst.stencilTestEnable = p->stencil;
+       zst.front.writeMask = p->stencilwr;
+       zst.front.failOp = p->sfail;
+       zst.front.passOp = p->szpass;
+       zst.front.depthFailOp = p->szfail;
+       zst.front.compareOp = p->sop;
+       zst.front.compareMask = p->smask;
+       zst.front.reference = p->sref;
+       zst.back = zst.front;
+
+       memset(&bat, 0, sizeof bat);
+       bat.colorWriteMask = p->colorwr;
+       bat.blendEnable = p->blend;
+       bat.srcColorBlendFactor = p->srcblend;
+       bat.dstColorBlendFactor = p->dstblend;
+       bat.colorBlendOp = VK_BLEND_OP_ADD;     /* TODO */
+       bat.srcAlphaBlendFactor = p->srcblend_a;
+       bat.dstAlphaBlendFactor = p->dstblend_a;
+
+       memset(&blend, 0, sizeof blend);
+       blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+       blend.attachmentCount = 1;
+       blend.pAttachments = &bat;
+
+       /* TODO */
+       memset(&lay, 0, sizeof lay);
+       lay.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+       if(vkCreatePipelineLayout(vkdev, &lay, 0, &p->vkobj_layout) != 0) {
+               return 0;
+       }
+
+       memset(&pinf, 0, sizeof pinf);
+       pinf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+       pinf.stageCount = num_sdr;
+       pinf.pStages = ssinf;
+       pinf.pVertexInputState = &vinp;
+       pinf.pInputAssemblyState = &vasm;
+       pinf.pViewportState = &vp;
+       pinf.pRasterizationState = &rast;
+       pinf.pDepthStencilState = &zst;
+       pinf.pMultisampleState = &msaa;
+       pinf.pColorBlendState = &blend;
+       pinf.layout = p->vkobj_layout;
+       pinf.renderPass = p->rpass;
+       pinf.basePipelineIndex = -1;
+
+       if(vkCreateGraphicsPipelines(vkdev, 0, 1, &pinf, 0, &p->vkobj) != 0) {
+               return 0;
+       }
+       p->vkobj_valid = 1;
+       return p->vkobj;
+}
+
+
 #define ARRSZ(arr)     (sizeof arr / sizeof *arr)
 static const char *known_layer_list[] = {
        "VK_LAYER_GOOGLE_threading",