From f8a4abcd15d9e27afd6be12c67bec7ccaf179e54 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 27 Jan 2016 20:42:54 -0800 Subject: [PATCH] anv: Do resolves at end of subpass --- src/vulkan/anv_meta_resolve.c | 61 +++++++++++++++++++++++++++++++++++ src/vulkan/anv_private.h | 1 + src/vulkan/gen7_cmd_buffer.c | 3 ++ src/vulkan/gen8_cmd_buffer.c | 3 ++ 4 files changed, 68 insertions(+) diff --git a/src/vulkan/anv_meta_resolve.c b/src/vulkan/anv_meta_resolve.c index 9969a0e5d88..ffd41857f13 100644 --- a/src/vulkan/anv_meta_resolve.c +++ b/src/vulkan/anv_meta_resolve.c @@ -802,3 +802,64 @@ void anv_CmdResolveImage( meta_resolve_restore(&state, cmd_buffer); } + +/** + * Emit any needed resolves for the current subpass. + */ +void +anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer) +{ + struct anv_framebuffer *fb = cmd_buffer->state.framebuffer; + struct anv_subpass *subpass = cmd_buffer->state.subpass; + struct anv_meta_saved_state saved_state; + + /* FINISHME(perf): Skip clears for resolve attachments. + * + * From the Vulkan 1.0 spec: + * + * If the first use of an attachment in a render pass is as a resolve + * attachment, then the loadOp is effectively ignored as the resolve is + * guaranteed to overwrite all pixels in the render area. + */ + + if (!subpass->has_resolve) + return; + + meta_resolve_save(&saved_state, cmd_buffer); + + for (uint32_t i = 0; i < subpass->color_count; ++i) { + uint32_t src_att = subpass->color_attachments[i]; + uint32_t dest_att = subpass->resolve_attachments[i]; + + if (dest_att == VK_ATTACHMENT_UNUSED) + continue; + + struct anv_image_view *src_iview = fb->attachments[src_att]; + struct anv_image_view *dest_iview = fb->attachments[dest_att]; + + struct anv_subpass resolve_subpass = { + .color_count = 1, + .color_attachments = (uint32_t[]) { dest_att }, + .depth_stencil_attachment = VK_ATTACHMENT_UNUSED, + }; + + anv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass); + + /* Subpass resolves must respect the render area. We can ignore the + * render area here because vkCmdBeginRenderPass set the render area + * with 3DSTATE_DRAWING_RECTANGLE. + * + * XXX(chadv): Does the hardware really respect + * 3DSTATE_DRAWING_RECTANGLE when draing a 3DPRIM_RECTLIST? + */ + emit_resolve(cmd_buffer, + src_iview, + &(VkOffset2D) { 0, 0 }, + dest_iview, + &(VkOffset2D) { 0, 0 }, + &(VkExtent2D) { fb->width, fb->height }); + } + + cmd_buffer->state.subpass = subpass; + meta_resolve_restore(&saved_state, cmd_buffer); +} diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index 6a670190ab9..b1d4577f93e 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -1277,6 +1277,7 @@ struct anv_state anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer); void anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer); +void anv_cmd_buffer_resolve_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 f201c151acb..609606bdf6a 100644 --- a/src/vulkan/gen7_cmd_buffer.c +++ b/src/vulkan/gen7_cmd_buffer.c @@ -896,6 +896,7 @@ void genX(CmdNextSubpass)( assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY); + anv_cmd_buffer_resolve_subpass(cmd_buffer); gen7_cmd_buffer_set_subpass(cmd_buffer, cmd_buffer->state.subpass + 1); anv_cmd_buffer_clear_subpass(cmd_buffer); } @@ -905,6 +906,8 @@ void genX(CmdEndRenderPass)( { ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + anv_cmd_buffer_resolve_subpass(cmd_buffer); + /* Emit a flushing pipe control at the end of a pass. This is kind of a * hack but it ensures that render targets always actually get written. * Eventually, we should do flushing based on image format transitions diff --git a/src/vulkan/gen8_cmd_buffer.c b/src/vulkan/gen8_cmd_buffer.c index daa049e98e0..4b1c51a8c59 100644 --- a/src/vulkan/gen8_cmd_buffer.c +++ b/src/vulkan/gen8_cmd_buffer.c @@ -972,6 +972,7 @@ void genX(CmdNextSubpass)( assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY); + anv_cmd_buffer_resolve_subpass(cmd_buffer); genX(cmd_buffer_set_subpass)(cmd_buffer, cmd_buffer->state.subpass + 1); anv_cmd_buffer_clear_subpass(cmd_buffer); } @@ -981,6 +982,8 @@ void genX(CmdEndRenderPass)( { ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + anv_cmd_buffer_resolve_subpass(cmd_buffer); + /* Emit a flushing pipe control at the end of a pass. This is kind of a * hack but it ensures that render targets always actually get written. * Eventually, we should do flushing based on image format transitions -- 2.30.2