diff options
author | Boris Brezillon <[email protected]> | 2019-09-05 20:47:45 +0200 |
---|---|---|
committer | Boris Brezillon <[email protected]> | 2019-09-13 16:25:06 +0200 |
commit | 6ddfd37c7e5a132910d748429cc89289e97f1b38 (patch) | |
tree | c1b18f42653f67cedd2bb0e9d3135ad676f80e39 /src/gallium/drivers/panfrost/pan_job.c | |
parent | 2fc91a16abe0e517dfb46517dc4795857f0a9343 (diff) |
panfrost: Move the batch submission logic to panfrost_batch_submit()
We are about to patch panfrost_flush() to flush all pending batches,
not only the current one. In order to do that, we need to move the
'flush single batch' code to panfrost_batch_submit().
While at it, we get rid of the existing pipelining logic, which is
currently unused and replace it by an unconditional wait at the end of
panfrost_batch_submit(). A new pipeline logic will be introduced later
on.
Signed-off-by: Boris Brezillon <[email protected]>
Reviewed-by: Alyssa Rosenzweig <[email protected]>
Diffstat (limited to 'src/gallium/drivers/panfrost/pan_job.c')
-rw-r--r-- | src/gallium/drivers/panfrost/pan_job.c | 128 |
1 files changed, 122 insertions, 6 deletions
diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index 3d64aa8e452..00df9006342 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -163,6 +163,106 @@ panfrost_batch_get_polygon_list(struct panfrost_batch *batch, unsigned size) return batch->polygon_list->gpu; } +static void +panfrost_batch_draw_wallpaper(struct panfrost_batch *batch) +{ + /* Nothing to reload? TODO: MRT wallpapers */ + if (batch->key.cbufs[0] == NULL) + return; + + /* Check if the buffer has any content on it worth preserving */ + + struct pipe_surface *surf = batch->key.cbufs[0]; + struct panfrost_resource *rsrc = pan_resource(surf->texture); + unsigned level = surf->u.tex.level; + + if (!rsrc->slices[level].initialized) + return; + + batch->ctx->wallpaper_batch = batch; + + /* Clamp the rendering area to the damage extent. The + * KHR_partial_update() spec states that trying to render outside of + * the damage region is "undefined behavior", so we should be safe. + */ + unsigned damage_width = (rsrc->damage.extent.maxx - rsrc->damage.extent.minx); + unsigned damage_height = (rsrc->damage.extent.maxy - rsrc->damage.extent.miny); + + if (damage_width && damage_height) { + panfrost_batch_intersection_scissor(batch, + rsrc->damage.extent.minx, + rsrc->damage.extent.miny, + rsrc->damage.extent.maxx, + rsrc->damage.extent.maxy); + } + + /* FIXME: Looks like aligning on a tile is not enough, but + * aligning on twice the tile size seems to works. We don't + * know exactly what happens here but this deserves extra + * investigation to figure it out. + */ + batch->minx = batch->minx & ~((MALI_TILE_LENGTH * 2) - 1); + batch->miny = batch->miny & ~((MALI_TILE_LENGTH * 2) - 1); + batch->maxx = MIN2(ALIGN_POT(batch->maxx, MALI_TILE_LENGTH * 2), + rsrc->base.width0); + batch->maxy = MIN2(ALIGN_POT(batch->maxy, MALI_TILE_LENGTH * 2), + rsrc->base.height0); + + struct pipe_scissor_state damage; + struct pipe_box rects[4]; + + /* Clamp the damage box to the rendering area. */ + damage.minx = MAX2(batch->minx, rsrc->damage.biggest_rect.x); + damage.miny = MAX2(batch->miny, rsrc->damage.biggest_rect.y); + damage.maxx = MIN2(batch->maxx, + rsrc->damage.biggest_rect.x + + rsrc->damage.biggest_rect.width); + damage.maxy = MIN2(batch->maxy, + rsrc->damage.biggest_rect.y + + rsrc->damage.biggest_rect.height); + + /* One damage rectangle means we can end up with at most 4 reload + * regions: + * 1: left region, only exists if damage.x > 0 + * 2: right region, only exists if damage.x + damage.width < fb->width + * 3: top region, only exists if damage.y > 0. The intersection with + * the left and right regions are dropped + * 4: bottom region, only exists if damage.y + damage.height < fb->height. + * The intersection with the left and right regions are dropped + * + * ____________________________ + * | | 3 | | + * | |___________| | + * | | damage | | + * | 1 | rect | 2 | + * | |___________| | + * | | 4 | | + * |_______|___________|______| + */ + u_box_2d(batch->minx, batch->miny, damage.minx - batch->minx, + batch->maxy - batch->miny, &rects[0]); + u_box_2d(damage.maxx, batch->miny, batch->maxx - damage.maxx, + batch->maxy - batch->miny, &rects[1]); + u_box_2d(damage.minx, batch->miny, damage.maxx - damage.minx, + damage.miny - batch->miny, &rects[2]); + u_box_2d(damage.minx, damage.maxy, damage.maxx - damage.minx, + batch->maxy - damage.maxy, &rects[3]); + + for (unsigned i = 0; i < 4; i++) { + /* Width and height are always >= 0 even if width is declared as a + * signed integer: u_box_2d() helper takes unsigned args and + * panfrost_set_damage_region() is taking care of clamping + * negative values. + */ + if (!rects[i].width || !rects[i].height) + continue; + + /* Blit the wallpaper in */ + panfrost_blit_wallpaper(batch->ctx, &rects[i]); + } + batch->ctx->wallpaper_batch = NULL; +} + void panfrost_batch_submit(struct panfrost_batch *batch) { @@ -171,6 +271,13 @@ panfrost_batch_submit(struct panfrost_batch *batch) struct panfrost_context *ctx = batch->ctx; int ret; + /* Nothing to do! */ + if (!batch->last_job.gpu && !batch->clear) + goto out; + + if (!batch->clear && batch->last_tiler.gpu) + panfrost_batch_draw_wallpaper(batch); + panfrost_scoreboard_link_batch(batch); bool has_draws = batch->last_job.gpu; @@ -180,19 +287,28 @@ panfrost_batch_submit(struct panfrost_batch *batch) if (ret) fprintf(stderr, "panfrost_batch_submit failed: %d\n", ret); +out: + /* If this is the bound batch, the panfrost_context parameters are + * relevant so submitting it invalidates those paramaters, but if it's + * not bound, the context parameters are for some other batch so we + * can't invalidate them. + */ + if (ctx->batch == batch) + panfrost_invalidate_frame(ctx); + /* The job has been submitted, let's invalidate the current FBO job * cache. */ assert(!ctx->batch || batch == ctx->batch); ctx->batch = NULL; - /* Remove the job from the ctx->batches set so that future - * panfrost_get_batch() calls don't see it. - * We must reset the job key to avoid removing another valid entry when - * the job is freed. + /* We always stall the pipeline for correct results since pipelined + * rendering is quite broken right now (to be fixed by the panfrost_job + * refactor, just take the perf hit for correctness) */ - _mesa_hash_table_remove_key(ctx->batches, &batch->key); - memset(&batch->key, 0, sizeof(batch->key)); + drmSyncobjWait(pan_screen(ctx->base.screen)->fd, &ctx->out_sync, 1, + INT64_MAX, 0, NULL); + panfrost_free_batch(batch); } void |