anv/cmd_buffer: Move the color portion of clear_subpass into begin_subpass

This doesn't really change much now but it will give us more/better
control over clears in the future.  The one interesting functional
change here is that we are now re-emitting 3DSTATE_DEPTH_BUFFERS and
friends for each clear.  However, this only happens at begin_subpass
time so it shouldn't be substantially more expensive.

Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
This commit is contained in:
Jason Ekstrand 2017-11-21 13:30:49 -08:00
parent 6fb9d6c6f5
commit 1900dd76d0
3 changed files with 94 additions and 92 deletions

View file

@ -1145,17 +1145,6 @@ subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
if (a == VK_ATTACHMENT_UNUSED)
continue;
assert(a < cmd_state->pass->attachment_count);
if (cmd_state->attachments[a].pending_clear_aspects) {
return true;
}
}
if (ds != VK_ATTACHMENT_UNUSED) {
assert(ds < cmd_state->pass->attachment_count);
if (cmd_state->attachments[ds].pending_clear_aspects)
@ -1189,86 +1178,6 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
};
struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
const uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
if (a == VK_ATTACHMENT_UNUSED)
continue;
assert(a < cmd_state->pass->attachment_count);
struct anv_attachment_state *att_state = &cmd_state->attachments[a];
if (!att_state->pending_clear_aspects)
continue;
assert(att_state->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
struct anv_image_view *iview = fb->attachments[a];
const struct anv_image *image = iview->image;
struct blorp_surf surf;
get_blorp_surf_for_anv_image(cmd_buffer->device,
image, VK_IMAGE_ASPECT_COLOR_BIT,
att_state->aux_usage, &surf);
uint32_t base_layer = iview->planes[0].isl.base_array_layer;
uint32_t layer_count = fb->layers;
if (att_state->fast_clear) {
surf.clear_color = vk_to_isl_color(att_state->clear_value.color);
/* 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;
/* We only support fast-clears on the first layer */
assert(iview->planes[0].isl.base_level == 0);
assert(iview->planes[0].isl.base_array_layer == 0);
assert(image->n_planes == 1);
blorp_fast_clear(&batch, &surf, iview->planes[0].isl.format, 0, 0, 1,
render_area.offset.x, render_area.offset.y,
render_area.offset.x + render_area.extent.width,
render_area.offset.y + render_area.extent.height);
base_layer++;
layer_count--;
cmd_buffer->state.pending_pipe_bits |=
ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
}
if (layer_count > 0) {
assert(image->n_planes == 1);
anv_cmd_buffer_mark_image_written(cmd_buffer, image,
VK_IMAGE_ASPECT_COLOR_BIT,
att_state->aux_usage,
iview->planes[0].isl.base_level,
base_layer, layer_count);
blorp_clear(&batch, &surf, iview->planes[0].isl.format,
anv_swizzle_for_render(iview->planes[0].isl.swizzle),
iview->planes[0].isl.base_level, base_layer, layer_count,
render_area.offset.x, render_area.offset.y,
render_area.offset.x + render_area.extent.width,
render_area.offset.y + render_area.extent.height,
vk_to_isl_color(att_state->clear_value.color), NULL);
}
att_state->pending_clear_aspects = 0;
}
const uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
assert(ds == VK_ATTACHMENT_UNUSED || ds < cmd_state->pass->attachment_count);
@ -1621,6 +1530,39 @@ anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
blorp_batch_finish(&batch);
}
void
anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
enum isl_aux_usage aux_usage,
enum isl_format format, struct isl_swizzle swizzle,
uint32_t level, uint32_t base_layer, uint32_t layer_count,
VkRect2D area, union isl_color_value clear_color)
{
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
/* We don't support planar images with multisampling yet */
assert(image->n_planes == 1);
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,
aux_usage, &surf);
anv_cmd_buffer_mark_image_written(cmd_buffer, image, aspect, aux_usage,
level, base_layer, layer_count);
blorp_clear(&batch, &surf, format, anv_swizzle_for_render(swizzle),
level, base_layer, layer_count,
area.offset.x, area.offset.y,
area.offset.x + area.extent.width,
area.offset.y + area.extent.height,
clear_color, NULL);
blorp_batch_finish(&batch);
}
void
anv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,

View file

@ -2620,6 +2620,14 @@ anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer *cmd_buffer,
uint32_t layer_count);
void
anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect,
enum isl_aux_usage aux_usage,
enum isl_format format, struct isl_swizzle swizzle,
uint32_t level, uint32_t base_layer, uint32_t layer_count,
VkRect2D area, union isl_color_value clear_color);
void
anv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect, uint32_t level,

View file

@ -3452,7 +3452,9 @@ static void
cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
uint32_t subpass_id)
{
cmd_buffer->state.subpass = &cmd_buffer->state.pass->subpasses[subpass_id];
struct anv_cmd_state *cmd_state = &cmd_buffer->state;
struct anv_subpass *subpass = &cmd_state->pass->subpasses[subpass_id];
cmd_state->subpass = subpass;
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_RENDER_TARGETS;
@ -3495,6 +3497,56 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
*/
cmd_buffer_subpass_sync_fast_clear_values(cmd_buffer);
VkRect2D render_area = cmd_buffer->state.render_area;
struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
for (uint32_t i = 0; i < subpass->color_count; ++i) {
const uint32_t a = subpass->color_attachments[i].attachment;
if (a == VK_ATTACHMENT_UNUSED)
continue;
assert(a < cmd_state->pass->attachment_count);
struct anv_attachment_state *att_state = &cmd_state->attachments[a];
if (!att_state->pending_clear_aspects)
continue;
assert(att_state->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
struct anv_image_view *iview = fb->attachments[a];
const struct anv_image *image = iview->image;
/* Multi-planar images are not supported as attachments */
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
assert(image->n_planes == 1);
uint32_t base_clear_layer = iview->planes[0].isl.base_array_layer;
uint32_t clear_layer_count = fb->layers;
if (att_state->fast_clear) {
/* We only support fast-clears on the first layer */
assert(iview->planes[0].isl.base_level == 0);
assert(iview->planes[0].isl.base_array_layer == 0);
anv_image_ccs_op(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
0, 0, 1, ISL_AUX_OP_FAST_CLEAR, false);
base_clear_layer++;
clear_layer_count--;
}
if (clear_layer_count > 0) {
assert(image->n_planes == 1);
anv_image_clear_color(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
att_state->aux_usage,
iview->planes[0].isl.format,
iview->planes[0].isl.swizzle,
iview->planes[0].isl.base_level,
base_clear_layer, clear_layer_count, render_area,
vk_to_isl_color(att_state->clear_value.color));
}
att_state->pending_clear_aspects = 0;
}
cmd_buffer_emit_depth_stencil(cmd_buffer);
anv_cmd_buffer_clear_subpass(cmd_buffer);