tu: Handle vkCmdClearAttachments() with sysmem
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3713>
This commit is contained in:
parent
07e07daeae
commit
8647a24a8d
|
@ -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,
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) \
|
||||
|
|
Loading…
Reference in New Issue