gallium/radeon: use a common function for DMA blit preparation
authorMarek Olšák <marek.olsak@amd.com>
Thu, 21 Apr 2016 21:46:19 +0000 (23:46 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 10 May 2016 15:20:09 +0000 (17:20 +0200)
this is more robust and probably fixes some bugs already

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/radeon/r600_pipe_common.h
src/gallium/drivers/radeon/r600_texture.c
src/gallium/drivers/radeonsi/cik_sdma.c
src/gallium/drivers/radeonsi/si_dma.c

index 5224e42..672ddd4 100644 (file)
@@ -3497,14 +3497,10 @@ static void evergreen_dma_copy(struct pipe_context *ctx,
                return;
        }
 
-       if (src->format != dst->format || src_box->depth > 1 ||
-           (rdst->dirty_level_mask | rdst->stencil_dirty_level_mask) & (1 << dst_level)) {
+       if (src_box->depth > 1 ||
+           !r600_prepare_for_dma_blit(&rctx->b, rdst, dst_level, dstx, dsty,
+                                       dstz, rsrc, src_level, src_box))
                goto fallback;
-       }
-
-       if (rsrc->dirty_level_mask & (1 << src_level)) {
-               ctx->flush_resource(ctx, src);
-       }
 
        src_x = util_format_get_nblocksx(src->format, src_box->x);
        dst_x = util_format_get_nblocksx(src->format, dst_x);
index 2291096..48e3663 100644 (file)
@@ -2972,9 +2972,10 @@ static void r600_dma_copy(struct pipe_context *ctx,
                return;
        }
 
-       if (src->format != dst->format || src_box->depth > 1) {
+       if (src_box->depth > 1 ||
+           !r600_prepare_for_dma_blit(&rctx->b, rdst, dst_level, dstx, dsty,
+                                       dstz, rsrc, src_level, src_box))
                goto fallback;
-       }
 
        src_x = util_format_get_nblocksx(src->format, src_box->x);
        dst_x = util_format_get_nblocksx(src->format, dst_x);
index c313bc9..e0db061 100644 (file)
@@ -623,6 +623,13 @@ void r600_update_prims_generated_query_state(struct r600_common_context *rctx,
 void r600_streamout_init(struct r600_common_context *rctx);
 
 /* r600_texture.c */
+bool r600_prepare_for_dma_blit(struct r600_common_context *rctx,
+                               struct r600_texture *rdst,
+                               unsigned dst_level, unsigned dstx,
+                               unsigned dsty, unsigned dstz,
+                               struct r600_texture *rsrc,
+                               unsigned src_level,
+                               const struct pipe_box *src_box);
 void r600_texture_get_fmask_info(struct r600_common_screen *rscreen,
                                 struct r600_texture *rtex,
                                 unsigned nr_samples,
index 3e71da2..103b7b7 100644 (file)
 #include <errno.h>
 #include <inttypes.h>
 
+bool r600_prepare_for_dma_blit(struct r600_common_context *rctx,
+                              struct r600_texture *rdst,
+                              unsigned dst_level, unsigned dstx,
+                              unsigned dsty, unsigned dstz,
+                              struct r600_texture *rsrc,
+                              unsigned src_level,
+                              const struct pipe_box *src_box)
+{
+       if (!rctx->dma.cs)
+               return false;
+
+       if (util_format_get_blocksizebits(rdst->resource.b.b.format) !=
+           util_format_get_blocksizebits(rsrc->resource.b.b.format))
+               return false;
+
+       /* MSAA: Blits don't exist in the real world. */
+       if (rsrc->resource.b.b.nr_samples > 1 ||
+           rdst->resource.b.b.nr_samples > 1)
+               return false;
+
+       /* Depth-stencil surfaces:
+        *   When dst is linear, the DB->CB copy preserves HTILE.
+        *   When dst is tiled, the 3D path must be used to update HTILE.
+        */
+       if (rsrc->is_depth || rdst->is_depth)
+               return false;
+
+       /* DCC as:
+        *   src: Use the 3D path. DCC decompression is expensive.
+        *   dst: If overwriting the whole texture, disable DCC and use SDMA.
+        *        Otherwise, use the 3D path.
+        * TODO: handle the case when the dst box covers the whole texture
+        */
+       if (rsrc->dcc_offset || rdst->dcc_offset)
+               return false;
+
+       /* CMASK as:
+        *   src: Both texture and SDMA paths need decompression. Use SDMA.
+        *   dst: If overwriting the whole texture, deallocate CMASK and use
+        *        SDMA. Otherwise, use the 3D path.
+        * TODO: handle the case when the dst box covers the whole texture
+        */
+       if (rdst->cmask.size && rdst->dirty_level_mask & (1 << dst_level))
+               return false;
+
+       /* All requirements are met. Prepare textures for SDMA. */
+       if (rsrc->cmask.size && rsrc->dirty_level_mask & (1 << src_level))
+               rctx->b.flush_resource(&rctx->b, &rsrc->resource.b.b);
+
+       assert(!(rsrc->dirty_level_mask & (1 << src_level)));
+       assert(!(rdst->dirty_level_mask & (1 << dst_level)));
+
+       return true;
+}
+
 /* Same as resource_copy_region, except that both upsampling and downsampling are allowed. */
 static void r600_copy_region_with_blit(struct pipe_context *pipe,
                                       struct pipe_resource *dst,
index 2a996c1..7f7db91 100644 (file)
@@ -226,19 +226,9 @@ void cik_sdma_copy(struct pipe_context *ctx,
         */
        goto fallback;
 
-       if (src->format != dst->format ||
-           rdst->surface.nsamples > 1 || rsrc->surface.nsamples > 1 ||
-           (rdst->dirty_level_mask | rdst->stencil_dirty_level_mask) & (1 << dst_level) ||
-           rdst->dcc_offset || rsrc->dcc_offset) {
+       if (!r600_prepare_for_dma_blit(&sctx->b, rdst, dst_level, dstx, dsty,
+                                       dstz, rsrc, src_level, src_box))
                goto fallback;
-       }
-
-       if (rsrc->dirty_level_mask & (1 << src_level)) {
-               if (rsrc->htile_buffer)
-                       goto fallback;
-
-               ctx->flush_resource(ctx, src);
-       }
 
        src_x = util_format_get_nblocksx(src->format, src_box->x);
        dst_x = util_format_get_nblocksx(src->format, dst_x);
index 72956ac..84961d5 100644 (file)
@@ -230,17 +230,10 @@ void si_dma_copy(struct pipe_context *ctx,
         */
        goto fallback;
 
-       if (src->format != dst->format || src_box->depth > 1 ||
-           (rdst->dirty_level_mask | rdst->stencil_dirty_level_mask) & (1 << dst_level) ||
-           rdst->cmask.size || rdst->fmask.size ||
-           rsrc->cmask.size || rsrc->fmask.size ||
-           rdst->dcc_offset || rsrc->dcc_offset) {
+       if (src_box->depth > 1 ||
+           !r600_prepare_for_dma_blit(&sctx->b, rdst, dst_level, dstx, dsty,
+                                       dstz, rsrc, src_level, src_box))
                goto fallback;
-       }
-
-       if (rsrc->dirty_level_mask & (1 << src_level)) {
-               ctx->flush_resource(ctx, src);
-       }
 
        src_x = util_format_get_nblocksx(src->format, src_box->x);
        dst_x = util_format_get_nblocksx(src->format, dst_x);