The use of the bionic toolchain (DETECT_OS_ANDROID) does not mean that the typical set of Android libraries (nativewindow, gralloc) are used on the system. Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36829>
499 lines
17 KiB
C
499 lines
17 KiB
C
/*
|
|
* Copyright © 2021 Intel Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "vk_debug_utils.h"
|
|
|
|
#include "vk_common_entrypoints.h"
|
|
#include "vk_command_buffer.h"
|
|
#include "vk_device.h"
|
|
#include "vk_queue.h"
|
|
#include "vk_object.h"
|
|
#include "vk_alloc.h"
|
|
#include "vk_util.h"
|
|
#include "stdarg.h"
|
|
#include "util/u_dynarray.h"
|
|
#include "util/u_printf.h"
|
|
|
|
void
|
|
vk_debug_message(struct vk_instance *instance,
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
|
VkDebugUtilsMessageTypeFlagsEXT types,
|
|
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
|
|
{
|
|
mtx_lock(&instance->debug_utils.callbacks_mutex);
|
|
|
|
list_for_each_entry(struct vk_debug_utils_messenger, messenger,
|
|
&instance->debug_utils.callbacks, link) {
|
|
if ((messenger->severity & severity) &&
|
|
(messenger->type & types))
|
|
messenger->callback(severity, types, pCallbackData, messenger->data);
|
|
}
|
|
|
|
mtx_unlock(&instance->debug_utils.callbacks_mutex);
|
|
}
|
|
|
|
/* This function intended to be used by the drivers to report a
|
|
* message to the special messenger, provided in the pNext chain while
|
|
* creating an instance. It's only meant to be used during
|
|
* vkCreateInstance or vkDestroyInstance calls.
|
|
*/
|
|
void
|
|
vk_debug_message_instance(struct vk_instance *instance,
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT severity,
|
|
VkDebugUtilsMessageTypeFlagsEXT types,
|
|
const char *pMessageIdName,
|
|
int32_t messageIdNumber,
|
|
const char *pMessage)
|
|
{
|
|
if (list_is_empty(&instance->debug_utils.instance_callbacks))
|
|
return;
|
|
|
|
const VkDebugUtilsMessengerCallbackDataEXT cbData = {
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
|
|
.pMessageIdName = pMessageIdName,
|
|
.messageIdNumber = messageIdNumber,
|
|
.pMessage = pMessage,
|
|
};
|
|
|
|
list_for_each_entry(struct vk_debug_utils_messenger, messenger,
|
|
&instance->debug_utils.instance_callbacks, link) {
|
|
if ((messenger->severity & severity) &&
|
|
(messenger->type & types))
|
|
messenger->callback(severity, types, &cbData, messenger->data);
|
|
}
|
|
}
|
|
|
|
void
|
|
vk_address_binding_report(struct vk_instance *instance,
|
|
struct vk_object_base *object,
|
|
uint64_t base_address,
|
|
uint64_t size,
|
|
VkDeviceAddressBindingTypeEXT type)
|
|
{
|
|
if (list_is_empty(&instance->debug_utils.callbacks))
|
|
return;
|
|
|
|
VkDeviceAddressBindingCallbackDataEXT addr_binding = {
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_ADDRESS_BINDING_CALLBACK_DATA_EXT,
|
|
.flags = object->client_visible ? 0 : VK_DEVICE_ADDRESS_BINDING_INTERNAL_OBJECT_BIT_EXT,
|
|
.baseAddress = base_address,
|
|
.size = size,
|
|
.bindingType = type,
|
|
};
|
|
|
|
VkDebugUtilsObjectNameInfoEXT object_name_info = {
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
|
.pNext = NULL,
|
|
.objectType = object->type,
|
|
.objectHandle = (uint64_t)(uintptr_t)object,
|
|
.pObjectName = object->object_name,
|
|
};
|
|
|
|
VkDebugUtilsMessengerCallbackDataEXT cb_data = {
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT,
|
|
.pNext = &addr_binding,
|
|
.objectCount = 1,
|
|
.pObjects = &object_name_info,
|
|
};
|
|
|
|
vk_debug_message(instance, VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
|
|
VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT,
|
|
&cb_data);
|
|
}
|
|
|
|
void
|
|
vk_emit_device_memory_report(struct vk_device* device,
|
|
VkDeviceMemoryReportEventTypeEXT type,
|
|
uint64_t mem_obj_id,
|
|
VkDeviceSize size,
|
|
VkObjectType obj_type,
|
|
uint64_t obj_handle,
|
|
uint32_t heap_index)
|
|
{
|
|
assert(device->memory_reports);
|
|
|
|
const VkDeviceMemoryReportCallbackDataEXT report = {
|
|
.sType = VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT,
|
|
.type = type,
|
|
.memoryObjectId = mem_obj_id,
|
|
.size = size,
|
|
.objectType = obj_type,
|
|
.objectHandle = obj_handle,
|
|
.heapIndex = heap_index,
|
|
};
|
|
|
|
for (uint32_t i = 0; i < device->memory_report_count; i++)
|
|
device->memory_reports[i].callback(&report, device->memory_reports[i].data);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
vk_common_CreateDebugUtilsMessengerEXT(
|
|
VkInstance _instance,
|
|
const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkDebugUtilsMessengerEXT *pMessenger)
|
|
{
|
|
VK_FROM_HANDLE(vk_instance, instance, _instance);
|
|
|
|
struct vk_debug_utils_messenger *messenger =
|
|
vk_alloc2(&instance->alloc, pAllocator,
|
|
sizeof(struct vk_debug_utils_messenger), 8,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
if (!messenger)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
if (pAllocator)
|
|
messenger->alloc = *pAllocator;
|
|
else
|
|
messenger->alloc = instance->alloc;
|
|
|
|
vk_object_base_init(NULL, &messenger->base,
|
|
VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
|
|
|
|
messenger->severity = pCreateInfo->messageSeverity;
|
|
messenger->type = pCreateInfo->messageType;
|
|
messenger->callback = pCreateInfo->pfnUserCallback;
|
|
messenger->data = pCreateInfo->pUserData;
|
|
|
|
mtx_lock(&instance->debug_utils.callbacks_mutex);
|
|
list_addtail(&messenger->link, &instance->debug_utils.callbacks);
|
|
mtx_unlock(&instance->debug_utils.callbacks_mutex);
|
|
|
|
*pMessenger = vk_debug_utils_messenger_to_handle(messenger);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_SubmitDebugUtilsMessageEXT(
|
|
VkInstance _instance,
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
|
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
|
|
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData)
|
|
{
|
|
VK_FROM_HANDLE(vk_instance, instance, _instance);
|
|
|
|
vk_debug_message(instance, messageSeverity, messageTypes, pCallbackData);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_DestroyDebugUtilsMessengerEXT(
|
|
VkInstance _instance,
|
|
VkDebugUtilsMessengerEXT _messenger,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
VK_FROM_HANDLE(vk_instance, instance, _instance);
|
|
VK_FROM_HANDLE(vk_debug_utils_messenger, messenger, _messenger);
|
|
|
|
if (messenger == NULL)
|
|
return;
|
|
|
|
mtx_lock(&instance->debug_utils.callbacks_mutex);
|
|
list_del(&messenger->link);
|
|
mtx_unlock(&instance->debug_utils.callbacks_mutex);
|
|
|
|
vk_object_base_finish(&messenger->base);
|
|
vk_free2(&instance->alloc, pAllocator, messenger);
|
|
}
|
|
|
|
static VkResult
|
|
vk_common_set_object_name_locked(
|
|
struct vk_device *device,
|
|
const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
|
|
{
|
|
if (unlikely(device->swapchain_name == NULL)) {
|
|
/* Even though VkSwapchain/Surface are non-dispatchable objects, we know
|
|
* a priori that these are actually pointers so we can use
|
|
* the pointer hash table for them.
|
|
*/
|
|
device->swapchain_name = _mesa_pointer_hash_table_create(NULL);
|
|
if (device->swapchain_name == NULL)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
char *object_name = vk_strdup(&device->alloc, pNameInfo->pObjectName,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (object_name == NULL)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
struct hash_entry *entry =
|
|
_mesa_hash_table_search(device->swapchain_name,
|
|
(void *)(uintptr_t)pNameInfo->objectHandle);
|
|
if (unlikely(entry == NULL)) {
|
|
entry = _mesa_hash_table_insert(device->swapchain_name,
|
|
(void *)(uintptr_t)pNameInfo->objectHandle,
|
|
object_name);
|
|
if (entry == NULL) {
|
|
vk_free(&device->alloc, object_name);
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
} else {
|
|
vk_free(&device->alloc, entry->data);
|
|
entry->data = object_name;
|
|
}
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
vk_common_DebugMarkerSetObjectNameEXT(
|
|
VkDevice _device,
|
|
const VkDebugMarkerObjectNameInfoEXT *pNameInfo)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
assert(pNameInfo->sType == VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT);
|
|
|
|
VkObjectType object_type;
|
|
switch (pNameInfo->objectType) {
|
|
case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT:
|
|
object_type = VK_OBJECT_TYPE_SURFACE_KHR;
|
|
break;
|
|
case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT:
|
|
object_type = VK_OBJECT_TYPE_SWAPCHAIN_KHR;
|
|
break;
|
|
case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT:
|
|
object_type = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT;
|
|
break;
|
|
case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT:
|
|
object_type = VK_OBJECT_TYPE_DISPLAY_KHR;
|
|
break;
|
|
case VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT:
|
|
object_type = VK_OBJECT_TYPE_DISPLAY_MODE_KHR;
|
|
break;
|
|
case VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT:
|
|
object_type = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT;
|
|
break;
|
|
default:
|
|
object_type = (VkObjectType)pNameInfo->objectType;
|
|
break;
|
|
}
|
|
|
|
VkDebugUtilsObjectNameInfoEXT name_info = {
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
|
.objectType = object_type,
|
|
.objectHandle = pNameInfo->object,
|
|
.pObjectName = pNameInfo->pObjectName,
|
|
};
|
|
|
|
return device->dispatch_table.SetDebugUtilsObjectNameEXT(_device, &name_info);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
vk_common_SetDebugUtilsObjectNameEXT(
|
|
VkDevice _device,
|
|
const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
|
|
{
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
|
if (pNameInfo->objectType == VK_OBJECT_TYPE_SWAPCHAIN_KHR ||
|
|
pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
|
|
#else
|
|
if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {
|
|
#endif
|
|
mtx_lock(&device->swapchain_name_mtx);
|
|
VkResult res = vk_common_set_object_name_locked(device, pNameInfo);
|
|
mtx_unlock(&device->swapchain_name_mtx);
|
|
return res;
|
|
}
|
|
|
|
struct vk_object_base *object =
|
|
vk_object_base_from_u64_handle(pNameInfo->objectHandle,
|
|
pNameInfo->objectType);
|
|
|
|
assert(object->device != NULL || object->instance != NULL);
|
|
VkAllocationCallbacks *alloc = object->device != NULL ?
|
|
&object->device->alloc : &object->instance->alloc;
|
|
if (object->object_name) {
|
|
vk_free(alloc, object->object_name);
|
|
object->object_name = NULL;
|
|
}
|
|
if (pNameInfo->pObjectName != NULL) {
|
|
object->object_name = vk_strdup(alloc, pNameInfo->pObjectName,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!object->object_name)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
vk_common_SetDebugUtilsObjectTagEXT(
|
|
VkDevice _device,
|
|
const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
|
|
{
|
|
/* no-op */
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static void
|
|
vk_common_append_debug_label(struct vk_device *device,
|
|
struct util_dynarray *labels,
|
|
const VkDebugUtilsLabelEXT *pLabelInfo)
|
|
{
|
|
util_dynarray_append(labels, VkDebugUtilsLabelEXT, *pLabelInfo);
|
|
VkDebugUtilsLabelEXT *current_label =
|
|
util_dynarray_top_ptr(labels, VkDebugUtilsLabelEXT);
|
|
current_label->pLabelName =
|
|
vk_strdup(&device->alloc, current_label->pLabelName,
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
}
|
|
|
|
static void
|
|
vk_common_pop_debug_label(struct vk_device *device,
|
|
struct util_dynarray *labels)
|
|
{
|
|
if (labels->size == 0)
|
|
return;
|
|
|
|
VkDebugUtilsLabelEXT previous_label =
|
|
util_dynarray_pop(labels, VkDebugUtilsLabelEXT);
|
|
vk_free(&device->alloc, (void *)previous_label.pLabelName);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_CmdBeginDebugUtilsLabelEXT(
|
|
VkCommandBuffer _commandBuffer,
|
|
const VkDebugUtilsLabelEXT *pLabelInfo)
|
|
{
|
|
VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
|
|
|
|
/* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
|
|
* should remove it first.
|
|
*/
|
|
if (!command_buffer->region_begin) {
|
|
vk_common_pop_debug_label(command_buffer->base.device,
|
|
&command_buffer->labels);
|
|
}
|
|
|
|
vk_common_append_debug_label(command_buffer->base.device,
|
|
&command_buffer->labels,
|
|
pLabelInfo);
|
|
command_buffer->region_begin = true;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_CmdEndDebugUtilsLabelEXT(VkCommandBuffer _commandBuffer)
|
|
{
|
|
VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
|
|
|
|
/* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
|
|
* should remove it first.
|
|
*/
|
|
if (!command_buffer->region_begin) {
|
|
vk_common_pop_debug_label(command_buffer->base.device,
|
|
&command_buffer->labels);
|
|
}
|
|
|
|
vk_common_pop_debug_label(command_buffer->base.device,
|
|
&command_buffer->labels);
|
|
command_buffer->region_begin = true;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_CmdInsertDebugUtilsLabelEXT(
|
|
VkCommandBuffer _commandBuffer,
|
|
const VkDebugUtilsLabelEXT *pLabelInfo)
|
|
{
|
|
VK_FROM_HANDLE(vk_command_buffer, command_buffer, _commandBuffer);
|
|
|
|
/* If the latest label was submitted by CmdInsertDebugUtilsLabelEXT, we
|
|
* should remove it first.
|
|
*/
|
|
if (!command_buffer->region_begin) {
|
|
vk_common_append_debug_label(command_buffer->base.device,
|
|
&command_buffer->labels,
|
|
pLabelInfo);
|
|
}
|
|
|
|
vk_common_append_debug_label(command_buffer->base.device,
|
|
&command_buffer->labels,
|
|
pLabelInfo);
|
|
command_buffer->region_begin = false;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_QueueBeginDebugUtilsLabelEXT(
|
|
VkQueue _queue,
|
|
const VkDebugUtilsLabelEXT *pLabelInfo)
|
|
{
|
|
VK_FROM_HANDLE(vk_queue, queue, _queue);
|
|
|
|
/* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
|
|
* should remove it first.
|
|
*/
|
|
if (!queue->region_begin)
|
|
(void)util_dynarray_pop(&queue->labels, VkDebugUtilsLabelEXT);
|
|
|
|
vk_common_append_debug_label(queue->base.device,
|
|
&queue->labels,
|
|
pLabelInfo);
|
|
queue->region_begin = true;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_QueueEndDebugUtilsLabelEXT(VkQueue _queue)
|
|
{
|
|
VK_FROM_HANDLE(vk_queue, queue, _queue);
|
|
|
|
/* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
|
|
* should remove it first.
|
|
*/
|
|
if (!queue->region_begin)
|
|
vk_common_pop_debug_label(queue->base.device, &queue->labels);
|
|
|
|
vk_common_pop_debug_label(queue->base.device, &queue->labels);
|
|
queue->region_begin = true;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
vk_common_QueueInsertDebugUtilsLabelEXT(
|
|
VkQueue _queue,
|
|
const VkDebugUtilsLabelEXT *pLabelInfo)
|
|
{
|
|
VK_FROM_HANDLE(vk_queue, queue, _queue);
|
|
|
|
/* If the latest label was submitted by QueueInsertDebugUtilsLabelEXT, we
|
|
* should remove it first.
|
|
*/
|
|
if (!queue->region_begin)
|
|
vk_common_pop_debug_label(queue->base.device, &queue->labels);
|
|
|
|
vk_common_append_debug_label(queue->base.device,
|
|
&queue->labels,
|
|
pLabelInfo);
|
|
queue->region_begin = false;
|
|
}
|
|
|
|
VkResult
|
|
vk_check_printf_status(struct vk_device *dev, struct u_printf_ctx *ctx)
|
|
{
|
|
if (u_printf_check_abort(stdout, ctx)) {
|
|
vk_device_set_lost(dev, "GPU abort.");
|
|
return VK_ERROR_DEVICE_LOST;
|
|
} else {
|
|
return VK_SUCCESS;
|
|
}
|
|
}
|