lima: add support for depth/stencil fbo attachments and textures
authorVasily Khoruzhick <anarsoul@gmail.com>
Sun, 7 Apr 2019 05:55:36 +0000 (22:55 -0700)
committerQiang Yu <yuq825@gmail.com>
Sun, 14 Apr 2019 01:16:00 +0000 (01:16 +0000)
Hardware supports writing back Z/S buffers and sampling from them,
so add support for that.

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Reviewed-by: Qiang Yu <yuq825@gmail.com>
Tested-by: Icenowy Zheng <icenowy@aosc.io>
src/gallium/drivers/lima/lima_context.c
src/gallium/drivers/lima/lima_context.h
src/gallium/drivers/lima/lima_draw.c
src/gallium/drivers/lima/lima_resource.c
src/gallium/drivers/lima/lima_screen.c
src/gallium/drivers/lima/lima_state.c
src/gallium/drivers/lima/lima_texture.c

index 35350ee71b8a5240aa390480cacabaf7b60548d8..9a373b96728381b04818940f43d6aa9d0a51b394 100644 (file)
@@ -273,3 +273,15 @@ lima_need_flush(struct lima_context *ctx, struct lima_bo *bo, bool write)
    return lima_submit_has_bo(ctx->gp_submit, bo, write) ||
       lima_submit_has_bo(ctx->pp_submit, bo, write);
 }
+
+bool
+lima_is_scanout(struct lima_context *ctx)
+{
+        /* If there is no color buffer, it's an FBO */
+        if (!ctx->framebuffer.base.nr_cbufs)
+                return false;
+
+        return ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_DISPLAY_TARGET ||
+               ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_SCANOUT ||
+               ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_SHARED;
+}
index 469378a4a3623a3fea6ffdecb33d16f300d83117..4bbe915bcdc1defd6170c4a34aea0af8299a7603 100644 (file)
@@ -292,5 +292,6 @@ lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags);
 void lima_flush(struct lima_context *ctx);
 
 bool lima_need_flush(struct lima_context *ctx, struct lima_bo *bo, bool write);
+bool lima_is_scanout(struct lima_context *ctx);
 
 #endif
index 2cbcadae1b16ccbdc430a713c0a21f7c5377f8bd..e0a1e181937f5ce2010b6da7172ba9ff3ef34b91 100644 (file)
@@ -116,6 +116,10 @@ struct lima_render_state {
    uint32_t varyings_address;
 };
 
+#define LIMA_PIXEL_FORMAT_B8G8R8A8     0x03
+#define LIMA_PIXEL_FORMAT_Z16          0x0e
+#define LIMA_PIXEL_FORMAT_Z24S8        0x0f
+
 /* plbu commands */
 #define PLBU_CMD_BEGIN(max) { \
    int i = 0, max_n = max; \
@@ -211,6 +215,9 @@ lima_ctx_dirty(struct lima_context *ctx)
 static bool
 lima_fb_need_reload(struct lima_context *ctx)
 {
+   /* Depth buffer is always discarded */
+   if (!ctx->framebuffer.base.nr_cbufs)
+      return false;
    if (ctx->damage.region) {
       /* for EGL_KHR_partial_update we just want to reload the
        * region not aligned to tile boundary */
@@ -670,8 +677,14 @@ lima_update_submit_bo(struct lima_context *ctx)
    else
       ctx->pp_stream.bo = NULL;
 
-   struct lima_resource *res = lima_resource(ctx->framebuffer.base.cbufs[0]->texture);
-   lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_WRITE);
+   if (ctx->framebuffer.base.nr_cbufs) {
+      struct lima_resource *res = lima_resource(ctx->framebuffer.base.cbufs[0]->texture);
+      lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_WRITE);
+   }
+   if (ctx->framebuffer.base.zsbuf) {
+      struct lima_resource *res = lima_resource(ctx->framebuffer.base.zsbuf->texture);
+      lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_WRITE);
+   }
    lima_submit_add_bo(ctx->pp_submit, ctx->plb[ctx->plb_index], LIMA_SUBMIT_BO_READ);
    lima_submit_add_bo(ctx->pp_submit, ctx->gp_tile_heap[ctx->plb_index], LIMA_SUBMIT_BO_READ);
    lima_submit_add_bo(ctx->pp_submit, screen->pp_buffer, LIMA_SUBMIT_BO_READ);
@@ -688,7 +701,7 @@ lima_clear(struct pipe_context *pctx, unsigned buffers,
       lima_flush(ctx);
 
       /* no need to reload if cleared */
-      if (buffers & PIPE_CLEAR_COLOR0) {
+      if (ctx->framebuffer.base.nr_cbufs && (buffers & PIPE_CLEAR_COLOR0)) {
          struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]);
          surf->reload = false;
       }
@@ -1421,13 +1434,47 @@ lima_finish_plbu_cmd(struct lima_context *ctx)
 }
 
 static void
-lima_pack_pp_frame_reg(struct lima_context *ctx, uint32_t *frame_reg,
-                       uint32_t *wb_reg)
+lima_pack_wb_zsbuf_reg(struct lima_context *ctx, uint32_t *wb_reg, int wb_idx)
 {
-   struct lima_resource *res = lima_resource(ctx->framebuffer.base.cbufs[0]->texture);
+   struct lima_context_framebuffer *fb = &ctx->framebuffer;
+   struct lima_resource *res = lima_resource(fb->base.zsbuf->texture);
+
+   uint32_t format;
+
+   switch (fb->base.zsbuf->format) {
+   case PIPE_FORMAT_Z16_UNORM:
+      format = LIMA_PIXEL_FORMAT_Z16;
+      break;
+   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+   case PIPE_FORMAT_Z24X8_UNORM:
+   default:
+      /* Assume Z24S8 */
+      format = LIMA_PIXEL_FORMAT_Z24S8;
+      break;
+   }
+
+   struct lima_pp_wb_reg *wb = (void *)wb_reg;
+   wb[wb_idx].type = 0x01; /* 1 for depth, stencil */
+   wb[wb_idx].address = res->bo->va;
+   wb[wb_idx].pixel_format = format;
+   if (res->tiled) {
+      wb[wb_idx].pixel_layout = 0x2;
+      wb[wb_idx].pitch = fb->tiled_w;
+   } else {
+      wb[wb_idx].pixel_layout = 0x0;
+      wb[wb_idx].pitch = res->levels[0].stride / 8;
+   }
+   wb[wb_idx].mrt_bits = 0;
+}
+
+static void
+lima_pack_wb_cbuf_reg(struct lima_context *ctx, uint32_t *wb_reg, int wb_idx)
+{
+   struct lima_context_framebuffer *fb = &ctx->framebuffer;
+   struct lima_resource *res = lima_resource(fb->base.cbufs[0]->texture);
 
    bool swap_channels = false;
-   switch (ctx->framebuffer.base.cbufs[0]->format) {
+   switch (fb->base.cbufs[0]->format) {
    case PIPE_FORMAT_R8G8B8A8_UNORM:
    case PIPE_FORMAT_R8G8B8X8_UNORM:
       swap_channels = true;
@@ -1436,9 +1483,30 @@ lima_pack_pp_frame_reg(struct lima_context *ctx, uint32_t *frame_reg,
       break;
    }
 
+   struct lima_pp_wb_reg *wb = (void *)wb_reg;
+   wb[wb_idx].type = 0x02; /* 2 for color buffer */
+   wb[wb_idx].address = res->bo->va;
+   wb[wb_idx].pixel_format = LIMA_PIXEL_FORMAT_B8G8R8A8;
+   if (res->tiled) {
+      wb[wb_idx].pixel_layout = 0x2;
+      wb[wb_idx].pitch = fb->tiled_w;
+   } else {
+      wb[wb_idx].pixel_layout = 0x0;
+      wb[wb_idx].pitch = res->levels[0].stride / 8;
+   }
+   wb[wb_idx].mrt_bits = swap_channels ? 0x4 : 0x0;
+}
+
+
+static void
+lima_pack_pp_frame_reg(struct lima_context *ctx, uint32_t *frame_reg,
+                       uint32_t *wb_reg)
+{
    struct lima_context_framebuffer *fb = &ctx->framebuffer;
    struct lima_pp_frame_reg *frame = (void *)frame_reg;
    struct lima_screen *screen = lima_screen(ctx->base.screen);
+   int wb_idx = 0;
+
    frame->render_address = screen->pp_buffer->va + pp_frame_rsw_offset;
    frame->flags = 0x02;
    frame->clear_value_depth = ctx->clear.depth;
@@ -1469,18 +1537,15 @@ lima_pack_pp_frame_reg(struct lima_context *ctx, uint32_t *frame_reg,
    frame->blocking = (fb->shift_min << 28) | (fb->shift_h << 16) | fb->shift_w;
    frame->foureight = 0x8888;
 
-   struct lima_pp_wb_reg *wb = (void *)wb_reg;
-   wb[0].type = 0x02; /* 1 for depth, stencil */
-   wb[0].address = res->bo->va;
-   wb[0].pixel_format = 0x03; /* BGRA8888 */
-   if (res->tiled) {
-      wb[0].pixel_layout = 0x2;
-      wb[0].pitch = fb->tiled_w;
-   } else {
-      wb[0].pixel_layout = 0x0;
-      wb[0].pitch = res->levels[0].stride / 8;
-   }
-   wb[0].mrt_bits = swap_channels ? 0x4 : 0x0;
+   if (fb->base.nr_cbufs)
+      lima_pack_wb_cbuf_reg(ctx, wb_reg, wb_idx++);
+
+   /* Mali4x0 can use on-tile buffer for depth/stencil, so to save some
+    * memory bandwidth don't write depth/stencil back to memory if we're
+    * rendering to scanout
+    */
+   if (!lima_is_scanout(ctx) && fb->base.zsbuf)
+      lima_pack_wb_zsbuf_reg(ctx, wb_reg, wb_idx++);
 }
 
 static void
@@ -1609,9 +1674,11 @@ _lima_flush(struct lima_context *ctx, bool end_of_frame)
 
    ctx->plb_index = (ctx->plb_index + 1) % lima_ctx_num_plb;
 
-   /* this surface may need reload when next draw if not end of frame */
-   struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]);
-   surf->reload = !end_of_frame;
+   if (ctx->framebuffer.base.nr_cbufs) {
+      /* this surface may need reload when next draw if not end of frame */
+      struct lima_surface *surf = lima_surface(ctx->framebuffer.base.cbufs[0]);
+      surf->reload = !end_of_frame;
+   }
 }
 
 void
index a3edfd0931aa74cdab51ddfa2b09b015f2f9682e..4e215e9e08f6a4a27ab5447e097882ca7d51d69f 100644 (file)
@@ -192,7 +192,8 @@ _lima_resource_create_with_modifiers(struct pipe_screen *pscreen,
    if (!should_tile && !drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
       return NULL;
 
-   if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET)) {
+   if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET) ||
+       (templat->bind & PIPE_BIND_DEPTH_STENCIL)) {
       should_align_dimensions = true;
       width = align(templat->width0, 16);
       height = align(templat->height0, 16);
index ae58f7fd82a1e95c18fc7046c51c0acfeb78c9a6..cd9639b41e2645e8bc2b475ae0722da7e08a092e 100644 (file)
@@ -272,6 +272,9 @@ lima_screen_is_format_supported(struct pipe_screen *pscreen,
       case PIPE_FORMAT_B8G8R8X8_UNORM:
       case PIPE_FORMAT_R8G8B8A8_UNORM:
       case PIPE_FORMAT_R8G8B8X8_UNORM:
+      case PIPE_FORMAT_Z16_UNORM:
+      case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+      case PIPE_FORMAT_Z24X8_UNORM:
          break;
       default:
          return FALSE;
@@ -317,6 +320,9 @@ lima_screen_is_format_supported(struct pipe_screen *pscreen,
       case PIPE_FORMAT_B8G8R8A8_UNORM:
       case PIPE_FORMAT_A8B8G8R8_SRGB:
       case PIPE_FORMAT_B8G8R8A8_SRGB:
+      case PIPE_FORMAT_Z16_UNORM:
+      case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+      case PIPE_FORMAT_Z24X8_UNORM:
          break;
       default:
          return FALSE;
index 7985dacd4077bd704a34cb2ca7d0fcdb55d24a67..1621618c865953c2a6676eb42ecc16adfcae4d4a 100644 (file)
@@ -47,7 +47,7 @@ lima_set_framebuffer_state(struct pipe_context *pctx,
 
    fb->base.samples = framebuffer->samples;
 
-   fb->base.nr_cbufs = 1;
+   fb->base.nr_cbufs = framebuffer->nr_cbufs;
    pipe_surface_reference(&fb->base.cbufs[0], framebuffer->cbufs[0]);
    pipe_surface_reference(&fb->base.zsbuf, framebuffer->zsbuf);
 
index 548d9839ff0409caf334a6d7021e285db345e9ab..90af0dec74b7dd774467927618f34685e44d876b 100644 (file)
 #include <drm-uapi/lima_drm.h>
 
 #define LIMA_TEXEL_FORMAT_BGR_565      0x0e
+#define LIMA_TEXEL_FORMAT_Z16          0x12
 #define LIMA_TEXEL_FORMAT_RGB_888      0x15
 #define LIMA_TEXEL_FORMAT_RGBA_8888    0x16
 #define LIMA_TEXEL_FORMAT_RGBX_8888    0x17
+#define LIMA_TEXEL_FORMAT_Z24S8        0x2c
 
 #define lima_tex_list_size 64
 
@@ -68,6 +70,13 @@ static uint32_t pipe_format_to_lima(enum pipe_format pformat)
    case PIPE_FORMAT_B5G6R5_UNORM:
       format = LIMA_TEXEL_FORMAT_BGR_565;
       break;
+   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+   case PIPE_FORMAT_Z24X8_UNORM:
+      format = LIMA_TEXEL_FORMAT_Z24S8;
+      break;
+   case PIPE_FORMAT_Z16_UNORM:
+      format = LIMA_TEXEL_FORMAT_Z16;
+      break;
    default:
       assert(0);
       break;