From 0d8a54f9137ea639eb2118ec4a6d309529593e75 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 27 Feb 2023 18:57:04 -0500 Subject: [PATCH] zink: avoid ballooning of copy box tracking * if the proposed box is smaller than an existing box then don't add it, * if the proposed box is adjacent to an existing box, expand * if the proposed box is larger than an existing box, replace this reduces the chances of having a ton of copy boxes to iterate over also add a perf warning in case a ton of copy boxes exist Part-of: --- src/gallium/drivers/zink/zink_resource.c | 146 +++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 60a8131..5a2ff1a 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -2206,7 +2206,153 @@ zink_resource_copy_box_intersects(struct zink_resource *res, unsigned level, con void zink_resource_copy_box_add(struct zink_resource *res, unsigned level, const struct pipe_box *box) { + if (res->obj->copies_valid) { + struct pipe_box *b = res->obj->copies[level].data; + unsigned num_boxes = util_dynarray_num_elements(&res->obj->copies[level], struct pipe_box); + for (unsigned i = 0; i < num_boxes; i++) { + switch (res->base.b.target) { + case PIPE_BUFFER: + case PIPE_TEXTURE_1D: + /* no-op included region */ + if (b->x <= box->x && b->x + b->width >= box->x + box->width) + return; + + /* try to merge adjacent regions */ + if (b->x == box->x + box->width) { + b->x -= box->width; + return; + } + if (b->x + b->width == box->x) { + b->width += box->width; + return; + } + + /* try to merge into region */ + if (box->x <= b->x && box->x + box->width >= b->x + b->width) { + *b = *box; + return; + } + break; + + case PIPE_TEXTURE_1D_ARRAY: + case PIPE_TEXTURE_2D: + /* no-op included region */ + if (b->x <= box->x && b->x + b->width >= box->x + box->width && + b->y <= box->y && b->y + b->height >= box->y + box->height) + return; + + /* try to merge adjacent regions */ + if (b->y == box->y && b->height == box->height) { + if (b->x == box->x + box->width) { + b->x -= box->width; + return; + } + if (b->x + b->width == box->x) { + b->width += box->width; + return; + } + } else if (b->x == box->x && b->width == box->width) { + if (b->y == box->y + box->height) { + b->y -= box->height; + return; + } + if (b->y + b->height == box->y) { + b->height += box->height; + return; + } + } + + /* try to merge into region */ + if (box->x <= b->x && box->x + box->width >= b->x + b->width && + box->y <= b->y && box->y + box->height >= b->y + b->height) { + *b = *box; + return; + } + break; + + default: + /* no-op included region */ + if (b->x <= box->x && b->x + b->width >= box->x + box->width && + b->y <= box->y && b->y + b->height >= box->y + box->height && + b->z <= box->z && b->z + b->depth >= box->z + box->depth) + return; + + /* try to merge adjacent regions */ + if (b->z == box->z && b->depth == box->depth) { + if (b->y == box->y && b->height == box->height) { + if (b->x == box->x + box->width) { + b->x -= box->width; + return; + } + if (b->x + b->width == box->x) { + b->width += box->width; + return; + } + } else if (b->x == box->x && b->width == box->width) { + if (b->y == box->y + box->height) { + b->y -= box->height; + return; + } + if (b->y + b->height == box->y) { + b->height += box->height; + return; + } + } + } else if (b->x == box->x && b->width == box->width) { + if (b->y == box->y && b->height == box->height) { + if (b->z == box->z + box->depth) { + b->z -= box->depth; + return; + } + if (b->z + b->depth == box->z) { + b->depth += box->depth; + return; + } + } else if (b->z == box->z && b->depth == box->depth) { + if (b->y == box->y + box->height) { + b->y -= box->height; + return; + } + if (b->y + b->height == box->y) { + b->height += box->height; + return; + } + } + } else if (b->y == box->y && b->height == box->height) { + if (b->z == box->z && b->depth == box->depth) { + if (b->x == box->x + box->width) { + b->x -= box->width; + return; + } + if (b->x + b->width == box->x) { + b->width += box->width; + return; + } + } else if (b->x == box->x && b->width == box->width) { + if (b->z == box->z + box->depth) { + b->z -= box->depth; + return; + } + if (b->z + b->depth == box->z) { + b->depth += box->depth; + return; + } + } + } + + /* try to merge into region */ + if (box->x <= b->x && box->x + box->width >= b->x + b->width && + box->y <= b->y && box->y + box->height >= b->y + b->height && + box->z <= b->z && box->z + box->depth >= b->z + b->depth) + return; + + break; + } + } + } util_dynarray_append(&res->obj->copies[level], struct pipe_box, *box); + if (util_dynarray_num_elements(&res->obj->copies[level], struct pipe_box) > 100) + mesa_logw("zink: PERF WARNING! > 100 copy boxes detected for %p\n", res); res->obj->copies_valid = true; } -- 2.7.4