From 3da798c9f1b463f514cf058577fe38561810ba74 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 23 Aug 2019 13:48:28 +0200 Subject: [PATCH] anv: prepare driver to report submission error through queues When we will submit to i915 from a submission thread, we won't be able to directly report the error to the user (in particular through the debug report callbacks). So prepare 2 paths to report errors device -> notifying the user immediately, queue -> notifying the user the next time an entry point is called. In this change we still report directly for both paths, this will change in the next commit. v2: Split NULL batch parameter handling in anv_queue_submit_simple_batch() in a different commit Signed-off-by: Lionel Landwerlin Reviewed-by: Jason Ekstrand --- src/intel/vulkan/anv_batch_chain.c | 5 +++-- src/intel/vulkan/anv_device.c | 26 ++++++++++++++++++++++++-- src/intel/vulkan/anv_private.h | 24 ++++++++++++++++-------- src/intel/vulkan/anv_queue.c | 27 ++++++++++++++++----------- src/intel/vulkan/genX_state.c | 2 +- 5 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c index b16fd818fd2..5720859a674 100644 --- a/src/intel/vulkan/anv_batch_chain.c +++ b/src/intel/vulkan/anv_batch_chain.c @@ -1614,7 +1614,7 @@ setup_empty_execbuf(struct anv_execbuf *execbuf, struct anv_device *device) } VkResult -anv_cmd_buffer_execbuf(struct anv_device *device, +anv_cmd_buffer_execbuf(struct anv_queue *queue, struct anv_cmd_buffer *cmd_buffer, const VkSemaphore *in_semaphores, uint32_t num_in_semaphores, @@ -1623,6 +1623,7 @@ anv_cmd_buffer_execbuf(struct anv_device *device, VkFence _fence) { ANV_FROM_HANDLE(anv_fence, fence, _fence); + struct anv_device *device = queue->device; UNUSED struct anv_physical_device *pdevice = &device->instance->physicalDevice; struct anv_execbuf execbuf; @@ -1792,7 +1793,7 @@ anv_cmd_buffer_execbuf(struct anv_device *device, if (need_out_fence) execbuf.execbuf.flags |= I915_EXEC_FENCE_OUT; - result = anv_device_execbuf(device, &execbuf.execbuf, execbuf.bos); + result = anv_queue_execbuf(queue, &execbuf.execbuf, execbuf.bos); /* Execbuf does not consume the in_fence. It's our job to close it. */ if (in_fence != -1) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 3e1e6e1c804..61448d8dbdd 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -2871,7 +2871,7 @@ _anv_device_set_lost(struct anv_device *device, VkResult err; va_list ap; - device->_lost = true; + p_atomic_inc(&device->_lost); va_start(ap, msg); err = __vk_errorv(device->instance, device, @@ -2885,6 +2885,28 @@ _anv_device_set_lost(struct anv_device *device, return err; } +VkResult +_anv_queue_set_lost(struct anv_queue *queue, + const char *file, int line, + const char *msg, ...) +{ + VkResult err; + va_list ap; + + p_atomic_inc(&queue->device->_lost); + + va_start(ap, msg); + err = __vk_errorv(queue->device->instance, queue->device, + VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, + VK_ERROR_DEVICE_LOST, file, line, msg, ap); + va_end(ap); + + if (env_var_as_boolean("ANV_ABORT_ON_DEVICE_LOSS", false)) + abort(); + + return err; +} + VkResult anv_device_query_status(struct anv_device *device) { @@ -2963,7 +2985,7 @@ VkResult anv_DeviceWaitIdle( if (anv_device_is_lost(device)) return VK_ERROR_DEVICE_LOST; - return anv_device_submit_simple_batch(device, NULL); + return anv_queue_submit_simple_batch(&device->queue, NULL); } bool diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 5dc0af64d37..ff28d897a21 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -69,6 +69,7 @@ typedef struct xcb_connection_t xcb_connection_t; typedef uint32_t xcb_visualid_t; typedef uint32_t xcb_window_t; +struct anv_batch; struct anv_buffer; struct anv_buffer_view; struct anv_image_view; @@ -1181,7 +1182,7 @@ struct anv_device { pthread_mutex_t mutex; pthread_cond_t queue_submit; - bool _lost; + int _lost; struct gen_batch_decode_ctx decoder_ctx; /* @@ -1231,22 +1232,26 @@ anv_mocs_for_bo(const struct anv_device *device, const struct anv_bo *bo) void anv_device_init_blorp(struct anv_device *device); void anv_device_finish_blorp(struct anv_device *device); +void _anv_device_set_all_queue_lost(struct anv_device *device); VkResult _anv_device_set_lost(struct anv_device *device, const char *file, int line, const char *msg, ...) anv_printflike(4, 5); +VkResult _anv_queue_set_lost(struct anv_queue *queue, + const char *file, int line, + const char *msg, ...) + anv_printflike(4, 5); #define anv_device_set_lost(dev, ...) \ _anv_device_set_lost(dev, __FILE__, __LINE__, __VA_ARGS__) +#define anv_queue_set_lost(queue, ...) \ + _anv_queue_set_lost(queue, __FILE__, __LINE__, __VA_ARGS__) static inline bool anv_device_is_lost(struct anv_device *device) { - return unlikely(device->_lost); + return unlikely(p_atomic_read(&device->_lost)); } -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); @@ -1313,6 +1318,11 @@ VkResult anv_device_wait(struct anv_device *device, struct anv_bo *bo, VkResult anv_queue_init(struct anv_device *device, struct anv_queue *queue); void anv_queue_finish(struct anv_queue *queue); +VkResult anv_queue_execbuf(struct anv_queue *queue, + struct drm_i915_gem_execbuffer2 *execbuf, + struct anv_bo **execbuf_bos); +VkResult anv_queue_submit_simple_batch(struct anv_queue *queue, + struct anv_batch *batch); uint64_t anv_gettime_ns(void); uint64_t anv_get_absolute_timeout(uint64_t timeout); @@ -1427,8 +1437,6 @@ void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords); void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other); uint64_t anv_batch_emit_reloc(struct anv_batch *batch, void *location, struct anv_bo *bo, uint32_t offset); -VkResult anv_device_submit_simple_batch(struct anv_device *device, - struct anv_batch *batch); static inline VkResult anv_batch_set_error(struct anv_batch *batch, VkResult error) @@ -2636,7 +2644,7 @@ void anv_cmd_buffer_end_batch_buffer(struct anv_cmd_buffer *cmd_buffer); void anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary, struct anv_cmd_buffer *secondary); void anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer); -VkResult anv_cmd_buffer_execbuf(struct anv_device *device, +VkResult anv_cmd_buffer_execbuf(struct anv_queue *queue, struct anv_cmd_buffer *cmd_buffer, const VkSemaphore *in_semaphores, uint32_t num_in_semaphores, diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c index dbe2febaef7..8bf58e3214a 100644 --- a/src/intel/vulkan/anv_queue.c +++ b/src/intel/vulkan/anv_queue.c @@ -77,14 +77,15 @@ static int64_t anv_get_relative_timeout(uint64_t abs_timeout) } VkResult -anv_device_execbuf(struct anv_device *device, - struct drm_i915_gem_execbuffer2 *execbuf, - struct anv_bo **execbuf_bos) +anv_queue_execbuf(struct anv_queue *queue, + struct drm_i915_gem_execbuffer2 *execbuf, + struct anv_bo **execbuf_bos) { + struct anv_device *device = queue->device; int ret = device->no_hw ? 0 : anv_gem_execbuffer(device, execbuf); if (ret != 0) { /* We don't know the real error. */ - return anv_device_set_lost(device, "execbuf2 failed: %m"); + return anv_queue_set_lost(queue, "execbuf2 failed: %m"); } struct drm_i915_gem_exec_object2 *objects = @@ -114,9 +115,10 @@ anv_queue_finish(struct anv_queue *queue) } VkResult -anv_device_submit_simple_batch(struct anv_device *device, - struct anv_batch *batch) +anv_queue_submit_simple_batch(struct anv_queue *queue, + struct anv_batch *batch) { + struct anv_device *device = queue->device; struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 exec2_objects[1]; struct anv_bo *bo; @@ -166,7 +168,7 @@ anv_device_submit_simple_batch(struct anv_device *device, bo->size, bo->offset, false); } - result = anv_device_execbuf(device, &execbuf, &bo); + result = anv_queue_execbuf(queue, &execbuf, &bo); if (result != VK_SUCCESS) goto fail; @@ -232,7 +234,7 @@ VkResult anv_QueueSubmit( * come up with something more efficient but this shouldn't be a * common case. */ - result = anv_cmd_buffer_execbuf(device, NULL, NULL, 0, NULL, 0, fence); + result = anv_cmd_buffer_execbuf(queue, NULL, NULL, 0, NULL, 0, fence); goto out; } @@ -246,7 +248,7 @@ VkResult anv_QueueSubmit( * come up with something more efficient but this shouldn't be a * common case. */ - result = anv_cmd_buffer_execbuf(device, NULL, + result = anv_cmd_buffer_execbuf(queue, NULL, pSubmits[i].pWaitSemaphores, pSubmits[i].waitSemaphoreCount, pSubmits[i].pSignalSemaphores, @@ -283,7 +285,7 @@ VkResult anv_QueueSubmit( num_out_semaphores = pSubmits[i].signalSemaphoreCount; } - result = anv_cmd_buffer_execbuf(device, cmd_buffer, + result = anv_cmd_buffer_execbuf(queue, cmd_buffer, in_semaphores, num_in_semaphores, out_semaphores, num_out_semaphores, execbuf_fence); @@ -321,7 +323,10 @@ VkResult anv_QueueWaitIdle( { ANV_FROM_HANDLE(anv_queue, queue, _queue); - return anv_DeviceWaitIdle(anv_device_to_handle(queue->device)); + if (anv_device_is_lost(queue->device)) + return VK_ERROR_DEVICE_LOST; + + return anv_queue_submit_simple_batch(queue, NULL); } VkResult anv_CreateFence( diff --git a/src/intel/vulkan/genX_state.c b/src/intel/vulkan/genX_state.c index df76b33a7c3..cd0ced4d163 100644 --- a/src/intel/vulkan/genX_state.c +++ b/src/intel/vulkan/genX_state.c @@ -325,7 +325,7 @@ genX(init_device_state)(struct anv_device *device) assert(batch.next <= batch.end); - return anv_device_submit_simple_batch(device, &batch); + return anv_queue_submit_simple_batch(&device->queue, &batch); } static uint32_t -- 2.30.2