radeonsi: always use SDMA for big buffer clears and first buffer uses
authorMarek Olšák <marek.olsak@amd.com>
Tue, 27 Dec 2016 00:33:42 +0000 (01:33 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Thu, 5 Jan 2017 17:43:23 +0000 (18:43 +0100)
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_cp_dma.c

index 5809317..3e908f6 100644 (file)
@@ -168,6 +168,7 @@ static void si_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst,
                            enum r600_coherency coher)
 {
        struct si_context *sctx = (struct si_context*)ctx;
+       struct radeon_winsys *ws = sctx->b.ws;
        unsigned tc_l2_flag = get_tc_l2_flag(sctx, coher);
        unsigned flush_flags = get_flush_flags(sctx, coher);
 
@@ -193,6 +194,25 @@ static void si_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst,
                return;
        }
 
+       /* dma_clear_buffer can use clear_buffer on failure. Make sure that
+        * doesn't happen. We don't want an infinite recursion: */
+       if (sctx->b.chip_class >= CIK && sctx->b.dma.cs &&
+           /* CP DMA is very slow. Always use SDMA for big clears. This
+            * alone improves DeusEx:MD performance by 70%. */
+           (size > 128 * 1024 ||
+            /* Buffers not used by the GFX IB yet will be cleared by SDMA.
+             * This happens to move most buffer clears to SDMA, including
+             * DCC and CMASK clears, because pipe->clear clears them before
+             * si_emit_framebuffer_state (in a draw call) adds them.
+             * For example, DeusEx:MD has 21 buffer clears per frame and all
+             * of them are moved to SDMA thanks to this. */
+            !ws->cs_is_buffer_referenced(sctx->b.gfx.cs,
+                                         r600_resource(dst)->buf,
+                                         RADEON_USAGE_READWRITE))) {
+               sctx->b.dma_clear_buffer(ctx, dst, offset, size, value);
+               return;
+       }
+
        uint64_t va = r600_resource(dst)->gpu_address + offset;
 
        /* Flush the caches. */