etnaviv: rework compatible render base
authorJonathan Marek <jonathan@marek.ca>
Sat, 10 Aug 2019 21:00:32 +0000 (17:00 -0400)
committerJonathan Marek <jonathan@marek.ca>
Fri, 11 Oct 2019 11:26:52 +0000 (07:26 -0400)
For PE-incompatible layouts, use a mechanism similar to what texture does
to create a compatible base resource.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
src/gallium/drivers/etnaviv/etnaviv_resource.c
src/gallium/drivers/etnaviv/etnaviv_resource.h
src/gallium/drivers/etnaviv/etnaviv_state.c
src/gallium/drivers/etnaviv/etnaviv_surface.c
src/gallium/drivers/etnaviv/etnaviv_surface.h
src/gallium/drivers/etnaviv/etnaviv_texture.c

index 4a3f62ac13391364c21b09e6a64371c3c3d46172..51d16aa19f7bf771b8fc52a6c7ccbf2a2428a23f 100644 (file)
@@ -138,10 +138,10 @@ etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
 {
    struct etna_resource *rsc = etna_resource(prsc);
 
-   if (rsc->external) {
-      if (etna_resource_older(etna_resource(rsc->external), rsc)) {
-         etna_copy_resource(pctx, rsc->external, prsc, 0, 0);
-         etna_resource(rsc->external)->seqno = rsc->seqno;
+   if (rsc->render) {
+      if (etna_resource_older(rsc, etna_resource(rsc->render))) {
+         etna_copy_resource(pctx, prsc, rsc->render, 0, 0);
+         rsc->seqno = etna_resource(rsc->render)->seqno;
       }
    } else if (etna_resource_needs_flush(rsc)) {
       etna_copy_resource(pctx, prsc, prsc, 0, 0);
index 6cd5eca29306edba9cc6e16f6eeebd46883af226..2e55421360b89d7ac8233d85df922341ba9a6994 100644 (file)
@@ -472,12 +472,7 @@ etna_resource_create_modifiers(struct pipe_screen *pscreen,
 static void
 etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc)
 {
-   struct etna_resource *res = etna_resource(prsc);
-
-   if (res->external)
-      etna_resource(res->external)->seqno++;
-   else
-      res->seqno++;
+   etna_resource(prsc)->seqno++;
 }
 
 static void
@@ -501,7 +496,7 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
       renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro);
 
    pipe_resource_reference(&rsc->texture, NULL);
-   pipe_resource_reference(&rsc->external, NULL);
+   pipe_resource_reference(&rsc->render, NULL);
 
    for (unsigned i = 0; i < ETNA_NUM_LOD; i++)
       FREE(rsc->levels[i].patch_offsets);
@@ -587,29 +582,6 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
    if (!rsc->pending_ctx)
       goto fail;
 
-   if (rsc->layout == ETNA_LAYOUT_LINEAR) {
-      /*
-       * Both sampler and pixel pipes can't handle linear, create a compatible
-       * base resource, where we can attach the imported buffer as an external
-       * resource.
-       */
-      struct pipe_resource tiled_templat = *tmpl;
-
-      /*
-       * Remove BIND_SCANOUT to avoid recursion, as etna_resource_create uses
-       * this function to import the scanout buffer and get a tiled resource.
-       */
-      tiled_templat.bind &= ~PIPE_BIND_SCANOUT;
-
-      ptiled = etna_resource_create(pscreen, &tiled_templat);
-      if (!ptiled)
-         goto fail;
-
-      etna_resource(ptiled)->external = prsc;
-
-      return ptiled;
-   }
-
    return prsc;
 
 fail:
@@ -630,13 +602,6 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
    /* Scanout is always attached to the base resource */
    struct renderonly_scanout *scanout = rsc->scanout;
 
-   /*
-    * External resources are preferred, so a import->export chain of
-    * render/sampler incompatible buffers yield the same handle.
-    */
-   if (rsc->external)
-      rsc = etna_resource(rsc->external);
-
    handle->stride = rsc->levels[0].stride;
    handle->offset = rsc->levels[0].offset;
    handle->modifier = layout_to_modifier(rsc->layout);
index 5beb8454afccd304a5bd2af17178307a3a4b8504..1c253006471b5987ff64693a89f1b9f28b5cefea 100644 (file)
@@ -84,13 +84,10 @@ struct etna_resource {
 
    struct etna_resource_level levels[ETNA_NUM_LOD];
 
-   /* When we are rendering to a texture, we need a differently tiled resource */
+   /* for when TE doesn't support the base layout */
    struct pipe_resource *texture;
-   /*
-    * If imported resources have an render/sampler incompatible tiling, we keep
-    * them as an external resource, which is blitted as needed.
-    */
-   struct pipe_resource *external;
+   /* for when PE doesn't support the base layout */
+   struct pipe_resource *render;
 
    enum etna_resource_status status;
 
index c629aab64948dd94d56dfc2d0a47a4da06eea6c4..79922f2664727dafbf49e8fb671fad85cf442f91 100644 (file)
@@ -108,14 +108,19 @@ etna_set_constant_buffer(struct pipe_context *pctx,
 }
 
 static void
-etna_update_render_resource(struct pipe_context *pctx, struct pipe_resource *pres)
+etna_update_render_resource(struct pipe_context *pctx, struct etna_resource *base)
 {
-   struct etna_resource *res = etna_resource(pres);
+   struct etna_resource *to = base, *from = base;
 
-   if (res->texture && etna_resource_older(res, etna_resource(res->texture))) {
-      /* The render buffer is older than the texture buffer. Copy it over. */
-      etna_copy_resource(pctx, pres, res->texture, 0, pres->last_level);
-      res->seqno = etna_resource(res->texture)->seqno;
+   if (base->texture && etna_resource_newer(etna_resource(base->texture), base))
+      from = etna_resource(base->texture);
+
+   if (base->render)
+      to = etna_resource(base->render);
+
+   if ((to != from) && etna_resource_older(to, from)) {
+      etna_copy_resource(pctx, &to->base, &from->base, 0, base->base.last_level);
+      to->seqno = from->seqno;
    }
 }
 
@@ -138,7 +143,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
       bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0;
 
       assert(res->layout & ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */
-      etna_update_render_resource(pctx, cbuf->base.texture);
+      etna_update_render_resource(pctx, etna_resource(cbuf->prsc));
 
       cs->PE_COLOR_FORMAT =
          VIVS_PE_COLOR_FORMAT_FORMAT(translate_rs_format(cbuf->base.format)) |
@@ -215,7 +220,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx,
       struct etna_surface *zsbuf = etna_surface(sv->zsbuf);
       struct etna_resource *res = etna_resource(zsbuf->base.texture);
 
-      etna_update_render_resource(pctx, zsbuf->base.texture);
+      etna_update_render_resource(pctx, etna_resource(zsbuf->prsc));
 
       assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */
 
index 442957380082f8b1d1c8e192e4679f2a3e952188..d93519db6dff95f4ee5527f82fd92c13837f3f6a 100644 (file)
 
 #include "hw/common.xml.h"
 
+#include "drm-uapi/drm_fourcc.h"
+
+static struct etna_resource *
+etna_render_handle_incompatible(struct pipe_context *pctx, struct pipe_resource *prsc)
+{
+   struct etna_context *ctx = etna_context(pctx);
+   struct etna_resource *res = etna_resource(prsc);
+   bool need_multitiled = ctx->specs.pixel_pipes > 1 && !ctx->specs.single_buffer;
+   bool want_supertiled = ctx->specs.can_supertile;
+
+   /* Resource is compatible if it is tiled and has multi tiling when required
+    * TODO: LINEAR_PE feature means render to linear is possible ?
+    */
+   if (res->layout != ETNA_LAYOUT_LINEAR &&
+       (!need_multitiled || (res->layout & ETNA_LAYOUT_BIT_MULTI)))
+      return res;
+
+   if (!res->render) {
+      struct pipe_resource templat = *prsc;
+      unsigned layout = ETNA_LAYOUT_TILED;
+      if (need_multitiled)
+         layout |= ETNA_LAYOUT_BIT_MULTI;
+      if (want_supertiled)
+         layout |= ETNA_LAYOUT_BIT_SUPER;
+
+      templat.bind &= (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
+                        PIPE_BIND_BLENDABLE);
+      res->render =
+         etna_resource_alloc(pctx->screen, layout,
+                             DRM_FORMAT_MOD_LINEAR, &templat);
+      assert(res->render);
+   }
+   return etna_resource(res->render);
+}
+
 static struct pipe_surface *
 etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
                     const struct pipe_surface *templat)
 {
    struct etna_context *ctx = etna_context(pctx);
-   struct etna_resource *rsc = etna_resource(prsc);
+   struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc);
    struct etna_surface *surf = CALLOC_STRUCT(etna_surface);
 
    if (!surf)
@@ -57,6 +92,7 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
 
    pipe_reference_init(&surf->base.reference, 1);
    pipe_resource_reference(&surf->base.texture, &rsc->base);
+   pipe_resource_reference(&surf->prsc, prsc);
 
    /* Allocate a TS for the resource if there isn't one yet,
     * and it is allowed by the hw (width is a multiple of 16).
@@ -148,6 +184,7 @@ static void
 etna_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf)
 {
    pipe_resource_reference(&psurf->texture, NULL);
+   pipe_resource_reference(&etna_surface(psurf)->prsc, NULL);
    FREE(psurf);
 }
 
index e8cfd209af40a7cdcb923127004f18da4f4c46a3..fef85f521e5586312d4df87c0a37fd476dcbe4f4 100644 (file)
@@ -41,6 +41,8 @@ struct etna_surface {
    struct etna_resource_level *level;
    struct etna_reloc reloc[ETNA_MAX_PIXELPIPES];
    struct etna_reloc ts_reloc;
+   /* keep pointer to original resource (for when a render compatible resource is used) */
+   struct pipe_resource *prsc;
 };
 
 static inline struct etna_surface *
index a38fd1c4a57057c8b46d8bc5eb217034a0aab0b9..748d3ff3e6fefd78e0cc39a7791f1f18c5b65696 100644 (file)
@@ -147,8 +147,8 @@ etna_update_sampler_source(struct pipe_sampler_view *view, int num)
    struct etna_context *ctx = etna_context(view->context);
    bool enable_sampler_ts = false;
 
-   if (base->external && etna_resource_newer(etna_resource(base->external), base))
-      from = etna_resource(base->external);
+   if (base->render && etna_resource_newer(etna_resource(base->render), base))
+      from = etna_resource(base->render);
 
    if (base->texture)
       to = etna_resource(base->texture);