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 <lionel.g.landwerlin@intel.com> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
@@ -1614,7 +1614,7 @@ setup_empty_execbuf(struct anv_execbuf *execbuf, struct anv_device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkResult
|
VkResult
|
||||||
anv_cmd_buffer_execbuf(struct anv_device *device,
|
anv_cmd_buffer_execbuf(struct anv_queue *queue,
|
||||||
struct anv_cmd_buffer *cmd_buffer,
|
struct anv_cmd_buffer *cmd_buffer,
|
||||||
const VkSemaphore *in_semaphores,
|
const VkSemaphore *in_semaphores,
|
||||||
uint32_t num_in_semaphores,
|
uint32_t num_in_semaphores,
|
||||||
@@ -1623,6 +1623,7 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
|
|||||||
VkFence _fence)
|
VkFence _fence)
|
||||||
{
|
{
|
||||||
ANV_FROM_HANDLE(anv_fence, fence, _fence);
|
ANV_FROM_HANDLE(anv_fence, fence, _fence);
|
||||||
|
struct anv_device *device = queue->device;
|
||||||
UNUSED struct anv_physical_device *pdevice = &device->instance->physicalDevice;
|
UNUSED struct anv_physical_device *pdevice = &device->instance->physicalDevice;
|
||||||
|
|
||||||
struct anv_execbuf execbuf;
|
struct anv_execbuf execbuf;
|
||||||
@@ -1792,7 +1793,7 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
|
|||||||
if (need_out_fence)
|
if (need_out_fence)
|
||||||
execbuf.execbuf.flags |= I915_EXEC_FENCE_OUT;
|
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. */
|
/* Execbuf does not consume the in_fence. It's our job to close it. */
|
||||||
if (in_fence != -1)
|
if (in_fence != -1)
|
||||||
|
@@ -2871,7 +2871,7 @@ _anv_device_set_lost(struct anv_device *device,
|
|||||||
VkResult err;
|
VkResult err;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
device->_lost = true;
|
p_atomic_inc(&device->_lost);
|
||||||
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
err = __vk_errorv(device->instance, device,
|
err = __vk_errorv(device->instance, device,
|
||||||
@@ -2885,6 +2885,28 @@ _anv_device_set_lost(struct anv_device *device,
|
|||||||
return err;
|
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
|
VkResult
|
||||||
anv_device_query_status(struct anv_device *device)
|
anv_device_query_status(struct anv_device *device)
|
||||||
{
|
{
|
||||||
@@ -2963,7 +2985,7 @@ VkResult anv_DeviceWaitIdle(
|
|||||||
if (anv_device_is_lost(device))
|
if (anv_device_is_lost(device))
|
||||||
return VK_ERROR_DEVICE_LOST;
|
return VK_ERROR_DEVICE_LOST;
|
||||||
|
|
||||||
return anv_device_submit_simple_batch(device, NULL);
|
return anv_queue_submit_simple_batch(&device->queue, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@@ -69,6 +69,7 @@ typedef struct xcb_connection_t xcb_connection_t;
|
|||||||
typedef uint32_t xcb_visualid_t;
|
typedef uint32_t xcb_visualid_t;
|
||||||
typedef uint32_t xcb_window_t;
|
typedef uint32_t xcb_window_t;
|
||||||
|
|
||||||
|
struct anv_batch;
|
||||||
struct anv_buffer;
|
struct anv_buffer;
|
||||||
struct anv_buffer_view;
|
struct anv_buffer_view;
|
||||||
struct anv_image_view;
|
struct anv_image_view;
|
||||||
@@ -1181,7 +1182,7 @@ struct anv_device {
|
|||||||
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t queue_submit;
|
pthread_cond_t queue_submit;
|
||||||
bool _lost;
|
int _lost;
|
||||||
|
|
||||||
struct gen_batch_decode_ctx decoder_ctx;
|
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_init_blorp(struct anv_device *device);
|
||||||
void anv_device_finish_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,
|
VkResult _anv_device_set_lost(struct anv_device *device,
|
||||||
const char *file, int line,
|
const char *file, int line,
|
||||||
const char *msg, ...)
|
const char *msg, ...)
|
||||||
anv_printflike(4, 5);
|
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, ...) \
|
#define anv_device_set_lost(dev, ...) \
|
||||||
_anv_device_set_lost(dev, __FILE__, __LINE__, __VA_ARGS__)
|
_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
|
static inline bool
|
||||||
anv_device_is_lost(struct anv_device *device)
|
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);
|
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);
|
VkResult anv_queue_init(struct anv_device *device, struct anv_queue *queue);
|
||||||
void anv_queue_finish(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_gettime_ns(void);
|
||||||
uint64_t anv_get_absolute_timeout(uint64_t timeout);
|
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);
|
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
|
||||||
uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
|
uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
|
||||||
void *location, struct anv_bo *bo, uint32_t offset);
|
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
|
static inline VkResult
|
||||||
anv_batch_set_error(struct anv_batch *batch, VkResult error)
|
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,
|
void anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary,
|
||||||
struct anv_cmd_buffer *secondary);
|
struct anv_cmd_buffer *secondary);
|
||||||
void anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer);
|
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,
|
struct anv_cmd_buffer *cmd_buffer,
|
||||||
const VkSemaphore *in_semaphores,
|
const VkSemaphore *in_semaphores,
|
||||||
uint32_t num_in_semaphores,
|
uint32_t num_in_semaphores,
|
||||||
|
@@ -77,14 +77,15 @@ static int64_t anv_get_relative_timeout(uint64_t abs_timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkResult
|
VkResult
|
||||||
anv_device_execbuf(struct anv_device *device,
|
anv_queue_execbuf(struct anv_queue *queue,
|
||||||
struct drm_i915_gem_execbuffer2 *execbuf,
|
struct drm_i915_gem_execbuffer2 *execbuf,
|
||||||
struct anv_bo **execbuf_bos)
|
struct anv_bo **execbuf_bos)
|
||||||
{
|
{
|
||||||
|
struct anv_device *device = queue->device;
|
||||||
int ret = device->no_hw ? 0 : anv_gem_execbuffer(device, execbuf);
|
int ret = device->no_hw ? 0 : anv_gem_execbuffer(device, execbuf);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
/* We don't know the real error. */
|
/* 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 =
|
struct drm_i915_gem_exec_object2 *objects =
|
||||||
@@ -114,9 +115,10 @@ anv_queue_finish(struct anv_queue *queue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkResult
|
VkResult
|
||||||
anv_device_submit_simple_batch(struct anv_device *device,
|
anv_queue_submit_simple_batch(struct anv_queue *queue,
|
||||||
struct anv_batch *batch)
|
struct anv_batch *batch)
|
||||||
{
|
{
|
||||||
|
struct anv_device *device = queue->device;
|
||||||
struct drm_i915_gem_execbuffer2 execbuf;
|
struct drm_i915_gem_execbuffer2 execbuf;
|
||||||
struct drm_i915_gem_exec_object2 exec2_objects[1];
|
struct drm_i915_gem_exec_object2 exec2_objects[1];
|
||||||
struct anv_bo *bo;
|
struct anv_bo *bo;
|
||||||
@@ -166,7 +168,7 @@ anv_device_submit_simple_batch(struct anv_device *device,
|
|||||||
bo->size, bo->offset, false);
|
bo->size, bo->offset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = anv_device_execbuf(device, &execbuf, &bo);
|
result = anv_queue_execbuf(queue, &execbuf, &bo);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@@ -232,7 +234,7 @@ VkResult anv_QueueSubmit(
|
|||||||
* come up with something more efficient but this shouldn't be a
|
* come up with something more efficient but this shouldn't be a
|
||||||
* common case.
|
* 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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +248,7 @@ VkResult anv_QueueSubmit(
|
|||||||
* come up with something more efficient but this shouldn't be a
|
* come up with something more efficient but this shouldn't be a
|
||||||
* common case.
|
* common case.
|
||||||
*/
|
*/
|
||||||
result = anv_cmd_buffer_execbuf(device, NULL,
|
result = anv_cmd_buffer_execbuf(queue, NULL,
|
||||||
pSubmits[i].pWaitSemaphores,
|
pSubmits[i].pWaitSemaphores,
|
||||||
pSubmits[i].waitSemaphoreCount,
|
pSubmits[i].waitSemaphoreCount,
|
||||||
pSubmits[i].pSignalSemaphores,
|
pSubmits[i].pSignalSemaphores,
|
||||||
@@ -283,7 +285,7 @@ VkResult anv_QueueSubmit(
|
|||||||
num_out_semaphores = pSubmits[i].signalSemaphoreCount;
|
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,
|
in_semaphores, num_in_semaphores,
|
||||||
out_semaphores, num_out_semaphores,
|
out_semaphores, num_out_semaphores,
|
||||||
execbuf_fence);
|
execbuf_fence);
|
||||||
@@ -321,7 +323,10 @@ VkResult anv_QueueWaitIdle(
|
|||||||
{
|
{
|
||||||
ANV_FROM_HANDLE(anv_queue, queue, _queue);
|
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(
|
VkResult anv_CreateFence(
|
||||||
|
@@ -325,7 +325,7 @@ genX(init_device_state)(struct anv_device *device)
|
|||||||
|
|
||||||
assert(batch.next <= batch.end);
|
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
|
static uint32_t
|
||||||
|
Reference in New Issue
Block a user