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