[Mesa-dev] [PATCH 27/30] i965: Wholesale replace the color resolve tracking code
Pohjolainen, Topi
topi.pohjolainen at gmail.com
Wed May 31 13:03:51 UTC 2017
On Fri, May 26, 2017 at 04:30:31PM -0700, Jason Ekstrand wrote:
> This commit reworks the resolve tracking for CCS and MCS to use the new
> isl_aux_state enum. This should provide much more accurate and easy to
> reason about tracking. In order to understand, for instance, the
> intel_miptree_prepare_ccs_access function, one only has to go look at
> the giant comment for the isl_aux_state enum and follow the arrows.
> Unfortunately, there's no good way to split this up without making a
> real mess so there are a bunch of changes in here:
>
> 1) We now do partial resolves. I really have no idea how this ever
> worked before. So far as I can tell, the only time the old code
> ever did a partial resolve was when it was using CCS_D where a
> partial resolve and a full resolve are the same thing.
>
> 2) We are now tracking 4 states instead of 3 for CCS_E. In particular,
> we distinguish between compressed with clear and compressed without
> clear. The end result is that you will never get two partial
> resolves in a row.
>
> 3) The texture view rules are now more correct. Previously, we would
> only bail if compression was not supported by the destination
> format. However, this is not actually correct. Not all format
> pairs are supported for texture views with CCS even if both support
> CCS individually. Fortunately, ISL has a helper for this.
>
> 4) We are no longer using intel_resolve_map for tracking aux state but
> are instead using a simple array of enum isl_aux_state indexed by
> level and layer. This is because, now that we're tracking 4
> different states, it's no longer clear which should be the "default"
> and array lookups are faster than linked list searches.
>
> 5) The new code is very assert-happy. Incorrect transitions will now
> get caught by assertions rather than by rendering corruption.
> ---
> src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 479 +++++++++++++++++---------
> src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 39 +--
> src/mesa/drivers/dri/i965/intel_resolve_map.h | 62 +---
> 3 files changed, 320 insertions(+), 260 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> index cae8358..3e30b2a 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> @@ -326,7 +326,7 @@ intel_miptree_create_layout(struct brw_context *brw,
> mt->aux_disable |= INTEL_AUX_DISABLE_CCS;
> mt->is_scanout = (layout_flags & MIPTREE_LAYOUT_FOR_SCANOUT) != 0;
> exec_list_make_empty(&mt->hiz_map);
> - exec_list_make_empty(&mt->color_resolve_map);
> + mt->aux_state = NULL;
> mt->cpp = _mesa_get_format_bytes(format);
> mt->num_samples = num_samples;
> mt->compressed = _mesa_is_format_compressed(format);
> @@ -576,6 +576,46 @@ intel_lower_compressed_format(struct brw_context *brw, mesa_format format)
> }
> }
>
> +static enum isl_aux_state **
> +create_aux_state_map(struct intel_mipmap_tree *mt,
> + enum isl_aux_state initial)
> +{
> + const uint32_t levels = mt->last_level + 1;
> +
> + uint32_t total_slices = 0;
> + for (uint32_t level = 0; level < levels; level++)
> + total_slices += mt->level[level].depth;
> +
> + const size_t per_level_array_size = levels * sizeof(enum isl_aux_state *);
> +
> + /* We're going to allocate a single chunk of data for both the per-level
> + * reference array and the arrays of aux_state. This makes cleanup
> + * significantly easier.
> + */
> + const size_t total_size = per_level_array_size +
> + total_slices * sizeof(enum isl_aux_state);
> + void *data = malloc(total_size);
> + if (data == NULL)
> + return NULL;
> +
> + enum isl_aux_state **per_level_arr = data;
> + enum isl_aux_state *s = data + per_level_array_size;
> + for (uint32_t level = 0; level < levels; level++) {
> + per_level_arr[level] = s;
> + for (uint32_t a = 0; a < mt->level[level].depth; a++)
> + *(s++) = initial;
> + }
> + assert((void *)s == data + total_size);
> +
> + return per_level_arr;
> +}
> +
> +static void
> +free_aux_state_map(enum isl_aux_state **state)
> +{
> + free(state);
> +}
> +
> static struct intel_mipmap_tree *
> miptree_create(struct brw_context *brw,
> GLenum target,
> @@ -935,7 +975,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
> free((*mt)->mcs_buf);
> }
> intel_resolve_map_clear(&(*mt)->hiz_map);
> - intel_resolve_map_clear(&(*mt)->color_resolve_map);
> + free_aux_state_map((*mt)->aux_state);
>
> intel_miptree_release(&(*mt)->plane[0]);
> intel_miptree_release(&(*mt)->plane[1]);
> @@ -1482,27 +1522,31 @@ intel_miptree_alloc_mcs(struct brw_context *brw,
> unreachable("Unrecognized sample count in intel_miptree_alloc_mcs");
> };
>
> + /* Multisampled miptrees are only supported for single level. */
> + assert(mt->first_level == 0);
> + enum isl_aux_state **aux_state =
> + create_aux_state_map(mt, ISL_AUX_STATE_CLEAR);
> + if (!aux_state)
> + return false;
> +
> mt->mcs_buf =
> intel_mcs_miptree_buf_create(brw, mt,
> format,
> mt->logical_width0,
> mt->logical_height0,
> MIPTREE_LAYOUT_ACCELERATED_UPLOAD);
> - if (!mt->mcs_buf)
> + if (!mt->mcs_buf) {
> + free(aux_state);
> return false;
> + }
>
> - intel_miptree_init_mcs(brw, mt, 0xFF);
> + mt->aux_state = aux_state;
>
> - /* Multisampled miptrees are only supported for single level. */
> - assert(mt->first_level == 0);
> - intel_miptree_set_fast_clear_state(brw, mt, mt->first_level, 0,
> - mt->logical_depth0,
> - INTEL_FAST_CLEAR_STATE_CLEAR);
> + intel_miptree_init_mcs(brw, mt, 0xFF);
>
> return true;
> }
>
> -
> bool
> intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw,
> struct intel_mipmap_tree *mt,
> @@ -1528,6 +1572,13 @@ intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw,
> if (!buf)
> return false;
>
> + enum isl_aux_state **aux_state =
> + create_aux_state_map(mt, ISL_AUX_STATE_PASS_THROUGH);
> + if (!aux_state) {
> + free(buf);
> + return false;
> + }
> +
> buf->size = temp_ccs_surf.size;
> buf->pitch = temp_ccs_surf.row_pitch;
> buf->qpitch = isl_surf_get_array_pitch_sa_rows(&temp_ccs_surf);
> @@ -1549,10 +1600,12 @@ intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw,
> 1, I915_TILING_Y, &buf->pitch, alloc_flags);
> if (!buf->bo) {
> free(buf);
> + free(aux_state);
> return false;
> }
>
> mt->mcs_buf = buf;
> + mt->aux_state = aux_state;
>
> /* From Gen9 onwards single-sampled (non-msrt) auxiliary buffers are
> * used for lossless compression which requires similar initialisation
> @@ -1975,19 +2028,35 @@ intel_miptree_all_slices_resolve_depth(struct brw_context *brw,
> BLORP_HIZ_OP_DEPTH_RESOLVE);
> }
>
> -enum intel_fast_clear_state
> -intel_miptree_get_fast_clear_state(const struct intel_mipmap_tree *mt,
> - unsigned level, unsigned layer)
> +bool
> +intel_miptree_has_color_unresolved(const struct intel_mipmap_tree *mt,
> + unsigned start_level, unsigned num_levels,
> + unsigned start_layer, unsigned num_layers)
> {
> - intel_miptree_check_level_layer(mt, level, layer);
> + assert(_mesa_is_format_color_format(mt->format));
>
> - const struct intel_resolve_map *item =
> - intel_resolve_map_const_get(&mt->color_resolve_map, level, layer);
> + if (!mt->mcs_buf)
> + return false;
>
> - if (!item)
> - return INTEL_FAST_CLEAR_STATE_RESOLVED;
> + /* Clamp the level range to fit the miptree */
> + assert(start_level + num_levels >= start_level);
This assert looks odd, and did you mean to have it after adjusting?
> + const uint32_t last_level =
> + MIN2(mt->last_level, start_level + num_levels - 1);
> + start_level = MAX2(mt->first_level, start_level);
> + num_levels = last_level - start_level + 1;
> +
> + for (uint32_t level = start_level; level <= last_level; level++) {
> + const uint32_t level_layers = MIN2(num_layers, mt->level[level].depth);
> + for (unsigned a = 0; a < level_layers; a++) {
> + enum isl_aux_state aux_state =
> + intel_miptree_get_aux_state(mt, level, start_layer + a);
> + assert(aux_state != ISL_AUX_STATE_AUX_INVALID);
> + if (aux_state != ISL_AUX_STATE_PASS_THROUGH)
> + return true;
> + }
> + }
>
> - return item->fast_clear_state;
> + return false;
> }
>
> static void
> @@ -2014,135 +2083,188 @@ intel_miptree_check_color_resolve(const struct brw_context *brw,
> (void)layer;
> }
>
> -void
> -intel_miptree_set_fast_clear_state(const struct brw_context *brw,
> - struct intel_mipmap_tree *mt,
> - unsigned level,
> - unsigned first_layer,
> - unsigned num_layers,
> - enum intel_fast_clear_state new_state)
> -{
> - /* Setting the state to resolved means removing the item from the list
> - * altogether.
> - */
> - assert(new_state != INTEL_FAST_CLEAR_STATE_RESOLVED);
> +static enum blorp_fast_clear_op
> +get_ccs_d_resolve_op(enum isl_aux_state aux_state,
> + bool ccs_supported, bool fast_clear_supported)
> +{
> + assert(ccs_supported == fast_clear_supported);
>
> - intel_miptree_check_color_resolve(brw, mt, level, first_layer);
> + switch (aux_state) {
> + case ISL_AUX_STATE_CLEAR:
> + case ISL_AUX_STATE_COMPRESSED_CLEAR:
> + if (!ccs_supported)
> + return BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
> + else
> + return BLORP_FAST_CLEAR_OP_NONE;
>
> - assert(first_layer + num_layers <= mt->physical_depth0);
> + case ISL_AUX_STATE_PASS_THROUGH:
> + return BLORP_FAST_CLEAR_OP_NONE;
>
> - for (unsigned i = 0; i < num_layers; i++)
> - intel_resolve_map_set(&mt->color_resolve_map, level,
> - first_layer + i, new_state);
> -}
> + case ISL_AUX_STATE_RESOLVED:
> + case ISL_AUX_STATE_AUX_INVALID:
> + case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
> + break;
> + }
>
> -bool
> -intel_miptree_has_color_unresolved(const struct intel_mipmap_tree *mt,
> - unsigned start_level, unsigned num_levels,
> - unsigned start_layer, unsigned num_layers)
> -{
> - return intel_resolve_map_find_any(&mt->color_resolve_map,
> - start_level, num_levels,
> - start_layer, num_layers) != NULL;
> + unreachable("Invalid aux state for CCS_D");
> }
>
> -void
> -intel_miptree_used_for_rendering(const struct brw_context *brw,
> - struct intel_mipmap_tree *mt, unsigned level,
> - unsigned start_layer, unsigned num_layers)
> +static enum blorp_fast_clear_op
> +get_ccs_e_resolve_op(enum isl_aux_state aux_state,
> + bool ccs_supported, bool fast_clear_supported)
> {
> - const bool is_lossless_compressed =
> - intel_miptree_is_lossless_compressed(brw, mt);
> + switch (aux_state) {
> + case ISL_AUX_STATE_CLEAR:
> + case ISL_AUX_STATE_COMPRESSED_CLEAR:
> + if (!ccs_supported)
> + return BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
> + else if (!fast_clear_supported)
> + return BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL;
> + else
> + return BLORP_FAST_CLEAR_OP_NONE;
>
> - for (unsigned i = 0; i < num_layers; ++i) {
> - const enum intel_fast_clear_state fast_clear_state =
> - intel_miptree_get_fast_clear_state(mt, level, start_layer + i);
> + case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
> + if (!ccs_supported)
> + return BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
> + else
> + return BLORP_FAST_CLEAR_OP_NONE;
>
> - /* If the buffer was previously in fast clear state, change it to
> - * unresolved state, since it won't be guaranteed to be clear after
> - * rendering occurs.
> - */
> - if (is_lossless_compressed ||
> - fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR) {
> - intel_miptree_set_fast_clear_state(
> - brw, mt, level, start_layer + i, 1,
> - INTEL_FAST_CLEAR_STATE_UNRESOLVED);
> - }
> + case ISL_AUX_STATE_PASS_THROUGH:
> + return BLORP_FAST_CLEAR_OP_NONE;
> +
> + case ISL_AUX_STATE_RESOLVED:
> + case ISL_AUX_STATE_AUX_INVALID:
> + break;
> }
> +
> + unreachable("Invalid aux state for CCS_E");
> }
>
> -static bool
> -intel_miptree_needs_color_resolve(const struct brw_context *brw,
> - const struct intel_mipmap_tree *mt,
> - int flags)
> +static void
> +intel_miptree_prepare_ccs_access(struct brw_context *brw,
> + struct intel_mipmap_tree *mt,
> + uint32_t level, uint32_t layer,
> + bool aux_supported,
> + bool fast_clear_supported)
> {
> - if (mt->aux_disable & INTEL_AUX_DISABLE_CCS)
> - return false;
> + enum isl_aux_state aux_state = intel_miptree_get_aux_state(mt, level, layer);
>
> - const bool is_lossless_compressed =
> - intel_miptree_is_lossless_compressed(brw, mt);
> + enum blorp_fast_clear_op resolve_op;
> + if (intel_miptree_is_lossless_compressed(brw, mt)) {
> + resolve_op = get_ccs_e_resolve_op(aux_state, aux_supported,
> + fast_clear_supported);
> + } else {
> + resolve_op = get_ccs_d_resolve_op(aux_state, aux_supported,
> + fast_clear_supported);
> + }
>
> - /* From gen9 onwards there is new compression scheme for single sampled
> - * surfaces called "lossless compressed". These don't need to be always
> - * resolved.
> - */
> - if ((flags & INTEL_MIPTREE_IGNORE_CCS_E) && is_lossless_compressed)
> - return false;
> + if (resolve_op != BLORP_FAST_CLEAR_OP_NONE) {
> + intel_miptree_check_color_resolve(brw, mt, level, layer);
> + brw_blorp_resolve_color(brw, mt, level, layer, resolve_op);
>
> - /* Fast color clear resolves only make sense for non-MSAA buffers. */
> - if (mt->msaa_layout != INTEL_MSAA_LAYOUT_NONE && !is_lossless_compressed)
> - return false;
> + switch (resolve_op) {
> + case BLORP_FAST_CLEAR_OP_RESOLVE_FULL:
> + /* The CCS full resolve operation destroys the CCS and sets it to the
> + * pass-through state. (You can also think of this as being both a
> + * resolve and an ambiguate in one operation.)
> + */
> + intel_miptree_set_aux_state(brw, mt, level, layer, 1,
> + ISL_AUX_STATE_PASS_THROUGH);
> + break;
>
> - return true;
> + case BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL:
> + intel_miptree_set_aux_state(brw, mt, level, layer, 1,
> + ISL_AUX_STATE_COMPRESSED_NO_CLEAR);
> + break;
> +
> + default:
> + unreachable("Invalid resolve op");
> + }
> + }
> }
>
> -static bool
> -intel_miptree_resolve_color(struct brw_context *brw,
> - struct intel_mipmap_tree *mt,
> - uint32_t start_level, uint32_t num_levels,
> - uint32_t start_layer, uint32_t num_layers,
> - int flags)
> +static void
> +intel_miptree_finish_ccs_write(struct brw_context *brw,
> + struct intel_mipmap_tree *mt,
> + uint32_t level, uint32_t layer,
> + bool written_with_ccs)
> {
> - intel_miptree_check_color_resolve(brw, mt, start_level, start_layer);
> + enum isl_aux_state aux_state = intel_miptree_get_aux_state(mt, level, layer);
>
> - if (!intel_miptree_needs_color_resolve(brw, mt, flags))
> - return false;
> + if (intel_miptree_is_lossless_compressed(brw, mt)) {
> + switch (aux_state) {
> + case ISL_AUX_STATE_CLEAR:
> + assert(written_with_ccs);
> + intel_miptree_set_aux_state(brw, mt, level, layer, 1,
> + ISL_AUX_STATE_COMPRESSED_CLEAR);
> + break;
>
> - enum blorp_fast_clear_op resolve_op;
> - if (brw->gen >= 9) {
> - if (intel_miptree_is_lossless_compressed(brw, mt)) {
> - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
> - } else {
> - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL;
> + case ISL_AUX_STATE_COMPRESSED_CLEAR:
> + case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
> + assert(written_with_ccs);
> + break; /* Nothing to do */
> +
> + case ISL_AUX_STATE_PASS_THROUGH:
> + if (written_with_ccs) {
> + intel_miptree_set_aux_state(brw, mt, level, layer, 1,
> + ISL_AUX_STATE_COMPRESSED_NO_CLEAR);
> + } else {
> + /* Nothing to do */
> + }
> + break;
> +
> + case ISL_AUX_STATE_RESOLVED:
> + case ISL_AUX_STATE_AUX_INVALID:
> + unreachable("Invalid aux state for CCS_E");
> }
> } else {
> - /* Broadwell and earlier do not have a partial resolve */
> - assert(!intel_miptree_is_lossless_compressed(brw, mt));
> - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
> - }
> + /* CCS_D is a bit simpler */
> + switch (aux_state) {
> + case ISL_AUX_STATE_CLEAR:
> + assert(written_with_ccs);
> + intel_miptree_set_aux_state(brw, mt, level, layer, 1,
> + ISL_AUX_STATE_COMPRESSED_CLEAR);
> + break;
>
> - bool resolved = false;
> - foreach_list_typed_safe(struct intel_resolve_map, map, link,
> - &mt->color_resolve_map) {
> - if (map->level < start_level ||
> - map->level >= (start_level + num_levels) ||
> - map->layer < start_layer ||
> - map->layer >= (start_layer + num_layers))
> - continue;
> + case ISL_AUX_STATE_COMPRESSED_CLEAR:
> + assert(written_with_ccs);
> + break; /* Nothing to do */
> +
> + case ISL_AUX_STATE_PASS_THROUGH:
> + /* Nothing to do */
> + break;
>
> - /* Arrayed fast clear is only supported for gen8+. */
> - assert(brw->gen >= 8 || map->level == 0);
> + case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
> + case ISL_AUX_STATE_RESOLVED:
> + case ISL_AUX_STATE_AUX_INVALID:
> + unreachable("Invalid aux state for CCS_D");
> + }
> + }
> +}
>
> - intel_miptree_check_level_layer(mt, map->level, map->layer);
> +static void
> +intel_miptree_finish_mcs_write(struct brw_context *brw,
> + struct intel_mipmap_tree *mt,
> + uint32_t level, uint32_t layer,
> + bool written_with_aux)
> +{
> + switch (intel_miptree_get_aux_state(mt, level, layer)) {
> + case ISL_AUX_STATE_CLEAR:
> + assert(written_with_aux);
> + intel_miptree_set_aux_state(brw, mt, level, layer, 1,
> + ISL_AUX_STATE_COMPRESSED_CLEAR);
> + break;
>
> - assert(map->fast_clear_state != INTEL_FAST_CLEAR_STATE_RESOLVED);
> + case ISL_AUX_STATE_COMPRESSED_CLEAR:
> + assert(written_with_aux);
> + break; /* Nothing to do */
>
> - brw_blorp_resolve_color(brw, mt, map->level, map->layer, resolve_op);
> - intel_resolve_map_remove(map);
> - resolved = true;
> + case ISL_AUX_STATE_COMPRESSED_NO_CLEAR:
> + case ISL_AUX_STATE_RESOLVED:
> + case ISL_AUX_STATE_PASS_THROUGH:
> + case ISL_AUX_STATE_AUX_INVALID:
> + unreachable("Invalid aux state for MCS");
> }
> -
> - return resolved;
> }
>
> void
> @@ -2152,17 +2274,29 @@ intel_miptree_prepare_access(struct brw_context *brw,
> uint32_t start_layer, uint32_t num_layers,
> bool aux_supported, bool fast_clear_supported)
> {
> + /* Clamp the level range to fit the miptree */
> + assert(start_level + num_levels >= start_level);
This also looks odd.
> + const uint32_t last_level =
> + MIN2(mt->last_level, start_level + num_levels - 1);
> + start_level = MAX2(mt->first_level, start_level);
> + num_levels = last_level - start_level + 1;
> +
> if (_mesa_is_format_color_format(mt->format)) {
> if (!mt->mcs_buf)
> return;
>
> if (mt->num_samples > 1) {
> /* Nothing to do for MSAA */
> + assert(aux_supported && fast_clear_supported);
> } else {
> - /* TODO: This is fairly terrible. We can do better. */
> - if (!aux_supported || !fast_clear_supported) {
> - intel_miptree_resolve_color(brw, mt, start_level, num_levels,
> - start_layer, num_layers, 0);
> + for (uint32_t level = start_level; level <= last_level; level++) {
> + const uint32_t level_layers =
> + MIN2(num_layers, mt->level[level].depth);
> + for (uint32_t a = 0; a < level_layers; a++) {
> + intel_miptree_prepare_ccs_access(brw, mt, level,
> + start_layer + a, aux_supported,
> + fast_clear_supported);
> + }
> }
> }
> } else if (mt->format == MESA_FORMAT_S_UINT8) {
> @@ -2197,12 +2331,18 @@ intel_miptree_finish_write(struct brw_context *brw,
> assert(num_layers <= mt->level[level].depth - start_layer);
>
> if (_mesa_is_format_color_format(mt->format)) {
> + if (!mt->mcs_buf)
> + return;
> +
> if (mt->num_samples > 1) {
> - /* Nothing to do for MSAA */
> + for (uint32_t a = 0; a < num_layers; a++) {
> + intel_miptree_finish_mcs_write(brw, mt, level, start_layer + a,
> + written_with_aux);
> + }
> } else {
> - if (written_with_aux) {
> - intel_miptree_used_for_rendering(brw, mt, level,
> - start_layer, num_layers);
> + for (uint32_t a = 0; a < num_layers; a++) {
> + intel_miptree_finish_ccs_write(brw, mt, level, start_layer + a,
> + written_with_aux);
> }
> }
> } else if (mt->format == MESA_FORMAT_S_UINT8) {
> @@ -2231,22 +2371,12 @@ enum isl_aux_state
> intel_miptree_get_aux_state(const struct intel_mipmap_tree *mt,
> uint32_t level, uint32_t layer)
> {
> + intel_miptree_check_level_layer(mt, level, layer);
> +
> if (_mesa_is_format_color_format(mt->format)) {
> assert(mt->mcs_buf != NULL);
> - if (mt->num_samples > 1) {
> - return ISL_AUX_STATE_COMPRESSED_CLEAR;
> - } else {
> - switch (intel_miptree_get_fast_clear_state(mt, level, layer)) {
> - case INTEL_FAST_CLEAR_STATE_RESOLVED:
> - return ISL_AUX_STATE_RESOLVED;
> - case INTEL_FAST_CLEAR_STATE_UNRESOLVED:
> - return ISL_AUX_STATE_COMPRESSED_CLEAR;
> - case INTEL_FAST_CLEAR_STATE_CLEAR:
> - return ISL_AUX_STATE_CLEAR;
> - default:
> - unreachable("Invalid fast clear state");
> - }
> - }
> + assert(mt->num_samples <= 1 || mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS);
> + return mt->aux_state[level][layer];
> } else if (mt->format == MESA_FORMAT_S_UINT8) {
> unreachable("Cannot get aux state for stencil");
> } else {
> @@ -2277,19 +2407,20 @@ intel_miptree_set_aux_state(struct brw_context *brw,
> num_layers = mt->level[level].depth - start_layer;
> assert(num_layers <= mt->level[level].depth - start_layer);
>
> - /* Right now, this only applies to clears. */
> - assert(aux_state == ISL_AUX_STATE_CLEAR);
> -
> if (_mesa_is_format_color_format(mt->format)) {
> - if (mt->num_samples > 1)
> - assert(mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS);
> + assert(mt->mcs_buf != NULL);
> + assert(mt->num_samples <= 1 || mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS);
>
> - assert(level == 0 && start_layer == 0 && num_layers == 1);
> - intel_miptree_set_fast_clear_state(brw, mt, 0, 0, 1,
> - INTEL_FAST_CLEAR_STATE_CLEAR);
> + for (unsigned a = 0; a < num_layers; a++)
> + mt->aux_state[level][start_layer + a] = aux_state;
> } else if (mt->format == MESA_FORMAT_S_UINT8) {
> - assert(!"Cannot set aux state for stencil");
> + unreachable("Cannot get aux state for stencil");
> } else {
> + assert(mt->hiz_buf != NULL);
> +
> + /* Right now, this only applies to clears. */
> + assert(aux_state == ISL_AUX_STATE_CLEAR);
> +
> for (unsigned a = 0; a < num_layers; a++) {
> intel_miptree_check_level_layer(mt, level, start_layer);
> intel_resolve_map_set(&mt->hiz_map, level, start_layer + a,
> @@ -2310,22 +2441,23 @@ intel_miptree_set_aux_state(struct brw_context *brw,
> * set).
> */
> static bool
> -intel_texture_view_requires_resolve(struct brw_context *brw,
> - struct intel_mipmap_tree *mt,
> - mesa_format format)
> +can_texture_with_ccs(struct brw_context *brw,
> + struct intel_mipmap_tree *mt,
> + mesa_format view_format)
> {
> - if (brw->gen < 9 ||
> - !intel_miptree_is_lossless_compressed(brw, mt))
> - return false;
> + if (!intel_miptree_is_lossless_compressed(brw, mt))
> + return false;
>
> - const enum isl_format isl_format = brw_isl_format_for_mesa_format(format);
> + enum isl_format isl_mt_format = brw_isl_format_for_mesa_format(mt->format);
> + enum isl_format isl_view_format = brw_isl_format_for_mesa_format(view_format);
>
> - if (isl_format_supports_ccs_e(&brw->screen->devinfo, isl_format))
> + if (!isl_formats_are_ccs_e_compatible(&brw->screen->devinfo,
> + isl_mt_format, isl_view_format)) {
> + perf_debug("Incompatible sampling format (%s) for rbc (%s)\n",
> + _mesa_get_format_name(view_format),
> + _mesa_get_format_name(mt->format));
> return false;
> -
> - perf_debug("Incompatible sampling format (%s) for rbc (%s)\n",
> - _mesa_get_format_name(format),
> - _mesa_get_format_name(mt->format));
> + }
>
> return true;
> }
> @@ -2338,19 +2470,29 @@ intel_miptree_prepare_texture_slices(struct brw_context *brw,
> uint32_t start_layer, uint32_t num_layers,
> bool *aux_supported_out)
> {
> - bool aux_supported;
> + bool aux_supported, clear_supported;
> if (_mesa_is_format_color_format(mt->format)) {
> - aux_supported = intel_miptree_is_lossless_compressed(brw, mt) &&
> - !intel_texture_view_requires_resolve(brw, mt, view_format);
> + if (mt->num_samples > 1) {
> + aux_supported = clear_supported = true;
> + } else {
> + aux_supported = can_texture_with_ccs(brw, mt, view_format);
> +
> + /* Clear color is specified as ints or floats and the conversion is
> + * done by the sampler. If we have a texture view, we would have to
> + * perform the clear color conversion manually. Just disable clear
> + * color.
> + */
> + clear_supported = aux_supported && (mt->format == view_format);
> + }
> } else if (mt->format == MESA_FORMAT_S_UINT8) {
> - aux_supported = false;
> + aux_supported = clear_supported = false;
> } else {
> - aux_supported = intel_miptree_sample_with_hiz(brw, mt);
> + aux_supported = clear_supported = intel_miptree_sample_with_hiz(brw, mt);
> }
>
> intel_miptree_prepare_access(brw, mt, start_level, num_levels,
> start_layer, num_layers,
> - aux_supported, aux_supported);
> + aux_supported, clear_supported);
> if (aux_supported_out)
> *aux_supported_out = aux_supported;
> }
> @@ -2488,7 +2630,8 @@ intel_miptree_make_shareable(struct brw_context *brw,
> * execute any will likely crash due to the missing aux buffer. So let's
> * delete all pending ops.
> */
> - exec_list_make_empty(&mt->color_resolve_map);
> + free(mt->aux_state);
> + mt->aux_state = NULL;
> }
>
> if (mt->hiz_buf) {
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> index 3f3a78d..528c32c 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> @@ -557,7 +557,14 @@ struct intel_mipmap_tree
> * indicates state other than RESOLVED.
> */
> struct exec_list hiz_map; /* List of intel_resolve_map. */
> - struct exec_list color_resolve_map; /* List of intel_resolve_map. */
> +
> + /**
> + * \brief Maps miptree slices to their current aux state
> + *
> + * This two-dimensional array is indexed as [level][layer] and stores an
> + * aux state for each slice.
> + */
> + enum isl_aux_state **aux_state;
>
> /**
> * \brief Stencil miptree for depthstencil textures.
> @@ -827,41 +834,11 @@ intel_miptree_all_slices_resolve_depth(struct brw_context *brw,
>
> /**\}*/
>
> -enum intel_fast_clear_state
> -intel_miptree_get_fast_clear_state(const struct intel_mipmap_tree *mt,
> - unsigned level, unsigned layer);
> -
> -void
> -intel_miptree_set_fast_clear_state(const struct brw_context *brw,
> - struct intel_mipmap_tree *mt,
> - unsigned level,
> - unsigned first_layer,
> - unsigned num_layers,
> - enum intel_fast_clear_state new_state);
> -
> bool
> intel_miptree_has_color_unresolved(const struct intel_mipmap_tree *mt,
> unsigned start_level, unsigned num_levels,
> unsigned start_layer, unsigned num_layers);
>
> -/**
> - * Update the fast clear state for a miptree to indicate that it has been used
> - * for rendering.
> - */
> -void
> -intel_miptree_used_for_rendering(const struct brw_context *brw,
> - struct intel_mipmap_tree *mt, unsigned level,
> - unsigned start_layer, unsigned num_layers);
> -
> -/**
> - * Flag values telling color resolve pass which special types of buffers
> - * can be ignored.
> - *
> - * INTEL_MIPTREE_IGNORE_CCS_E: Lossless compressed (single-sample
> - * compression scheme since gen9)
> - */
> -#define INTEL_MIPTREE_IGNORE_CCS_E (1 << 0)
> -
>
> #define INTEL_REMAINING_LAYERS UINT32_MAX
> #define INTEL_REMAINING_LEVELS UINT32_MAX
> diff --git a/src/mesa/drivers/dri/i965/intel_resolve_map.h b/src/mesa/drivers/dri/i965/intel_resolve_map.h
> index 17d3983..771d855 100644
> --- a/src/mesa/drivers/dri/i965/intel_resolve_map.h
> +++ b/src/mesa/drivers/dri/i965/intel_resolve_map.h
> @@ -33,63 +33,6 @@ extern "C" {
> #endif
>
> /**
> - * Enum for keeping track of the fast clear state of a buffer associated with
> - * a miptree.
> - *
> - * Fast clear works by deferring the memory writes that would be used to clear
> - * the buffer, so that instead of performing them at the time of the clear
> - * operation, the hardware automatically performs them at the time that the
> - * buffer is later accessed for rendering. The MCS buffer keeps track of
> - * which regions of the buffer still have pending clear writes.
> - *
> - * This enum keeps track of the driver's knowledge of pending fast clears in
> - * the MCS buffer.
> - *
> - * MCS buffers only exist on Gen7+.
> - */
> -enum intel_fast_clear_state
> -{
> - /**
> - * No deferred clears are pending for this miptree, and the contents of the
> - * color buffer are entirely correct. An MCS buffer may or may not exist
> - * for this miptree. If it does exist, it is entirely in the "no deferred
> - * clears pending" state. If it does not exist, it will be created the
> - * first time a fast color clear is executed.
> - *
> - * In this state, the color buffer can be used for purposes other than
> - * rendering without needing a render target resolve.
> - *
> - * Since there is no such thing as a "fast color clear resolve" for MSAA
> - * buffers, an MSAA buffer will never be in this state.
> - */
> - INTEL_FAST_CLEAR_STATE_RESOLVED,
> -
> - /**
> - * An MCS buffer exists for this miptree, and deferred clears are pending
> - * for some regions of the color buffer, as indicated by the MCS buffer.
> - * The contents of the color buffer are only correct for the regions where
> - * the MCS buffer doesn't indicate a deferred clear.
> - *
> - * If a single-sample buffer is in this state, a render target resolve must
> - * be performed before it can be used for purposes other than rendering.
> - */
> - INTEL_FAST_CLEAR_STATE_UNRESOLVED,
> -
> - /**
> - * An MCS buffer exists for this miptree, and deferred clears are pending
> - * for the entire color buffer, and the contents of the MCS buffer reflect
> - * this. The contents of the color buffer are undefined.
> - *
> - * If a single-sample buffer is in this state, a render target resolve must
> - * be performed before it can be used for purposes other than rendering.
> - *
> - * If the client attempts to clear a buffer which is already in this state,
> - * the clear can be safely skipped, since the buffer is already clear.
> - */
> - INTEL_FAST_CLEAR_STATE_CLEAR,
> -};
> -
> -/**
> * \brief Map of miptree slices to needed resolves.
> *
> * The map is implemented as a linear doubly-linked list.
> @@ -121,10 +64,7 @@ struct intel_resolve_map {
> uint32_t level;
> uint32_t layer;
>
> - union {
> - enum blorp_hiz_op need;
> - enum intel_fast_clear_state fast_clear_state;
> - };
> + enum blorp_hiz_op need;
> };
>
> void
> --
> 2.5.0.400.gff86faf
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list