From ffcc4d1c4e872b3bb5be1d6952e527e5c091370c Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 21 Jun 2019 13:57:42 -0700 Subject: [PATCH] panfrost: Handle generate_mipmap ourselves To avoid interference with the wallpaper code, we need to do some state tracking when generating mipmaps. In particular, we need to mark the generated layers as invalid before generating the mipmap, so we don't try to backblit them if they already had content. Likewise, we need to flush both before and after generating a mipmap since our usual set_framebuffer_state flushing isn't quite there yet. Ideally better optimizations would save the flush but I digress. Signed-off-by: Alyssa Rosenzweig --- src/gallium/drivers/panfrost/pan_resource.c | 52 +++++++++++++++++++++ src/gallium/drivers/panfrost/pan_screen.c | 3 ++ 2 files changed, 55 insertions(+) diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 1a691a5be34..027cd61f16d 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -39,6 +39,7 @@ #include "util/u_surface.h" #include "util/u_transfer.h" #include "util/u_transfer_helper.h" +#include "util/u_gen_mipmap.h" #include "pan_context.h" #include "pan_screen.h" @@ -663,6 +664,56 @@ panfrost_resource_get_internal_format(struct pipe_resource *prsrc) return prsrc->format; } +static boolean +panfrost_generate_mipmap( + struct pipe_context *pctx, + struct pipe_resource *prsrc, + enum pipe_format format, + unsigned base_level, + unsigned last_level, + unsigned first_layer, + unsigned last_layer) +{ + struct panfrost_context *ctx = pan_context(pctx); + struct panfrost_resource *rsrc = pan_resource(prsrc); + + /* Generating a mipmap invalidates the written levels, so make that + * explicit so we don't try to wallpaper them back and end up with + * u_blitter recursion */ + + assert(rsrc->bo); + for (unsigned l = base_level + 1; l <= last_level; ++l) + rsrc->bo->slices[l].initialized = false; + + /* Beyond that, we just delegate the hard stuff. We're careful to + * include flushes on both ends to make sure the data is really valid. + * We could be doing a lot better perf-wise, especially once we have + * reorder-type optimizations in place. But for now prioritize + * correctness. */ + + struct panfrost_job *job = panfrost_get_job_for_fbo(ctx); + bool has_draws = job->last_job.gpu; + + if (has_draws) + panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME); + + /* We've flushed the original buffer if needed, now trigger a blit */ + + bool blit_res = util_gen_mipmap( + pctx, prsrc, format, + base_level, last_level, + first_layer, last_layer, + PIPE_TEX_FILTER_LINEAR); + + /* If the blit was successful, flush once more. If it wasn't, well, let + * the state tracker deal with it. */ + + if (blit_res) + panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME); + + return blit_res; +} + static void panfrost_resource_set_stencil(struct pipe_resource *prsrc, struct pipe_resource *stencil) @@ -730,6 +781,7 @@ panfrost_resource_context_init(struct pipe_context *pctx) pctx->surface_destroy = panfrost_surface_destroy; pctx->resource_copy_region = util_resource_copy_region; pctx->blit = panfrost_blit; + pctx->generate_mipmap = panfrost_generate_mipmap; pctx->flush_resource = panfrost_flush_resource; pctx->invalidate_resource = panfrost_invalidate_resource; pctx->transfer_flush_region = u_transfer_helper_transfer_flush_region; diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index 15e68fbe2c1..1ae01d5a4f0 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -143,6 +143,9 @@ panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; + case PIPE_CAP_GENERATE_MIPMAP: + return 1; + case PIPE_CAP_DEPTH_CLIP_DISABLE: return 1; -- 2.30.2