summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorAlyssa Rosenzweig <[email protected]>2019-07-15 14:15:24 -0700
committerAlyssa Rosenzweig <[email protected]>2019-07-16 07:21:08 -0700
commit5ad00fb3ed913599fecbae785284fc883242aaf0 (patch)
tree633431699328178b661bffe13eb4d816fc4c0c67 /src/gallium/drivers
parentd60994989e5be0839e6b57b1c97eb23b4ba3dc0f (diff)
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 <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/panfrost/pan_context.c31
-rw-r--r--src/gallium/drivers/panfrost/pan_resource.c60
-rw-r--r--src/gallium/drivers/panfrost/pan_resource.h7
-rw-r--r--src/gallium/drivers/panfrost/pan_screen.c2
-rw-r--r--src/gallium/drivers/panfrost/pan_util.h1
5 files changed, 100 insertions, 1 deletions
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index aed49311c02..d720f086361 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -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
diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c
index 7b46acaf58b..d3cbfe70c77 100644
--- a/src/gallium/drivers/panfrost/pan_resource.c
+++ b/src/gallium/drivers/panfrost/pan_resource.c
@@ -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)
diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h
index 3814c2b27eb..e51ba8959c3 100644
--- a/src/gallium/drivers/panfrost/pan_resource.h
+++ b/src/gallium/drivers/panfrost/pan_resource.h
@@ -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
diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c
index 43a26856f9b..ffd2de4734e 100644
--- a/src/gallium/drivers/panfrost/pan_screen.c
+++ b/src/gallium/drivers/panfrost/pan_screen.c
@@ -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
};
diff --git a/src/gallium/drivers/panfrost/pan_util.h b/src/gallium/drivers/panfrost/pan_util.h
index 3ae70218606..24c71d59ba0 100644
--- a/src/gallium/drivers/panfrost/pan_util.h
+++ b/src/gallium/drivers/panfrost/pan_util.h
@@ -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;