freedreno: native fence fd support
[mesa.git] / src / gallium / drivers / freedreno / freedreno_gmem.c
index 0d73349057c37b9877b4882eb06f5514a3fc0948..69fb16d058bdafe579c4bc4c568fd1d8eac477b9 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "freedreno_gmem.h"
 #include "freedreno_context.h"
+#include "freedreno_fence.h"
 #include "freedreno_resource.h"
 #include "freedreno_query_hw.h"
 #include "freedreno_util.h"
  * resolve.
  */
 
-static uint32_t bin_width(struct fd_context *ctx)
+static uint32_t bin_width(struct fd_screen *screen)
 {
-       if (is_a4xx(ctx->screen))
+       if (is_a4xx(screen) || is_a5xx(screen))
                return 1024;
-       if (is_a3xx(ctx->screen))
+       if (is_a3xx(screen))
                return 992;
        return 512;
 }
@@ -103,20 +104,22 @@ total_size(uint8_t cbuf_cpp[], uint8_t zsbuf_cpp[2],
 }
 
 static void
-calculate_tiles(struct fd_context *ctx)
+calculate_tiles(struct fd_batch *batch)
 {
+       struct fd_context *ctx = batch->ctx;
        struct fd_gmem_stateobj *gmem = &ctx->gmem;
-       struct pipe_scissor_state *scissor = &ctx->max_scissor;
-       struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
-       uint32_t gmem_size = ctx->screen->gmemsize_bytes;
+       struct pipe_scissor_state *scissor = &batch->max_scissor;
+       struct pipe_framebuffer_state *pfb = &batch->framebuffer;
+       const uint32_t gmem_alignment = ctx->screen->gmem_alignment;
+       const uint32_t gmem_size = ctx->screen->gmemsize_bytes;
        uint32_t minx, miny, width, height;
        uint32_t nbins_x = 1, nbins_y = 1;
        uint32_t bin_w, bin_h;
-       uint32_t max_width = bin_width(ctx);
+       uint32_t max_width = bin_width(ctx->screen);
        uint8_t cbuf_cpp[MAX_RENDER_TARGETS] = {0}, zsbuf_cpp[2] = {0};
        uint32_t i, j, t, xoff, yoff;
        uint32_t tpp_x, tpp_y;
-       bool has_zs = !!(ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL));
+       bool has_zs = !!(batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL));
        int tile_n[ARRAY_SIZE(ctx->pipe)];
 
        if (has_zs) {
@@ -145,21 +148,22 @@ calculate_tiles(struct fd_context *ctx)
                width = pfb->width;
                height = pfb->height;
        } else {
-               minx = scissor->minx & ~31; /* round down to multiple of 32 */
-               miny = scissor->miny & ~31;
+               /* round down to multiple of alignment: */
+               minx = scissor->minx & ~(gmem_alignment - 1);
+               miny = scissor->miny & ~(gmem_alignment - 1);
                width = scissor->maxx - minx;
                height = scissor->maxy - miny;
        }
 
-       bin_w = align(width, 32);
-       bin_h = align(height, 32);
+       bin_w = align(width, gmem_alignment);
+       bin_h = align(height, gmem_alignment);
 
        /* first, find a bin width that satisfies the maximum width
         * restrictions:
         */
        while (bin_w > max_width) {
                nbins_x++;
-               bin_w = align(width / nbins_x, 32);
+               bin_w = align(width / nbins_x, gmem_alignment);
        }
 
        if (fd_mesa_debug & FD_DBG_MSGS) {
@@ -176,10 +180,10 @@ calculate_tiles(struct fd_context *ctx)
        while (total_size(cbuf_cpp, zsbuf_cpp, bin_w, bin_h, gmem) > gmem_size) {
                if (bin_w > bin_h) {
                        nbins_x++;
-                       bin_w = align(width / nbins_x, 32);
+                       bin_w = align(width / nbins_x, gmem_alignment);
                } else {
                        nbins_y++;
-                       bin_h = align(height / nbins_y, 32);
+                       bin_h = align(height / nbins_y, gmem_alignment);
                }
        }
 
@@ -302,14 +306,15 @@ calculate_tiles(struct fd_context *ctx)
 }
 
 static void
-render_tiles(struct fd_context *ctx)
+render_tiles(struct fd_batch *batch)
 {
+       struct fd_context *ctx = batch->ctx;
        struct fd_gmem_stateobj *gmem = &ctx->gmem;
        int i;
 
-       ctx->emit_tile_init(ctx);
+       ctx->emit_tile_init(batch);
 
-       if (ctx->restore)
+       if (batch->restore)
                ctx->stats.batch_restore++;
 
        for (i = 0; i < (gmem->nbins_x * gmem->nbins_y); i++) {
@@ -318,101 +323,89 @@ render_tiles(struct fd_context *ctx)
                DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d",
                        tile->bin_h, tile->yoff, tile->bin_w, tile->xoff);
 
-               ctx->emit_tile_prep(ctx, tile);
+               ctx->emit_tile_prep(batch, tile);
 
-               if (ctx->restore) {
-                       fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_MEM2GMEM);
-                       ctx->emit_tile_mem2gmem(ctx, tile);
-                       fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
+               if (batch->restore) {
+                       ctx->emit_tile_mem2gmem(batch, tile);
                }
 
-               ctx->emit_tile_renderprep(ctx, tile);
+               ctx->emit_tile_renderprep(batch, tile);
 
-               fd_hw_query_prepare_tile(ctx, i, ctx->ring);
+               fd_hw_query_prepare_tile(batch, i, batch->gmem);
 
                /* emit IB to drawcmds: */
-               ctx->emit_ib(ctx->ring, ctx->draw_start, ctx->draw_end);
-               fd_reset_wfi(ctx);
+               ctx->emit_ib(batch->gmem, batch->draw);
+               fd_reset_wfi(batch);
 
                /* emit gmem2mem to transfer tile back to system memory: */
-               fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_GMEM2MEM);
-               ctx->emit_tile_gmem2mem(ctx, tile);
-               fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
+               ctx->emit_tile_gmem2mem(batch, tile);
        }
+
+       if (ctx->emit_tile_fini)
+               ctx->emit_tile_fini(batch);
 }
 
 static void
-render_sysmem(struct fd_context *ctx)
+render_sysmem(struct fd_batch *batch)
 {
-       ctx->emit_sysmem_prep(ctx);
+       struct fd_context *ctx = batch->ctx;
+
+       ctx->emit_sysmem_prep(batch);
 
-       fd_hw_query_prepare_tile(ctx, 0, ctx->ring);
+       fd_hw_query_prepare_tile(batch, 0, batch->gmem);
 
        /* emit IB to drawcmds: */
-       ctx->emit_ib(ctx->ring, ctx->draw_start, ctx->draw_end);
-       fd_reset_wfi(ctx);
+       ctx->emit_ib(batch->gmem, batch->draw);
+       fd_reset_wfi(batch);
 }
 
 void
-fd_gmem_render_tiles(struct fd_context *ctx)
+fd_gmem_render_tiles(struct fd_batch *batch)
 {
-       struct pipe_framebuffer_state *pfb = &ctx->framebuffer;
+       struct fd_context *ctx = batch->ctx;
+       struct pipe_framebuffer_state *pfb = &batch->framebuffer;
        bool sysmem = false;
 
        if (ctx->emit_sysmem_prep) {
-               if (ctx->cleared || ctx->gmem_reason || (ctx->num_draws > 5)) {
+               if (batch->cleared || batch->gmem_reason || (batch->num_draws > 5)) {
                        DBG("GMEM: cleared=%x, gmem_reason=%x, num_draws=%u",
-                               ctx->cleared, ctx->gmem_reason, ctx->num_draws);
+                               batch->cleared, batch->gmem_reason, batch->num_draws);
                } else if (!(fd_mesa_debug & FD_DBG_NOBYPASS)) {
                        sysmem = true;
                }
        }
 
-       /* close out the draw cmds by making sure any active queries are
-        * paused:
-        */
-       fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_NULL);
-
-       /* mark the end of the clear/draw cmds before emitting per-tile cmds: */
-       fd_ringmarker_mark(ctx->draw_end);
-       fd_ringmarker_mark(ctx->binning_end);
-
-       fd_reset_wfi(ctx);
+       fd_reset_wfi(batch);
 
        ctx->stats.batch_total++;
 
        if (sysmem) {
-               DBG("rendering sysmem (%s/%s)",
+               DBG("%p: rendering sysmem %ux%u (%s/%s)",
+                       batch, pfb->width, pfb->height,
                        util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
                        util_format_short_name(pipe_surface_format(pfb->zsbuf)));
-               fd_hw_query_prepare(ctx, 1);
-               render_sysmem(ctx);
+               fd_hw_query_prepare(batch, 1);
+               render_sysmem(batch);
                ctx->stats.batch_sysmem++;
        } else {
                struct fd_gmem_stateobj *gmem = &ctx->gmem;
-               calculate_tiles(ctx);
-               DBG("rendering %dx%d tiles (%s/%s)", gmem->nbins_x, gmem->nbins_y,
+               calculate_tiles(batch);
+               DBG("%p: rendering %dx%d tiles %ux%u (%s/%s)",
+                       batch, pfb->width, pfb->height, gmem->nbins_x, gmem->nbins_y,
                        util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
                        util_format_short_name(pipe_surface_format(pfb->zsbuf)));
-               fd_hw_query_prepare(ctx, gmem->nbins_x * gmem->nbins_y);
-               render_tiles(ctx);
+               fd_hw_query_prepare(batch, gmem->nbins_x * gmem->nbins_y);
+               render_tiles(batch);
                ctx->stats.batch_gmem++;
        }
 
-       /* GPU executes starting from tile cmds, which IB back to draw cmds: */
-       fd_ringmarker_flush(ctx->draw_end);
-
-       /* mark start for next draw/binning cmds: */
-       fd_ringmarker_mark(ctx->draw_start);
-       fd_ringmarker_mark(ctx->binning_start);
-
-       fd_reset_wfi(ctx);
-
-       /* reset maximal bounds: */
-       ctx->max_scissor.minx = ctx->max_scissor.miny = ~0;
-       ctx->max_scissor.maxx = ctx->max_scissor.maxy = 0;
+       int out_fence_fd = -1;
+       fd_ringbuffer_flush2(batch->gmem, batch->in_fence_fd,
+                       batch->needs_out_fence_fd ? &out_fence_fd : NULL);
 
-       ctx->dirty = ~0;
+       fd_fence_ref(&ctx->screen->base, &ctx->last_fence, NULL);
+       ctx->last_fence = fd_fence_create(ctx,
+                       fd_ringbuffer_timestamp(batch->gmem), out_fence_fd);
 }
 
 /* tile needs restore if it isn't completely contained within the
@@ -435,26 +428,26 @@ skip_restore(struct pipe_scissor_state *scissor, struct fd_tile *tile)
  * case would be a single clear.
  */
 bool
-fd_gmem_needs_restore(struct fd_context *ctx, struct fd_tile *tile,
+fd_gmem_needs_restore(struct fd_batch *batch, struct fd_tile *tile,
                uint32_t buffers)
 {
-       if (!(ctx->restore & buffers))
+       if (!(batch->restore & buffers))
                return false;
 
        /* if buffers partially cleared, then slow-path to figure out
         * if this particular tile needs restoring:
         */
        if ((buffers & FD_BUFFER_COLOR) &&
-                       (ctx->partial_cleared & FD_BUFFER_COLOR) &&
-                       skip_restore(&ctx->cleared_scissor.color, tile))
+                       (batch->partial_cleared & FD_BUFFER_COLOR) &&
+                       skip_restore(&batch->cleared_scissor.color, tile))
                return false;
        if ((buffers & FD_BUFFER_DEPTH) &&
-                       (ctx->partial_cleared & FD_BUFFER_DEPTH) &&
-                       skip_restore(&ctx->cleared_scissor.depth, tile))
+                       (batch->partial_cleared & FD_BUFFER_DEPTH) &&
+                       skip_restore(&batch->cleared_scissor.depth, tile))
                return false;
        if ((buffers & FD_BUFFER_STENCIL) &&
-                       (ctx->partial_cleared & FD_BUFFER_STENCIL) &&
-                       skip_restore(&ctx->cleared_scissor.stencil, tile))
+                       (batch->partial_cleared & FD_BUFFER_STENCIL) &&
+                       skip_restore(&batch->cleared_scissor.stencil, tile))
                return false;
 
        return true;