anv/blorp: Rework image clear/resolve helpers

This replaces image_fast_clear and ccs_resolve with two new helpers that
simply perform an isl_aux_op whatever that may be on CCS or MCS.  This
is a bit cleaner as it separates performing the aux operation from which
blorp helper we have to call to do it.

Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
This commit is contained in:
Jason Ekstrand 2017-11-21 09:56:41 -08:00
parent 482c24783e
commit 42f1668a54
3 changed files with 169 additions and 107 deletions

View File

@ -1440,75 +1440,6 @@ fast_clear_aux_usage(const struct anv_image *image,
return image->planes[plane].aux_usage;
}
void
anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
const uint32_t base_level, const uint32_t level_count,
const uint32_t base_layer, uint32_t layer_count)
{
assert(image->type == VK_IMAGE_TYPE_3D || image->extent.depth == 1);
if (image->type == VK_IMAGE_TYPE_3D) {
assert(base_layer == 0);
assert(layer_count == anv_minify(image->extent.depth, base_level));
}
struct blorp_batch batch;
blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
struct blorp_surf surf;
get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
fast_clear_aux_usage(image, aspect),
&surf);
/* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
*
* "After Render target fast clear, pipe-control with color cache
* write-flush must be issued before sending any DRAW commands on
* that render target."
*
* This comment is a bit cryptic and doesn't really tell you what's going
* or what's really needed. It appears that fast clear ops are not
* properly synchronized with other drawing. This means that we cannot
* have a fast clear operation in the pipe at the same time as other
* regular drawing operations. We need to use a PIPE_CONTROL to ensure
* that the contents of the previous draw hit the render target before we
* resolve and then use a second PIPE_CONTROL after the resolve to ensure
* that it is completed before any additional drawing occurs.
*/
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
uint32_t width_div = image->format->planes[plane].denominator_scales[0];
uint32_t height_div = image->format->planes[plane].denominator_scales[1];
for (uint32_t l = 0; l < level_count; l++) {
const uint32_t level = base_level + l;
const VkExtent3D extent = {
.width = anv_minify(image->extent.width, level),
.height = anv_minify(image->extent.height, level),
.depth = anv_minify(image->extent.depth, level),
};
if (image->type == VK_IMAGE_TYPE_3D)
layer_count = extent.depth;
assert(level < anv_image_aux_levels(image, aspect));
assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, level));
blorp_fast_clear(&batch, &surf, surf.surf->format,
level, base_layer, layer_count,
0, 0,
extent.width / width_div,
extent.height / height_div);
}
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
}
void
anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
{
@ -1683,36 +1614,154 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer,
}
void
anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
const struct anv_image * const image,
VkImageAspectFlagBits aspect,
const uint8_t level,
const uint32_t start_layer, const uint32_t layer_count,
const enum blorp_fast_clear_op op)
anv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
uint32_t base_layer, uint32_t layer_count,
enum isl_aux_op mcs_op, bool predicate)
{
assert(cmd_buffer && image);
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
assert(image->samples > 1);
assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, 0));
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
/* The resolved subresource range must have a CCS buffer. */
assert(level < anv_image_aux_levels(image, aspect));
assert(start_layer + layer_count <=
anv_image_aux_layers(image, aspect, level));
assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV && image->samples == 1);
/* Multisampling with multi-planar formats is not supported */
assert(image->n_planes == 1);
struct blorp_batch batch;
blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
BLORP_BATCH_PREDICATE_ENABLE);
predicate ? BLORP_BATCH_PREDICATE_ENABLE : 0);
struct blorp_surf surf;
get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
ANV_AUX_USAGE_DEFAULT, &surf);
/* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
*
* "After Render target fast clear, pipe-control with color cache
* write-flush must be issued before sending any DRAW commands on
* that render target."
*
* This comment is a bit cryptic and doesn't really tell you what's going
* or what's really needed. It appears that fast clear ops are not
* properly synchronized with other drawing. This means that we cannot
* have a fast clear operation in the pipe at the same time as other
* regular drawing operations. We need to use a PIPE_CONTROL to ensure
* that the contents of the previous draw hit the render target before we
* resolve and then use a second PIPE_CONTROL after the resolve to ensure
* that it is completed before any additional drawing occurs.
*/
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
switch (mcs_op) {
case ISL_AUX_OP_FAST_CLEAR:
blorp_fast_clear(&batch, &surf, surf.surf->format,
0, base_layer, layer_count,
0, 0, image->extent.width, image->extent.height);
break;
case ISL_AUX_OP_FULL_RESOLVE:
case ISL_AUX_OP_PARTIAL_RESOLVE:
case ISL_AUX_OP_AMBIGUATE:
default:
unreachable("Unsupported MCS operation");
}
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
blorp_batch_finish(&batch);
}
static enum blorp_fast_clear_op
isl_to_blorp_fast_clear_op(enum isl_aux_op isl_op)
{
switch (isl_op) {
case ISL_AUX_OP_FAST_CLEAR: return BLORP_FAST_CLEAR_OP_CLEAR;
case ISL_AUX_OP_FULL_RESOLVE: return BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
case ISL_AUX_OP_PARTIAL_RESOLVE: return BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL;
default:
unreachable("Unsupported CCS/MCS aux op");
}
}
void
anv_image_ccs_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect, uint32_t level,
uint32_t base_layer, uint32_t layer_count,
enum isl_aux_op ccs_op, bool predicate)
{
assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
assert(image->samples == 1);
assert(level < anv_image_aux_levels(image, aspect));
/* Multi-LOD YcBcR is not allowed */
assert(image->n_planes == 1 || level == 0);
assert(base_layer + layer_count <=
anv_image_aux_layers(image, aspect, level));
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
uint32_t width_div = image->format->planes[plane].denominator_scales[0];
uint32_t height_div = image->format->planes[plane].denominator_scales[1];
uint32_t level_width = anv_minify(image->extent.width, level) / width_div;
uint32_t level_height = anv_minify(image->extent.height, level) / height_div;
struct blorp_batch batch;
blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
predicate ? BLORP_BATCH_PREDICATE_ENABLE : 0);
struct blorp_surf surf;
get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
fast_clear_aux_usage(image, aspect),
&surf);
surf.clear_color_addr = anv_to_blorp_address(
anv_image_get_clear_color_addr(cmd_buffer->device, image, aspect, level));
blorp_ccs_resolve(&batch, &surf, level, start_layer, layer_count,
image->planes[plane].surface.isl.format, op);
if (ccs_op == ISL_AUX_OP_FULL_RESOLVE ||
ccs_op == ISL_AUX_OP_PARTIAL_RESOLVE) {
/* If we're doing a resolve operation, then we need the indirect clear
* color. The clear and ambiguate operations just stomp the CCS to a
* particular value and don't care about format or clear value.
*/
const struct anv_address clear_color_addr =
anv_image_get_clear_color_addr(cmd_buffer->device, image,
aspect, level);
surf.clear_color_addr = anv_to_blorp_address(clear_color_addr);
}
/* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
*
* "After Render target fast clear, pipe-control with color cache
* write-flush must be issued before sending any DRAW commands on
* that render target."
*
* This comment is a bit cryptic and doesn't really tell you what's going
* or what's really needed. It appears that fast clear ops are not
* properly synchronized with other drawing. This means that we cannot
* have a fast clear operation in the pipe at the same time as other
* regular drawing operations. We need to use a PIPE_CONTROL to ensure
* that the contents of the previous draw hit the render target before we
* resolve and then use a second PIPE_CONTROL after the resolve to ensure
* that it is completed before any additional drawing occurs.
*/
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
switch (ccs_op) {
case ISL_AUX_OP_FAST_CLEAR:
blorp_fast_clear(&batch, &surf, surf.surf->format,
level, base_layer, layer_count,
0, 0, level_width, level_height);
break;
case ISL_AUX_OP_FULL_RESOLVE:
case ISL_AUX_OP_PARTIAL_RESOLVE:
blorp_ccs_resolve(&batch, &surf, level, base_layer, layer_count,
surf.surf->format, isl_to_blorp_fast_clear_op(ccs_op));
break;
case ISL_AUX_OP_AMBIGUATE:
default:
unreachable("Unsupported CCS operation");
}
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
blorp_batch_finish(&batch);
}

View File

@ -2585,20 +2585,19 @@ void
anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
enum blorp_hiz_op op);
void
anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
const struct anv_image * const image,
VkImageAspectFlagBits aspect,
const uint8_t level,
const uint32_t start_layer, const uint32_t layer_count,
const enum blorp_fast_clear_op op);
void
anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
const uint32_t base_level, const uint32_t level_count,
const uint32_t base_layer, uint32_t layer_count);
anv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
uint32_t base_layer, uint32_t layer_count,
enum isl_aux_op mcs_op, bool predicate);
void
anv_image_ccs_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect, uint32_t level,
uint32_t base_layer, uint32_t layer_count,
enum isl_aux_op ccs_op, bool predicate);
void
anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,

View File

@ -689,9 +689,22 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
"define an MCS buffer.");
}
anv_image_fast_clear(cmd_buffer, image, aspect,
base_level, level_count,
base_layer, layer_count);
if (image->samples == 1) {
for (uint32_t l = 0; l < level_count; l++) {
const uint32_t level = base_level + l;
const uint32_t level_layer_count =
MIN2(layer_count, anv_image_aux_layers(image, aspect, level));
anv_image_ccs_op(cmd_buffer, image, aspect, level,
base_layer, level_layer_count,
ISL_AUX_OP_FAST_CLEAR, false);
}
} else {
assert(image->samples > 1);
assert(base_level == 0 && level_count == 1);
anv_image_mcs_op(cmd_buffer, image, aspect,
base_layer, layer_count,
ISL_AUX_OP_FAST_CLEAR, false);
}
}
/* At this point, some elements of the CCS buffer may have the fast-clear
* bit-arrangement. As the user writes to a subresource, we need to have
@ -760,10 +773,11 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
genX(load_needs_resolve_predicate)(cmd_buffer, image, aspect, level);
anv_ccs_resolve(cmd_buffer, image, aspect, level, base_layer, layer_count,
image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E ?
BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL :
BLORP_FAST_CLEAR_OP_RESOLVE_FULL);
anv_image_ccs_op(cmd_buffer, image, aspect, level,
base_layer, layer_count,
image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E ?
ISL_AUX_OP_PARTIAL_RESOLVE : ISL_AUX_OP_FULL_RESOLVE,
true);
genX(set_image_needs_resolve)(cmd_buffer, image, aspect, level, false);
}