From 304af47ba2500dc3afe34250b3416fd8f04a176a Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Thu, 13 Mar 2025 09:40:53 -0400 Subject: [PATCH] tu: Only allow power-of-two fragment areas Non-power-of-two fragment areas can result in precision loss and missed fragments, which was seen in an upcoming CTS test. Part-of: --- src/freedreno/vulkan/tu_cmd_buffer.cc | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index 183634611fe..c47f3f0e517 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -2363,8 +2363,16 @@ tu_calc_frag_area(struct tu_cmd_buffer *cmd, else floor_y += 1.f; } - tile->frag_areas[i].width = floor_x; - tile->frag_areas[i].height = floor_y; + uint32_t width = floor_x; + uint32_t height = floor_y; + + /* Areas that aren't a power of two, especially large areas, can create + * in floating-point rounding errors when dividing by the area in the + * viewport that result in under-rendering. Round down to a power of two + * to make sure all operations are exact. + */ + width = 1u << util_logbase2(width); + height = 1u << util_logbase2(height); /* Make sure that the width/height divides the tile width/height so * we don't have to do extra awkward clamping of the edges of each @@ -2373,10 +2381,13 @@ tu_calc_frag_area(struct tu_cmd_buffer *cmd, * * TODO: Try to take advantage of the total area allowance here, too. */ - while (tiling->tile0.width % tile->frag_areas[i].width != 0) - tile->frag_areas[i].width--; - while (tiling->tile0.height % tile->frag_areas[i].height != 0) - tile->frag_areas[i].height--; + while (tiling->tile0.width % width != 0) + width /= 2; + while (tiling->tile0.height % height != 0) + height /= 2; + + tile->frag_areas[i].width = width; + tile->frag_areas[i].height = height; } /* If at any point we were forced to use the same scaling for all