From 597ff919e7d3540627da19a03ebaf2d6a24f4bd3 Mon Sep 17 00:00:00 2001 From: Nanley Chery Date: Fri, 17 Mar 2017 22:36:05 -0700 Subject: [PATCH] anv: Stop resolving CCS implicitly With an earlier patch from this series, resolves are additionally performed on layout transitions. Remove the now unnecessary implicit resolves within render passes. Signed-off-by: Nanley Chery Reviewed-by: Jason Ekstrand --- src/intel/vulkan/anv_blorp.c | 150 ++------------------------------- src/intel/vulkan/anv_pass.c | 14 --- src/intel/vulkan/anv_private.h | 10 --- 3 files changed, 5 insertions(+), 169 deletions(-) diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index 62269937d1c..a789cdcaf38 100644 --- a/src/intel/vulkan/anv_blorp.c +++ b/src/intel/vulkan/anv_blorp.c @@ -1502,150 +1502,16 @@ anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer, ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT; } -static void -ccs_resolve_attachment(struct anv_cmd_buffer *cmd_buffer, - uint32_t att) -{ - struct anv_framebuffer *fb = cmd_buffer->state.framebuffer; - struct anv_attachment_state *att_state = - &cmd_buffer->state.attachments[att]; - - if (att_state->aux_usage == ISL_AUX_USAGE_NONE || - att_state->aux_usage == ISL_AUX_USAGE_MCS) - return; /* Nothing to resolve */ - - assert(att_state->aux_usage == ISL_AUX_USAGE_CCS_E || - att_state->aux_usage == ISL_AUX_USAGE_CCS_D); - - struct anv_render_pass *pass = cmd_buffer->state.pass; - const uint32_t subpass_idx = anv_get_subpass_id(&cmd_buffer->state); - - /* Scan forward to see what all ways this attachment will be used. - * Ideally, we would like to resolve in the same subpass as the last write - * of a particular attachment. That way we only resolve once but it's - * still hot in the cache. - */ - bool found_draw = false; - enum anv_subpass_usage usage = 0; - for (uint32_t s = subpass_idx + 1; s < pass->subpass_count; s++) { - usage |= pass->attachments[att].subpass_usage[s]; - - if (usage & (ANV_SUBPASS_USAGE_DRAW | ANV_SUBPASS_USAGE_RESOLVE_DST)) { - /* We found another subpass that draws to this attachment. We'll - * wait to resolve until then. - */ - found_draw = true; - break; - } - } - - struct anv_image_view *iview = fb->attachments[att]; - const struct anv_image *image = iview->image; - assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT); - - enum blorp_fast_clear_op resolve_op = BLORP_FAST_CLEAR_OP_NONE; - if (!found_draw) { - /* This is the last subpass that writes to this attachment so we need to - * resolve here. Ideally, we would like to only resolve if the storeOp - * is set to VK_ATTACHMENT_STORE_OP_STORE. However, we need to ensure - * that the CCS bits are set to "resolved" because there may be copy or - * blit operations (which may ignore CCS) between now and the next time - * we render and we need to ensure that anything they write will be - * respected in the next render. Unfortunately, the hardware does not - * provide us with any sort of "invalidate" pass that sets the CCS to - * "resolved" without writing to the render target. - */ - if (iview->image->aux_usage != ISL_AUX_USAGE_CCS_E) { - /* The image destination surface doesn't support compression outside - * the render pass. We need a full resolve. - */ - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_FULL; - } else if (att_state->fast_clear) { - /* We don't know what to do with clear colors outside the render - * pass. We need a partial resolve. Only transparent black is - * built into the surface state object and thus no resolve is - * required for this case. - */ - if (att_state->clear_value.color.uint32[0] || - att_state->clear_value.color.uint32[1] || - att_state->clear_value.color.uint32[2] || - att_state->clear_value.color.uint32[3]) - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL; - } else { - /* The image "natively" supports all the compression we care about - * and we don't need to resolve at all. If this is the case, we also - * don't need to resolve for any of the input attachment cases below. - */ - } - } else if (usage & ANV_SUBPASS_USAGE_INPUT) { - /* Input attachments are clear-color aware so, at least on Sky Lake, we - * can frequently sample from them with no resolves at all. - */ - if (att_state->aux_usage != att_state->input_aux_usage) { - assert(att_state->input_aux_usage == ISL_AUX_USAGE_NONE); - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_FULL; - } else if (!att_state->clear_color_is_zero_one) { - /* Sky Lake PRM, Vol. 2d, RENDER_SURFACE_STATE::Red Clear Color: - * - * "If Number of Multisamples is MULTISAMPLECOUNT_1 AND if this RT - * is fast cleared with non-0/1 clear value, this RT must be - * partially resolved (refer to Partial Resolve operation) before - * binding this surface to Sampler." - */ - resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL; - } - } - - if (resolve_op == BLORP_FAST_CLEAR_OP_NONE) - return; - - /* From the Sky Lake PRM Vol. 7, "Render Target Resolve": - * - * "When performing a render target resolve, PIPE_CONTROL with end of - * pipe sync must be delivered." - * - * 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. 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; - - const uint32_t aux_layers = - anv_image_aux_layers(image, iview->isl.base_level); - anv_ccs_resolve(cmd_buffer, att_state->color_rt_state, image, - iview->isl.base_level, MIN2(fb->layers, aux_layers), - resolve_op); - - cmd_buffer->state.pending_pipe_bits |= - ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT; - - /* Once we've done any sort of resolve, we're no longer fast-cleared */ - att_state->fast_clear = false; - if (att_state->aux_usage == ISL_AUX_USAGE_CCS_D) - att_state->aux_usage = ISL_AUX_USAGE_NONE; -} - 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; - - for (uint32_t i = 0; i < subpass->color_count; ++i) { - const uint32_t att = subpass->color_attachments[i].attachment; - if (att == VK_ATTACHMENT_UNUSED) - continue; - - assert(att < cmd_buffer->state.pass->attachment_count); - ccs_resolve_attachment(cmd_buffer, att); - } - if (subpass->has_resolve) { + struct blorp_batch batch; + blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0); + /* We are about to do some MSAA resolves. We need to flush so that the * result of writes to the MSAA color attachments show up in the sampler * when we blit to the single-sampled resolve target. @@ -1687,9 +1553,6 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer) assert(src_iview->aspect_mask == dst_iview->aspect_mask); - struct blorp_batch batch; - blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0); - resolve_image(&batch, src_iview->image, src_aux_usage, src_iview->isl.base_level, src_iview->isl.base_array_layer, @@ -1700,13 +1563,10 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer) render_area.offset.x, render_area.offset.y, render_area.offset.x, render_area.offset.y, render_area.extent.width, render_area.extent.height); - - blorp_batch_finish(&batch); - - ccs_resolve_attachment(cmd_buffer, dst_att); } - } + blorp_batch_finish(&batch); + } } void diff --git a/src/intel/vulkan/anv_pass.c b/src/intel/vulkan/anv_pass.c index ab0733fc103..a77e52b0c00 100644 --- a/src/intel/vulkan/anv_pass.c +++ b/src/intel/vulkan/anv_pass.c @@ -73,10 +73,6 @@ VkResult anv_CreateRenderPass( } anv_multialloc_add(&ma, &subpass_attachments, subpass_attachment_count); - enum anv_subpass_usage *subpass_usages; - anv_multialloc_add(&ma, &subpass_usages, - pCreateInfo->subpassCount * pCreateInfo->attachmentCount); - if (!anv_multialloc_alloc2(&ma, &device->alloc, pAllocator, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); @@ -102,8 +98,6 @@ VkResult anv_CreateRenderPass( att->initial_layout = pCreateInfo->pAttachments[i].initialLayout; att->final_layout = pCreateInfo->pAttachments[i].finalLayout; att->first_subpass_layout = VK_IMAGE_LAYOUT_UNDEFINED; - att->subpass_usage = subpass_usages; - subpass_usages += pass->subpass_count; } bool has_color = false, has_depth = false, has_input = false; @@ -127,7 +121,6 @@ VkResult anv_CreateRenderPass( if (a != VK_ATTACHMENT_UNUSED) { has_input = true; pass->attachments[a].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_INPUT; pass->attachments[a].last_subpass_idx = i; init_first_subpass_layout(&pass->attachments[a], @@ -149,7 +142,6 @@ VkResult anv_CreateRenderPass( if (a != VK_ATTACHMENT_UNUSED) { has_color = true; pass->attachments[a].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW; pass->attachments[a].last_subpass_idx = i; init_first_subpass_layout(&pass->attachments[a], @@ -172,11 +164,6 @@ VkResult anv_CreateRenderPass( pass->attachments[color_att].usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; pass->attachments[a].usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - pass->attachments[color_att].subpass_usage[i] |= - ANV_SUBPASS_USAGE_RESOLVE_SRC; - pass->attachments[a].subpass_usage[i] |= - ANV_SUBPASS_USAGE_RESOLVE_DST; pass->attachments[a].last_subpass_idx = i; init_first_subpass_layout(&pass->attachments[a], @@ -193,7 +180,6 @@ VkResult anv_CreateRenderPass( has_depth = true; pass->attachments[a].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW; pass->attachments[a].last_subpass_idx = i; init_first_subpass_layout(&pass->attachments[a], diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 70eb3d87604..e7b47ead361 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2290,13 +2290,6 @@ anv_subpass_view_count(const struct anv_subpass *subpass) return MAX2(1, _mesa_bitcount(subpass->view_mask)); } -enum anv_subpass_usage { - ANV_SUBPASS_USAGE_DRAW = (1 << 0), - ANV_SUBPASS_USAGE_INPUT = (1 << 1), - ANV_SUBPASS_USAGE_RESOLVE_SRC = (1 << 2), - ANV_SUBPASS_USAGE_RESOLVE_DST = (1 << 3), -}; - struct anv_render_pass_attachment { /* TODO: Consider using VkAttachmentDescription instead of storing each of * its members individually. @@ -2311,9 +2304,6 @@ struct anv_render_pass_attachment { VkImageLayout final_layout; VkImageLayout first_subpass_layout; - /* An array, indexed by subpass id, of how the attachment will be used. */ - enum anv_subpass_usage * subpass_usage; - /* The subpass id in which the attachment will be used last. */ uint32_t last_subpass_idx; }; -- 2.30.2