anv: Emit load clears at start of each subpass

This should improve cache residency for render targets.

Pre-patch, vkCmdBeginRenderPass emitted all the meta clears for
VK_ATTACHMENT_LOAD_OP_CLEAR before any subpass began. Post-patch,
vCmdBeginRenderPass and vkCmdNextSubpass emit only the clears needed for
that current subpass.
This commit is contained in:
Chad Versace 2016-01-13 14:47:51 -08:00
parent 0679bef49f
commit deb8dd89b5
4 changed files with 78 additions and 43 deletions

View file

@ -335,15 +335,21 @@ fail:
static void
emit_color_clear(struct anv_cmd_buffer *cmd_buffer,
uint32_t attachment,
VkClearColorValue clear_value)
const VkClearAttachment *clear_att)
{
struct anv_device *device = cmd_buffer->device;
VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
const struct anv_subpass *subpass = cmd_buffer->state.subpass;
const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
struct anv_pipeline *pipeline = device->meta_state.clear.color_pipelines[0];
VkClearColorValue clear_value = clear_att->clearValue.color;
struct anv_pipeline *pipeline =
device->meta_state.clear.color_pipelines[clear_att->colorAttachment];
VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
VkPipeline pipeline_h = anv_pipeline_to_handle(pipeline);
assert(clear_att->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
assert(clear_att->colorAttachment < subpass->color_count);
const struct color_clear_vattrs vertex_data[3] = {
{
.vue_header = { 0 },
@ -372,13 +378,6 @@ emit_color_clear(struct anv_cmd_buffer *cmd_buffer,
.offset = state.offset,
};
anv_cmd_buffer_begin_subpass(cmd_buffer,
&(struct anv_subpass) {
.color_count = 1,
.color_attachments = (uint32_t[]) { attachment },
.depth_stencil_attachment = VK_ATTACHMENT_UNUSED,
});
ANV_CALL(CmdSetViewport)(cmd_buffer_h, 0, 1,
(VkViewport[]) {
{
@ -511,13 +510,22 @@ create_depthstencil_pipeline(struct anv_device *device,
static void
emit_depthstencil_clear(struct anv_cmd_buffer *cmd_buffer,
uint32_t attachment,
VkImageAspectFlags aspects,
VkClearDepthStencilValue clear_value)
const VkClearAttachment *clear_att)
{
struct anv_device *device = cmd_buffer->device;
VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
const struct anv_subpass *subpass = cmd_buffer->state.subpass;
const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
uint32_t attachment = subpass->depth_stencil_attachment;
VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
VkImageAspectFlags aspects = clear_att->aspectMask;
VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
assert(aspects == VK_IMAGE_ASPECT_DEPTH_BIT ||
aspects == VK_IMAGE_ASPECT_STENCIL_BIT ||
aspects == (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT));
assert(attachment != VK_ATTACHMENT_UNUSED);
const struct depthstencil_clear_vattrs vertex_data[3] = {
{
@ -544,12 +552,6 @@ emit_depthstencil_clear(struct anv_cmd_buffer *cmd_buffer,
.offset = state.offset,
};
anv_cmd_buffer_begin_subpass(cmd_buffer,
&(struct anv_subpass) {
.color_count = 0,
.depth_stencil_attachment = attachment,
});
ANV_CALL(CmdSetViewport)(cmd_buffer_h, 0, 1,
(VkViewport[]) {
{
@ -684,45 +686,54 @@ anv_device_finish_meta_clear_state(struct anv_device *device)
}
/**
* At least one aspect must be specified.
* The parameters mean that same as those in vkCmdClearAttachments.
*/
static void
emit_clear(struct anv_cmd_buffer *cmd_buffer,
uint32_t attachment,
VkImageAspectFlags aspects,
const VkClearValue *value)
const VkClearAttachment *clear_att)
{
if (aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
emit_color_clear(cmd_buffer, attachment, value->color);
if (clear_att->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
emit_color_clear(cmd_buffer, clear_att);
} else {
assert(aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT));
emit_depthstencil_clear(cmd_buffer, attachment, aspects,
value->depthStencil);
assert(clear_att->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT));
emit_depthstencil_clear(cmd_buffer, clear_att);
}
}
static bool
pass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
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;
for (uint32_t i = 0; i < cmd_state->pass->attachment_count; ++i) {
if (cmd_state->attachments[i].pending_clear_aspects) {
for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
uint32_t a = cmd_state->subpass->color_attachments[i];
if (cmd_state->attachments[a].pending_clear_aspects) {
return true;
}
}
if (ds != VK_ATTACHMENT_UNUSED &&
cmd_state->attachments[ds].pending_clear_aspects) {
return true;
}
return false;
}
/**
* Emit any pending attachment clears for the current subpass.
*
* @see anv_attachment_state::pending_clear_aspects
*/
void
anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer)
anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_cmd_state *cmd_state = &cmd_buffer->state;
struct anv_meta_saved_state saved_state;
if (!pass_needs_clear(cmd_buffer))
if (!subpass_needs_clear(cmd_buffer))
return;
meta_clear_begin(&saved_state, cmd_buffer);
@ -730,17 +741,39 @@ anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer)
if (cmd_state->framebuffer->layers > 1)
anv_finishme("clearing multi-layer framebuffer");
for (uint32_t a = 0; a < cmd_state->pass->attachment_count; ++a) {
for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
uint32_t a = cmd_state->subpass->color_attachments[i];
if (!cmd_state->attachments[a].pending_clear_aspects)
continue;
emit_clear(cmd_buffer, a,
cmd_state->attachments[a].pending_clear_aspects,
&cmd_state->attachments[a].clear_value);
assert(cmd_state->attachments[a].pending_clear_aspects ==
VK_IMAGE_ASPECT_COLOR_BIT);
VkClearAttachment clear_att = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.colorAttachment = i, /* Use attachment index relative to subpass */
.clearValue = cmd_state->attachments[a].clear_value,
};
emit_clear(cmd_buffer, &clear_att);
cmd_state->attachments[a].pending_clear_aspects = 0;
}
uint32_t ds = cmd_state->subpass->depth_stencil_attachment;
if (ds != VK_ATTACHMENT_UNUSED &&
cmd_state->attachments[ds].pending_clear_aspects) {
VkClearAttachment clear_att = {
.aspectMask = cmd_state->attachments[ds].pending_clear_aspects,
.clearValue = cmd_state->attachments[ds].clear_value,
};
emit_clear(cmd_buffer, &clear_att);
cmd_state->attachments[ds].pending_clear_aspects = 0;
}
meta_clear_end(&saved_state, cmd_buffer);
}

View file

@ -1260,7 +1260,7 @@ anv_cmd_buffer_push_constants(struct anv_cmd_buffer *cmd_buffer,
struct anv_state
anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer);
void anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer);
void anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer);
const struct anv_image_view *
anv_cmd_buffer_get_depth_stencil_view(const struct anv_cmd_buffer *cmd_buffer);

View file

@ -830,8 +830,8 @@ void genX(CmdBeginRenderPass)(
.DrawingRectangleOriginY = 0,
.DrawingRectangleOriginX = 0);
anv_cmd_buffer_clear_attachments(cmd_buffer);
gen7_cmd_buffer_begin_subpass(cmd_buffer, pass->subpasses);
anv_cmd_buffer_clear_subpass(cmd_buffer);
}
void genX(CmdNextSubpass)(
@ -843,6 +843,7 @@ void genX(CmdNextSubpass)(
assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
gen7_cmd_buffer_begin_subpass(cmd_buffer, cmd_buffer->state.subpass + 1);
anv_cmd_buffer_clear_subpass(cmd_buffer);
}
void genX(CmdEndRenderPass)(

View file

@ -829,8 +829,8 @@ void genX(CmdBeginRenderPass)(
.DrawingRectangleOriginY = 0,
.DrawingRectangleOriginX = 0);
anv_cmd_buffer_clear_attachments(cmd_buffer);
genX(cmd_buffer_begin_subpass)(cmd_buffer, pass->subpasses);
anv_cmd_buffer_clear_subpass(cmd_buffer);
}
void genX(CmdNextSubpass)(
@ -842,6 +842,7 @@ void genX(CmdNextSubpass)(
assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
genX(cmd_buffer_begin_subpass)(cmd_buffer, cmd_buffer->state.subpass + 1);
anv_cmd_buffer_clear_subpass(cmd_buffer);
}
void genX(CmdEndRenderPass)(