summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2019-07-08 16:12:29 -0700
committerChia-I Wu <[email protected]>2019-07-09 14:26:55 -0700
commit6ca1bbabbe27a5005c69f1dd4c69fe0fe7feb807 (patch)
treec30dbd168550057faeb0f703f870f386940bf3f2
parent2b2093961eeb7b9d70573fde33eb8b87d5a6f35f (diff)
virgl: fix some false positives in transfers_overlap
Rewrite the function and check z/depth more carefully. We intentionally avoid u_box_test_intersection_2d because it returns true when two boxes touch but do not intersect and can be confusing. Signed-off-by: Chia-I Wu <[email protected]> Reviewed-by: Alexandros Frantzis <[email protected]>
-rw-r--r--src/gallium/drivers/virgl/virgl_transfer_queue.c113
1 files changed, 86 insertions, 27 deletions
diff --git a/src/gallium/drivers/virgl/virgl_transfer_queue.c b/src/gallium/drivers/virgl/virgl_transfer_queue.c
index 970ee986cc1..53fa6760e3b 100644
--- a/src/gallium/drivers/virgl/virgl_transfer_queue.c
+++ b/src/gallium/drivers/virgl/virgl_transfer_queue.c
@@ -53,6 +53,90 @@ struct list_iteration_args
enum virgl_transfer_queue_lists type;
};
+static int
+transfer_dim(const struct virgl_transfer *xfer)
+{
+ switch (xfer->base.resource->target) {
+ case PIPE_BUFFER:
+ case PIPE_TEXTURE_1D:
+ return 1;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
+ return 2;
+ default:
+ return 3;
+ }
+}
+
+static void
+box_min_max(const struct pipe_box *box, int dim, int *min, int *max)
+{
+ switch (dim) {
+ case 0:
+ if (box->width > 0) {
+ *min = box->x;
+ *max = box->x + box->width;
+ } else {
+ *max = box->x;
+ *min = box->x + box->width;
+ }
+ break;
+ case 1:
+ if (box->height > 0) {
+ *min = box->y;
+ *max = box->y + box->height;
+ } else {
+ *max = box->y;
+ *min = box->y + box->height;
+ }
+ break;
+ default:
+ if (box->depth > 0) {
+ *min = box->z;
+ *max = box->z + box->depth;
+ } else {
+ *max = box->z;
+ *min = box->z + box->depth;
+ }
+ break;
+ }
+}
+
+static bool
+transfer_overlap(const struct virgl_transfer *xfer,
+ const struct virgl_hw_res *hw_res,
+ unsigned level,
+ const struct pipe_box *box,
+ bool include_touching)
+{
+ const int dim_count = transfer_dim(xfer);
+
+ if (xfer->hw_res != hw_res || xfer->base.level != level)
+ return false;
+
+ for (int dim = 0; dim < dim_count; dim++) {
+ int xfer_min;
+ int xfer_max;
+ int box_min;
+ int box_max;
+
+ box_min_max(&xfer->base.box, dim, &xfer_min, &xfer_max);
+ box_min_max(box, dim, &box_min, &box_max);
+
+ if (include_touching) {
+ /* touching is considered overlapping */
+ if (xfer_min > box_max || xfer_max < box_min)
+ return false;
+ } else {
+ /* touching is not considered overlapping */
+ if (xfer_min >= box_max || xfer_max <= box_min)
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool transfers_intersect(struct virgl_transfer *queued,
struct virgl_transfer *current)
{
@@ -68,33 +152,8 @@ static bool transfers_intersect(struct virgl_transfer *queued,
static bool transfers_overlap(struct virgl_transfer *queued,
struct virgl_transfer *current)
{
- boolean tmp;
-
- if (queued->hw_res != current->hw_res)
- return false;
-
- if (queued->base.level != current->base.level)
- return false;
-
- if (queued->base.box.z != current->base.box.z)
- return true;
-
- if (queued->base.box.depth != 1 || current->base.box.depth != 1)
- return true;
-
- /*
- * Special case for boxes with [x: 0, width: 1] and [x: 1, width: 1].
- */
- if (queued->base.resource->target == PIPE_BUFFER) {
- if (queued->base.box.x + queued->base.box.width == current->base.box.x)
- return false;
-
- if (current->base.box.x + current->base.box.width == queued->base.box.x)
- return false;
- }
-
- tmp = u_box_test_intersection_2d(&queued->base.box, &current->base.box);
- return (tmp == TRUE);
+ return transfer_overlap(queued, current->hw_res, current->base.level,
+ &current->base.box, false);
}
static void set_true(UNUSED struct virgl_transfer_queue *queue,