zink: Use pipe_box helpers for damage calculations

The old code got the accumulation a bit wrong.  For one thing, it always
accumulates with whatever was there instead of resetting to empty each
time.  For another, it sets with with y and height with x when it writes
back to the resource.  This is also all too complicated because it
converts between pipe_box, u_rect, and VkRect2D on every iteration.

Instead, there are helpers in util/box.h which will do most of this work
for us and they're correct.  Let's just use them to get rid of the bugs
and make everything simpler and more obvious at the same time.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12194
Fixes: 3d38c9597f ("zink: hook up KHR_partial_update")
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33855>
(cherry picked from commit 11939a70df)
This commit is contained in:
Faith Ekstrand 2025-03-03 10:27:43 -06:00 committed by Eric Engestrom
parent a8a5e94ddf
commit 58d30fed2f
2 changed files with 28 additions and 23 deletions

View file

@ -5104,7 +5104,7 @@
"description": "zink: Use pipe_box helpers for damage calculations",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "3d38c9597ff3b687026fa4c664f8b4aa20b97f53",
"notes": null

View file

@ -1469,30 +1469,35 @@ zink_set_damage_region(struct pipe_screen *pscreen, struct pipe_resource *pres,
{
struct zink_resource *res = zink_resource(pres);
for (unsigned i = 0; i < nrects; i++) {
int y = pres->height0 - rects[i].y - rects[i].height;
/* convert back to coord-based rects to use coordinate calcs */
struct u_rect currect = {
.x0 = res->damage.offset.x,
.y0 = res->damage.offset.y,
.x1 = res->damage.offset.x + res->damage.extent.width,
.y1 = res->damage.offset.y + res->damage.extent.height,
};
struct u_rect newrect = {
.x0 = rects[i].x,
.y0 = y,
.x1 = rects[i].x + rects[i].width,
.y1 = y + rects[i].height,
};
struct u_rect u;
u_rect_union(&u, &currect, &newrect);
res->damage.extent.width = u.y1 - u.y0;
res->damage.extent.height = u.x1 - u.x0;
res->damage.offset.x = u.x0;
res->damage.offset.y = u.y0;
if (nrects == 0) {
res->use_damage = false;
return;
}
res->use_damage = nrects > 0;
struct pipe_box damage = rects[0];
for (unsigned i = 1; i < nrects; i++)
u_box_union_2d(&damage, &damage, &rects[i]);
/* The damage we get from EGL uses a lower-left origin but Vulkan uses
* upper-left so we need to flip it.
*/
damage.y = pres->height0 - (damage.y + damage.height);
/* Intersect with the area of the resource */
struct pipe_box res_area;
u_box_origin_2d(pres->width0, pres->height0, &res_area);
u_box_intersect_2d(&damage, &damage, &res_area);
res->damage = (VkRect2D) {
.offset.x = damage.x,
.offset.y = damage.y,
.extent.width = damage.width,
.extent.height = damage.height,
};
res->use_damage = damage.x != 0 ||
damage.y != 0 ||
damage.width != res->base.b.width0 ||
damage.height != res->base.b.height0;
}
static void