• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Collabora Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "compiler/spirv/spirv.h"
25 
26 #include "zink_pipeline.h"
27 
28 #include "zink_compiler.h"
29 #include "zink_context.h"
30 #include "zink_program.h"
31 #include "zink_render_pass.h"
32 #include "zink_screen.h"
33 #include "zink_state.h"
34 
35 #include "util/u_debug.h"
36 #include "util/u_prim.h"
37 
38 static VkBlendFactor
clamp_void_blend_factor(VkBlendFactor f)39 clamp_void_blend_factor(VkBlendFactor f)
40 {
41    if (f == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA)
42       return VK_BLEND_FACTOR_ZERO;
43    if (f == VK_BLEND_FACTOR_DST_ALPHA)
44       return VK_BLEND_FACTOR_ONE;
45    return f;
46 }
47 
48 VkPipeline
zink_create_gfx_pipeline(struct zink_screen * screen,struct zink_gfx_program * prog,struct zink_gfx_pipeline_state * state,const uint8_t * binding_map,VkPrimitiveTopology primitive_topology)49 zink_create_gfx_pipeline(struct zink_screen *screen,
50                          struct zink_gfx_program *prog,
51                          struct zink_gfx_pipeline_state *state,
52                          const uint8_t *binding_map,
53                          VkPrimitiveTopology primitive_topology)
54 {
55    struct zink_rasterizer_hw_state *hw_rast_state = (void*)state;
56    VkPipelineVertexInputStateCreateInfo vertex_input_state;
57    if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs || !state->uses_dynamic_stride) {
58       memset(&vertex_input_state, 0, sizeof(vertex_input_state));
59       vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
60       vertex_input_state.pVertexBindingDescriptions = state->element_state->b.bindings;
61       vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings;
62       vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs;
63       vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs;
64       if (!screen->info.have_EXT_extended_dynamic_state || !state->uses_dynamic_stride) {
65          for (int i = 0; i < state->element_state->num_bindings; ++i) {
66             const unsigned buffer_id = binding_map[i];
67             VkVertexInputBindingDescription *binding = &state->element_state->b.bindings[i];
68             binding->stride = state->vertex_strides[buffer_id];
69          }
70       }
71    }
72 
73    VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state;
74    if (!screen->info.have_EXT_vertex_input_dynamic_state && state->element_state->b.divisors_present) {
75        memset(&vdiv_state, 0, sizeof(vdiv_state));
76        vertex_input_state.pNext = &vdiv_state;
77        vdiv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
78        vdiv_state.vertexBindingDivisorCount = state->element_state->b.divisors_present;
79        vdiv_state.pVertexBindingDivisors = state->element_state->b.divisors;
80    }
81 
82    VkPipelineInputAssemblyStateCreateInfo primitive_state = {0};
83    primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
84    primitive_state.topology = primitive_topology;
85    if (!screen->info.have_EXT_extended_dynamic_state2) {
86       switch (primitive_topology) {
87       case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
88       case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
89       case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
90       case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
91       case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
92          if (screen->info.have_EXT_primitive_topology_list_restart) {
93             primitive_state.primitiveRestartEnable = state->dyn_state2.primitive_restart ? VK_TRUE : VK_FALSE;
94             break;
95          }
96          FALLTHROUGH;
97       case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
98          if (state->dyn_state2.primitive_restart)
99             mesa_loge("zink: restart_index set with unsupported primitive topology %u\n", primitive_topology);
100          primitive_state.primitiveRestartEnable = VK_FALSE;
101          break;
102       default:
103          primitive_state.primitiveRestartEnable = state->dyn_state2.primitive_restart ? VK_TRUE : VK_FALSE;
104       }
105    }
106 
107    VkPipelineColorBlendAttachmentState blend_att[PIPE_MAX_COLOR_BUFS];
108    VkPipelineColorBlendStateCreateInfo blend_state = {0};
109    blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
110    if (state->blend_state) {
111       unsigned num_attachments = state->render_pass ?
112                                  state->render_pass->state.num_rts :
113                                  state->rendering_info.colorAttachmentCount;
114       if (state->render_pass && state->render_pass->state.have_zsbuf)
115          num_attachments--;
116       if (state->void_alpha_attachments) {
117          for (unsigned i = 0; i < num_attachments; i++) {
118             blend_att[i] = state->blend_state->attachments[i];
119             if (state->void_alpha_attachments & BITFIELD_BIT(i)) {
120                blend_att[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
121                blend_att[i].srcColorBlendFactor = clamp_void_blend_factor(blend_att[i].srcColorBlendFactor);
122                blend_att[i].dstColorBlendFactor = clamp_void_blend_factor(blend_att[i].dstColorBlendFactor);
123             }
124          }
125          blend_state.pAttachments = blend_att;
126       } else
127          blend_state.pAttachments = state->blend_state->attachments;
128       blend_state.attachmentCount = num_attachments;
129       blend_state.logicOpEnable = state->blend_state->logicop_enable;
130       blend_state.logicOp = state->blend_state->logicop_func;
131    }
132 
133    VkPipelineMultisampleStateCreateInfo ms_state = {0};
134    ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
135    ms_state.rasterizationSamples = state->rast_samples + 1;
136    if (state->blend_state) {
137       ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
138       if (state->blend_state->alpha_to_one && !screen->info.feats.features.alphaToOne) {
139          static bool warned = false;
140          warn_missing_feature(warned, "alphaToOne");
141       }
142       ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
143    }
144    /* "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
145     * - Chapter 27. Rasterization
146     *
147     * thus it never makes sense to leave this as NULL since gallium will provide correct
148     * data here as long as sample_mask is initialized on context creation
149     */
150    ms_state.pSampleMask = &state->sample_mask;
151    if (hw_rast_state->force_persample_interp) {
152       ms_state.sampleShadingEnable = VK_TRUE;
153       ms_state.minSampleShading = 1.0;
154    }
155 
156    VkPipelineViewportStateCreateInfo viewport_state = {0};
157    VkPipelineViewportDepthClipControlCreateInfoEXT clip = {
158       VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT,
159       NULL,
160       VK_TRUE
161    };
162    viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
163    viewport_state.viewportCount = screen->info.have_EXT_extended_dynamic_state ? 0 : state->dyn_state1.num_viewports;
164    viewport_state.pViewports = NULL;
165    viewport_state.scissorCount = screen->info.have_EXT_extended_dynamic_state ? 0 : state->dyn_state1.num_viewports;
166    viewport_state.pScissors = NULL;
167    if (!screen->driver_workarounds.depth_clip_control_missing && !hw_rast_state->clip_halfz)
168       viewport_state.pNext = &clip;
169 
170    VkPipelineRasterizationStateCreateInfo rast_state = {0};
171    rast_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
172 
173    rast_state.depthClampEnable = true;
174    rast_state.rasterizerDiscardEnable = state->dyn_state2.rasterizer_discard;
175    rast_state.polygonMode = hw_rast_state->polygon_mode;
176    rast_state.cullMode = state->dyn_state1.cull_mode;
177    rast_state.frontFace = state->dyn_state1.front_face;
178 
179    rast_state.depthBiasEnable = VK_TRUE;
180    rast_state.depthBiasConstantFactor = 0.0;
181    rast_state.depthBiasClamp = 0.0;
182    rast_state.depthBiasSlopeFactor = 0.0;
183    rast_state.lineWidth = 1.0f;
184 
185    VkPipelineRasterizationDepthClipStateCreateInfoEXT depth_clip_state = {0};
186    depth_clip_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT;
187    depth_clip_state.depthClipEnable = hw_rast_state->depth_clip;
188    if (screen->info.have_EXT_depth_clip_enable) {
189       depth_clip_state.pNext = rast_state.pNext;
190       rast_state.pNext = &depth_clip_state;
191    } else {
192       static bool warned = false;
193       warn_missing_feature(warned, "VK_EXT_depth_clip_enable");
194       rast_state.depthClampEnable = !hw_rast_state->depth_clip;
195    }
196 
197    VkPipelineRasterizationProvokingVertexStateCreateInfoEXT pv_state;
198    pv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
199    pv_state.provokingVertexMode = hw_rast_state->pv_last ?
200                                   VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
201                                   VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
202    if (screen->info.have_EXT_provoking_vertex && hw_rast_state->pv_last) {
203       pv_state.pNext = rast_state.pNext;
204       rast_state.pNext = &pv_state;
205    }
206 
207    VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {0};
208    depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
209    depth_stencil_state.depthTestEnable = state->dyn_state1.depth_stencil_alpha_state->depth_test;
210    depth_stencil_state.depthCompareOp = state->dyn_state1.depth_stencil_alpha_state->depth_compare_op;
211    depth_stencil_state.depthBoundsTestEnable = state->dyn_state1.depth_stencil_alpha_state->depth_bounds_test;
212    depth_stencil_state.minDepthBounds = state->dyn_state1.depth_stencil_alpha_state->min_depth_bounds;
213    depth_stencil_state.maxDepthBounds = state->dyn_state1.depth_stencil_alpha_state->max_depth_bounds;
214    depth_stencil_state.stencilTestEnable = state->dyn_state1.depth_stencil_alpha_state->stencil_test;
215    depth_stencil_state.front = state->dyn_state1.depth_stencil_alpha_state->stencil_front;
216    depth_stencil_state.back = state->dyn_state1.depth_stencil_alpha_state->stencil_back;
217    depth_stencil_state.depthWriteEnable = state->dyn_state1.depth_stencil_alpha_state->depth_write;
218 
219    VkDynamicState dynamicStateEnables[30] = {
220       VK_DYNAMIC_STATE_LINE_WIDTH,
221       VK_DYNAMIC_STATE_DEPTH_BIAS,
222       VK_DYNAMIC_STATE_BLEND_CONSTANTS,
223       VK_DYNAMIC_STATE_STENCIL_REFERENCE,
224    };
225    unsigned state_count = 4;
226    if (screen->info.have_EXT_extended_dynamic_state) {
227       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT;
228       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT;
229       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;
230       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE;
231       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP;
232       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE;
233       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE;
234       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
235       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
236       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_OP;
237       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE;
238       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_FRONT_FACE;
239       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY;
240       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_CULL_MODE;
241       if (state->sample_locations_enabled)
242          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT;
243    } else {
244       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT;
245       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR;
246    }
247    if (state->element_state->num_attribs) {
248       if (screen->info.have_EXT_vertex_input_dynamic_state)
249          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
250       else if (screen->info.have_EXT_extended_dynamic_state && state->uses_dynamic_stride)
251          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE;
252    }
253    if (screen->info.have_EXT_extended_dynamic_state2) {
254       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE;
255       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE;
256       if (screen->info.dynamic_state2_feats.extendedDynamicState2PatchControlPoints)
257          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
258    }
259    if (!screen->driver_workarounds.color_write_missing)
260       dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
261 
262    VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
263    if (screen->info.have_EXT_line_rasterization) {
264       rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
265       rast_line_state.pNext = rast_state.pNext;
266       rast_line_state.stippledLineEnable = VK_FALSE;
267       rast_line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
268 
269       bool check_warn = false;
270       switch (primitive_topology) {
271       case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
272       case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
273       case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
274       case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
275          check_warn = true;
276          break;
277       default: break;
278       }
279       if (prog->nir[PIPE_SHADER_TESS_EVAL]) {
280          check_warn |= !prog->nir[PIPE_SHADER_TESS_EVAL]->info.tess.point_mode &&
281                        prog->nir[PIPE_SHADER_TESS_EVAL]->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES;
282       }
283       if (prog->nir[PIPE_SHADER_GEOMETRY]) {
284          switch (prog->nir[PIPE_SHADER_GEOMETRY]->info.gs.output_primitive) {
285          case SHADER_PRIM_LINES:
286          case SHADER_PRIM_LINE_LOOP:
287          case SHADER_PRIM_LINE_STRIP:
288          case SHADER_PRIM_LINES_ADJACENCY:
289          case SHADER_PRIM_LINE_STRIP_ADJACENCY:
290             check_warn = true;
291             break;
292          default: break;
293          }
294       }
295 
296       if (check_warn) {
297          const char *features[4][2] = {
298             [VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT] = {"",""},
299             [VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT] = {"rectangularLines", "stippledRectangularLines"},
300             [VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT] = {"bresenhamLines", "stippledBresenhamLines"},
301             [VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT] = {"smoothLines", "stippledSmoothLines"},
302          };
303          static bool warned[6] = {0};
304          const VkPhysicalDeviceLineRasterizationFeaturesEXT *line_feats = &screen->info.line_rast_feats;
305          /* line features can be represented as an array VkBool32[6],
306           * with the 3 base features preceding the 3 (matching) stippled features
307           */
308          const VkBool32 *feat = &line_feats->rectangularLines;
309          unsigned mode_idx = hw_rast_state->line_mode - VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
310          /* add base mode index, add 3 if stippling is enabled */
311          mode_idx += hw_rast_state->line_stipple_enable * 3;
312          if (*(feat + mode_idx))
313             rast_line_state.lineRasterizationMode = hw_rast_state->line_mode;
314          else
315             warn_missing_feature(warned[mode_idx], features[hw_rast_state->line_mode][hw_rast_state->line_stipple_enable]);
316       }
317 
318       if (hw_rast_state->line_stipple_enable) {
319          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
320          rast_line_state.stippledLineEnable = VK_TRUE;
321       }
322 
323       rast_state.pNext = &rast_line_state;
324    }
325    assert(state_count < ARRAY_SIZE(dynamicStateEnables));
326 
327    VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
328    pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
329    pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
330    pipelineDynamicStateCreateInfo.dynamicStateCount = state_count;
331 
332    VkGraphicsPipelineCreateInfo pci = {0};
333    pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
334    pci.layout = prog->base.layout;
335    if (state->render_pass)
336       pci.renderPass = state->render_pass->render_pass;
337    else
338       pci.pNext = &state->rendering_info;
339    if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs || !state->uses_dynamic_stride)
340       pci.pVertexInputState = &vertex_input_state;
341    pci.pInputAssemblyState = &primitive_state;
342    pci.pRasterizationState = &rast_state;
343    pci.pColorBlendState = &blend_state;
344    pci.pMultisampleState = &ms_state;
345    pci.pViewportState = &viewport_state;
346    pci.pDepthStencilState = &depth_stencil_state;
347    pci.pDynamicState = &pipelineDynamicStateCreateInfo;
348 
349    VkPipelineTessellationStateCreateInfo tci = {0};
350    VkPipelineTessellationDomainOriginStateCreateInfo tdci = {0};
351    if (prog->shaders[PIPE_SHADER_TESS_CTRL] && prog->shaders[PIPE_SHADER_TESS_EVAL]) {
352       tci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
353       tci.patchControlPoints = state->dyn_state2.vertices_per_patch;
354       pci.pTessellationState = &tci;
355       tci.pNext = &tdci;
356       tdci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
357       tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
358    }
359 
360    VkPipelineShaderStageCreateInfo shader_stages[ZINK_SHADER_COUNT];
361    uint32_t num_stages = 0;
362    for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
363       if (!prog->modules[i])
364          continue;
365 
366       VkPipelineShaderStageCreateInfo stage = {0};
367       stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
368       stage.stage = zink_shader_stage(i);
369       stage.module = prog->modules[i]->shader;
370       stage.pName = "main";
371       shader_stages[num_stages++] = stage;
372    }
373    assert(num_stages > 0);
374 
375    pci.pStages = shader_stages;
376    pci.stageCount = num_stages;
377 
378    VkPipeline pipeline;
379    VkResult result = VKSCR(CreateGraphicsPipelines)(screen->dev, prog->base.pipeline_cache,
380                                                     1, &pci, NULL, &pipeline);
381    if (result != VK_SUCCESS) {
382       mesa_loge("ZINK: vkCreateGraphicsPipelines failed (%s)", vk_Result_to_str(result));
383       return VK_NULL_HANDLE;
384    }
385 
386    return pipeline;
387 }
388 
389 VkPipeline
zink_create_compute_pipeline(struct zink_screen * screen,struct zink_compute_program * comp,struct zink_compute_pipeline_state * state)390 zink_create_compute_pipeline(struct zink_screen *screen, struct zink_compute_program *comp, struct zink_compute_pipeline_state *state)
391 {
392    VkComputePipelineCreateInfo pci = {0};
393    pci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
394    pci.layout = comp->base.layout;
395 
396    VkPipelineShaderStageCreateInfo stage = {0};
397    stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
398    stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
399    stage.module = comp->curr->shader;
400    stage.pName = "main";
401 
402    VkSpecializationInfo sinfo = {0};
403    VkSpecializationMapEntry me[3];
404    if (state->use_local_size) {
405       stage.pSpecializationInfo = &sinfo;
406       sinfo.mapEntryCount = 3;
407       sinfo.pMapEntries = &me[0];
408       sinfo.dataSize = sizeof(state->local_size);
409       sinfo.pData = &state->local_size[0];
410       uint32_t ids[] = {ZINK_WORKGROUP_SIZE_X, ZINK_WORKGROUP_SIZE_Y, ZINK_WORKGROUP_SIZE_Z};
411       for (int i = 0; i < 3; i++) {
412          me[i].size = sizeof(uint32_t);
413          me[i].constantID = ids[i];
414          me[i].offset = i * sizeof(uint32_t);
415       }
416    }
417 
418    pci.stage = stage;
419 
420    VkPipeline pipeline;
421    VkResult result = VKSCR(CreateComputePipelines)(screen->dev, comp->base.pipeline_cache,
422                                                    1, &pci, NULL, &pipeline);
423    if (result != VK_SUCCESS) {
424       mesa_loge("ZINK: vkCreateComputePipelines failed (%s)", vk_Result_to_str(result));
425       return VK_NULL_HANDLE;
426    }
427    zink_screen_update_pipeline_cache(screen, &comp->base);
428 
429    return pipeline;
430 }
431