tu: Handle vkCmdClearAttachments() with sysmem

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3713>
This commit is contained in:
Connor Abbott 2020-02-06 15:55:05 +01:00 committed by Jonathan Marek
parent 07e07daeae
commit 8647a24a8d
4 changed files with 172 additions and 98 deletions

View File

@ -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,

View File

@ -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++;

View File

@ -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_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));
tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLIT_BASE_GMEM, 1);
tu_cs_emit(cs, cmd->state.pass->attachments[a].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(&pAttachments[j].clearValue, 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);
}
}
tu_cond_exec_end(cs, &state);
uint32_t clear_count = 3;
for (unsigned j = 0; j < rectCount; j++)
clear_count += 18 + 66 * pRects[j].layerCount + 17;
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);
if (result != VK_SUCCESS) {
cmd->record_result = result;
return;
}
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");
}
if (a == VK_ATTACHMENT_UNUSED)
continue;
tu_clear_sysmem_attachment(cmd, cs, a,
&pAttachments[j].clearValue,
&pRects[i]);
}
}
tu_cond_exec_end(cs, &state);
}

View File

@ -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) \