[Mesa-dev] [PATCH 15/19] radeonsi: move CMASK size computation into ac_surface

Marek Olšák maraeo at gmail.com
Fri Jun 22 22:32:06 UTC 2018


From: Marek Olšák <marek.olsak at amd.com>

---
 src/amd/common/ac_surface.c                   | 61 +++++++++++++++
 src/amd/common/ac_surface.h                   |  5 ++
 src/gallium/drivers/radeonsi/si_clear.c       | 14 ++--
 src/gallium/drivers/radeonsi/si_pipe.h        |  7 +-
 src/gallium/drivers/radeonsi/si_state.c       |  2 +-
 src/gallium/drivers/radeonsi/si_texture.c     | 77 ++-----------------
 .../winsys/radeon/drm/radeon_drm_surface.c    | 13 ++++
 7 files changed, 94 insertions(+), 85 deletions(-)

diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c
index f5f88c1e791..9eb63bab038 100644
--- a/src/amd/common/ac_surface.c
+++ b/src/amd/common/ac_surface.c
@@ -540,20 +540,80 @@ static int gfx6_surface_settings(ADDR_HANDLE addrlib,
 		if (r != ADDR_OK)
 			return r;
 
 		assert(AddrBaseSwizzleOut.tileSwizzle <=
 		       u_bit_consecutive(0, sizeof(surf->tile_swizzle) * 8));
 		surf->tile_swizzle = AddrBaseSwizzleOut.tileSwizzle;
 	}
 	return 0;
 }
 
+void ac_compute_cmask(const struct radeon_info *info,
+		      const struct ac_surf_config *config,
+		      struct radeon_surf *surf)
+{
+	unsigned pipe_interleave_bytes = info->pipe_interleave_bytes;
+	unsigned num_pipes = info->num_tile_pipes;
+	unsigned cl_width, cl_height;
+
+	if (surf->flags & RADEON_SURF_Z_OR_SBUFFER)
+		return;
+
+	assert(info->chip_class <= VI);
+
+	switch (num_pipes) {
+	case 2:
+		cl_width = 32;
+		cl_height = 16;
+		break;
+	case 4:
+		cl_width = 32;
+		cl_height = 32;
+		break;
+	case 8:
+		cl_width = 64;
+		cl_height = 32;
+		break;
+	case 16: /* Hawaii */
+		cl_width = 64;
+		cl_height = 64;
+		break;
+	default:
+		assert(0);
+		return;
+	}
+
+	unsigned base_align = num_pipes * pipe_interleave_bytes;
+
+	unsigned width = align(config->info.width, cl_width*8);
+	unsigned height = align(config->info.height, cl_height*8);
+	unsigned slice_elements = (width * height) / (8*8);
+
+	/* Each element of CMASK is a nibble. */
+	unsigned slice_bytes = slice_elements / 2;
+
+	surf->u.legacy.cmask_slice_tile_max = (width * height) / (128*128);
+	if (surf->u.legacy.cmask_slice_tile_max)
+		surf->u.legacy.cmask_slice_tile_max -= 1;
+
+	unsigned num_layers;
+	if (config->is_3d)
+		num_layers = config->info.depth;
+	else if (config->is_cube)
+		num_layers = 6;
+	else
+		num_layers = config->info.array_size;
+
+	surf->cmask_alignment = MAX2(256, base_align);
+	surf->cmask_size = align(slice_bytes, base_align) * num_layers;
+}
+
 /**
  * Fill in the tiling information in \p surf based on the given surface config.
  *
  * The following fields of \p surf must be initialized by the caller:
  * blk_w, blk_h, bpe, flags.
  */
 static int gfx6_compute_surface(ADDR_HANDLE addrlib,
 				const struct radeon_info *info,
 				const struct ac_surf_config *config,
 				enum radeon_surf_mode mode,
@@ -955,20 +1015,21 @@ static int gfx6_compute_surface(ADDR_HANDLE addrlib,
 	/* The rotated micro tile mode doesn't work if both CMASK and RB+ are
 	 * used at the same time. This case is not currently expected to occur
 	 * because we don't use rotated. Enforce this restriction on all chips
 	 * to facilitate testing.
 	 */
 	if (surf->micro_tile_mode == RADEON_MICRO_MODE_ROTATED) {
 		assert(!"rotate micro tile mode is unsupported");
 		return ADDR_ERROR;
 	}
 
+	ac_compute_cmask(info, config, surf);
 	return 0;
 }
 
 /* This is only called when expecting a tiled layout. */
 static int
 gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib,
 				ADDR2_COMPUTE_SURFACE_INFO_INPUT *in,
 				bool is_fmask, unsigned flags,
 				AddrSwizzleMode *swizzle_mode)
 {
diff --git a/src/amd/common/ac_surface.h b/src/amd/common/ac_surface.h
index 01f1cc8dbac..6d95e610a59 100644
--- a/src/amd/common/ac_surface.h
+++ b/src/amd/common/ac_surface.h
@@ -102,20 +102,21 @@ struct legacy_surf_layout {
      * sampled from.
      */
     unsigned                    depth_adjusted:1;
     unsigned                    stencil_adjusted:1;
 
     struct legacy_surf_level    level[RADEON_SURF_MAX_LEVELS];
     struct legacy_surf_level    stencil_level[RADEON_SURF_MAX_LEVELS];
     uint8_t                     tiling_index[RADEON_SURF_MAX_LEVELS];
     uint8_t                     stencil_tiling_index[RADEON_SURF_MAX_LEVELS];
     struct legacy_surf_fmask    fmask;
+    unsigned                    cmask_slice_tile_max;
 };
 
 /* Same as addrlib - AddrResourceType. */
 enum gfx9_resource_type {
     RADEON_RESOURCE_1D = 0,
     RADEON_RESOURCE_2D,
     RADEON_RESOURCE_3D,
 };
 
 struct gfx9_surf_flags {
@@ -241,15 +242,19 @@ struct ac_surf_config {
 
 ADDR_HANDLE amdgpu_addr_create(const struct radeon_info *info,
 			       const struct amdgpu_gpu_info *amdinfo,
 			       uint64_t *max_alignment);
 
 int ac_compute_surface(ADDR_HANDLE addrlib, const struct radeon_info *info,
 		       const struct ac_surf_config * config,
 		       enum radeon_surf_mode mode,
 		       struct radeon_surf *surf);
 
+void ac_compute_cmask(const struct radeon_info *info,
+		      const struct ac_surf_config *config,
+		      struct radeon_surf *surf);
+
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* AC_SURFACE_H */
diff --git a/src/gallium/drivers/radeonsi/si_clear.c b/src/gallium/drivers/radeonsi/si_clear.c
index 050bbf3c181..7ea4459d512 100644
--- a/src/gallium/drivers/radeonsi/si_clear.c
+++ b/src/gallium/drivers/radeonsi/si_clear.c
@@ -35,38 +35,34 @@ enum {
 };
 
 static void si_alloc_separate_cmask(struct si_screen *sscreen,
 				    struct si_texture *tex)
 {
 	if (tex->cmask_buffer)
                 return;
 
 	assert(tex->cmask.size == 0);
 
-	si_texture_get_cmask_info(sscreen, tex, &tex->cmask);
-	if (!tex->cmask.size)
+	if (!tex->surface.cmask_size)
 		return;
 
 	tex->cmask_buffer =
 		si_aligned_buffer_create(&sscreen->b,
 					 SI_RESOURCE_FLAG_UNMAPPABLE,
 					 PIPE_USAGE_DEFAULT,
-					 tex->cmask.size,
-					 tex->cmask.alignment);
-	if (tex->cmask_buffer == NULL) {
-		tex->cmask.size = 0;
+					 tex->surface.cmask_size,
+					 tex->surface.cmask_alignment);
+	if (tex->cmask_buffer == NULL)
 		return;
-	}
 
-	/* update colorbuffer state bits */
+	tex->cmask.size = tex->surface.cmask_size;
 	tex->cmask.base_address_reg = tex->cmask_buffer->gpu_address >> 8;
-
 	tex->cb_color_info |= S_028C70_FAST_CLEAR(1);
 
 	p_atomic_inc(&sscreen->compressed_colortex_counter);
 }
 
 static bool si_set_clear_color(struct si_texture *tex,
 			       enum pipe_format surface_format,
 			       const union pipe_color_union *color)
 {
 	union util_color uc;
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index ddd1dfbf762..b6ef60cbe3e 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -225,24 +225,22 @@ struct r600_resource {
 };
 
 struct r600_transfer {
 	struct threaded_transfer	b;
 	struct r600_resource		*staging;
 	unsigned			offset;
 };
 
 struct r600_cmask_info {
 	uint64_t offset;
-	uint64_t size;
-	unsigned alignment;
-	unsigned slice_tile_max;
 	uint64_t base_address_reg;
+	uint32_t size;
 };
 
 struct si_texture {
 	struct r600_resource		buffer;
 
 	struct radeon_surf		surface;
 	uint64_t			size;
 	struct si_texture		*flushed_depth_texture;
 
 	/* Colorbuffer compression and fast clear. */
@@ -1218,23 +1216,20 @@ void si_update_vs_viewport_state(struct si_context *ctx);
 void si_init_viewport_functions(struct si_context *ctx);
 
 /* si_texture.c */
 bool si_prepare_for_dma_blit(struct si_context *sctx,
 			     struct si_texture *dst,
 			     unsigned dst_level, unsigned dstx,
 			     unsigned dsty, unsigned dstz,
 			     struct si_texture *src,
 			     unsigned src_level,
 			     const struct pipe_box *src_box);
-void si_texture_get_cmask_info(struct si_screen *sscreen,
-			       struct si_texture *tex,
-			       struct r600_cmask_info *out);
 void si_eliminate_fast_color_clear(struct si_context *sctx,
 				   struct si_texture *tex);
 void si_texture_discard_cmask(struct si_screen *sscreen,
 			      struct si_texture *tex);
 bool si_init_flushed_depth_texture(struct pipe_context *ctx,
 				   struct pipe_resource *texture,
 				   struct si_texture **staging);
 void si_print_texture_info(struct si_screen *sscreen,
 			   struct si_texture *tex, struct u_log_context *log);
 struct pipe_resource *si_texture_create(struct pipe_screen *screen,
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index e23666b4019..cb05de2ca9d 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -3123,21 +3123,21 @@ static void si_emit_framebuffer_state(struct si_context *sctx)
 			radeon_set_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + i * 0x3C,
 						   sctx->chip_class >= VI ? 14 : 13);
 			radeon_emit(cs, cb_color_base);		/* CB_COLOR0_BASE */
 			radeon_emit(cs, cb_color_pitch);	/* CB_COLOR0_PITCH */
 			radeon_emit(cs, cb_color_slice);	/* CB_COLOR0_SLICE */
 			radeon_emit(cs, cb->cb_color_view);	/* CB_COLOR0_VIEW */
 			radeon_emit(cs, cb_color_info);		/* CB_COLOR0_INFO */
 			radeon_emit(cs, cb_color_attrib);	/* CB_COLOR0_ATTRIB */
 			radeon_emit(cs, cb->cb_dcc_control);	/* CB_COLOR0_DCC_CONTROL */
 			radeon_emit(cs, cb_color_cmask);	/* CB_COLOR0_CMASK */
-			radeon_emit(cs, tex->cmask.slice_tile_max);	/* CB_COLOR0_CMASK_SLICE */
+			radeon_emit(cs, tex->surface.u.legacy.cmask_slice_tile_max); /* CB_COLOR0_CMASK_SLICE */
 			radeon_emit(cs, cb_color_fmask);		/* CB_COLOR0_FMASK */
 			radeon_emit(cs, cb_color_fmask_slice);		/* CB_COLOR0_FMASK_SLICE */
 			radeon_emit(cs, tex->color_clear_value[0]);	/* CB_COLOR0_CLEAR_WORD0 */
 			radeon_emit(cs, tex->color_clear_value[1]);	/* CB_COLOR0_CLEAR_WORD1 */
 
 			if (sctx->chip_class >= VI) /* R_028C94_CB_COLOR0_DCC_BASE */
 				radeon_emit(cs, cb_dcc_base);
 		}
 	}
 	for (; i < 8 ; i++)
diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 4cc8786429a..b0ad144c6d5 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -862,85 +862,20 @@ static void si_texture_destroy(struct pipe_screen *screen,
 	    r600_resource_reference(&tex->cmask_buffer, NULL);
 	}
 	pb_reference(&resource->buf, NULL);
 	r600_resource_reference(&tex->dcc_separate_buffer, NULL);
 	r600_resource_reference(&tex->last_dcc_separate_buffer, NULL);
 	FREE(tex);
 }
 
 static const struct u_resource_vtbl si_texture_vtbl;
 
-void si_texture_get_cmask_info(struct si_screen *sscreen,
-			       struct si_texture *tex,
-			       struct r600_cmask_info *out)
-{
-	unsigned pipe_interleave_bytes = sscreen->info.pipe_interleave_bytes;
-	unsigned num_pipes = sscreen->info.num_tile_pipes;
-	unsigned cl_width, cl_height;
-
-	if (sscreen->info.chip_class >= GFX9) {
-		out->alignment = tex->surface.u.gfx9.cmask_alignment;
-		out->size = tex->surface.u.gfx9.cmask_size;
-		return;
-	}
-
-	switch (num_pipes) {
-	case 2:
-		cl_width = 32;
-		cl_height = 16;
-		break;
-	case 4:
-		cl_width = 32;
-		cl_height = 32;
-		break;
-	case 8:
-		cl_width = 64;
-		cl_height = 32;
-		break;
-	case 16: /* Hawaii */
-		cl_width = 64;
-		cl_height = 64;
-		break;
-	default:
-		assert(0);
-		return;
-	}
-
-	unsigned base_align = num_pipes * pipe_interleave_bytes;
-
-	unsigned width = align(tex->buffer.b.b.width0, cl_width*8);
-	unsigned height = align(tex->buffer.b.b.height0, cl_height*8);
-	unsigned slice_elements = (width * height) / (8*8);
-
-	/* Each element of CMASK is a nibble. */
-	unsigned slice_bytes = slice_elements / 2;
-
-	out->slice_tile_max = (width * height) / (128*128);
-	if (out->slice_tile_max)
-		out->slice_tile_max -= 1;
-
-	out->alignment = MAX2(256, base_align);
-	out->size = util_num_layers(&tex->buffer.b.b, 0) *
-		    align(slice_bytes, base_align);
-}
-
-static void si_texture_allocate_cmask(struct si_screen *sscreen,
-				      struct si_texture *tex)
-{
-	si_texture_get_cmask_info(sscreen, tex, &tex->cmask);
-
-	tex->cmask.offset = align64(tex->size, tex->cmask.alignment);
-	tex->size = tex->cmask.offset + tex->cmask.size;
-
-	tex->cb_color_info |= S_028C70_FAST_CLEAR(1);
-}
-
 static void si_texture_get_htile_size(struct si_screen *sscreen,
 				      struct si_texture *tex)
 {
 	unsigned cl_width, cl_height, width, height;
 	unsigned slice_elements, slice_bytes, pipe_interleave_bytes, base_align;
 	unsigned num_pipes = sscreen->info.num_tile_pipes;
 
 	assert(sscreen->info.chip_class <= VI);
 
 	tex->surface.htile_size = 0;
@@ -1097,24 +1032,24 @@ void si_print_texture_info(struct si_screen *sscreen,
 	if (tex->surface.fmask_size)
 		u_log_printf(log, "  FMask: offset=%"PRIu64", size=%"PRIu64", alignment=%u, pitch_in_pixels=%u, "
 			"bankh=%u, slice_tile_max=%u, tile_mode_index=%u\n",
 			tex->fmask_offset, tex->surface.fmask_size, tex->surface.fmask_alignment,
 			tex->surface.u.legacy.fmask.pitch_in_pixels,
 			tex->surface.u.legacy.fmask.bankh,
 			tex->surface.u.legacy.fmask.slice_tile_max,
 			tex->surface.u.legacy.fmask.tiling_index);
 
 	if (tex->cmask.size)
-		u_log_printf(log, "  CMask: offset=%"PRIu64", size=%"PRIu64", alignment=%u, "
+		u_log_printf(log, "  CMask: offset=%"PRIu64", size=%u, alignment=%u, "
 			"slice_tile_max=%u\n",
-			tex->cmask.offset, tex->cmask.size, tex->cmask.alignment,
-			tex->cmask.slice_tile_max);
+			tex->cmask.offset, tex->cmask.size, tex->surface.cmask_alignment,
+			tex->surface.u.legacy.cmask_slice_tile_max);
 
 	if (tex->htile_offset)
 		u_log_printf(log, "  HTile: offset=%"PRIu64", size=%u, "
 			"alignment=%u, TC_compatible = %u\n",
 			tex->htile_offset, tex->surface.htile_size,
 			tex->surface.htile_alignment,
 			tex->tc_compatible_htile);
 
 	if (tex->dcc_offset) {
 		u_log_printf(log, "  DCC: offset=%"PRIu64", size=%u, alignment=%u\n",
@@ -1240,21 +1175,25 @@ si_texture_create_object(struct pipe_screen *screen,
 		}
 	} else {
 		if (base->nr_samples > 1 &&
 		    !buf &&
 		    !(sscreen->debug_flags & DBG(NO_FMASK))) {
 			/* Allocate FMASK. */
 			tex->fmask_offset = align64(tex->size,
 						     tex->surface.fmask_alignment);
 			tex->size = tex->fmask_offset + tex->surface.fmask_size;
 
-			si_texture_allocate_cmask(sscreen, tex);
+			/* Allocate CMASK. */
+			tex->cmask.size = tex->surface.cmask_size;
+			tex->cmask.offset = align64(tex->size, tex->surface.cmask_alignment);
+			tex->size = tex->cmask.offset + tex->cmask.size;
+			tex->cb_color_info |= S_028C70_FAST_CLEAR(1);
 			tex->cmask_buffer = &tex->buffer;
 
 			if (!tex->surface.fmask_size || !tex->cmask.size) {
 				FREE(tex);
 				return NULL;
 			}
 		}
 
 		/* Shared textures must always set up DCC here.
 		 * If it's not present, it will be disabled by
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_surface.c b/src/gallium/winsys/radeon/drm/radeon_drm_surface.c
index 4677a3bea7c..5e6978c58ef 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_surface.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_surface.c
@@ -286,17 +286,30 @@ static int radeon_winsys_surface_init(struct radeon_winsys *rws,
         surf_ws->u.legacy.fmask.slice_tile_max =
             (fmask.u.legacy.level[0].nblk_x * fmask.u.legacy.level[0].nblk_y) / 64;
         if (surf_ws->u.legacy.fmask.slice_tile_max)
             surf_ws->u.legacy.fmask.slice_tile_max -= 1;
 
         surf_ws->u.legacy.fmask.tiling_index = fmask.u.legacy.tiling_index[0];
         surf_ws->u.legacy.fmask.bankh = fmask.u.legacy.bankh;
         surf_ws->u.legacy.fmask.pitch_in_pixels = fmask.u.legacy.level[0].nblk_x;
     }
 
+    if (ws->gen == DRV_SI) {
+	    struct ac_surf_config config;
+
+	    /* Only these fields need to be set for the CMASK computation. */
+	    config.info.width = tex->width0;
+	    config.info.height = tex->height0;
+	    config.info.depth = tex->depth0;
+	    config.info.array_size = tex->array_size;
+	    config.is_3d = !!(tex->target == PIPE_TEXTURE_3D);
+	    config.is_cube = !!(tex->target == PIPE_TEXTURE_CUBE);
+
+	    ac_compute_cmask(&ws->info, &config, surf_ws);
+    }
     return 0;
 }
 
 void radeon_surface_init_functions(struct radeon_drm_winsys *ws)
 {
     ws->base.surface_init = radeon_winsys_surface_init;
 }
-- 
2.17.1



More information about the mesa-dev mailing list