iris: fix aux buf map failure in 32bits app on Android
[mesa.git] / src / gallium / drivers / iris / iris_fence.c
index 2ab11b80697bfa4f87a31e3da32e81864bd7737e..dbd2d8265881eefc84ca02bfd4cc3592eea5876a 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include "util/u_inlines.h"
+#include "intel/common/gen_gem.h"
 
 #include "iris_batch.h"
 #include "iris_bufmgr.h"
@@ -41,7 +42,7 @@ gem_syncobj_create(int fd, uint32_t flags)
       .flags = flags,
    };
 
-   drm_ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args);
+   gen_ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &args);
 
    return args.handle;
 }
@@ -53,7 +54,7 @@ gem_syncobj_destroy(int fd, uint32_t handle)
       .handle = handle,
    };
 
-   drm_ioctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args);
+   gen_ioctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args);
 }
 
 /**
@@ -93,7 +94,7 @@ iris_batch_add_syncpt(struct iris_batch *batch,
                       unsigned flags)
 {
    struct drm_i915_gem_exec_fence *fence =
-      util_dynarray_grow(&batch->exec_fences, sizeof(*fence));
+      util_dynarray_grow(&batch->exec_fences, struct drm_i915_gem_exec_fence, 1);
 
    *fence = (struct drm_i915_gem_exec_fence) {
       .handle = syncpt->handle,
@@ -101,7 +102,7 @@ iris_batch_add_syncpt(struct iris_batch *batch,
    };
 
    struct iris_syncpt **store =
-      util_dynarray_grow(&batch->syncpts, sizeof(*store));
+      util_dynarray_grow(&batch->syncpts, struct iris_syncpt *, 1);
 
    *store = NULL;
    iris_syncpt_reference(batch->screen, store, syncpt);
@@ -138,9 +139,10 @@ iris_fence_reference(struct pipe_screen *p_screen,
    *dst = src;
 }
 
-static bool
-check_syncpt(struct pipe_screen *p_screen,
-             struct iris_syncpt *syncpt)
+bool
+iris_wait_syncpt(struct pipe_screen *p_screen,
+                 struct iris_syncpt *syncpt,
+                 int64_t timeout_nsec)
 {
    if (!syncpt)
       return false;
@@ -149,8 +151,9 @@ check_syncpt(struct pipe_screen *p_screen,
    struct drm_syncobj_wait args = {
       .handles = (uintptr_t)&syncpt->handle,
       .count_handles = 1,
+      .timeout_nsec = timeout_nsec,
    };
-   return drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args);
+   return gen_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args);
 }
 
 static void
@@ -160,14 +163,10 @@ iris_fence_flush(struct pipe_context *ctx,
 {
    struct iris_screen *screen = (void *) ctx->screen;
    struct iris_context *ice = (struct iris_context *)ctx;
-   struct iris_batch *batch[IRIS_BATCH_COUNT] = {
-      &ice->render_batch,
-      &ice->compute_batch,
-   };
 
    /* XXX PIPE_FLUSH_DEFERRED */
-   for (unsigned i = 0; i < ARRAY_SIZE(batch); i++)
-      iris_batch_flush(batch[i]);
+   for (unsigned i = 0; i < IRIS_BATCH_COUNT; i++)
+      iris_batch_flush(&ice->batches[i]);
 
    if (!out_fence)
       return;
@@ -178,13 +177,15 @@ iris_fence_flush(struct pipe_context *ctx,
 
    pipe_reference_init(&fence->ref, 1);
 
-   for (unsigned b = 0; b < ARRAY_SIZE(batch); b++) {
-      if (!check_syncpt(ctx->screen, batch[b]->last_syncpt))
+   for (unsigned b = 0; b < IRIS_BATCH_COUNT; b++) {
+      if (!iris_wait_syncpt(ctx->screen, ice->batches[b].last_syncpt, 0))
          continue;
 
       iris_syncpt_reference(screen, &fence->syncpt[fence->count++],
-                            batch[b]->last_syncpt);
+                            ice->batches[b].last_syncpt);
    }
+
+   iris_fence_reference(ctx->screen, out_fence, NULL);
    *out_fence = fence;
 }
 
@@ -193,13 +194,10 @@ iris_fence_await(struct pipe_context *ctx,
                  struct pipe_fence_handle *fence)
 {
    struct iris_context *ice = (struct iris_context *)ctx;
-   struct iris_batch *batch[IRIS_BATCH_COUNT] = {
-      &ice->render_batch,
-      &ice->compute_batch,
-   };
-   for (unsigned b = 0; b < ARRAY_SIZE(batch); b++) {
+
+   for (unsigned b = 0; b < IRIS_BATCH_COUNT; b++) {
       for (unsigned i = 0; i < fence->count; i++) {
-         iris_batch_add_syncpt(batch[b], fence->syncpt[i],
+         iris_batch_add_syncpt(&ice->batches[b], fence->syncpt[i],
                                I915_EXEC_FENCE_WAIT);
       }
    }
@@ -210,27 +208,28 @@ iris_fence_await(struct pipe_context *ctx,
 #define MSEC_PER_SEC (1000)
 
 static uint64_t
-rel2abs(uint64_t timeout)
+gettime_ns(void)
 {
-   struct timespec ts;
-   uint64_t now;
+   struct timespec current;
+   clock_gettime(CLOCK_MONOTONIC, &current);
+   return (uint64_t)current.tv_sec * NSEC_PER_SEC + current.tv_nsec;
+}
 
-   if (!timeout)
+static uint64_t
+rel2abs(uint64_t timeout)
+{
+   if (timeout == 0)
       return 0;
 
-   if (timeout == PIPE_TIMEOUT_INFINITE)
-      return INT64_MAX;
+   uint64_t current_time = gettime_ns();
+   uint64_t max_timeout = (uint64_t) INT64_MAX - current_time;
 
-   clock_gettime(CLOCK_MONOTONIC, &ts);
-   now = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
+   timeout = MIN2(max_timeout, timeout);
 
-   if (now > INT64_MAX - timeout)
-      return INT64_MAX;
-
-   return now + timeout;
+   return current_time + timeout;
 }
 
-static boolean
+static bool
 iris_fence_finish(struct pipe_screen *p_screen,
                   struct pipe_context *ctx,
                   struct pipe_fence_handle *fence,
@@ -248,10 +247,10 @@ iris_fence_finish(struct pipe_screen *p_screen,
    struct drm_syncobj_wait args = {
       .handles = (uintptr_t)handles,
       .count_handles = fence->count,
-      .timeout_nsec = rel2abs(timeout), /* XXX */
+      .timeout_nsec = rel2abs(timeout),
       .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL
    };
-   return drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args) == 0;
+   return gen_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args) == 0;
 }
 
 #ifndef SYNC_IOC_MAGIC
@@ -287,7 +286,7 @@ sync_merge_fd(int sync_fd, int new_fd)
       .fence = -1,
    };
 
-   drm_ioctl(sync_fd, SYNC_IOC_MERGE, &args);
+   gen_ioctl(sync_fd, SYNC_IOC_MERGE, &args);
    close(new_fd);
    close(sync_fd);
 
@@ -301,6 +300,22 @@ iris_fence_get_fd(struct pipe_screen *p_screen,
    struct iris_screen *screen = (struct iris_screen *)p_screen;
    int fd = -1;
 
+   if (fence->count == 0) {
+      /* Our fence has no syncobj's recorded.  This means that all of the
+       * batches had already completed, their syncobj's had been signalled,
+       * and so we didn't bother to record them.  But we're being asked to
+       * export such a fence.  So export a dummy already-signalled syncobj.
+       */
+      struct drm_syncobj_handle args = {
+         .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE, .fd = -1,
+      };
+
+      args.handle = gem_syncobj_create(screen->fd, DRM_SYNCOBJ_CREATE_SIGNALED);
+      gen_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
+      gem_syncobj_destroy(screen->fd, args.handle);
+      return args.fd;
+   }
+
    for (unsigned i = 0; i < fence->count; i++) {
       struct drm_syncobj_handle args = {
          .handle = fence->syncpt[i]->handle,
@@ -308,7 +323,7 @@ iris_fence_get_fd(struct pipe_screen *p_screen,
          .fd = -1,
       };
 
-      drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
+      gen_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
       fd = sync_merge_fd(fd, args.fd);
    }
 
@@ -328,7 +343,12 @@ iris_fence_create_fd(struct pipe_context *ctx,
       .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
       .fd = fd,
    };
-   drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
+   if (gen_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args) == -1) {
+      fprintf(stderr, "DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE failed: %s\n",
+              strerror(errno));
+      *out = NULL;
+      return;
+   }
 
    struct iris_syncpt *syncpt = malloc(sizeof(*syncpt));
    syncpt->handle = args.handle;