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 <alyssa.rosenzw...@collabora.com> --- 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 dccb0143a53..27f352c68ba 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.20.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev