From deb8dd89b5b211436eea2b8142a6b0acceeec6fd Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 13 Jan 2016 14:47:51 -0800 Subject: [PATCH] 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. --- src/vulkan/anv_meta_clear.c | 113 ++++++++++++++++++++++------------- src/vulkan/anv_private.h | 2 +- src/vulkan/gen7_cmd_buffer.c | 3 +- src/vulkan/gen8_cmd_buffer.c | 3 +- 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/vulkan/anv_meta_clear.c b/src/vulkan/anv_meta_clear.c index 969fbe62874..39b7b968662 100644 --- a/src/vulkan/anv_meta_clear.c +++ b/src/vulkan/anv_meta_clear.c @@ -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); } diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index 9e6c3bf57fc..a76e78aa8e4 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -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); diff --git a/src/vulkan/gen7_cmd_buffer.c b/src/vulkan/gen7_cmd_buffer.c index 7257d6595dd..bea0abea1cc 100644 --- a/src/vulkan/gen7_cmd_buffer.c +++ b/src/vulkan/gen7_cmd_buffer.c @@ -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)( diff --git a/src/vulkan/gen8_cmd_buffer.c b/src/vulkan/gen8_cmd_buffer.c index 277cee08974..10bc8f7bf54 100644 --- a/src/vulkan/gen8_cmd_buffer.c +++ b/src/vulkan/gen8_cmd_buffer.c @@ -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)( -- 2.30.2