From 732101d609b6545ca768df69768e57226ff30818 Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Sat, 4 Jan 2025 22:54:27 +0100 Subject: [PATCH] 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 Part-of: --- src/freedreno/vulkan/tu_cmd_buffer.cc | 11 +++- src/freedreno/vulkan/tu_lrz.cc | 74 +++++++++++++-------------- src/freedreno/vulkan/tu_lrz.h | 6 +++ 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index 6c509571b26..ee712f8f5d4 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -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); diff --git a/src/freedreno/vulkan/tu_lrz.cc b/src/freedreno/vulkan/tu_lrz.cc index da1583b03ae..f1b0c5d526b 100644 --- a/src/freedreno/vulkan/tu_lrz.cc +++ b/src/freedreno/vulkan/tu_lrz.cc @@ -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(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(cmd, cs, FD_LRZ_CLEAR); } - if (!lrz->fast_clear && !invalidate_lrz) { + if (!lrz->fast_clear && !lrz->disable_for_rp) { tu6_clear_lrz(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(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(cmd, cs, {.enable = false}); } - tu_emit_event_write(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(cmd, cs, FD_LRZ_CLEAR); + tu_emit_event_write(cmd, cs, FD_LRZ_FLUSH); + } else { + tu_emit_event_write(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(cmd, &cmd->cs, { - .enable = true, - .dir = LRZ_DIR_INVALID, - .disable_on_wrong_dir = true, - }); - } } TU_GENX(tu_lrz_disable_during_renderpass); +template +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; diff --git a/src/freedreno/vulkan/tu_lrz.h b/src/freedreno/vulkan/tu_lrz.h index e58cdaf4a40..01b1e082361 100644 --- a/src/freedreno/vulkan/tu_lrz.h +++ b/src/freedreno/vulkan/tu_lrz.h @@ -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 +void +tu_lrz_flush_valid_during_renderpass(struct tu_cmd_buffer *cmd, + struct tu_cs *cs); + #endif /* TU_LRZ_H */