vulkan/log: Add common vk_error and vk_errorf helpers
These helpers have quite a bit of smarts in them to log errors to chase the object chain as needed and log errors to roughly the appropriate object. For instance, VK_ERROR_OUT_OF_DEVICE_MEMORY always goes to a device while VK_ERROR_OUT_OF_HOST_MEMORY always goes to the instance. Tested-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13045>
This commit is contained in:

committed by
Marge Bot

parent
ec34ec388b
commit
0cad3beb2a
@@ -26,6 +26,7 @@
|
|||||||
#include "vk_debug_report.h"
|
#include "vk_debug_report.h"
|
||||||
|
|
||||||
#include "vk_command_buffer.h"
|
#include "vk_command_buffer.h"
|
||||||
|
#include "vk_enum_to_str.h"
|
||||||
#include "vk_queue.h"
|
#include "vk_queue.h"
|
||||||
#include "vk_device.h"
|
#include "vk_device.h"
|
||||||
#include "vk_physical_device.h"
|
#include "vk_physical_device.h"
|
||||||
@@ -247,3 +248,91 @@ __vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
|||||||
ralloc_free(message);
|
ralloc_free(message);
|
||||||
ralloc_free(message_idname);
|
ralloc_free(message_idname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct vk_object_base *
|
||||||
|
vk_object_for_error(struct vk_object_base *obj, VkResult error)
|
||||||
|
{
|
||||||
|
if (obj == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (error) {
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||||
|
case VK_ERROR_INITIALIZATION_FAILED:
|
||||||
|
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||||
|
case VK_ERROR_UNKNOWN:
|
||||||
|
return &vk_object_to_instance(obj)->base;
|
||||||
|
case VK_ERROR_FEATURE_NOT_PRESENT:
|
||||||
|
return &vk_object_to_physical_device(obj)->base;
|
||||||
|
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||||
|
case VK_ERROR_MEMORY_MAP_FAILED:
|
||||||
|
case VK_ERROR_TOO_MANY_OBJECTS:
|
||||||
|
return &vk_object_to_device(obj)->base;
|
||||||
|
default:
|
||||||
|
assert(obj->client_visible);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult
|
||||||
|
__vk_errorv_impl(const void *_obj, VkResult error,
|
||||||
|
const char *file, int line,
|
||||||
|
const char *format, va_list va)
|
||||||
|
{
|
||||||
|
struct vk_object_base *object = (struct vk_object_base *)_obj;
|
||||||
|
struct vk_instance *instance = vk_object_to_instance(object);
|
||||||
|
object = vk_object_for_error(object, error);
|
||||||
|
|
||||||
|
/* If object->client_visible isn't set then the object hasn't been fully
|
||||||
|
* constructed and we shouldn't hand it back to the client. This typically
|
||||||
|
* happens if an error is thrown during object construction. This is safe
|
||||||
|
* to do as long as vk_object_base_init() has already been called.
|
||||||
|
*/
|
||||||
|
if (object && !object->client_visible)
|
||||||
|
object = NULL;
|
||||||
|
|
||||||
|
const char *error_str = vk_Result_to_str(error);
|
||||||
|
|
||||||
|
if (format) {
|
||||||
|
char *message = ralloc_vasprintf(NULL, format, va);
|
||||||
|
|
||||||
|
if (object) {
|
||||||
|
__vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
|
||||||
|
VK_LOG_OBJS(object), file, line,
|
||||||
|
"%s (%s)", message, error_str);
|
||||||
|
} else {
|
||||||
|
__vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
|
||||||
|
VK_LOG_NO_OBJS(instance), file, line,
|
||||||
|
"%s (%s)", message, error_str);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (object) {
|
||||||
|
__vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
|
||||||
|
VK_LOG_OBJS(object), file, line,
|
||||||
|
"%s", error_str);
|
||||||
|
} else {
|
||||||
|
__vk_log(VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
||||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT,
|
||||||
|
VK_LOG_NO_OBJS(instance), file, line,
|
||||||
|
"%s", error_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult
|
||||||
|
__vk_errorf_impl(const void *_obj, VkResult error,
|
||||||
|
const char *file, int line,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
VkResult result = __vk_errorv_impl(_obj, error, file, line, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@@ -71,3 +71,27 @@ __vk_log_impl(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
|||||||
int line,
|
int line,
|
||||||
const char *format,
|
const char *format,
|
||||||
...);
|
...);
|
||||||
|
|
||||||
|
#define vk_error(obj, error) \
|
||||||
|
__vk_errorf_impl(obj, error, __FILE__, __LINE__, NULL)
|
||||||
|
|
||||||
|
#define vk_errorf(obj, error, ...) \
|
||||||
|
__vk_errorf_impl(obj, error, __FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
/* For now, the function is named __vk_errorf_impl and we use a macro to
|
||||||
|
* re-name it for any drivers which include this header. This is to prevent
|
||||||
|
* linking errors while we do the rework. We'll drop it once everyone is
|
||||||
|
* using the common log function.
|
||||||
|
*/
|
||||||
|
#define __vk_errorf(...) __vk_errorf_impl(__VA_ARGS__)
|
||||||
|
#define __vk_errorv(...) __vk_errorv_impl(__VA_ARGS__)
|
||||||
|
|
||||||
|
VkResult
|
||||||
|
__vk_errorv_impl(const void *_obj, VkResult error,
|
||||||
|
const char *file, int line,
|
||||||
|
const char *format, va_list va);
|
||||||
|
|
||||||
|
VkResult PRINTFLIKE(5, 6)
|
||||||
|
__vk_errorf_impl(const void *_obj, VkResult error,
|
||||||
|
const char *file, int line,
|
||||||
|
const char *format, ...);
|
||||||
|
Reference in New Issue
Block a user