vulkan: Pull the device lost framework from ANV

It's a bit on the over-complicated side but the objective is to make the
debug log messages show up in the same thread as the first
VK_ERROR_DEVICE_LOST so we don't massively confuse the app.  It's
unknown if this is actually ever a problem but, with submit happening
off on its own thread, logging errors from threads the client doesn't
know about doesn't seem like a massively great plan.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Acked-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13427>
This commit is contained in:
Jason Ekstrand 2021-10-19 18:32:28 -05:00
parent e6b4678fdb
commit dd89ef96d7
5 changed files with 126 additions and 0 deletions

View File

@ -189,6 +189,10 @@ Core Mesa environment variables
overrides the WSI present mode clients specify in
``VkSwapchainCreateInfoKHR::presentMode``. Values can be ``fifo``,
``relaxed``, ``mailbox`` or ``immediate``.
:envvar:`MESA_VK_ABORT_ON_DEVICE_LOSS`
causes the Vulkan driver to call abort() immediately after detecting a
lost device. This is extremely useful when testing as it prevents the
test suite from continuing on with a lost device.
:envvar:`MESA_LOADER_DRIVER_OVERRIDE`
chooses a different driver binary such as ``etnaviv`` or ``zink``.

View File

@ -29,6 +29,7 @@
#include "vk_physical_device.h"
#include "vk_queue.h"
#include "vk_util.h"
#include "util/debug.h"
#include "util/hash_table.h"
#include "util/ralloc.h"
@ -117,6 +118,45 @@ vk_device_finish(UNUSED struct vk_device *device)
vk_object_base_finish(&device->base);
}
void
_vk_device_report_lost(struct vk_device *device)
{
assert(p_atomic_read(&device->_lost.lost) > 0);
device->_lost.reported = true;
vk_foreach_queue(queue, device) {
if (queue->_lost.lost) {
__vk_errorf(queue, VK_ERROR_DEVICE_LOST,
queue->_lost.error_file, queue->_lost.error_line,
"%s", queue->_lost.error_msg);
}
}
}
VkResult
_vk_device_set_lost(struct vk_device *device,
const char *file, int line,
const char *msg, ...)
{
/* This flushes out any per-queue device lost messages */
if (vk_device_is_lost(device))
return VK_ERROR_DEVICE_LOST;
p_atomic_inc(&device->_lost.lost);
device->_lost.reported = true;
va_list ap;
va_start(ap, msg);
__vk_errorv(device, VK_ERROR_DEVICE_LOST, file, line, msg, ap);
va_end(ap);
if (env_var_as_boolean("MESA_VK_ABORT_ON_DEVICE_LOSS", false))
abort();
return VK_ERROR_DEVICE_LOST;
}
PFN_vkVoidFunction
vk_device_get_proc_addr(const struct vk_device *device,
const char *name)

View File

@ -28,6 +28,7 @@
#include "vk_object.h"
#include "util/list.h"
#include "util/u_atomic.h"
#ifdef __cplusplus
extern "C" {
@ -47,6 +48,11 @@ struct vk_device {
struct list_head queues;
struct {
int lost;
bool reported;
} _lost;
#ifdef ANDROID
mtx_t swapchain_private_mtx;
struct hash_table *swapchain_private;
@ -66,6 +72,31 @@ vk_device_init(struct vk_device *device,
void
vk_device_finish(struct vk_device *device);
VkResult PRINTFLIKE(4, 5)
_vk_device_set_lost(struct vk_device *device,
const char *file, int line,
const char *msg, ...);
#define vk_device_set_lost(device, ...) \
_vk_device_set_lost(device, __FILE__, __LINE__, __VA_ARGS__)
void _vk_device_report_lost(struct vk_device *device);
static inline bool
vk_device_is_lost_no_report(struct vk_device *device)
{
return p_atomic_read(&device->_lost.lost) > 0;
}
static inline bool
vk_device_is_lost(struct vk_device *device)
{
int lost = vk_device_is_lost_no_report(device);
if (unlikely(lost && !device->_lost.reported))
_vk_device_report_lost(device);
return lost;
}
PFN_vkVoidFunction
vk_device_get_proc_addr(const struct vk_device *device,
const char *name);

View File

@ -23,6 +23,8 @@
#include "vk_queue.h"
#include "util/debug.h"
#include "vk_device.h"
VkResult
@ -54,3 +56,30 @@ vk_queue_finish(struct vk_queue *queue)
list_del(&queue->link);
vk_object_base_finish(&queue->base);
}
VkResult
_vk_queue_set_lost(struct vk_queue *queue,
const char *file, int line,
const char *msg, ...)
{
if (queue->_lost.lost)
return VK_ERROR_DEVICE_LOST;
queue->_lost.lost = true;
queue->_lost.error_file = file;
queue->_lost.error_line = line;
va_list ap;
va_start(ap, msg);
vsnprintf(queue->_lost.error_msg, sizeof(queue->_lost.error_msg), msg, ap);
va_end(ap);
p_atomic_inc(&queue->base.device->_lost.lost);
if (env_var_as_boolean("MESA_VK_ABORT_ON_DEVICE_LOSS", false)) {
_vk_device_report_lost(queue->base.device);
abort();
}
return VK_ERROR_DEVICE_LOST;
}

View File

@ -48,6 +48,14 @@ struct vk_queue {
/* Which queue this is within the queue family */
uint32_t index_in_family;
struct {
/* Only set once atomically by the queue */
int lost;
int error_line;
const char *error_file;
char error_msg[80];
} _lost;
/**
* VK_EXT_debug_utils
*
@ -99,6 +107,20 @@ vk_queue_init(struct vk_queue *queue, struct vk_device *device,
void
vk_queue_finish(struct vk_queue *queue);
VkResult PRINTFLIKE(4, 5)
_vk_queue_set_lost(struct vk_queue *queue,
const char *file, int line,
const char *msg, ...);
#define vk_queue_set_lost(queue, ...) \
_vk_queue_set_lost(queue, __FILE__, __LINE__, __VA_ARGS__)
static inline bool
vk_queue_is_lost(struct vk_queue *queue)
{
return queue->_lost.lost;
}
#define vk_foreach_queue(queue, device) \
list_for_each_entry(struct vk_queue, queue, &(device)->queues, link)