Module: Mesa
Branch: main
Commit: 0d8a54f9137ea639eb2118ec4a6d309529593e75
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=0d8a54f9137ea639eb2118ec4a6d309529593e75

Author: Mike Blumenkrantz <[email protected]>
Date:   Mon Feb 27 18:57:04 2023 -0500

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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21665>

---

 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 60a81319034..5a2ff1ad56b 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;
 }
 

Reply via email to