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)
}
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
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)
{"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
};