[Mesa-dev] [PATCH 03/10] gallium/radeon: replace radeon_surf_info::dcc_enabled with num_dcc_levels

Marek Olšák maraeo at gmail.com
Sat Oct 29 11:17:18 UTC 2016


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

---
 src/gallium/drivers/radeon/r600_texture.c      | 14 +++++++-------
 src/gallium/drivers/radeon/radeon_winsys.h     |  6 +++++-
 src/gallium/drivers/radeonsi/si_blit.c         |  4 ++--
 src/gallium/drivers/radeonsi/si_descriptors.c  |  4 ++--
 src/gallium/drivers/radeonsi/si_state.c        |  2 +-
 src/gallium/winsys/amdgpu/drm/amdgpu_surface.c |  4 ++--
 6 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index bc981da..46281cb 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -66,22 +66,22 @@ bool r600_prepare_for_dma_blit(struct r600_common_context *rctx,
 	 *   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: Use the 3D path to compress the pixels with DCC.
 	 */
-	if ((rsrc->dcc_offset && rsrc->surface.level[src_level].dcc_enabled) ||
-	    (rdst->dcc_offset && rdst->surface.level[dst_level].dcc_enabled))
+	if ((rsrc->dcc_offset && src_level < rsrc->surface.num_dcc_levels) ||
+	    (rdst->dcc_offset && dst_level < rdst->surface.num_dcc_levels))
 		return false;
 
 	/* CMASK as:
 	 *   src: Both texture and SDMA paths need decompression. Use SDMA.
 	 *   dst: If overwriting the whole texture, discard CMASK and use
 	 *        SDMA. Otherwise, use the 3D path.
 	 */
 	if (rdst->cmask.size && rdst->dirty_level_mask & (1 << dst_level)) {
 		/* The CMASK clear is only enabled for the first level. */
 		assert(dst_level == 0);
@@ -933,21 +933,21 @@ void r600_print_texture_info(struct r600_texture *rtex, FILE *f)
 			rtex->htile_buffer->buf->alignment,
 			rtex->tc_compatible_htile);
 
 	if (rtex->dcc_offset) {
 		fprintf(f, "  DCC: offset=%"PRIu64", size=%"PRIu64", alignment=%u\n",
 			rtex->dcc_offset, rtex->surface.dcc_size,
 			rtex->surface.dcc_alignment);
 		for (i = 0; i <= rtex->resource.b.b.last_level; i++)
 			fprintf(f, "  DCCLevel[%i]: enabled=%u, offset=%"PRIu64", "
 				"fast_clear_size=%"PRIu64"\n",
-				i, rtex->surface.level[i].dcc_enabled,
+				i, i < rtex->surface.num_dcc_levels,
 				rtex->surface.level[i].dcc_offset,
 				rtex->surface.level[i].dcc_fast_clear_size);
 	}
 
 	for (i = 0; i <= rtex->resource.b.b.last_level; i++)
 		fprintf(f, "  Level[%i]: offset=%"PRIu64", slice_size=%"PRIu64", "
 			"npix_x=%u, npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
 			"pitch_bytes=%u, mode=%u, tiling_index = %u\n",
 			i, rtex->surface.level[i].offset,
 			rtex->surface.level[i].slice_size,
@@ -1737,21 +1737,21 @@ bool vi_dcc_formats_compatible(enum pipe_format format1,
 }
 
 void vi_dcc_disable_if_incompatible_format(struct r600_common_context *rctx,
 					   struct pipe_resource *tex,
 					   unsigned level,
 					   enum pipe_format view_format)
 {
 	struct r600_texture *rtex = (struct r600_texture *)tex;
 
 	if (rtex->dcc_offset &&
-	    rtex->surface.level[level].dcc_enabled &&
+	    level < rtex->surface.num_dcc_levels &&
 	    !vi_dcc_formats_compatible(tex->format, view_format))
 		if (!r600_texture_disable_dcc(rctx, (struct r600_texture*)tex))
 			rctx->decompress_dcc(&rctx->b, rtex);
 }
 
 struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
 						struct pipe_resource *texture,
 						const struct pipe_surface *templ,
 						unsigned width, unsigned height)
 {
@@ -2089,21 +2089,21 @@ static void vi_separate_dcc_try_enable(struct r600_common_context *rctx,
 
 	/* Enable the DCC stat gathering. */
 	if (!tex->dcc_gather_statistics) {
 		tex->dcc_gather_statistics = true;
 		vi_separate_dcc_start_query(&rctx->b, tex);
 	}
 
 	if (!vi_should_enable_separate_dcc(tex))
 		return; /* stats show that DCC decompression is too expensive */
 
-	assert(tex->surface.level[0].dcc_enabled);
+	assert(tex->surface.num_dcc_levels);
 	assert(!tex->dcc_separate_buffer);
 
 	r600_texture_discard_cmask(rctx->screen, tex);
 
 	/* Get a DCC buffer. */
 	if (tex->last_dcc_separate_buffer) {
 		assert(tex->dcc_gather_statistics);
 		assert(!tex->dcc_separate_buffer);
 		tex->dcc_separate_buffer = tex->last_dcc_separate_buffer;
 		tex->last_dcc_separate_buffer = NULL;
@@ -2304,21 +2304,21 @@ static bool vi_get_fast_clear_parameters(enum pipe_format surface_format,
 	return true;
 }
 
 void vi_dcc_clear_level(struct r600_common_context *rctx,
 			struct r600_texture *rtex,
 			unsigned level, unsigned clear_value)
 {
 	struct pipe_resource *dcc_buffer;
 	uint64_t dcc_offset;
 
-	assert(rtex->dcc_offset && rtex->surface.level[level].dcc_enabled);
+	assert(rtex->dcc_offset && level < rtex->surface.num_dcc_levels);
 
 	if (rtex->dcc_separate_buffer) {
 		dcc_buffer = &rtex->dcc_separate_buffer->b.b;
 		dcc_offset = 0;
 	} else {
 		dcc_buffer = &rtex->resource.b.b;
 		dcc_offset = rtex->dcc_offset;
 	}
 
 	dcc_offset += rtex->surface.level[level].dcc_offset;
@@ -2476,21 +2476,21 @@ void evergreen_do_fast_color_clear(struct r600_common_context *rctx,
 			/* Stoney can't do a CMASK-based clear, so all clears are
 			 * considered to be hypothetically slow clears, which
 			 * is weighed when determining to enable separate DCC.
 			 */
 			if (tex->dcc_gather_statistics &&
 			    rctx->family == CHIP_STONEY)
 				tex->num_slow_clears++;
 		}
 
 		/* Try to clear DCC first, otherwise try CMASK. */
-		if (tex->dcc_offset && tex->surface.level[0].dcc_enabled) {
+		if (tex->dcc_offset && tex->surface.num_dcc_levels) {
 			uint32_t reset_value;
 			bool clear_words_needed;
 
 			if (rctx->screen->debug_flags & DBG_NO_DCC_CLEAR)
 				continue;
 
 			if (!vi_get_fast_clear_parameters(fb->cbufs[i]->format,
 							  color, &reset_value,
 							  &clear_words_needed))
 				continue;
diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h
index 2330cdd..f5b9f10 100644
--- a/src/gallium/drivers/radeon/radeon_winsys.h
+++ b/src/gallium/drivers/radeon/radeon_winsys.h
@@ -276,28 +276,32 @@ enum radeon_surf_mode {
 
 struct radeon_surf_level {
     uint64_t                    offset;
     uint64_t                    slice_size;
     uint64_t                    dcc_offset;
     uint64_t                    dcc_fast_clear_size;
     uint16_t                    nblk_x;
     uint16_t                    nblk_y;
     uint32_t                    pitch_bytes;
     enum radeon_surf_mode       mode;
-    bool                        dcc_enabled;
 };
 
 struct radeon_surf {
     /* Format properties. */
     unsigned                    blk_w:4;
     unsigned                    blk_h:4;
     unsigned                    bpe:5;
+    /* Number of mipmap levels where DCC is enabled starting from level 0.
+     * Non-zero levels may be disabled due to alignment constraints, but not
+     * the first level.
+     */
+    unsigned                    num_dcc_levels:4;
     uint32_t                    flags;
 
     /* These are return values. Some of them can be set by the caller, but
      * they will be treated as hints (e.g. bankw, bankh) and might be
      * changed by the calculator.
      */
     uint64_t                    surf_size;
     uint64_t                    dcc_size;
     uint64_t                    htile_size;
 
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index db41f56..0f46d71 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -422,21 +422,21 @@ static void si_blit_decompress_color(struct pipe_context *ctx,
 		level_mask &= rtex->dirty_level_mask;
 	if (!level_mask)
 		return;
 
 	if (rtex->dcc_offset && need_dcc_decompress) {
 		custom_blend = sctx->custom_blend_dcc_decompress;
 
 		/* disable levels without DCC */
 		for (int i = first_level; i <= last_level; i++) {
 			if (!rtex->dcc_offset ||
-			    !rtex->surface.level[i].dcc_enabled)
+			    i >= rtex->surface.num_dcc_levels)
 				level_mask &= ~(1 << i);
 		}
 	} else if (rtex->fmask.size) {
 		custom_blend = sctx->custom_blend_decompress;
 	} else {
 		custom_blend = sctx->custom_blend_fastclear;
 	}
 
 	while (level_mask) {
 		unsigned level = u_bit_scan(&level_mask);
@@ -1022,21 +1022,21 @@ static bool do_hardware_msaa_resolve(struct pipe_context *ctx,
 			src->last_msaa_resolve_target_micro_mode =
 				dst->surface.micro_tile_mode;
 			goto resolve_to_temp;
 		}
 
 		/* Resolving into a surface with DCC is unsupported. Since
 		 * it's being overwritten anyway, clear it to uncompressed.
 		 * This is still the fastest codepath even with this clear.
 		 */
 		if (dst->dcc_offset &&
-		    dst->surface.level[info->dst.level].dcc_enabled) {
+		    info->dst.level < dst->surface.num_dcc_levels) {
 			vi_dcc_clear_level(&sctx->b, dst, info->dst.level,
 					   0xFFFFFFFF);
 			dst->dirty_level_mask &= ~(1 << info->dst.level);
 		}
 
 		/* Resolve directly from src to dst. */
 		si_blitter_begin(ctx, SI_COLOR_RESOLVE |
 				 (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND));
 		util_blitter_custom_resolve_color(sctx->blitter,
 						  info->dst.resource, info->dst.level,
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 19cae65..9358542 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -387,21 +387,21 @@ void si_set_mutable_tex_desc_fields(struct r600_texture *tex,
 	state[3] &= C_008F1C_TILING_INDEX;
 	state[4] &= C_008F20_PITCH;
 	state[6] &= C_008F28_COMPRESSION_EN;
 
 	state[0] = va >> 8;
 	state[1] |= S_008F14_BASE_ADDRESS_HI(va >> 40);
 	state[3] |= S_008F1C_TILING_INDEX(si_tile_mode_index(tex, base_level,
 							     is_stencil));
 	state[4] |= S_008F20_PITCH(pitch - 1);
 
-	if (tex->dcc_offset && tex->surface.level[first_level].dcc_enabled) {
+	if (tex->dcc_offset && first_level < tex->surface.num_dcc_levels) {
 		state[6] |= S_008F28_COMPRESSION_EN(1);
 		state[7] = ((!tex->dcc_separate_buffer ? tex->resource.gpu_address : 0) +
 			    tex->dcc_offset +
 			    base_level_info->dcc_offset) >> 8;
 	} else if (tex->tc_compatible_htile) {
 		state[6] |= S_008F28_COMPRESSION_EN(1);
 		state[7] = tex->htile_buffer->gpu_address >> 8;
 	}
 }
 
@@ -662,21 +662,21 @@ static void si_set_shader_image(struct si_context *ctx,
 		si_set_buf_desc_address(res, view->u.buf.offset, desc + 4);
 
 		images->compressed_colortex_mask &= ~(1 << slot);
 		res->bind_history |= PIPE_BIND_SHADER_IMAGE;
 	} else {
 		static const unsigned char swizzle[4] = { 0, 1, 2, 3 };
 		struct r600_texture *tex = (struct r600_texture *)res;
 		unsigned level = view->u.tex.level;
 		unsigned width, height, depth;
 		bool uses_dcc = tex->dcc_offset &&
-				tex->surface.level[level].dcc_enabled;
+				level < tex->surface.num_dcc_levels;
 
 		assert(!tex->is_depth);
 		assert(tex->fmask.size == 0);
 
 		if (uses_dcc &&
 		    (view->access & PIPE_IMAGE_ACCESS_WRITE ||
 		     !vi_dcc_formats_compatible(res->b.b.format, view->format))) {
 			/* If DCC can't be disabled, at least decompress it.
 			 * The decompression is relatively cheap if the surface
 			 * has been decompressed already.
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 0633b64..bf89d8b 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -2493,21 +2493,21 @@ static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom
 			/* This must be set for fast clear to work without FMASK. */
 			if (sctx->b.chip_class >= CIK)
 				cb_color_pitch |= S_028C64_FMASK_TILE_MAX(pitch_tile_max);
 			cb_color_attrib |= S_028C74_FMASK_TILE_MODE_INDEX(tile_mode_index);
 			cb_color_fmask = cb_color_base;
 			cb_color_fmask_slice = S_028C88_TILE_MAX(slice_tile_max);
 		}
 
 		cb_color_info = cb->cb_color_info | tex->cb_color_info;
 
-		if (tex->dcc_offset && cb->level_info->dcc_enabled) {
+		if (tex->dcc_offset && cb->base.u.tex.level < tex->surface.num_dcc_levels) {
 			bool is_msaa_resolve_dst = state->cbufs[0] &&
 						   state->cbufs[0]->texture->nr_samples > 1 &&
 						   state->cbufs[1] == &cb->base &&
 						   state->cbufs[1]->texture->nr_samples <= 1;
 
 			if (!is_msaa_resolve_dst)
 				cb_color_info |= S_028C70_DCC_ENABLE(1);
 		}
 
 		radeon_set_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + i * 0x3C,
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
index 45edcc2..8c57287 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
@@ -211,39 +211,38 @@ static int compute_level(struct amdgpu_winsys *ws,
 
    if (is_stencil)
       surf->stencil_tiling_index[level] = AddrSurfInfoOut->tileIndex;
    else
       surf->tiling_index[level] = AddrSurfInfoOut->tileIndex;
 
    surf->surf_size = surf_level->offset + AddrSurfInfoOut->surfSize;
 
    /* Clear DCC fields at the beginning. */
    surf_level->dcc_offset = 0;
-   surf_level->dcc_enabled = false;
 
    /* The previous level's flag tells us if we can use DCC for this level. */
    if (AddrSurfInfoIn->flags.dccCompatible &&
        (level == 0 || AddrDccOut->subLvlCompressible)) {
       AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize;
       AddrDccIn->tileMode = AddrSurfInfoOut->tileMode;
       AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo;
       AddrDccIn->tileIndex = AddrSurfInfoOut->tileIndex;
       AddrDccIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex;
 
       ret = AddrComputeDccInfo(ws->addrlib,
                                AddrDccIn,
                                AddrDccOut);
 
       if (ret == ADDR_OK) {
          surf_level->dcc_offset = surf->dcc_size;
          surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize;
-         surf_level->dcc_enabled = true;
+         surf->num_dcc_levels = level + 1;
          surf->dcc_size = surf_level->dcc_offset + AddrDccOut->dccRamSize;
          surf->dcc_alignment = MAX2(surf->dcc_alignment, AddrDccOut->dccRamBaseAlign);
       }
    }
 
    /* TC-compatible HTILE. */
    if (!is_stencil &&
        AddrSurfInfoIn->flags.depth &&
        AddrSurfInfoIn->flags.tcCompatible &&
        surf_level->mode == RADEON_SURF_MODE_2D &&
@@ -481,20 +480,21 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
          if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE)
             AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */
          else
             AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */
 
          /* Addrlib doesn't set this if tileIndex is forced like above. */
          AddrSurfInfoOut.macroModeIndex = cik_get_macro_tile_index(surf);
       }
    }
 
+   surf->num_dcc_levels = 0;
    surf->surf_size = 0;
    surf->dcc_size = 0;
    surf->dcc_alignment = 1;
    surf->htile_size = 0;
    surf->htile_alignment = 1;
 
    /* Calculate texture layout information. */
    for (level = 0; level <= tex->last_level; level++) {
       r = compute_level(ws, tex, surf, false, level, compressed,
                         &AddrSurfInfoIn, &AddrSurfInfoOut,
-- 
2.7.4



More information about the mesa-dev mailing list