Mesa (master): anv/device: Add a helper for querying whether a BO is busy

Jason Ekstrand jekstrand at kemper.freedesktop.org
Thu Apr 6 04:22:15 UTC 2017


Module: Mesa
Branch: master
Commit: f195d40eca49800799d85d110939a125041f4028
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f195d40eca49800799d85d110939a125041f4028

Author: Jason Ekstrand <jason.ekstrand at intel.com>
Date:   Wed Apr  5 09:55:15 2017 -0700

anv/device: Add a helper for querying whether a BO is busy

This is a bit more efficient than using GEM_WAIT with a timeout of 0.

Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

---

 src/intel/vulkan/anv_device.c  | 34 ++++++++++++++++++++++++++++------
 src/intel/vulkan/anv_gem.c     | 17 +++++++++++++++++
 src/intel/vulkan/anv_private.h |  2 ++
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index 356b1b5f0d..35ef4c486b 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -1328,6 +1328,31 @@ anv_device_query_status(struct anv_device *device)
 }
 
 VkResult
+anv_device_bo_busy(struct anv_device *device, struct anv_bo *bo)
+{
+   /* Note:  This only returns whether or not the BO is in use by an i915 GPU.
+    * Other usages of the BO (such as on different hardware) will not be
+    * flagged as "busy" by this ioctl.  Use with care.
+    */
+   int ret = anv_gem_busy(device, bo->gem_handle);
+   if (ret == 1) {
+      return VK_NOT_READY;
+   } else if (ret == -1) {
+      /* We don't know the real error. */
+      device->lost = true;
+      return vk_errorf(VK_ERROR_DEVICE_LOST, "gem wait failed: %m");
+   }
+
+   /* Query for device status after the busy call.  If the BO we're checking
+    * got caught in a GPU hang we don't want to return VK_SUCCESS to the
+    * client because it clearly doesn't have valid data.  Yes, this most
+    * likely means an ioctl, but we just did an ioctl to query the busy status
+    * so it's no great loss.
+    */
+   return anv_device_query_status(device);
+}
+
+VkResult
 anv_device_wait(struct anv_device *device, struct anv_bo *bo,
                 int64_t timeout)
 {
@@ -1906,14 +1931,11 @@ VkResult anv_GetFenceStatus(
       return VK_SUCCESS;
 
    case ANV_FENCE_STATE_SUBMITTED: {
-      VkResult result = anv_device_wait(device, &fence->bo, 0);
-      switch (result) {
-      case VK_SUCCESS:
+      VkResult result = anv_device_bo_busy(device, &fence->bo);
+      if (result == VK_SUCCESS) {
          fence->state = ANV_FENCE_STATE_SIGNALED;
          return VK_SUCCESS;
-      case VK_TIMEOUT:
-         return VK_NOT_READY;
-      default:
+      } else {
          return result;
       }
    }
diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c
index 2d07a3dbb0..185086fefc 100644
--- a/src/intel/vulkan/anv_gem.c
+++ b/src/intel/vulkan/anv_gem.c
@@ -147,6 +147,23 @@ anv_gem_set_domain(struct anv_device *device, uint32_t gem_handle,
 }
 
 /**
+ * Returns 0, 1, or negative to indicate error
+ */
+int
+anv_gem_busy(struct anv_device *device, uint32_t gem_handle)
+{
+   struct drm_i915_gem_busy busy = {
+      .handle = gem_handle,
+   };
+
+   int ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
+   if (ret < 0)
+      return ret;
+
+   return busy.busy != 0;
+}
+
+/**
  * On error, \a timeout_ns holds the remaining time.
  */
 int
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 95666d8f4b..5e07808985 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -644,6 +644,7 @@ VkResult anv_device_execbuf(struct anv_device *device,
                             struct drm_i915_gem_execbuffer2 *execbuf,
                             struct anv_bo **execbuf_bos);
 VkResult anv_device_query_status(struct anv_device *device);
+VkResult anv_device_bo_busy(struct anv_device *device, struct anv_bo *bo);
 VkResult anv_device_wait(struct anv_device *device, struct anv_bo *bo,
                          int64_t timeout);
 
@@ -653,6 +654,7 @@ void anv_gem_munmap(void *p, uint64_t size);
 uint32_t anv_gem_create(struct anv_device *device, size_t size);
 void anv_gem_close(struct anv_device *device, uint32_t gem_handle);
 uint32_t anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
+int anv_gem_busy(struct anv_device *device, uint32_t gem_handle);
 int anv_gem_wait(struct anv_device *device, uint32_t gem_handle, int64_t *timeout_ns);
 int anv_gem_execbuffer(struct anv_device *device,
                        struct drm_i915_gem_execbuffer2 *execbuf);




More information about the mesa-commit mailing list