From f195d40eca49800799d85d110939a125041f4028 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 5 Apr 2017 09:55:15 -0700 Subject: [PATCH] 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 --- 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 356b1b5f0d2..35ef4c486b2 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -1327,6 +1327,31 @@ anv_device_query_status(struct anv_device *device) return VK_SUCCESS; } +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 2d07a3dbb0e..185086fefcc 100644 --- a/src/intel/vulkan/anv_gem.c +++ b/src/intel/vulkan/anv_gem.c @@ -146,6 +146,23 @@ anv_gem_set_domain(struct anv_device *device, uint32_t gem_handle, return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &gem_set_domain); } +/** + * 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. */ diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 95666d8f4b6..5e07808985a 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); -- 2.30.2