[Mesa-dev] [PATCH 6/9] radeonsi: support creating EQAA color textures

Marek Olšák maraeo at gmail.com
Wed May 2 04:13:22 UTC 2018


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

---
 src/gallium/drivers/radeonsi/si_clear.c   |  4 +-
 src/gallium/drivers/radeonsi/si_pipe.h    |  1 +
 src/gallium/drivers/radeonsi/si_texture.c | 45 +++++++++++++++--------
 3 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_clear.c b/src/gallium/drivers/radeonsi/si_clear.c
index 0f3546b02da..23977186611 100644
--- a/src/gallium/drivers/radeonsi/si_clear.c
+++ b/src/gallium/drivers/radeonsi/si_clear.c
@@ -240,32 +240,32 @@ void vi_dcc_clear_level(struct si_context *sctx,
 	} else {
 		dcc_buffer = &rtex->buffer.b.b;
 		dcc_offset = rtex->dcc_offset;
 	}
 
 	if (sctx->chip_class >= GFX9) {
 		/* Mipmap level clears aren't implemented. */
 		assert(rtex->buffer.b.b.last_level == 0);
 		/* 4x and 8x MSAA needs a sophisticated compute shader for
 		 * the clear. See AMDVLK. */
-		assert(rtex->buffer.b.b.nr_samples <= 2);
+		assert(rtex->num_color_samples <= 2);
 		clear_size = rtex->surface.dcc_size;
 	} else {
 		unsigned num_layers = util_num_layers(&rtex->buffer.b.b, level);
 
 		/* If this is 0, fast clear isn't possible. (can occur with MSAA) */
 		assert(rtex->surface.u.legacy.level[level].dcc_fast_clear_size);
 		/* Layered 4x and 8x MSAA DCC fast clears need to clear
 		 * dcc_fast_clear_size bytes for each layer. A compute shader
 		 * would be more efficient than separate per-layer clear operations.
 		 */
-		assert(rtex->buffer.b.b.nr_samples <= 2 || num_layers == 1);
+		assert(rtex->num_color_samples <= 2 || num_layers == 1);
 
 		dcc_offset += rtex->surface.u.legacy.level[level].dcc_offset;
 		clear_size = rtex->surface.u.legacy.level[level].dcc_fast_clear_size *
 			     num_layers;
 	}
 
 	si_clear_buffer(sctx, dcc_buffer, dcc_offset, clear_size,
 			clear_value, SI_COHERENCY_CB_META);
 }
 
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index b5caf944759..241385baed7 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -247,20 +247,21 @@ struct r600_texture {
 
 	/* Colorbuffer compression and fast clear. */
 	uint64_t			fmask_offset;
 	struct r600_cmask_info		cmask;
 	struct r600_resource		*cmask_buffer;
 	uint64_t			dcc_offset; /* 0 = disabled */
 	unsigned			cb_color_info; /* fast clear enable bit */
 	unsigned			color_clear_value[2];
 	unsigned			last_msaa_resolve_target_micro_mode;
 	unsigned			num_level0_transfers;
+	unsigned			num_color_samples;
 
 	/* Depth buffer compression and fast clear. */
 	uint64_t			htile_offset;
 	float				depth_clear_value;
 	uint16_t			dirty_level_mask; /* each bit says if that mipmap is compressed */
 	uint16_t			stencil_dirty_level_mask; /* each bit says if that mipmap is compressed */
 	enum pipe_format		db_render_format:16;
 	uint8_t				stencil_clear_value;
 	bool				tc_compatible_htile:1;
 	bool				depth_cleared:1; /* if it was cleared at least once */
diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c
index 1e328b90b62..52b8b87732f 100644
--- a/src/gallium/drivers/radeonsi/si_texture.c
+++ b/src/gallium/drivers/radeonsi/si_texture.c
@@ -213,20 +213,21 @@ static unsigned si_texture_get_offset(struct si_screen *sscreen,
 		       box->z * (uint64_t)rtex->surface.u.legacy.level[level].slice_size_dw * 4 +
 		       (box->y / rtex->surface.blk_h *
 		        rtex->surface.u.legacy.level[level].nblk_x +
 		        box->x / rtex->surface.blk_w) * rtex->surface.bpe;
 	}
 }
 
 static int si_init_surface(struct si_screen *sscreen,
 			   struct radeon_surf *surface,
 			   const struct pipe_resource *ptex,
+			   unsigned num_color_samples,
 			   enum radeon_surf_mode array_mode,
 			   unsigned pitch_in_bytes_override,
 			   unsigned offset,
 			   bool is_imported,
 			   bool is_scanout,
 			   bool is_flushed_depth,
 			   bool tc_compatible_htile)
 {
 	const struct util_format_description *desc =
 		util_format_description(ptex->format);
@@ -267,48 +268,48 @@ static int si_init_surface(struct si_screen *sscreen,
 	}
 
 	if (sscreen->info.chip_class >= VI &&
 	    (ptex->flags & SI_RESOURCE_FLAG_DISABLE_DCC ||
 	     ptex->format == PIPE_FORMAT_R9G9B9E5_FLOAT ||
 	     (ptex->nr_samples >= 2 && !sscreen->dcc_msaa_allowed)))
 		flags |= RADEON_SURF_DISABLE_DCC;
 
 	/* VI: DCC clear for 4x and 8x MSAA array textures unimplemented. */
 	if (sscreen->info.chip_class == VI &&
-	    ptex->nr_samples >= 4 &&
+	    num_color_samples >= 4 &&
 	    ptex->array_size > 1)
 		flags |= RADEON_SURF_DISABLE_DCC;
 
 	/* GFX9: DCC clear for 4x and 8x MSAA textures unimplemented. */
 	if (sscreen->info.chip_class >= GFX9 &&
-	    ptex->nr_samples >= 4)
+	    num_color_samples >= 4)
 		flags |= RADEON_SURF_DISABLE_DCC;
 
 	if (ptex->bind & PIPE_BIND_SCANOUT || is_scanout) {
 		/* This should catch bugs in gallium users setting incorrect flags. */
 		assert(ptex->nr_samples <= 1 &&
 		       ptex->array_size == 1 &&
 		       ptex->depth0 == 1 &&
 		       ptex->last_level == 0 &&
 		       !(flags & RADEON_SURF_Z_OR_SBUFFER));
 
 		flags |= RADEON_SURF_SCANOUT;
 	}
 
 	if (ptex->bind & PIPE_BIND_SHARED)
 		flags |= RADEON_SURF_SHAREABLE;
 	if (is_imported)
 		flags |= RADEON_SURF_IMPORTED | RADEON_SURF_SHAREABLE;
 	if (!(ptex->flags & SI_RESOURCE_FLAG_FORCE_TILING))
 		flags |= RADEON_SURF_OPTIMIZE_FOR_SPACE;
 
-	r = sscreen->ws->surface_init(sscreen->ws, ptex, ptex->nr_samples,
+	r = sscreen->ws->surface_init(sscreen->ws, ptex, num_color_samples,
 				      flags, bpe, array_mode, surface);
 	if (r) {
 		return r;
 	}
 
 	unsigned pitch = pitch_in_bytes_override / bpe;
 
 	if (sscreen->info.chip_class >= GFX9) {
 		if (pitch) {
 			surface->u.gfx9.surf_pitch = pitch;
@@ -1138,20 +1139,21 @@ void si_print_texture_info(struct si_screen *sscreen,
 				rtex->surface.u.legacy.stencil_level[i].mode,
 				rtex->surface.u.legacy.stencil_tiling_index[i]);
 		}
 	}
 }
 
 /* Common processing for r600_texture_create and r600_texture_from_handle */
 static struct r600_texture *
 si_texture_create_object(struct pipe_screen *screen,
 			 const struct pipe_resource *base,
+			 unsigned num_color_samples,
 			 struct pb_buffer *buf,
 			 struct radeon_surf *surface)
 {
 	struct r600_texture *rtex;
 	struct r600_resource *resource;
 	struct si_screen *sscreen = (struct si_screen*)screen;
 
 	rtex = CALLOC_STRUCT(r600_texture);
 	if (!rtex)
 		return NULL;
@@ -1161,20 +1163,21 @@ si_texture_create_object(struct pipe_screen *screen,
 	resource->b.b.next = NULL;
 	resource->b.vtbl = &si_texture_vtbl;
 	pipe_reference_init(&resource->b.b.reference, 1);
 	resource->b.b.screen = screen;
 
 	/* don't include stencil-only formats which we don't support for rendering */
 	rtex->is_depth = util_format_has_depth(util_format_description(rtex->buffer.b.b.format));
 
 	rtex->surface = *surface;
 	rtex->size = rtex->surface.surf_size;
+	rtex->num_color_samples = num_color_samples;
 
 	rtex->tc_compatible_htile = rtex->surface.htile_size != 0 &&
 				    (rtex->surface.flags &
 				     RADEON_SURF_TC_COMPATIBLE_HTILE);
 
 	/* TC-compatible HTILE:
 	 * - VI only supports Z32_FLOAT.
 	 * - GFX9 only supports Z32_FLOAT and Z16_UNORM. */
 	if (rtex->tc_compatible_htile) {
 		if (sscreen->info.chip_class >= GFX9 &&
@@ -1377,53 +1380,60 @@ si_choose_tiling(struct si_screen *sscreen,
 
 	/* Make small textures 1D tiled. */
 	if (templ->width0 <= 16 || templ->height0 <= 16 ||
 	    (sscreen->debug_flags & DBG(NO_2D_TILING)))
 		return RADEON_SURF_MODE_1D;
 
 	/* The allocator will switch to 1D if needed. */
 	return RADEON_SURF_MODE_2D;
 }
 
+static unsigned si_get_num_color_samples(const struct pipe_resource *templ,
+					 bool imported)
+{
+	return CLAMP(templ->nr_samples, 1, 8);
+}
+
 struct pipe_resource *si_texture_create(struct pipe_screen *screen,
 					const struct pipe_resource *templ)
 {
 	struct si_screen *sscreen = (struct si_screen*)screen;
 	struct radeon_surf surface = {0};
 	bool is_flushed_depth = templ->flags & SI_RESOURCE_FLAG_FLUSHED_DEPTH;
 	bool tc_compatible_htile =
 		sscreen->info.chip_class >= VI &&
 		/* There are issues with TC-compatible HTILE on Tonga (and
 		 * Iceland is the same design), and documented bug workarounds
 		 * don't help. For example, this fails:
 		 *   piglit/bin/tex-miplevel-selection 'texture()' 2DShadow -auto
 		 */
 		sscreen->info.family != CHIP_TONGA &&
 		sscreen->info.family != CHIP_ICELAND &&
 		(templ->flags & PIPE_RESOURCE_FLAG_TEXTURING_MORE_LIKELY) &&
 		!(sscreen->debug_flags & DBG(NO_HYPERZ)) &&
 		!is_flushed_depth &&
 		templ->nr_samples <= 1 && /* TC-compat HTILE is less efficient with MSAA */
 		util_format_is_depth_or_stencil(templ->format);
-
+	unsigned num_color_samples = si_get_num_color_samples(templ, false);
 	int r;
 
-	r = si_init_surface(sscreen, &surface, templ,
+	r = si_init_surface(sscreen, &surface, templ, num_color_samples,
 			    si_choose_tiling(sscreen, templ, tc_compatible_htile),
 			    0, 0, false, false, is_flushed_depth,
 			    tc_compatible_htile);
 	if (r) {
 		return NULL;
 	}
 
 	return (struct pipe_resource *)
-	       si_texture_create_object(screen, templ, NULL, &surface);
+	       si_texture_create_object(screen, templ, num_color_samples,
+					NULL, &surface);
 }
 
 static struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen,
 						    const struct pipe_resource *templ,
 						    struct winsys_handle *whandle,
 						    unsigned usage)
 {
 	struct si_screen *sscreen = (struct si_screen*)screen;
 	struct pb_buffer *buf = NULL;
 	unsigned stride = 0, offset = 0;
@@ -1440,27 +1450,31 @@ static struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen,
 		return NULL;
 
 	buf = sscreen->ws->buffer_from_handle(sscreen->ws, whandle, &stride, &offset);
 	if (!buf)
 		return NULL;
 
 	sscreen->ws->buffer_get_metadata(buf, &metadata);
 	si_surface_import_metadata(sscreen, &surface, &metadata,
 				     &array_mode, &is_scanout);
 
-	r = si_init_surface(sscreen, &surface, templ, array_mode, stride,
-			      offset, true, is_scanout, false, false);
+	unsigned num_color_samples = si_get_num_color_samples(templ, true);
+
+	r = si_init_surface(sscreen, &surface, templ, num_color_samples,
+			    array_mode, stride, offset, true, is_scanout,
+			    false, false);
 	if (r) {
 		return NULL;
 	}
 
-	rtex = si_texture_create_object(screen, templ, buf, &surface);
+	rtex = si_texture_create_object(screen, templ, num_color_samples,
+					buf, &surface);
 	if (!rtex)
 		return NULL;
 
 	rtex->buffer.b.is_shared = true;
 	rtex->buffer.external_usage = usage;
 
 	si_apply_opaque_metadata(sscreen, rtex, &metadata);
 
 	assert(rtex->surface.tile_swizzle == 0);
 	return &rtex->buffer.b.b;
@@ -2368,31 +2382,32 @@ si_texture_from_memobj(struct pipe_screen *screen,
 		 * All the use cases we are aware of at the moment for memory
 		 * objects use dedicated allocations. So lets keep the initial
 		 * implementation simple.
 		 *
 		 * A possible alternative is to attempt to reconstruct the
 		 * tiling information when the TexParameter TEXTURE_TILING_EXT
 		 * is set.
 		 */
 		array_mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
 		is_scanout = false;
-
 	}
 
-	r = si_init_surface(sscreen, &surface, templ,
-			      array_mode, memobj->stride,
-			      offset, true, is_scanout,
-			      false, false);
+	unsigned num_color_samples = si_get_num_color_samples(templ, true);
+
+	r = si_init_surface(sscreen, &surface, templ, num_color_samples,
+			    array_mode, memobj->stride, offset, true,
+			    is_scanout, false, false);
 	if (r)
 		return NULL;
 
-	rtex = si_texture_create_object(screen, templ, memobj->buf, &surface);
+	rtex = si_texture_create_object(screen, templ, num_color_samples,
+					memobj->buf, &surface);
 	if (!rtex)
 		return NULL;
 
 	/* r600_texture_create_object doesn't increment refcount of
 	 * memobj->buf, so increment it here.
 	 */
 	pb_reference(&buf, memobj->buf);
 
 	rtex->buffer.b.is_shared = true;
 	rtex->buffer.external_usage = PIPE_HANDLE_USAGE_READ_WRITE;
-- 
2.17.0



More information about the mesa-dev mailing list