1 /*
2 * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
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
lima_clip_scissor_to_viewport(struct lima_context * ctx)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
lima_is_scissor_zero(struct lima_context * ctx)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
lima_update_job_wb(struct lima_context * ctx,unsigned buffers)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
lima_damage_rect_union(struct pipe_scissor_state * rect,unsigned minx,unsigned maxx,unsigned miny,unsigned maxy)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
lima_clear(struct pipe_context * pctx,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)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
lima_pipe_format_to_attrib_type(enum pipe_format format)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
lima_pack_vs_cmd(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)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
lima_pack_plbu_cmd(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)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
lima_blend_func(enum pipe_blend_func pipe)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
lima_blend_factor_has_alpha(enum pipe_blendfactor pipe)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
lima_blend_factor_is_inv(enum pipe_blendfactor pipe)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
lima_blend_factor(enum pipe_blendfactor pipe)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
lima_calculate_alpha_blend(enum pipe_blend_func rgb_func,enum pipe_blend_func alpha_func,enum pipe_blendfactor rgb_src_factor,enum pipe_blendfactor rgb_dst_factor,enum pipe_blendfactor alpha_src_factor,enum pipe_blendfactor alpha_dst_factor)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
lima_stencil_op(enum pipe_stencil_op pipe)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
lima_calculate_depth_test(struct pipe_depth_stencil_alpha_state * depth,struct pipe_rasterizer_state * rst)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 }
605
606 static void
lima_pack_render_state(struct lima_context * ctx,const struct pipe_draw_info * info)607 lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *info)
608 {
609 struct lima_fs_compiled_shader *fs = ctx->fs;
610 struct lima_render_state *render =
611 lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_plb_rsw,
612 sizeof(*render));
613 bool early_z = true;
614 bool pixel_kill = true;
615
616 /* do hw support RGBA independ blend?
617 * PIPE_CAP_INDEP_BLEND_ENABLE
618 *
619 * how to handle the no cbuf only zbuf case?
620 */
621 struct pipe_rt_blend_state *rt = ctx->blend->base.rt;
622 render->blend_color_bg = float_to_ubyte(ctx->blend_color.color[2]) |
623 (float_to_ubyte(ctx->blend_color.color[1]) << 16);
624 render->blend_color_ra = float_to_ubyte(ctx->blend_color.color[0]) |
625 (float_to_ubyte(ctx->blend_color.color[3]) << 16);
626
627 if (rt->blend_enable) {
628 render->alpha_blend = lima_calculate_alpha_blend(rt->rgb_func, rt->alpha_func,
629 rt->rgb_src_factor, rt->rgb_dst_factor,
630 rt->alpha_src_factor, rt->alpha_dst_factor);
631 }
632 else {
633 /*
634 * Special handling for blending disabled.
635 * Binary driver is generating the same alpha_value,
636 * as when we would just enable blending, without changing/setting any blend equation/params.
637 * Normaly in this case mesa would set all rt fields (func/factor) to zero.
638 */
639 render->alpha_blend = lima_calculate_alpha_blend(PIPE_BLEND_ADD, PIPE_BLEND_ADD,
640 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO,
641 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ZERO);
642 }
643
644 render->alpha_blend |= (rt->colormask & PIPE_MASK_RGBA) << 28;
645
646 struct pipe_rasterizer_state *rst = &ctx->rasterizer->base;
647 render->depth_test = lima_calculate_depth_test(&ctx->zsa->base, rst);
648
649 if (!rst->depth_clip_near || ctx->viewport.near == 0.0f)
650 render->depth_test |= 0x10; /* don't clip depth near */
651 if (!rst->depth_clip_far || ctx->viewport.far == 1.0f)
652 render->depth_test |= 0x20; /* don't clip depth far */
653
654 ushort far, near;
655
656 near = float_to_ushort(ctx->viewport.near);
657 far = float_to_ushort(ctx->viewport.far);
658
659 /* overlap with plbu? any place can remove one? */
660 render->depth_range = near | (far << 16);
661
662 struct pipe_stencil_state *stencil = ctx->zsa->base.stencil;
663 struct pipe_stencil_ref *ref = &ctx->stencil_ref;
664
665 if (stencil[0].enabled) { /* stencil is enabled */
666 render->stencil_front = stencil[0].func |
667 (lima_stencil_op(stencil[0].fail_op) << 3) |
668 (lima_stencil_op(stencil[0].zfail_op) << 6) |
669 (lima_stencil_op(stencil[0].zpass_op) << 9) |
670 (ref->ref_value[0] << 16) |
671 (stencil[0].valuemask << 24);
672 render->stencil_back = render->stencil_front;
673 render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[0].writemask & 0xff) << 8;
674 if (stencil[1].enabled) { /* two-side is enabled */
675 render->stencil_back = stencil[1].func |
676 (lima_stencil_op(stencil[1].fail_op) << 3) |
677 (lima_stencil_op(stencil[1].zfail_op) << 6) |
678 (lima_stencil_op(stencil[1].zpass_op) << 9) |
679 (ref->ref_value[1] << 16) |
680 (stencil[1].valuemask << 24);
681 render->stencil_test = (stencil[0].writemask & 0xff) | (stencil[1].writemask & 0xff) << 8;
682 }
683 /* TODO: Find out, what (render->stecil_test & 0xff000000) is */
684 }
685 else {
686 /* Default values, when stencil is disabled:
687 * stencil[0|1].valuemask = 0xff
688 * stencil[0|1].func = PIPE_FUNC_ALWAYS
689 * stencil[0|1].writemask = 0xff
690 */
691 render->stencil_front = 0xff000007;
692 render->stencil_back = 0xff000007;
693 render->stencil_test = 0x0000ffff;
694 }
695
696 /* need more investigation */
697 if (info->mode == PIPE_PRIM_POINTS)
698 render->multi_sample = 0x0000F000;
699 else if (info->mode < PIPE_PRIM_TRIANGLES)
700 render->multi_sample = 0x0000F400;
701 else
702 render->multi_sample = 0x0000F800;
703 if (ctx->framebuffer.base.samples)
704 render->multi_sample |= 0x68;
705
706 /* alpha test */
707 if (ctx->zsa->base.alpha_enabled) {
708 render->multi_sample |= ctx->zsa->base.alpha_func;
709 render->stencil_test |= float_to_ubyte(ctx->zsa->base.alpha_ref_value) << 16;
710 } else {
711 /* func = PIPE_FUNC_ALWAYS */
712 render->multi_sample |= 0x7;
713 }
714
715 render->shader_address =
716 ctx->fs->bo->va | (((uint32_t *)ctx->fs->bo->map)[0] & 0x1F);
717
718 /* seems not needed */
719 render->uniforms_address = 0x00000000;
720
721 render->textures_address = 0x00000000;
722
723 render->aux0 = (ctx->vs->state.varying_stride >> 3);
724 render->aux1 = 0x00000000;
725 if (ctx->rasterizer->base.front_ccw)
726 render->aux1 = 0x00001000;
727
728 if (ctx->blend->base.dither)
729 render->aux1 |= 0x00002000;
730
731 if (fs->state.uses_discard ||
732 ctx->zsa->base.alpha_enabled) {
733 early_z = false;
734 pixel_kill = false;
735 }
736
737 if (rt->blend_enable)
738 pixel_kill = false;
739
740 if ((rt->colormask & PIPE_MASK_RGBA) != PIPE_MASK_RGBA)
741 pixel_kill = false;
742
743 if (early_z)
744 render->aux0 |= 0x300;
745
746 if (pixel_kill)
747 render->aux0 |= 0x1000;
748
749 if (ctx->tex_stateobj.num_samplers) {
750 render->textures_address =
751 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc);
752 render->aux0 |= ctx->tex_stateobj.num_samplers << 14;
753 render->aux0 |= 0x20;
754 }
755
756 if (ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer) {
757 render->uniforms_address =
758 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array);
759 uint32_t size = ctx->buffer_state[lima_ctx_buff_pp_uniform].size;
760 uint32_t bits = 0;
761 if (size >= 8) {
762 bits = util_last_bit(size >> 3) - 1;
763 bits += size & u_bit_consecutive(0, bits + 3) ? 1 : 0;
764 }
765 render->uniforms_address |= bits > 0xf ? 0xf : bits;
766
767 render->aux0 |= 0x80;
768 render->aux1 |= 0x10000;
769 }
770
771 if (ctx->vs->state.num_varyings) {
772 render->varying_types = 0x00000000;
773 render->varyings_address = ctx->gp_output->va +
774 ctx->gp_output_varyings_offt;
775 for (int i = 0, index = 0; i < ctx->vs->state.num_outputs; i++) {
776 int val;
777
778 if (i == ctx->vs->state.gl_pos_idx ||
779 i == ctx->vs->state.point_size_idx)
780 continue;
781
782 struct lima_varying_info *v = ctx->vs->state.varying + i;
783 if (v->component_size == 4)
784 val = v->components > 2 ? 0 : 1;
785 else
786 val = v->components > 2 ? 2 : 3;
787
788 if (index < 10)
789 render->varying_types |= val << (3 * index);
790 else if (index == 10) {
791 render->varying_types |= val << 30;
792 render->varyings_address |= val >> 2;
793 }
794 else if (index == 11)
795 render->varyings_address |= val << 1;
796
797 index++;
798 }
799 }
800 else {
801 render->varying_types = 0x00000000;
802 render->varyings_address = 0x00000000;
803 }
804
805 struct lima_job *job = lima_job_get(ctx);
806
807 lima_dump_command_stream_print(
808 job->dump, render, sizeof(*render),
809 false, "add render state at va %x\n",
810 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
811
812 lima_dump_rsw_command_stream_print(
813 job->dump, render, sizeof(*render),
814 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_plb_rsw));
815 }
816
817 static void
lima_update_gp_attribute_info(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)818 lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_info *info,
819 const struct pipe_draw_start_count_bias *draw)
820 {
821 struct lima_job *job = lima_job_get(ctx);
822 struct lima_vertex_element_state *ve = ctx->vertex_elements;
823 struct lima_context_vertex_buffer *vb = &ctx->vertex_buffers;
824
825 uint32_t *attribute =
826 lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_attribute_info,
827 MAX2(1, ve->num_elements) * 8);
828
829 int n = 0;
830 for (int i = 0; i < ve->num_elements; i++) {
831 struct pipe_vertex_element *pve = ve->pipe + i;
832
833 assert(pve->vertex_buffer_index < vb->count);
834 assert(vb->enabled_mask & (1 << pve->vertex_buffer_index));
835
836 struct pipe_vertex_buffer *pvb = vb->vb + pve->vertex_buffer_index;
837 struct lima_resource *res = lima_resource(pvb->buffer.resource);
838
839 lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ);
840
841 unsigned start = info->index_size ? (ctx->min_index + draw->index_bias) : draw->start;
842 attribute[n++] = res->bo->va + pvb->buffer_offset + pve->src_offset
843 + start * pvb->stride;
844 attribute[n++] = (pvb->stride << 11) |
845 (lima_pipe_format_to_attrib_type(pve->src_format) << 2) |
846 (util_format_get_nr_components(pve->src_format) - 1);
847 }
848
849 lima_dump_command_stream_print(
850 job->dump, attribute, n * 4, false, "update attribute info at va %x\n",
851 lima_ctx_buff_va(ctx, lima_ctx_buff_gp_attribute_info));
852 }
853
854 static void
lima_update_gp_uniform(struct lima_context * ctx)855 lima_update_gp_uniform(struct lima_context *ctx)
856 {
857 struct lima_context_constant_buffer *ccb =
858 ctx->const_buffer + PIPE_SHADER_VERTEX;
859 struct lima_vs_compiled_shader *vs = ctx->vs;
860 int uniform_size = MIN2(vs->state.uniform_size, ccb->size);
861
862 int size = uniform_size + vs->state.constant_size + 32;
863 void *vs_const_buff =
864 lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_uniform, size);
865
866 if (ccb->buffer)
867 memcpy(vs_const_buff, ccb->buffer, uniform_size);
868
869 memcpy(vs_const_buff + uniform_size,
870 ctx->viewport.transform.scale,
871 sizeof(ctx->viewport.transform.scale));
872 memcpy(vs_const_buff + uniform_size + 16,
873 ctx->viewport.transform.translate,
874 sizeof(ctx->viewport.transform.translate));
875
876 if (vs->constant)
877 memcpy(vs_const_buff + uniform_size + 32,
878 vs->constant, vs->state.constant_size);
879
880 struct lima_job *job = lima_job_get(ctx);
881
882 if (lima_debug & LIMA_DEBUG_GP) {
883 float *vs_const_buff_f = vs_const_buff;
884 printf("gp uniforms:\n");
885 for (int i = 0; i < (size / sizeof(float)); i++) {
886 if ((i % 4) == 0)
887 printf("%4d:", i / 4);
888 printf(" %8.4f", vs_const_buff_f[i]);
889 if ((i % 4) == 3)
890 printf("\n");
891 }
892 printf("\n");
893 }
894
895 lima_dump_command_stream_print(
896 job->dump, vs_const_buff, size, true,
897 "update gp uniform at va %x\n",
898 lima_ctx_buff_va(ctx, lima_ctx_buff_gp_uniform));
899 }
900
901 static void
lima_update_pp_uniform(struct lima_context * ctx)902 lima_update_pp_uniform(struct lima_context *ctx)
903 {
904 const float *const_buff = ctx->const_buffer[PIPE_SHADER_FRAGMENT].buffer;
905 size_t const_buff_size = ctx->const_buffer[PIPE_SHADER_FRAGMENT].size / sizeof(float);
906
907 if (!const_buff)
908 return;
909
910 uint16_t *fp16_const_buff =
911 lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform,
912 const_buff_size * sizeof(uint16_t));
913
914 uint32_t *array =
915 lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_uniform_array, 4);
916
917 for (int i = 0; i < const_buff_size; i++)
918 fp16_const_buff[i] = _mesa_float_to_half(const_buff[i]);
919
920 *array = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform);
921
922 struct lima_job *job = lima_job_get(ctx);
923
924 lima_dump_command_stream_print(
925 job->dump, fp16_const_buff, const_buff_size * 2,
926 false, "add pp uniform data at va %x\n",
927 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform));
928 lima_dump_command_stream_print(
929 job->dump, array, 4, false, "add pp uniform info at va %x\n",
930 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_uniform_array));
931 }
932
933 static void
lima_update_varying(struct lima_context * ctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)934 lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info,
935 const struct pipe_draw_start_count_bias *draw)
936 {
937 struct lima_job *job = lima_job_get(ctx);
938 struct lima_screen *screen = lima_screen(ctx->base.screen);
939 struct lima_vs_compiled_shader *vs = ctx->vs;
940 uint32_t gp_output_size;
941 unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count;
942
943 uint32_t *varying =
944 lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_varying_info,
945 vs->state.num_outputs * 8);
946 int n = 0;
947
948 int offset = 0;
949
950 for (int i = 0; i < vs->state.num_outputs; i++) {
951 struct lima_varying_info *v = vs->state.varying + i;
952
953 if (i == vs->state.gl_pos_idx ||
954 i == vs->state.point_size_idx)
955 continue;
956
957 int size = v->component_size * 4;
958
959 /* does component_size == 2 need to be 16 aligned? */
960 if (v->component_size == 4)
961 offset = align(offset, 16);
962
963 v->offset = offset;
964 offset += size;
965 }
966
967 vs->state.varying_stride = align(offset, 16);
968
969 /* gl_Position is always present, allocate space for it */
970 gp_output_size = align(4 * 4 * num, 0x40);
971
972 /* Allocate space for varyings if there're any */
973 if (vs->state.num_varyings) {
974 ctx->gp_output_varyings_offt = gp_output_size;
975 gp_output_size += align(vs->state.varying_stride * num, 0x40);
976 }
977
978 /* Allocate space for gl_PointSize if it's there */
979 if (vs->state.point_size_idx != -1) {
980 ctx->gp_output_point_size_offt = gp_output_size;
981 gp_output_size += 4 * num;
982 }
983
984 /* gp_output can be too large for the suballocator, so create a
985 * separate bo for it. The bo cache should prevent performance hit.
986 */
987 ctx->gp_output = lima_bo_create(screen, gp_output_size, 0);
988 assert(ctx->gp_output);
989 lima_job_add_bo(job, LIMA_PIPE_GP, ctx->gp_output, LIMA_SUBMIT_BO_WRITE);
990 lima_job_add_bo(job, LIMA_PIPE_PP, ctx->gp_output, LIMA_SUBMIT_BO_READ);
991
992 for (int i = 0; i < vs->state.num_outputs; i++) {
993 struct lima_varying_info *v = vs->state.varying + i;
994
995 if (i == vs->state.gl_pos_idx) {
996 /* gl_Position */
997 varying[n++] = ctx->gp_output->va;
998 varying[n++] = 0x8020;
999 } else if (i == vs->state.point_size_idx) {
1000 /* gl_PointSize */
1001 varying[n++] = ctx->gp_output->va + ctx->gp_output_point_size_offt;
1002 varying[n++] = 0x2021;
1003 } else {
1004 /* Varying */
1005 varying[n++] = ctx->gp_output->va + ctx->gp_output_varyings_offt +
1006 v->offset;
1007 varying[n++] = (vs->state.varying_stride << 11) | (v->components - 1) |
1008 (v->component_size == 2 ? 0x0C : 0);
1009 }
1010 }
1011
1012 lima_dump_command_stream_print(
1013 job->dump, varying, n * 4, false, "update varying info at va %x\n",
1014 lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info));
1015 }
1016
1017 static void
lima_draw_vbo_update(struct pipe_context * pctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)1018 lima_draw_vbo_update(struct pipe_context *pctx,
1019 const struct pipe_draw_info *info,
1020 const struct pipe_draw_start_count_bias *draw)
1021 {
1022 struct lima_context *ctx = lima_context(pctx);
1023 struct lima_context_framebuffer *fb = &ctx->framebuffer;
1024 unsigned buffers = 0;
1025
1026 if (fb->base.zsbuf) {
1027 if (ctx->zsa->base.depth_enabled)
1028 buffers |= PIPE_CLEAR_DEPTH;
1029 if (ctx->zsa->base.stencil[0].enabled ||
1030 ctx->zsa->base.stencil[1].enabled)
1031 buffers |= PIPE_CLEAR_STENCIL;
1032 }
1033
1034 if (fb->base.nr_cbufs)
1035 buffers |= PIPE_CLEAR_COLOR0;
1036
1037 lima_update_job_wb(ctx, buffers);
1038
1039 lima_update_gp_attribute_info(ctx, info, draw);
1040
1041 if ((ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1042 ctx->const_buffer[PIPE_SHADER_VERTEX].dirty) ||
1043 ctx->dirty & LIMA_CONTEXT_DIRTY_VIEWPORT ||
1044 ctx->dirty & LIMA_CONTEXT_DIRTY_COMPILED_VS) {
1045 lima_update_gp_uniform(ctx);
1046 ctx->const_buffer[PIPE_SHADER_VERTEX].dirty = false;
1047 }
1048
1049 lima_update_varying(ctx, info, draw);
1050
1051 lima_pack_vs_cmd(ctx, info, draw);
1052
1053 if (ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF &&
1054 ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty) {
1055 lima_update_pp_uniform(ctx);
1056 ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty = false;
1057 }
1058
1059 lima_update_textures(ctx);
1060
1061 lima_pack_render_state(ctx, info);
1062 lima_pack_plbu_cmd(ctx, info, draw);
1063
1064 if (ctx->gp_output) {
1065 lima_bo_unreference(ctx->gp_output); /* held by job */
1066 ctx->gp_output = NULL;
1067 }
1068
1069 ctx->dirty = 0;
1070 }
1071
1072 static void
lima_draw_vbo_indexed(struct pipe_context * pctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)1073 lima_draw_vbo_indexed(struct pipe_context *pctx,
1074 const struct pipe_draw_info *info,
1075 const struct pipe_draw_start_count_bias *draw)
1076 {
1077 struct lima_context *ctx = lima_context(pctx);
1078 struct lima_job *job = lima_job_get(ctx);
1079 struct pipe_resource *indexbuf = NULL;
1080 bool needs_indices = true;
1081
1082 /* Mali Utgard GPU always need min/max index info for index draw,
1083 * compute it if upper layer does not do for us */
1084 if (info->index_bounds_valid) {
1085 ctx->min_index = info->min_index;
1086 ctx->max_index = info->max_index;
1087 needs_indices = false;
1088 }
1089
1090 if (info->has_user_indices) {
1091 util_upload_index_buffer(&ctx->base, info, draw, &indexbuf, &ctx->index_offset, 0x40);
1092 ctx->index_res = lima_resource(indexbuf);
1093 }
1094 else {
1095 ctx->index_res = lima_resource(info->index.resource);
1096 ctx->index_offset = 0;
1097 needs_indices = !panfrost_minmax_cache_get(ctx->index_res->index_cache, draw->start,
1098 draw->count, &ctx->min_index, &ctx->max_index);
1099 }
1100
1101 if (needs_indices) {
1102 u_vbuf_get_minmax_index(pctx, info, draw, &ctx->min_index, &ctx->max_index);
1103 if (!info->has_user_indices)
1104 panfrost_minmax_cache_add(ctx->index_res->index_cache, draw->start, draw->count,
1105 ctx->min_index, ctx->max_index);
1106 }
1107
1108 lima_job_add_bo(job, LIMA_PIPE_GP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1109 lima_job_add_bo(job, LIMA_PIPE_PP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ);
1110 lima_draw_vbo_update(pctx, info, draw);
1111
1112 if (indexbuf)
1113 pipe_resource_reference(&indexbuf, NULL);
1114 }
1115
1116 static void
lima_draw_vbo_count(struct pipe_context * pctx,const struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draw)1117 lima_draw_vbo_count(struct pipe_context *pctx,
1118 const struct pipe_draw_info *info,
1119 const struct pipe_draw_start_count_bias *draw)
1120 {
1121 static const uint32_t max_verts = 65535;
1122
1123 struct pipe_draw_start_count_bias local_draw = *draw;
1124 unsigned start = draw->start;
1125 unsigned count = draw->count;
1126
1127 while (count) {
1128 unsigned this_count = count;
1129 unsigned step;
1130
1131 u_split_draw(info, max_verts, &this_count, &step);
1132
1133 local_draw.start = start;
1134 local_draw.count = this_count;
1135
1136 lima_draw_vbo_update(pctx, info, &local_draw);
1137
1138 count -= step;
1139 start += step;
1140 }
1141 }
1142
1143 static void
lima_draw_vbo(struct pipe_context * pctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)1144 lima_draw_vbo(struct pipe_context *pctx,
1145 const struct pipe_draw_info *info,
1146 unsigned drawid_offset,
1147 const struct pipe_draw_indirect_info *indirect,
1148 const struct pipe_draw_start_count_bias *draws,
1149 unsigned num_draws)
1150 {
1151 if (num_draws > 1) {
1152 util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
1153 return;
1154 }
1155
1156 /* check if draw mode and vertex/index count match,
1157 * otherwise gp will hang */
1158 if (!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) {
1159 debug_printf("draw mode and vertex/index count mismatch\n");
1160 return;
1161 }
1162
1163 struct lima_context *ctx = lima_context(pctx);
1164
1165 if (!ctx->uncomp_fs || !ctx->uncomp_vs) {
1166 debug_warn_once("no shader, skip draw\n");
1167 return;
1168 }
1169
1170 lima_clip_scissor_to_viewport(ctx);
1171 if (lima_is_scissor_zero(ctx))
1172 return;
1173
1174 if (!lima_update_fs_state(ctx) || !lima_update_vs_state(ctx))
1175 return;
1176
1177 struct lima_job *job = lima_job_get(ctx);
1178 job->pp_max_stack_size = MAX2(job->pp_max_stack_size, ctx->fs->state.stack_size);
1179
1180 lima_dump_command_stream_print(
1181 job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false,
1182 "add vs at va %x\n", ctx->vs->bo->va);
1183 lima_dump_shader(job->dump, ctx->vs->bo->map, ctx->vs->state.shader_size, false);
1184
1185 lima_dump_command_stream_print(
1186 job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, false,
1187 "add fs at va %x\n", ctx->fs->bo->va);
1188 lima_dump_shader(job->dump, ctx->fs->bo->map, ctx->fs->state.shader_size, true);
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
lima_draw_init(struct lima_context * ctx)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