panfrost: Implement opportunistic AFBC

Rather than hardcoding a BO layout at creation-time, we implement the
ability to hint layouts at various points in a BO's lifetime,
potentially reallocating and switching layouts if it's heuristically
deemed useful to do so.

In this patch, we add a simple hinting implementation, opportunistically
compressing FBOs.

Support is hidden behind PAN_MESA_DEBUG=afbc as the implementation is
incomplete (software access to AFBC is unimplemented at the moment) and
therefore would regress significantly.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
This commit is contained in:
Alyssa Rosenzweig 2019-07-15 14:15:24 -07:00
parent d60994989e
commit 5ad00fb3ed
5 changed files with 100 additions and 1 deletions

View File

@ -2334,6 +2334,32 @@ panfrost_sampler_view_destroy(
ralloc_free(view);
}
/* Hints that a framebuffer should use AFBC where possible */
static void
panfrost_hint_afbc(
struct panfrost_screen *screen,
const struct pipe_framebuffer_state *fb)
{
/* AFBC implemenation incomplete; hide it */
if (!(pan_debug & PAN_DBG_AFBC)) return;
/* Hint AFBC to the resources bound to each color buffer */
for (unsigned i = 0; i < fb->nr_cbufs; ++i) {
struct pipe_surface *surf = fb->cbufs[i];
struct panfrost_resource *rsrc = pan_resource(surf->texture);
panfrost_resource_hint_layout(screen, rsrc, PAN_AFBC, 1);
}
/* Also hint it to the depth buffer */
if (fb->zsbuf) {
struct panfrost_resource *rsrc = pan_resource(fb->zsbuf->texture);
panfrost_resource_hint_layout(screen, rsrc, PAN_AFBC, 1);
}
}
static void
panfrost_set_framebuffer_state(struct pipe_context *pctx,
const struct pipe_framebuffer_state *fb)
@ -2379,6 +2405,11 @@ panfrost_set_framebuffer_state(struct pipe_context *pctx,
}
if (needs_reattach) {
/* Given that we're rendering, we'd love to have compression */
struct panfrost_screen *screen = pan_screen(ctx->base.screen);
panfrost_hint_afbc(screen, &ctx->pipe_framebuffer);
if (ctx->require_sfbd)
ctx->vt_framebuffer_sfbd = panfrost_emit_sfbd(ctx, ~0);
else

View File

@ -712,6 +712,66 @@ panfrost_get_texture_address(
return rsrc->bo->gpu + level_offset + face_offset;
}
/* Given a resource that has already been allocated, hint that it should use a
* given layout. These are suggestions, not commands; it is perfectly legal to
* stub out this function, but there will be performance implications. */
void
panfrost_resource_hint_layout(
struct panfrost_screen *screen,
struct panfrost_resource *rsrc,
enum panfrost_memory_layout layout,
signed weight)
{
/* Nothing to do, although a sophisticated implementation might store
* the hint */
if (rsrc->layout == layout)
return;
/* We don't use the weight yet, but we should check that it's positive
* (semantically meaning that we should choose the given `layout`) */
if (weight <= 0)
return;
/* Check if the preferred layout is legal for this buffer */
if (layout == PAN_AFBC) {
bool can_afbc = panfrost_format_supports_afbc(rsrc->base.format);
bool is_scanout = rsrc->base.bind &
(PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
if (!can_afbc || is_scanout)
return;
}
/* Simple heuristic so far: if the resource is uninitialized, switch to
* the hinted layout. If it is initialized, keep the original layout.
* This misses some cases where it would be beneficial to switch and
* blit. */
bool is_initialized = false;
for (unsigned i = 0; i < MAX_MIP_LEVELS; ++i)
is_initialized |= rsrc->slices[i].initialized;
if (is_initialized)
return;
/* We're uninitialized, so do a layout switch. Reinitialize slices. */
size_t new_size;
rsrc->layout = layout;
panfrost_setup_slices(rsrc, &new_size);
/* If we grew in size, reallocate the BO */
if (new_size > rsrc->bo->size) {
panfrost_drm_release_bo(screen, rsrc->bo, true);
rsrc->bo = panfrost_drm_create_bo(screen, new_size, PAN_ALLOCATE_DELAY_MMAP);
}
}
static void
panfrost_resource_set_stencil(struct pipe_resource *prsrc,
struct pipe_resource *stencil)

View File

@ -112,6 +112,13 @@ void panfrost_resource_screen_init(struct panfrost_screen *screen);
void panfrost_resource_context_init(struct pipe_context *pctx);
void
panfrost_resource_hint_layout(
struct panfrost_screen *screen,
struct panfrost_resource *rsrc,
enum panfrost_memory_layout layout,
signed weight);
/* AFBC */
bool

View File

@ -54,7 +54,7 @@ static const struct debug_named_value debug_options[] = {
{"msgs", PAN_DBG_MSGS, "Print debug messages"},
{"trace", PAN_DBG_TRACE, "Trace the command stream"},
{"deqp", PAN_DBG_DEQP, "Hacks for dEQP"},
/* ^^ If Rob can do it, so can I */
{"afbc", PAN_DBG_AFBC, "Enable non-conformant AFBC impl"},
DEBUG_NAMED_VALUE_END
};

View File

@ -31,6 +31,7 @@
#define PAN_DBG_MSGS 0x0001
#define PAN_DBG_TRACE 0x0002
#define PAN_DBG_DEQP 0x0004
#define PAN_DBG_AFBC 0x0008
extern int pan_debug;