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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33500>
This commit is contained in:
Connor Abbott
2025-03-13 09:40:53 -04:00
committed by Marge Bot
parent 5ad00bae8b
commit 304af47ba2
+17 -6
View File
@@ -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