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
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;
if (attachment->gmem_offset < 0)
return;
- uint32_t clear_vals[4] = { 0 };
-
if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
clear_mask = 0xf;
}
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,
});
}
}
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.
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++;
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,
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;
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);
}