tu: Do not disable LRZ for whole RP if it is disabled in RP

It's not rare when only last few draws in a big renderpass disable
LRZ, we shouldn't bail out in such case.

If LRZ is disabled in dir tracking bit during binning - LRZ would
be disabled for the whole IB in the tiling step, so we should avoid
disabling via dir tracking bit and track the state inside the driver.
This doesn't work with secondary command buffers (and renderpass
resume/suspend), in such cases we have to disable LRZ via dir tracking
bit, if LRZ is not valid.

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32868>
This commit is contained in:
Danylo Piliaiev
2025-01-04 22:54:27 +01:00
committed by Marge Bot
parent d6684aedf4
commit 732101d609
3 changed files with 53 additions and 38 deletions
+10 -1
View File
@@ -4386,6 +4386,9 @@ tu_CmdExecuteCommands(VkCommandBuffer commandBuffer,
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
assert(tu_cs_is_empty(&secondary->cs));
TU_CALLX(cmd->device, tu_lrz_flush_valid_during_renderpass)
(cmd, &cmd->draw_cs);
result = tu_cs_add_entries(&cmd->draw_cs, &secondary->draw_cs);
if (result != VK_SUCCESS) {
vk_command_buffer_set_error(&cmd->vk, result);
@@ -7137,8 +7140,14 @@ tu_CmdEndRendering(VkCommandBuffer commandBuffer)
{
VK_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
if (cmd_buffer->state.suspending)
if (cmd_buffer->state.suspending) {
cmd_buffer->state.suspended_pass.lrz = cmd_buffer->state.lrz;
/* We cannot pass LRZ state to next resuming renderpass, so we have to
* force disable it here.
*/
TU_CALLX(cmd_buffer->device, tu_lrz_flush_valid_during_renderpass)
(cmd_buffer, &cmd_buffer->draw_cs);
}
if (!cmd_buffer->state.suspending) {
tu_cs_end(&cmd_buffer->draw_cs);
+37 -37
View File
@@ -353,13 +353,11 @@ tu_lrz_tiling_begin(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
return;
}
bool invalidate_lrz = !lrz->valid && lrz->gpu_dir_tracking;
if (invalidate_lrz) {
/* Following the blob we elect to disable LRZ for the whole renderpass
* if it is known that LRZ is disabled somewhere in the renderpass.
*
if (lrz->disable_for_rp) {
/* We may deem necessary to disable LRZ for the whole renderpass.
* This is accomplished by making later GRAS_LRZ_CNTL (in binning pass)
* to fail the comparison of depth views.
* TODO: Find if there are conditions where it is beneficial.
*/
tu6_disable_lrz_via_depth_view<CHIP>(cmd, cs);
tu6_write_lrz_reg(cmd, cs, A6XX_GRAS_LRZ_DEPTH_VIEW(.dword = 0));
@@ -384,7 +382,7 @@ tu_lrz_tiling_begin(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
tu_emit_event_write<CHIP>(cmd, cs, FD_LRZ_CLEAR);
}
if (!lrz->fast_clear && !invalidate_lrz) {
if (!lrz->fast_clear && !lrz->disable_for_rp) {
tu6_clear_lrz<CHIP>(cmd, cs, lrz->image_view->image, &lrz->depth_clear_value);
/* Even though we disable fast-clear we still have to dirty
* fast-clear buffer because both secondary cmdbufs and following
@@ -414,7 +412,7 @@ tu_lrz_before_tile(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
tu6_emit_lrz_buffer<CHIP>(cs, lrz->image_view->image);
if (lrz->gpu_dir_tracking) {
if (!lrz->valid) {
if (lrz->disable_for_rp) {
/* Make sure we fail the comparison of depth views */
tu6_write_lrz_reg(cmd, cs, A6XX_GRAS_LRZ_DEPTH_VIEW(.dword = 0));
} else {
@@ -448,18 +446,22 @@ tu_lrz_tiling_end(struct tu_cmd_buffer *cmd, struct tu_cs *cs)
tu6_write_lrz_cntl<CHIP>(cmd, cs, {.enable = false});
}
tu_emit_event_write<CHIP>(cmd, cs, FD_LRZ_FLUSH);
/* If gpu_dir_tracking is enabled and lrz is not valid blob, at this point,
* additionally clears direction buffer:
* GRAS_LRZ_DEPTH_VIEW(.dword = 0)
* GRAS_LRZ_DEPTH_VIEW(.dword = 0xffffffff)
* A6XX_GRAS_LRZ_CNTL(.enable = true, .disable_on_wrong_dir = true)
* LRZ_CLEAR
* LRZ_FLUSH
* Since it happens after all of the rendering is done there is no known
* reason to do such clear.
/* If we haven't disabled LRZ during renderpass, we need to disable it here
* for next renderpass to not use invalid LRZ values.
*/
if (cmd->state.lrz.gpu_dir_tracking && !cmd->state.lrz.disable_for_rp &&
!cmd->state.lrz.valid) {
tu6_write_lrz_reg(cmd, cs, A6XX_GRAS_LRZ_DEPTH_VIEW(
.base_layer = 0b11111111111,
.layer_count = 0b11111111111,
.base_mip_level = 0b1111,
));
tu_emit_event_write<CHIP>(cmd, cs, FD_LRZ_CLEAR);
tu_emit_event_write<CHIP>(cmd, cs, FD_LRZ_FLUSH);
} else {
tu_emit_event_write<CHIP>(cmd, cs, FD_LRZ_FLUSH);
}
}
TU_GENX(tu_lrz_tiling_end);
@@ -632,17 +634,25 @@ tu_lrz_disable_during_renderpass(struct tu_cmd_buffer *cmd,
cmd->state.lrz.valid = false;
cmd->state.dirty |= TU_CMD_DIRTY_LRZ;
if (cmd->state.lrz.gpu_dir_tracking) {
tu6_write_lrz_cntl<CHIP>(cmd, &cmd->cs, {
.enable = true,
.dir = LRZ_DIR_INVALID,
.disable_on_wrong_dir = true,
});
}
}
TU_GENX(tu_lrz_disable_during_renderpass);
template <chip CHIP>
void
tu_lrz_flush_valid_during_renderpass(struct tu_cmd_buffer *cmd,
struct tu_cs *cs)
{
if (cmd->state.lrz.valid || cmd->state.lrz.disable_for_rp)
return;
tu6_write_lrz_reg(cmd, cs, A6XX_GRAS_LRZ_DEPTH_VIEW(
.base_layer = 0b11111111111,
.layer_count = 0b11111111111,
.base_mip_level = 0b1111,
));
}
TU_GENX(tu_lrz_flush_valid_during_renderpass);
/* update lrz state based on stencil-test func:
*
* Conceptually the order of the pipeline is:
@@ -910,17 +920,7 @@ tu6_calculate_lrz_state(struct tu_cmd_buffer *cmd,
if (disable_lrz)
cmd->state.lrz.valid = false;
if (disable_lrz && cmd->state.lrz.gpu_dir_tracking) {
/* Direction byte on GPU should be set to CUR_DIR_DISABLED,
* for this it's not enough to emit empty GRAS_LRZ_CNTL.
*/
gras_lrz_cntl.enable = true;
gras_lrz_cntl.dir = LRZ_DIR_INVALID;
return gras_lrz_cntl;
}
if (temporary_disable_lrz)
if (temporary_disable_lrz || disable_lrz)
gras_lrz_cntl.enable = false;
cmd->state.lrz.enabled = cmd->state.lrz.valid && gras_lrz_cntl.enable;
+6
View File
@@ -33,6 +33,7 @@ struct tu_lrz_state
VkClearValue depth_clear_value;
/* If LRZ is in invalid state we cannot use it until depth is cleared */
bool valid : 1;
bool disable_for_rp : 1;
/* Allows to temporary disable LRZ */
bool enabled : 1;
bool fast_clear : 1;
@@ -99,4 +100,9 @@ void
tu_lrz_disable_during_renderpass(struct tu_cmd_buffer *cmd,
const char *reason);
template <chip CHIP>
void
tu_lrz_flush_valid_during_renderpass(struct tu_cmd_buffer *cmd,
struct tu_cs *cs);
#endif /* TU_LRZ_H */