Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/lima/lima_draw.c
4565 views
1
/*
2
* Copyright (c) 2011-2013 Luc Verhaegen <[email protected]>
3
* Copyright (c) 2017-2019 Lima Project
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sub license,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the
13
* next paragraph) shall be included in all copies or substantial portions
14
* of the Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
* DEALINGS IN THE SOFTWARE.
23
*
24
*/
25
26
#include "util/format/u_format.h"
27
#include "util/u_debug.h"
28
#include "util/u_draw.h"
29
#include "util/half_float.h"
30
#include "util/u_helpers.h"
31
#include "util/u_inlines.h"
32
#include "util/u_pack_color.h"
33
#include "util/u_split_draw.h"
34
#include "util/u_upload_mgr.h"
35
#include "util/u_prim.h"
36
#include "util/u_vbuf.h"
37
#include "util/hash_table.h"
38
39
#include "lima_context.h"
40
#include "lima_screen.h"
41
#include "lima_resource.h"
42
#include "lima_program.h"
43
#include "lima_bo.h"
44
#include "lima_job.h"
45
#include "lima_texture.h"
46
#include "lima_util.h"
47
#include "lima_gpu.h"
48
49
#include "pan_minmax_cache.h"
50
51
#include <drm-uapi/lima_drm.h>
52
53
static void
54
lima_clip_scissor_to_viewport(struct lima_context *ctx)
55
{
56
struct lima_context_framebuffer *fb = &ctx->framebuffer;
57
struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
58
int viewport_left, viewport_right, viewport_bottom, viewport_top;
59
60
if (ctx->rasterizer && ctx->rasterizer->base.scissor) {
61
struct pipe_scissor_state *scissor = &ctx->scissor;
62
cscissor->minx = scissor->minx;
63
cscissor->maxx = scissor->maxx;
64
cscissor->miny = scissor->miny;
65
cscissor->maxy = scissor->maxy;
66
} else {
67
cscissor->minx = 0;
68
cscissor->maxx = fb->base.width;
69
cscissor->miny = 0;
70
cscissor->maxy = fb->base.height;
71
}
72
73
viewport_left = MAX2(ctx->viewport.left, 0);
74
cscissor->minx = MAX2(cscissor->minx, viewport_left);
75
viewport_right = MIN2(MAX2(ctx->viewport.right, 0), fb->base.width);
76
cscissor->maxx = MIN2(cscissor->maxx, viewport_right);
77
if (cscissor->minx > cscissor->maxx)
78
cscissor->minx = cscissor->maxx;
79
80
viewport_bottom = MAX2(ctx->viewport.bottom, 0);
81
cscissor->miny = MAX2(cscissor->miny, viewport_bottom);
82
viewport_top = MIN2(MAX2(ctx->viewport.top, 0), fb->base.height);
83
cscissor->maxy = MIN2(cscissor->maxy, viewport_top);
84
if (cscissor->miny > cscissor->maxy)
85
cscissor->miny = cscissor->maxy;
86
}
87
88
static bool
89
lima_is_scissor_zero(struct lima_context *ctx)
90
{
91
struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
92
93
return cscissor->minx == cscissor->maxx || cscissor->miny == cscissor->maxy;
94
}
95
96
static void
97
lima_update_job_wb(struct lima_context *ctx, unsigned buffers)
98
{
99
struct lima_job *job = lima_job_get(ctx);
100
struct lima_context_framebuffer *fb = &ctx->framebuffer;
101
102
/* add to job when the buffer is dirty and resolve is clear (not added before) */
103
if (fb->base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0) &&
104
!(job->resolve & PIPE_CLEAR_COLOR0)) {
105
struct lima_resource *res = lima_resource(fb->base.cbufs[0]->texture);
106
lima_flush_job_accessing_bo(ctx, res->bo, true);
107
_mesa_hash_table_insert(ctx->write_jobs, &res->base, job);
108
lima_job_add_bo(job, LIMA_PIPE_PP, res->bo, LIMA_SUBMIT_BO_WRITE);
109
}
110
111
/* add to job when the buffer is dirty and resolve is clear (not added before) */
112
if (fb->base.zsbuf && (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) &&
113
!(job->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
114
struct lima_resource *res = lima_resource(fb->base.zsbuf->texture);
115
lima_flush_job_accessing_bo(ctx, res->bo, true);
116
_mesa_hash_table_insert(ctx->write_jobs, &res->base, job);
117
lima_job_add_bo(job, LIMA_PIPE_PP, res->bo, LIMA_SUBMIT_BO_WRITE);
118
}
119
120
job->resolve |= buffers;
121
}
122
123
static void
124
lima_damage_rect_union(struct pipe_scissor_state *rect,
125
unsigned minx, unsigned maxx,
126
unsigned miny, unsigned maxy)
127
{
128
rect->minx = MIN2(rect->minx, minx);
129
rect->miny = MIN2(rect->miny, miny);
130
rect->maxx = MAX2(rect->maxx, maxx);
131
rect->maxy = MAX2(rect->maxy, maxy);
132
}
133
134
static void
135
lima_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
136
const union pipe_color_union *color, double depth, unsigned stencil)
137
{
138
struct lima_context *ctx = lima_context(pctx);
139
struct lima_job *job = lima_job_get(ctx);
140
141
/* flush if this job already contains any draw, otherwise multi clear can be
142
* combined into a single job */
143
if (lima_job_has_draw_pending(job)) {
144
lima_do_job(job);
145
job = lima_job_get(ctx);
146
}
147
148
lima_update_job_wb(ctx, buffers);
149
150
/* no need to reload if cleared */
151
if (ctx->framebuffer.base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0)) {
152
struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]);
153
surf->reload &= ~PIPE_CLEAR_COLOR0;
154
}
155
156
struct lima_job_clear *clear = &job->clear;
157
clear->buffers = buffers;
158
159
if (buffers & PIPE_CLEAR_COLOR0) {
160
clear->color_8pc =
161
((uint32_t)float_to_ubyte(color->f[3]) << 24) |
162
((uint32_t)float_to_ubyte(color->f[2]) << 16) |
163
((uint32_t)float_to_ubyte(color->f[1]) << 8) |
164
float_to_ubyte(color->f[0]);
165
166
clear->color_16pc =
167
((uint64_t)float_to_ushort(color->f[3]) << 48) |
168
((uint64_t)float_to_ushort(color->f[2]) << 32) |
169
((uint64_t)float_to_ushort(color->f[1]) << 16) |
170
float_to_ushort(color->f[0]);
171
}
172
173
struct lima_surface *zsbuf = lima_surface(ctx->framebuffer.base.zsbuf);
174
175
if (buffers & PIPE_CLEAR_DEPTH) {
176
clear->depth = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, depth);
177
if (zsbuf)
178
zsbuf->reload &= ~PIPE_CLEAR_DEPTH;
179
}
180
181
if (buffers & PIPE_CLEAR_STENCIL) {
182
clear->stencil = stencil;
183
if (zsbuf)
184
zsbuf->reload &= ~PIPE_CLEAR_STENCIL;
185
}
186
187
ctx->dirty |= LIMA_CONTEXT_DIRTY_CLEAR;
188
189
lima_damage_rect_union(&job->damage_rect,
190
0, ctx->framebuffer.base.width,
191
0, ctx->framebuffer.base.height);
192
}
193
194
enum lima_attrib_type {
195
LIMA_ATTRIB_FLOAT = 0x000,
196
LIMA_ATTRIB_I32 = 0x001,
197
LIMA_ATTRIB_U32 = 0x002,
198
LIMA_ATTRIB_FP16 = 0x003,
199
LIMA_ATTRIB_I16 = 0x004,
200
LIMA_ATTRIB_U16 = 0x005,
201
LIMA_ATTRIB_I8 = 0x006,
202
LIMA_ATTRIB_U8 = 0x007,
203
LIMA_ATTRIB_I8N = 0x008,
204
LIMA_ATTRIB_U8N = 0x009,
205
LIMA_ATTRIB_I16N = 0x00A,
206
LIMA_ATTRIB_U16N = 0x00B,
207
LIMA_ATTRIB_I32N = 0x00D,
208
LIMA_ATTRIB_U32N = 0x00E,
209
LIMA_ATTRIB_FIXED = 0x101
210
};
211
212
static enum lima_attrib_type
213
lima_pipe_format_to_attrib_type(enum pipe_format format)
214
{
215
const struct util_format_description *desc = util_format_description(format);
216
int i = util_format_get_first_non_void_channel(format);
217
const struct util_format_channel_description *c = desc->channel + i;
218
219
switch (c->type) {
220
case UTIL_FORMAT_TYPE_FLOAT:
221
if (c->size == 16)
222
return LIMA_ATTRIB_FP16;
223
else
224
return LIMA_ATTRIB_FLOAT;
225
case UTIL_FORMAT_TYPE_FIXED:
226
return LIMA_ATTRIB_FIXED;
227
case UTIL_FORMAT_TYPE_SIGNED:
228
if (c->size == 8) {
229
if (c->normalized)
230
return LIMA_ATTRIB_I8N;
231
else
232
return LIMA_ATTRIB_I8;
233
}
234
else if (c->size == 16) {
235
if (c->normalized)
236
return LIMA_ATTRIB_I16N;
237
else
238
return LIMA_ATTRIB_I16;
239
}
240
else if (c->size == 32) {
241
if (c->normalized)
242
return LIMA_ATTRIB_I32N;
243
else
244
return LIMA_ATTRIB_I32;
245
}
246
break;
247
case UTIL_FORMAT_TYPE_UNSIGNED:
248
if (c->size == 8) {
249
if (c->normalized)
250
return LIMA_ATTRIB_U8N;
251
else
252
return LIMA_ATTRIB_U8;
253
}
254
else if (c->size == 16) {
255
if (c->normalized)
256
return LIMA_ATTRIB_U16N;
257
else
258
return LIMA_ATTRIB_U16;
259
}
260
else if (c->size == 32) {
261
if (c->normalized)
262
return LIMA_ATTRIB_U32N;
263
else
264
return LIMA_ATTRIB_U32;
265
}
266
break;
267
}
268
269
return LIMA_ATTRIB_FLOAT;
270
}
271
272
static void
273
lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
274
const struct pipe_draw_start_count_bias *draw)
275
{
276
struct lima_context_constant_buffer *ccb =
277
ctx->const_buffer + PIPE_SHADER_VERTEX;
278
struct lima_vs_compiled_shader *vs = ctx->vs;
279
struct lima_job *job = lima_job_get(ctx);
280
281
VS_CMD_BEGIN(&job->vs_cmd_array, 24);
282
283
if (!info->index_size) {
284
VS_CMD_ARRAYS_SEMAPHORE_BEGIN_1();
285
VS_CMD_ARRAYS_SEMAPHORE_BEGIN_2();
286
}
287
int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
288
289
int size = uniform_size + vs->state.constant_size + 32;
290
VS_CMD_UNIFORMS_ADDRESS(
291
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform),
292
align(size, 16));
293
294
VS_CMD_SHADER_ADDRESS(ctx->vs->bo->va, ctx->vs->state.shader_size);
295
VS_CMD_SHADER_INFO(ctx->vs->state.prefetch, ctx->vs->state.shader_size);
296
297
int num_outputs = ctx->vs->state.num_outputs;
298
int num_attributes = ctx->vertex_elements->num_elements;
299
VS_CMD_VARYING_ATTRIBUTE_COUNT(num_outputs, MAX2(1, num_attributes));
300
301
VS_CMD_UNKNOWN1();
302
303
VS_CMD_ATTRIBUTES_ADDRESS(
304
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info),
305
MAX2(1, num_attributes));
306
307
VS_CMD_VARYINGS_ADDRESS(
308
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info),
309
num_outputs);
310
311
unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
312
VS_CMD_DRAW(num, info->index_size);
313
314
VS_CMD_UNKNOWN2();
315
316
VS_CMD_ARRAYS_SEMAPHORE_END(info->index_size);
317
318
VS_CMD_END();
319
}
320
321
static void
322
lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info,
323
const struct pipe_draw_start_count_bias *draw)
324
{
325
struct lima_vs_compiled_shader *vs = ctx->vs;
326
struct pipe_scissor_state *cscissor = &ctx->clipped_scissor;
327
struct lima_job *job = lima_job_get(ctx);
328
PLBU_CMD_BEGIN(&job->plbu_cmd_array, 32);
329
330
PLBU_CMD_VIEWPORT_LEFT(fui(ctx->viewport.left));
331
PLBU_CMD_VIEWPORT_RIGHT(fui(ctx->viewport.right));
332
PLBU_CMD_VIEWPORT_BOTTOM(fui(ctx->viewport.bottom));
333
PLBU_CMD_VIEWPORT_TOP(fui(ctx->viewport.top));
334
335
if (!info->index_size)
336
PLBU_CMD_ARRAYS_SEMAPHORE_BEGIN();
337
338
int cf = ctx->rasterizer->base.cull_face;
339
int ccw = ctx->rasterizer->base.front_ccw;
340
uint32_t cull = 0;
341
bool force_point_size = false;
342
343
if (cf != PIPE_FACE_NONE) {
344
if (cf & PIPE_FACE_FRONT)
345
cull |= ccw ? 0x00040000 : 0x00020000;
346
if (cf & PIPE_FACE_BACK)
347
cull |= ccw ? 0x00020000 : 0x00040000;
348
}
349
350
/* Specify point size with PLBU command if shader doesn't write */
351
if (info->mode == PIPE_PRIM_POINTS && ctx->vs->state.point_size_idx == -1)
352
force_point_size = true;
353
354
/* Specify line width with PLBU command for lines */
355
if (info->mode > PIPE_PRIM_POINTS && info->mode < PIPE_PRIM_TRIANGLES)
356
force_point_size = true;
357
358
PLBU_CMD_PRIMITIVE_SETUP(force_point_size, cull, info->index_size);
359
360
PLBU_CMD_RSW_VERTEX_ARRAY(
361
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw),
362
ctx->gp_output->va);
363
364
/* TODO
365
* - we should set it only for the first draw that enabled the scissor and for
366
* latter draw only if scissor is dirty
367
*/
368
369
assert(cscissor->minx < cscissor->maxx && cscissor->miny < cscissor->maxy);
370
PLBU_CMD_SCISSORS(cscissor->minx, cscissor->maxx, cscissor->miny, cscissor->maxy);
371
372
lima_damage_rect_union(&job->damage_rect, cscissor->minx, cscissor->maxx,
373
cscissor->miny, cscissor->maxy);
374
375
PLBU_CMD_UNKNOWN1();
376
377
PLBU_CMD_DEPTH_RANGE_NEAR(fui(ctx->viewport.near));
378
PLBU_CMD_DEPTH_RANGE_FAR(fui(ctx->viewport.far));
379
380
if ((info->mode == PIPE_PRIM_POINTS && ctx->vs->state.point_size_idx == -1) ||
381
((info->mode >= PIPE_PRIM_LINES) && (info->mode < PIPE_PRIM_TRIANGLES)))
382
{
383
uint32_t v = info->mode == PIPE_PRIM_POINTS ?
384
fui(ctx->rasterizer->base.point_size) : fui(ctx->rasterizer->base.line_width);
385
PLBU_CMD_LOW_PRIM_SIZE(v);
386
}
387
388
if (info->index_size) {
389
PLBU_CMD_INDEXED_DEST(ctx->gp_output->va);
390
if (vs->state.point_size_idx != -1)
391
PLBU_CMD_INDEXED_PT_SIZE(ctx->gp_output->va + ctx->gp_output_point_size_offt);
392
393
PLBU_CMD_INDICES(ctx->index_res->bo->va + draw->start * info->index_size + ctx->index_offset);
394
}
395
else {
396
/* can this make the attribute info static? */
397
PLBU_CMD_DRAW_ARRAYS(info->mode, draw->start, draw->count);
398
}
399
400
PLBU_CMD_ARRAYS_SEMAPHORE_END();
401
402
if (info->index_size)
403
PLBU_CMD_DRAW_ELEMENTS(info->mode, ctx->min_index, draw->count);
404
405
PLBU_CMD_END();
406
}
407
408
static int
409
lima_blend_func(enum pipe_blend_func pipe)
410
{
411
switch (pipe) {
412
case PIPE_BLEND_ADD:
413
return 2;
414
case PIPE_BLEND_SUBTRACT:
415
return 0;
416
case PIPE_BLEND_REVERSE_SUBTRACT:
417
return 1;
418
case PIPE_BLEND_MIN:
419
return 4;
420
case PIPE_BLEND_MAX:
421
return 5;
422
}
423
return -1;
424
}
425
426
static int
427
lima_blend_factor_has_alpha(enum pipe_blendfactor pipe)
428
{
429
/* Bit 4 is set if the blendfactor uses alpha */
430
switch (pipe) {
431
case PIPE_BLENDFACTOR_SRC_ALPHA:
432
case PIPE_BLENDFACTOR_DST_ALPHA:
433
case PIPE_BLENDFACTOR_CONST_ALPHA:
434
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
435
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
436
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
437
return 1;
438
439
case PIPE_BLENDFACTOR_SRC_COLOR:
440
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
441
case PIPE_BLENDFACTOR_DST_COLOR:
442
case PIPE_BLENDFACTOR_INV_DST_COLOR:
443
case PIPE_BLENDFACTOR_CONST_COLOR:
444
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
445
case PIPE_BLENDFACTOR_ZERO:
446
case PIPE_BLENDFACTOR_ONE:
447
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
448
return 0;
449
450
case PIPE_BLENDFACTOR_SRC1_COLOR:
451
case PIPE_BLENDFACTOR_SRC1_ALPHA:
452
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
453
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
454
return -1; /* not supported */
455
}
456
return -1;
457
}
458
459
static int
460
lima_blend_factor_is_inv(enum pipe_blendfactor pipe)
461
{
462
/* Bit 3 is set if the blendfactor type is inverted */
463
switch (pipe) {
464
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
465
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
466
case PIPE_BLENDFACTOR_INV_DST_COLOR:
467
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
468
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
469
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
470
case PIPE_BLENDFACTOR_ONE:
471
return 1;
472
473
case PIPE_BLENDFACTOR_SRC_COLOR:
474
case PIPE_BLENDFACTOR_SRC_ALPHA:
475
case PIPE_BLENDFACTOR_DST_COLOR:
476
case PIPE_BLENDFACTOR_DST_ALPHA:
477
case PIPE_BLENDFACTOR_CONST_COLOR:
478
case PIPE_BLENDFACTOR_CONST_ALPHA:
479
case PIPE_BLENDFACTOR_ZERO:
480
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
481
return 0;
482
483
case PIPE_BLENDFACTOR_SRC1_COLOR:
484
case PIPE_BLENDFACTOR_SRC1_ALPHA:
485
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
486
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
487
return -1; /* not supported */
488
}
489
return -1;
490
}
491
492
static int
493
lima_blend_factor(enum pipe_blendfactor pipe)
494
{
495
/* Bits 0-2 indicate the blendfactor type */
496
switch (pipe) {
497
case PIPE_BLENDFACTOR_SRC_COLOR:
498
case PIPE_BLENDFACTOR_SRC_ALPHA:
499
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
500
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
501
return 0;
502
503
case PIPE_BLENDFACTOR_DST_COLOR:
504
case PIPE_BLENDFACTOR_DST_ALPHA:
505
case PIPE_BLENDFACTOR_INV_DST_COLOR:
506
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
507
return 1;
508
509
case PIPE_BLENDFACTOR_CONST_COLOR:
510
case PIPE_BLENDFACTOR_CONST_ALPHA:
511
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
512
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
513
return 2;
514
515
case PIPE_BLENDFACTOR_ZERO:
516
case PIPE_BLENDFACTOR_ONE:
517
return 3;
518
519
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
520
return 4;
521
522
case PIPE_BLENDFACTOR_SRC1_COLOR:
523
case PIPE_BLENDFACTOR_SRC1_ALPHA:
524
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
525
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
526
return -1; /* not supported */
527
}
528
return -1;
529
}
530
531
static int
532
lima_calculate_alpha_blend(enum pipe_blend_func rgb_func, enum pipe_blend_func alpha_func,
533
enum pipe_blendfactor rgb_src_factor, enum pipe_blendfactor rgb_dst_factor,
534
enum pipe_blendfactor alpha_src_factor, enum pipe_blendfactor alpha_dst_factor)
535
{
536
/* PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE has to be changed to PIPE_BLENDFACTOR_ONE
537
* if it is set for alpha_src.
538
*/
539
if (alpha_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE)
540
alpha_src_factor = PIPE_BLENDFACTOR_ONE;
541
542
return lima_blend_func(rgb_func) |
543
(lima_blend_func(alpha_func) << 3) |
544
545
(lima_blend_factor(rgb_src_factor) << 6) |
546
(lima_blend_factor_is_inv(rgb_src_factor) << 9) |
547
(lima_blend_factor_has_alpha(rgb_src_factor) << 10) |
548
549
(lima_blend_factor(rgb_dst_factor) << 11) |
550
(lima_blend_factor_is_inv(rgb_dst_factor) << 14) |
551
(lima_blend_factor_has_alpha(rgb_dst_factor) << 15) |
552
553
(lima_blend_factor(alpha_src_factor) << 16) |
554
(lima_blend_factor_is_inv(alpha_src_factor) << 19) |
555
556
(lima_blend_factor(alpha_dst_factor) << 20) |
557
(lima_blend_factor_is_inv(alpha_dst_factor) << 23) |
558
0x0C000000; /* need to check if this is GLESv1 glAlphaFunc */
559
}
560
561
static int
562
lima_stencil_op(enum pipe_stencil_op pipe)
563
{
564
switch (pipe) {
565
case PIPE_STENCIL_OP_KEEP:
566
return 0;
567
case PIPE_STENCIL_OP_ZERO:
568
return 2;
569
case PIPE_STENCIL_OP_REPLACE:
570
return 1;
571
case PIPE_STENCIL_OP_INCR:
572
return 6;
573
case PIPE_STENCIL_OP_DECR:
574
return 7;
575
case PIPE_STENCIL_OP_INCR_WRAP:
576
return 4;
577
case PIPE_STENCIL_OP_DECR_WRAP:
578
return 5;
579
case PIPE_STENCIL_OP_INVERT:
580
return 3;
581
}
582
return -1;
583
}
584
585
static unsigned
586
lima_calculate_depth_test(struct pipe_depth_stencil_alpha_state *depth,
587
struct pipe_rasterizer_state *rst)
588
{
589
int offset_scale = 0, offset_units = 0;
590
enum pipe_compare_func func = (depth->depth_enabled ? depth->depth_func : PIPE_FUNC_ALWAYS);
591
592
offset_scale = CLAMP(rst->offset_scale * 4, -128, 127);
593
if (offset_scale < 0)
594
offset_scale += 0x100;
595
596
offset_units = CLAMP(rst->offset_units * 2, -128, 127);
597
if (offset_units < 0)
598
offset_units += 0x100;
599
600
return (depth->depth_enabled && depth->depth_writemask) |
601
((int)func << 1) |
602
(offset_scale << 16) |
603
(offset_units << 24) |
604
0x30; /* find out what is this */
605
}
606
607
static void
608
lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *info)
609
{
610
struct lima_fs_compiled_shader *fs = ctx->fs;
611
struct lima_render_state *render =
612
lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_plb_rsw,
613
sizeof(*render));
614
bool early_z = true;
615
bool pixel_kill = true;
616
617
/* do hw support RGBA independ blend?
618
* PIPE_CAP_INDEP_BLEND_ENABLE
619
*
620
* how to handle the no cbuf only zbuf case?
621
*/
622
struct pipe_rt_blend_state *rt = ctx->blend->base.rt;
623
render->blend_color_bg = float_to_ubyte(ctx->blend_color.color[2]) |
624
(float_to_ubyte(ctx->blend_color.color[1]) << 16);
625
render->blend_color_ra = float_to_ubyte(ctx->blend_color.color[0]) |
626
(float_to_ubyte(ctx->blend_color.color[3]) << 16);
627
628
if (rt->blend_enable) {
629
render->alpha_blend = lima_calculate_alpha_blend(rt->rgb_func, rt->alpha_func,
630
rt->rgb_src_factor, rt->rgb_dst_factor,
631
rt->alpha_src_factor, rt->alpha_dst_factor);
632
}
633
else {
634
/*
635
* Special handling for blending disabled.
636
* Binary driver is generating the same alpha_value,
637
* as when we would just enable blending, without changing/setting any blend equation/params.
638
* Normaly in this case mesa would set all rt fields (func/factor) to zero.
639
*/
640
render->alpha_blend = lima_calculate_alpha_blend(PIPE_BLEND_ADD, PIPE_BLEND_ADD,
641
PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO,
642
PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO);
643
}
644
645
render->alpha_blend |= (rt->colormask & PIPE_MASK_RGBA) << 28;
646
647
struct pipe_rasterizer_state *rst = &ctx->rasterizer->base;
648
render->depth_test = lima_calculate_depth_test(&ctx->zsa->base, rst);
649
650
ushort far, near;
651
652
near = float_to_ushort(ctx->viewport.near);
653
far = float_to_ushort(ctx->viewport.far);
654
655
/* Insert a small 'epsilon' difference between 'near' and 'far' when
656
* they are equal, to avoid application bugs. */
657
if (far == near) {
658
if (near > 0)
659
near--;
660
if (far < USHRT_MAX)
661
far++;
662
}
663
664
/* overlap with plbu? any place can remove one? */
665
render->depth_range = near | (far << 16);
666
667
struct pipe_stencil_state *stencil = ctx->zsa->base.stencil;
668
struct pipe_stencil_ref *ref = &ctx->stencil_ref;
669
670
if (stencil[0].enabled) { /* stencil is enabled */
671
render->stencil_front = stencil[0].func |
672
(lima_stencil_op(stencil[0].fail_op) << 3) |
673
(lima_stencil_op(stencil[0].zfail_op) << 6) |
674
(lima_stencil_op(stencil[0].zpass_op) << 9) |
675
(ref->ref_value[0] << 16) |
676
(stencil[0].valuemask << 24);
677
render->stencil_back = render->stencil_front;
678
render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[0].writemask & 0xff) << 8;
679
if (stencil[1].enabled) { /* two-side is enabled */
680
render->stencil_back = stencil[1].func |
681
(lima_stencil_op(stencil[1].fail_op) << 3) |
682
(lima_stencil_op(stencil[1].zfail_op) << 6) |
683
(lima_stencil_op(stencil[1].zpass_op) << 9) |
684
(ref->ref_value[1] << 16) |
685
(stencil[1].valuemask << 24);
686
render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[1].writemask & 0xff) << 8;
687
}
688
/* TODO: Find out, what (render->stecil_test & 0xff000000) is */
689
}
690
else {
691
/* Default values, when stencil is disabled:
692
* stencil[0|1].valuemask = 0xff
693
* stencil[0|1].func = PIPE_FUNC_ALWAYS
694
* stencil[0|1].writemask = 0xff
695
*/
696
render->stencil_front = 0xff000007;
697
render->stencil_back = 0xff000007;
698
render->stencil_test = 0x0000ffff;
699
}
700
701
/* need more investigation */
702
if (info->mode == PIPE_PRIM_POINTS)
703
render->multi_sample = 0x0000F000;
704
else if (info->mode < PIPE_PRIM_TRIANGLES)
705
render->multi_sample = 0x0000F400;
706
else
707
render->multi_sample = 0x0000F800;
708
if (ctx->framebuffer.base.samples)
709
render->multi_sample |= 0x68;
710
711
/* alpha test */
712
if (ctx->zsa->base.alpha_enabled) {
713
render->multi_sample |= ctx->zsa->base.alpha_func;
714
render->stencil_test |= float_to_ubyte(ctx->zsa->base.alpha_ref_value) << 16;
715
} else {
716
/* func = PIPE_FUNC_ALWAYS */
717
render->multi_sample |= 0x7;
718
}
719
720
render->shader_address =
721
ctx->fs->bo->va | (((uint32_t *)ctx->fs->bo->map)[0] & 0x1F);
722
723
/* seems not needed */
724
render->uniforms_address = 0x00000000;
725
726
render->textures_address = 0x00000000;
727
728
render->aux0 = (ctx->vs->state.varying_stride >> 3);
729
render->aux1 = 0x00001000;
730
if (ctx->blend->base.dither)
731
render->aux1 |= 0x00002000;
732
733
if (fs->state.uses_discard ||
734
ctx->zsa->base.alpha_enabled) {
735
early_z = false;
736
pixel_kill = false;
737
}
738
739
if (rt->blend_enable)
740
pixel_kill = false;
741
742
if ((rt->colormask & PIPE_MASK_RGBA) != PIPE_MASK_RGBA)
743
pixel_kill = false;
744
745
if (early_z)
746
render->aux0 |= 0x300;
747
748
if (pixel_kill)
749
render->aux0 |= 0x1000;
750
751
if (ctx->tex_stateobj.num_samplers) {
752
render->textures_address =
753
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc);
754
render->aux0 |= ctx->tex_stateobj.num_samplers << 14;
755
render->aux0 |= 0x20;
756
}
757
758
if (ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer) {
759
render->uniforms_address =
760
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array);
761
uint32_t size = ctx->buffer_state[lima_ctx_buff_pp_uniform].size;
762
uint32_t bits = 0;
763
if (size >= 8) {
764
bits = util_last_bit(size >> 3) - 1;
765
bits += size & u_bit_consecutive(0, bits + 3) ? 1 : 0;
766
}
767
render->uniforms_address |= bits > 0xf ? 0xf : bits;
768
769
render->aux0 |= 0x80;
770
render->aux1 |= 0x10000;
771
}
772
773
if (ctx->vs->state.num_varyings) {
774
render->varying_types = 0x00000000;
775
render->varyings_address = ctx->gp_output->va +
776
ctx->gp_output_varyings_offt;
777
for (int i = 0, index = 0; i < ctx->vs->state.num_outputs; i++) {
778
int val;
779
780
if (i == ctx->vs->state.gl_pos_idx ||
781
i == ctx->vs->state.point_size_idx)
782
continue;
783
784
struct lima_varying_info *v = ctx->vs->state.varying + i;
785
if (v->component_size == 4)
786
val = v->components > 2 ? 0 : 1;
787
else
788
val = v->components > 2 ? 2 : 3;
789
790
if (index < 10)
791
render->varying_types |= val << (3 * index);
792
else if (index == 10) {
793
render->varying_types |= val << 30;
794
render->varyings_address |= val >> 2;
795
}
796
else if (index == 11)
797
render->varyings_address |= val << 1;
798
799
index++;
800
}
801
}
802
else {
803
render->varying_types = 0x00000000;
804
render->varyings_address = 0x00000000;
805
}
806
807
struct lima_job *job = lima_job_get(ctx);
808
809
lima_dump_command_stream_print(
810
job->dump, render, sizeof(*render),
811
false, "add render state at va %x\n",
812
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
813
814
lima_dump_rsw_command_stream_print(
815
job->dump, render, sizeof(*render),
816
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
817
}
818
819
static void
820
lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_info *info,
821
const struct pipe_draw_start_count_bias *draw)
822
{
823
struct lima_job *job = lima_job_get(ctx);
824
struct lima_vertex_element_state *ve = ctx->vertex_elements;
825
struct lima_context_vertex_buffer *vb = &ctx->vertex_buffers;
826
827
uint32_t *attribute =
828
lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_attribute_info,
829
MAX2(1, ve->num_elements) * 8);
830
831
int n = 0;
832
for (int i = 0; i < ve->num_elements; i++) {
833
struct pipe_vertex_element *pve = ve->pipe + i;
834
835
assert(pve->vertex_buffer_index < vb->count);
836
assert(vb->enabled_mask & (1 << pve->vertex_buffer_index));
837
838
struct pipe_vertex_buffer *pvb = vb->vb + pve->vertex_buffer_index;
839
struct lima_resource *res = lima_resource(pvb->buffer.resource);
840
841
lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ);
842
843
unsigned start = info->index_size ? (ctx->min_index + draw->index_bias) : draw->start;
844
attribute[n++] = res->bo->va + pvb->buffer_offset + pve->src_offset
845
+ start * pvb->stride;
846
attribute[n++] = (pvb->stride << 11) |
847
(lima_pipe_format_to_attrib_type(pve->src_format) << 2) |
848
(util_format_get_nr_components(pve->src_format) - 1);
849
}
850
851
lima_dump_command_stream_print(
852
job->dump, attribute, n * 4, false, "update attribute info at va %x\n",
853
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info));
854
}
855
856
static void
857
lima_update_gp_uniform(struct lima_context *ctx)
858
{
859
struct lima_context_constant_buffer *ccb =
860
ctx->const_buffer + PIPE_SHADER_VERTEX;
861
struct lima_vs_compiled_shader *vs = ctx->vs;
862
int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
863
864
int size = uniform_size + vs->state.constant_size + 32;
865
void *vs_const_buff =
866
lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_uniform, size);
867
868
if (ccb->buffer)
869
memcpy(vs_const_buff, ccb->buffer, uniform_size);
870
871
memcpy(vs_const_buff + uniform_size,
872
ctx->viewport.transform.scale,
873
sizeof(ctx->viewport.transform.scale));
874
memcpy(vs_const_buff + uniform_size + 16,
875
ctx->viewport.transform.translate,
876
sizeof(ctx->viewport.transform.translate));
877
878
if (vs->constant)
879
memcpy(vs_const_buff + uniform_size + 32,
880
vs->constant, vs->state.constant_size);
881
882
struct lima_job *job = lima_job_get(ctx);
883
884
if (lima_debug & LIMA_DEBUG_GP) {
885
float *vs_const_buff_f = vs_const_buff;
886
printf("gp uniforms:\n");
887
for (int i = 0; i < (size / sizeof(float)); i++) {
888
if ((i % 4) == 0)
889
printf("%4d:", i / 4);
890
printf(" %8.4f", vs_const_buff_f[i]);
891
if ((i % 4) == 3)
892
printf("\n");
893
}
894
printf("\n");
895
}
896
897
lima_dump_command_stream_print(
898
job->dump, vs_const_buff, size, true,
899
"update gp uniform at va %x\n",
900
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform));
901
}
902
903
static void
904
lima_update_pp_uniform(struct lima_context *ctx)
905
{
906
const float *const_buff = ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer;
907
size_t const_buff_size = ctx->const_buffer[PIPE_SHADER_FRAGMENT].size / sizeof(float);
908
909
if (!const_buff)
910
return;
911
912
uint16_t *fp16_const_buff =
913
lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform,
914
const_buff_size * sizeof(uint16_t));
915
916
uint32_t *array =
917
lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform_array, 4);
918
919
for (int i = 0; i < const_buff_size; i++)
920
fp16_const_buff[i] = _mesa_float_to_half(const_buff[i]);
921
922
*array = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform);
923
924
struct lima_job *job = lima_job_get(ctx);
925
926
lima_dump_command_stream_print(
927
job->dump, fp16_const_buff, const_buff_size * 2,
928
false, "add pp uniform data at va %x\n",
929
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform));
930
lima_dump_command_stream_print(
931
job->dump, array, 4, false, "add pp uniform info at va %x\n",
932
lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array));
933
}
934
935
static void
936
lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info,
937
const struct pipe_draw_start_count_bias *draw)
938
{
939
struct lima_job *job = lima_job_get(ctx);
940
struct lima_screen *screen = lima_screen(ctx->base.screen);
941
struct lima_vs_compiled_shader *vs = ctx->vs;
942
uint32_t gp_output_size;
943
unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
944
945
uint32_t *varying =
946
lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_varying_info,
947
vs->state.num_outputs * 8);
948
int n = 0;
949
950
int offset = 0;
951
952
for (int i = 0; i < vs->state.num_outputs; i++) {
953
struct lima_varying_info *v = vs->state.varying + i;
954
955
if (i == vs->state.gl_pos_idx ||
956
i == vs->state.point_size_idx)
957
continue;
958
959
int size = v->component_size * 4;
960
961
/* does component_size == 2 need to be 16 aligned? */
962
if (v->component_size == 4)
963
offset = align(offset, 16);
964
965
v->offset = offset;
966
offset += size;
967
}
968
969
vs->state.varying_stride = align(offset, 16);
970
971
/* gl_Position is always present, allocate space for it */
972
gp_output_size = align(4 * 4 * num, 0x40);
973
974
/* Allocate space for varyings if there're any */
975
if (vs->state.num_varyings) {
976
ctx->gp_output_varyings_offt = gp_output_size;
977
gp_output_size += align(vs->state.varying_stride * num, 0x40);
978
}
979
980
/* Allocate space for gl_PointSize if it's there */
981
if (vs->state.point_size_idx != -1) {
982
ctx->gp_output_point_size_offt = gp_output_size;
983
gp_output_size += 4 * num;
984
}
985
986
/* gp_output can be too large for the suballocator, so create a
987
* separate bo for it. The bo cache should prevent performance hit.
988
*/
989
ctx->gp_output = lima_bo_create(screen, gp_output_size, 0);
990
assert(ctx->gp_output);
991
lima_job_add_bo(job, LIMA_PIPE_GP, ctx->gp_output, LIMA_SUBMIT_BO_WRITE);
992
lima_job_add_bo(job, LIMA_PIPE_PP, ctx->gp_output, LIMA_SUBMIT_BO_READ);
993
994
for (int i = 0; i < vs->state.num_outputs; i++) {
995
struct lima_varying_info *v = vs->state.varying + i;
996
997
if (i == vs->state.gl_pos_idx) {
998
/* gl_Position */
999
varying[n++] = ctx->gp_output->va;
1000
varying[n++] = 0x8020;
1001
} else if (i == vs->state.point_size_idx) {
1002
/* gl_PointSize */
1003
varying[n++] = ctx->gp_output->va + ctx->gp_output_point_size_offt;
1004
varying[n++] = 0x2021;
1005
} else {
1006
/* Varying */
1007
varying[n++] = ctx->gp_output->va + ctx->gp_output_varyings_offt +
1008
v->offset;
1009
varying[n++] = (vs->state.varying_stride << 11) | (v->components - 1) |
1010
(v->component_size == 2 ? 0x0C : 0);
1011
}
1012
}
1013
1014
lima_dump_command_stream_print(
1015
job->dump, varying, n * 4, false, "update varying info at va %x\n",
1016
lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info));
1017
}
1018
1019
static void
1020
lima_draw_vbo_update(struct pipe_context *pctx,
1021
const struct pipe_draw_info *info,
1022
const struct pipe_draw_start_count_bias *draw)
1023
{
1024
struct lima_context *ctx = lima_context(pctx);
1025
struct lima_context_framebuffer *fb = &ctx->framebuffer;
1026
unsigned buffers = 0;
1027
1028
if (fb->base.zsbuf) {
1029
if (ctx->zsa->base.depth_enabled)
1030
buffers |= PIPE_CLEAR_DEPTH;
1031
if (ctx->zsa->base.stencil[0].enabled ||
1032
ctx->zsa->base.stencil[1].enabled)
1033
buffers |= PIPE_CLEAR_STENCIL;
1034
}
1035
1036
if (fb->base.nr_cbufs)
1037
buffers |= PIPE_CLEAR_COLOR0;
1038
1039
lima_update_job_wb(ctx, buffers);
1040
1041
lima_update_gp_attribute_info(ctx, info, draw);
1042
1043
if ((ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1044
ctx->const_buffer[PIPE_SHADER_VERTEX].dirty) ||
1045
ctx->dirty & LIMA_CONTEXT_DIRTY_VIEWPORT ||
1046
ctx->dirty & LIMA_CONTEXT_DIRTY_COMPILED_VS) {
1047
lima_update_gp_uniform(ctx);
1048
ctx->const_buffer[PIPE_SHADER_VERTEX].dirty = false;
1049
}
1050
1051
lima_update_varying(ctx, info, draw);
1052
1053
lima_pack_vs_cmd(ctx, info, draw);
1054
1055
if (ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1056
ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty) {
1057
lima_update_pp_uniform(ctx);
1058
ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty = false;
1059
}
1060
1061
lima_update_textures(ctx);
1062
1063
lima_pack_render_state(ctx, info);
1064
lima_pack_plbu_cmd(ctx, info, draw);
1065
1066
if (ctx->gp_output) {
1067
lima_bo_unreference(ctx->gp_output); /* held by job */
1068
ctx->gp_output = NULL;
1069
}
1070
1071
ctx->dirty = 0;
1072
}
1073
1074
static void
1075
lima_draw_vbo_indexed(struct pipe_context *pctx,
1076
const struct pipe_draw_info *info,
1077
const struct pipe_draw_start_count_bias *draw)
1078
{
1079
struct lima_context *ctx = lima_context(pctx);
1080
struct lima_job *job = lima_job_get(ctx);
1081
struct pipe_resource *indexbuf = NULL;
1082
bool needs_indices = true;
1083
1084
/* Mali Utgard GPU always need min/max index info for index draw,
1085
* compute it if upper layer does not do for us */
1086
if (info->index_bounds_valid) {
1087
ctx->min_index = info->min_index;
1088
ctx->max_index = info->max_index;
1089
needs_indices = false;
1090
}
1091
1092
if (info->has_user_indices) {
1093
util_upload_index_buffer(&ctx->base, info, draw, &indexbuf, &ctx->index_offset, 0x40);
1094
ctx->index_res = lima_resource(indexbuf);
1095
}
1096
else {
1097
ctx->index_res = lima_resource(info->index.resource);
1098
ctx->index_offset = 0;
1099
needs_indices = !panfrost_minmax_cache_get(ctx->index_res->index_cache, draw->start,
1100
draw->count, &ctx->min_index, &ctx->max_index);
1101
}
1102
1103
if (needs_indices) {
1104
u_vbuf_get_minmax_index(pctx, info, draw, &ctx->min_index, &ctx->max_index);
1105
if (!info->has_user_indices)
1106
panfrost_minmax_cache_add(ctx->index_res->index_cache, draw->start, draw->count,
1107
ctx->min_index, ctx->max_index);
1108
}
1109
1110
lima_job_add_bo(job, LIMA_PIPE_GP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1111
lima_job_add_bo(job, LIMA_PIPE_PP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1112
lima_draw_vbo_update(pctx, info, draw);
1113
1114
if (indexbuf)
1115
pipe_resource_reference(&indexbuf, NULL);
1116
}
1117
1118
static void
1119
lima_draw_vbo_count(struct pipe_context *pctx,
1120
const struct pipe_draw_info *info,
1121
const struct pipe_draw_start_count_bias *draw)
1122
{
1123
static const uint32_t max_verts = 65535;
1124
1125
struct pipe_draw_start_count_bias local_draw = *draw;
1126
unsigned start = draw->start;
1127
unsigned count = draw->count;
1128
1129
while (count) {
1130
unsigned this_count = count;
1131
unsigned step;
1132
1133
u_split_draw(info, max_verts, &this_count, &step);
1134
1135
local_draw.start = start;
1136
local_draw.count = this_count;
1137
1138
lima_draw_vbo_update(pctx, info, &local_draw);
1139
1140
count -= step;
1141
start += step;
1142
}
1143
}
1144
1145
static void
1146
lima_draw_vbo(struct pipe_context *pctx,
1147
const struct pipe_draw_info *info,
1148
unsigned drawid_offset,
1149
const struct pipe_draw_indirect_info *indirect,
1150
const struct pipe_draw_start_count_bias *draws,
1151
unsigned num_draws)
1152
{
1153
if (num_draws > 1) {
1154
util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
1155
return;
1156
}
1157
1158
/* check if draw mode and vertex/index count match,
1159
* otherwise gp will hang */
1160
if (!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) {
1161
debug_printf("draw mode and vertex/index count mismatch\n");
1162
return;
1163
}
1164
1165
struct lima_context *ctx = lima_context(pctx);
1166
1167
if (!ctx->uncomp_fs || !ctx->uncomp_vs) {
1168
debug_warn_once("no shader, skip draw\n");
1169
return;
1170
}
1171
1172
lima_clip_scissor_to_viewport(ctx);
1173
if (lima_is_scissor_zero(ctx))
1174
return;
1175
1176
if (!lima_update_fs_state(ctx) || !lima_update_vs_state(ctx))
1177
return;
1178
1179
struct lima_job *job = lima_job_get(ctx);
1180
job->pp_max_stack_size = MAX2(job->pp_max_stack_size, ctx->fs->state.stack_size);
1181
1182
lima_dump_command_stream_print(
1183
job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false,
1184
"add vs at va %x\n", ctx->vs->bo->va);
1185
1186
lima_dump_command_stream_print(
1187
job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, false,
1188
"add fs at va %x\n", ctx->fs->bo->va);
1189
1190
lima_job_add_bo(job, LIMA_PIPE_GP, ctx->vs->bo, LIMA_SUBMIT_BO_READ);
1191
lima_job_add_bo(job, LIMA_PIPE_PP, ctx->fs->bo, LIMA_SUBMIT_BO_READ);
1192
1193
if (info->index_size)
1194
lima_draw_vbo_indexed(pctx, info, &draws[0]);
1195
else
1196
lima_draw_vbo_count(pctx, info, &draws[0]);
1197
1198
job->draws++;
1199
/* Flush job if we hit the limit of draws per job otherwise we may
1200
* hit tile heap size limit */
1201
if (job->draws > MAX_DRAWS_PER_JOB) {
1202
unsigned resolve = job->resolve;
1203
lima_do_job(job);
1204
job = lima_job_get(ctx);
1205
/* Subsequent job will need to resolve the same buffers */
1206
lima_update_job_wb(ctx, resolve);
1207
}
1208
}
1209
1210
void
1211
lima_draw_init(struct lima_context *ctx)
1212
{
1213
ctx->base.clear = lima_clear;
1214
ctx->base.draw_vbo = lima_draw_vbo;
1215
}
1216
1217