2 * Copyright (C) 2017-2019 Lima Project
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
28 #include "drm-uapi/lima_drm.h"
30 #include "util/u_math.h"
31 #include "util/ralloc.h"
32 #include "util/os_time.h"
33 #include "util/hash_table.h"
34 #include "util/u_upload_mgr.h"
35 #include "util/u_inlines.h"
37 #include "lima_screen.h"
38 #include "lima_context.h"
39 #include "lima_submit.h"
41 #include "lima_util.h"
42 #include "lima_format.h"
43 #include "lima_resource.h"
44 #include "lima_texture.h"
45 #include "lima_fence.h"
48 #define VOID2U64(x) ((uint64_t)(unsigned long)(x))
51 lima_get_fb_info(struct lima_submit
*submit
)
53 struct lima_context
*ctx
= submit
->ctx
;
54 struct lima_submit_fb_info
*fb
= &submit
->fb
;
56 fb
->width
= ctx
->framebuffer
.base
.width
;
57 fb
->height
= ctx
->framebuffer
.base
.height
;
59 int width
= align(fb
->width
, 16) >> 4;
60 int height
= align(fb
->height
, 16) >> 4;
62 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
70 int limit
= screen
->plb_max_blk
;
71 while ((width
* height
) > limit
) {
72 if (width
>= height
) {
73 width
= (width
+ 1) >> 1;
76 height
= (height
+ 1) >> 1;
84 fb
->shift_min
= MIN3(fb
->shift_w
, fb
->shift_h
, 2);
87 static struct lima_submit
*
88 lima_submit_create(struct lima_context
*ctx
)
90 struct lima_submit
*s
;
92 s
= rzalloc(ctx
, struct lima_submit
);
96 s
->fd
= lima_screen(ctx
->base
.screen
)->fd
;
99 s
->damage_rect
.minx
= s
->damage_rect
.miny
= 0xffff;
100 s
->damage_rect
.maxx
= s
->damage_rect
.maxy
= 0;
102 for (int i
= 0; i
< 2; i
++) {
103 util_dynarray_init(s
->gem_bos
+ i
, s
);
104 util_dynarray_init(s
->bos
+ i
, s
);
107 util_dynarray_init(&s
->vs_cmd_array
, s
);
108 util_dynarray_init(&s
->plbu_cmd_array
, s
);
109 util_dynarray_init(&s
->plbu_cmd_head
, s
);
111 struct lima_context_framebuffer
*fb
= &ctx
->framebuffer
;
112 pipe_surface_reference(&s
->key
.cbuf
, fb
->base
.cbufs
[0]);
113 pipe_surface_reference(&s
->key
.zsbuf
, fb
->base
.zsbuf
);
121 lima_submit_free(struct lima_submit
*submit
)
123 struct lima_context
*ctx
= submit
->ctx
;
125 _mesa_hash_table_remove_key(ctx
->submits
, &submit
->key
);
127 if (submit
->key
.cbuf
&& (submit
->resolve
& PIPE_CLEAR_COLOR0
))
128 _mesa_hash_table_remove_key(ctx
->write_submits
, submit
->key
.cbuf
->texture
);
129 if (submit
->key
.zsbuf
&& (submit
->resolve
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)))
130 _mesa_hash_table_remove_key(ctx
->write_submits
, submit
->key
.zsbuf
->texture
);
132 pipe_surface_reference(&submit
->key
.cbuf
, NULL
);
133 pipe_surface_reference(&submit
->key
.zsbuf
, NULL
);
135 /* TODO: do we need a cache for submit? */
139 static struct lima_submit
*
140 _lima_submit_get(struct lima_context
*ctx
)
142 struct lima_context_framebuffer
*fb
= &ctx
->framebuffer
;
143 struct lima_submit_key local_key
= {
144 .cbuf
= fb
->base
.cbufs
[0],
145 .zsbuf
= fb
->base
.zsbuf
,
148 struct hash_entry
*entry
= _mesa_hash_table_search(ctx
->submits
, &local_key
);
152 struct lima_submit
*submit
= lima_submit_create(ctx
);
156 _mesa_hash_table_insert(ctx
->submits
, &submit
->key
, submit
);
162 * Note: this function can only be called in draw code path,
163 * must not exist in flush code path.
166 lima_submit_get(struct lima_context
*ctx
)
171 ctx
->submit
= _lima_submit_get(ctx
);
175 bool lima_submit_add_bo(struct lima_submit
*submit
, int pipe
,
176 struct lima_bo
*bo
, uint32_t flags
)
178 util_dynarray_foreach(submit
->gem_bos
+ pipe
, struct drm_lima_gem_submit_bo
, gem_bo
) {
179 if (bo
->handle
== gem_bo
->handle
) {
180 gem_bo
->flags
|= flags
;
185 struct drm_lima_gem_submit_bo
*submit_bo
=
186 util_dynarray_grow(submit
->gem_bos
+ pipe
, struct drm_lima_gem_submit_bo
, 1);
187 submit_bo
->handle
= bo
->handle
;
188 submit_bo
->flags
= flags
;
190 struct lima_bo
**jbo
= util_dynarray_grow(submit
->bos
+ pipe
, struct lima_bo
*, 1);
193 /* prevent bo from being freed when submit start */
194 lima_bo_reference(bo
);
200 lima_submit_start(struct lima_submit
*submit
, int pipe
, void *frame
, uint32_t size
)
202 struct lima_context
*ctx
= submit
->ctx
;
203 struct drm_lima_gem_submit req
= {
206 .nr_bos
= submit
->gem_bos
[pipe
].size
/ sizeof(struct drm_lima_gem_submit_bo
),
207 .bos
= VOID2U64(util_dynarray_begin(submit
->gem_bos
+ pipe
)),
208 .frame
= VOID2U64(frame
),
210 .out_sync
= ctx
->out_sync
[pipe
],
213 if (ctx
->in_sync_fd
>= 0) {
214 int err
= drmSyncobjImportSyncFile(submit
->fd
, ctx
->in_sync
[pipe
],
219 req
.in_sync
[0] = ctx
->in_sync
[pipe
];
220 close(ctx
->in_sync_fd
);
221 ctx
->in_sync_fd
= -1;
224 bool ret
= drmIoctl(submit
->fd
, DRM_IOCTL_LIMA_GEM_SUBMIT
, &req
) == 0;
226 util_dynarray_foreach(submit
->bos
+ pipe
, struct lima_bo
*, bo
) {
227 lima_bo_unreference(*bo
);
234 lima_submit_wait(struct lima_submit
*submit
, int pipe
, uint64_t timeout_ns
)
236 int64_t abs_timeout
= os_time_get_absolute_timeout(timeout_ns
);
237 if (abs_timeout
== OS_TIMEOUT_INFINITE
)
238 abs_timeout
= INT64_MAX
;
240 struct lima_context
*ctx
= submit
->ctx
;
241 return !drmSyncobjWait(submit
->fd
, ctx
->out_sync
+ pipe
, 1, abs_timeout
, 0, NULL
);
245 lima_submit_has_bo(struct lima_submit
*submit
, struct lima_bo
*bo
, bool all
)
247 for (int i
= 0; i
< 2; i
++) {
248 util_dynarray_foreach(submit
->gem_bos
+ i
, struct drm_lima_gem_submit_bo
, gem_bo
) {
249 if (bo
->handle
== gem_bo
->handle
) {
250 if (all
|| gem_bo
->flags
& LIMA_SUBMIT_BO_WRITE
)
262 lima_submit_create_stream_bo(struct lima_submit
*submit
, int pipe
,
263 unsigned size
, uint32_t *va
)
265 struct lima_context
*ctx
= submit
->ctx
;
269 struct pipe_resource
*pres
= NULL
;
270 u_upload_alloc(ctx
->uploader
, 0, size
, 0x40, &offset
, &pres
, &cpu
);
272 struct lima_resource
*res
= lima_resource(pres
);
273 *va
= res
->bo
->va
+ offset
;
275 lima_submit_add_bo(submit
, pipe
, res
->bo
, LIMA_SUBMIT_BO_READ
);
277 pipe_resource_reference(&pres
, NULL
);
282 static inline struct lima_damage_region
*
283 lima_submit_get_damage(struct lima_submit
*submit
)
285 if (!(submit
->key
.cbuf
&& (submit
->resolve
& PIPE_CLEAR_COLOR0
)))
288 struct lima_surface
*surf
= lima_surface(submit
->key
.cbuf
);
289 struct lima_resource
*res
= lima_resource(surf
->base
.texture
);
294 lima_fb_need_reload(struct lima_submit
*submit
)
296 /* Depth buffer is always discarded */
297 if (!(submit
->key
.cbuf
&& (submit
->resolve
& PIPE_CLEAR_COLOR0
)))
300 struct lima_surface
*surf
= lima_surface(submit
->key
.cbuf
);
301 struct lima_resource
*res
= lima_resource(surf
->base
.texture
);
302 if (res
->damage
.region
) {
303 /* for EGL_KHR_partial_update, when EGL_EXT_buffer_age is enabled,
304 * we need to reload damage region, otherwise just want to reload
305 * the region not aligned to tile boundary */
306 //if (!res->damage.aligned)
310 else if (surf
->reload
)
317 lima_pack_reload_plbu_cmd(struct lima_submit
*submit
)
319 #define lima_reload_render_state_offset 0x0000
320 #define lima_reload_gl_pos_offset 0x0040
321 #define lima_reload_varying_offset 0x0080
322 #define lima_reload_tex_desc_offset 0x00c0
323 #define lima_reload_tex_array_offset 0x0100
324 #define lima_reload_buffer_size 0x0140
326 struct lima_context
*ctx
= submit
->ctx
;
329 void *cpu
= lima_submit_create_stream_bo(
330 submit
, LIMA_PIPE_PP
, lima_reload_buffer_size
, &va
);
332 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
334 uint32_t reload_shader_first_instr_size
=
335 ((uint32_t *)(screen
->pp_buffer
->map
+ pp_reload_program_offset
))[0] & 0x1f;
336 uint32_t reload_shader_va
= screen
->pp_buffer
->va
+ pp_reload_program_offset
;
338 struct lima_render_state reload_render_state
= {
339 .alpha_blend
= 0xf03b1ad2,
340 .depth_test
= 0x0000000e,
341 .depth_range
= 0xffff0000,
342 .stencil_front
= 0x00000007,
343 .stencil_back
= 0x00000007,
344 .multi_sample
= 0x0000f007,
345 .shader_address
= reload_shader_va
| reload_shader_first_instr_size
,
346 .varying_types
= 0x00000001,
347 .textures_address
= va
+ lima_reload_tex_array_offset
,
349 .varyings_address
= va
+ lima_reload_varying_offset
,
351 memcpy(cpu
+ lima_reload_render_state_offset
, &reload_render_state
,
352 sizeof(reload_render_state
));
354 lima_tex_desc
*td
= cpu
+ lima_reload_tex_desc_offset
;
355 memset(td
, 0, lima_min_tex_desc_size
);
356 lima_texture_desc_set_res(ctx
, td
, submit
->key
.cbuf
->texture
, 0, 0);
357 td
->unnorm_coords
= 1;
358 td
->texture_type
= LIMA_TEXTURE_TYPE_2D
;
359 td
->min_img_filter_nearest
= 1;
360 td
->mag_img_filter_nearest
= 1;
361 td
->wrap_s_clamp_to_edge
= 1;
362 td
->wrap_t_clamp_to_edge
= 1;
363 td
->unknown_2_2
= 0x1;
365 uint32_t *ta
= cpu
+ lima_reload_tex_array_offset
;
366 ta
[0] = va
+ lima_reload_tex_desc_offset
;
368 struct lima_submit_fb_info
*fb
= &submit
->fb
;
369 float reload_gl_pos
[] = {
374 memcpy(cpu
+ lima_reload_gl_pos_offset
, reload_gl_pos
,
375 sizeof(reload_gl_pos
));
377 float reload_varying
[] = {
381 memcpy(cpu
+ lima_reload_varying_offset
, reload_varying
,
382 sizeof(reload_varying
));
384 PLBU_CMD_BEGIN(&submit
->plbu_cmd_head
, 20);
386 PLBU_CMD_VIEWPORT_LEFT(0);
387 PLBU_CMD_VIEWPORT_RIGHT(fui(fb
->width
));
388 PLBU_CMD_VIEWPORT_BOTTOM(0);
389 PLBU_CMD_VIEWPORT_TOP(fui(fb
->height
));
391 PLBU_CMD_RSW_VERTEX_ARRAY(
392 va
+ lima_reload_render_state_offset
,
393 va
+ lima_reload_gl_pos_offset
);
398 PLBU_CMD_INDICES(screen
->pp_buffer
->va
+ pp_shared_index_offset
);
399 PLBU_CMD_INDEXED_DEST(va
+ lima_reload_gl_pos_offset
);
400 PLBU_CMD_DRAW_ELEMENTS(0xf, 0, 3);
406 lima_pack_head_plbu_cmd(struct lima_submit
*submit
)
408 struct lima_context
*ctx
= submit
->ctx
;
409 struct lima_submit_fb_info
*fb
= &submit
->fb
;
411 PLBU_CMD_BEGIN(&submit
->plbu_cmd_head
, 10);
414 PLBU_CMD_BLOCK_STEP(fb
->shift_min
, fb
->shift_h
, fb
->shift_w
);
415 PLBU_CMD_TILED_DIMENSIONS(fb
->tiled_w
, fb
->tiled_h
);
416 PLBU_CMD_BLOCK_STRIDE(fb
->block_w
);
418 PLBU_CMD_ARRAY_ADDRESS(
419 ctx
->plb_gp_stream
->va
+ ctx
->plb_index
* ctx
->plb_gp_size
,
420 fb
->block_w
* fb
->block_h
);
424 if (lima_fb_need_reload(submit
))
425 lima_pack_reload_plbu_cmd(submit
);
429 hilbert_rotate(int n
, int *x
, int *y
, int rx
, int ry
)
445 hilbert_coords(int n
, int d
, int *x
, int *y
)
451 for (i
= 0; (1 << i
) < n
; i
++) {
456 hilbert_rotate(1 << i
, x
, y
, rx
, ry
);
466 lima_get_pp_stream_size(int num_pp
, int tiled_w
, int tiled_h
, uint32_t *off
)
468 /* carefully calculate each stream start address:
469 * 1. overflow: each stream size may be different due to
470 * fb->tiled_w * fb->tiled_h can't be divided by num_pp,
471 * extra size should be added to the preceeding stream
472 * 2. alignment: each stream address should be 0x20 aligned
474 int delta
= tiled_w
* tiled_h
/ num_pp
* 16 + 16;
475 int remain
= tiled_w
* tiled_h
% num_pp
;
478 for (int i
= 0; i
< num_pp
; i
++) {
486 offset
= align(offset
, 0x20);
493 inside_damage_region(int x
, int y
, struct lima_damage_region
*ds
)
495 if (!ds
|| !ds
->region
)
498 for (int i
= 0; i
< ds
->num_region
; i
++) {
499 struct pipe_scissor_state
*ss
= ds
->region
+ i
;
500 if (x
>= ss
->minx
&& x
< ss
->maxx
&&
501 y
>= ss
->miny
&& y
< ss
->maxy
)
509 lima_generate_pp_stream(struct lima_submit
*submit
, int off_x
, int off_y
,
510 int tiled_w
, int tiled_h
)
512 struct lima_context
*ctx
= submit
->ctx
;
513 struct lima_pp_stream_state
*ps
= &ctx
->pp_stream
;
514 struct lima_submit_fb_info
*fb
= &submit
->fb
;
515 struct lima_damage_region
*damage
= lima_submit_get_damage(submit
);
516 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
517 int i
, num_pp
= screen
->num_pp
;
519 /* use hilbert_coords to generates 1D to 2D relationship.
520 * 1D for pp stream index and 2D for plb block x/y on framebuffer.
521 * if multi pp, interleave the 1D index to make each pp's render target
522 * close enough which should result close workload
524 int max
= MAX2(tiled_w
, tiled_h
);
531 /* Don't update count if we get zero rect. We'll just generate
532 * PP stream with just terminators in it.
534 if ((tiled_w
* tiled_h
) != 0) {
535 dim
= util_logbase2_ceil(max
);
536 count
= 1 << (dim
+ dim
);
539 for (i
= 0; i
< num_pp
; i
++)
540 stream
[i
] = ps
->map
+ ps
->offset
[i
];
542 for (i
= 0; i
< count
; i
++) {
544 hilbert_coords(max
, i
, &x
, &y
);
545 if (x
< tiled_w
&& y
< tiled_h
) {
549 if (!inside_damage_region(x
, y
, damage
))
552 int pp
= index
% num_pp
;
553 int offset
= ((y
>> fb
->shift_h
) * fb
->block_w
+
554 (x
>> fb
->shift_w
)) * LIMA_CTX_PLB_BLK_SIZE
;
555 int plb_va
= ctx
->plb
[ctx
->plb_index
]->va
+ offset
;
557 stream
[pp
][si
[pp
]++] = 0;
558 stream
[pp
][si
[pp
]++] = 0xB8000000 | x
| (y
<< 8);
559 stream
[pp
][si
[pp
]++] = 0xE0000002 | ((plb_va
>> 3) & ~0xE0000003);
560 stream
[pp
][si
[pp
]++] = 0xB0000000;
566 for (i
= 0; i
< num_pp
; i
++) {
567 stream
[i
][si
[i
]++] = 0;
568 stream
[i
][si
[i
]++] = 0xBC000000;
569 stream
[i
][si
[i
]++] = 0;
570 stream
[i
][si
[i
]++] = 0;
572 lima_dump_command_stream_print(
573 stream
[i
], si
[i
] * 4, false, "pp plb stream %d at va %x\n",
574 i
, ps
->va
+ ps
->offset
[i
]);
579 lima_update_damage_pp_stream(struct lima_submit
*submit
)
581 struct lima_context
*ctx
= submit
->ctx
;
582 struct lima_damage_region
*ds
= lima_submit_get_damage(submit
);
583 struct lima_submit_fb_info
*fb
= &submit
->fb
;
584 struct pipe_scissor_state bound
;
585 struct pipe_scissor_state
*dr
= &submit
->damage_rect
;
587 if (ds
&& ds
->region
) {
588 struct pipe_scissor_state
*dbound
= &ds
->bound
;
589 bound
.minx
= MAX2(dbound
->minx
, dr
->minx
>> 4);
590 bound
.miny
= MAX2(dbound
->miny
, dr
->miny
>> 4);
591 bound
.maxx
= MIN2(dbound
->maxx
, (dr
->maxx
+ 0xf) >> 4);
592 bound
.maxy
= MIN2(dbound
->maxy
, (dr
->maxy
+ 0xf) >> 4);
594 bound
.minx
= dr
->minx
>> 4;
595 bound
.miny
= dr
->miny
>> 4;
596 bound
.maxx
= (dr
->maxx
+ 0xf) >> 4;
597 bound
.maxy
= (dr
->maxy
+ 0xf) >> 4;
600 /* Clamp to FB size */
601 bound
.minx
= MIN2(bound
.minx
, fb
->tiled_w
);
602 bound
.miny
= MIN2(bound
.miny
, fb
->tiled_h
);
603 bound
.maxx
= MIN2(bound
.maxx
, fb
->tiled_w
);
604 bound
.maxy
= MIN2(bound
.maxy
, fb
->tiled_h
);
606 int tiled_w
= bound
.maxx
- bound
.minx
;
607 int tiled_h
= bound
.maxy
- bound
.miny
;
609 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
610 int size
= lima_get_pp_stream_size(
611 screen
->num_pp
, tiled_w
, tiled_h
, ctx
->pp_stream
.offset
);
613 ctx
->pp_stream
.map
= lima_submit_create_stream_bo(
614 submit
, LIMA_PIPE_PP
, size
, &ctx
->pp_stream
.va
);
616 lima_generate_pp_stream(submit
, bound
.minx
, bound
.miny
, tiled_w
, tiled_h
);
620 lima_update_full_pp_stream(struct lima_submit
*submit
)
622 struct lima_context
*ctx
= submit
->ctx
;
623 struct lima_submit_fb_info
*fb
= &submit
->fb
;
624 struct lima_ctx_plb_pp_stream_key key
= {
625 .plb_index
= ctx
->plb_index
,
626 .tiled_w
= fb
->tiled_w
,
627 .tiled_h
= fb
->tiled_h
,
630 struct hash_entry
*entry
=
631 _mesa_hash_table_search(ctx
->plb_pp_stream
, &key
);
632 struct lima_ctx_plb_pp_stream
*s
= entry
->data
;
635 ctx
->pp_stream
.map
= lima_bo_map(s
->bo
);
636 ctx
->pp_stream
.va
= s
->bo
->va
;
637 memcpy(ctx
->pp_stream
.offset
, s
->offset
, sizeof(s
->offset
));
640 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
641 int size
= lima_get_pp_stream_size(
642 screen
->num_pp
, fb
->tiled_w
, fb
->tiled_h
, s
->offset
);
643 s
->bo
= lima_bo_create(screen
, size
, 0);
645 ctx
->pp_stream
.map
= lima_bo_map(s
->bo
);
646 ctx
->pp_stream
.va
= s
->bo
->va
;
647 memcpy(ctx
->pp_stream
.offset
, s
->offset
, sizeof(s
->offset
));
649 lima_generate_pp_stream(submit
, 0, 0, fb
->tiled_w
, fb
->tiled_h
);
652 lima_submit_add_bo(submit
, LIMA_PIPE_PP
, s
->bo
, LIMA_SUBMIT_BO_READ
);
656 lima_damage_fullscreen(struct lima_submit
*submit
)
658 struct pipe_scissor_state
*dr
= &submit
->damage_rect
;
660 return dr
->minx
== 0 &&
662 dr
->maxx
== submit
->fb
.width
&&
663 dr
->maxy
== submit
->fb
.height
;
667 lima_update_pp_stream(struct lima_submit
*submit
)
669 struct lima_context
*ctx
= submit
->ctx
;
670 struct lima_damage_region
*damage
= lima_submit_get_damage(submit
);
671 if ((damage
&& damage
->region
) || !lima_damage_fullscreen(submit
))
672 lima_update_damage_pp_stream(submit
);
673 else if (ctx
->plb_pp_stream
)
674 lima_update_full_pp_stream(submit
);
676 ctx
->pp_stream
.map
= NULL
;
680 lima_update_submit_bo(struct lima_submit
*submit
)
682 struct lima_context
*ctx
= submit
->ctx
;
684 lima_submit_add_bo(submit
, LIMA_PIPE_GP
, ctx
->plb_gp_stream
,
685 LIMA_SUBMIT_BO_READ
);
686 lima_submit_add_bo(submit
, LIMA_PIPE_GP
, ctx
->plb
[ctx
->plb_index
],
687 LIMA_SUBMIT_BO_WRITE
);
688 lima_submit_add_bo(submit
, LIMA_PIPE_GP
, ctx
->gp_tile_heap
[ctx
->plb_index
],
689 LIMA_SUBMIT_BO_WRITE
);
691 lima_dump_command_stream_print(
692 ctx
->plb_gp_stream
->map
+ ctx
->plb_index
* ctx
->plb_gp_size
,
693 ctx
->plb_gp_size
, false, "gp plb stream at va %x\n",
694 ctx
->plb_gp_stream
->va
+ ctx
->plb_index
* ctx
->plb_gp_size
);
696 lima_submit_add_bo(submit
, LIMA_PIPE_PP
, ctx
->plb
[ctx
->plb_index
],
697 LIMA_SUBMIT_BO_READ
);
698 lima_submit_add_bo(submit
, LIMA_PIPE_PP
, ctx
->gp_tile_heap
[ctx
->plb_index
],
699 LIMA_SUBMIT_BO_READ
);
701 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
702 lima_submit_add_bo(submit
, LIMA_PIPE_PP
, screen
->pp_buffer
, LIMA_SUBMIT_BO_READ
);
706 lima_finish_plbu_cmd(struct util_dynarray
*plbu_cmd_array
)
709 uint32_t *plbu_cmd
= util_dynarray_ensure_cap(plbu_cmd_array
, plbu_cmd_array
->size
+ 2 * 4);
711 plbu_cmd
[i
++] = 0x00000000;
712 plbu_cmd
[i
++] = 0x50000000; /* END */
714 plbu_cmd_array
->size
+= i
* 4;
718 lima_pack_wb_zsbuf_reg(struct lima_submit
*submit
, uint32_t *wb_reg
, int wb_idx
)
720 struct lima_submit_fb_info
*fb
= &submit
->fb
;
721 struct pipe_surface
*zsbuf
= submit
->key
.zsbuf
;
722 struct lima_resource
*res
= lima_resource(zsbuf
->texture
);
723 int level
= zsbuf
->u
.tex
.level
;
724 uint32_t format
= lima_format_get_pixel(zsbuf
->format
);
726 struct lima_pp_wb_reg
*wb
= (void *)wb_reg
;
727 wb
[wb_idx
].type
= 0x01; /* 1 for depth, stencil */
728 wb
[wb_idx
].address
= res
->bo
->va
+ res
->levels
[level
].offset
;
729 wb
[wb_idx
].pixel_format
= format
;
731 wb
[wb_idx
].pixel_layout
= 0x2;
732 wb
[wb_idx
].pitch
= fb
->tiled_w
;
734 wb
[wb_idx
].pixel_layout
= 0x0;
735 wb
[wb_idx
].pitch
= res
->levels
[level
].stride
/ 8;
737 wb
[wb_idx
].mrt_bits
= 0;
741 lima_pack_wb_cbuf_reg(struct lima_submit
*submit
, uint32_t *wb_reg
, int wb_idx
)
743 struct lima_submit_fb_info
*fb
= &submit
->fb
;
744 struct pipe_surface
*cbuf
= submit
->key
.cbuf
;
745 struct lima_resource
*res
= lima_resource(cbuf
->texture
);
746 int level
= cbuf
->u
.tex
.level
;
747 unsigned layer
= cbuf
->u
.tex
.first_layer
;
748 uint32_t format
= lima_format_get_pixel(cbuf
->format
);
749 bool swap_channels
= lima_format_get_swap_rb(cbuf
->format
);
751 struct lima_pp_wb_reg
*wb
= (void *)wb_reg
;
752 wb
[wb_idx
].type
= 0x02; /* 2 for color buffer */
753 wb
[wb_idx
].address
= res
->bo
->va
+ res
->levels
[level
].offset
+ layer
* res
->levels
[level
].layer_stride
;
754 wb
[wb_idx
].pixel_format
= format
;
756 wb
[wb_idx
].pixel_layout
= 0x2;
757 wb
[wb_idx
].pitch
= fb
->tiled_w
;
759 wb
[wb_idx
].pixel_layout
= 0x0;
760 wb
[wb_idx
].pitch
= res
->levels
[level
].stride
/ 8;
762 wb
[wb_idx
].mrt_bits
= swap_channels
? 0x4 : 0x0;
766 lima_pack_pp_frame_reg(struct lima_submit
*submit
, uint32_t *frame_reg
,
769 struct lima_context
*ctx
= submit
->ctx
;
770 struct lima_submit_fb_info
*fb
= &submit
->fb
;
771 struct lima_pp_frame_reg
*frame
= (void *)frame_reg
;
772 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
775 frame
->render_address
= screen
->pp_buffer
->va
+ pp_frame_rsw_offset
;
777 frame
->clear_value_depth
= submit
->clear
.depth
;
778 frame
->clear_value_stencil
= submit
->clear
.stencil
;
779 frame
->clear_value_color
= submit
->clear
.color_8pc
;
780 frame
->clear_value_color_1
= submit
->clear
.color_8pc
;
781 frame
->clear_value_color_2
= submit
->clear
.color_8pc
;
782 frame
->clear_value_color_3
= submit
->clear
.color_8pc
;
785 frame
->width
= fb
->width
- 1;
786 frame
->height
= fb
->height
- 1;
788 /* frame->fragment_stack_address is overwritten per-pp in the kernel
789 * by the values of pp_frame.fragment_stack_address[i] */
791 /* These are "stack size" and "stack offset" shifted,
792 * here they are assumed to be always the same. */
793 frame
->fragment_stack_size
= submit
->pp_max_stack_size
<< 16 | submit
->pp_max_stack_size
;
795 /* related with MSAA and different value when r4p0/r7p0 */
796 frame
->supersampled_height
= fb
->height
* 2 - 1;
797 frame
->scale
= 0xE0C;
801 frame
->blocking
= (fb
->shift_min
<< 28) | (fb
->shift_h
<< 16) | fb
->shift_w
;
802 frame
->foureight
= 0x8888;
804 if (submit
->key
.cbuf
&& (submit
->resolve
& PIPE_CLEAR_COLOR0
))
805 lima_pack_wb_cbuf_reg(submit
, wb_reg
, wb_idx
++);
807 if (submit
->key
.zsbuf
&&
808 (submit
->resolve
& (PIPE_CLEAR_DEPTH
| PIPE_CLEAR_STENCIL
)))
809 lima_pack_wb_zsbuf_reg(submit
, wb_reg
, wb_idx
++);
813 lima_do_submit(struct lima_submit
*submit
)
815 #define pp_stack_pp_size 0x400
817 struct lima_context
*ctx
= submit
->ctx
;
819 lima_pack_head_plbu_cmd(submit
);
820 lima_finish_plbu_cmd(&submit
->plbu_cmd_array
);
822 lima_update_submit_bo(submit
);
824 int vs_cmd_size
= submit
->vs_cmd_array
.size
;
825 uint32_t vs_cmd_va
= 0;
828 void *vs_cmd
= lima_submit_create_stream_bo(
829 submit
, LIMA_PIPE_GP
, vs_cmd_size
, &vs_cmd_va
);
830 memcpy(vs_cmd
, util_dynarray_begin(&submit
->vs_cmd_array
), vs_cmd_size
);
832 lima_dump_command_stream_print(
833 vs_cmd
, vs_cmd_size
, false, "flush vs cmd at va %x\n", vs_cmd_va
);
834 lima_dump_vs_command_stream_print(vs_cmd
, vs_cmd_size
, vs_cmd_va
);
837 uint32_t plbu_cmd_va
;
838 int plbu_cmd_size
= submit
->plbu_cmd_array
.size
+ submit
->plbu_cmd_head
.size
;
839 void *plbu_cmd
= lima_submit_create_stream_bo(
840 submit
, LIMA_PIPE_GP
, plbu_cmd_size
, &plbu_cmd_va
);
842 util_dynarray_begin(&submit
->plbu_cmd_head
),
843 submit
->plbu_cmd_head
.size
);
844 memcpy(plbu_cmd
+ submit
->plbu_cmd_head
.size
,
845 util_dynarray_begin(&submit
->plbu_cmd_array
),
846 submit
->plbu_cmd_array
.size
);
848 lima_dump_command_stream_print(
849 plbu_cmd
, plbu_cmd_size
, false, "flush plbu cmd at va %x\n", plbu_cmd_va
);
850 lima_dump_plbu_command_stream_print(plbu_cmd
, plbu_cmd_size
, plbu_cmd_va
);
852 struct lima_screen
*screen
= lima_screen(ctx
->base
.screen
);
853 struct drm_lima_gp_frame gp_frame
;
854 struct lima_gp_frame_reg
*gp_frame_reg
= (void *)gp_frame
.frame
;
855 gp_frame_reg
->vs_cmd_start
= vs_cmd_va
;
856 gp_frame_reg
->vs_cmd_end
= vs_cmd_va
+ vs_cmd_size
;
857 gp_frame_reg
->plbu_cmd_start
= plbu_cmd_va
;
858 gp_frame_reg
->plbu_cmd_end
= plbu_cmd_va
+ plbu_cmd_size
;
859 gp_frame_reg
->tile_heap_start
= ctx
->gp_tile_heap
[ctx
->plb_index
]->va
;
860 gp_frame_reg
->tile_heap_end
= ctx
->gp_tile_heap
[ctx
->plb_index
]->va
+ ctx
->gp_tile_heap_size
;
862 lima_dump_command_stream_print(
863 &gp_frame
, sizeof(gp_frame
), false, "add gp frame\n");
865 if (!lima_submit_start(submit
, LIMA_PIPE_GP
, &gp_frame
, sizeof(gp_frame
)))
866 fprintf(stderr
, "gp submit error\n");
868 if (lima_dump_command_stream
) {
869 if (lima_submit_wait(submit
, LIMA_PIPE_GP
, PIPE_TIMEOUT_INFINITE
)) {
870 if (ctx
->gp_output
) {
871 float *pos
= lima_bo_map(ctx
->gp_output
);
872 lima_dump_command_stream_print(
873 pos
, 4 * 4 * 16, true, "gl_pos dump at va %x\n",
877 uint32_t *plb
= lima_bo_map(ctx
->plb
[ctx
->plb_index
]);
878 lima_dump_command_stream_print(
879 plb
, LIMA_CTX_PLB_BLK_SIZE
, false, "plb dump at va %x\n",
880 ctx
->plb
[ctx
->plb_index
]->va
);
883 fprintf(stderr
, "gp submit wait error\n");
888 uint32_t pp_stack_va
= 0;
889 if (submit
->pp_max_stack_size
) {
890 lima_submit_create_stream_bo(
891 submit
, LIMA_PIPE_PP
,
892 screen
->num_pp
* submit
->pp_max_stack_size
* pp_stack_pp_size
,
896 lima_update_pp_stream(submit
);
898 struct lima_pp_stream_state
*ps
= &ctx
->pp_stream
;
899 if (screen
->gpu_type
== DRM_LIMA_PARAM_GPU_ID_MALI400
) {
900 struct drm_lima_m400_pp_frame pp_frame
= {0};
901 lima_pack_pp_frame_reg(submit
, pp_frame
.frame
, pp_frame
.wb
);
902 pp_frame
.num_pp
= screen
->num_pp
;
904 for (int i
= 0; i
< screen
->num_pp
; i
++) {
905 pp_frame
.plbu_array_address
[i
] = ps
->va
+ ps
->offset
[i
];
906 if (submit
->pp_max_stack_size
)
907 pp_frame
.fragment_stack_address
[i
] = pp_stack_va
+
908 submit
->pp_max_stack_size
* pp_stack_pp_size
* i
;
911 lima_dump_command_stream_print(
912 &pp_frame
, sizeof(pp_frame
), false, "add pp frame\n");
914 if (!lima_submit_start(submit
, LIMA_PIPE_PP
, &pp_frame
, sizeof(pp_frame
)))
915 fprintf(stderr
, "pp submit error\n");
918 struct drm_lima_m450_pp_frame pp_frame
= {0};
919 lima_pack_pp_frame_reg(submit
, pp_frame
.frame
, pp_frame
.wb
);
920 pp_frame
.num_pp
= screen
->num_pp
;
922 if (submit
->pp_max_stack_size
)
923 for (int i
= 0; i
< screen
->num_pp
; i
++)
924 pp_frame
.fragment_stack_address
[i
] = pp_stack_va
+
925 submit
->pp_max_stack_size
* pp_stack_pp_size
* i
;
928 for (int i
= 0; i
< screen
->num_pp
; i
++)
929 pp_frame
.plbu_array_address
[i
] = ps
->va
+ ps
->offset
[i
];
932 pp_frame
.use_dlbu
= true;
934 struct lima_submit_fb_info
*fb
= &submit
->fb
;
935 pp_frame
.dlbu_regs
[0] = ctx
->plb
[ctx
->plb_index
]->va
;
936 pp_frame
.dlbu_regs
[1] = ((fb
->tiled_h
- 1) << 16) | (fb
->tiled_w
- 1);
937 unsigned s
= util_logbase2(LIMA_CTX_PLB_BLK_SIZE
) - 7;
938 pp_frame
.dlbu_regs
[2] = (s
<< 28) | (fb
->shift_h
<< 16) | fb
->shift_w
;
939 pp_frame
.dlbu_regs
[3] = ((fb
->tiled_h
- 1) << 24) | ((fb
->tiled_w
- 1) << 16);
942 lima_dump_command_stream_print(
943 &pp_frame
, sizeof(pp_frame
), false, "add pp frame\n");
945 if (!lima_submit_start(submit
, LIMA_PIPE_PP
, &pp_frame
, sizeof(pp_frame
)))
946 fprintf(stderr
, "pp submit error\n");
949 if (lima_dump_command_stream
) {
950 if (!lima_submit_wait(submit
, LIMA_PIPE_PP
, PIPE_TIMEOUT_INFINITE
)) {
951 fprintf(stderr
, "pp wait error\n");
956 ctx
->plb_index
= (ctx
->plb_index
+ 1) % lima_ctx_num_plb
;
958 if (submit
->key
.cbuf
&& (submit
->resolve
& PIPE_CLEAR_COLOR0
)) {
959 /* Set reload flag for next draw. It'll be unset if buffer is cleared */
960 struct lima_surface
*surf
= lima_surface(submit
->key
.cbuf
);
964 lima_dump_file_next();
966 if (ctx
->submit
== submit
)
969 lima_submit_free(submit
);
973 lima_flush(struct lima_context
*ctx
)
975 hash_table_foreach(ctx
->submits
, entry
) {
976 struct lima_submit
*submit
= entry
->data
;
977 lima_do_submit(submit
);
982 lima_flush_submit_accessing_bo(
983 struct lima_context
*ctx
, struct lima_bo
*bo
, bool write
)
985 hash_table_foreach(ctx
->submits
, entry
) {
986 struct lima_submit
*submit
= entry
->data
;
987 if (lima_submit_has_bo(submit
, bo
, write
))
988 lima_do_submit(submit
);
993 * This is for current submit flush previous submit which write to the resource it wants
994 * to read. Tipical usage is flush the FBO which is used as current task's texture.
997 lima_flush_previous_submit_writing_resource(
998 struct lima_context
*ctx
, struct pipe_resource
*prsc
)
1000 struct hash_entry
*entry
= _mesa_hash_table_search(ctx
->write_submits
, prsc
);
1003 struct lima_submit
*submit
= entry
->data
;
1005 /* do not flush current submit */
1006 if (submit
!= ctx
->submit
)
1007 lima_do_submit(submit
);
1012 lima_pipe_flush(struct pipe_context
*pctx
, struct pipe_fence_handle
**fence
,
1015 struct lima_context
*ctx
= lima_context(pctx
);
1020 int drm_fd
= lima_screen(ctx
->base
.screen
)->fd
;
1023 if (!drmSyncobjExportSyncFile(drm_fd
, ctx
->out_sync
[LIMA_PIPE_PP
], &fd
))
1024 *fence
= lima_fence_create(fd
);
1029 lima_submit_compare(const void *s1
, const void *s2
)
1031 return memcmp(s1
, s2
, sizeof(struct lima_submit_key
)) == 0;
1035 lima_submit_hash(const void *key
)
1037 return _mesa_hash_data(key
, sizeof(struct lima_submit_key
));
1040 bool lima_submit_init(struct lima_context
*ctx
)
1042 int fd
= lima_screen(ctx
->base
.screen
)->fd
;
1044 ctx
->submits
= _mesa_hash_table_create(ctx
, lima_submit_hash
, lima_submit_compare
);
1048 ctx
->write_submits
= _mesa_hash_table_create(
1049 ctx
, _mesa_hash_pointer
, _mesa_key_pointer_equal
);
1050 if (!ctx
->write_submits
)
1053 ctx
->in_sync_fd
= -1;
1055 for (int i
= 0; i
< 2; i
++) {
1056 if (drmSyncobjCreate(fd
, DRM_SYNCOBJ_CREATE_SIGNALED
, ctx
->in_sync
+ i
) ||
1057 drmSyncobjCreate(fd
, DRM_SYNCOBJ_CREATE_SIGNALED
, ctx
->out_sync
+ i
))
1061 ctx
->base
.flush
= lima_pipe_flush
;
1066 void lima_submit_fini(struct lima_context
*ctx
)
1068 int fd
= lima_screen(ctx
->base
.screen
)->fd
;
1072 for (int i
= 0; i
< 2; i
++) {
1073 if (ctx
->in_sync
[i
])
1074 drmSyncobjDestroy(fd
, ctx
->in_sync
[i
]);
1075 if (ctx
->out_sync
[i
])
1076 drmSyncobjDestroy(fd
, ctx
->out_sync
[i
]);
1079 if (ctx
->in_sync_fd
>= 0)
1080 close(ctx
->in_sync_fd
);