From 8647a24a8d66a0a3663563d4d713a5a5b28d8d64 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Thu, 6 Feb 2020 15:55:05 +0100 Subject: [PATCH] tu: Handle vkCmdClearAttachments() with sysmem Part-of: --- src/freedreno/vulkan/tu_blit.h | 19 ++++ src/freedreno/vulkan/tu_cmd_buffer.c | 81 +++------------ src/freedreno/vulkan/tu_meta_clear.c | 143 ++++++++++++++++++++++----- src/freedreno/vulkan/tu_private.h | 15 +++ 4 files changed, 166 insertions(+), 92 deletions(-) diff --git a/src/freedreno/vulkan/tu_blit.h b/src/freedreno/vulkan/tu_blit.h index cadcfc0cf29..6400fa9d2bc 100644 --- a/src/freedreno/vulkan/tu_blit.h +++ b/src/freedreno/vulkan/tu_blit.h @@ -102,6 +102,25 @@ tu_blit_surf_whole(struct tu_image *image, int level, int layer) }); } +static inline struct tu_blit_surf +sysmem_attachment_surf(const struct tu_image_view *view, uint32_t base_layer, + const VkRect2D *rect) +{ + return tu_blit_surf_ext(view->image, (VkImageSubresourceLayers) { + .mipLevel = view->base_mip, + .baseArrayLayer = base_layer, + }, (VkOffset3D) { + .x = rect->offset.x, + .y = rect->offset.y, + .z = 0, + }, (VkExtent3D) { + .width = rect->extent.width, + .height = rect->extent.height, + .depth = 1, + }); +} + + enum tu_blit_type { TU_BLIT_DEFAULT, TU_BLIT_COPY, diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index e751a6273d0..0df31a07f2e 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -848,33 +848,8 @@ tu6_emit_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs, if (!clear_mask) return; - const struct tu_native_format *format = - tu6_get_native_format(iview->vk_format); - assert(format && format->rb >= 0); - - tu_cs_emit_regs(cs, - A6XX_RB_BLIT_DST_INFO(.color_format = format->rb)); - - tu_cs_emit_regs(cs, - A6XX_RB_BLIT_INFO(.gmem = true, - .clear_mask = clear_mask)); - - tu_cs_emit_regs(cs, - A6XX_RB_BLIT_BASE_GMEM(attachment->gmem_offset)); - - tu_cs_emit_regs(cs, - A6XX_RB_UNKNOWN_88D0(0)); - - uint32_t clear_vals[4] = { 0 }; - tu_pack_clear_value(&info->pClearValues[a], iview->vk_format, clear_vals); - - tu_cs_emit_regs(cs, - A6XX_RB_BLIT_CLEAR_COLOR_DW0(clear_vals[0]), - A6XX_RB_BLIT_CLEAR_COLOR_DW1(clear_vals[1]), - A6XX_RB_BLIT_CLEAR_COLOR_DW2(clear_vals[2]), - A6XX_RB_BLIT_CLEAR_COLOR_DW3(clear_vals[3])); - - tu6_emit_blit(cmd, cs); + tu_clear_gmem_attachment(cmd, cs, a, clear_mask, + &info->pClearValues[a]); } static void @@ -1320,27 +1295,10 @@ tu6_emit_binning_pass(struct tu_cmd_buffer *cmd, struct tu_cs *cs) cmd->wait_for_idle = false; } -static inline struct tu_blit_surf -sysmem_clear_surf(const struct tu_image_view *view, const VkRect2D *render_area) -{ - return tu_blit_surf_ext(view->image, (VkImageSubresourceLayers) { - .mipLevel = view->base_mip, - .baseArrayLayer = view->base_layer, - }, (VkOffset3D) { - .x = render_area->offset.x, - .y = render_area->offset.y, - .z = 0, - }, (VkExtent3D) { - .width = render_area->extent.width, - .height = render_area->extent.height, - .depth = 1, - }); -} - static void -tu6_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs, - uint32_t a, - const VkRenderPassBeginInfo *info) +tu_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs, + uint32_t a, + const VkRenderPassBeginInfo *info) { const struct tu_framebuffer *fb = cmd->state.framebuffer; const struct tu_image_view *iview = fb->attachments[a].attachment; @@ -1352,8 +1310,6 @@ tu6_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs, if (attachment->gmem_offset < 0) return; - uint32_t clear_vals[4] = { 0 }; - if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { clear_mask = 0xf; } @@ -1369,20 +1325,11 @@ tu6_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs, if (!clear_mask) return; - if (iview->aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT)) { - tu_2d_clear_zs(&info->pClearValues[a].depthStencil, iview->vk_format, - clear_vals); - } else { - tu_2d_clear_color(&info->pClearValues[a].color, iview->vk_format, - clear_vals); - } - - tu_blit(cmd, cs, &(struct tu_blit) { - .dst = sysmem_clear_surf(iview, &info->renderArea), - .layers = iview->layer_count, - .clear_value = { clear_vals[0], clear_vals[1], clear_vals[2], clear_vals[3] }, - .type = TU_BLIT_CLEAR, + tu_clear_sysmem_attachment(cmd, cs, a, + &info->pClearValues[a], &(struct VkClearRect) { + .rect = info->renderArea, + .baseArrayLayer = iview->base_layer, + .layerCount = iview->layer_count, }); } @@ -1405,7 +1352,7 @@ tu_cmd_prepare_sysmem_clear_ib(struct tu_cmd_buffer *cmd, } for (uint32_t i = 0; i < cmd->state.pass->attachment_count; ++i) - tu6_emit_sysmem_clear_attachment(cmd, &sub_cs, i, info); + tu_emit_sysmem_clear_attachment(cmd, &sub_cs, i, info); /* TODO: We shouldn't need this flush, but without it we'd have an empty IB * when nothing clears which we currently can't handle. @@ -2599,9 +2546,9 @@ tu_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) struct tu_cs *cs = &cmd->draw_cs; VkResult result = tu_cs_reserve_space(cmd->device, cs, 1024); - if (result != VK_SUCCESS) { - cmd->record_result = result; - return; + if (result != VK_SUCCESS) { + cmd->record_result = result; + return; } const struct tu_subpass *subpass = cmd->state.subpass++; diff --git a/src/freedreno/vulkan/tu_meta_clear.c b/src/freedreno/vulkan/tu_meta_clear.c index 478b7ce9aa3..7d24c737cc7 100644 --- a/src/freedreno/vulkan/tu_meta_clear.c +++ b/src/freedreno/vulkan/tu_meta_clear.c @@ -92,6 +92,74 @@ tu_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, clear_image(cmdbuf, image, clear_value, pRanges + i); } +void +tu_clear_sysmem_attachment(struct tu_cmd_buffer *cmd, + struct tu_cs *cs, + uint32_t attachment, + const VkClearValue *value, + const VkClearRect *rect) +{ + if (!cmd->state.framebuffer) { + tu_finishme("sysmem CmdClearAttachments in secondary command buffer"); + return; + } + + const struct tu_image_view *iview = + cmd->state.framebuffer->attachments[attachment].attachment; + + uint32_t clear_vals[4] = { 0 }; + if (iview->aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | + VK_IMAGE_ASPECT_STENCIL_BIT)) { + tu_2d_clear_zs(&value->depthStencil, iview->vk_format, + clear_vals); + } else { + tu_2d_clear_color(&value->color, iview->vk_format, + clear_vals); + } + + tu_blit(cmd, cs, &(struct tu_blit) { + .dst = sysmem_attachment_surf(iview, rect->baseArrayLayer, &rect->rect), + .layers = rect->layerCount, + .clear_value = { clear_vals[0], clear_vals[1], clear_vals[2], clear_vals[3] }, + .type = TU_BLIT_CLEAR, + }); +} + +void +tu_clear_gmem_attachment(struct tu_cmd_buffer *cmd, + struct tu_cs *cs, + uint32_t attachment, + uint8_t component_mask, + const VkClearValue *value) +{ + VkFormat fmt = cmd->state.pass->attachments[attachment].format; + const struct tu_native_format *format = tu6_get_native_format(fmt); + assert(format && format->rb >= 0); + + tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_DST_INFO, 1); + tu_cs_emit(cs, A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format->rb)); + + tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_INFO, 1); + tu_cs_emit(cs, A6XX_RB_BLIT_INFO_GMEM | A6XX_RB_BLIT_INFO_CLEAR_MASK(component_mask)); + + tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_BASE_GMEM, 1); + tu_cs_emit(cs, cmd->state.pass->attachments[attachment].gmem_offset); + + tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_88D0, 1); + tu_cs_emit(cs, 0); + + uint32_t clear_vals[4] = { 0 }; + tu_pack_clear_value(value, fmt, clear_vals); + + tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0, 4); + tu_cs_emit(cs, clear_vals[0]); + tu_cs_emit(cs, clear_vals[1]); + tu_cs_emit(cs, clear_vals[2]); + tu_cs_emit(cs, clear_vals[3]); + + tu6_emit_event_write(cmd, cs, BLIT, false); +} + void tu_CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, @@ -103,17 +171,20 @@ tu_CmdClearAttachments(VkCommandBuffer commandBuffer, const struct tu_subpass *subpass = cmd->state.subpass; struct tu_cs *cs = &cmd->draw_cs; - VkResult result = tu_cs_reserve_space(cmd->device, cs, - rectCount * (3 + 15 * attachmentCount)); + /* Note: reserving space here should never fail because we allocated + * enough above. + */ + struct tu_cond_exec_state state; + VkResult result = + tu_cond_exec_start(cmd->device, cs, &state, + CP_COND_REG_EXEC_0_MODE(RENDER_MODE) | + CP_COND_REG_EXEC_0_GMEM, + rectCount * (3 + attachmentCount * 15)); if (result != VK_SUCCESS) { cmd->record_result = result; return; } - /* TODO: deal with layered rendering (when layered rendering is implemented) - * TODO: disable bypass rendering for subpass (when bypass is implemented) - */ - for (unsigned i = 0; i < rectCount; i++) { unsigned x1 = pRects[i].rect.offset.x; unsigned y1 = pRects[i].rect.offset.y; @@ -141,32 +212,54 @@ tu_CmdClearAttachments(VkCommandBuffer commandBuffer, if (a == VK_ATTACHMENT_UNUSED) continue; - VkFormat fmt = cmd->state.pass->attachments[a].format; - const struct tu_native_format *format = tu6_get_native_format(fmt); - assert(format && format->rb >= 0); + tu_clear_gmem_attachment(cmd, cs, a, clear_mask, + &pAttachments[j].clearValue); - tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_DST_INFO, 1); - tu_cs_emit(cs, A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format->rb)); + } + } + + tu_cond_exec_end(cs, &state); - tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_INFO, 1); - tu_cs_emit(cs, A6XX_RB_BLIT_INFO_GMEM | A6XX_RB_BLIT_INFO_CLEAR_MASK(clear_mask)); + uint32_t clear_count = 3; + for (unsigned j = 0; j < rectCount; j++) + clear_count += 18 + 66 * pRects[j].layerCount + 17; - tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_BASE_GMEM, 1); - tu_cs_emit(cs, cmd->state.pass->attachments[a].gmem_offset); + result = + tu_cond_exec_start(cmd->device, cs, &state, + CP_COND_REG_EXEC_0_MODE(RENDER_MODE) | + CP_COND_REG_EXEC_0_SYSMEM, + attachmentCount * clear_count); - tu_cs_emit_pkt4(cs, REG_A6XX_RB_UNKNOWN_88D0, 1); - tu_cs_emit(cs, 0); + if (result != VK_SUCCESS) { + cmd->record_result = result; + return; + } - uint32_t clear_vals[4] = { 0 }; - tu_pack_clear_value(&pAttachments[j].clearValue, fmt, clear_vals); + for (unsigned i = 0; i < rectCount; i++) { + for (unsigned j = 0; j < attachmentCount; j++) { + uint32_t a; + unsigned clear_mask = 0; + if (pAttachments[j].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { + clear_mask = 0xf; + a = subpass->color_attachments[pAttachments[j].colorAttachment].attachment; + } else { + a = subpass->depth_stencil_attachment.attachment; + if (pAttachments[j].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) + clear_mask |= 1; + if (pAttachments[j].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) + clear_mask |= 2; + if (clear_mask != 3) + tu_finishme("sysmem depth/stencil only clears"); + } - tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_CLEAR_COLOR_DW0, 4); - tu_cs_emit(cs, clear_vals[0]); - tu_cs_emit(cs, clear_vals[1]); - tu_cs_emit(cs, clear_vals[2]); - tu_cs_emit(cs, clear_vals[3]); + if (a == VK_ATTACHMENT_UNUSED) + continue; - tu6_emit_event_write(cmd, cs, BLIT, false); + tu_clear_sysmem_attachment(cmd, cs, a, + &pAttachments[j].clearValue, + &pRects[i]); } } + + tu_cond_exec_end(cs, &state); } diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index a86a18bdfa3..7c53e509d8e 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -1636,6 +1636,21 @@ tu_gem_info_offset(const struct tu_device *dev, uint32_t gem_handle); uint64_t tu_gem_info_iova(const struct tu_device *dev, uint32_t gem_handle); + +void +tu_clear_sysmem_attachment(struct tu_cmd_buffer *cmd, + struct tu_cs *cs, + uint32_t attachment, + const VkClearValue *value, + const VkClearRect *rect); + +void +tu_clear_gmem_attachment(struct tu_cmd_buffer *cmd, + struct tu_cs *cs, + uint32_t attachment, + uint8_t component_mask, + const VkClearValue *value); + #define TU_DEFINE_HANDLE_CASTS(__tu_type, __VkType) \ \ static inline struct __tu_type *__tu_type##_from_handle(__VkType _handle) \ -- 2.30.2