From b1dcc9a1d77a655cacaead03ca6ebb46ada1682f Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Tue, 25 Mar 2025 16:13:56 -0400 Subject: [PATCH] tu: Fix binning_possible detection with bin merging When bin merging we maximize instead of minimize the VSC pipe size, which means that we fail when there are too many pipes instead of when the pipes are too large. This means that we need to calculate binning_possible differently, and we need to skip tu_tiling_config_update_pipes() when binning is impossible because otherwise we will write out-of-bounds. Fixes: 3fdaad0948c ("tu: Implement bin merging for fragment density map") Part-of: --- src/freedreno/vulkan/tu_util.cc | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/freedreno/vulkan/tu_util.cc b/src/freedreno/vulkan/tu_util.cc index 7feae56552a..5b72272e366 100644 --- a/src/freedreno/vulkan/tu_util.cc +++ b/src/freedreno/vulkan/tu_util.cc @@ -318,6 +318,17 @@ tu_tiling_config_update_tile_layout(struct tu_framebuffer *fb, } } +static bool +is_hw_binning_possible(const struct tu_tiling_config *tiling) +{ + /* Similar to older gens, # of tiles per pipe cannot be more than 32. + * But there are no hangs with 16 or more tiles per pipe in either + * X or Y direction, so that limit does not seem to apply. + */ + uint32_t tiles_per_pipe = tiling->pipe0.width * tiling->pipe0.height; + return tiles_per_pipe <= 32; +} + static void tu_tiling_config_update_pipe_layout(struct tu_tiling_config *tiling, const struct tu_device *dev, @@ -340,6 +351,8 @@ tu_tiling_config_update_pipe_layout(struct tu_tiling_config *tiling, DIV_ROUND_UP(tiling->tile_count.width, tiling->pipe0.width); tiling->pipe_count.height = DIV_ROUND_UP(tiling->tile_count.height, tiling->pipe0.height); + tiling->binning_possible = + tiling->pipe_count.width * tiling->pipe_count.height <= max_pipe_count; return; } @@ -361,6 +374,8 @@ tu_tiling_config_update_pipe_layout(struct tu_tiling_config *tiling, DIV_ROUND_UP(tiling->tile_count.height, tiling->pipe0.height); } } + + tiling->binning_possible = is_hw_binning_possible(tiling); } static void @@ -376,6 +391,9 @@ tu_tiling_config_update_pipes(struct tu_tiling_config *tiling, .height = (tiling->tile_count.height - 1) % tiling->pipe0.height + 1, }; + if (!tiling->binning_possible) + return; + assert(used_pipe_count <= max_pipe_count); assert(max_pipe_count <= ARRAY_SIZE(tiling->pipe_config)); @@ -403,22 +421,9 @@ tu_tiling_config_update_pipes(struct tu_tiling_config *tiling, sizeof(uint32_t) * (max_pipe_count - used_pipe_count)); } -static bool -is_hw_binning_possible(const struct tu_tiling_config *tiling) -{ - /* Similar to older gens, # of tiles per pipe cannot be more than 32. - * But there are no hangs with 16 or more tiles per pipe in either - * X or Y direction, so that limit does not seem to apply. - */ - uint32_t tiles_per_pipe = tiling->pipe0.width * tiling->pipe0.height; - return tiles_per_pipe <= 32; -} - static void tu_tiling_config_update_binning(struct tu_tiling_config *tiling, const struct tu_device *device) { - tiling->binning_possible = is_hw_binning_possible(tiling); - if (tiling->binning_possible) { tiling->binning = (tiling->tile_count.width * tiling->tile_count.height) > 2;