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