1 /*
2  * Copyright © 2021 Collabora Ltd.
3  *
4  * Derived from tu_pipeline.c which is:
5  * Copyright © 2016 Red Hat.
6  * Copyright © 2016 Bas Nieuwenhuizen
7  * Copyright © 2015 Intel Corporation
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice (including the next
17  * paragraph) shall be included in all copies or substantial portions of the
18  * Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  */
28 
29 #include "panvk_cs.h"
30 #include "panvk_private.h"
31 
32 #include "pan_bo.h"
33 
34 #include "nir/nir.h"
35 #include "nir/nir_builder.h"
36 #include "spirv/nir_spirv.h"
37 #include "util/debug.h"
38 #include "util/mesa-sha1.h"
39 #include "util/u_atomic.h"
40 #include "vk_format.h"
41 #include "vk_util.h"
42 
43 #include "panfrost/util/pan_lower_framebuffer.h"
44 
45 
46 struct panvk_pipeline_builder
47 {
48    struct panvk_device *device;
49    struct panvk_pipeline_cache *cache;
50    const VkAllocationCallbacks *alloc;
51    struct {
52       const VkGraphicsPipelineCreateInfo *gfx;
53       const VkComputePipelineCreateInfo *compute;
54    } create_info;
55    const struct panvk_pipeline_layout *layout;
56 
57    struct panvk_shader *shaders[MESA_SHADER_STAGES];
58    struct {
59       uint32_t shader_offset;
60       uint32_t rsd_offset;
61       uint32_t sysvals_offset;
62    } stages[MESA_SHADER_STAGES];
63    uint32_t blend_shader_offsets[MAX_RTS];
64    uint32_t shader_total_size;
65    uint32_t static_state_size;
66    uint32_t vpd_offset;
67 
68    bool rasterizer_discard;
69    /* these states are affectd by rasterizer_discard */
70    VkSampleCountFlagBits samples;
71    bool use_depth_stencil_attachment;
72    uint8_t active_color_attachments;
73    enum pipe_format color_attachment_formats[MAX_RTS];
74 };
75 
76 static VkResult
panvk_pipeline_builder_create_pipeline(struct panvk_pipeline_builder * builder,struct panvk_pipeline ** out_pipeline)77 panvk_pipeline_builder_create_pipeline(struct panvk_pipeline_builder *builder,
78                                        struct panvk_pipeline **out_pipeline)
79 {
80    struct panvk_device *dev = builder->device;
81 
82    struct panvk_pipeline *pipeline =
83       vk_object_zalloc(&dev->vk, builder->alloc,
84                        sizeof(*pipeline), VK_OBJECT_TYPE_PIPELINE);
85    if (!pipeline)
86       return VK_ERROR_OUT_OF_HOST_MEMORY;
87 
88    pipeline->layout = builder->layout;
89    *out_pipeline = pipeline;
90    return VK_SUCCESS;
91 }
92 
93 static void
panvk_pipeline_builder_finish(struct panvk_pipeline_builder * builder)94 panvk_pipeline_builder_finish(struct panvk_pipeline_builder *builder)
95 {
96    for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
97       if (!builder->shaders[i])
98          continue;
99       panvk_shader_destroy(builder->device, builder->shaders[i], builder->alloc);
100    }
101 }
102 
103 static bool
panvk_pipeline_static_state(struct panvk_pipeline * pipeline,uint32_t id)104 panvk_pipeline_static_state(struct panvk_pipeline *pipeline, uint32_t id)
105 {
106    return !(pipeline->dynamic_state_mask & (1 << id));
107 }
108 
109 static VkResult
panvk_pipeline_builder_compile_shaders(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)110 panvk_pipeline_builder_compile_shaders(struct panvk_pipeline_builder *builder,
111                                        struct panvk_pipeline *pipeline)
112 {
113    const VkPipelineShaderStageCreateInfo *stage_infos[MESA_SHADER_STAGES] = {
114       NULL
115    };
116    const VkPipelineShaderStageCreateInfo *stages =
117       builder->create_info.gfx ?
118       builder->create_info.gfx->pStages :
119       &builder->create_info.compute->stage;
120    unsigned stage_count =
121       builder->create_info.gfx ? builder->create_info.gfx->stageCount : 1;
122 
123    for (uint32_t i = 0; i < stage_count; i++) {
124       gl_shader_stage stage = vk_to_mesa_shader_stage(stages[i].stage);
125       stage_infos[stage] = &stages[i];
126    }
127 
128    /* compile shaders in reverse order */
129    unsigned sysval_ubo = builder->layout->num_ubos + builder->layout->num_dyn_ubos;
130 
131    for (gl_shader_stage stage = MESA_SHADER_STAGES - 1;
132         stage > MESA_SHADER_NONE; stage--) {
133       const VkPipelineShaderStageCreateInfo *stage_info = stage_infos[stage];
134       if (!stage_info)
135          continue;
136 
137       struct panvk_shader *shader;
138 
139       shader = panvk_per_arch(shader_create)(builder->device, stage, stage_info,
140                                              builder->layout, sysval_ubo,
141                                              &pipeline->blend.state,
142                                              panvk_pipeline_static_state(pipeline,
143                                                                          VK_DYNAMIC_STATE_BLEND_CONSTANTS),
144                                              builder->alloc);
145       if (!shader)
146          return VK_ERROR_OUT_OF_HOST_MEMORY;
147 
148       if (shader->info.sysvals.sysval_count)
149          sysval_ubo++;
150 
151       builder->shaders[stage] = shader;
152       builder->shader_total_size = ALIGN_POT(builder->shader_total_size, 128);
153       builder->stages[stage].shader_offset = builder->shader_total_size;
154       builder->shader_total_size +=
155          util_dynarray_num_elements(&shader->binary, uint8_t);
156    }
157 
158    return VK_SUCCESS;
159 }
160 
161 static VkResult
panvk_pipeline_builder_upload_shaders(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)162 panvk_pipeline_builder_upload_shaders(struct panvk_pipeline_builder *builder,
163                                       struct panvk_pipeline *pipeline)
164 {
165    struct panfrost_bo *bin_bo =
166       panfrost_bo_create(&builder->device->physical_device->pdev,
167                          builder->shader_total_size, PAN_BO_EXECUTE,
168                          "Shader");
169 
170    pipeline->binary_bo = bin_bo;
171    panfrost_bo_mmap(bin_bo);
172 
173    for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
174       const struct panvk_shader *shader = builder->shaders[i];
175       if (!shader)
176          continue;
177 
178       memcpy(pipeline->binary_bo->ptr.cpu + builder->stages[i].shader_offset,
179              util_dynarray_element(&shader->binary, uint8_t, 0),
180              util_dynarray_num_elements(&shader->binary, uint8_t));
181    }
182 
183    return VK_SUCCESS;
184 }
185 
186 static bool
panvk_pipeline_static_sysval(struct panvk_pipeline * pipeline,unsigned id)187 panvk_pipeline_static_sysval(struct panvk_pipeline *pipeline,
188                              unsigned id)
189 {
190    switch (id) {
191    case PAN_SYSVAL_VIEWPORT_SCALE:
192    case PAN_SYSVAL_VIEWPORT_OFFSET:
193       return panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT);
194    default:
195       return false;
196    }
197 }
198 
199 static void
panvk_pipeline_builder_alloc_static_state_bo(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)200 panvk_pipeline_builder_alloc_static_state_bo(struct panvk_pipeline_builder *builder,
201                                              struct panvk_pipeline *pipeline)
202 {
203    struct panfrost_device *pdev =
204       &builder->device->physical_device->pdev;
205    unsigned bo_size = 0;
206 
207    for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
208       const struct panvk_shader *shader = builder->shaders[i];
209       if (!shader)
210          continue;
211 
212       if (pipeline->fs.dynamic_rsd && i == MESA_SHADER_FRAGMENT)
213          continue;
214 
215       bo_size = ALIGN_POT(bo_size, pan_alignment(RENDERER_STATE));
216       builder->stages[i].rsd_offset = bo_size;
217       bo_size += pan_size(RENDERER_STATE);
218       if (i == MESA_SHADER_FRAGMENT)
219          bo_size += pan_size(BLEND) * MAX2(pipeline->blend.state.rt_count, 1);
220    }
221 
222    if (builder->create_info.gfx &&
223        panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT) &&
224        panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) {
225       bo_size = ALIGN_POT(bo_size, pan_alignment(VIEWPORT));
226       builder->vpd_offset = bo_size;
227       bo_size += pan_size(VIEWPORT);
228    }
229 
230    for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
231       const struct panvk_shader *shader = builder->shaders[i];
232       if (!shader || !shader->info.sysvals.sysval_count)
233          continue;
234 
235       bool static_sysvals = true;
236       for (unsigned s = 0; s < shader->info.sysvals.sysval_count; s++) {
237          unsigned id = shader->info.sysvals.sysvals[i];
238          static_sysvals &= panvk_pipeline_static_sysval(pipeline, id);
239          switch (PAN_SYSVAL_TYPE(id)) {
240          case PAN_SYSVAL_VIEWPORT_SCALE:
241          case PAN_SYSVAL_VIEWPORT_OFFSET:
242             pipeline->sysvals[i].dirty_mask |= PANVK_DYNAMIC_VIEWPORT;
243             break;
244          case PAN_SYSVAL_SSBO:
245             pipeline->sysvals[i].dirty_mask |= PANVK_DYNAMIC_SSBO;
246             break;
247          case PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS:
248             pipeline->sysvals[i].dirty_mask |= PANVK_DYNAMIC_VERTEX_INSTANCE_OFFSETS;
249             break;
250          default:
251             break;
252          }
253       }
254 
255       if (!static_sysvals) {
256          builder->stages[i].sysvals_offset = ~0;
257          continue;
258       }
259 
260       bo_size = ALIGN_POT(bo_size, 16);
261       builder->stages[i].sysvals_offset = bo_size;
262       bo_size += shader->info.sysvals.sysval_count * 16;
263    }
264 
265    if (bo_size) {
266       pipeline->state_bo =
267          panfrost_bo_create(pdev, bo_size, 0, "Pipeline descriptors");
268       panfrost_bo_mmap(pipeline->state_bo);
269    }
270 }
271 
272 static void
panvk_pipeline_builder_upload_sysval(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline,unsigned id,union panvk_sysval_data * data)273 panvk_pipeline_builder_upload_sysval(struct panvk_pipeline_builder *builder,
274                                      struct panvk_pipeline *pipeline,
275                                      unsigned id, union panvk_sysval_data *data)
276 {
277    switch (PAN_SYSVAL_TYPE(id)) {
278    case PAN_SYSVAL_VIEWPORT_SCALE:
279       panvk_sysval_upload_viewport_scale(builder->create_info.gfx->pViewportState->pViewports,
280                                          data);
281       break;
282    case PAN_SYSVAL_VIEWPORT_OFFSET:
283       panvk_sysval_upload_viewport_offset(builder->create_info.gfx->pViewportState->pViewports,
284                                           data);
285       break;
286    default:
287       unreachable("Invalid static sysval");
288    }
289 }
290 
291 static void
panvk_pipeline_builder_init_sysvals(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline,gl_shader_stage stage)292 panvk_pipeline_builder_init_sysvals(struct panvk_pipeline_builder *builder,
293                                     struct panvk_pipeline *pipeline,
294                                     gl_shader_stage stage)
295 {
296    const struct panvk_shader *shader = builder->shaders[stage];
297 
298    pipeline->sysvals[stage].ids = shader->info.sysvals;
299    pipeline->sysvals[stage].ubo_idx = shader->sysval_ubo;
300 
301    if (!shader->info.sysvals.sysval_count ||
302        builder->stages[stage].sysvals_offset == ~0)
303       return;
304 
305    union panvk_sysval_data *static_data =
306       pipeline->state_bo->ptr.cpu + builder->stages[stage].sysvals_offset;
307 
308    pipeline->sysvals[stage].ubo =
309       pipeline->state_bo->ptr.gpu + builder->stages[stage].sysvals_offset;
310 
311    for (unsigned i = 0; i < shader->info.sysvals.sysval_count; i++) {
312       unsigned id = shader->info.sysvals.sysvals[i];
313 
314       panvk_pipeline_builder_upload_sysval(builder,
315                                            pipeline,
316                                            id, &static_data[i]);
317    }
318 }
319 
320 static void
panvk_pipeline_builder_init_shaders(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)321 panvk_pipeline_builder_init_shaders(struct panvk_pipeline_builder *builder,
322                                     struct panvk_pipeline *pipeline)
323 {
324    for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
325       const struct panvk_shader *shader = builder->shaders[i];
326       if (!shader)
327          continue;
328 
329       pipeline->tls_size = MAX2(pipeline->tls_size, shader->info.tls_size);
330       pipeline->wls_size = MAX2(pipeline->wls_size, shader->info.wls_size);
331 
332       if (shader->has_img_access)
333          pipeline->img_access_mask |= BITFIELD_BIT(i);
334 
335       if (i == MESA_SHADER_VERTEX && shader->info.vs.writes_point_size)
336          pipeline->ia.writes_point_size = true;
337 
338       mali_ptr shader_ptr = pipeline->binary_bo->ptr.gpu +
339                             builder->stages[i].shader_offset;
340 
341       void *rsd = pipeline->state_bo->ptr.cpu + builder->stages[i].rsd_offset;
342       mali_ptr gpu_rsd = pipeline->state_bo->ptr.gpu + builder->stages[i].rsd_offset;
343 
344       if (i != MESA_SHADER_FRAGMENT) {
345          panvk_per_arch(emit_non_fs_rsd)(builder->device, &shader->info, shader_ptr, rsd);
346       } else if (!pipeline->fs.dynamic_rsd) {
347          void *bd = rsd + pan_size(RENDERER_STATE);
348 
349          panvk_per_arch(emit_base_fs_rsd)(builder->device, pipeline, rsd);
350          for (unsigned rt = 0; rt < MAX2(pipeline->blend.state.rt_count, 1); rt++) {
351             panvk_per_arch(emit_blend)(builder->device, pipeline, rt, bd);
352             bd += pan_size(BLEND);
353          }
354       } else {
355          gpu_rsd = 0;
356          panvk_per_arch(emit_base_fs_rsd)(builder->device, pipeline, &pipeline->fs.rsd_template);
357          for (unsigned rt = 0; rt < MAX2(pipeline->blend.state.rt_count, 1); rt++) {
358             panvk_per_arch(emit_blend)(builder->device, pipeline, rt,
359                                        &pipeline->blend.bd_template[rt]);
360          }
361       }
362 
363       pipeline->rsds[i] = gpu_rsd;
364       panvk_pipeline_builder_init_sysvals(builder, pipeline, i);
365 
366       if (i == MESA_SHADER_COMPUTE)
367          pipeline->cs.local_size = shader->local_size;
368    }
369 
370    pipeline->num_ubos = builder->layout->num_ubos + builder->layout->num_dyn_ubos;
371    for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) {
372       if (pipeline->sysvals[i].ids.sysval_count)
373          pipeline->num_ubos = MAX2(pipeline->num_ubos, pipeline->sysvals[i].ubo_idx + 1);
374    }
375 
376    pipeline->num_sysvals = 0;
377    for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++)
378       pipeline->num_sysvals += pipeline->sysvals[i].ids.sysval_count;
379 }
380 
381 
382 static void
panvk_pipeline_builder_parse_viewport(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)383 panvk_pipeline_builder_parse_viewport(struct panvk_pipeline_builder *builder,
384                                       struct panvk_pipeline *pipeline)
385 {
386    /* The spec says:
387     *
388     *    pViewportState is a pointer to an instance of the
389     *    VkPipelineViewportStateCreateInfo structure, and is ignored if the
390     *    pipeline has rasterization disabled.
391     */
392    if (!builder->rasterizer_discard &&
393        panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT) &&
394        panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) {
395       void *vpd = pipeline->state_bo->ptr.cpu + builder->vpd_offset;
396       panvk_per_arch(emit_viewport)(builder->create_info.gfx->pViewportState->pViewports,
397                                     builder->create_info.gfx->pViewportState->pScissors,
398                                     vpd);
399       pipeline->vpd = pipeline->state_bo->ptr.gpu +
400                       builder->vpd_offset;
401    }
402    if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT))
403       pipeline->viewport = builder->create_info.gfx->pViewportState->pViewports[0];
404 
405    if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR))
406       pipeline->scissor = builder->create_info.gfx->pViewportState->pScissors[0];
407 }
408 
409 static void
panvk_pipeline_builder_parse_dynamic(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)410 panvk_pipeline_builder_parse_dynamic(struct panvk_pipeline_builder *builder,
411                                      struct panvk_pipeline *pipeline)
412 {
413    const VkPipelineDynamicStateCreateInfo *dynamic_info =
414       builder->create_info.gfx->pDynamicState;
415 
416    if (!dynamic_info)
417       return;
418 
419    for (uint32_t i = 0; i < dynamic_info->dynamicStateCount; i++) {
420       VkDynamicState state = dynamic_info->pDynamicStates[i];
421       switch (state) {
422       case VK_DYNAMIC_STATE_VIEWPORT ... VK_DYNAMIC_STATE_STENCIL_REFERENCE:
423          pipeline->dynamic_state_mask |= 1 << state;
424          break;
425       default:
426          unreachable("unsupported dynamic state");
427       }
428    }
429 
430 }
431 
432 static enum mali_draw_mode
translate_prim_topology(VkPrimitiveTopology in)433 translate_prim_topology(VkPrimitiveTopology in)
434 {
435    switch (in) {
436    case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
437       return MALI_DRAW_MODE_POINTS;
438    case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
439       return MALI_DRAW_MODE_LINES;
440    case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
441       return MALI_DRAW_MODE_LINE_STRIP;
442    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
443       return MALI_DRAW_MODE_TRIANGLES;
444    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
445       return MALI_DRAW_MODE_TRIANGLE_STRIP;
446    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
447       return MALI_DRAW_MODE_TRIANGLE_FAN;
448    case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
449    case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
450    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
451    case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
452    case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
453    default:
454       unreachable("Invalid primitive type");
455    }
456 }
457 
458 static void
panvk_pipeline_builder_parse_input_assembly(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)459 panvk_pipeline_builder_parse_input_assembly(struct panvk_pipeline_builder *builder,
460                                             struct panvk_pipeline *pipeline)
461 {
462    pipeline->ia.primitive_restart =
463       builder->create_info.gfx->pInputAssemblyState->primitiveRestartEnable;
464    pipeline->ia.topology =
465       translate_prim_topology(builder->create_info.gfx->pInputAssemblyState->topology);
466 }
467 
468 static enum pipe_logicop
translate_logicop(VkLogicOp in)469 translate_logicop(VkLogicOp in)
470 {
471    switch (in) {
472    case VK_LOGIC_OP_CLEAR: return PIPE_LOGICOP_CLEAR;
473    case VK_LOGIC_OP_AND: return PIPE_LOGICOP_AND;
474    case VK_LOGIC_OP_AND_REVERSE: return PIPE_LOGICOP_AND_REVERSE;
475    case VK_LOGIC_OP_COPY: return PIPE_LOGICOP_COPY;
476    case VK_LOGIC_OP_AND_INVERTED: return PIPE_LOGICOP_AND_INVERTED;
477    case VK_LOGIC_OP_NO_OP: return PIPE_LOGICOP_NOOP;
478    case VK_LOGIC_OP_XOR: return PIPE_LOGICOP_XOR;
479    case VK_LOGIC_OP_OR: return PIPE_LOGICOP_OR;
480    case VK_LOGIC_OP_NOR: return PIPE_LOGICOP_NOR;
481    case VK_LOGIC_OP_EQUIVALENT: return PIPE_LOGICOP_EQUIV;
482    case VK_LOGIC_OP_INVERT: return PIPE_LOGICOP_INVERT;
483    case VK_LOGIC_OP_OR_REVERSE: return PIPE_LOGICOP_OR_REVERSE;
484    case VK_LOGIC_OP_COPY_INVERTED: return PIPE_LOGICOP_COPY_INVERTED;
485    case VK_LOGIC_OP_OR_INVERTED: return PIPE_LOGICOP_OR_INVERTED;
486    case VK_LOGIC_OP_NAND: return PIPE_LOGICOP_NAND;
487    case VK_LOGIC_OP_SET: return PIPE_LOGICOP_SET;
488    default: unreachable("Invalid logicop");
489    }
490 }
491 
492 static enum blend_func
translate_blend_op(VkBlendOp in)493 translate_blend_op(VkBlendOp in)
494 {
495    switch (in) {
496    case VK_BLEND_OP_ADD: return BLEND_FUNC_ADD;
497    case VK_BLEND_OP_SUBTRACT: return BLEND_FUNC_SUBTRACT;
498    case VK_BLEND_OP_REVERSE_SUBTRACT: return BLEND_FUNC_REVERSE_SUBTRACT;
499    case VK_BLEND_OP_MIN: return BLEND_FUNC_MIN;
500    case VK_BLEND_OP_MAX: return BLEND_FUNC_MAX;
501    default: unreachable("Invalid blend op");
502    }
503 }
504 
505 static enum blend_factor
translate_blend_factor(VkBlendFactor in,bool dest_has_alpha)506 translate_blend_factor(VkBlendFactor in, bool dest_has_alpha)
507 {
508    switch (in) {
509    case VK_BLEND_FACTOR_ZERO:
510    case VK_BLEND_FACTOR_ONE:
511       return BLEND_FACTOR_ZERO;
512    case VK_BLEND_FACTOR_SRC_COLOR:
513    case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
514       return BLEND_FACTOR_SRC_COLOR;
515    case VK_BLEND_FACTOR_DST_COLOR:
516    case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
517       return BLEND_FACTOR_DST_COLOR;
518    case VK_BLEND_FACTOR_SRC_ALPHA:
519    case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
520       return BLEND_FACTOR_SRC_ALPHA;
521    case VK_BLEND_FACTOR_DST_ALPHA:
522    case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
523       return dest_has_alpha ? BLEND_FACTOR_DST_ALPHA : BLEND_FACTOR_ZERO;
524    case VK_BLEND_FACTOR_CONSTANT_COLOR:
525    case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
526       return BLEND_FACTOR_CONSTANT_COLOR;
527    case VK_BLEND_FACTOR_CONSTANT_ALPHA:
528    case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
529       return BLEND_FACTOR_CONSTANT_ALPHA;
530    case VK_BLEND_FACTOR_SRC1_COLOR:
531    case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
532       return BLEND_FACTOR_SRC1_COLOR;
533    case VK_BLEND_FACTOR_SRC1_ALPHA:
534    case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
535       return BLEND_FACTOR_SRC1_ALPHA;
536    case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:
537       return BLEND_FACTOR_SRC_ALPHA_SATURATE;
538    default: unreachable("Invalid blend factor");
539    }
540 }
541 
542 static bool
inverted_blend_factor(VkBlendFactor in,bool dest_has_alpha)543 inverted_blend_factor(VkBlendFactor in, bool dest_has_alpha)
544 {
545    switch (in) {
546    case VK_BLEND_FACTOR_ONE:
547    case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
548    case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
549    case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
550    case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
551    case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
552    case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
553    case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
554       return true;
555    case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
556       return dest_has_alpha ? true : false;
557    case VK_BLEND_FACTOR_DST_ALPHA:
558       return !dest_has_alpha ? true : false;
559    default:
560       return false;
561    }
562 }
563 
564 bool
panvk_per_arch(blend_needs_lowering)565 panvk_per_arch(blend_needs_lowering)(const struct panfrost_device *dev,
566                                      const struct pan_blend_state *state,
567                                      unsigned rt)
568 {
569    /* LogicOp requires a blend shader */
570    if (state->logicop_enable)
571       return true;
572 
573    /* Not all formats can be blended by fixed-function hardware */
574    if (!panfrost_blendable_formats_v7[state->rts[rt].format].internal)
575       return true;
576 
577    unsigned constant_mask = pan_blend_constant_mask(state->rts[rt].equation);
578 
579    /* v6 doesn't support blend constants in FF blend equations.
580     * v7 only uses the constant from RT 0 (TODO: what if it's the same
581     * constant? or a constant is shared?)
582     */
583    if (constant_mask && (PAN_ARCH == 6 || (PAN_ARCH == 7 && rt > 0)))
584       return true;
585 
586    if (!pan_blend_is_homogenous_constant(constant_mask, state->constants))
587       return true;
588 
589    bool supports_2src = pan_blend_supports_2src(dev->arch);
590    return !pan_blend_can_fixed_function(state->rts[rt].equation, supports_2src);
591 }
592 
593 static void
panvk_pipeline_builder_parse_color_blend(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)594 panvk_pipeline_builder_parse_color_blend(struct panvk_pipeline_builder *builder,
595                                          struct panvk_pipeline *pipeline)
596 {
597    struct panfrost_device *pdev = &builder->device->physical_device->pdev;
598    pipeline->blend.state.logicop_enable =
599       builder->create_info.gfx->pColorBlendState->logicOpEnable;
600    pipeline->blend.state.logicop_func =
601       translate_logicop(builder->create_info.gfx->pColorBlendState->logicOp);
602    pipeline->blend.state.rt_count = util_last_bit(builder->active_color_attachments);
603    memcpy(pipeline->blend.state.constants,
604           builder->create_info.gfx->pColorBlendState->blendConstants,
605           sizeof(pipeline->blend.state.constants));
606 
607    for (unsigned i = 0; i < pipeline->blend.state.rt_count; i++) {
608       const VkPipelineColorBlendAttachmentState *in =
609          &builder->create_info.gfx->pColorBlendState->pAttachments[i];
610       struct pan_blend_rt_state *out = &pipeline->blend.state.rts[i];
611 
612       out->format = builder->color_attachment_formats[i];
613 
614       bool dest_has_alpha = util_format_has_alpha(out->format);
615 
616       out->nr_samples = builder->create_info.gfx->pMultisampleState->rasterizationSamples;
617       out->equation.blend_enable = in->blendEnable;
618       out->equation.color_mask = in->colorWriteMask;
619       out->equation.rgb_func = translate_blend_op(in->colorBlendOp);
620       out->equation.rgb_src_factor = translate_blend_factor(in->srcColorBlendFactor, dest_has_alpha);
621       out->equation.rgb_invert_src_factor = inverted_blend_factor(in->srcColorBlendFactor, dest_has_alpha);
622       out->equation.rgb_dst_factor = translate_blend_factor(in->dstColorBlendFactor, dest_has_alpha);
623       out->equation.rgb_invert_dst_factor = inverted_blend_factor(in->dstColorBlendFactor, dest_has_alpha);
624       out->equation.alpha_func = translate_blend_op(in->alphaBlendOp);
625       out->equation.alpha_src_factor = translate_blend_factor(in->srcAlphaBlendFactor, dest_has_alpha);
626       out->equation.alpha_invert_src_factor = inverted_blend_factor(in->srcAlphaBlendFactor, dest_has_alpha);
627       out->equation.alpha_dst_factor = translate_blend_factor(in->dstAlphaBlendFactor, dest_has_alpha);
628       out->equation.alpha_invert_dst_factor = inverted_blend_factor(in->dstAlphaBlendFactor, dest_has_alpha);
629 
630       pipeline->blend.reads_dest |= pan_blend_reads_dest(out->equation);
631 
632       unsigned constant_mask =
633          panvk_per_arch(blend_needs_lowering)(pdev, &pipeline->blend.state, i) ?
634          0 : pan_blend_constant_mask(out->equation);
635       pipeline->blend.constant[i].index = ffs(constant_mask) - 1;
636       if (constant_mask && PAN_ARCH >= 6) {
637          /* On Bifrost, the blend constant is expressed with a UNORM of the
638           * size of the target format. The value is then shifted such that
639           * used bits are in the MSB. Here we calculate the factor at pipeline
640           * creation time so we only have to do a
641           *   hw_constant = float_constant * factor;
642           * at descriptor emission time.
643           */
644          const struct util_format_description *format_desc =
645             util_format_description(out->format);
646          unsigned chan_size = 0;
647          for (unsigned c = 0; c < format_desc->nr_channels; c++)
648             chan_size = MAX2(format_desc->channel[c].size, chan_size);
649          pipeline->blend.constant[i].bifrost_factor =
650             ((1 << chan_size) - 1) << (16 - chan_size);
651       }
652    }
653 }
654 
655 static void
panvk_pipeline_builder_parse_multisample(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)656 panvk_pipeline_builder_parse_multisample(struct panvk_pipeline_builder *builder,
657                                          struct panvk_pipeline *pipeline)
658 {
659    unsigned nr_samples =
660       MAX2(builder->create_info.gfx->pMultisampleState->rasterizationSamples, 1);
661 
662    pipeline->ms.rast_samples =
663       builder->create_info.gfx->pMultisampleState->rasterizationSamples;
664    pipeline->ms.sample_mask =
665       builder->create_info.gfx->pMultisampleState->pSampleMask ?
666       builder->create_info.gfx->pMultisampleState->pSampleMask[0] : UINT16_MAX;
667    pipeline->ms.min_samples =
668       MAX2(builder->create_info.gfx->pMultisampleState->minSampleShading * nr_samples, 1);
669 }
670 
671 static enum mali_stencil_op
translate_stencil_op(VkStencilOp in)672 translate_stencil_op(VkStencilOp in)
673 {
674    switch (in) {
675    case VK_STENCIL_OP_KEEP: return MALI_STENCIL_OP_KEEP;
676    case VK_STENCIL_OP_ZERO: return MALI_STENCIL_OP_ZERO;
677    case VK_STENCIL_OP_REPLACE: return MALI_STENCIL_OP_REPLACE;
678    case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return MALI_STENCIL_OP_INCR_SAT;
679    case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return MALI_STENCIL_OP_DECR_SAT;
680    case VK_STENCIL_OP_INCREMENT_AND_WRAP: return MALI_STENCIL_OP_INCR_WRAP;
681    case VK_STENCIL_OP_DECREMENT_AND_WRAP: return MALI_STENCIL_OP_DECR_WRAP;
682    case VK_STENCIL_OP_INVERT: return MALI_STENCIL_OP_INVERT;
683    default: unreachable("Invalid stencil op");
684    }
685 }
686 
687 static void
panvk_pipeline_builder_parse_zs(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)688 panvk_pipeline_builder_parse_zs(struct panvk_pipeline_builder *builder,
689                                 struct panvk_pipeline *pipeline)
690 {
691    if (!builder->use_depth_stencil_attachment)
692       return;
693 
694    pipeline->zs.z_test = builder->create_info.gfx->pDepthStencilState->depthTestEnable;
695    pipeline->zs.z_write = builder->create_info.gfx->pDepthStencilState->depthWriteEnable;
696    pipeline->zs.z_compare_func =
697       panvk_per_arch(translate_compare_func)(builder->create_info.gfx->pDepthStencilState->depthCompareOp);
698    pipeline->zs.s_test = builder->create_info.gfx->pDepthStencilState->stencilTestEnable;
699    pipeline->zs.s_front.fail_op =
700       translate_stencil_op(builder->create_info.gfx->pDepthStencilState->front.failOp);
701    pipeline->zs.s_front.pass_op =
702       translate_stencil_op(builder->create_info.gfx->pDepthStencilState->front.passOp);
703    pipeline->zs.s_front.z_fail_op =
704       translate_stencil_op(builder->create_info.gfx->pDepthStencilState->front.depthFailOp);
705    pipeline->zs.s_front.compare_func =
706       panvk_per_arch(translate_compare_func)(builder->create_info.gfx->pDepthStencilState->front.compareOp);
707    pipeline->zs.s_front.compare_mask =
708       builder->create_info.gfx->pDepthStencilState->front.compareMask;
709    pipeline->zs.s_front.write_mask =
710       builder->create_info.gfx->pDepthStencilState->front.writeMask;
711    pipeline->zs.s_front.ref =
712       builder->create_info.gfx->pDepthStencilState->front.reference;
713    pipeline->zs.s_back.fail_op =
714       translate_stencil_op(builder->create_info.gfx->pDepthStencilState->back.failOp);
715    pipeline->zs.s_back.pass_op =
716       translate_stencil_op(builder->create_info.gfx->pDepthStencilState->back.passOp);
717    pipeline->zs.s_back.z_fail_op =
718       translate_stencil_op(builder->create_info.gfx->pDepthStencilState->back.depthFailOp);
719    pipeline->zs.s_back.compare_func =
720       panvk_per_arch(translate_compare_func)(builder->create_info.gfx->pDepthStencilState->back.compareOp);
721    pipeline->zs.s_back.compare_mask =
722       builder->create_info.gfx->pDepthStencilState->back.compareMask;
723    pipeline->zs.s_back.write_mask =
724       builder->create_info.gfx->pDepthStencilState->back.writeMask;
725    pipeline->zs.s_back.ref =
726       builder->create_info.gfx->pDepthStencilState->back.reference;
727 }
728 
729 static void
panvk_pipeline_builder_parse_rast(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)730 panvk_pipeline_builder_parse_rast(struct panvk_pipeline_builder *builder,
731                                   struct panvk_pipeline *pipeline)
732 {
733    pipeline->rast.clamp_depth = builder->create_info.gfx->pRasterizationState->depthClampEnable;
734    pipeline->rast.depth_bias.enable = builder->create_info.gfx->pRasterizationState->depthBiasEnable;
735    pipeline->rast.depth_bias.constant_factor =
736       builder->create_info.gfx->pRasterizationState->depthBiasConstantFactor;
737    pipeline->rast.depth_bias.clamp = builder->create_info.gfx->pRasterizationState->depthBiasClamp;
738    pipeline->rast.depth_bias.slope_factor = builder->create_info.gfx->pRasterizationState->depthBiasSlopeFactor;
739    pipeline->rast.front_ccw = builder->create_info.gfx->pRasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE;
740    pipeline->rast.cull_front_face = builder->create_info.gfx->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT;
741    pipeline->rast.cull_back_face = builder->create_info.gfx->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT;
742 }
743 
744 static bool
panvk_fs_required(struct panvk_pipeline * pipeline)745 panvk_fs_required(struct panvk_pipeline *pipeline)
746 {
747    const struct pan_shader_info *info = &pipeline->fs.info;
748 
749    /* If we generally have side effects */
750    if (info->fs.sidefx)
751       return true;
752 
753     /* If colour is written we need to execute */
754     const struct pan_blend_state *blend = &pipeline->blend.state;
755     for (unsigned i = 0; i < blend->rt_count; ++i) {
756        if (blend->rts[i].equation.color_mask)
757           return true;
758     }
759 
760     /* If depth is written and not implied we need to execute.
761      * TODO: Predicate on Z/S writes being enabled */
762     return (info->fs.writes_depth || info->fs.writes_stencil);
763 }
764 
765 #define PANVK_DYNAMIC_FS_RSD_MASK \
766         ((1 << VK_DYNAMIC_STATE_DEPTH_BIAS) | \
767          (1 << VK_DYNAMIC_STATE_BLEND_CONSTANTS) | \
768          (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) | \
769          (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) | \
770          (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE))
771 
772 static void
panvk_pipeline_builder_init_fs_state(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)773 panvk_pipeline_builder_init_fs_state(struct panvk_pipeline_builder *builder,
774                                      struct panvk_pipeline *pipeline)
775 {
776    if (!builder->shaders[MESA_SHADER_FRAGMENT])
777       return;
778 
779    pipeline->fs.dynamic_rsd =
780       pipeline->dynamic_state_mask & PANVK_DYNAMIC_FS_RSD_MASK;
781    pipeline->fs.address = pipeline->binary_bo->ptr.gpu +
782                           builder->stages[MESA_SHADER_FRAGMENT].shader_offset;
783    pipeline->fs.info = builder->shaders[MESA_SHADER_FRAGMENT]->info;
784    pipeline->fs.rt_mask = builder->active_color_attachments;
785    pipeline->fs.required = panvk_fs_required(pipeline);
786 }
787 
788 static void
panvk_pipeline_update_varying_slot(struct panvk_varyings_info * varyings,gl_shader_stage stage,const struct pan_shader_varying * varying,bool input)789 panvk_pipeline_update_varying_slot(struct panvk_varyings_info *varyings,
790                                    gl_shader_stage stage,
791                                    const struct pan_shader_varying *varying,
792                                    bool input)
793 {
794    bool fs = stage == MESA_SHADER_FRAGMENT;
795    gl_varying_slot loc = varying->location;
796    enum panvk_varying_buf_id buf_id =
797       panvk_varying_buf_id(fs, loc);
798 
799    varyings->stage[stage].loc[varyings->stage[stage].count++] = loc;
800 
801    if (panvk_varying_is_builtin(stage, loc)) {
802       varyings->buf_mask |= 1 << buf_id;
803       return;
804    }
805 
806    assert(loc < ARRAY_SIZE(varyings->varying));
807 
808    enum pipe_format new_fmt = varying->format;
809    enum pipe_format old_fmt = varyings->varying[loc].format;
810 
811    BITSET_SET(varyings->active, loc);
812 
813    /* We expect inputs to either be set by a previous stage or be built
814     * in, skip the entry if that's not the case, we'll emit a const
815     * varying returning zero for those entries.
816     */
817    if (input && old_fmt == PIPE_FORMAT_NONE)
818       return;
819 
820    unsigned new_size = util_format_get_blocksize(new_fmt);
821    unsigned old_size = util_format_get_blocksize(old_fmt);
822 
823    if (old_size < new_size)
824       varyings->varying[loc].format = new_fmt;
825 
826    varyings->buf_mask |= 1 << buf_id;
827 }
828 
829 static void
panvk_pipeline_builder_collect_varyings(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)830 panvk_pipeline_builder_collect_varyings(struct panvk_pipeline_builder *builder,
831                                         struct panvk_pipeline *pipeline)
832 {
833    for (uint32_t s = 0; s < MESA_SHADER_STAGES; s++) {
834       if (!builder->shaders[s])
835          continue;
836 
837       const struct pan_shader_info *info = &builder->shaders[s]->info;
838 
839       for (unsigned i = 0; i < info->varyings.input_count; i++) {
840          panvk_pipeline_update_varying_slot(&pipeline->varyings, s,
841                                             &info->varyings.input[i],
842                                             true);
843       }
844 
845       for (unsigned i = 0; i < info->varyings.output_count; i++) {
846          panvk_pipeline_update_varying_slot(&pipeline->varyings, s,
847                                             &info->varyings.output[i],
848                                             false);
849       }
850    }
851 
852    /* TODO: Xfb */
853    gl_varying_slot loc;
854    BITSET_FOREACH_SET(loc, pipeline->varyings.active, VARYING_SLOT_MAX) {
855       if (pipeline->varyings.varying[loc].format == PIPE_FORMAT_NONE)
856          continue;
857 
858       enum panvk_varying_buf_id buf_id =
859          panvk_varying_buf_id(false, loc);
860       unsigned buf_idx = panvk_varying_buf_index(&pipeline->varyings, buf_id);
861       unsigned varying_sz = panvk_varying_size(&pipeline->varyings, loc);
862 
863       pipeline->varyings.varying[loc].buf = buf_idx;
864       pipeline->varyings.varying[loc].offset =
865          pipeline->varyings.buf[buf_idx].stride;
866       pipeline->varyings.buf[buf_idx].stride += varying_sz;
867    }
868 }
869 
870 static void
panvk_pipeline_builder_parse_vertex_input(struct panvk_pipeline_builder * builder,struct panvk_pipeline * pipeline)871 panvk_pipeline_builder_parse_vertex_input(struct panvk_pipeline_builder *builder,
872                                           struct panvk_pipeline *pipeline)
873 {
874    struct panvk_attribs_info *attribs = &pipeline->attribs;
875    const VkPipelineVertexInputStateCreateInfo *info =
876       builder->create_info.gfx->pVertexInputState;
877 
878    const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_info =
879       vk_find_struct_const(info->pNext,
880                            PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
881 
882    for (unsigned i = 0; i < info->vertexBindingDescriptionCount; i++) {
883       const VkVertexInputBindingDescription *desc =
884          &info->pVertexBindingDescriptions[i];
885       attribs->buf_count = MAX2(desc->binding + 1, attribs->buf_count);
886       attribs->buf[desc->binding].stride = desc->stride;
887       attribs->buf[desc->binding].per_instance =
888          desc->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE;
889       attribs->buf[desc->binding].instance_divisor = 1;
890       attribs->buf[desc->binding].special = false;
891    }
892 
893    for (unsigned i = 0; i < info->vertexAttributeDescriptionCount; i++) {
894       const VkVertexInputAttributeDescription *desc =
895          &info->pVertexAttributeDescriptions[i];
896       attribs->attrib[desc->location].buf = desc->binding;
897       attribs->attrib[desc->location].format =
898          vk_format_to_pipe_format(desc->format);
899       attribs->attrib[desc->location].offset = desc->offset;
900    }
901 
902    if (div_info) {
903       for (unsigned i = 0; i < div_info->vertexBindingDivisorCount; i++) {
904          const VkVertexInputBindingDivisorDescriptionEXT *div =
905             &div_info->pVertexBindingDivisors[i];
906          attribs->buf[div->binding].instance_divisor = div->divisor;
907       }
908    }
909 
910    const struct pan_shader_info *vs =
911       &builder->shaders[MESA_SHADER_VERTEX]->info;
912 
913    if (vs->attribute_count >= PAN_VERTEX_ID) {
914       attribs->buf[attribs->buf_count].special = true;
915       attribs->buf[attribs->buf_count].special_id = PAN_VERTEX_ID;
916       attribs->attrib[PAN_VERTEX_ID].buf = attribs->buf_count++;
917       attribs->attrib[PAN_VERTEX_ID].format = PIPE_FORMAT_R32_UINT;
918    }
919 
920    if (vs->attribute_count >= PAN_INSTANCE_ID) {
921       attribs->buf[attribs->buf_count].special = true;
922       attribs->buf[attribs->buf_count].special_id = PAN_INSTANCE_ID;
923       attribs->attrib[PAN_INSTANCE_ID].buf = attribs->buf_count++;
924       attribs->attrib[PAN_INSTANCE_ID].format = PIPE_FORMAT_R32_UINT;
925    }
926 
927    attribs->attrib_count = MAX2(attribs->attrib_count, vs->attribute_count);
928 }
929 
930 static VkResult
panvk_pipeline_builder_build(struct panvk_pipeline_builder * builder,struct panvk_pipeline ** pipeline)931 panvk_pipeline_builder_build(struct panvk_pipeline_builder *builder,
932                              struct panvk_pipeline **pipeline)
933 {
934    VkResult result = panvk_pipeline_builder_create_pipeline(builder, pipeline);
935    if (result != VK_SUCCESS)
936       return result;
937 
938    /* TODO: make those functions return a result and handle errors */
939    if (builder->create_info.gfx) {
940       panvk_pipeline_builder_parse_dynamic(builder, *pipeline);
941       panvk_pipeline_builder_parse_color_blend(builder, *pipeline);
942       panvk_pipeline_builder_compile_shaders(builder, *pipeline);
943       panvk_pipeline_builder_collect_varyings(builder, *pipeline);
944       panvk_pipeline_builder_parse_input_assembly(builder, *pipeline);
945       panvk_pipeline_builder_parse_multisample(builder, *pipeline);
946       panvk_pipeline_builder_parse_zs(builder, *pipeline);
947       panvk_pipeline_builder_parse_rast(builder, *pipeline);
948       panvk_pipeline_builder_parse_vertex_input(builder, *pipeline);
949       panvk_pipeline_builder_upload_shaders(builder, *pipeline);
950       panvk_pipeline_builder_init_fs_state(builder, *pipeline);
951       panvk_pipeline_builder_alloc_static_state_bo(builder, *pipeline);
952       panvk_pipeline_builder_init_shaders(builder, *pipeline);
953       panvk_pipeline_builder_parse_viewport(builder, *pipeline);
954    } else {
955       panvk_pipeline_builder_compile_shaders(builder, *pipeline);
956       panvk_pipeline_builder_upload_shaders(builder, *pipeline);
957       panvk_pipeline_builder_alloc_static_state_bo(builder, *pipeline);
958       panvk_pipeline_builder_init_shaders(builder, *pipeline);
959    }
960 
961    return VK_SUCCESS;
962 }
963 
964 static void
panvk_pipeline_builder_init_graphics(struct panvk_pipeline_builder * builder,struct panvk_device * dev,struct panvk_pipeline_cache * cache,const VkGraphicsPipelineCreateInfo * create_info,const VkAllocationCallbacks * alloc)965 panvk_pipeline_builder_init_graphics(struct panvk_pipeline_builder *builder,
966                                      struct panvk_device *dev,
967                                      struct panvk_pipeline_cache *cache,
968                                      const VkGraphicsPipelineCreateInfo *create_info,
969                                      const VkAllocationCallbacks *alloc)
970 {
971    VK_FROM_HANDLE(panvk_pipeline_layout, layout, create_info->layout);
972    assert(layout);
973    *builder = (struct panvk_pipeline_builder) {
974       .device = dev,
975       .cache = cache,
976       .layout = layout,
977       .create_info.gfx = create_info,
978       .alloc = alloc,
979    };
980 
981    builder->rasterizer_discard =
982       create_info->pRasterizationState->rasterizerDiscardEnable;
983 
984    if (builder->rasterizer_discard) {
985       builder->samples = VK_SAMPLE_COUNT_1_BIT;
986    } else {
987       builder->samples = create_info->pMultisampleState->rasterizationSamples;
988 
989       const struct panvk_render_pass *pass = panvk_render_pass_from_handle(create_info->renderPass);
990       const struct panvk_subpass *subpass = &pass->subpasses[create_info->subpass];
991 
992       builder->use_depth_stencil_attachment =
993          subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED;
994 
995       assert(subpass->color_count <= create_info->pColorBlendState->attachmentCount);
996       builder->active_color_attachments = 0;
997       for (uint32_t i = 0; i < subpass->color_count; i++) {
998          uint32_t idx = subpass->color_attachments[i].idx;
999          if (idx == VK_ATTACHMENT_UNUSED)
1000             continue;
1001 
1002          builder->active_color_attachments |= 1 << i;
1003          builder->color_attachment_formats[i] = pass->attachments[idx].format;
1004       }
1005    }
1006 }
1007 
1008 VkResult
panvk_per_arch(CreateGraphicsPipelines)1009 panvk_per_arch(CreateGraphicsPipelines)(VkDevice device,
1010                                         VkPipelineCache pipelineCache,
1011                                         uint32_t count,
1012                                         const VkGraphicsPipelineCreateInfo *pCreateInfos,
1013                                         const VkAllocationCallbacks *pAllocator,
1014                                         VkPipeline *pPipelines)
1015 {
1016    VK_FROM_HANDLE(panvk_device, dev, device);
1017    VK_FROM_HANDLE(panvk_pipeline_cache, cache, pipelineCache);
1018 
1019    for (uint32_t i = 0; i < count; i++) {
1020       struct panvk_pipeline_builder builder;
1021       panvk_pipeline_builder_init_graphics(&builder, dev, cache,
1022                                            &pCreateInfos[i], pAllocator);
1023 
1024       struct panvk_pipeline *pipeline;
1025       VkResult result = panvk_pipeline_builder_build(&builder, &pipeline);
1026       panvk_pipeline_builder_finish(&builder);
1027 
1028       if (result != VK_SUCCESS) {
1029          for (uint32_t j = 0; j < i; j++) {
1030             panvk_DestroyPipeline(device, pPipelines[j], pAllocator);
1031             pPipelines[j] = VK_NULL_HANDLE;
1032          }
1033 
1034          return result;
1035       }
1036 
1037       pPipelines[i] = panvk_pipeline_to_handle(pipeline);
1038    }
1039 
1040    return VK_SUCCESS;
1041 }
1042 
1043 static void
panvk_pipeline_builder_init_compute(struct panvk_pipeline_builder * builder,struct panvk_device * dev,struct panvk_pipeline_cache * cache,const VkComputePipelineCreateInfo * create_info,const VkAllocationCallbacks * alloc)1044 panvk_pipeline_builder_init_compute(struct panvk_pipeline_builder *builder,
1045                                     struct panvk_device *dev,
1046                                     struct panvk_pipeline_cache *cache,
1047                                     const VkComputePipelineCreateInfo *create_info,
1048                                     const VkAllocationCallbacks *alloc)
1049 {
1050    VK_FROM_HANDLE(panvk_pipeline_layout, layout, create_info->layout);
1051    assert(layout);
1052    *builder = (struct panvk_pipeline_builder) {
1053       .device = dev,
1054       .cache = cache,
1055       .layout = layout,
1056       .create_info.compute = create_info,
1057       .alloc = alloc,
1058    };
1059 }
1060 
1061 VkResult
panvk_per_arch(CreateComputePipelines)1062 panvk_per_arch(CreateComputePipelines)(VkDevice device,
1063                                        VkPipelineCache pipelineCache,
1064                                        uint32_t count,
1065                                        const VkComputePipelineCreateInfo *pCreateInfos,
1066                                        const VkAllocationCallbacks *pAllocator,
1067                                        VkPipeline *pPipelines)
1068 {
1069    VK_FROM_HANDLE(panvk_device, dev, device);
1070    VK_FROM_HANDLE(panvk_pipeline_cache, cache, pipelineCache);
1071 
1072    for (uint32_t i = 0; i < count; i++) {
1073       struct panvk_pipeline_builder builder;
1074       panvk_pipeline_builder_init_compute(&builder, dev, cache,
1075                                           &pCreateInfos[i], pAllocator);
1076 
1077       struct panvk_pipeline *pipeline;
1078       VkResult result = panvk_pipeline_builder_build(&builder, &pipeline);
1079       panvk_pipeline_builder_finish(&builder);
1080 
1081       if (result != VK_SUCCESS) {
1082          for (uint32_t j = 0; j < i; j++) {
1083             panvk_DestroyPipeline(device, pPipelines[j], pAllocator);
1084             pPipelines[j] = VK_NULL_HANDLE;
1085          }
1086 
1087          return result;
1088       }
1089 
1090       pPipelines[i] = panvk_pipeline_to_handle(pipeline);
1091    }
1092 
1093    return VK_SUCCESS;
1094 }
1095