From 969820e7fe95a2465d14ebd719f16abbf8729e76 Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Thu, 17 Apr 2025 14:13:02 +0200 Subject: [PATCH] tu/lrz: Disable LRZ if RP writes depth but doesn't set on GPU dir If the render pass writes depth (with direction) but doesn't set direction on the GPU, the LRZ buffer cannot be used in subsequent render passes because the direction information is lost. Fixes rendering in "Elite Dangerous" game. Signed-off-by: Danylo Piliaiev Part-of: --- src/freedreno/vulkan/tu_cmd_buffer.cc | 6 ++++++ src/freedreno/vulkan/tu_lrz.cc | 19 +++++++++++++++++-- src/freedreno/vulkan/tu_lrz.h | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index 795634d0670..7d546c5c4a8 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -4960,6 +4960,12 @@ tu_CmdExecuteCommands(VkCommandBuffer commandBuffer, */ if (!secondary->state.lrz.valid) cmd->state.lrz.valid = false; + if (secondary->state.lrz.gpu_dir_set) + cmd->state.lrz.gpu_dir_set = true; + if (cmd->state.lrz.prev_direction == TU_LRZ_UNKNOWN && + secondary->state.lrz.prev_direction != TU_LRZ_UNKNOWN) + cmd->state.lrz.prev_direction = + secondary->state.lrz.prev_direction; tu_clone_trace(cmd, &cmd->draw_cs, &secondary->trace); tu_render_pass_state_merge(&cmd->state.rp, &secondary->state.rp); diff --git a/src/freedreno/vulkan/tu_lrz.cc b/src/freedreno/vulkan/tu_lrz.cc index 705a91d60a5..64697979052 100644 --- a/src/freedreno/vulkan/tu_lrz.cc +++ b/src/freedreno/vulkan/tu_lrz.cc @@ -504,8 +504,18 @@ tu_lrz_tiling_end(struct tu_cmd_buffer *cmd, struct tu_cs *cs) /* 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.valid_at_start && - !cmd->state.lrz.valid) { + bool disable_for_next_rp = cmd->state.lrz.valid_at_start && + !cmd->state.lrz.valid; + /* If the render pass writes depth (with direction) but doesn't set + * direction on the GPU, the LRZ buffer cannot be used in subsequent + * render passes because the direction information is lost. + */ + if (!cmd->state.lrz.gpu_dir_set && + cmd->state.lrz.prev_direction != TU_LRZ_UNKNOWN) { + disable_for_next_rp = true; + } + + if (cmd->state.lrz.gpu_dir_tracking && disable_for_next_rp) { tu6_write_lrz_reg(cmd, cs, A6XX_GRAS_LRZ_DEPTH_VIEW( .base_layer = 0b11111111111, .layer_count = 0b11111111111, @@ -962,6 +972,11 @@ tu6_calculate_lrz_state(struct tu_cmd_buffer *cmd, if (!cmd->state.lrz.enabled) memset(&gras_lrz_cntl, 0, sizeof(gras_lrz_cntl)); + if (cmd->state.lrz.enabled && gras_lrz_cntl.lrz_write && + cmd->state.lrz.prev_direction != TU_LRZ_UNKNOWN) { + cmd->state.lrz.gpu_dir_set = true; + } + return gras_lrz_cntl; } diff --git a/src/freedreno/vulkan/tu_lrz.h b/src/freedreno/vulkan/tu_lrz.h index 414f9a4d401..1ff80e0874d 100644 --- a/src/freedreno/vulkan/tu_lrz.h +++ b/src/freedreno/vulkan/tu_lrz.h @@ -45,6 +45,7 @@ struct tu_lrz_state bool gpu_dir_tracking : 1; /* Continue using old LRZ state (LOAD_OP_LOAD of depth) */ bool reuse_previous_state : 1; + bool gpu_dir_set : 1; enum tu_lrz_direction prev_direction; };