17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2018 Collabora Ltd.
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg#include "compiler/spirv/spirv.h"
257ec681f3Smrg
267ec681f3Smrg#include "zink_pipeline.h"
277ec681f3Smrg
287ec681f3Smrg#include "zink_compiler.h"
297ec681f3Smrg#include "zink_context.h"
307ec681f3Smrg#include "zink_program.h"
317ec681f3Smrg#include "zink_render_pass.h"
327ec681f3Smrg#include "zink_screen.h"
337ec681f3Smrg#include "zink_state.h"
347ec681f3Smrg
357ec681f3Smrg#include "util/u_debug.h"
367ec681f3Smrg#include "util/u_prim.h"
377ec681f3Smrg
387ec681f3Smrgstatic VkBlendFactor
397ec681f3Smrgclamp_void_blend_factor(VkBlendFactor f)
407ec681f3Smrg{
417ec681f3Smrg   if (f == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA)
427ec681f3Smrg      return VK_BLEND_FACTOR_ZERO;
437ec681f3Smrg   if (f == VK_BLEND_FACTOR_DST_ALPHA)
447ec681f3Smrg      return VK_BLEND_FACTOR_ONE;
457ec681f3Smrg   return f;
467ec681f3Smrg}
477ec681f3Smrg
487ec681f3SmrgVkPipeline
497ec681f3Smrgzink_create_gfx_pipeline(struct zink_screen *screen,
507ec681f3Smrg                         struct zink_gfx_program *prog,
517ec681f3Smrg                         struct zink_gfx_pipeline_state *state,
527ec681f3Smrg                         VkPrimitiveTopology primitive_topology)
537ec681f3Smrg{
547ec681f3Smrg   struct zink_rasterizer_hw_state *hw_rast_state = (void*)state;
557ec681f3Smrg   VkPipelineVertexInputStateCreateInfo vertex_input_state;
567ec681f3Smrg   if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs) {
577ec681f3Smrg      memset(&vertex_input_state, 0, sizeof(vertex_input_state));
587ec681f3Smrg      vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
597ec681f3Smrg      vertex_input_state.pVertexBindingDescriptions = state->element_state->b.bindings;
607ec681f3Smrg      vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings;
617ec681f3Smrg      vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs;
627ec681f3Smrg      vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs;
637ec681f3Smrg   }
647ec681f3Smrg
657ec681f3Smrg   VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state;
667ec681f3Smrg   if (!screen->info.have_EXT_vertex_input_dynamic_state && state->element_state->b.divisors_present) {
677ec681f3Smrg       memset(&vdiv_state, 0, sizeof(vdiv_state));
687ec681f3Smrg       vertex_input_state.pNext = &vdiv_state;
697ec681f3Smrg       vdiv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
707ec681f3Smrg       vdiv_state.vertexBindingDivisorCount = state->element_state->b.divisors_present;
717ec681f3Smrg       vdiv_state.pVertexBindingDivisors = state->element_state->b.divisors;
727ec681f3Smrg   }
737ec681f3Smrg
747ec681f3Smrg   VkPipelineInputAssemblyStateCreateInfo primitive_state = {0};
757ec681f3Smrg   primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
767ec681f3Smrg   primitive_state.topology = primitive_topology;
777ec681f3Smrg   if (!screen->info.have_EXT_extended_dynamic_state2) {
787ec681f3Smrg      switch (primitive_topology) {
797ec681f3Smrg      case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
807ec681f3Smrg      case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
817ec681f3Smrg      case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
827ec681f3Smrg      case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
837ec681f3Smrg      case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
847ec681f3Smrg      case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
857ec681f3Smrg         if (state->primitive_restart)
867ec681f3Smrg            debug_printf("restart_index set with unsupported primitive topology %u\n", primitive_topology);
877ec681f3Smrg         primitive_state.primitiveRestartEnable = VK_FALSE;
887ec681f3Smrg         break;
897ec681f3Smrg      default:
907ec681f3Smrg         primitive_state.primitiveRestartEnable = state->primitive_restart ? VK_TRUE : VK_FALSE;
917ec681f3Smrg      }
927ec681f3Smrg   }
937ec681f3Smrg
947ec681f3Smrg   VkPipelineColorBlendAttachmentState blend_att[PIPE_MAX_COLOR_BUFS];
957ec681f3Smrg   VkPipelineColorBlendStateCreateInfo blend_state = {0};
967ec681f3Smrg   blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
977ec681f3Smrg   if (state->blend_state) {
987ec681f3Smrg      unsigned num_attachments = state->render_pass->state.num_rts;
997ec681f3Smrg      if (state->render_pass->state.have_zsbuf)
1007ec681f3Smrg         num_attachments--;
1017ec681f3Smrg      if (state->void_alpha_attachments) {
1027ec681f3Smrg         for (unsigned i = 0; i < num_attachments; i++) {
1037ec681f3Smrg            blend_att[i] = state->blend_state->attachments[i];
1047ec681f3Smrg            if (state->void_alpha_attachments & BITFIELD_BIT(i)) {
1057ec681f3Smrg               blend_att[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
1067ec681f3Smrg               blend_att[i].srcColorBlendFactor = clamp_void_blend_factor(blend_att[i].srcColorBlendFactor);
1077ec681f3Smrg               blend_att[i].dstColorBlendFactor = clamp_void_blend_factor(blend_att[i].dstColorBlendFactor);
1087ec681f3Smrg            }
1097ec681f3Smrg         }
1107ec681f3Smrg         blend_state.pAttachments = blend_att;
1117ec681f3Smrg      } else
1127ec681f3Smrg         blend_state.pAttachments = state->blend_state->attachments;
1137ec681f3Smrg      blend_state.attachmentCount = num_attachments;
1147ec681f3Smrg      blend_state.logicOpEnable = state->blend_state->logicop_enable;
1157ec681f3Smrg      blend_state.logicOp = state->blend_state->logicop_func;
1167ec681f3Smrg   }
1177ec681f3Smrg
1187ec681f3Smrg   VkPipelineMultisampleStateCreateInfo ms_state = {0};
1197ec681f3Smrg   ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1207ec681f3Smrg   ms_state.rasterizationSamples = state->rast_samples + 1;
1217ec681f3Smrg   if (state->blend_state) {
1227ec681f3Smrg      ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
1237ec681f3Smrg      if (state->blend_state->alpha_to_one && !screen->info.feats.features.alphaToOne)
1247ec681f3Smrg         warn_missing_feature("alphaToOne");
1257ec681f3Smrg      ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
1267ec681f3Smrg   }
1277ec681f3Smrg   /* "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
1287ec681f3Smrg    * - Chapter 27. Rasterization
1297ec681f3Smrg    *
1307ec681f3Smrg    * thus it never makes sense to leave this as NULL since gallium will provide correct
1317ec681f3Smrg    * data here as long as sample_mask is initialized on context creation
1327ec681f3Smrg    */
1337ec681f3Smrg   ms_state.pSampleMask = &state->sample_mask;
1347ec681f3Smrg   if (hw_rast_state->force_persample_interp) {
1357ec681f3Smrg      ms_state.sampleShadingEnable = VK_TRUE;
1367ec681f3Smrg      ms_state.minSampleShading = 1.0;
1377ec681f3Smrg   }
1387ec681f3Smrg
1397ec681f3Smrg   VkPipelineViewportStateCreateInfo viewport_state = {0};
1407ec681f3Smrg   viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1417ec681f3Smrg   viewport_state.viewportCount = screen->info.have_EXT_extended_dynamic_state ? 0 : state->dyn_state1.num_viewports;
1427ec681f3Smrg   viewport_state.pViewports = NULL;
1437ec681f3Smrg   viewport_state.scissorCount = screen->info.have_EXT_extended_dynamic_state ? 0 : state->dyn_state1.num_viewports;
1447ec681f3Smrg   viewport_state.pScissors = NULL;
1457ec681f3Smrg
1467ec681f3Smrg   VkPipelineRasterizationStateCreateInfo rast_state = {0};
1477ec681f3Smrg   rast_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1487ec681f3Smrg
1497ec681f3Smrg   rast_state.depthClampEnable = hw_rast_state->depth_clamp;
1507ec681f3Smrg   rast_state.rasterizerDiscardEnable = hw_rast_state->rasterizer_discard;
1517ec681f3Smrg   rast_state.polygonMode = hw_rast_state->polygon_mode;
1527ec681f3Smrg   rast_state.cullMode = hw_rast_state->cull_mode;
1537ec681f3Smrg   rast_state.frontFace = state->dyn_state1.front_face;
1547ec681f3Smrg
1557ec681f3Smrg   rast_state.depthBiasEnable = VK_TRUE;
1567ec681f3Smrg   rast_state.depthBiasConstantFactor = 0.0;
1577ec681f3Smrg   rast_state.depthBiasClamp = 0.0;
1587ec681f3Smrg   rast_state.depthBiasSlopeFactor = 0.0;
1597ec681f3Smrg   rast_state.lineWidth = 1.0f;
1607ec681f3Smrg
1617ec681f3Smrg   VkPipelineRasterizationProvokingVertexStateCreateInfoEXT pv_state;
1627ec681f3Smrg   pv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
1637ec681f3Smrg   pv_state.provokingVertexMode = hw_rast_state->pv_last ?
1647ec681f3Smrg                                  VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
1657ec681f3Smrg                                  VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
1667ec681f3Smrg   if (screen->info.have_EXT_provoking_vertex && hw_rast_state->pv_last) {
1677ec681f3Smrg      pv_state.pNext = rast_state.pNext;
1687ec681f3Smrg      rast_state.pNext = &pv_state;
1697ec681f3Smrg   }
1707ec681f3Smrg
1717ec681f3Smrg   VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {0};
1727ec681f3Smrg   depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1737ec681f3Smrg   depth_stencil_state.depthTestEnable = state->dyn_state1.depth_stencil_alpha_state->depth_test;
1747ec681f3Smrg   depth_stencil_state.depthCompareOp = state->dyn_state1.depth_stencil_alpha_state->depth_compare_op;
1757ec681f3Smrg   depth_stencil_state.depthBoundsTestEnable = state->dyn_state1.depth_stencil_alpha_state->depth_bounds_test;
1767ec681f3Smrg   depth_stencil_state.minDepthBounds = state->dyn_state1.depth_stencil_alpha_state->min_depth_bounds;
1777ec681f3Smrg   depth_stencil_state.maxDepthBounds = state->dyn_state1.depth_stencil_alpha_state->max_depth_bounds;
1787ec681f3Smrg   depth_stencil_state.stencilTestEnable = state->dyn_state1.depth_stencil_alpha_state->stencil_test;
1797ec681f3Smrg   depth_stencil_state.front = state->dyn_state1.depth_stencil_alpha_state->stencil_front;
1807ec681f3Smrg   depth_stencil_state.back = state->dyn_state1.depth_stencil_alpha_state->stencil_back;
1817ec681f3Smrg   depth_stencil_state.depthWriteEnable = state->dyn_state1.depth_stencil_alpha_state->depth_write;
1827ec681f3Smrg
1837ec681f3Smrg   VkDynamicState dynamicStateEnables[30] = {
1847ec681f3Smrg      VK_DYNAMIC_STATE_LINE_WIDTH,
1857ec681f3Smrg      VK_DYNAMIC_STATE_DEPTH_BIAS,
1867ec681f3Smrg      VK_DYNAMIC_STATE_BLEND_CONSTANTS,
1877ec681f3Smrg      VK_DYNAMIC_STATE_STENCIL_REFERENCE,
1887ec681f3Smrg   };
1897ec681f3Smrg   unsigned state_count = 4;
1907ec681f3Smrg   if (screen->info.have_EXT_extended_dynamic_state) {
1917ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT;
1927ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT;
1937ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;
1947ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT;
1957ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT;
1967ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT;
1977ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT;
1987ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
1997ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
2007ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_OP_EXT;
2017ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT;
2027ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_FRONT_FACE_EXT;
2037ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT;
2047ec681f3Smrg      if (state->sample_locations_enabled)
2057ec681f3Smrg         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT;
2067ec681f3Smrg   } else {
2077ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT;
2087ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR;
2097ec681f3Smrg   }
2107ec681f3Smrg   if (state->element_state->num_attribs) {
2117ec681f3Smrg      if (screen->info.have_EXT_vertex_input_dynamic_state)
2127ec681f3Smrg         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
2137ec681f3Smrg      else if (screen->info.have_EXT_extended_dynamic_state)
2147ec681f3Smrg         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
2157ec681f3Smrg   }
2167ec681f3Smrg   if (screen->info.have_EXT_extended_dynamic_state2)
2177ec681f3Smrg      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT;
2187ec681f3Smrg
2197ec681f3Smrg   VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
2207ec681f3Smrg   if (screen->info.have_EXT_line_rasterization) {
2217ec681f3Smrg      rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
2227ec681f3Smrg      rast_line_state.pNext = rast_state.pNext;
2237ec681f3Smrg      rast_line_state.stippledLineEnable = VK_FALSE;
2247ec681f3Smrg      rast_line_state.lineRasterizationMode = hw_rast_state->line_mode;
2257ec681f3Smrg
2267ec681f3Smrg      if (hw_rast_state->line_stipple_enable) {
2277ec681f3Smrg         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
2287ec681f3Smrg         rast_line_state.stippledLineEnable = VK_TRUE;
2297ec681f3Smrg      }
2307ec681f3Smrg      rast_state.pNext = &rast_line_state;
2317ec681f3Smrg   }
2327ec681f3Smrg
2337ec681f3Smrg   VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
2347ec681f3Smrg   pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2357ec681f3Smrg   pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
2367ec681f3Smrg   pipelineDynamicStateCreateInfo.dynamicStateCount = state_count;
2377ec681f3Smrg
2387ec681f3Smrg   VkGraphicsPipelineCreateInfo pci = {0};
2397ec681f3Smrg   pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
2407ec681f3Smrg   pci.layout = prog->base.layout;
2417ec681f3Smrg   pci.renderPass = state->render_pass->render_pass;
2427ec681f3Smrg   if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs)
2437ec681f3Smrg      pci.pVertexInputState = &vertex_input_state;
2447ec681f3Smrg   pci.pInputAssemblyState = &primitive_state;
2457ec681f3Smrg   pci.pRasterizationState = &rast_state;
2467ec681f3Smrg   pci.pColorBlendState = &blend_state;
2477ec681f3Smrg   pci.pMultisampleState = &ms_state;
2487ec681f3Smrg   pci.pViewportState = &viewport_state;
2497ec681f3Smrg   pci.pDepthStencilState = &depth_stencil_state;
2507ec681f3Smrg   pci.pDynamicState = &pipelineDynamicStateCreateInfo;
2517ec681f3Smrg
2527ec681f3Smrg   VkPipelineTessellationStateCreateInfo tci = {0};
2537ec681f3Smrg   VkPipelineTessellationDomainOriginStateCreateInfo tdci = {0};
2547ec681f3Smrg   if (prog->shaders[PIPE_SHADER_TESS_CTRL] && prog->shaders[PIPE_SHADER_TESS_EVAL]) {
2557ec681f3Smrg      tci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
2567ec681f3Smrg      tci.patchControlPoints = state->vertices_per_patch + 1;
2577ec681f3Smrg      pci.pTessellationState = &tci;
2587ec681f3Smrg      tci.pNext = &tdci;
2597ec681f3Smrg      tdci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
2607ec681f3Smrg      tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
2617ec681f3Smrg   }
2627ec681f3Smrg
2637ec681f3Smrg   VkPipelineShaderStageCreateInfo shader_stages[ZINK_SHADER_COUNT];
2647ec681f3Smrg   uint32_t num_stages = 0;
2657ec681f3Smrg   for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
2667ec681f3Smrg      if (!prog->modules[i])
2677ec681f3Smrg         continue;
2687ec681f3Smrg
2697ec681f3Smrg      VkPipelineShaderStageCreateInfo stage = {0};
2707ec681f3Smrg      stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
2717ec681f3Smrg      stage.stage = zink_shader_stage(i);
2727ec681f3Smrg      stage.module = prog->modules[i]->shader;
2737ec681f3Smrg      stage.pName = "main";
2747ec681f3Smrg      shader_stages[num_stages++] = stage;
2757ec681f3Smrg   }
2767ec681f3Smrg   assert(num_stages > 0);
2777ec681f3Smrg
2787ec681f3Smrg   pci.pStages = shader_stages;
2797ec681f3Smrg   pci.stageCount = num_stages;
2807ec681f3Smrg
2817ec681f3Smrg   VkPipeline pipeline;
2827ec681f3Smrg   if (vkCreateGraphicsPipelines(screen->dev, prog->base.pipeline_cache, 1, &pci,
2837ec681f3Smrg                                 NULL, &pipeline) != VK_SUCCESS) {
2847ec681f3Smrg      debug_printf("vkCreateGraphicsPipelines failed\n");
2857ec681f3Smrg      return VK_NULL_HANDLE;
2867ec681f3Smrg   }
2877ec681f3Smrg
2887ec681f3Smrg   return pipeline;
2897ec681f3Smrg}
2907ec681f3Smrg
2917ec681f3SmrgVkPipeline
2927ec681f3Smrgzink_create_compute_pipeline(struct zink_screen *screen, struct zink_compute_program *comp, struct zink_compute_pipeline_state *state)
2937ec681f3Smrg{
2947ec681f3Smrg   VkComputePipelineCreateInfo pci = {0};
2957ec681f3Smrg   pci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
2967ec681f3Smrg   pci.layout = comp->base.layout;
2977ec681f3Smrg
2987ec681f3Smrg   VkPipelineShaderStageCreateInfo stage = {0};
2997ec681f3Smrg   stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
3007ec681f3Smrg   stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
3017ec681f3Smrg   stage.module = comp->module->shader;
3027ec681f3Smrg   stage.pName = "main";
3037ec681f3Smrg
3047ec681f3Smrg   VkSpecializationInfo sinfo = {0};
3057ec681f3Smrg   VkSpecializationMapEntry me[3];
3067ec681f3Smrg   if (state->use_local_size) {
3077ec681f3Smrg      stage.pSpecializationInfo = &sinfo;
3087ec681f3Smrg      sinfo.mapEntryCount = 3;
3097ec681f3Smrg      sinfo.pMapEntries = &me[0];
3107ec681f3Smrg      sinfo.dataSize = sizeof(state->local_size);
3117ec681f3Smrg      sinfo.pData = &state->local_size[0];
3127ec681f3Smrg      uint32_t ids[] = {ZINK_WORKGROUP_SIZE_X, ZINK_WORKGROUP_SIZE_Y, ZINK_WORKGROUP_SIZE_Z};
3137ec681f3Smrg      for (int i = 0; i < 3; i++) {
3147ec681f3Smrg         me[i].size = sizeof(uint32_t);
3157ec681f3Smrg         me[i].constantID = ids[i];
3167ec681f3Smrg         me[i].offset = i * sizeof(uint32_t);
3177ec681f3Smrg      }
3187ec681f3Smrg   }
3197ec681f3Smrg
3207ec681f3Smrg   pci.stage = stage;
3217ec681f3Smrg
3227ec681f3Smrg   VkPipeline pipeline;
3237ec681f3Smrg   if (vkCreateComputePipelines(screen->dev, comp->base.pipeline_cache, 1, &pci,
3247ec681f3Smrg                                 NULL, &pipeline) != VK_SUCCESS) {
3257ec681f3Smrg      debug_printf("vkCreateComputePipelines failed\n");
3267ec681f3Smrg      return VK_NULL_HANDLE;
3277ec681f3Smrg   }
3287ec681f3Smrg   zink_screen_update_pipeline_cache(screen, &comp->base);
3297ec681f3Smrg
3307ec681f3Smrg   return pipeline;
3317ec681f3Smrg}
332