Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_cs.c
4560 views
1
/*
2
* Copyright (C) 2021 Collabora Ltd.
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
* DEALINGS IN THE SOFTWARE.
22
*/
23
24
#include "util/macros.h"
25
#include "compiler/shader_enums.h"
26
27
#include "panfrost-quirks.h"
28
#include "pan_cs.h"
29
#include "pan_encoder.h"
30
#include "pan_pool.h"
31
32
#include "panvk_cs.h"
33
#include "panvk_private.h"
34
#include "panvk_varyings.h"
35
36
static mali_pixel_format
37
panvk_varying_hw_format(const struct panvk_device *dev,
38
const struct panvk_varyings_info *varyings,
39
gl_shader_stage stage, unsigned idx)
40
{
41
const struct panfrost_device *pdev = &dev->physical_device->pdev;
42
gl_varying_slot loc = varyings->stage[stage].loc[idx];
43
bool fs = stage == MESA_SHADER_FRAGMENT;
44
45
switch (loc) {
46
case VARYING_SLOT_PNTC:
47
case VARYING_SLOT_PSIZ:
48
return (MALI_R16F << 12) |
49
(pdev->quirks & HAS_SWIZZLES ?
50
panfrost_get_default_swizzle(1) : 0);
51
case VARYING_SLOT_POS:
52
return ((fs ? MALI_RGBA32F : MALI_SNAP_4) << 12) |
53
(pdev->quirks & HAS_SWIZZLES ?
54
panfrost_get_default_swizzle(4) : 0);
55
default:
56
assert(!panvk_varying_is_builtin(stage, loc));
57
return pdev->formats[varyings->varying[loc].format].hw;
58
}
59
}
60
61
static void
62
panvk_emit_varying(const struct panvk_device *dev,
63
const struct panvk_varyings_info *varyings,
64
gl_shader_stage stage, unsigned idx,
65
void *attrib)
66
{
67
const struct panfrost_device *pdev = &dev->physical_device->pdev;
68
gl_varying_slot loc = varyings->stage[stage].loc[idx];
69
bool fs = stage == MESA_SHADER_FRAGMENT;
70
71
pan_pack(attrib, ATTRIBUTE, cfg) {
72
if (!panvk_varying_is_builtin(stage, loc)) {
73
cfg.buffer_index = varyings->varying[loc].buf;
74
cfg.offset = varyings->varying[loc].offset;
75
} else {
76
cfg.buffer_index =
77
panvk_varying_buf_index(varyings,
78
panvk_varying_buf_id(fs, loc));
79
}
80
cfg.offset_enable = !pan_is_bifrost(pdev);
81
cfg.format = panvk_varying_hw_format(dev, varyings, stage, idx);
82
}
83
}
84
85
void
86
panvk_emit_varyings(const struct panvk_device *dev,
87
const struct panvk_varyings_info *varyings,
88
gl_shader_stage stage,
89
void *descs)
90
{
91
struct mali_attribute_packed *attrib = descs;
92
93
for (unsigned i = 0; i < varyings->stage[stage].count; i++)
94
panvk_emit_varying(dev, varyings, stage, i, attrib++);
95
}
96
97
static void
98
panvk_emit_varying_buf(const struct panvk_device *dev,
99
const struct panvk_varyings_info *varyings,
100
enum panvk_varying_buf_id id, void *buf)
101
{
102
unsigned buf_idx = panvk_varying_buf_index(varyings, id);
103
enum mali_attribute_special special_id = panvk_varying_special_buf_id(id);
104
105
pan_pack(buf, ATTRIBUTE_BUFFER, cfg) {
106
if (special_id) {
107
cfg.type = 0;
108
cfg.special = special_id;
109
} else {
110
unsigned offset = varyings->buf[buf_idx].address & 63;
111
112
cfg.stride = varyings->buf[buf_idx].stride;
113
cfg.size = varyings->buf[buf_idx].size + offset;
114
cfg.pointer = varyings->buf[buf_idx].address & ~63ULL;
115
}
116
}
117
}
118
119
void
120
panvk_emit_varying_bufs(const struct panvk_device *dev,
121
const struct panvk_varyings_info *varyings,
122
void *descs)
123
{
124
const struct panfrost_device *pdev = &dev->physical_device->pdev;
125
struct mali_attribute_buffer_packed *buf = descs;
126
127
for (unsigned i = 0; i < PANVK_VARY_BUF_MAX; i++) {
128
if (varyings->buf_mask & (1 << i))
129
panvk_emit_varying_buf(dev, varyings, i, buf++);
130
}
131
132
if (pan_is_bifrost(pdev))
133
memset(buf, 0, sizeof(*buf));
134
}
135
136
static void
137
panvk_emit_attrib_buf(const struct panvk_device *dev,
138
const struct panvk_attribs_info *info,
139
const struct panvk_draw_info *draw,
140
const struct panvk_attrib_buf *bufs,
141
unsigned buf_count,
142
unsigned idx, void *desc)
143
{
144
ASSERTED const struct panfrost_device *pdev = &dev->physical_device->pdev;
145
const struct panvk_attrib_buf_info *buf_info = &info->buf[idx];
146
147
if (buf_info->special) {
148
assert(!pan_is_bifrost(pdev));
149
switch (buf_info->special_id) {
150
case PAN_VERTEX_ID:
151
panfrost_vertex_id(draw->padded_vertex_count, desc,
152
draw->instance_count > 1);
153
return;
154
case PAN_INSTANCE_ID:
155
panfrost_instance_id(draw->padded_vertex_count, desc,
156
draw->instance_count > 1);
157
return;
158
default:
159
unreachable("Invalid attribute ID");
160
}
161
}
162
163
assert(idx < buf_count);
164
const struct panvk_attrib_buf *buf = &bufs[idx];
165
unsigned divisor = buf_info->per_instance ?
166
draw->padded_vertex_count : 0;
167
unsigned stride = divisor && draw->instance_count == 1 ?
168
0 : buf_info->stride;
169
mali_ptr addr = buf->address & ~63ULL;
170
unsigned size = buf->size + (buf->address & 63);
171
172
/* TODO: support instanced arrays */
173
pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {
174
if (draw->instance_count > 1 && divisor) {
175
cfg.type = MALI_ATTRIBUTE_TYPE_1D_MODULUS;
176
cfg.divisor = divisor;
177
}
178
179
cfg.pointer = addr;
180
cfg.stride = stride;
181
cfg.size = size;
182
}
183
}
184
185
void
186
panvk_emit_attrib_bufs(const struct panvk_device *dev,
187
const struct panvk_attribs_info *info,
188
const struct panvk_attrib_buf *bufs,
189
unsigned buf_count,
190
const struct panvk_draw_info *draw,
191
void *descs)
192
{
193
const struct panfrost_device *pdev = &dev->physical_device->pdev;
194
struct mali_attribute_buffer_packed *buf = descs;
195
196
for (unsigned i = 0; i < info->buf_count; i++)
197
panvk_emit_attrib_buf(dev, info, draw, bufs, buf_count, i, buf++);
198
199
/* A NULL entry is needed to stop prefecting on Bifrost */
200
if (pan_is_bifrost(pdev))
201
memset(buf, 0, sizeof(*buf));
202
}
203
204
static void
205
panvk_emit_attrib(const struct panvk_device *dev,
206
const struct panvk_attribs_info *attribs,
207
const struct panvk_attrib_buf *bufs,
208
unsigned buf_count,
209
unsigned idx, void *attrib)
210
{
211
const struct panfrost_device *pdev = &dev->physical_device->pdev;
212
213
pan_pack(attrib, ATTRIBUTE, cfg) {
214
cfg.buffer_index = attribs->attrib[idx].buf;
215
cfg.offset = attribs->attrib[idx].offset +
216
(bufs[cfg.buffer_index].address & 63);
217
cfg.format = pdev->formats[attribs->attrib[idx].format].hw;
218
}
219
}
220
221
void
222
panvk_emit_attribs(const struct panvk_device *dev,
223
const struct panvk_attribs_info *attribs,
224
const struct panvk_attrib_buf *bufs,
225
unsigned buf_count,
226
void *descs)
227
{
228
struct mali_attribute_packed *attrib = descs;
229
230
for (unsigned i = 0; i < attribs->attrib_count; i++)
231
panvk_emit_attrib(dev, attribs, bufs, buf_count, i, attrib++);
232
}
233
234
void
235
panvk_emit_ubos(const struct panvk_pipeline *pipeline,
236
const struct panvk_descriptor_state *state,
237
void *descs)
238
{
239
struct mali_uniform_buffer_packed *ubos = descs;
240
241
for (unsigned i = 0; i < ARRAY_SIZE(state->sets); i++) {
242
const struct panvk_descriptor_set_layout *set_layout =
243
pipeline->layout->sets[i].layout;
244
const struct panvk_descriptor_set *set = state->sets[i].set;
245
unsigned offset = pipeline->layout->sets[i].ubo_offset;
246
247
if (!set_layout)
248
continue;
249
250
if (!set) {
251
unsigned num_ubos = (set_layout->num_dynoffsets != 0) + set_layout->num_ubos;
252
memset(&ubos[offset], 0, num_ubos * sizeof(*ubos));
253
} else {
254
memcpy(&ubos[offset], set->ubos, set_layout->num_ubos * sizeof(*ubos));
255
if (set_layout->num_dynoffsets) {
256
pan_pack(&ubos[offset + set_layout->num_ubos], UNIFORM_BUFFER, cfg) {
257
cfg.pointer = state->sets[i].dynoffsets.gpu;
258
cfg.entries = DIV_ROUND_UP(set->layout->num_dynoffsets, 16);
259
}
260
}
261
}
262
}
263
264
for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) {
265
if (!pipeline->sysvals[i].ids.sysval_count)
266
continue;
267
268
pan_pack(&ubos[pipeline->sysvals[i].ubo_idx], UNIFORM_BUFFER, cfg) {
269
cfg.pointer = pipeline->sysvals[i].ubo ? :
270
state->sysvals[i];
271
cfg.entries = pipeline->sysvals[i].ids.sysval_count;
272
}
273
}
274
}
275
276
void
277
panvk_emit_vertex_job(const struct panvk_device *dev,
278
const struct panvk_pipeline *pipeline,
279
const struct panvk_draw_info *draw,
280
void *job)
281
{
282
const struct panfrost_device *pdev = &dev->physical_device->pdev;
283
void *section = pan_section_ptr(job, COMPUTE_JOB, INVOCATION);
284
285
memcpy(section, &draw->invocation, MALI_INVOCATION_LENGTH);
286
287
pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) {
288
cfg.job_task_split = 5;
289
}
290
291
pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) {
292
cfg.draw_descriptor_is_64b = true;
293
if (!pan_is_bifrost(pdev))
294
cfg.texture_descriptor_is_64b = true;
295
cfg.state = pipeline->rsds[MESA_SHADER_VERTEX];
296
cfg.attributes = draw->stages[MESA_SHADER_VERTEX].attributes;
297
cfg.attribute_buffers = draw->attribute_bufs;
298
cfg.varyings = draw->stages[MESA_SHADER_VERTEX].varyings;
299
cfg.varying_buffers = draw->varying_bufs;
300
cfg.thread_storage = draw->tls;
301
cfg.offset_start = draw->offset_start;
302
cfg.instance_size = draw->instance_count > 1 ?
303
draw->padded_vertex_count : 1;
304
cfg.uniform_buffers = draw->ubos;
305
cfg.push_uniforms = draw->stages[PIPE_SHADER_VERTEX].push_constants;
306
cfg.textures = draw->textures;
307
cfg.samplers = draw->samplers;
308
}
309
310
pan_section_pack(job, COMPUTE_JOB, DRAW_PADDING, cfg);
311
}
312
313
void
314
panvk_emit_tiler_job(const struct panvk_device *dev,
315
const struct panvk_pipeline *pipeline,
316
const struct panvk_draw_info *draw,
317
void *job)
318
{
319
const struct panfrost_device *pdev = &dev->physical_device->pdev;
320
void *section = pan_is_bifrost(pdev) ?
321
pan_section_ptr(job, BIFROST_TILER_JOB, INVOCATION) :
322
pan_section_ptr(job, MIDGARD_TILER_JOB, INVOCATION);
323
324
memcpy(section, &draw->invocation, MALI_INVOCATION_LENGTH);
325
326
section = pan_is_bifrost(pdev) ?
327
pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE) :
328
pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE);
329
330
pan_pack(section, PRIMITIVE, cfg) {
331
cfg.draw_mode = pipeline->ia.topology;
332
if (pipeline->ia.writes_point_size)
333
cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16;
334
335
cfg.first_provoking_vertex = true;
336
if (pipeline->ia.primitive_restart)
337
cfg.primitive_restart = MALI_PRIMITIVE_RESTART_IMPLICIT;
338
cfg.job_task_split = 6;
339
/* TODO: indexed draws */
340
cfg.index_count = draw->vertex_count;
341
}
342
343
section = pan_is_bifrost(pdev) ?
344
pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE_SIZE) :
345
pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE_SIZE);
346
pan_pack(section, PRIMITIVE_SIZE, cfg) {
347
if (pipeline->ia.writes_point_size) {
348
cfg.size_array = draw->psiz;
349
} else {
350
cfg.constant = draw->line_width;
351
}
352
}
353
354
section = pan_is_bifrost(pdev) ?
355
pan_section_ptr(job, BIFROST_TILER_JOB, DRAW) :
356
pan_section_ptr(job, MIDGARD_TILER_JOB, DRAW);
357
358
pan_pack(section, DRAW, cfg) {
359
cfg.four_components_per_vertex = true;
360
cfg.draw_descriptor_is_64b = true;
361
if (!pan_is_bifrost(pdev))
362
cfg.texture_descriptor_is_64b = true;
363
cfg.front_face_ccw = pipeline->rast.front_ccw;
364
cfg.cull_front_face = pipeline->rast.cull_front_face;
365
cfg.cull_back_face = pipeline->rast.cull_back_face;
366
cfg.position = draw->position;
367
cfg.state = draw->fs_rsd;
368
cfg.attributes = draw->stages[MESA_SHADER_FRAGMENT].attributes;
369
cfg.attribute_buffers = draw->attribute_bufs;
370
cfg.viewport = draw->viewport;
371
cfg.varyings = draw->stages[MESA_SHADER_FRAGMENT].varyings;
372
cfg.varying_buffers = cfg.varyings ? draw->varying_bufs : 0;
373
if (pan_is_bifrost(pdev))
374
cfg.thread_storage = draw->tls;
375
else
376
cfg.fbd = draw->fb;
377
378
/* For all primitives but lines DRAW.flat_shading_vertex must
379
* be set to 0 and the provoking vertex is selected with the
380
* PRIMITIVE.first_provoking_vertex field.
381
*/
382
if (pipeline->ia.topology == MALI_DRAW_MODE_LINES ||
383
pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP ||
384
pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) {
385
/* The logic is inverted on bifrost. */
386
cfg.flat_shading_vertex = pan_is_bifrost(pdev) ?
387
true : false;
388
}
389
390
cfg.offset_start = draw->offset_start;
391
cfg.instance_size = draw->instance_count > 1 ?
392
draw->padded_vertex_count : 1;
393
cfg.uniform_buffers = draw->ubos;
394
cfg.push_uniforms = draw->stages[PIPE_SHADER_FRAGMENT].push_constants;
395
cfg.textures = draw->textures;
396
cfg.samplers = draw->samplers;
397
398
/* TODO: occlusion queries */
399
}
400
401
if (pan_is_bifrost(pdev)) {
402
pan_section_pack(job, BIFROST_TILER_JOB, TILER, cfg) {
403
cfg.address = draw->tiler_ctx->bifrost;
404
}
405
pan_section_pack(job, BIFROST_TILER_JOB, DRAW_PADDING, padding);
406
pan_section_pack(job, BIFROST_TILER_JOB, PADDING, padding);
407
}
408
}
409
410
void
411
panvk_emit_fragment_job(const struct panvk_device *dev,
412
const struct panvk_framebuffer *fb,
413
mali_ptr fbdesc,
414
void *job)
415
{
416
pan_section_pack(job, FRAGMENT_JOB, HEADER, header) {
417
header.type = MALI_JOB_TYPE_FRAGMENT;
418
header.index = 1;
419
}
420
421
pan_section_pack(job, FRAGMENT_JOB, PAYLOAD, payload) {
422
payload.bound_min_x = 0;
423
payload.bound_min_y = 0;
424
425
payload.bound_max_x = (fb->width - 1) >> MALI_TILE_SHIFT;
426
payload.bound_max_y = (fb->height - 1) >> MALI_TILE_SHIFT;
427
payload.framebuffer = fbdesc;
428
}
429
}
430
431
void
432
panvk_emit_viewport(const VkViewport *viewport, const VkRect2D *scissor,
433
void *vpd)
434
{
435
/* The spec says "width must be greater than 0.0" */
436
assert(viewport->x >= 0);
437
int minx = (int)viewport->x;
438
int maxx = (int)(viewport->x + viewport->width);
439
440
/* Viewport height can be negative */
441
int miny = MIN2((int)viewport->y, (int)(viewport->y + viewport->height));
442
int maxy = MAX2((int)viewport->y, (int)(viewport->y + viewport->height));
443
444
assert(scissor->offset.x >= 0 && scissor->offset.y >= 0);
445
miny = MAX2(scissor->offset.x, minx);
446
miny = MAX2(scissor->offset.y, miny);
447
maxx = MIN2(scissor->offset.x + scissor->extent.width, maxx);
448
maxy = MIN2(scissor->offset.y + scissor->extent.height, maxy);
449
450
/* Make sure we don't end up with a max < min when width/height is 0 */
451
maxx = maxx > minx ? maxx - 1 : maxx;
452
maxy = maxy > miny ? maxy - 1 : maxy;
453
454
assert(viewport->minDepth >= 0.0f && viewport->minDepth <= 1.0f);
455
assert(viewport->maxDepth >= 0.0f && viewport->maxDepth <= 1.0f);
456
457
pan_pack(vpd, VIEWPORT, cfg) {
458
cfg.scissor_minimum_x = minx;
459
cfg.scissor_minimum_y = miny;
460
cfg.scissor_maximum_x = maxx;
461
cfg.scissor_maximum_y = maxy;
462
cfg.minimum_z = MIN2(viewport->minDepth, viewport->maxDepth);
463
cfg.maximum_z = MAX2(viewport->minDepth, viewport->maxDepth);
464
}
465
}
466
467
void
468
panvk_sysval_upload_viewport_scale(const VkViewport *viewport,
469
union panvk_sysval_data *data)
470
{
471
data->f32[0] = 0.5f * viewport->width;
472
data->f32[1] = 0.5f * viewport->height;
473
data->f32[2] = 0.5f * (viewport->maxDepth - viewport->minDepth);
474
}
475
476
void
477
panvk_sysval_upload_viewport_offset(const VkViewport *viewport,
478
union panvk_sysval_data *data)
479
{
480
data->f32[0] = (0.5f * viewport->width) + viewport->x;
481
data->f32[1] = (0.5f * viewport->height) + viewport->y;
482
data->f32[2] = (0.5f * (viewport->maxDepth - viewport->minDepth)) + viewport->minDepth;
483
}
484
485
static enum mali_bifrost_register_file_format
486
bifrost_blend_type_from_nir(nir_alu_type nir_type)
487
{
488
switch(nir_type) {
489
case 0: /* Render target not in use */
490
return 0;
491
case nir_type_float16:
492
return MALI_BIFROST_REGISTER_FILE_FORMAT_F16;
493
case nir_type_float32:
494
return MALI_BIFROST_REGISTER_FILE_FORMAT_F32;
495
case nir_type_int32:
496
return MALI_BIFROST_REGISTER_FILE_FORMAT_I32;
497
case nir_type_uint32:
498
return MALI_BIFROST_REGISTER_FILE_FORMAT_U32;
499
case nir_type_int16:
500
return MALI_BIFROST_REGISTER_FILE_FORMAT_I16;
501
case nir_type_uint16:
502
return MALI_BIFROST_REGISTER_FILE_FORMAT_U16;
503
default:
504
unreachable("Unsupported blend shader type for NIR alu type");
505
}
506
}
507
508
static void
509
panvk_emit_bifrost_blend(const struct panvk_device *dev,
510
const struct panvk_pipeline *pipeline,
511
unsigned rt, void *bd)
512
{
513
const struct pan_blend_state *blend = &pipeline->blend.state;
514
const struct panfrost_device *pdev = &dev->physical_device->pdev;
515
const struct pan_blend_rt_state *rts = &blend->rts[rt];
516
517
pan_pack(bd, BLEND, cfg) {
518
if (!blend->rt_count || !rts->equation.color_mask) {
519
cfg.enable = false;
520
cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OFF;
521
continue;
522
}
523
524
cfg.srgb = util_format_is_srgb(rts->format);
525
cfg.load_destination = pan_blend_reads_dest(blend->rts[rt].equation);
526
cfg.round_to_fb_precision = true;
527
528
const struct util_format_description *format_desc =
529
util_format_description(rts->format);
530
unsigned chan_size = 0;
531
for (unsigned i = 0; i < format_desc->nr_channels; i++)
532
chan_size = MAX2(format_desc->channel[0].size, chan_size);
533
534
pan_blend_to_fixed_function_equation(blend->rts[rt].equation,
535
&cfg.bifrost.equation);
536
537
/* Fixed point constant */
538
float fconst =
539
pan_blend_get_constant(pan_blend_constant_mask(blend->rts[rt].equation),
540
blend->constants);
541
u16 constant = fconst * ((1 << chan_size) - 1);
542
constant <<= 16 - chan_size;
543
cfg.bifrost.constant = constant;
544
545
if (pan_blend_is_opaque(blend->rts[rt].equation))
546
cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OPAQUE;
547
else
548
cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_FIXED_FUNCTION;
549
550
/* If we want the conversion to work properly,
551
* num_comps must be set to 4
552
*/
553
cfg.bifrost.internal.fixed_function.num_comps = 4;
554
cfg.bifrost.internal.fixed_function.conversion.memory_format =
555
panfrost_format_to_bifrost_blend(pdev, rts->format);
556
cfg.bifrost.internal.fixed_function.conversion.register_format =
557
bifrost_blend_type_from_nir(pipeline->fs.info.bifrost.blend[rt].type);
558
cfg.bifrost.internal.fixed_function.rt = rt;
559
}
560
}
561
562
static void
563
panvk_emit_midgard_blend(const struct panvk_device *dev,
564
const struct panvk_pipeline *pipeline,
565
unsigned rt, void *bd)
566
{
567
const struct pan_blend_state *blend = &pipeline->blend.state;
568
const struct pan_blend_rt_state *rts = &blend->rts[rt];
569
570
pan_pack(bd, BLEND, cfg) {
571
if (!blend->rt_count || !rts->equation.color_mask) {
572
cfg.enable = false;
573
continue;
574
}
575
576
cfg.srgb = util_format_is_srgb(rts->format);
577
cfg.load_destination = pan_blend_reads_dest(blend->rts[rt].equation);
578
cfg.round_to_fb_precision = true;
579
cfg.midgard.blend_shader = false;
580
pan_blend_to_fixed_function_equation(blend->rts[rt].equation,
581
&cfg.midgard.equation);
582
cfg.midgard.constant =
583
pan_blend_get_constant(pan_blend_constant_mask(blend->rts[rt].equation),
584
blend->constants);
585
}
586
}
587
588
void
589
panvk_emit_blend(const struct panvk_device *dev,
590
const struct panvk_pipeline *pipeline,
591
unsigned rt, void *bd)
592
{
593
const struct panfrost_device *pdev = &dev->physical_device->pdev;
594
595
if (pan_is_bifrost(pdev))
596
panvk_emit_bifrost_blend(dev, pipeline, rt, bd);
597
else
598
panvk_emit_midgard_blend(dev, pipeline, rt, bd);
599
}
600
601
void
602
panvk_emit_blend_constant(const struct panvk_device *dev,
603
const struct panvk_pipeline *pipeline,
604
unsigned rt, const float *constants, void *bd)
605
{
606
const struct panfrost_device *pdev = &dev->physical_device->pdev;
607
float constant = constants[pipeline->blend.constant[rt].index];
608
609
pan_pack(bd, BLEND, cfg) {
610
cfg.enable = false;
611
if (pan_is_bifrost(pdev)) {
612
cfg.bifrost.constant = constant * pipeline->blend.constant[rt].bifrost_factor;
613
} else {
614
cfg.midgard.constant = constant;
615
}
616
}
617
}
618
619
void
620
panvk_emit_dyn_fs_rsd(const struct panvk_device *dev,
621
const struct panvk_pipeline *pipeline,
622
const struct panvk_cmd_state *state,
623
void *rsd)
624
{
625
pan_pack(rsd, RENDERER_STATE, cfg) {
626
if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS)) {
627
cfg.depth_units = state->rast.depth_bias.constant_factor * 2.0f;
628
cfg.depth_factor = state->rast.depth_bias.slope_factor;
629
cfg.depth_bias_clamp = state->rast.depth_bias.clamp;
630
}
631
632
if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK)) {
633
cfg.stencil_front.mask = state->zs.s_front.compare_mask;
634
cfg.stencil_back.mask = state->zs.s_back.compare_mask;
635
}
636
637
if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) {
638
cfg.stencil_mask_misc.stencil_mask_front = state->zs.s_front.write_mask;
639
cfg.stencil_mask_misc.stencil_mask_back = state->zs.s_back.write_mask;
640
}
641
642
if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) {
643
cfg.stencil_front.reference_value = state->zs.s_front.ref;
644
cfg.stencil_back.reference_value = state->zs.s_back.ref;
645
}
646
}
647
}
648
649
void
650
panvk_emit_base_fs_rsd(const struct panvk_device *dev,
651
const struct panvk_pipeline *pipeline,
652
void *rsd)
653
{
654
const struct panfrost_device *pdev = &dev->physical_device->pdev;
655
const struct pan_shader_info *info = &pipeline->fs.info;
656
657
pan_pack(rsd, RENDERER_STATE, cfg) {
658
if (pipeline->fs.required) {
659
pan_shader_prepare_rsd(pdev, info, pipeline->fs.address, &cfg);
660
if (pan_is_bifrost(pdev)) {
661
cfg.properties.bifrost.allow_forward_pixel_to_kill = info->fs.can_fpk;
662
} else {
663
/* If either depth or stencil is enabled, discard matters */
664
bool zs_enabled =
665
(pipeline->zs.z_test && pipeline->zs.z_compare_func != MALI_FUNC_ALWAYS) ||
666
pipeline->zs.s_test;
667
668
cfg.properties.midgard.work_register_count = info->work_reg_count;
669
cfg.properties.midgard.force_early_z =
670
info->fs.can_early_z && !pipeline->ms.alpha_to_coverage &&
671
pipeline->zs.z_compare_func == MALI_FUNC_ALWAYS;
672
673
674
/* Workaround a hardware errata where early-z cannot be enabled
675
* when discarding even when the depth buffer is read-only, by
676
* lying to the hardware about the discard and setting the
677
* reads tilebuffer? flag to compensate */
678
cfg.properties.midgard.shader_reads_tilebuffer =
679
info->fs.outputs_read ||
680
(!zs_enabled && info->fs.can_discard);
681
cfg.properties.midgard.shader_contains_discard =
682
zs_enabled && info->fs.can_discard;
683
}
684
} else {
685
if (pan_is_bifrost(pdev)) {
686
cfg.properties.bifrost.shader_modifies_coverage = true;
687
cfg.properties.bifrost.allow_forward_pixel_to_kill = true;
688
cfg.properties.bifrost.allow_forward_pixel_to_be_killed = true;
689
cfg.properties.bifrost.zs_update_operation = MALI_PIXEL_KILL_STRONG_EARLY;
690
} else {
691
cfg.shader.shader = 0x1;
692
cfg.properties.midgard.work_register_count = 1;
693
cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION;
694
cfg.properties.midgard.force_early_z = true;
695
}
696
}
697
698
bool msaa = pipeline->ms.rast_samples > 1;
699
cfg.multisample_misc.multisample_enable = msaa;
700
cfg.multisample_misc.sample_mask =
701
msaa ? pipeline->ms.sample_mask : UINT16_MAX;
702
703
cfg.multisample_misc.depth_function =
704
pipeline->zs.z_test ? pipeline->zs.z_compare_func : MALI_FUNC_ALWAYS;
705
706
cfg.multisample_misc.depth_write_mask = pipeline->zs.z_write;
707
cfg.multisample_misc.fixed_function_near_discard = !pipeline->rast.clamp_depth;
708
cfg.multisample_misc.fixed_function_far_discard = !pipeline->rast.clamp_depth;
709
cfg.multisample_misc.shader_depth_range_fixed = true;
710
711
cfg.stencil_mask_misc.stencil_enable = pipeline->zs.s_test;
712
cfg.stencil_mask_misc.alpha_to_coverage = pipeline->ms.alpha_to_coverage;
713
cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS;
714
cfg.stencil_mask_misc.depth_range_1 = pipeline->rast.depth_bias.enable;
715
cfg.stencil_mask_misc.depth_range_2 = pipeline->rast.depth_bias.enable;
716
cfg.stencil_mask_misc.single_sampled_lines = pipeline->ms.rast_samples <= 1;
717
718
if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS))) {
719
cfg.depth_units = pipeline->rast.depth_bias.constant_factor * 2.0f;
720
cfg.depth_factor = pipeline->rast.depth_bias.slope_factor;
721
cfg.depth_bias_clamp = pipeline->rast.depth_bias.clamp;
722
}
723
724
if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK))) {
725
cfg.stencil_front.mask = pipeline->zs.s_front.compare_mask;
726
cfg.stencil_back.mask = pipeline->zs.s_back.compare_mask;
727
}
728
729
if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK))) {
730
cfg.stencil_mask_misc.stencil_mask_front = pipeline->zs.s_front.write_mask;
731
cfg.stencil_mask_misc.stencil_mask_back = pipeline->zs.s_back.write_mask;
732
}
733
734
if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE))) {
735
cfg.stencil_front.reference_value = pipeline->zs.s_front.ref;
736
cfg.stencil_back.reference_value = pipeline->zs.s_back.ref;
737
}
738
739
cfg.stencil_front.compare_function = pipeline->zs.s_front.compare_func;
740
cfg.stencil_front.stencil_fail = pipeline->zs.s_front.fail_op;
741
cfg.stencil_front.depth_fail = pipeline->zs.s_front.z_fail_op;
742
cfg.stencil_front.depth_pass = pipeline->zs.s_front.pass_op;
743
cfg.stencil_back.compare_function = pipeline->zs.s_back.compare_func;
744
cfg.stencil_back.stencil_fail = pipeline->zs.s_back.fail_op;
745
cfg.stencil_back.depth_fail = pipeline->zs.s_back.z_fail_op;
746
cfg.stencil_back.depth_pass = pipeline->zs.s_back.pass_op;
747
}
748
}
749
750
void
751
panvk_emit_non_fs_rsd(const struct panvk_device *dev,
752
const struct pan_shader_info *shader_info,
753
mali_ptr shader_ptr,
754
void *rsd)
755
{
756
const struct panfrost_device *pdev = &dev->physical_device->pdev;
757
758
assert(shader_info->stage != MESA_SHADER_FRAGMENT);
759
760
pan_pack(rsd, RENDERER_STATE, cfg) {
761
pan_shader_prepare_rsd(pdev, shader_info, shader_ptr, &cfg);
762
}
763
}
764
765
void
766
panvk_emit_bifrost_tiler_context(const struct panvk_device *dev,
767
unsigned width, unsigned height,
768
const struct panfrost_ptr *descs)
769
{
770
const struct panfrost_device *pdev = &dev->physical_device->pdev;
771
772
pan_pack(descs->cpu + MALI_BIFROST_TILER_LENGTH, BIFROST_TILER_HEAP, cfg) {
773
cfg.size = pdev->tiler_heap->size;
774
cfg.base = pdev->tiler_heap->ptr.gpu;
775
cfg.bottom = pdev->tiler_heap->ptr.gpu;
776
cfg.top = pdev->tiler_heap->ptr.gpu + pdev->tiler_heap->size;
777
}
778
779
pan_pack(descs->cpu, BIFROST_TILER, cfg) {
780
cfg.hierarchy_mask = 0x28;
781
cfg.fb_width = width;
782
cfg.fb_height = height;
783
cfg.heap = descs->gpu + MALI_BIFROST_TILER_LENGTH;
784
}
785
}
786
787
unsigned
788
panvk_emit_fb(const struct panvk_device *dev,
789
const struct panvk_batch *batch,
790
const struct panvk_subpass *subpass,
791
const struct panvk_pipeline *pipeline,
792
const struct panvk_framebuffer *fb,
793
const struct panvk_clear_value *clears,
794
const struct pan_tls_info *tlsinfo,
795
const struct pan_tiler_context *tilerctx,
796
void *desc)
797
{
798
const struct panfrost_device *pdev = &dev->physical_device->pdev;
799
struct panvk_image_view *view;
800
bool crc_valid[8] = { false };
801
struct pan_fb_info fbinfo = {
802
.width = fb->width,
803
.height = fb->height,
804
.extent.maxx = fb->width - 1,
805
.extent.maxy = fb->height - 1,
806
.nr_samples = 1,
807
};
808
809
for (unsigned cb = 0; cb < subpass->color_count; cb++) {
810
int idx = subpass->color_attachments[cb].idx;
811
view = idx != VK_ATTACHMENT_UNUSED ?
812
fb->attachments[idx].iview : NULL;
813
if (!view)
814
continue;
815
fbinfo.rts[cb].view = &view->pview;
816
fbinfo.rts[cb].clear = subpass->color_attachments[idx].clear;
817
fbinfo.rts[cb].crc_valid = &crc_valid[cb];
818
819
memcpy(fbinfo.rts[cb].clear_value, clears[idx].color,
820
sizeof(fbinfo.rts[cb].clear_value));
821
fbinfo.nr_samples =
822
MAX2(fbinfo.nr_samples, view->pview.image->layout.nr_samples);
823
}
824
825
if (subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED) {
826
view = fb->attachments[subpass->zs_attachment.idx].iview;
827
const struct util_format_description *fdesc =
828
util_format_description(view->pview.format);
829
830
fbinfo.nr_samples =
831
MAX2(fbinfo.nr_samples, view->pview.image->layout.nr_samples);
832
833
if (util_format_has_depth(fdesc)) {
834
fbinfo.zs.clear.z = subpass->zs_attachment.clear;
835
fbinfo.zs.clear_value.depth = clears[subpass->zs_attachment.idx].depth;
836
fbinfo.zs.view.zs = &view->pview;
837
}
838
839
if (util_format_has_depth(fdesc)) {
840
fbinfo.zs.clear.s = subpass->zs_attachment.clear;
841
fbinfo.zs.clear_value.stencil = clears[subpass->zs_attachment.idx].depth;
842
if (!fbinfo.zs.view.zs)
843
fbinfo.zs.view.s = &view->pview;
844
}
845
}
846
847
return pan_emit_fbd(pdev, &fbinfo, tlsinfo, tilerctx, desc);
848
}
849
850