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 {
|
enum tu_blit_type {
|
||||||
TU_BLIT_DEFAULT,
|
TU_BLIT_DEFAULT,
|
||||||
TU_BLIT_COPY,
|
TU_BLIT_COPY,
|
||||||
|
|
|
@ -848,33 +848,8 @@ tu6_emit_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs,
|
||||||
if (!clear_mask)
|
if (!clear_mask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const struct tu_native_format *format =
|
tu_clear_gmem_attachment(cmd, cs, a, clear_mask,
|
||||||
tu6_get_native_format(iview->vk_format);
|
&info->pClearValues[a]);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1320,27 +1295,10 @@ tu6_emit_binning_pass(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
|
||||||
cmd->wait_for_idle = false;
|
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
|
static void
|
||||||
tu6_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs,
|
tu_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs,
|
||||||
uint32_t a,
|
uint32_t a,
|
||||||
const VkRenderPassBeginInfo *info)
|
const VkRenderPassBeginInfo *info)
|
||||||
{
|
{
|
||||||
const struct tu_framebuffer *fb = cmd->state.framebuffer;
|
const struct tu_framebuffer *fb = cmd->state.framebuffer;
|
||||||
const struct tu_image_view *iview = fb->attachments[a].attachment;
|
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)
|
if (attachment->gmem_offset < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t clear_vals[4] = { 0 };
|
|
||||||
|
|
||||||
if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
||||||
clear_mask = 0xf;
|
clear_mask = 0xf;
|
||||||
}
|
}
|
||||||
|
@ -1369,20 +1325,11 @@ tu6_emit_sysmem_clear_attachment(struct tu_cmd_buffer *cmd, struct tu_cs *cs,
|
||||||
if (!clear_mask)
|
if (!clear_mask)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (iview->aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT |
|
tu_clear_sysmem_attachment(cmd, cs, a,
|
||||||
VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
&info->pClearValues[a], &(struct VkClearRect) {
|
||||||
tu_2d_clear_zs(&info->pClearValues[a].depthStencil, iview->vk_format,
|
.rect = info->renderArea,
|
||||||
clear_vals);
|
.baseArrayLayer = iview->base_layer,
|
||||||
} else {
|
.layerCount = iview->layer_count,
|
||||||
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,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
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
|
/* 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.
|
* 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;
|
struct tu_cs *cs = &cmd->draw_cs;
|
||||||
|
|
||||||
VkResult result = tu_cs_reserve_space(cmd->device, cs, 1024);
|
VkResult result = tu_cs_reserve_space(cmd->device, cs, 1024);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
cmd->record_result = result;
|
cmd->record_result = result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct tu_subpass *subpass = cmd->state.subpass++;
|
const struct tu_subpass *subpass = cmd->state.subpass++;
|
||||||
|
|
|
@ -92,6 +92,74 @@ tu_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
|
||||||
clear_image(cmdbuf, image, clear_value, pRanges + i);
|
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
|
void
|
||||||
tu_CmdClearAttachments(VkCommandBuffer commandBuffer,
|
tu_CmdClearAttachments(VkCommandBuffer commandBuffer,
|
||||||
uint32_t attachmentCount,
|
uint32_t attachmentCount,
|
||||||
|
@ -103,17 +171,20 @@ tu_CmdClearAttachments(VkCommandBuffer commandBuffer,
|
||||||
const struct tu_subpass *subpass = cmd->state.subpass;
|
const struct tu_subpass *subpass = cmd->state.subpass;
|
||||||
struct tu_cs *cs = &cmd->draw_cs;
|
struct tu_cs *cs = &cmd->draw_cs;
|
||||||
|
|
||||||
VkResult result = tu_cs_reserve_space(cmd->device, cs,
|
/* Note: reserving space here should never fail because we allocated
|
||||||
rectCount * (3 + 15 * attachmentCount));
|
* 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) {
|
if (result != VK_SUCCESS) {
|
||||||
cmd->record_result = result;
|
cmd->record_result = result;
|
||||||
return;
|
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++) {
|
for (unsigned i = 0; i < rectCount; i++) {
|
||||||
unsigned x1 = pRects[i].rect.offset.x;
|
unsigned x1 = pRects[i].rect.offset.x;
|
||||||
unsigned y1 = pRects[i].rect.offset.y;
|
unsigned y1 = pRects[i].rect.offset.y;
|
||||||
|
@ -141,32 +212,54 @@ tu_CmdClearAttachments(VkCommandBuffer commandBuffer,
|
||||||
if (a == VK_ATTACHMENT_UNUSED)
|
if (a == VK_ATTACHMENT_UNUSED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
VkFormat fmt = cmd->state.pass->attachments[a].format;
|
tu_clear_gmem_attachment(cmd, cs, a, clear_mask,
|
||||||
const struct tu_native_format *format = tu6_get_native_format(fmt);
|
&pAttachments[j].clearValue);
|
||||||
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(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
|
uint64_t
|
||||||
tu_gem_info_iova(const struct tu_device *dev, uint32_t gem_handle);
|
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) \
|
#define TU_DEFINE_HANDLE_CASTS(__tu_type, __VkType) \
|
||||||
\
|
\
|
||||||
static inline struct __tu_type *__tu_type##_from_handle(__VkType _handle) \
|
static inline struct __tu_type *__tu_type##_from_handle(__VkType _handle) \
|
||||||
|
|
Loading…
Reference in New Issue