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
38static VkBlendFactor
39clamp_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
48VkPipeline
49zink_create_gfx_pipeline(struct zink_screen *screen,
50                         struct zink_gfx_program *prog,
51                         struct zink_gfx_pipeline_state *state,
52                         VkPrimitiveTopology primitive_topology)
53{
54   struct zink_rasterizer_hw_state *hw_rast_state = (void*)state;
55   VkPipelineVertexInputStateCreateInfo vertex_input_state;
56   if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs) {
57      memset(&vertex_input_state, 0, sizeof(vertex_input_state));
58      vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
59      vertex_input_state.pVertexBindingDescriptions = state->element_state->b.bindings;
60      vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings;
61      vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs;
62      vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs;
63   }
64
65   VkPipelineVertexInputDivisorStateCreateInfoEXT vdiv_state;
66   if (!screen->info.have_EXT_vertex_input_dynamic_state && state->element_state->b.divisors_present) {
67       memset(&vdiv_state, 0, sizeof(vdiv_state));
68       vertex_input_state.pNext = &vdiv_state;
69       vdiv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
70       vdiv_state.vertexBindingDivisorCount = state->element_state->b.divisors_present;
71       vdiv_state.pVertexBindingDivisors = state->element_state->b.divisors;
72   }
73
74   VkPipelineInputAssemblyStateCreateInfo primitive_state = {0};
75   primitive_state.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
76   primitive_state.topology = primitive_topology;
77   if (!screen->info.have_EXT_extended_dynamic_state2) {
78      switch (primitive_topology) {
79      case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
80      case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
81      case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
82      case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
83      case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
84      case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
85         if (state->primitive_restart)
86            debug_printf("restart_index set with unsupported primitive topology %u\n", primitive_topology);
87         primitive_state.primitiveRestartEnable = VK_FALSE;
88         break;
89      default:
90         primitive_state.primitiveRestartEnable = state->primitive_restart ? VK_TRUE : VK_FALSE;
91      }
92   }
93
94   VkPipelineColorBlendAttachmentState blend_att[PIPE_MAX_COLOR_BUFS];
95   VkPipelineColorBlendStateCreateInfo blend_state = {0};
96   blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
97   if (state->blend_state) {
98      unsigned num_attachments = state->render_pass->state.num_rts;
99      if (state->render_pass->state.have_zsbuf)
100         num_attachments--;
101      if (state->void_alpha_attachments) {
102         for (unsigned i = 0; i < num_attachments; i++) {
103            blend_att[i] = state->blend_state->attachments[i];
104            if (state->void_alpha_attachments & BITFIELD_BIT(i)) {
105               blend_att[i].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
106               blend_att[i].srcColorBlendFactor = clamp_void_blend_factor(blend_att[i].srcColorBlendFactor);
107               blend_att[i].dstColorBlendFactor = clamp_void_blend_factor(blend_att[i].dstColorBlendFactor);
108            }
109         }
110         blend_state.pAttachments = blend_att;
111      } else
112         blend_state.pAttachments = state->blend_state->attachments;
113      blend_state.attachmentCount = num_attachments;
114      blend_state.logicOpEnable = state->blend_state->logicop_enable;
115      blend_state.logicOp = state->blend_state->logicop_func;
116   }
117
118   VkPipelineMultisampleStateCreateInfo ms_state = {0};
119   ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
120   ms_state.rasterizationSamples = state->rast_samples + 1;
121   if (state->blend_state) {
122      ms_state.alphaToCoverageEnable = state->blend_state->alpha_to_coverage;
123      if (state->blend_state->alpha_to_one && !screen->info.feats.features.alphaToOne)
124         warn_missing_feature("alphaToOne");
125      ms_state.alphaToOneEnable = state->blend_state->alpha_to_one;
126   }
127   /* "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
128    * - Chapter 27. Rasterization
129    *
130    * thus it never makes sense to leave this as NULL since gallium will provide correct
131    * data here as long as sample_mask is initialized on context creation
132    */
133   ms_state.pSampleMask = &state->sample_mask;
134   if (hw_rast_state->force_persample_interp) {
135      ms_state.sampleShadingEnable = VK_TRUE;
136      ms_state.minSampleShading = 1.0;
137   }
138
139   VkPipelineViewportStateCreateInfo viewport_state = {0};
140   viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
141   viewport_state.viewportCount = screen->info.have_EXT_extended_dynamic_state ? 0 : state->dyn_state1.num_viewports;
142   viewport_state.pViewports = NULL;
143   viewport_state.scissorCount = screen->info.have_EXT_extended_dynamic_state ? 0 : state->dyn_state1.num_viewports;
144   viewport_state.pScissors = NULL;
145
146   VkPipelineRasterizationStateCreateInfo rast_state = {0};
147   rast_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
148
149   rast_state.depthClampEnable = hw_rast_state->depth_clamp;
150   rast_state.rasterizerDiscardEnable = hw_rast_state->rasterizer_discard;
151   rast_state.polygonMode = hw_rast_state->polygon_mode;
152   rast_state.cullMode = hw_rast_state->cull_mode;
153   rast_state.frontFace = state->dyn_state1.front_face;
154
155   rast_state.depthBiasEnable = VK_TRUE;
156   rast_state.depthBiasConstantFactor = 0.0;
157   rast_state.depthBiasClamp = 0.0;
158   rast_state.depthBiasSlopeFactor = 0.0;
159   rast_state.lineWidth = 1.0f;
160
161   VkPipelineRasterizationProvokingVertexStateCreateInfoEXT pv_state;
162   pv_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT;
163   pv_state.provokingVertexMode = hw_rast_state->pv_last ?
164                                  VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT :
165                                  VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
166   if (screen->info.have_EXT_provoking_vertex && hw_rast_state->pv_last) {
167      pv_state.pNext = rast_state.pNext;
168      rast_state.pNext = &pv_state;
169   }
170
171   VkPipelineDepthStencilStateCreateInfo depth_stencil_state = {0};
172   depth_stencil_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
173   depth_stencil_state.depthTestEnable = state->dyn_state1.depth_stencil_alpha_state->depth_test;
174   depth_stencil_state.depthCompareOp = state->dyn_state1.depth_stencil_alpha_state->depth_compare_op;
175   depth_stencil_state.depthBoundsTestEnable = state->dyn_state1.depth_stencil_alpha_state->depth_bounds_test;
176   depth_stencil_state.minDepthBounds = state->dyn_state1.depth_stencil_alpha_state->min_depth_bounds;
177   depth_stencil_state.maxDepthBounds = state->dyn_state1.depth_stencil_alpha_state->max_depth_bounds;
178   depth_stencil_state.stencilTestEnable = state->dyn_state1.depth_stencil_alpha_state->stencil_test;
179   depth_stencil_state.front = state->dyn_state1.depth_stencil_alpha_state->stencil_front;
180   depth_stencil_state.back = state->dyn_state1.depth_stencil_alpha_state->stencil_back;
181   depth_stencil_state.depthWriteEnable = state->dyn_state1.depth_stencil_alpha_state->depth_write;
182
183   VkDynamicState dynamicStateEnables[30] = {
184      VK_DYNAMIC_STATE_LINE_WIDTH,
185      VK_DYNAMIC_STATE_DEPTH_BIAS,
186      VK_DYNAMIC_STATE_BLEND_CONSTANTS,
187      VK_DYNAMIC_STATE_STENCIL_REFERENCE,
188   };
189   unsigned state_count = 4;
190   if (screen->info.have_EXT_extended_dynamic_state) {
191      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT;
192      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT;
193      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS;
194      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT;
195      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT;
196      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT;
197      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT;
198      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
199      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
200      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_OP_EXT;
201      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT;
202      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_FRONT_FACE_EXT;
203      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT;
204      if (state->sample_locations_enabled)
205         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT;
206   } else {
207      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VIEWPORT;
208      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_SCISSOR;
209   }
210   if (state->element_state->num_attribs) {
211      if (screen->info.have_EXT_vertex_input_dynamic_state)
212         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
213      else if (screen->info.have_EXT_extended_dynamic_state)
214         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
215   }
216   if (screen->info.have_EXT_extended_dynamic_state2)
217      dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT;
218
219   VkPipelineRasterizationLineStateCreateInfoEXT rast_line_state;
220   if (screen->info.have_EXT_line_rasterization) {
221      rast_line_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT;
222      rast_line_state.pNext = rast_state.pNext;
223      rast_line_state.stippledLineEnable = VK_FALSE;
224      rast_line_state.lineRasterizationMode = hw_rast_state->line_mode;
225
226      if (hw_rast_state->line_stipple_enable) {
227         dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
228         rast_line_state.stippledLineEnable = VK_TRUE;
229      }
230      rast_state.pNext = &rast_line_state;
231   }
232
233   VkPipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {0};
234   pipelineDynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
235   pipelineDynamicStateCreateInfo.pDynamicStates = dynamicStateEnables;
236   pipelineDynamicStateCreateInfo.dynamicStateCount = state_count;
237
238   VkGraphicsPipelineCreateInfo pci = {0};
239   pci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
240   pci.layout = prog->base.layout;
241   pci.renderPass = state->render_pass->render_pass;
242   if (!screen->info.have_EXT_vertex_input_dynamic_state || !state->element_state->num_attribs)
243      pci.pVertexInputState = &vertex_input_state;
244   pci.pInputAssemblyState = &primitive_state;
245   pci.pRasterizationState = &rast_state;
246   pci.pColorBlendState = &blend_state;
247   pci.pMultisampleState = &ms_state;
248   pci.pViewportState = &viewport_state;
249   pci.pDepthStencilState = &depth_stencil_state;
250   pci.pDynamicState = &pipelineDynamicStateCreateInfo;
251
252   VkPipelineTessellationStateCreateInfo tci = {0};
253   VkPipelineTessellationDomainOriginStateCreateInfo tdci = {0};
254   if (prog->shaders[PIPE_SHADER_TESS_CTRL] && prog->shaders[PIPE_SHADER_TESS_EVAL]) {
255      tci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
256      tci.patchControlPoints = state->vertices_per_patch + 1;
257      pci.pTessellationState = &tci;
258      tci.pNext = &tdci;
259      tdci.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
260      tdci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
261   }
262
263   VkPipelineShaderStageCreateInfo shader_stages[ZINK_SHADER_COUNT];
264   uint32_t num_stages = 0;
265   for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
266      if (!prog->modules[i])
267         continue;
268
269      VkPipelineShaderStageCreateInfo stage = {0};
270      stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
271      stage.stage = zink_shader_stage(i);
272      stage.module = prog->modules[i]->shader;
273      stage.pName = "main";
274      shader_stages[num_stages++] = stage;
275   }
276   assert(num_stages > 0);
277
278   pci.pStages = shader_stages;
279   pci.stageCount = num_stages;
280
281   VkPipeline pipeline;
282   if (vkCreateGraphicsPipelines(screen->dev, prog->base.pipeline_cache, 1, &pci,
283                                 NULL, &pipeline) != VK_SUCCESS) {
284      debug_printf("vkCreateGraphicsPipelines failed\n");
285      return VK_NULL_HANDLE;
286   }
287
288   return pipeline;
289}
290
291VkPipeline
292zink_create_compute_pipeline(struct zink_screen *screen, struct zink_compute_program *comp, struct zink_compute_pipeline_state *state)
293{
294   VkComputePipelineCreateInfo pci = {0};
295   pci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
296   pci.layout = comp->base.layout;
297
298   VkPipelineShaderStageCreateInfo stage = {0};
299   stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
300   stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
301   stage.module = comp->module->shader;
302   stage.pName = "main";
303
304   VkSpecializationInfo sinfo = {0};
305   VkSpecializationMapEntry me[3];
306   if (state->use_local_size) {
307      stage.pSpecializationInfo = &sinfo;
308      sinfo.mapEntryCount = 3;
309      sinfo.pMapEntries = &me[0];
310      sinfo.dataSize = sizeof(state->local_size);
311      sinfo.pData = &state->local_size[0];
312      uint32_t ids[] = {ZINK_WORKGROUP_SIZE_X, ZINK_WORKGROUP_SIZE_Y, ZINK_WORKGROUP_SIZE_Z};
313      for (int i = 0; i < 3; i++) {
314         me[i].size = sizeof(uint32_t);
315         me[i].constantID = ids[i];
316         me[i].offset = i * sizeof(uint32_t);
317      }
318   }
319
320   pci.stage = stage;
321
322   VkPipeline pipeline;
323   if (vkCreateComputePipelines(screen->dev, comp->base.pipeline_cache, 1, &pci,
324                                 NULL, &pipeline) != VK_SUCCESS) {
325      debug_printf("vkCreateComputePipelines failed\n");
326      return VK_NULL_HANDLE;
327   }
328   zink_screen_update_pipeline_cache(screen, &comp->base);
329
330   return pipeline;
331}
332