diff options
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 179 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 80 |
2 files changed, 259 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c index 42df708b316..04ac46f789c 100644 --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c @@ -2220,6 +2220,185 @@ intel_miptree_all_slices_resolve_color(struct brw_context *brw, intel_miptree_resolve_color(brw, mt, 0, UINT32_MAX, 0, UINT32_MAX, flags); } +static inline uint32_t +miptree_level_range_length(const struct intel_mipmap_tree *mt, + uint32_t start_level, uint32_t num_levels) +{ + assert(start_level >= mt->first_level); + assert(start_level <= mt->last_level); + + if (num_levels == INTEL_REMAINING_LAYERS) + num_levels = mt->last_level - start_level + 1; + /* Check for overflow */ + assert(start_level + num_levels >= start_level); + assert(start_level + num_levels <= mt->last_level + 1); + + return num_levels; +} + +static inline uint32_t +miptree_layer_range_length(const struct intel_mipmap_tree *mt, uint32_t level, + uint32_t start_layer, uint32_t num_layers) +{ + assert(level <= mt->last_level); + uint32_t total_num_layers = mt->level[level].depth; + + assert(start_layer < total_num_layers); + if (num_layers == INTEL_REMAINING_LAYERS) + num_layers = total_num_layers - start_layer; + /* Check for overflow */ + assert(start_layer + num_layers >= start_layer); + assert(start_layer + num_layers <= total_num_layers); + + return num_layers; +} + +void +intel_miptree_prepare_access(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, + bool aux_supported, bool fast_clear_supported) +{ + num_levels = miptree_level_range_length(mt, start_level, num_levels); + + if (_mesa_is_format_color_format(mt->format)) { + if (!mt->mcs_buf) + return; + + if (mt->num_samples > 1) { + /* Nothing to do for MSAA */ + } 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); + } + } + } else if (mt->format == MESA_FORMAT_S_UINT8) { + /* Nothing to do for stencil */ + } else { + if (!mt->hiz_buf) + return; + + if (aux_supported) { + assert(fast_clear_supported); + intel_miptree_depth_hiz_resolve(brw, mt, start_level, num_levels, + start_layer, num_layers, + BLORP_HIZ_OP_HIZ_RESOLVE); + } else { + assert(!fast_clear_supported); + intel_miptree_depth_hiz_resolve(brw, mt, start_level, num_levels, + start_layer, num_layers, + BLORP_HIZ_OP_DEPTH_RESOLVE); + } + } +} + +void +intel_miptree_finish_write(struct brw_context *brw, + struct intel_mipmap_tree *mt, uint32_t level, + uint32_t start_layer, uint32_t num_layers, + bool written_with_aux) +{ + num_layers = miptree_layer_range_length(mt, level, start_layer, num_layers); + + if (_mesa_is_format_color_format(mt->format)) { + if (mt->num_samples > 1) { + /* Nothing to do for MSAA */ + } else { + if (written_with_aux) { + intel_miptree_used_for_rendering(brw, mt, level, + start_layer, num_layers); + } + } + } else if (mt->format == MESA_FORMAT_S_UINT8) { + /* Nothing to do for stencil */ + } else { + if (written_with_aux) { + for (unsigned a = 0; a < num_layers; a++) { + intel_miptree_check_level_layer(mt, level, start_layer); + intel_miptree_slice_set_needs_depth_resolve(mt, level, + start_layer + a); + } + } else { + for (unsigned a = 0; a < num_layers; a++) { + intel_miptree_check_level_layer(mt, level, start_layer); + intel_miptree_slice_set_needs_hiz_resolve(mt, level, + start_layer + a); + } + } + } +} + +enum isl_aux_state +intel_miptree_get_aux_state(const struct intel_mipmap_tree *mt, + uint32_t level, uint32_t 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"); + } + } + } else if (mt->format == MESA_FORMAT_S_UINT8) { + unreachable("Cannot get aux state for stencil"); + } else { + assert(mt->hiz_buf != NULL); + const struct intel_resolve_map *map = + intel_resolve_map_const_get(&mt->hiz_map, level, layer); + if (!map) + return ISL_AUX_STATE_RESOLVED; + switch (map->need) { + case BLORP_HIZ_OP_DEPTH_RESOLVE: + return ISL_AUX_STATE_COMPRESSED_CLEAR; + case BLORP_HIZ_OP_HIZ_RESOLVE: + return ISL_AUX_STATE_AUX_INVALID; + default: + unreachable("Invalid hiz op"); + } + } +} + +void +intel_miptree_set_aux_state(struct brw_context *brw, + struct intel_mipmap_tree *mt, uint32_t level, + uint32_t start_layer, uint32_t num_layers, + enum isl_aux_state aux_state) +{ + num_layers = miptree_layer_range_length(mt, level, start_layer, num_layers); + + /* 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(level == 0 && start_layer == 0 && num_layers == 1); + intel_miptree_set_fast_clear_state(brw, mt, 0, 0, 1, + INTEL_FAST_CLEAR_STATE_CLEAR); + } else if (mt->format == MESA_FORMAT_S_UINT8) { + assert(!"Cannot set aux state for stencil"); + } else { + for (unsigned a = 0; a < num_layers; a++) { + intel_miptree_check_level_layer(mt, level, start_layer); + intel_miptree_slice_set_needs_depth_resolve(mt, level, + start_layer + a); + } + } +} + /** * Make it possible to share the BO backing the given miptree with another * process or another miptree. diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h index ac928e8f3be..77572292f63 100644 --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h @@ -947,6 +947,86 @@ intel_miptree_all_slices_resolve_color(struct brw_context *brw, struct intel_mipmap_tree *mt, int flags); +#define INTEL_REMAINING_LAYERS UINT32_MAX +#define INTEL_REMAINING_LEVELS UINT32_MAX + +/** Prepare a miptree for access + * + * This function should be called prior to any access to miptree in order to + * perform any needed resolves. + * + * \param[in] start_level The first mip level to be accessed + * + * \param[in] num_levels The number of miplevels to be accessed or + * INTEL_REMAINING_LEVELS to indicate every level + * above start_level will be accessed + * + * \param[in] start_layer The first array slice or 3D layer to be accessed + * + * \param[in] num_layers The number of array slices or 3D layers be + * accessed or INTEL_REMAINING_LAYERS to indicate + * every layer above start_layer will be accessed + * + * \param[in] aux_supported Whether or not the access will support the + * miptree's auxiliary compression format; this + * must be false for uncompressed miptrees + * + * \param[in] fast_clear_supported Whether or not the access will support + * fast clears in the miptree's auxiliary + * compression format + */ +void +intel_miptree_prepare_access(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, + bool aux_supported, bool fast_clear_supported); + +/** Complete a write operation + * + * This function should be called after any operation writes to a miptree. + * This will update the miptree's compression state so that future resolves + * happen correctly. Technically, this function can be called before the + * write occurs but the caller must ensure that they don't interlace + * intel_miptree_prepare_access and intel_miptree_finish_write calls to + * overlapping layer/level ranges. + * + * \param[in] level The mip level that was written + * + * \param[in] start_layer The first array slice or 3D layer written + * + * \param[in] num_layers The number of array slices or 3D layers + * written or INTEL_REMAINING_LAYERS to indicate + * every layer above start_layer was written + * + * \param[in] written_with_aux Whether or not the write was done with + * auxiliary compression enabled + */ +void +intel_miptree_finish_write(struct brw_context *brw, + struct intel_mipmap_tree *mt, uint32_t level, + uint32_t start_layer, uint32_t num_layers, + bool written_with_aux); + +/** Get the auxiliary compression state of a miptree slice */ +enum isl_aux_state +intel_miptree_get_aux_state(const struct intel_mipmap_tree *mt, + uint32_t level, uint32_t layer); + +/** Set the auxiliary compression state of a miptree slice range + * + * This function directly sets the auxiliary compression state of a slice + * range of a miptree. It only modifies data structures and does not do any + * resolves. This should only be called by code which directly performs + * compression operations such as fast clears and resolves. Most code should + * use intel_miptree_prepare_access or intel_miptree_finish_write. + */ +void +intel_miptree_set_aux_state(struct brw_context *brw, + struct intel_mipmap_tree *mt, uint32_t level, + uint32_t start_layer, uint32_t num_layers, + enum isl_aux_state aux_state); + void intel_miptree_make_shareable(struct brw_context *brw, struct intel_mipmap_tree *mt); |