Implement initial VK_EXT_debug_utils changes
This affects the loader, scripts, and layers and introduces the
changes to support the VK_EXT_debug_utils extension.
Change-Id: Ia5336f63e85b00f1e59416c06aacd4ae331fd692
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 1f1ec3b..51223dc 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -144,7 +144,8 @@
struct instance_layer_data {
VkInstance instance = VK_NULL_HANDLE;
debug_report_data *report_data = nullptr;
- std::vector<VkDebugReportCallbackEXT> logging_callback;
+ vector<VkDebugReportCallbackEXT> logging_callback;
+ vector<VkDebugUtilsMessengerEXT> logging_messenger;
VkLayerInstanceDispatchTable dispatch_table;
CALL_STATE vkEnumeratePhysicalDevicesState = UNCALLED;
@@ -2032,7 +2033,9 @@
}
static void init_core_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
- layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation");
+ layer_debug_report_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_core_validation");
+ layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator,
+ "lunarg_core_validation");
}
// For the given ValidationCheck enum, set all relevant instance disabled flags to true
@@ -2070,7 +2073,7 @@
instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(*pInstance), instance_layer_data_map);
instance_data->instance = *pInstance;
layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr);
- instance_data->report_data = debug_report_create_instance(
+ instance_data->report_data = debug_utils_create_instance(
&instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
instance_data->api_version = instance_data->extensions.InitFromInstanceCreateInfo(
@@ -2098,13 +2101,18 @@
lock_guard_t lock(global_lock);
// Clean up logging callback, if any
+ while (instance_data->logging_messenger.size() > 0) {
+ VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back();
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
+ instance_data->logging_messenger.pop_back();
+ }
while (instance_data->logging_callback.size() > 0) {
VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
- layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
instance_data->logging_callback.pop_back();
}
- layer_debug_report_destroy_instance(instance_data->report_data);
+ layer_debug_utils_destroy_instance(instance_data->report_data);
FreeLayerDataPtr(key, instance_layer_data_map);
}
@@ -2277,7 +2285,7 @@
// Save PhysicalDevice handle
device_data->physical_device = gpu;
- device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
+ device_data->report_data = layer_debug_utils_create_device(instance_data->report_data, *pDevice);
// Get physical device limits for this device
instance_data->dispatch_table.GetPhysicalDeviceProperties(gpu, &(device_data->phys_dev_properties.properties));
@@ -2342,7 +2350,7 @@
// Queues persist until device is destroyed
dev_data->queueMap.clear();
// Report any memory leaks
- layer_debug_report_destroy_device(device);
+ layer_debug_utils_destroy_device(device);
lock.unlock();
#if DISPATCH_MAP_DEBUG
@@ -11713,6 +11721,107 @@
return result;
}
+// VK_EXT_debug_utils commands
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ VkResult result = VK_SUCCESS;
+ if (pNameInfo->pObjectName) {
+ dev_data->report_data->debugUtilsObjectNameMap->insert(
+ std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName));
+ } else {
+ dev_data->report_data->debugUtilsObjectNameMap->erase(pNameInfo->objectHandle);
+ }
+ if (nullptr != dev_data->dispatch_table.SetDebugUtilsObjectNameEXT) {
+ result = dev_data->dispatch_table.SetDebugUtilsObjectNameEXT(device, pNameInfo);
+ }
+ return result;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ VkResult result = VK_SUCCESS;
+ if (nullptr != dev_data->dispatch_table.SetDebugUtilsObjectTagEXT) {
+ result = dev_data->dispatch_table.SetDebugUtilsObjectTagEXT(device, pTagInfo);
+ }
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueBeginDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
+ BeginQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo);
+ if (nullptr != dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueEndDebugUtilsLabelEXT(VkQueue queue) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
+ if (nullptr != dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT(queue);
+ }
+ EndQueueDebugUtilsLabel(dev_data->report_data, queue);
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueInsertDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
+ InsertQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo);
+ if (nullptr != dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
+ BeginCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo);
+ if (nullptr != dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
+ if (nullptr != dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT(commandBuffer);
+ }
+ EndCmdDebugUtilsLabel(dev_data->report_data, commandBuffer);
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
+ InsertCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo);
+ if (nullptr != dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
+ VkResult result = instance_data->dispatch_table.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+
+ if (VK_SUCCESS == result) {
+ result = layer_create_messenger_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMessenger);
+ }
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
+ instance_data->dispatch_table.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
+}
+
+VKAPI_ATTR void VKAPI_CALL SubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
+ instance_data->dispatch_table.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
+}
+
+// VK_EXT_debug_report commands
VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
@@ -11721,7 +11830,7 @@
VkResult res = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (VK_SUCCESS == res) {
lock_guard_t lock(global_lock);
- res = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
+ res = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
return res;
}
@@ -11731,7 +11840,7 @@
instance_layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
lock_guard_t lock(global_lock);
- layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, msgCallback, pAllocator);
}
VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
@@ -12388,6 +12497,17 @@
{"vkMergeValidationCachesEXT", (void *)MergeValidationCachesEXT},
{"vkCmdSetDiscardRectangleEXT", (void *)CmdSetDiscardRectangleEXT},
{"vkCmdSetSampleLocationsEXT", (void *)CmdSetSampleLocationsEXT},
+ {"vkSetDebugUtilsObjectNameEXT", (void *)SetDebugUtilsObjectNameEXT},
+ {"vkSetDebugUtilsObjectTagEXT", (void *)SetDebugUtilsObjectTagEXT},
+ {"vkQueueBeginDebugUtilsLabelEXT", (void *)QueueBeginDebugUtilsLabelEXT},
+ {"vkQueueEndDebugUtilsLabelEXT", (void *)QueueEndDebugUtilsLabelEXT},
+ {"vkQueueInsertDebugUtilsLabelEXT", (void *)QueueInsertDebugUtilsLabelEXT},
+ {"vkCmdBeginDebugUtilsLabelEXT", (void *)CmdBeginDebugUtilsLabelEXT},
+ {"vkCmdEndDebugUtilsLabelEXT", (void *)CmdEndDebugUtilsLabelEXT},
+ {"vkCmdInsertDebugUtilsLabelEXT", (void *)CmdInsertDebugUtilsLabelEXT},
+ {"vkCreateDebugUtilsMessengerEXT", (void *)CreateDebugUtilsMessengerEXT},
+ {"vkDestroyDebugUtilsMessengerEXT", (void *)DestroyDebugUtilsMessengerEXT},
+ {"vkSubmitDebugUtilsMessageEXT", (void *)SubmitDebugUtilsMessageEXT},
};
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
diff --git a/layers/object_tracker.h b/layers/object_tracker.h
index d9fdf8b..5a6f545 100644
--- a/layers/object_tracker.h
+++ b/layers/object_tracker.h
@@ -35,7 +35,6 @@
#include "vk_layer_table.h"
#include "vk_object_types.h"
#include "vulkan/vk_layer.h"
-#include "vk_object_types.h"
#include "vk_enum_string_helper.h"
#include "vk_layer_extension_utils.h"
#include "vk_layer_table.h"
@@ -96,11 +95,15 @@
debug_report_data *report_data;
std::vector<VkDebugReportCallbackEXT> logging_callback;
+ std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
// The following are for keeping track of the temporary callbacks that can
// be used in vkCreateInstance and vkDestroyInstance:
- uint32_t num_tmp_callbacks;
- VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
- VkDebugReportCallbackEXT *tmp_callbacks;
+ uint32_t num_tmp_report_callbacks;
+ VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
+ VkDebugReportCallbackEXT *tmp_report_callbacks;
+ uint32_t num_tmp_debug_messengers;
+ VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
+ VkDebugUtilsMessengerEXT *tmp_debug_messengers;
std::vector<VkQueueFamilyProperties> queue_family_properties;
@@ -119,9 +122,12 @@
num_objects{},
num_total_objects(0),
report_data(nullptr),
- num_tmp_callbacks(0),
- tmp_dbg_create_infos(nullptr),
- tmp_callbacks(nullptr),
+ num_tmp_report_callbacks(0),
+ tmp_report_create_infos(nullptr),
+ tmp_report_callbacks(nullptr),
+ num_tmp_debug_messengers(0),
+ tmp_messenger_create_infos(nullptr),
+ tmp_debug_messengers(nullptr),
object_map{},
dispatch_table{} {
object_map.resize(kVulkanObjectTypeMax + 1);
diff --git a/layers/object_tracker_utils.cpp b/layers/object_tracker_utils.cpp
index c9573dd..177c145 100644
--- a/layers/object_tracker_utils.cpp
+++ b/layers/object_tracker_utils.cpp
@@ -32,7 +32,8 @@
uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
void InitObjectTracker(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
- layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_object_tracker");
+ layer_debug_report_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_object_tracker");
+ layer_debug_messenger_actions(my_data->report_data, my_data->logging_messenger, pAllocator, "lunarg_object_tracker");
}
// Add new queue to head of global queue list
@@ -328,12 +329,13 @@
layer_data *instance_data = GetLayerDataPtr(key, layer_data_map);
// Enable the temporary callback(s) here to catch cleanup issues:
- bool callback_setup = false;
- if (instance_data->num_tmp_callbacks > 0) {
- if (!layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks,
- instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) {
- callback_setup = true;
- }
+ if (instance_data->num_tmp_debug_messengers > 0) {
+ layer_enable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers,
+ instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers);
+ }
+ if (instance_data->num_tmp_report_callbacks > 0) {
+ layer_enable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks,
+ instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks);
}
// TODO: The instance handle can not be validated here. The loader will likely have to validate it.
@@ -375,22 +377,32 @@
pInstanceTable->DestroyInstance(instance, pAllocator);
// Disable and cleanup the temporary callback(s):
- if (callback_setup) {
- layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks);
+ layer_disable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers,
+ instance_data->tmp_debug_messengers);
+ layer_disable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks,
+ instance_data->tmp_report_callbacks);
+ if (instance_data->num_tmp_debug_messengers > 0) {
+ layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers);
+ instance_data->num_tmp_debug_messengers = 0;
}
- if (instance_data->num_tmp_callbacks > 0) {
- layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks);
- instance_data->num_tmp_callbacks = 0;
+ if (instance_data->num_tmp_report_callbacks > 0) {
+ layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks);
+ instance_data->num_tmp_report_callbacks = 0;
}
// Clean up logging callback, if any
+ while (instance_data->logging_messenger.size() > 0) {
+ VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back();
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
+ instance_data->logging_messenger.pop_back();
+ }
while (instance_data->logging_callback.size() > 0) {
VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
- layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
instance_data->logging_callback.pop_back();
}
- layer_debug_report_destroy_instance(instance_data->report_data);
+ layer_debug_utils_destroy_instance(instance_data->report_data);
FreeLayerDataPtr(key, layer_data_map);
lock.unlock();
@@ -572,7 +584,7 @@
VkResult result = pInstanceTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
if (VK_SUCCESS == result) {
layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
- result = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pCallback);
+ result = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pCallback);
CreateObject(instance, *pCallback, kVulkanObjectTypeDebugReportCallbackEXT, pAllocator);
}
return result;
@@ -583,7 +595,7 @@
VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance);
pInstanceTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
- layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, msgCallback, pAllocator);
DestroyObject(instance, msgCallback, kVulkanObjectTypeDebugReportCallbackEXT, pAllocator, VALIDATION_ERROR_242009b4,
VALIDATION_ERROR_242009b6);
}
@@ -595,7 +607,159 @@
pInstanceTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
}
-static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
+// VK_EXT_debug_utils commands
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ if (skip) {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ if (pNameInfo->pObjectName) {
+ dev_data->report_data->debugUtilsObjectNameMap->insert(
+ std::make_pair<uint64_t, std::string>((uint64_t &&) pNameInfo->objectHandle, pNameInfo->pObjectName));
+ } else {
+ dev_data->report_data->debugUtilsObjectNameMap->erase(pNameInfo->objectHandle);
+ }
+ VkResult result = dev_data->dispatch_table.SetDebugUtilsObjectNameEXT(device, pNameInfo);
+ return result;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(device, device, kVulkanObjectTypeDevice, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ if (skip) {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ VkResult result = dev_data->dispatch_table.SetDebugUtilsObjectTagEXT(device, pTagInfo);
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueBeginDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(queue, queue, kVulkanObjectTypeQueue, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
+ if (!skip) {
+ BeginQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo);
+ if (dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.QueueBeginDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueEndDebugUtilsLabelEXT(VkQueue queue) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(queue, queue, kVulkanObjectTypeQueue, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
+ if (!skip) {
+ if (dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.QueueEndDebugUtilsLabelEXT(queue);
+ }
+ EndQueueDebugUtilsLabel(dev_data->report_data, queue);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL QueueInsertDebugUtilsLabelEXT(VkQueue queue, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(queue, queue, kVulkanObjectTypeQueue, false, VALIDATION_ERROR_UNDEFINED, VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(queue), layer_data_map);
+ if (!skip) {
+ InsertQueueDebugUtilsLabel(dev_data->report_data, queue, pLabelInfo);
+ if (dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.QueueInsertDebugUtilsLabelEXT(queue, pLabelInfo);
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false, VALIDATION_ERROR_UNDEFINED,
+ VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
+ if (!skip) {
+ BeginCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo);
+ if (dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.CmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false, VALIDATION_ERROR_UNDEFINED,
+ VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
+ if (!skip) {
+ if (dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.CmdEndDebugUtilsLabelEXT(commandBuffer);
+ }
+ EndCmdDebugUtilsLabel(dev_data->report_data, commandBuffer);
+ }
+}
+
+VKAPI_ATTR void VKAPI_CALL CmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT *pLabelInfo) {
+ bool skip = VK_FALSE;
+ std::unique_lock<std::mutex> lock(global_lock);
+ skip |= ValidateObject(commandBuffer, commandBuffer, kVulkanObjectTypeCommandBuffer, false, VALIDATION_ERROR_UNDEFINED,
+ VALIDATION_ERROR_UNDEFINED);
+ lock.unlock();
+ layer_data *dev_data = GetLayerDataPtr(get_dispatch_key(commandBuffer), layer_data_map);
+ if (!skip) {
+ InsertCmdDebugUtilsLabel(dev_data->report_data, commandBuffer, pLabelInfo);
+ if (dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT) {
+ dev_data->dispatch_table.CmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
+ }
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance);
+ VkResult result = pInstanceTable->CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+ if (VK_SUCCESS == result) {
+ layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
+ result = layer_create_messenger_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMessenger);
+ CreateObject(instance, *pMessenger, kVulkanObjectTypeDebugUtilsMessengerEXT, pAllocator);
+ }
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance);
+ pInstanceTable->DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+ layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
+ DestroyObject(instance, messenger, kVulkanObjectTypeDebugUtilsMessengerEXT, pAllocator, VALIDATION_ERROR_UNDEFINED,
+ VALIDATION_ERROR_UNDEFINED);
+}
+
+VKAPI_ATTR void VKAPI_CALL SubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ot_instance_table_map, instance);
+ pInstanceTable->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
+}
+
+static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
+ {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
static const VkLayerProperties globalLayerProps = {"VK_LAYER_LUNARG_object_tracker",
VK_LAYER_API_VERSION, // specVersion
@@ -656,7 +820,7 @@
}
layer_data *device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
- device_data->report_data = layer_debug_report_create_device(phy_dev_data->report_data, *pDevice);
+ device_data->report_data = layer_debug_utils_create_device(phy_dev_data->report_data, *pDevice);
layer_init_device_dispatch_table(*pDevice, &device_data->dispatch_table, fpGetDeviceProcAddr);
// Add link back to physDev
@@ -779,11 +943,13 @@
// Look for one or more debug report create info structures, and copy the
// callback(s) for each one found (for use by vkDestroyInstance)
- layer_copy_tmp_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_callbacks, &instance_data->tmp_dbg_create_infos,
- &instance_data->tmp_callbacks);
+ layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &instance_data->num_tmp_debug_messengers,
+ &instance_data->tmp_messenger_create_infos, &instance_data->tmp_debug_messengers);
+ layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_report_callbacks,
+ &instance_data->tmp_report_create_infos, &instance_data->tmp_report_callbacks);
- instance_data->report_data = debug_report_create_instance(pInstanceTable, *pInstance, pCreateInfo->enabledExtensionCount,
- pCreateInfo->ppEnabledExtensionNames);
+ instance_data->report_data = debug_utils_create_instance(pInstanceTable, *pInstance, pCreateInfo->enabledExtensionCount,
+ pCreateInfo->ppEnabledExtensionNames);
InitObjectTracker(instance_data, pAllocator);
diff --git a/layers/parameter_validation.h b/layers/parameter_validation.h
index 49ff279..d03152c 100644
--- a/layers/parameter_validation.h
+++ b/layers/parameter_validation.h
@@ -61,12 +61,17 @@
debug_report_data *report_data = nullptr;
std::vector<VkDebugReportCallbackEXT> logging_callback;
+ std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
// The following are for keeping track of the temporary callbacks that can
// be used in vkCreateInstance and vkDestroyInstance:
- uint32_t num_tmp_callbacks = 0;
- VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos = nullptr;
- VkDebugReportCallbackEXT *tmp_callbacks = nullptr;
+ uint32_t num_tmp_report_callbacks = 0;
+ VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos = nullptr;
+ VkDebugReportCallbackEXT *tmp_report_callbacks = nullptr;
+ uint32_t num_tmp_debug_messengers = 0;
+ VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos = nullptr;
+ VkDebugUtilsMessengerEXT *tmp_debug_messengers = nullptr;
+
InstanceExtensions extensions = {};
VkLayerInstanceDispatchTable dispatch_table = {};
uint32_t api_version;
diff --git a/layers/parameter_validation_utils.cpp b/layers/parameter_validation_utils.cpp
index b818159..3dfd27c 100644
--- a/layers/parameter_validation_utils.cpp
+++ b/layers/parameter_validation_utils.cpp
@@ -79,6 +79,12 @@
VkDebugReportCallbackEXT *pMsgCallback);
extern bool parameter_validation_vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback,
const VkAllocationCallbacks *pAllocator);
+extern bool parameter_validation_vkCreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger);
+extern bool parameter_validation_vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator);
extern bool parameter_validation_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool);
extern bool parameter_validation_vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
@@ -96,10 +102,14 @@
void InitializeManualParameterValidationFunctionPointers(void);
static void init_parameter_validation(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
- layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "lunarg_parameter_validation");
+ layer_debug_report_actions(instance_data->report_data, instance_data->logging_callback, pAllocator,
+ "lunarg_parameter_validation");
+ layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator,
+ "lunarg_parameter_validation");
}
-static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
+static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
+ {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
static const VkLayerProperties global_layer = {
"VK_LAYER_LUNARG_parameter_validation",
@@ -216,21 +226,39 @@
layer_init_instance_dispatch_table(*pInstance, &my_instance_data->dispatch_table, fpGetInstanceProcAddr);
my_instance_data->instance = *pInstance;
my_instance_data->report_data =
- debug_report_create_instance(&my_instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
- pCreateInfo->ppEnabledExtensionNames);
+ debug_utils_create_instance(&my_instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount,
+ pCreateInfo->ppEnabledExtensionNames);
// Look for one or more debug report create info structures
// and setup a callback(s) for each one found.
- if (!layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_instance_data->num_tmp_callbacks,
- &my_instance_data->tmp_dbg_create_infos, &my_instance_data->tmp_callbacks)) {
- if (my_instance_data->num_tmp_callbacks > 0) {
+ if (!layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &my_instance_data->num_tmp_debug_messengers,
+ &my_instance_data->tmp_messenger_create_infos,
+ &my_instance_data->tmp_debug_messengers)) {
+ if (my_instance_data->num_tmp_debug_messengers > 0) {
// Setup the temporary callback(s) here to catch early issues:
- if (layer_enable_tmp_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_callbacks,
- my_instance_data->tmp_dbg_create_infos, my_instance_data->tmp_callbacks)) {
+ if (layer_enable_tmp_debug_messengers(my_instance_data->report_data, my_instance_data->num_tmp_debug_messengers,
+ my_instance_data->tmp_messenger_create_infos,
+ my_instance_data->tmp_debug_messengers)) {
// Failure of setting up one or more of the callback.
// Therefore, clean up and don't use those callbacks:
- layer_free_tmp_callbacks(my_instance_data->tmp_dbg_create_infos, my_instance_data->tmp_callbacks);
- my_instance_data->num_tmp_callbacks = 0;
+ layer_free_tmp_debug_messengers(my_instance_data->tmp_messenger_create_infos,
+ my_instance_data->tmp_debug_messengers);
+ my_instance_data->num_tmp_debug_messengers = 0;
+ }
+ }
+ }
+ if (!layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &my_instance_data->num_tmp_report_callbacks,
+ &my_instance_data->tmp_report_create_infos, &my_instance_data->tmp_report_callbacks)) {
+ if (my_instance_data->num_tmp_report_callbacks > 0) {
+ // Setup the temporary callback(s) here to catch early issues:
+ if (layer_enable_tmp_report_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_report_callbacks,
+ my_instance_data->tmp_report_create_infos,
+ my_instance_data->tmp_report_callbacks)) {
+ // Failure of setting up one or more of the callback.
+ // Therefore, clean up and don't use those callbacks:
+ layer_free_tmp_report_callbacks(my_instance_data->tmp_report_create_infos,
+ my_instance_data->tmp_report_callbacks);
+ my_instance_data->num_tmp_report_callbacks = 0;
}
}
}
@@ -269,9 +297,13 @@
}
// Disable the tmp callbacks:
- if (my_instance_data->num_tmp_callbacks > 0) {
- layer_disable_tmp_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_callbacks,
- my_instance_data->tmp_callbacks);
+ if (my_instance_data->num_tmp_debug_messengers > 0) {
+ layer_disable_tmp_debug_messengers(my_instance_data->report_data, my_instance_data->num_tmp_debug_messengers,
+ my_instance_data->tmp_debug_messengers);
+ }
+ if (my_instance_data->num_tmp_report_callbacks > 0) {
+ layer_disable_tmp_report_callbacks(my_instance_data->report_data, my_instance_data->num_tmp_report_callbacks,
+ my_instance_data->tmp_report_callbacks);
}
}
@@ -286,9 +318,15 @@
// Enable the temporary callback(s) here to catch vkDestroyInstance issues:
bool callback_setup = false;
- if (instance_data->num_tmp_callbacks > 0) {
- if (!layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks,
- instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) {
+ if (instance_data->num_tmp_debug_messengers > 0) {
+ if (!layer_enable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers,
+ instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers)) {
+ callback_setup = true;
+ }
+ }
+ if (instance_data->num_tmp_report_callbacks > 0) {
+ if (!layer_enable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks,
+ instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks)) {
callback_setup = true;
}
}
@@ -297,24 +335,36 @@
// Disable and cleanup the temporary callback(s):
if (callback_setup) {
- layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks);
+ layer_disable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers,
+ instance_data->tmp_debug_messengers);
+ layer_disable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks,
+ instance_data->tmp_report_callbacks);
}
- if (instance_data->num_tmp_callbacks > 0) {
- layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks);
- instance_data->num_tmp_callbacks = 0;
+ if (instance_data->num_tmp_debug_messengers > 0) {
+ layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers);
+ instance_data->num_tmp_debug_messengers = 0;
+ }
+ if (instance_data->num_tmp_report_callbacks > 0) {
+ layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks);
+ instance_data->num_tmp_report_callbacks = 0;
}
if (!skip) {
instance_data->dispatch_table.DestroyInstance(instance, pAllocator);
// Clean up logging callback, if any
+ while (instance_data->logging_messenger.size() > 0) {
+ VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back();
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
+ instance_data->logging_messenger.pop_back();
+ }
while (instance_data->logging_callback.size() > 0) {
VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
- layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
instance_data->logging_callback.pop_back();
}
- layer_debug_report_destroy_instance(instance_data->report_data);
+ layer_debug_utils_destroy_instance(instance_data->report_data);
}
FreeLayerDataPtr(key, instance_layer_data_map);
@@ -330,7 +380,11 @@
auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
VkResult result = instance_data->dispatch_table.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (result == VK_SUCCESS) {
- result = layer_create_msg_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
+ result = layer_create_report_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
+ // If something happened during this call, clean up the message callback that was created earlier in the lower levels
+ if (VK_SUCCESS != result) {
+ instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, *pMsgCallback, pAllocator);
+ }
}
return result;
}
@@ -341,7 +395,36 @@
if (!skip) {
auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
instance_data->dispatch_table.DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
- layer_destroy_msg_callback(instance_data->report_data, msgCallback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, msgCallback, pAllocator);
+ }
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ bool skip = parameter_validation_vkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+ if (skip) return VK_ERROR_VALIDATION_FAILED_EXT;
+
+ auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
+ VkResult result = instance_data->dispatch_table.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+ if (VK_SUCCESS == result) {
+ result = layer_create_messenger_callback(instance_data->report_data, false, pCreateInfo, pAllocator, pMessenger);
+ // If something happened during this call, clean up the message callback that was created earlier in the lower levels
+ if (VK_SUCCESS != result) {
+ instance_data->dispatch_table.DestroyDebugUtilsMessengerEXT(instance, *pMessenger, pAllocator);
+ }
+ }
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ bool skip = parameter_validation_vkDestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+ if (!skip) {
+ auto instance_data = GetLayerDataPtr(get_dispatch_key(instance), instance_layer_data_map);
+ instance_data->dispatch_table.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
}
}
@@ -472,7 +555,7 @@
layer_data *my_device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
assert(my_device_data != nullptr);
- my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+ my_device_data->report_data = layer_debug_utils_create_device(my_instance_data->report_data, *pDevice);
layer_init_device_dispatch_table(*pDevice, &my_device_data->dispatch_table, fpGetDeviceProcAddr);
// Query and save physical device limits for this device
@@ -533,7 +616,7 @@
}
if (!skip) {
- layer_debug_report_destroy_device(device);
+ layer_debug_utils_destroy_device(device);
device_data->dispatch_table.DestroyDevice(device, pAllocator);
}
FreeLayerDataPtr(key, layer_data_map);
diff --git a/layers/threading.cpp b/layers/threading.cpp
index d27d75f..ce5f8e3 100644
--- a/layers/threading.cpp
+++ b/layers/threading.cpp
@@ -42,7 +42,8 @@
static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
static void initThreading(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
- layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "google_threading");
+ layer_debug_report_actions(my_data->report_data, my_data->logging_callback, pAllocator, "google_threading");
+ layer_debug_messenger_actions(my_data->report_data, my_data->logging_messenger, pAllocator, "google_threading");
}
VKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
@@ -67,14 +68,16 @@
my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
- my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
- pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
+ my_data->report_data = debug_utils_create_instance(my_data->instance_dispatch_table, *pInstance,
+ pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
initThreading(my_data, pAllocator);
// Look for one or more debug report create info structures, and copy the
// callback(s) for each one found (for use by vkDestroyInstance)
- layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos,
- &my_data->tmp_callbacks);
+ layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &my_data->num_tmp_debug_messengers, &my_data->tmp_messenger_create_infos,
+ &my_data->tmp_debug_messengers);
+ layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &my_data->num_tmp_report_callbacks, &my_data->tmp_report_create_infos,
+ &my_data->tmp_report_callbacks);
return result;
}
@@ -85,9 +88,15 @@
// Enable the temporary callback(s) here to catch cleanup issues:
bool callback_setup = false;
- if (my_data->num_tmp_callbacks > 0) {
- if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos,
- my_data->tmp_callbacks)) {
+ if (my_data->num_tmp_debug_messengers > 0) {
+ if (!layer_enable_tmp_debug_messengers(my_data->report_data, my_data->num_tmp_debug_messengers,
+ my_data->tmp_messenger_create_infos, my_data->tmp_debug_messengers)) {
+ callback_setup = true;
+ }
+ }
+ if (my_data->num_tmp_report_callbacks > 0) {
+ if (!layer_enable_tmp_report_callbacks(my_data->report_data, my_data->num_tmp_report_callbacks,
+ my_data->tmp_report_create_infos, my_data->tmp_report_callbacks)) {
callback_setup = true;
}
}
@@ -105,21 +114,31 @@
// Disable and cleanup the temporary callback(s):
if (callback_setup) {
- layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks);
+ layer_disable_tmp_debug_messengers(my_data->report_data, my_data->num_tmp_debug_messengers, my_data->tmp_debug_messengers);
+ layer_disable_tmp_report_callbacks(my_data->report_data, my_data->num_tmp_report_callbacks, my_data->tmp_report_callbacks);
}
- if (my_data->num_tmp_callbacks > 0) {
- layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks);
- my_data->num_tmp_callbacks = 0;
+ if (my_data->num_tmp_debug_messengers > 0) {
+ layer_free_tmp_debug_messengers(my_data->tmp_messenger_create_infos, my_data->tmp_debug_messengers);
+ my_data->num_tmp_debug_messengers = 0;
+ }
+ if (my_data->num_tmp_report_callbacks > 0) {
+ layer_free_tmp_report_callbacks(my_data->tmp_report_create_infos, my_data->tmp_report_callbacks);
+ my_data->num_tmp_report_callbacks = 0;
}
- // Clean up logging callback, if any
+ // Clean up logging callbacks, if any
+ while (my_data->logging_messenger.size() > 0) {
+ VkDebugUtilsMessengerEXT messenger = my_data->logging_messenger.back();
+ layer_destroy_messenger_callback(my_data->report_data, messenger, pAllocator);
+ my_data->logging_messenger.pop_back();
+ }
while (my_data->logging_callback.size() > 0) {
VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
- layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
+ layer_destroy_report_callback(my_data->report_data, callback, pAllocator);
my_data->logging_callback.pop_back();
}
- layer_debug_report_destroy_instance(my_data->report_data);
+ layer_debug_utils_destroy_instance(my_data->report_data);
delete my_data->instance_dispatch_table;
FreeLayerDataPtr(key, layer_data_map);
}
@@ -151,7 +170,7 @@
my_device_data->device_dispatch_table = new VkLayerDispatchTable;
layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
- my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+ my_device_data->report_data = layer_debug_utils_create_device(my_instance_data->report_data, *pDevice);
return result;
}
@@ -194,8 +213,8 @@
return result;
}
-static const VkExtensionProperties threading_extensions[] = {
- {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
+static const VkExtensionProperties threading_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
+ {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION}};
static const VkLayerProperties layerProps = {
"VK_LAYER_GOOGLE_threading",
@@ -272,6 +291,52 @@
return pTable->GetPhysicalDeviceProcAddr(instance, funcName);
}
+// VK_EXT_debug_utils commands
+VKAPI_ATTR VkResult VKAPI_CALL CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ layer_data *my_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
+ bool threadChecks = startMultiThread();
+ if (threadChecks) {
+ startReadObject(my_data, instance);
+ }
+ VkResult result = my_data->instance_dispatch_table->CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+
+ if (VK_SUCCESS == result) {
+ result = layer_create_messenger_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMessenger);
+ // If something happened during this call, clean up the message callback that was created earlier in the lower levels
+ if (VK_SUCCESS != result) {
+ my_data->instance_dispatch_table->DestroyDebugUtilsMessengerEXT(instance, *pMessenger, pAllocator);
+ }
+ }
+ if (threadChecks) {
+ finishReadObject(my_data, instance);
+ } else {
+ finishMultiThread();
+ }
+ return result;
+}
+
+VKAPI_ATTR void VKAPI_CALL DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ layer_data *my_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
+ bool threadChecks = startMultiThread();
+ if (threadChecks) {
+ startReadObject(my_data, instance);
+ startWriteObject(my_data, messenger);
+ }
+ my_data->instance_dispatch_table->DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+ layer_destroy_messenger_callback(my_data->report_data, messenger, pAllocator);
+ if (threadChecks) {
+ finishReadObject(my_data, instance);
+ finishWriteObject(my_data, messenger);
+ } else {
+ finishMultiThread();
+ }
+}
+
+// VK_EXT_debug_report commands
VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
@@ -284,7 +349,11 @@
VkResult result =
my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (VK_SUCCESS == result) {
- result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
+ result = layer_create_report_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
+ // If something happened during this call, clean up the message callback that was created earlier in the lower levels
+ if (VK_SUCCESS != result) {
+ my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, *pMsgCallback, pAllocator);
+ }
}
if (threadChecks) {
finishReadObject(my_data, instance);
@@ -303,7 +372,7 @@
startWriteObject(my_data, callback);
}
my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
- layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
+ layer_destroy_report_callback(my_data->report_data, callback, pAllocator);
if (threadChecks) {
finishReadObject(my_data, instance);
finishWriteObject(my_data, callback);
@@ -400,6 +469,23 @@
} // namespace threading
// vk_layer_logging.h expects these to be defined
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ return threading::CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ threading::DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkSubmitDebugUtilsMessageEXT(VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ threading::SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
+}
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
diff --git a/layers/threading.h b/layers/threading.h
index e2301d0..70814a5 100644
--- a/layers/threading.h
+++ b/layers/threading.h
@@ -228,13 +228,19 @@
debug_report_data *report_data;
std::vector<VkDebugReportCallbackEXT> logging_callback;
+ std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
VkLayerDispatchTable *device_dispatch_table;
VkLayerInstanceDispatchTable *instance_dispatch_table;
+
// The following are for keeping track of the temporary callbacks that can
// be used in vkCreateInstance and vkDestroyInstance:
- uint32_t num_tmp_callbacks;
- VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
- VkDebugReportCallbackEXT *tmp_callbacks;
+ uint32_t num_tmp_report_callbacks;
+ VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
+ VkDebugReportCallbackEXT *tmp_report_callbacks;
+ uint32_t num_tmp_debug_messengers;
+ VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
+ VkDebugUtilsMessengerEXT *tmp_debug_messengers;
+
counter<VkCommandBuffer> c_VkCommandBuffer;
counter<VkDevice> c_VkDevice;
counter<VkInstance> c_VkInstance;
@@ -270,15 +276,19 @@
counter<VkDescriptorUpdateTemplateKHR> c_VkDescriptorUpdateTemplateKHR;
counter<VkValidationCacheEXT> c_VkValidationCacheEXT;
counter<VkSamplerYcbcrConversionKHR> c_VkSamplerYcbcrConversionKHR;
+ counter<VkDebugUtilsMessengerEXT> c_VkDebugUtilsMessengerEXT;
#else // DISTINCT_NONDISPATCHABLE_HANDLES
counter<uint64_t> c_uint64_t;
#endif // DISTINCT_NONDISPATCHABLE_HANDLES
layer_data()
: report_data(nullptr),
- num_tmp_callbacks(0),
- tmp_dbg_create_infos(nullptr),
- tmp_callbacks(nullptr),
+ num_tmp_report_callbacks(0),
+ tmp_report_create_infos(nullptr),
+ tmp_report_callbacks(nullptr),
+ num_tmp_debug_messengers(0),
+ tmp_messenger_create_infos(nullptr),
+ tmp_debug_messengers(nullptr),
c_VkCommandBuffer("VkCommandBuffer", VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT),
c_VkDevice("VkDevice", VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT),
c_VkInstance("VkInstance", VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT),
@@ -314,7 +324,9 @@
c_VkSwapchainKHR("VkSwapchainKHR", VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT),
c_VkDescriptorUpdateTemplateKHR("VkDescriptorUpdateTemplateKHR",
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT),
- c_VkSamplerYcbcrConversionKHR("VkSamplerYcbcrConversionKHR", VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT)
+ c_VkSamplerYcbcrConversionKHR("VkSamplerYcbcrConversionKHR",
+ VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT),
+ c_VkDebugUtilsMessengerEXT("VkDebugUtilsMessengerEXT", VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT)
#else // DISTINCT_NONDISPATCHABLE_HANDLES
c_uint64_t("NON_DISPATCHABLE_HANDLE", VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT)
#endif // DISTINCT_NONDISPATCHABLE_HANDLES
@@ -365,6 +377,7 @@
WRAPPER(VkDescriptorUpdateTemplateKHR)
WRAPPER(VkValidationCacheEXT)
WRAPPER(VkSamplerYcbcrConversionKHR)
+WRAPPER(VkDebugUtilsMessengerEXT)
#else // DISTINCT_NONDISPATCHABLE_HANDLES
WRAPPER(uint64_t)
#endif // DISTINCT_NONDISPATCHABLE_HANDLES
diff --git a/layers/unique_objects.cpp b/layers/unique_objects.cpp
index 3700370..702f07b 100644
--- a/layers/unique_objects.cpp
+++ b/layers/unique_objects.cpp
@@ -59,7 +59,9 @@
static uint32_t loader_layer_if_version = CURRENT_LOADER_LAYER_INTERFACE_VERSION;
static void initUniqueObjects(instance_layer_data *instance_data, const VkAllocationCallbacks *pAllocator) {
- layer_debug_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "google_unique_objects");
+ layer_debug_report_actions(instance_data->report_data, instance_data->logging_callback, pAllocator, "google_unique_objects");
+ layer_debug_messenger_actions(instance_data->report_data, instance_data->logging_messenger, pAllocator,
+ "google_unique_objects");
}
// Check enabled instance extensions against supported instance extension whitelist
@@ -118,17 +120,27 @@
layer_init_instance_dispatch_table(*pInstance, &instance_data->dispatch_table, fpGetInstanceProcAddr);
instance_data->instance = *pInstance;
- instance_data->report_data = debug_report_create_instance(
+ instance_data->report_data = debug_utils_create_instance(
&instance_data->dispatch_table, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
// Set up temporary debug callbacks to output messages at CreateInstance-time
- if (!layer_copy_tmp_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_callbacks, &instance_data->tmp_dbg_create_infos,
- &instance_data->tmp_callbacks)) {
- if (instance_data->num_tmp_callbacks > 0) {
- if (layer_enable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks,
- instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks)) {
- layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks);
- instance_data->num_tmp_callbacks = 0;
+ if (!layer_copy_tmp_debug_messengers(pCreateInfo->pNext, &instance_data->num_tmp_debug_messengers,
+ &instance_data->tmp_messenger_create_infos, &instance_data->tmp_debug_messengers)) {
+ if (instance_data->num_tmp_debug_messengers > 0) {
+ if (layer_enable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers,
+ instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers)) {
+ layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers);
+ instance_data->num_tmp_debug_messengers = 0;
+ }
+ }
+ }
+ if (!layer_copy_tmp_report_callbacks(pCreateInfo->pNext, &instance_data->num_tmp_report_callbacks,
+ &instance_data->tmp_report_create_infos, &instance_data->tmp_report_callbacks)) {
+ if (instance_data->num_tmp_report_callbacks > 0) {
+ if (layer_enable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks,
+ instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks)) {
+ layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks);
+ instance_data->num_tmp_report_callbacks = 0;
}
}
}
@@ -137,10 +149,17 @@
InstanceExtensionWhitelist(pCreateInfo, *pInstance);
// Disable and free tmp callbacks, no longer necessary
- if (instance_data->num_tmp_callbacks > 0) {
- layer_disable_tmp_callbacks(instance_data->report_data, instance_data->num_tmp_callbacks, instance_data->tmp_callbacks);
- layer_free_tmp_callbacks(instance_data->tmp_dbg_create_infos, instance_data->tmp_callbacks);
- instance_data->num_tmp_callbacks = 0;
+ if (instance_data->num_tmp_debug_messengers > 0) {
+ layer_disable_tmp_debug_messengers(instance_data->report_data, instance_data->num_tmp_debug_messengers,
+ instance_data->tmp_debug_messengers);
+ layer_free_tmp_debug_messengers(instance_data->tmp_messenger_create_infos, instance_data->tmp_debug_messengers);
+ instance_data->num_tmp_debug_messengers = 0;
+ }
+ if (instance_data->num_tmp_report_callbacks > 0) {
+ layer_disable_tmp_report_callbacks(instance_data->report_data, instance_data->num_tmp_report_callbacks,
+ instance_data->tmp_report_callbacks);
+ layer_free_tmp_report_callbacks(instance_data->tmp_report_create_infos, instance_data->tmp_report_callbacks);
+ instance_data->num_tmp_report_callbacks = 0;
}
return result;
@@ -153,13 +172,18 @@
disp_table->DestroyInstance(instance, pAllocator);
// Clean up logging callback, if any
+ while (instance_data->logging_messenger.size() > 0) {
+ VkDebugUtilsMessengerEXT messenger = instance_data->logging_messenger.back();
+ layer_destroy_messenger_callback(instance_data->report_data, messenger, pAllocator);
+ instance_data->logging_messenger.pop_back();
+ }
while (instance_data->logging_callback.size() > 0) {
VkDebugReportCallbackEXT callback = instance_data->logging_callback.back();
- layer_destroy_msg_callback(instance_data->report_data, callback, pAllocator);
+ layer_destroy_report_callback(instance_data->report_data, callback, pAllocator);
instance_data->logging_callback.pop_back();
}
- layer_debug_report_destroy_instance(instance_data->report_data);
+ layer_debug_utils_destroy_instance(instance_data->report_data);
FreeLayerDataPtr(key, instance_layer_data_map);
}
@@ -185,7 +209,7 @@
}
layer_data *my_device_data = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
- my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+ my_device_data->report_data = layer_debug_utils_create_device(my_instance_data->report_data, *pDevice);
// Setup layer's device dispatch table
layer_init_device_dispatch_table(*pDevice, &my_device_data->dispatch_table, fpGetDeviceProcAddr);
@@ -202,7 +226,7 @@
dispatch_key key = get_dispatch_key(device);
layer_data *dev_data = GetLayerDataPtr(key, layer_data_map);
- layer_debug_report_destroy_device(device);
+ layer_debug_utils_destroy_device(device);
dev_data->dispatch_table.DestroyDevice(device, pAllocator);
FreeLayerDataPtr(key, layer_data_map);
@@ -877,6 +901,37 @@
return result;
}
+// VK_EXT_debug_utils
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectTagEXT(VkDevice device, const VkDebugUtilsObjectTagInfoEXT *pTagInfo) {
+ layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ auto local_tag_info = new safe_VkDebugUtilsObjectTagInfoEXT(pTagInfo);
+ {
+ std::lock_guard<std::mutex> lock(global_lock);
+ auto it = device_data->unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_tag_info->objectHandle));
+ if (it != device_data->unique_id_mapping.end()) {
+ local_tag_info->objectHandle = it->second;
+ }
+ }
+ VkResult result = device_data->dispatch_table.SetDebugUtilsObjectTagEXT(
+ device, reinterpret_cast<const VkDebugUtilsObjectTagInfoEXT *>(local_tag_info));
+ return result;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL SetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
+ layer_data *device_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
+ auto local_name_info = new safe_VkDebugUtilsObjectNameInfoEXT(pNameInfo);
+ {
+ std::lock_guard<std::mutex> lock(global_lock);
+ auto it = device_data->unique_id_mapping.find(reinterpret_cast<uint64_t &>(local_name_info->objectHandle));
+ if (it != device_data->unique_id_mapping.end()) {
+ local_name_info->objectHandle = it->second;
+ }
+ }
+ VkResult result = device_data->dispatch_table.SetDebugUtilsObjectNameEXT(
+ device, reinterpret_cast<const VkDebugUtilsObjectNameInfoEXT *>(local_name_info));
+ return result;
+}
+
} // namespace unique_objects
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
diff --git a/layers/unique_objects.h b/layers/unique_objects.h
index 3dd3a79..0a03234 100644
--- a/layers/unique_objects.h
+++ b/layers/unique_objects.h
@@ -50,12 +50,17 @@
debug_report_data *report_data;
std::vector<VkDebugReportCallbackEXT> logging_callback;
+ std::vector<VkDebugUtilsMessengerEXT> logging_messenger;
VkLayerInstanceDispatchTable dispatch_table = {};
- // The following are for keeping track of the temporary callbacks that can be used in vkCreateInstance and vkDestroyInstance:
- uint32_t num_tmp_callbacks;
- VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
- VkDebugReportCallbackEXT *tmp_callbacks;
+ // The following are for keeping track of the temporary callbacks that can
+ // be used in vkCreateInstance and vkDestroyInstance:
+ uint32_t num_tmp_report_callbacks;
+ VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
+ VkDebugReportCallbackEXT *tmp_report_callbacks;
+ uint32_t num_tmp_debug_messengers;
+ VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
+ VkDebugUtilsMessengerEXT *tmp_debug_messengers;
};
struct layer_data {
diff --git a/layers/vk_layer_config.cpp b/layers/vk_layer_config.cpp
index b1b09d4..51f4278 100644
--- a/layers/vk_layer_config.cpp
+++ b/layers/vk_layer_config.cpp
@@ -248,31 +248,74 @@
}
}
-VK_LAYER_EXPORT void print_msg_flags(VkFlags msgFlags, char *msg_flags) {
+VK_LAYER_EXPORT void PrintMessageFlags(VkFlags vk_flags, char *msg_flags) {
bool separator = false;
msg_flags[0] = 0;
- if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
+ if (vk_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
strcat(msg_flags, "DEBUG");
separator = true;
}
- if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
+ if (vk_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
if (separator) strcat(msg_flags, ",");
strcat(msg_flags, "INFO");
separator = true;
}
- if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ if (vk_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
if (separator) strcat(msg_flags, ",");
strcat(msg_flags, "WARN");
separator = true;
}
- if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
+ if (vk_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
if (separator) strcat(msg_flags, ",");
strcat(msg_flags, "PERF");
separator = true;
}
- if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ if (vk_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
if (separator) strcat(msg_flags, ",");
strcat(msg_flags, "ERROR");
}
}
+
+VK_LAYER_EXPORT void PrintMessageSeverity(VkFlags vk_flags, char *msg_flags) {
+ bool separator = false;
+
+ msg_flags[0] = 0;
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
+ strcat(msg_flags, "VERBOSE");
+ separator = true;
+ }
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
+ if (separator) strcat(msg_flags, ",");
+ strcat(msg_flags, "INFO");
+ separator = true;
+ }
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
+ if (separator) strcat(msg_flags, ",");
+ strcat(msg_flags, "WARN");
+ separator = true;
+ }
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
+ if (separator) strcat(msg_flags, ",");
+ strcat(msg_flags, "ERROR");
+ }
+}
+
+VK_LAYER_EXPORT void PrintMessageType(VkFlags vk_flags, char *msg_flags) {
+ bool separator = false;
+
+ msg_flags[0] = 0;
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
+ strcat(msg_flags, "GEN");
+ separator = true;
+ }
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
+ strcat(msg_flags, "SPEC");
+ separator = true;
+ }
+ if (vk_flags & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) {
+ if (separator) strcat(msg_flags, ",");
+ strcat(msg_flags, "PERF");
+ separator = true;
+ }
+}
diff --git a/layers/vk_layer_config.h b/layers/vk_layer_config.h
index b12ba50..e0b9d32 100644
--- a/layers/vk_layer_config.h
+++ b/layers/vk_layer_config.h
@@ -63,7 +63,9 @@
uint32_t option_default);
VK_LAYER_EXPORT void setLayerOption(const char *_option, const char *_val);
-VK_LAYER_EXPORT void print_msg_flags(VkFlags msgFlags, char *msg_flags);
+VK_LAYER_EXPORT void PrintMessageFlags(VkFlags vk_flags, char *msg_flags);
+VK_LAYER_EXPORT void PrintMessageSeverity(VkFlags vk_flags, char *msg_flags);
+VK_LAYER_EXPORT void PrintMessageType(VkFlags vk_flags, char *msg_flags);
#ifdef __cplusplus
}
diff --git a/layers/vk_layer_logging.h b/layers/vk_layer_logging.h
index 559b5a4..61e109a 100644
--- a/layers/vk_layer_logging.h
+++ b/layers/vk_layer_logging.h
@@ -1,6 +1,6 @@
-/* Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
+/* Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
*
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: Tobin Ehlis <tobin@lunarg.com>
+ * Author: Mark Young <marky@lunarg.com>
*
*/
@@ -28,6 +29,7 @@
#include "vk_layer_table.h"
#include "vk_loader_platform.h"
#include "vulkan/vk_layer.h"
+#include "vk_object_types.h"
#include <signal.h>
#include <cinttypes>
#include <stdarg.h>
@@ -35,51 +37,103 @@
#include <stdio.h>
#include <unordered_map>
#include <vector>
+#include <sstream>
+#include <string>
+
+// TODO: Could be autogenerated for the specific handles for extra type safety...
+template <typename HANDLE_T>
+static inline uint64_t HandleToUint64(HANDLE_T *h) {
+ return reinterpret_cast<uint64_t>(h);
+}
+
+static inline uint64_t HandleToUint64(uint64_t h) { return h; }
+
+// Data we store per label for logging
+typedef struct _LoggingLabelData {
+ std::string name;
+ float color[4];
+} LoggingLabelData;
typedef struct _debug_report_data {
VkLayerDbgFunctionNode *debug_callback_list;
VkLayerDbgFunctionNode *default_debug_callback_list;
- VkFlags active_flags;
+ VkDebugUtilsMessageSeverityFlagsEXT active_severities;
+ VkDebugUtilsMessageTypeFlagsEXT active_types;
bool g_DEBUG_REPORT;
+ bool g_DEBUG_UTILS;
std::unordered_map<uint64_t, std::string> *debugObjectNameMap;
+ std::unordered_map<uint64_t, std::string> *debugUtilsObjectNameMap;
+ std::unordered_map<VkQueue, std::vector<LoggingLabelData>> *debugUtilsQueueLabels;
+ bool queueLabelHasInsert;
+ std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>> *debugUtilsCmdBufLabels;
+ bool cmdBufLabelHasInsert;
} debug_report_data;
template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key,
std::unordered_map<void *, debug_report_data *> &data_map);
+static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+ VkDebugUtilsMessageSeverityFlagsEXT *da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT *da_type) {
+ // All layer warnings are spec warnings currently. At least as far as anything not specifically
+ // called out. In the future, we'll label things using the new split severity and type values.
+ *da_type = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ *da_severity = 0;
+ if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
+ *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
+ *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
+ *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ }
+ if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
+ *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ }
+ if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
+ *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ }
+}
+
// Forward Declarations
-static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags,
- VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode,
- const char *pLayerPrefix, const char *pMsg);
+static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
+ uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix,
+ const char *message);
// Add a debug message callback node structure to the specified callback linked list
-static inline void AddDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
- VkLayerDbgFunctionNode *new_node) {
+static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
+ VkLayerDbgFunctionNode *new_node) {
new_node->pNext = *list_head;
*list_head = new_node;
}
-// Remove specified debug message callback node structure from the specified callback linked list
-static inline void RemoveDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
- VkDebugReportCallbackEXT callback) {
+// Remove specified debug messenger node structure from the specified linked list
+static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
+ VkDebugUtilsMessengerEXT messenger) {
VkLayerDbgFunctionNode *cur_callback = *list_head;
VkLayerDbgFunctionNode *prev_callback = cur_callback;
bool matched = false;
- VkFlags local_flags = 0;
+ VkFlags local_severities = 0;
+ VkFlags local_types = 0;
while (cur_callback) {
- if (cur_callback->msgCallback == callback) {
+ if (cur_callback->is_messenger && cur_callback->messenger.messenger == messenger) {
matched = true;
prev_callback->pNext = cur_callback->pNext;
if (*list_head == cur_callback) {
*list_head = cur_callback->pNext;
}
- debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
- reinterpret_cast<uint64_t &>(cur_callback->msgCallback), 0, 0, "DebugReport",
- "Destroyed callback\n");
+ debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, 0, "DebugUtilsMessenger",
+ "Destroyed messenger\n");
} else {
matched = false;
- local_flags |= cur_callback->msgFlags;
+ local_severities |= cur_callback->messenger.messageSeverity;
+ local_types |= cur_callback->messenger.messageType;
}
prev_callback = cur_callback;
cur_callback = cur_callback->pNext;
@@ -87,7 +141,45 @@
free(prev_callback);
}
}
- debug_data->active_flags = local_flags;
+ debug_data->active_severities = local_severities;
+ debug_data->active_types = local_types;
+}
+
+// Remove specified debug message callback node structure from the specified callback linked list
+static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
+ VkDebugReportCallbackEXT callback) {
+ VkLayerDbgFunctionNode *cur_callback = *list_head;
+ VkLayerDbgFunctionNode *prev_callback = cur_callback;
+ bool matched = false;
+ VkFlags local_severities = 0;
+ VkFlags local_types = 0;
+
+ while (cur_callback) {
+ if (!cur_callback->is_messenger && cur_callback->report.msgCallback == callback) {
+ matched = true;
+ prev_callback->pNext = cur_callback->pNext;
+ if (*list_head == cur_callback) {
+ *list_head = cur_callback->pNext;
+ }
+ debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, 0, "DebugReport",
+ "Destroyed callback\n");
+ } else {
+ matched = false;
+ VkFlags this_severities = 0;
+ VkFlags this_types = 0;
+ DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
+ local_severities |= this_severities;
+ local_types |= this_types;
+ }
+ prev_callback = cur_callback;
+ cur_callback = cur_callback->pNext;
+ if (matched) {
+ free(prev_callback);
+ }
+ }
+ debug_data->active_severities = local_severities;
+ debug_data->active_types = local_types;
}
// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
@@ -97,9 +189,15 @@
while (current_callback) {
prev_callback = current_callback->pNext;
- debug_report_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
- (uint64_t)current_callback->msgCallback, 0, 0, "DebugReport",
- "Debug Report callbacks not removed before DestroyInstance");
+ if (!current_callback->is_messenger) {
+ debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ (uint64_t)current_callback->report.msgCallback, 0, 0, "DebugReport",
+ "Debug Report callbacks not removed before DestroyInstance");
+ } else {
+ debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ (uint64_t)current_callback->messenger.messenger, 0, 0, "Messenger",
+ "Debug messengers not removed before DestroyInstance");
+ }
free(current_callback);
current_callback = prev_callback;
}
@@ -107,46 +205,222 @@
}
// Utility function to handle reporting
-static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags,
- VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode,
- const char *pLayerPrefix, const char *pMsg) {
+static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
+ uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix,
+ const char *message) {
bool bail = false;
- VkLayerDbgFunctionNode *pTrav = NULL;
+ VkLayerDbgFunctionNode *layer_dbg_node = NULL;
if (debug_data->debug_callback_list != NULL) {
- pTrav = debug_data->debug_callback_list;
+ layer_dbg_node = debug_data->debug_callback_list;
} else {
- pTrav = debug_data->default_debug_callback_list;
+ layer_dbg_node = debug_data->default_debug_callback_list;
}
- while (pTrav) {
- if (pTrav->msgFlags & msgFlags) {
- auto it = debug_data->debugObjectNameMap->find(srcObject);
+ VkDebugUtilsMessageSeverityFlagsEXT severity;
+ VkDebugUtilsMessageTypeFlagsEXT types;
+ VkDebugUtilsMessengerCallbackDataEXT callback_data;
+ VkDebugUtilsObjectNameInfoEXT object_name_info;
+
+ // Convert the info to the VK_EXT_debug_utils form in case we need it.
+ DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
+ object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ object_name_info.pNext = NULL;
+ object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
+ object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
+ object_name_info.pObjectName = NULL;
+
+ callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.pNext = NULL;
+ callback_data.flags = 0;
+ callback_data.pMessageIdName = layer_prefix;
+ callback_data.messageIdNumber = msg_code;
+ callback_data.pMessage = message;
+ callback_data.queueLabelCount = 0;
+ callback_data.pQueueLabels = NULL;
+ callback_data.cmdBufLabelCount = 0;
+ callback_data.pCmdBufLabels = NULL;
+ callback_data.objectCount = 1;
+ callback_data.pObjects = &object_name_info;
+
+ VkDebugUtilsLabelEXT *queue_labels = nullptr;
+ VkDebugUtilsLabelEXT *cmd_buf_labels = nullptr;
+ std::string new_debug_report_message = "";
+ std::ostringstream oss;
+ oss << "Object: 0x" << std::hex << src_object;
+
+ if (0 != src_object) {
+ // If this is a queue, add any queue labels to the callback data.
+ if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
+ auto label_iter = debug_data->debugUtilsQueueLabels->find(reinterpret_cast<VkQueue>(src_object));
+ if (label_iter != debug_data->debugUtilsQueueLabels->end()) {
+ queue_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
+ if (nullptr != queue_labels) {
+ // Record the labels, but record them in reverse order since we want the
+ // most recent at the top.
+ uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
+ uint32_t last_index = label_size - 1;
+ for (uint32_t label = 0; label < label_size; ++label) {
+ queue_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ queue_labels[last_index - label].pNext = nullptr;
+ queue_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
+ queue_labels[last_index - label].color[0] = label_iter->second[label].color[0];
+ queue_labels[last_index - label].color[1] = label_iter->second[label].color[1];
+ queue_labels[last_index - label].color[2] = label_iter->second[label].color[2];
+ queue_labels[last_index - label].color[3] = label_iter->second[label].color[3];
+ }
+ callback_data.queueLabelCount = label_size;
+ callback_data.pQueueLabels = queue_labels;
+ }
+ }
+ // If this is a command buffer, add any command buffer labels to the callback data.
+ } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
+ auto label_iter = debug_data->debugUtilsCmdBufLabels->find(reinterpret_cast<VkCommandBuffer>(src_object));
+ if (label_iter != debug_data->debugUtilsCmdBufLabels->end()) {
+ cmd_buf_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
+ if (nullptr != cmd_buf_labels) {
+ // Record the labels, but record them in reverse order since we want the
+ // most recent at the top.
+ uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
+ uint32_t last_index = label_size - 1;
+ for (uint32_t label = 0; label < label_size; ++label) {
+ cmd_buf_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ cmd_buf_labels[last_index - label].pNext = nullptr;
+ cmd_buf_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
+ cmd_buf_labels[last_index - label].color[0] = label_iter->second[label].color[0];
+ cmd_buf_labels[last_index - label].color[1] = label_iter->second[label].color[1];
+ cmd_buf_labels[last_index - label].color[2] = label_iter->second[label].color[2];
+ cmd_buf_labels[last_index - label].color[3] = label_iter->second[label].color[3];
+ }
+ callback_data.cmdBufLabelCount = label_size;
+ callback_data.pCmdBufLabels = cmd_buf_labels;
+ }
+ }
+ }
+ // Look for any debug utils or marker names to use for this object
+ callback_data.pObjects[0].pObjectName = NULL;
+ auto utils_name_iter = debug_data->debugUtilsObjectNameMap->find(src_object);
+ if (utils_name_iter != debug_data->debugUtilsObjectNameMap->end()) {
+ callback_data.pObjects[0].pObjectName = utils_name_iter->second.c_str();
+ } else {
+ auto marker_name_iter = debug_data->debugObjectNameMap->find(src_object);
+ if (marker_name_iter != debug_data->debugObjectNameMap->end()) {
+ callback_data.pObjects[0].pObjectName = marker_name_iter->second.c_str();
+ }
+ }
+ if (NULL != callback_data.pObjects[0].pObjectName) {
+ oss << " (Name = " << callback_data.pObjects[0].pObjectName << ")";
+ }
+ }
+ new_debug_report_message += oss.str();
+ new_debug_report_message += " | ";
+ new_debug_report_message += message;
+
+ while (layer_dbg_node) {
+ if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags) &&
+ layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, msg_code, layer_prefix,
+ new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
+ bail = true;
+ } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
+ (layer_dbg_node->messenger.messageType & types) &&
+ layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
+ &callback_data, layer_dbg_node->pUserData)) {
+ bail = true;
+ }
+ layer_dbg_node = layer_dbg_node->pNext;
+ }
+
+ if (nullptr != queue_labels) {
+ delete[] queue_labels;
+ }
+ if (nullptr != cmd_buf_labels) {
+ delete[] cmd_buf_labels;
+ }
+
+ return bail;
+}
+
+static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
+ *dr_flags = 0;
+
+ if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
+ if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ } else {
+ *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ }
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ }
+}
+
+static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
+ VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
+ VkDebugUtilsMessageTypeFlagsEXT message_type,
+ VkDebugUtilsMessengerCallbackDataEXT *callback_data) {
+ bool bail = false;
+ VkLayerDbgFunctionNode *layer_dbg_node = NULL;
+
+ if (debug_data->debug_callback_list != NULL) {
+ layer_dbg_node = debug_data->debug_callback_list;
+ } else {
+ layer_dbg_node = debug_data->default_debug_callback_list;
+ }
+
+ VkDebugReportFlagsEXT object_flags = 0;
+
+ DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
+
+ while (layer_dbg_node) {
+ if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
+ (layer_dbg_node->messenger.messageType & message_type)) {
+ // Loop through each object and give it the proper name if it was set.
+ for (uint32_t obj = 0; obj < callback_data->objectCount; obj++) {
+ auto it = debug_data->debugUtilsObjectNameMap->find(callback_data->pObjects[obj].objectHandle);
+ if (it == debug_data->debugUtilsObjectNameMap->end()) {
+ continue;
+ }
+ callback_data->pObjects[obj].pObjectName = it->second.c_str();
+ }
+ if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
+ layer_dbg_node->pUserData)) {
+ bail = true;
+ }
+ } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
+ auto it = debug_data->debugObjectNameMap->find(callback_data->pObjects[0].objectHandle);
+ VkDebugReportObjectTypeEXT object_type = get_debug_report_enum[callback_data->pObjects[0].objectType];
if (it == debug_data->debugObjectNameMap->end()) {
- if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg,
- pTrav->pUserData)) {
+ if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
+ callback_data->messageIdNumber, callback_data->pMessageIdName,
+ callback_data->pMessage, layer_dbg_node->pUserData)) {
bail = true;
}
} else {
std::string newMsg = "SrcObject name = ";
newMsg.append(it->second.c_str());
newMsg.append(" ");
- newMsg.append(pMsg);
- if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, newMsg.c_str(),
- pTrav->pUserData)) {
+ newMsg.append(callback_data->pMessage);
+ if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
+ callback_data->messageIdNumber, callback_data->pMessageIdName,
+ newMsg.c_str(), layer_dbg_node->pUserData)) {
bail = true;
}
}
}
- pTrav = pTrav->pNext;
+ layer_dbg_node = layer_dbg_node->pNext;
}
return bail;
}
-static inline debug_report_data *debug_report_create_instance(
+static inline debug_report_data *debug_utils_create_instance(
VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
- const char *const *ppEnabledExtensions) // layer or extension name to be enabled
+ const char *const *enabled_extensions) // layer or extension name to be enabled
{
debug_report_data *debug_data = (debug_report_data *)malloc(sizeof(debug_report_data));
if (!debug_data) return NULL;
@@ -154,78 +428,162 @@
memset(debug_data, 0, sizeof(debug_report_data));
for (uint32_t i = 0; i < extension_count; i++) {
// TODO: Check other property fields
- if (strcmp(ppEnabledExtensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
+ if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
debug_data->g_DEBUG_REPORT = true;
+ } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
+ debug_data->g_DEBUG_UTILS = true;
}
}
debug_data->debugObjectNameMap = new std::unordered_map<uint64_t, std::string>;
+ debug_data->debugUtilsObjectNameMap = new std::unordered_map<uint64_t, std::string>;
+ debug_data->debugUtilsQueueLabels = new std::unordered_map<VkQueue, std::vector<LoggingLabelData>>;
+ debug_data->debugUtilsCmdBufLabels = new std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>>;
+ debug_data->queueLabelHasInsert = false;
+ debug_data->cmdBufLabelHasInsert = false;
return debug_data;
}
-static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data) {
+static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
if (debug_data) {
RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
delete debug_data->debugObjectNameMap;
+ delete debug_data->debugUtilsObjectNameMap;
+ delete debug_data->debugUtilsQueueLabels;
+ delete debug_data->debugUtilsCmdBufLabels;
free(debug_data);
}
}
-static inline debug_report_data *layer_debug_report_create_device(debug_report_data *instance_debug_data, VkDevice device) {
+static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
// DEBUG_REPORT shares data between Instance and Device,
// so just return instance's data pointer
return instance_debug_data;
}
-static inline void layer_debug_report_destroy_device(VkDevice device) {
+static inline void layer_debug_utils_destroy_device(VkDevice device) {
// Nothing to do since we're using instance data record
}
-static inline void layer_destroy_msg_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator) {
- RemoveDebugMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
- RemoveDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
+static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *allocator) {
+ RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
+ RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
}
-static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, bool default_callback,
- const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
+static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
+ const VkDebugUtilsMessengerCreateInfoEXT *create_info,
+ const VkAllocationCallbacks *allocator,
+ VkDebugUtilsMessengerEXT *messenger) {
VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+ pNewDbgFuncNode->is_messenger = true;
// Handle of 0 is logging_callback so use allocated Node address as unique handle
- if (!(*pCallback)) *pCallback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
- pNewDbgFuncNode->msgCallback = *pCallback;
- pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
- pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
- pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
+ pNewDbgFuncNode->messenger.messenger = *messenger;
+ pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
+ pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
+ pNewDbgFuncNode->messenger.messageType = create_info->messageType;
+ pNewDbgFuncNode->pUserData = create_info->pUserData;
+ debug_data->active_severities |= create_info->messageSeverity;
+ debug_data->active_types |= create_info->messageType;
if (default_callback) {
- AddDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
- debug_data->active_flags |= pCreateInfo->flags;
+ AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
} else {
- AddDebugMessageCallback(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
- debug_data->active_flags = pCreateInfo->flags;
+ AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
}
- debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
- (uint64_t)*pCallback, 0, 0, "DebugReport", "Added callback");
+ VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
+ VkDebugUtilsObjectNameInfoEXT blank_object = {};
+ callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.pNext = NULL;
+ callback_data.flags = 0;
+ callback_data.pMessageIdName = "Layer Internal Message";
+ callback_data.messageIdNumber = 0;
+ callback_data.pMessage = "Added messenger";
+ callback_data.queueLabelCount = 0;
+ callback_data.pQueueLabels = NULL;
+ callback_data.cmdBufLabelCount = 0;
+ callback_data.pCmdBufLabels = NULL;
+ callback_data.objectCount = 1;
+ callback_data.pObjects = &blank_object;
+ blank_object.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ blank_object.pNext = NULL;
+ blank_object.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
+ blank_object.objectHandle = HandleToUint64(*messenger);
+ blank_object.pObjectName = NULL;
+ debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data);
return VK_SUCCESS;
}
-static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(debug_report_data *debug_data, const char *funcName) {
- if (!debug_data || !debug_data->g_DEBUG_REPORT) {
- return NULL;
+static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *allocator) {
+ RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
+ RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
+}
+
+static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
+ const VkDebugReportCallbackCreateInfoEXT *create_info,
+ const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
+ if (!pNewDbgFuncNode) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+ pNewDbgFuncNode->is_messenger = false;
+
+ // Handle of 0 is logging_callback so use allocated Node address as unique handle
+ if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
+ pNewDbgFuncNode->report.msgCallback = *callback;
+ pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
+ pNewDbgFuncNode->report.msgFlags = create_info->flags;
+ pNewDbgFuncNode->pUserData = create_info->pUserData;
+
+ VkFlags local_severity = 0;
+ VkFlags local_type = 0;
+ DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
+ debug_data->active_severities |= local_severity;
+ debug_data->active_types |= local_type;
+ if (default_callback) {
+ AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
+ } else {
+ AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
}
- if (!strcmp(funcName, "vkCreateDebugReportCallbackEXT")) {
- return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
+ debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0,
+ 0, "DebugReport", "Added callback");
+ return VK_SUCCESS;
+}
+
+static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
+ if (!debug_data) {
+ return NULL;
}
- if (!strcmp(funcName, "vkDestroyDebugReportCallbackEXT")) {
- return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
+ if (debug_data->g_DEBUG_REPORT) {
+ if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
+ return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
+ }
+ if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
+ return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
+ }
+ if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
+ return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
+ }
}
- if (!strcmp(funcName, "vkDebugReportMessageEXT")) {
- return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
+ if (debug_data->g_DEBUG_UTILS) {
+ if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
+ return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
+ }
+ if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
+ return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
+ }
+ if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
+ return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
+ }
}
return NULL;
}
@@ -235,8 +593,9 @@
// then allocates an array that can hold that many structs, as well as that
// many VkDebugReportCallbackEXT handles. It then copies each
// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
-static inline VkResult layer_copy_tmp_callbacks(const void *pChain, uint32_t *num_callbacks,
- VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
+static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
+ VkDebugReportCallbackCreateInfoEXT **infos,
+ VkDebugReportCallbackEXT **callbacks) {
uint32_t n = *num_callbacks = 0;
const void *pNext = pChain;
@@ -279,22 +638,23 @@
return VK_SUCCESS;
}
-// This utility frees the arrays allocated by layer_copy_tmp_callbacks()
-static inline void layer_free_tmp_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
+// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
+static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
free(infos);
free(callbacks);
}
// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
-// that were copied by layer_copy_tmp_callbacks()
-static inline VkResult layer_enable_tmp_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
- VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
+// that were copied by layer_copy_tmp_report_callbacks()
+static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
+ VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks) {
VkResult rtn = VK_SUCCESS;
for (uint32_t i = 0; i < num_callbacks; i++) {
- rtn = layer_create_msg_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
+ rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
if (rtn != VK_SUCCESS) {
for (uint32_t j = 0; j < i; j++) {
- layer_destroy_msg_callback(debug_data, callbacks[j], NULL);
+ layer_destroy_report_callback(debug_data, callbacks[j], NULL);
}
return rtn;
}
@@ -303,19 +663,104 @@
}
// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
-// that were copied by layer_copy_tmp_callbacks()
-static inline void layer_disable_tmp_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
- VkDebugReportCallbackEXT *callbacks) {
+// that were copied by layer_copy_tmp_report_callbacks()
+static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
+ VkDebugReportCallbackEXT *callbacks) {
for (uint32_t i = 0; i < num_callbacks; i++) {
- layer_destroy_msg_callback(debug_data, callbacks[i], NULL);
+ layer_destroy_report_callback(debug_data, callbacks[i], NULL);
+ }
+}
+
+// This utility (called at vkCreateInstance() time), looks at a pNext chain.
+// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
+// then allocates an array that can hold that many structs, as well as that
+// many VkDebugUtilsMessengerEXT handles. It then copies each
+// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
+static VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
+ VkDebugUtilsMessengerCreateInfoEXT **infos, VkDebugUtilsMessengerEXT **messengers) {
+ uint32_t n = *num_messengers = 0;
+
+ const void *pNext = pChain;
+ while (pNext) {
+ // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
+ if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ n++;
+ }
+ pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
+ }
+ if (n == 0) {
+ return VK_SUCCESS;
+ }
+
+ // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
+ VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
+ ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
+ if (!pInfos) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ // 3rd, allocate memory for a unique handle for each messenger:
+ VkDebugUtilsMessengerEXT *pMessengers = *messengers =
+ ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
+ if (!pMessengers) {
+ free(pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
+ // vkDestroyInstance, and assign a unique handle to each callback (just
+ // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
+ pNext = pChain;
+ while (pNext) {
+ if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
+ *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
+ }
+ pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+ }
+
+ *num_messengers = n;
+ return VK_SUCCESS;
+}
+
+// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
+static void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos, VkDebugUtilsMessengerEXT *messengers) {
+ free(infos);
+ free(messengers);
+}
+
+// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
+// that were copied by layer_copy_tmp_debug_messengers()
+static VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
+ VkDebugUtilsMessengerCreateInfoEXT *infos, VkDebugUtilsMessengerEXT *messengers) {
+ VkResult rtn = VK_SUCCESS;
+ for (uint32_t i = 0; i < num_messengers; i++) {
+ rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
+ if (rtn != VK_SUCCESS) {
+ for (uint32_t j = 0; j < i; j++) {
+ layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
+ }
+ return rtn;
+ }
+ }
+ return rtn;
+}
+
+// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
+// that were copied by layer_copy_tmp_debug_messengers()
+static void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
+ VkDebugUtilsMessengerEXT *messengers) {
+ for (uint32_t i = 0; i < num_messengers; i++) {
+ layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
}
}
// Checks if the message will get logged.
// Allows layer to defer collecting & formating data if the
// message will be discarded.
-static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msgFlags) {
- if (!debug_data || !(debug_data->active_flags & msgFlags)) {
+static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
+ VkFlags local_severity = 0;
+ VkFlags local_type = 0;
+ DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
+ if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
// Message is not wanted
return false;
}
@@ -358,14 +803,17 @@
// Takes format and variable arg list so that output string
// is only computed if a message needs to be logged
#ifndef WIN32
-static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
- uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format, ...)
- __attribute__((format(printf, 8, 9)));
+static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
+ uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, const char *format,
+ ...) __attribute__((format(printf, 8, 9)));
#endif
-static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
- uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format,
+static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
+ uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, const char *format,
...) {
- if (!debug_data || !(debug_data->active_flags & msgFlags)) {
+ VkFlags local_severity = 0;
+ VkFlags local_type = 0;
+ DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
+ if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
// Message is not wanted
return false;
}
@@ -378,37 +826,38 @@
str = nullptr;
}
va_end(argptr);
- bool result = debug_report_log_msg(debug_data, msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix,
- str ? str : "Allocation failure");
+ bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, location, msg_code, layer_prefix,
+ str ? str : "Allocation failure");
free(str);
return result;
}
-static inline VKAPI_ATTR VkBool32 VKAPI_CALL log_callback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
- size_t location, int32_t msgCode, const char *pLayerPrefix,
- const char *pMsg, void *pUserData) {
- char msg_flags[30];
+static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
+ uint64_t src_object, size_t location, int32_t msg_code,
+ const char *layer_prefix, const char *message, void *user_data) {
+ char msg_flag_string[30];
- print_msg_flags(msgFlags, msg_flags);
+ PrintMessageFlags(msg_flags, msg_flag_string);
- fprintf((FILE *)pUserData, "%s(%s): object: 0x%" PRIx64 " type: %d location: %lu msgCode: %d: %s\n", pLayerPrefix, msg_flags,
- srcObject, objType, (unsigned long)location, msgCode, pMsg);
- fflush((FILE *)pUserData);
+ fprintf((FILE *)user_data, "%s(%s): object: 0x%" PRIx64 " type: %d location: %lu msg_code: %d: %s\n", layer_prefix,
+ msg_flag_string, src_object, obj_type, (unsigned long)location, msg_code, message);
+ fflush((FILE *)user_data);
return false;
}
-static inline VKAPI_ATTR VkBool32 VKAPI_CALL win32_debug_output_msg(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject, size_t location, int32_t msgCode,
- const char *pLayerPrefix, const char *pMsg, void *pUserData) {
+static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
+ uint64_t src_object, size_t location, int32_t msg_code,
+ const char *layer_prefix, const char *message,
+ void *user_data) {
#ifdef WIN32
- char msg_flags[30];
+ char msg_flag_string[30];
char buf[2048];
- print_msg_flags(msgFlags, msg_flags);
+ PrintMessageFlags(msg_flags, msg_flag_string);
_snprintf(buf, sizeof(buf) - 1,
- "%s (%s): object: 0x%" PRIxPTR " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msgCode: %d: %s\n", pLayerPrefix,
- msg_flags, (size_t)srcObject, objType, location, msgCode, pMsg);
+ "%s (%s): object: 0x%" PRIxPTR " type: %d location: " PRINTF_SIZE_T_SPECIFIER " msg_code: %d: %s\n", layer_prefix,
+ msg_flag_string, (size_t)src_object, obj_type, location, msg_code, message);
OutputDebugString(buf);
#endif
@@ -416,9 +865,9 @@
return false;
}
-static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject, size_t location, int32_t msgCode,
- const char *pLayerPrefix, const char *pMsg, void *pUserData) {
+static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
+ uint64_t src_object, size_t location, int32_t msg_code,
+ const char *layer_prefix, const char *message, void *user_data) {
#ifdef WIN32
DebugBreak();
#else
@@ -428,15 +877,177 @@
return false;
}
-// TODO: Could be autogenerated for the specific handles for extra type safety...
-template <typename HANDLE_T>
-static inline uint64_t HandleToUint64(HANDLE_T *h) {
- return reinterpret_cast<uint64_t>(h);
+static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
+ VkDebugUtilsMessageTypeFlagsEXT message_type,
+ const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
+ void *user_data) {
+ char msg_severity[30];
+ char msg_type[30];
+
+ PrintMessageSeverity(message_severity, msg_severity);
+ PrintMessageType(message_type, msg_type);
+
+ fprintf((FILE *)user_data, "%s(%s / %s): object: 0x%" PRIx64 " type: %d msgNum: %d - %s\n", callback_data->pMessageIdName,
+ msg_severity, msg_type, callback_data->pObjects[0].objectHandle, callback_data->pObjects[0].objectType,
+ callback_data->messageIdNumber, callback_data->pMessage);
+ fflush((FILE *)user_data);
+
+ return false;
}
-template <typename HANDLE_T>
-uint64_t HandleToUint64(HANDLE_T h);
+static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
+ VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
+ const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
+#ifdef WIN32
+ char buf[2048];
+ char msg_severity[30];
+ char msg_type[30];
-static inline uint64_t HandleToUint64(uint64_t h) { return h; }
+ PrintMessageSeverity(message_severity, msg_severity);
+ PrintMessageType(message_type, msg_type);
+
+ _snprintf(buf, sizeof(buf) - 1, "%s (%s / %s): object: 0x%" PRIxPTR " type: %d msgNum: %d - %s\n",
+ callback_data->pMessageIdName, msg_severity, msg_type, callback_data->pObjects[0].objectHandle,
+ callback_data->pObjects[0].objectType, callback_data->messageIdNumber, callback_data->pMessage);
+
+ OutputDebugString(buf);
+#endif
+
+ return false;
+}
+
+// This utility converts from the VkDebugUtilsLabelEXT structure into the logging version of the structure.
+// In the logging version, we only record what we absolutely need to convey back to the callbacks.
+static inline void InsertLabelIntoLog(const VkDebugUtilsLabelEXT *utils_label, std::vector<LoggingLabelData> &log_vector) {
+ LoggingLabelData log_label_data = {};
+ log_label_data.name = utils_label->pLabelName;
+ log_label_data.color[0] = utils_label->color[0];
+ log_label_data.color[1] = utils_label->color[1];
+ log_label_data.color[2] = utils_label->color[2];
+ log_label_data.color[3] = utils_label->color[3];
+ log_vector.push_back(log_label_data);
+}
+
+static void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue, const VkDebugUtilsLabelEXT *label_info) {
+ if (nullptr != label_info && nullptr != label_info->pLabelName) {
+ auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
+ if (label_iter == report_data->debugUtilsQueueLabels->end()) {
+ std::vector<LoggingLabelData> new_queue_labels;
+ InsertLabelIntoLog(label_info, new_queue_labels);
+ report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
+ } else {
+ // If the last thing was a label insert, we need to pop it off of the label vector before any
+ // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
+ // temporary location that exists until the next operation occurs. In this case, a new
+ // "vkQueueBeginDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
+ if (report_data->queueLabelHasInsert) {
+ report_data->queueLabelHasInsert = false;
+ label_iter->second.pop_back();
+ }
+ InsertLabelIntoLog(label_info, label_iter->second);
+ }
+ }
+}
+
+static void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
+ auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
+ if (label_iter != report_data->debugUtilsQueueLabels->end()) {
+ // If the last thing was a label insert, we need to pop it off of the label vector before any
+ // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
+ // temporary location that exists until the next operation occurs. In this case, a
+ // "vkQueueEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
+ if (report_data->queueLabelHasInsert) {
+ report_data->queueLabelHasInsert = false;
+ label_iter->second.pop_back();
+ }
+ // Now pop the normal item
+ label_iter->second.pop_back();
+ }
+}
+
+static void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue, const VkDebugUtilsLabelEXT *label_info) {
+ if (nullptr != label_info && nullptr != label_info->pLabelName) {
+ auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
+ if (label_iter == report_data->debugUtilsQueueLabels->end()) {
+ std::vector<LoggingLabelData> new_queue_labels;
+ InsertLabelIntoLog(label_info, new_queue_labels);
+ report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
+ } else {
+ // If the last thing was a label insert, we need to pop it off of the label vector before any
+ // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
+ // temporary location that exists until the next operation occurs. In this case, a new
+ // "vkQueueInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
+ if (report_data->queueLabelHasInsert) {
+ label_iter->second.pop_back();
+ }
+ // Insert this new label and mark it as one that has been "inserted" so we can remove it on
+ // the next queue label operation.
+ InsertLabelIntoLog(label_info, label_iter->second);
+ report_data->queueLabelHasInsert = true;
+ }
+ }
+}
+
+static void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
+ const VkDebugUtilsLabelEXT *label_info) {
+ if (nullptr != label_info && nullptr != label_info->pLabelName) {
+ auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
+ if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
+ std::vector<LoggingLabelData> new_cmdbuf_labels;
+ InsertLabelIntoLog(label_info, new_cmdbuf_labels);
+ report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
+ } else {
+ // If the last thing was a label insert, we need to pop it off of the label vector before any
+ // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
+ // temporary location that exists until the next operation occurs. In this case, a
+ // "vkCmdBeginDebugUtilsLabelEXT" has occurred erasing the inserted label.
+ if (report_data->cmdBufLabelHasInsert) {
+ report_data->cmdBufLabelHasInsert = false;
+ label_iter->second.pop_back();
+ }
+ InsertLabelIntoLog(label_info, label_iter->second);
+ }
+ }
+}
+
+static void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
+ auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
+ if (label_iter != report_data->debugUtilsCmdBufLabels->end()) {
+ // If the last thing was a label insert, we need to pop it off of the label vector before any
+ // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
+ // temporary location that exists until the next operation occurs. In this case, a
+ // "vkCmdEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
+ if (report_data->cmdBufLabelHasInsert) {
+ report_data->cmdBufLabelHasInsert = false;
+ label_iter->second.pop_back();
+ }
+ // Now pop the normal item
+ label_iter->second.pop_back();
+ }
+}
+
+static void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
+ const VkDebugUtilsLabelEXT *label_info) {
+ if (nullptr != label_info && nullptr != label_info->pLabelName) {
+ auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
+ if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
+ std::vector<LoggingLabelData> new_cmdbuf_labels;
+ InsertLabelIntoLog(label_info, new_cmdbuf_labels);
+ report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
+ } else {
+ // If the last thing was a label insert, we need to pop it off of the label vector before any
+ // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
+ // temporary location that exists until the next operation occurs. In this case, a new
+ // "vkCmdInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
+ if (report_data->cmdBufLabelHasInsert) {
+ label_iter->second.pop_back();
+ }
+ // Insert this new label and mark it as one that has been "inserted" so we can remove it on
+ // the next command buffer label operation.
+ InsertLabelIntoLog(label_info, label_iter->second);
+ report_data->cmdBufLabelHasInsert = true;
+ }
+ }
+}
#endif // LAYER_LOGGING_H
diff --git a/layers/vk_layer_utils.cpp b/layers/vk_layer_utils.cpp
index d788daf..629b19f 100644
--- a/layers/vk_layer_utils.cpp
+++ b/layers/vk_layer_utils.cpp
@@ -91,8 +91,9 @@
// If a vk_layer_settings.txt file is present and an application defines a debug callback, both callbacks
// will be active. If no vk_layer_settings.txt file is present, creating an application-defined debug
// callback will cause the default callbacks to be unregisterd and removed.
-VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugReportCallbackEXT> &logging_callback,
- const VkAllocationCallbacks *pAllocator, const char *layer_identifier) {
+VK_LAYER_EXPORT void layer_debug_report_actions(debug_report_data *report_data,
+ std::vector<VkDebugReportCallbackEXT> &logging_callback,
+ const VkAllocationCallbacks *pAllocator, const char *layer_identifier) {
VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
std::string report_flags_key = layer_identifier;
@@ -115,9 +116,9 @@
memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
dbgCreateInfo.flags = report_flags;
- dbgCreateInfo.pfnCallback = log_callback;
+ dbgCreateInfo.pfnCallback = report_log_callback;
dbgCreateInfo.pUserData = (void *)log_output;
- layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
+ layer_create_report_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
logging_callback.push_back(callback);
}
@@ -128,9 +129,9 @@
memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
dbgCreateInfo.flags = report_flags;
- dbgCreateInfo.pfnCallback = win32_debug_output_msg;
+ dbgCreateInfo.pfnCallback = report_win32_debug_output_msg;
dbgCreateInfo.pUserData = NULL;
- layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
+ layer_create_report_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
logging_callback.push_back(callback);
}
@@ -143,7 +144,64 @@
dbgCreateInfo.flags = report_flags;
dbgCreateInfo.pfnCallback = DebugBreakCallback;
dbgCreateInfo.pUserData = NULL;
- layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
+ layer_create_report_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
logging_callback.push_back(callback);
}
}
+
+VK_LAYER_EXPORT void layer_debug_messenger_actions(debug_report_data *report_data,
+ std::vector<VkDebugUtilsMessengerEXT> &logging_messenger,
+ const VkAllocationCallbacks *pAllocator, const char *layer_identifier) {
+ VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
+
+ std::string report_flags_key = layer_identifier;
+ std::string debug_action_key = layer_identifier;
+ std::string log_filename_key = layer_identifier;
+ report_flags_key.append(".report_flags");
+ debug_action_key.append(".debug_action");
+ log_filename_key.append(".log_filename");
+
+ // Initialize layer options
+ VkDebugReportFlagsEXT report_flags = GetLayerOptionFlags(report_flags_key, report_flags_option_definitions, 0);
+ VkLayerDbgActionFlags debug_action = GetLayerOptionFlags(debug_action_key, debug_actions_option_definitions, 0);
+ // Flag as default if these settings are not from a vk_layer_settings.txt file
+ bool default_layer_callback = (debug_action & VK_DBG_LAYER_ACTION_DEFAULT) ? true : false;
+ VkDebugUtilsMessengerCreateInfoEXT dbgCreateInfo;
+ memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
+ dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ dbgCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ if (report_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ }
+ if (report_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ }
+ if (report_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
+ dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ dbgCreateInfo.messageType |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ }
+ if (report_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
+ dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ }
+ if (report_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
+ dbgCreateInfo.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ }
+
+ if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) {
+ const char *log_filename = getLayerOption(log_filename_key.c_str());
+ FILE *log_output = getLayerLogOutput(log_filename, layer_identifier);
+ dbgCreateInfo.pfnUserCallback = messenger_log_callback;
+ dbgCreateInfo.pUserData = (void *)log_output;
+ layer_create_messenger_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &messenger);
+ logging_messenger.push_back(messenger);
+ }
+
+ messenger = VK_NULL_HANDLE;
+
+ if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
+ dbgCreateInfo.pfnUserCallback = messenger_win32_debug_output_msg;
+ dbgCreateInfo.pUserData = NULL;
+ layer_create_messenger_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &messenger);
+ logging_messenger.push_back(messenger);
+ }
+}
diff --git a/layers/vk_layer_utils.h b/layers/vk_layer_utils.h
index d1969c8..08574a5 100644
--- a/layers/vk_layer_utils.h
+++ b/layers/vk_layer_utils.h
@@ -37,10 +37,6 @@
#define VK_LAYER_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION)
-
-
-
-
typedef enum VkStringErrorFlagBits {
VK_STRING_ERROR_NONE = 0x00000000,
VK_STRING_ERROR_LENGTH = 0x00000001,
@@ -48,8 +44,13 @@
} VkStringErrorFlagBits;
typedef VkFlags VkStringErrorFlags;
-VK_LAYER_EXPORT void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugReportCallbackEXT> &logging_callback,
- const VkAllocationCallbacks *pAllocator, const char *layer_identifier);
+VK_LAYER_EXPORT void layer_debug_report_actions(debug_report_data *report_data,
+ std::vector<VkDebugReportCallbackEXT> &logging_callback,
+ const VkAllocationCallbacks *pAllocator, const char *layer_identifier);
+
+VK_LAYER_EXPORT void layer_debug_messenger_actions(debug_report_data *report_data,
+ std::vector<VkDebugUtilsMessengerEXT> &logging_messenger,
+ const VkAllocationCallbacks *pAllocator, const char *layer_identifier);
VK_LAYER_EXPORT VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
VK_LAYER_EXPORT bool white_list(const char *item, const char *whitelist);
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index 2f96665..f543f86 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -75,8 +75,8 @@
trampoline.c
wsi.c
wsi.h
- debug_report.c
- debug_report.h
+ debug_utils.c
+ debug_utils.h
gpa_helper.h
cJSON.c
cJSON.h
diff --git a/loader/debug_report.c b/loader/debug_report.c
deleted file mode 100644
index 04e55cc..0000000
--- a/loader/debug_report.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
- * Copyright (C) 2015-2016 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
- * Author: Jon Ashburn <jon@LunarG.com>
- *
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#ifndef WIN32
-#include <signal.h>
-#else
-#endif
-#include "vk_loader_platform.h"
-#include "debug_report.h"
-#include "vulkan/vk_layer.h"
-
-typedef void(VKAPI_PTR *PFN_stringCallback)(char *message);
-
-static const VkExtensionProperties debug_report_extension_info = {
- .extensionName = VK_EXT_DEBUG_REPORT_EXTENSION_NAME, .specVersion = VK_EXT_DEBUG_REPORT_SPEC_VERSION,
-};
-
-void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
- loader_add_to_ext_list(inst, ext_list, 1, &debug_report_extension_info);
-}
-
-void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
- ptr_instance->enabled_known_extensions.ext_debug_report = 0;
-
- for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
- if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
- ptr_instance->enabled_known_extensions.ext_debug_report = 1;
- return;
- }
- }
-}
-
-VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
- VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
- sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
- } else {
-#endif
- pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
- }
- if (!pNewDbgFuncNode) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
- memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
-
- pNewDbgFuncNode->msgCallback = callback;
- pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
- pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
- pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
- pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
- inst->DbgFunctionHead = pNewDbgFuncNode;
-
- return VK_SUCCESS;
-}
-
-static VKAPI_ATTR VkResult VKAPI_CALL
-debug_report_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
- struct loader_instance *inst = loader_get_instance(instance);
- loader_platform_thread_lock_mutex(&loader_lock);
- VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
- loader_platform_thread_unlock_mutex(&loader_lock);
- return result;
-}
-
-// Utility function to handle reporting
-VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
- uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
- VkBool32 bail = false;
- VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
- while (pTrav) {
- if (pTrav->msgFlags & msgFlags) {
- if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, pTrav->pUserData)) {
- bail = true;
- }
- }
- pTrav = pTrav->pNext;
- }
-
- return bail;
-}
-
-void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator) {
- VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
- VkLayerDbgFunctionNode *pPrev = pTrav;
-
- while (pTrav) {
- if (pTrav->msgCallback == callback) {
- pPrev->pNext = pTrav->pNext;
- if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- pAllocator->pfnFree(pAllocator->pUserData, pTrav);
- } else {
-#endif
- loader_instance_heap_free(inst, pTrav);
- }
- break;
- }
- pPrev = pTrav;
- pTrav = pTrav->pNext;
- }
-}
-
-// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
-// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
-// then allocates array that can hold that many structs, as well as that many
-// VkDebugReportCallbackEXT handles. It then copies each
-// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
-VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
- VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
- uint32_t n = *num_callbacks = 0;
- VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
- VkDebugReportCallbackEXT *pCallbacks = NULL;
-
- // NOTE: The loader is not using pAllocator, and so this function doesn't
- // either.
-
- const void *pNext = pChain;
- while (pNext) {
- // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
- if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
- n++;
- }
- pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
- }
- if (n == 0) {
- return VK_SUCCESS;
- }
-
-// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
- pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
- } else {
-#endif
- pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
- }
- if (!pInfos) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
-// 3rd, allocate memory for a unique handle for each callback:
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
- pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
- if (!pCallbacks) {
- pAllocator->pfnFree(pAllocator->pUserData, pInfos);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
- } else {
-#endif
- pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
- if (!pCallbacks) {
- free(pInfos);
- return VK_ERROR_OUT_OF_HOST_MEMORY;
- }
- }
- // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
- // vkDestroyInstance, and assign a unique handle to each callback (just
- // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
- pNext = pChain;
- while (pNext) {
- if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
- memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
- *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
- }
- pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
- }
-
- *num_callbacks = n;
- return VK_SUCCESS;
-}
-
-void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
- VkDebugReportCallbackEXT *callbacks) {
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- pAllocator->pfnFree(pAllocator->pUserData, infos);
- pAllocator->pfnFree(pAllocator->pUserData, callbacks);
- } else {
-#endif
- free(infos);
- free(callbacks);
- }
-}
-
-VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
- uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
- VkDebugReportCallbackEXT *callbacks) {
- VkResult rtn = VK_SUCCESS;
- for (uint32_t i = 0; i < num_callbacks; i++) {
- rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
- if (rtn != VK_SUCCESS) {
- for (uint32_t j = 0; j < i; j++) {
- util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
- }
- return rtn;
- }
- }
- return rtn;
-}
-
-void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
- VkDebugReportCallbackEXT *callbacks) {
- for (uint32_t i = 0; i < num_callbacks; i++) {
- util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
- }
-}
-
-static VKAPI_ATTR void VKAPI_CALL debug_report_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator) {
- struct loader_instance *inst = loader_get_instance(instance);
- loader_platform_thread_lock_mutex(&loader_lock);
-
- inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
-
- util_DestroyDebugReportCallback(inst, callback, pAllocator);
-
- loader_platform_thread_unlock_mutex(&loader_lock);
-}
-
-static VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType, uint64_t object,
- size_t location, int32_t msgCode, const char *pLayerPrefix,
- const char *pMsg) {
- struct loader_instance *inst = loader_get_instance(instance);
-
- inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
-}
-
-// This is the instance chain terminator function
-// for CreateDebugReportCallback
-VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
- const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkDebugReportCallbackEXT *pCallback) {
- VkDebugReportCallbackEXT *icd_info = NULL;
- const struct loader_icd_term *icd_term;
- struct loader_instance *inst = (struct loader_instance *)instance;
- VkResult res = VK_SUCCESS;
- uint32_t storage_idx;
- VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
- inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
- sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
- if (icd_info) {
- memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
- }
- } else {
-#endif
- icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
- }
- if (!icd_info) {
- res = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto out;
- }
-
- storage_idx = 0;
- for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
- if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
- continue;
- }
-
- res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
-
- if (res != VK_SUCCESS) {
- goto out;
- }
- storage_idx++;
- }
-
-// Setup the debug report callback in the terminator since a layer may want
-// to grab the information itself (RenderDoc) and then return back to the
-// user callback a sub-set of the messages.
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
- if (pAllocator != NULL) {
- pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
- sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
- } else {
-#else
- {
-#endif
- pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
- VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
- }
- if (!pNewDbgFuncNode) {
- res = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto out;
- }
- memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
-
- pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
- pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
- pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
- pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
- inst->DbgFunctionHead = pNewDbgFuncNode;
-
- *(VkDebugReportCallbackEXT **)pCallback = icd_info;
- pNewDbgFuncNode->msgCallback = *pCallback;
-
-out:
-
- // Roll back on errors
- if (VK_SUCCESS != res) {
- storage_idx = 0;
- for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
- if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
- continue;
- }
-
- if (icd_info && icd_info[storage_idx]) {
- icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
- }
- storage_idx++;
- }
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- if (NULL != pNewDbgFuncNode) {
- pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
- }
- if (NULL != icd_info) {
- pAllocator->pfnFree(pAllocator->pUserData, icd_info);
- }
- } else {
-#endif
- if (NULL != pNewDbgFuncNode) {
- free(pNewDbgFuncNode);
- }
- if (NULL != icd_info) {
- free(icd_info);
- }
- }
- }
-
- return res;
-}
-
-// This is the instance chain terminator function for DestroyDebugReportCallback
-VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator) {
- uint32_t storage_idx;
- VkDebugReportCallbackEXT *icd_info;
- const struct loader_icd_term *icd_term;
-
- struct loader_instance *inst = (struct loader_instance *)instance;
- icd_info = *(VkDebugReportCallbackEXT **)&callback;
- storage_idx = 0;
- for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
- if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
- continue;
- }
-
- if (icd_info[storage_idx]) {
- icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
- }
- storage_idx++;
- }
-
-#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
- {
-#else
- if (pAllocator != NULL) {
- pAllocator->pfnFree(pAllocator->pUserData, icd_info);
- } else {
-#endif
- free(icd_info);
- }
-}
-
-// This is the instance chain terminator function for DebugReportMessage
-VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
- int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
- const struct loader_icd_term *icd_term;
-
- struct loader_instance *inst = (struct loader_instance *)instance;
-
- loader_platform_thread_lock_mutex(&loader_lock);
- for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
- if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
- icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
- pMsg);
- }
- }
-
- // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value
- // as there is nothing to bail from at this point.
-
- util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
-
- loader_platform_thread_unlock_mutex(&loader_lock);
-}
-
-bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
- // debug_report is currently advertised to be supported by the loader,
- // so always return the entry points if name matches and it's enabled
- *addr = NULL;
-
- if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
- *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_CreateDebugReportCallbackEXT
- : NULL;
- return true;
- }
- if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
- *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DestroyDebugReportCallbackEXT
- : NULL;
- return true;
- }
- if (!strcmp("vkDebugReportMessageEXT", name)) {
- *addr = (ptr_instance->enabled_known_extensions.ext_debug_report == 1) ? (void *)debug_report_DebugReportMessageEXT : NULL;
- return true;
- }
- return false;
-}
diff --git a/loader/debug_report.h b/loader/debug_report.h
deleted file mode 100644
index 89074d7..0000000
--- a/loader/debug_report.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2015-2016 The Khronos Group Inc.
- * Copyright (c) 2015-2016 Valve Corporation
- * Copyright (c) 2015-2016 LunarG, Inc.
- * Copyright (C) 2015-2016 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
- * Author: Jon Ashburn <jon@lunarg.com>
- *
- */
-
-#include "vk_loader_platform.h"
-#include "loader.h"
-
-// CreateMsgCallback is global and needs to be
-// applied to all layers and ICDs.
-// What happens if a layer is enabled on both the instance chain
-// as well as the device chain and a call to CreateMsgCallback is made?
-// Do we need to make sure that each layer / driver only gets called once?
-// Should a layer implementing support for CreateMsgCallback only be allowed (?)
-// to live on one chain? Or maybe make it the application's responsibility.
-// If the app enables DRAW_STATE on at both CreateInstance time and CreateDevice
-// time, CreateMsgCallback will call the DRAW_STATE layer twice. Once via
-// the instance chain and once via the device chain.
-// The loader should only return the DEBUG_REPORT extension as supported
-// for the GetGlobalExtensionSupport call. That should help eliminate one
-// duplication.
-// Since the instance chain requires us iterating over the available ICDs
-// and each ICD will have it's own unique MsgCallback object we need to
-// track those objects to give back the right one.
-// This also implies that the loader has to intercept vkDestroyObject and
-// if the extension is enabled and the object type is a MsgCallback then
-// we must translate the object into the proper ICD specific ones.
-// DestroyObject works on a device chain. Should not be what's destroying
-// the MsgCallback object. That needs to be an instance thing. So, since
-// we used an instance to create it, we need a custom Destroy that also
-// takes an instance. That way we can iterate over the ICDs properly.
-// Example use:
-// CreateInstance: DEBUG_REPORT
-// Loader will create instance chain with enabled extensions.
-// TODO: Should validation layers be enabled here? If not, they will not be in
-// the instance chain.
-// fn = GetProcAddr(INSTANCE, "vkCreateMsgCallback") -> point to loader's
-// vkCreateMsgCallback
-// App creates a callback object: fn(..., &MsgCallbackObject1)
-// Have only established the instance chain so far. Loader will call the
-// instance chain.
-// Each layer in the instance chain will call down to the next layer,
-// terminating with
-// the CreateMsgCallback loader terminator function that creates the actual
-// MsgCallbackObject1 object.
-// The loader CreateMsgCallback terminator will iterate over the ICDs.
-// Calling each ICD that supports vkCreateMsgCallback and collect answers in
-// icd_msg_callback_map here.
-// As result is sent back up the chain each layer has opportunity to record the
-// callback operation and
-// appropriate MsgCallback object.
-// ...
-// Any reports matching the flags set in MsgCallbackObject1 will generate the
-// defined callback behavior
-// in the layer / ICD that initiated that report.
-// ...
-// CreateDevice: MemTracker:...
-// App does not include DEBUG_REPORT as that is a global extension.
-// TODO: GetExtensionSupport must not report DEBUG_REPORT when using instance.
-// App MUST include any desired validation layers or they will not participate
-// in the device call chain.
-// App creates a callback object: fn(..., &MsgCallbackObject2)
-// Loader's vkCreateMsgCallback is called.
-// Loader sends call down instance chain - this is a global extension - any
-// validation layer that was
-// enabled at CreateInstance will be able to register the callback. Loader will
-// iterate over the ICDs and
-// will record the ICD's version of the MsgCallback2 object here.
-// ...
-// Any report will go to the layer's report function and it will check the flags
-// for MsgCallbackObject1
-// and MsgCallbackObject2 and take the appropriate action as indicated by the
-// app.
-// ...
-// App calls vkDestroyMsgCallback( MsgCallbackObject1 )
-// Loader's DestroyMsgCallback is where call starts. DestroyMsgCallback will be
-// sent down instance chain
-// ending in the loader's DestroyMsgCallback terminator which will iterate over
-// the ICD's destroying each
-// ICD version of that MsgCallback object and then destroy the loader's version
-// of the object.
-// Any reports generated after this will only have MsgCallbackObject2 available.
-
-void debug_report_add_instance_extensions(const struct loader_instance *inst, struct loader_extension_list *ext_list);
-
-void debug_report_create_instance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
-
-bool debug_report_instance_gpa(struct loader_instance *ptr_instance, const char *name, void **addr);
-
-VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
- const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkDebugReportCallbackEXT *pCallback);
-
-VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator);
-
-VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
- int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
-
-VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback);
-
-void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator);
-
-VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
- VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks);
-void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
- VkDebugReportCallbackEXT *callbacks);
-VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
- uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
- VkDebugReportCallbackEXT *callbacks);
-
-void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
- VkDebugReportCallbackEXT *callbacks);
-
-VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
- uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
diff --git a/loader/debug_utils.c b/loader/debug_utils.c
new file mode 100644
index 0000000..3689131
--- /dev/null
+++ b/loader/debug_utils.c
@@ -0,0 +1,1004 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@LunarG.com>
+ * Author: Mark Young <marky@lunarg.com>
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#ifndef WIN32
+#include <signal.h>
+#else
+#endif
+#include "vk_loader_platform.h"
+#include "debug_utils.h"
+#include "vulkan/vk_layer.h"
+#include "vk_object_types.h"
+
+// VK_EXT_debug_report related items
+
+VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger) {
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = true;
+ pNewDbgFuncNode->messenger.messenger = messenger;
+ pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
+ pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
+ pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ return VK_SUCCESS;
+}
+
+static VKAPI_ATTR VkResult VKAPI_CALL
+debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+ VkResult result = inst->disp->layer_inst_disp.CreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return result;
+}
+
+VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ VkBool32 bail = false;
+
+ if (NULL != pCallbackData && NULL != pCallbackData->pObjects && 0 < pCallbackData->objectCount) {
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkDebugReportObjectTypeEXT object_type;
+ VkDebugReportFlagsEXT object_flags = 0;
+ uint64_t object_handle;
+
+ debug_utils_AnnotFlagsToReportFlags(messageSeverity, messageTypes, &object_flags);
+ debug_utils_AnnotObjectToDebugReportObject(pCallbackData->pObjects, &object_type, &object_handle);
+
+ while (pTrav) {
+ if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & messageSeverity) &&
+ (pTrav->messenger.messageType & messageTypes)) {
+ if (pTrav->messenger.pfnUserCallback(messageSeverity, messageTypes, pCallbackData, pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+ if (!pTrav->is_messenger && pTrav->report.msgFlags & object_flags) {
+ if (pTrav->report.pfnMsgCallback(object_flags, object_type, object_handle, 0, pCallbackData->messageIdNumber,
+ pCallbackData->pMessageIdName, pCallbackData->pMessage, pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+
+ pTrav = pTrav->pNext;
+ }
+ }
+
+ return bail;
+}
+
+void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkLayerDbgFunctionNode *pPrev = pTrav;
+
+ while (pTrav) {
+ if (pTrav->is_messenger && pTrav->messenger.messenger == messenger) {
+ pPrev->pNext = pTrav->pNext;
+ if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+ } else {
+#endif
+ loader_instance_heap_free(inst, pTrav);
+ }
+ break;
+ }
+ pPrev = pTrav;
+ pTrav = pTrav->pNext;
+ }
+}
+
+// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
+// counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
+// then allocates array that can hold that many structs, as well as that many
+// VkDebugUtilsMessengerEXT handles. It then copies each
+// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
+VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
+ uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
+ VkDebugUtilsMessengerEXT **messengers) {
+ uint32_t n = *num_messengers = 0;
+ VkDebugUtilsMessengerCreateInfoEXT *pInfos = NULL;
+ VkDebugUtilsMessengerEXT *pMessengers = NULL;
+
+ const void *pNext = pChain;
+ while (pNext) {
+ // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
+ if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ n++;
+ }
+ pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
+ }
+ if (n == 0) {
+ return VK_SUCCESS;
+ }
+
+// 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerCreateInfoEXT), sizeof(void *),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ } else {
+#endif
+ pInfos = *infos = ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
+ }
+ if (!pInfos) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+// 3rd, allocate memory for a unique handle for each callback:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugUtilsMessengerEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (NULL == pMessengers) {
+ pAllocator->pfnFree(pAllocator->pUserData, pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ } else {
+#endif
+ pMessengers = *messengers = ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
+ if (NULL == pMessengers) {
+ free(pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+ // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
+ // vkDestroyInstance, and assign a unique handle to each messenger (just
+ // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
+ pNext = pChain;
+ while (pNext) {
+ if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
+ *pMessengers++ = (VkDebugUtilsMessengerEXT)(uintptr_t)pInfos++;
+ }
+ pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+ }
+
+ *num_messengers = n;
+ return VK_SUCCESS;
+}
+
+void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, infos);
+ pAllocator->pfnFree(pAllocator->pUserData, messengers);
+ } else {
+#endif
+ free(infos);
+ free(messengers);
+ }
+}
+
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers) {
+ VkResult rtn = VK_SUCCESS;
+ for (uint32_t i = 0; i < num_messengers; i++) {
+ rtn = util_CreateDebugUtilsMessenger(inst, &infos[i], pAllocator, messengers[i]);
+ if (rtn != VK_SUCCESS) {
+ for (uint32_t j = 0; j < i; j++) {
+ util_DestroyDebugUtilsMessenger(inst, messengers[j], pAllocator);
+ }
+ return rtn;
+ }
+ }
+ return rtn;
+}
+
+void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers) {
+ for (uint32_t i = 0; i < num_messengers; i++) {
+ util_DestroyDebugUtilsMessenger(inst, messengers[i], pAllocator);
+ }
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(
+ VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ struct loader_instance *inst = loader_get_instance(instance);
+
+ inst->disp->layer_inst_disp.SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, pCallbackData);
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ inst->disp->layer_inst_disp.DestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator);
+
+ util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// This is the instance chain terminator function for CreateDebugUtilsMessenger
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger) {
+ VkDebugUtilsMessengerEXT *icd_info = NULL;
+ const struct loader_icd_term *icd_term;
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ VkResult res = VK_SUCCESS;
+ uint32_t storage_idx;
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ icd_info = ((VkDebugUtilsMessengerEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
+ inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT),
+ sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (icd_info) {
+ memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT));
+ }
+ } else {
+#endif
+ icd_info = calloc(sizeof(VkDebugUtilsMessengerEXT), inst->total_icd_count);
+ }
+ if (!icd_info) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (!icd_term->dispatch.CreateDebugUtilsMessengerEXT) {
+ continue;
+ }
+
+ res = icd_term->dispatch.CreateDebugUtilsMessengerEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ storage_idx++;
+ }
+
+// Setup the debug report callback in the terminator since a layer may want
+// to grab the information itself (RenderDoc) and then return back to the
+// user callback a sub-set of the messages.
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#else
+ {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = true;
+ pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
+ pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
+ pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ *(VkDebugUtilsMessengerEXT **)pMessenger = icd_info;
+ pNewDbgFuncNode->messenger.messenger = *pMessenger;
+
+out:
+
+ // Roll back on errors
+ if (VK_SUCCESS != res) {
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+ continue;
+ }
+
+ if (icd_info && icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ if (NULL != pNewDbgFuncNode) {
+ pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ }
+ } else {
+#endif
+ if (NULL != pNewDbgFuncNode) {
+ free(pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ free(icd_info);
+ }
+ }
+ }
+
+ return res;
+}
+
+// This is the instance chain terminator function for DestroyDebugUtilsMessenger
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator) {
+ uint32_t storage_idx;
+ VkDebugUtilsMessengerEXT *icd_info;
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ icd_info = *(VkDebugUtilsMessengerEXT **)&messenger;
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
+ continue;
+ }
+
+ if (icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugUtilsMessengerEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ } else {
+#endif
+ free(icd_info);
+ }
+}
+
+// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
+VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (icd_term->dispatch.SubmitDebugUtilsMessageEXT != NULL) {
+ icd_term->dispatch.SubmitDebugUtilsMessageEXT(icd_term->instance, messageSeverity, messageTypes, pCallbackData);
+ }
+ }
+
+ // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value
+ // as there is nothing to bail from at this point.
+
+ util_SubmitDebugUtilsMessageEXT(inst, messageSeverity, messageTypes, pCallbackData);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// VK_EXT_debug_report related items
+
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = false;
+ pNewDbgFuncNode->report.msgCallback = callback;
+ pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
+ pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ return VK_SUCCESS;
+}
+
+static VKAPI_ATTR VkResult VKAPI_CALL
+debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+ VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);
+ loader_platform_thread_unlock_mutex(&loader_lock);
+ return result;
+}
+
+// Utility function to handle reporting
+VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+ uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+ VkBool32 bail = false;
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity;
+ VkDebugUtilsMessageTypeFlagsEXT types;
+ VkDebugUtilsMessengerCallbackDataEXT callback_data;
+ VkDebugUtilsObjectNameInfoEXT object_name;
+
+ debug_utils_ReportFlagsToAnnotFlags(msgFlags, false, &severity, &types);
+ debug_utils_ReportObjectToAnnotObject(objectType, srcObject, &object_name);
+
+ callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.pNext = NULL;
+ callback_data.flags = 0;
+ callback_data.pMessageIdName = pLayerPrefix;
+ callback_data.messageIdNumber = msgCode;
+ callback_data.pMessage = pMsg;
+ callback_data.cmdBufLabelCount = 0;
+ callback_data.pCmdBufLabels = NULL;
+ callback_data.queueLabelCount = 0;
+ callback_data.pQueueLabels = NULL;
+ callback_data.objectCount = 1;
+ callback_data.pObjects = &object_name;
+
+ while (pTrav) {
+ if (!pTrav->is_messenger && pTrav->report.msgFlags & msgFlags) {
+ if (pTrav->report.pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg,
+ pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+ if (pTrav->is_messenger && (pTrav->messenger.messageSeverity & severity) && (pTrav->messenger.messageType & types)) {
+ if (pTrav->messenger.pfnUserCallback(severity, types, &callback_data, pTrav->pUserData)) {
+ bail = true;
+ }
+ }
+
+ pTrav = pTrav->pNext;
+ }
+
+ return bail;
+}
+
+void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
+ VkLayerDbgFunctionNode *pPrev = pTrav;
+
+ while (pTrav) {
+ if (!pTrav->is_messenger && pTrav->report.msgCallback == callback) {
+ pPrev->pNext = pTrav->pNext;
+ if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, pTrav);
+ } else {
+#endif
+ loader_instance_heap_free(inst, pTrav);
+ }
+ break;
+ }
+ pPrev = pTrav;
+ pTrav = pTrav->pNext;
+ }
+}
+
+// This utility (used by vkInstanceCreateInfo(), looks at a pNext chain. It
+// counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
+// then allocates array that can hold that many structs, as well as that many
+// VkDebugReportCallbackEXT handles. It then copies each
+// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
+VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
+ VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks) {
+ uint32_t n = *num_callbacks = 0;
+ VkDebugReportCallbackCreateInfoEXT *pInfos = NULL;
+ VkDebugReportCallbackEXT *pCallbacks = NULL;
+
+ const void *pNext = pChain;
+ while (pNext) {
+ // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
+ if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+ n++;
+ }
+ pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
+ }
+ if (n == 0) {
+ return VK_SUCCESS;
+ }
+
+// 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugReportCallbackCreateInfoEXT), sizeof(void *),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ } else {
+#endif
+ pInfos = *infos = ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
+ }
+ if (!pInfos) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+// 3rd, allocate memory for a unique handle for each callback:
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(
+ pAllocator->pUserData, n * sizeof(VkDebugReportCallbackEXT), sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (!pCallbacks) {
+ pAllocator->pfnFree(pAllocator->pUserData, pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ } else {
+#endif
+ pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
+ if (!pCallbacks) {
+ free(pInfos);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+ // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
+ // vkDestroyInstance, and assign a unique handle to each callback (just
+ // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
+ pNext = pChain;
+ while (pNext) {
+ if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
+ memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
+ *pCallbacks++ = (VkDebugReportCallbackEXT)(uintptr_t)pInfos++;
+ }
+ pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
+ }
+
+ *num_callbacks = n;
+ return VK_SUCCESS;
+}
+
+void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks) {
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, infos);
+ pAllocator->pfnFree(pAllocator->pUserData, callbacks);
+ } else {
+#endif
+ free(infos);
+ free(callbacks);
+ }
+}
+
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks) {
+ VkResult rtn = VK_SUCCESS;
+ for (uint32_t i = 0; i < num_callbacks; i++) {
+ rtn = util_CreateDebugReportCallback(inst, &infos[i], pAllocator, callbacks[i]);
+ if (rtn != VK_SUCCESS) {
+ for (uint32_t j = 0; j < i; j++) {
+ util_DestroyDebugReportCallback(inst, callbacks[j], pAllocator);
+ }
+ return rtn;
+ }
+ }
+ return rtn;
+}
+
+void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
+ VkDebugReportCallbackEXT *callbacks) {
+ for (uint32_t i = 0; i < num_callbacks; i++) {
+ util_DestroyDebugReportCallback(inst, callbacks[i], pAllocator);
+ }
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ struct loader_instance *inst = loader_get_instance(instance);
+ loader_platform_thread_lock_mutex(&loader_lock);
+
+ inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
+
+ util_DestroyDebugReportCallback(inst, callback, pAllocator);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+static VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType, uint64_t object,
+ size_t location, int32_t msgCode, const char *pLayerPrefix,
+ const char *pMsg) {
+ struct loader_instance *inst = loader_get_instance(instance);
+
+ inst->disp->layer_inst_disp.DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+}
+
+// This is the instance chain terminator function
+// for CreateDebugReportCallback
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugReportCallbackEXT *pCallback) {
+ VkDebugReportCallbackEXT *icd_info = NULL;
+ const struct loader_icd_term *icd_term;
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ VkResult res = VK_SUCCESS;
+ uint32_t storage_idx;
+ VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ icd_info = ((VkDebugReportCallbackEXT *)pAllocator->pfnAllocation(pAllocator->pUserData,
+ inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
+ sizeof(void *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+ if (icd_info) {
+ memset(icd_info, 0, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT));
+ }
+ } else {
+#endif
+ icd_info = calloc(sizeof(VkDebugReportCallbackEXT), inst->total_icd_count);
+ }
+ if (!icd_info) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (!icd_term->dispatch.CreateDebugReportCallbackEXT) {
+ continue;
+ }
+
+ res = icd_term->dispatch.CreateDebugReportCallbackEXT(icd_term->instance, pCreateInfo, pAllocator, &icd_info[storage_idx]);
+
+ if (res != VK_SUCCESS) {
+ goto out;
+ }
+ storage_idx++;
+ }
+
+// Setup the debug report callback in the terminator since a layer may want
+// to grab the information itself (RenderDoc) and then return back to the
+// user callback a sub-set of the messages.
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 0)
+ if (pAllocator != NULL) {
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)pAllocator->pfnAllocation(pAllocator->pUserData, sizeof(VkLayerDbgFunctionNode),
+ sizeof(int *), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ } else {
+#else
+ {
+#endif
+ pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_instance_heap_alloc(inst, sizeof(VkLayerDbgFunctionNode),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ }
+ if (!pNewDbgFuncNode) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
+
+ pNewDbgFuncNode->is_messenger = false;
+ pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
+ pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
+ pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
+ pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
+ inst->DbgFunctionHead = pNewDbgFuncNode;
+
+ *(VkDebugReportCallbackEXT **)pCallback = icd_info;
+ pNewDbgFuncNode->report.msgCallback = *pCallback;
+
+out:
+
+ // Roll back on errors
+ if (VK_SUCCESS != res) {
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+ continue;
+ }
+
+ if (icd_info && icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ if (NULL != pNewDbgFuncNode) {
+ pAllocator->pfnFree(pAllocator->pUserData, pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ }
+ } else {
+#endif
+ if (NULL != pNewDbgFuncNode) {
+ free(pNewDbgFuncNode);
+ }
+ if (NULL != icd_info) {
+ free(icd_info);
+ }
+ }
+ }
+
+ return res;
+}
+
+// This is the instance chain terminator function for DestroyDebugReportCallback
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ uint32_t storage_idx;
+ VkDebugReportCallbackEXT *icd_info;
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+ icd_info = *(VkDebugReportCallbackEXT **)&callback;
+ storage_idx = 0;
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
+ continue;
+ }
+
+ if (icd_info[storage_idx]) {
+ icd_term->dispatch.DestroyDebugReportCallbackEXT(icd_term->instance, icd_info[storage_idx], pAllocator);
+ }
+ storage_idx++;
+ }
+
+#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
+ {
+#else
+ if (pAllocator != NULL) {
+ pAllocator->pfnFree(pAllocator->pUserData, icd_info);
+ } else {
+#endif
+ free(icd_info);
+ }
+}
+
+// This is the instance chain terminator function for DebugReportMessage
+VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
+ int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+ const struct loader_icd_term *icd_term;
+
+ struct loader_instance *inst = (struct loader_instance *)instance;
+
+ loader_platform_thread_lock_mutex(&loader_lock);
+ for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
+ if (icd_term->dispatch.DebugReportMessageEXT != NULL) {
+ icd_term->dispatch.DebugReportMessageEXT(icd_term->instance, flags, objType, object, location, msgCode, pLayerPrefix,
+ pMsg);
+ }
+ }
+
+ // Now that all ICDs have seen the message, call the necessary callbacks. Ignoring "bail" return value
+ // as there is nothing to bail from at this point.
+
+ util_DebugReportMessage(inst, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+
+ loader_platform_thread_unlock_mutex(&loader_lock);
+}
+
+// General utilities
+
+static const VkExtensionProperties debug_utils_extension_info[] = {
+ {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
+ {VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION},
+};
+
+void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
+ loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
+ debug_utils_extension_info);
+}
+
+void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo) {
+ ptr_instance->enabled_known_extensions.ext_debug_report = 0;
+ ptr_instance->enabled_known_extensions.ext_debug_utils = 0;
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
+ ptr_instance->enabled_known_extensions.ext_debug_report = 1;
+ } else if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
+ ptr_instance->enabled_known_extensions.ext_debug_utils = 1;
+ }
+ }
+}
+
+bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr) {
+ bool ret_type = false;
+
+ *addr = NULL;
+
+ if (ptr_instance->enabled_known_extensions.ext_debug_report == 1) {
+ if (!strcmp("vkCreateDebugReportCallbackEXT", name)) {
+ *addr = (void *)debug_utils_CreateDebugReportCallbackEXT;
+ ret_type = true;
+ } else if (!strcmp("vkDestroyDebugReportCallbackEXT", name)) {
+ *addr = (void *)debug_utils_DestroyDebugReportCallbackEXT;
+ ret_type = true;
+ } else if (!strcmp("vkDebugReportMessageEXT", name)) {
+ *addr = (void *)debug_utils_DebugReportMessageEXT;
+ return true;
+ }
+ }
+ if (ptr_instance->enabled_known_extensions.ext_debug_utils == 1) {
+ if (!strcmp("vkCreateDebugUtilsMessengerEXT", name)) {
+ *addr = (void *)debug_utils_CreateDebugUtilsMessengerEXT;
+ ret_type = true;
+ } else if (!strcmp("vkDestroyDebugUtilsMessengerEXT", name)) {
+ *addr = (void *)debug_utils_DestroyDebugUtilsMessengerEXT;
+ ret_type = true;
+ } else if (!strcmp("vkSubmitDebugUtilsMessageEXT", name)) {
+ *addr = (void *)debug_utils_SubmitDebugUtilsMessageEXT;
+ ret_type = true;
+ }
+ }
+
+ return ret_type;
+}
+
+bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+ VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT *da_type) {
+ bool type_set = false;
+ if (NULL == da_severity || NULL == da_type) {
+ return false;
+ }
+ *da_type = 0;
+
+ if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ type_set = true;
+ } else if ((dr_flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ } else if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ } else if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
+ *da_severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ type_set = true;
+ }
+
+ if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ } else if (!type_set) {
+ if (default_flag_is_spec) {
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ } else {
+ *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ }
+
+ return true;
+}
+
+bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
+ if (NULL == dr_flags) {
+ return false;
+ }
+
+ *dr_flags = 0;
+
+ if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
+ if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ } else {
+ *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
+ }
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
+ } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
+ *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ }
+
+ return true;
+}
+
+bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
+ VkDebugUtilsObjectNameInfoEXT *da_object_name_info) {
+ if (NULL == da_object_name_info) {
+ return false;
+ }
+ da_object_name_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ da_object_name_info->pNext = NULL;
+ da_object_name_info->objectHandle = (uint64_t)(uintptr_t)object_handle;
+ da_object_name_info->pObjectName = NULL;
+ da_object_name_info->objectType = convertDebugReportObjectToCoreObject(dr_object_type);
+ return true;
+}
+
+bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
+ VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle) {
+ if (NULL == da_object_name_info || NULL == dr_object_type || NULL == dr_object_handle) {
+ return false;
+ }
+ *dr_object_type = convertCoreObjectToDebugReportObject(da_object_name_info->objectType);
+ *dr_object_handle = da_object_name_info->objectHandle;
+ return true;
+}
diff --git a/loader/debug_utils.h b/loader/debug_utils.h
new file mode 100644
index 0000000..c33a6fc
--- /dev/null
+++ b/loader/debug_utils.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2017 The Khronos Group Inc.
+ * Copyright (c) 2015-2017 Valve Corporation
+ * Copyright (c) 2015-2017 LunarG, Inc.
+ * Copyright (C) 2015-2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Mark Young <markyk@lunarg.com>
+ *
+ */
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+// General utilities
+
+void debug_utils_AddInstanceExtensions(const struct loader_instance *inst, struct loader_extension_list *ext_list);
+void debug_utils_CreateInstance(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
+bool debug_utils_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr);
+bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
+ VkDebugUtilsMessageSeverityFlagBitsEXT *da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT *da_type);
+bool debug_utils_AnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
+ VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags);
+bool debug_utils_ReportObjectToAnnotObject(VkDebugReportObjectTypeEXT dr_object_type, uint64_t object_handle,
+ VkDebugUtilsObjectNameInfoEXT *da_object_name_info);
+bool debug_utils_AnnotObjectToDebugReportObject(const VkDebugUtilsObjectNameInfoEXT *da_object_name_info,
+ VkDebugReportObjectTypeEXT *dr_object_type, uint64_t *dr_object_handle);
+
+// VK_EXT_debug_utils related items
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugUtilsMessengerEXT *pMessenger);
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator);
+VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance instance,
+ VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger);
+VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers);
+VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData);
+VkResult util_CopyDebugUtilsMessengerCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator,
+ uint32_t *num_messengers, VkDebugUtilsMessengerCreateInfoEXT **infos,
+ VkDebugUtilsMessengerEXT **messengers);
+void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
+ const VkAllocationCallbacks *pAllocator);
+void util_DestroyDebugUtilsMessengers(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_messengers, VkDebugUtilsMessengerEXT *messengers);
+void util_FreeDebugUtilsMessengerCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerCreateInfoEXT *infos,
+ VkDebugUtilsMessengerEXT *messengers);
+
+// VK_EXT_debug_report related items
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDebugReportCallbackEXT *pCallback);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
+ int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
+
+VkResult util_CreateDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback);
+VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator,
+ uint32_t num_callbacks, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks);
+VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+ uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg);
+VkResult util_CopyDebugReportCreateInfos(const void *pChain, const VkAllocationCallbacks *pAllocator, uint32_t *num_callbacks,
+ VkDebugReportCallbackCreateInfoEXT **infos, VkDebugReportCallbackEXT **callbacks);
+void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator);
+void util_DestroyDebugReportCallbacks(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator, uint32_t num_callbacks,
+ VkDebugReportCallbackEXT *callbacks);
+void util_FreeDebugReportCreateInfos(const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackCreateInfoEXT *infos,
+ VkDebugReportCallbackEXT *callbacks);
diff --git a/loader/extension_manual.c b/loader/extension_manual.c
index 65c625e..2b70af7 100644
--- a/loader/extension_manual.c
+++ b/loader/extension_manual.c
@@ -28,7 +28,7 @@
#include "vk_loader_extensions.h"
#include <vulkan/vk_icd.h>
#include "wsi.h"
-#include "debug_report.h"
+#include "debug_utils.h"
// ---- Manually added trampoline/terminator functions
diff --git a/loader/gpa_helper.h b/loader/gpa_helper.h
index 463e352..1196edf 100644
--- a/loader/gpa_helper.h
+++ b/loader/gpa_helper.h
@@ -20,7 +20,7 @@
*/
#include <string.h>
-#include "debug_report.h"
+#include "debug_utils.h"
#include "wsi.h"
static inline void *trampolineGetProcAddr(struct loader_instance *inst, const char *funcName) {
@@ -189,7 +189,7 @@
// Instance extensions
void *addr;
- if (debug_report_instance_gpa(inst, funcName, &addr)) return addr;
+ if (debug_utils_InstanceGpa(inst, funcName, &addr)) return addr;
if (wsi_swapchain_instance_gpa(inst, funcName, &addr)) return addr;
diff --git a/loader/loader.c b/loader/loader.c
index d4e0e02..92be90b 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -45,7 +45,7 @@
#include "vk_loader_platform.h"
#include "loader.h"
#include "gpa_helper.h"
-#include "debug_report.h"
+#include "debug_utils.h"
#include "wsi.h"
#include "vulkan/vk_icd.h"
#include "cJSON.h"
@@ -322,8 +322,46 @@
va_end(ap);
if (inst) {
- util_DebugReportMessage(inst, msg_type, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(uintptr_t)inst, 0, msg_code,
- "loader", msg);
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity;
+ VkDebugUtilsMessageTypeFlagsEXT type;
+ VkDebugUtilsMessengerCallbackDataEXT callback_data;
+ VkDebugUtilsObjectNameInfoEXT object_name;
+
+ if ((msg_type & LOADER_INFO_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ } else if ((msg_type & LOADER_WARN_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ } else if ((msg_type & LOADER_ERROR_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ } else if ((msg_type & LOADER_DEBUG_BIT) != 0) {
+ severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ }
+
+ if ((msg_type & LOADER_PERF_BIT) != 0) {
+ type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ } else {
+ type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+
+ callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ callback_data.pNext = NULL;
+ callback_data.flags = 0;
+ callback_data.pMessageIdName = "Loader Message";
+ callback_data.messageIdNumber = 0;
+ callback_data.pMessage = msg;
+ callback_data.queueLabelCount = 0;
+ callback_data.pQueueLabels = NULL;
+ callback_data.cmdBufLabelCount = 0;
+ callback_data.pCmdBufLabels = NULL;
+ callback_data.objectCount = 1;
+ callback_data.pObjects = &object_name;
+ object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ object_name.pNext = NULL;
+ object_name.objectType = VK_OBJECT_TYPE_INSTANCE;
+ object_name.objectHandle = (uint64_t)(uintptr_t)inst;
+ object_name.pObjectName = NULL;
+
+ util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data);
}
if (!(msg_type & g_loader_log_msgs)) {
@@ -1608,7 +1646,7 @@
};
// Traverse loader's extensions, adding non-duplicate extensions to the list
- debug_report_add_instance_extensions(inst, inst_exts);
+ debug_utils_AddInstanceExtensions(inst, inst_exts);
out:
return res;
diff --git a/loader/loader.h b/loader/loader.h
index ae928f9..9342e21 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -276,9 +276,12 @@
union loader_instance_extension_enables enabled_known_extensions;
VkLayerDbgFunctionNode *DbgFunctionHead;
- uint32_t num_tmp_callbacks;
- VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
- VkDebugReportCallbackEXT *tmp_callbacks;
+ uint32_t num_tmp_report_callbacks;
+ VkDebugReportCallbackCreateInfoEXT *tmp_report_create_infos;
+ VkDebugReportCallbackEXT *tmp_report_callbacks;
+ uint32_t num_tmp_messengers;
+ VkDebugUtilsMessengerCreateInfoEXT *tmp_messenger_create_infos;
+ VkDebugUtilsMessengerEXT *tmp_messengers;
VkAllocationCallbacks alloc_callbacks;
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 7915006..6b0464d 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -28,7 +28,7 @@
#include "vk_loader_platform.h"
#include "loader.h"
-#include "debug_report.h"
+#include "debug_utils.h"
#include "wsi.h"
#include "vk_loader_extensions.h"
#include "gpa_helper.h"
@@ -324,23 +324,42 @@
ptr_instance->app_api_minor_version = VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion);
}
- // Look for one or more debug report create info structures
+ // Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
// and setup a callback(s) for each one found.
- ptr_instance->num_tmp_callbacks = 0;
- ptr_instance->tmp_dbg_create_infos = NULL;
- ptr_instance->tmp_callbacks = NULL;
- if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_callbacks,
- &ptr_instance->tmp_dbg_create_infos, &ptr_instance->tmp_callbacks)) {
- // One or more were found, but allocation failed. Therefore, clean up
- // and fail this function:
+ ptr_instance->num_tmp_report_callbacks = 0;
+ ptr_instance->tmp_report_create_infos = NULL;
+ ptr_instance->tmp_report_callbacks = NULL;
+ ptr_instance->num_tmp_messengers = 0;
+ ptr_instance->tmp_messenger_create_infos = NULL;
+ ptr_instance->tmp_messengers = NULL;
+
+ // Handle cases of VK_EXT_debug_utils
+ if (util_CopyDebugUtilsMessengerCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_messengers,
+ &ptr_instance->tmp_messenger_create_infos, &ptr_instance->tmp_messengers)) {
+ // One or more were found, but allocation failed. Therefore, clean up and fail this function:
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
- } else if (ptr_instance->num_tmp_callbacks > 0) {
+ } else if (ptr_instance->num_tmp_messengers > 0) {
+ // Setup the temporary messenger(s) here to catch early issues:
+ if (util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
+ // Failure of setting up one or more of the messenger. Therefore, clean up and fail this function:
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ }
+
+ // Handle cases of VK_EXT_debug_report
+ if (util_CopyDebugReportCreateInfos(pCreateInfo->pNext, pAllocator, &ptr_instance->num_tmp_report_callbacks,
+ &ptr_instance->tmp_report_create_infos, &ptr_instance->tmp_report_callbacks)) {
+ // One or more were found, but allocation failed. Therefore, clean up and fail this function:
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ } else if (ptr_instance->num_tmp_report_callbacks > 0) {
// Setup the temporary callback(s) here to catch early issues:
- if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
- ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks)) {
- // Failure of setting up one or more of the callback. Therefore,
- // clean up and fail this function:
+ if (util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
+ // Failure of setting up one or more of the callback. Therefore, clean up and fail this function:
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
@@ -404,7 +423,7 @@
memset(ptr_instance->enabled_known_extensions.padding, 0, sizeof(uint64_t) * 4);
wsi_create_instance(ptr_instance, &ici);
- debug_report_create_instance(ptr_instance, &ici);
+ debug_utils_CreateInstance(ptr_instance, &ici);
extensions_create_instance(ptr_instance, &ici);
*pInstance = created_instance;
@@ -426,10 +445,19 @@
if (NULL != ptr_instance->disp) {
loader_instance_heap_free(ptr_instance, ptr_instance->disp);
}
- if (ptr_instance->num_tmp_callbacks > 0) {
- util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
- ptr_instance->tmp_callbacks);
- util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks);
+ if (ptr_instance->num_tmp_report_callbacks > 0) {
+ // Remove temporary VK_EXT_debug_report items
+ util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_callbacks);
+ util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos,
+ ptr_instance->tmp_report_callbacks);
+ }
+ if (ptr_instance->num_tmp_messengers > 0) {
+ // Remove temporary VK_EXT_debug_utils items
+ util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messengers);
+ util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos,
+ ptr_instance->tmp_messengers);
}
if (NULL != ptr_instance->expanded_activated_layer_list.list) {
@@ -445,9 +473,11 @@
loader_instance_heap_free(ptr_instance, ptr_instance);
} else {
- // Remove temporary debug_report callback
- util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
- ptr_instance->tmp_callbacks);
+ // Remove temporary VK_EXT_debug_report or VK_EXT_debug_utils items
+ util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messengers);
+ util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_callbacks);
}
if (loaderLocked) {
@@ -462,6 +492,7 @@
const VkLayerInstanceDispatchTable *disp;
struct loader_instance *ptr_instance = NULL;
bool callback_setup = false;
+ bool messenger_setup = false;
if (instance == VK_NULL_HANDLE) {
return;
@@ -477,10 +508,18 @@
ptr_instance->alloc_callbacks = *pAllocator;
}
- if (ptr_instance->num_tmp_callbacks > 0) {
- // Setup the temporary callback(s) here to catch cleanup issues:
- if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks,
- ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks)) {
+ if (ptr_instance->num_tmp_messengers > 0) {
+ // Setup the temporary VK_EXT_debug_utils messenger(s) here to catch cleanup issues:
+ if (!util_CreateDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers,
+ ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers)) {
+ messenger_setup = true;
+ }
+ }
+
+ if (ptr_instance->num_tmp_report_callbacks > 0) {
+ // Setup the temporary VK_EXT_debug_report callback(s) here to catch cleanup issues:
+ if (!util_CreateDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks)) {
callback_setup = true;
}
}
@@ -508,9 +547,15 @@
loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp);
}
+ if (messenger_setup) {
+ util_DestroyDebugUtilsMessengers(ptr_instance, pAllocator, ptr_instance->num_tmp_messengers, ptr_instance->tmp_messengers);
+ util_FreeDebugUtilsMessengerCreateInfos(pAllocator, ptr_instance->tmp_messenger_create_infos, ptr_instance->tmp_messengers);
+ }
+
if (callback_setup) {
- util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_callbacks, ptr_instance->tmp_callbacks);
- util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_dbg_create_infos, ptr_instance->tmp_callbacks);
+ util_DestroyDebugReportCallbacks(ptr_instance, pAllocator, ptr_instance->num_tmp_report_callbacks,
+ ptr_instance->tmp_report_callbacks);
+ util_FreeDebugReportCreateInfos(pAllocator, ptr_instance->tmp_report_create_infos, ptr_instance->tmp_report_callbacks);
}
loader_instance_heap_free(ptr_instance, ptr_instance->disp);
loader_instance_heap_free(ptr_instance, ptr_instance);
diff --git a/loader/vk_loader_layer.h b/loader/vk_loader_layer.h
index 425154d..dfcf5b2 100644
--- a/loader/vk_loader_layer.h
+++ b/loader/vk_loader_layer.h
@@ -21,11 +21,26 @@
*/
#pragma once
-// Linked list node for tree of debug callback functions
-typedef struct VkLayerDbgFunctionNode_ {
+// Linked list node for tree of debug callbacks
+typedef struct VkDebugReportContent {
VkDebugReportCallbackEXT msgCallback;
PFN_vkDebugReportCallbackEXT pfnMsgCallback;
VkFlags msgFlags;
+} VkDebugReportContent;
+
+typedef struct VkDebugUtilsMessengerContent {
+ VkDebugUtilsMessengerEXT messenger;
+ VkDebugUtilsMessageSeverityFlagsEXT messageSeverity;
+ VkDebugUtilsMessageTypeFlagsEXT messageType;
+ PFN_vkDebugUtilsMessengerCallbackEXT pfnUserCallback;
+} VkDebugUtilsMessengerContent;
+
+typedef struct VkLayerDbgFunctionNode_ {
+ bool is_messenger;
+ union {
+ VkDebugReportContent report;
+ VkDebugUtilsMessengerContent messenger;
+ };
void *pUserData;
struct VkLayerDbgFunctionNode_ *pNext;
} VkLayerDbgFunctionNode;
diff --git a/scripts/helper_file_generator.py b/scripts/helper_file_generator.py
index fb519b6..e460f96 100644
--- a/scripts/helper_file_generator.py
+++ b/scripts/helper_file_generator.py
@@ -747,7 +747,8 @@
#
# Object types header: create object enum type header file
def GenerateObjectTypesHeader(self):
- object_types_header = '// Object Type enum for validation layer internal object handling\n'
+ object_types_header = ''
+ object_types_header += '// Object Type enum for validation layer internal object handling\n'
object_types_header += 'typedef enum VulkanObjectType {\n'
object_types_header += ' kVulkanObjectTypeUnknown = 0,\n'
enum_num = 1
@@ -777,7 +778,7 @@
object_types_header += '\n'
object_types_header += '// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version\n'
object_types_header += 'const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {\n'
- object_types_header += ' VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // No Match\n'
+ object_types_header += ' VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeUnknown\n'
for object_type in type_list:
search_type = object_type.replace("kVulkanObjectType", "").lower()
for vk_object_type in self.debug_report_object_types:
@@ -793,7 +794,7 @@
object_types_header += '\n'
object_types_header += '// Helper array to get Official Vulkan VkObjectType enum from the internal layers version\n'
object_types_header += 'const VkObjectType get_object_type_enum[] = {\n'
- object_types_header += ' VK_OBJECT_TYPE_UNKNOWN, // No Match\n'
+ object_types_header += ' VK_OBJECT_TYPE_UNKNOWN, // kVulkanObjectTypeUnknown\n'
for object_type in type_list:
search_type = object_type.replace("kVulkanObjectType", "").lower()
for vk_object_type in self.core_object_types:
@@ -804,6 +805,47 @@
break
object_types_header += '};\n'
+ # Create a function to convert from VkDebugReportObjectTypeEXT to VkObjectType
+ object_types_header += '\n'
+ object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n'
+ object_types_header += 'static VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObjectTypeEXT debug_report_obj){\n'
+ object_types_header += ' if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT) {\n'
+ object_types_header += ' return VK_OBJECT_TYPE_UNKNOWN;\n'
+ for core_object_type in self.core_object_types:
+ core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower()
+ core_target_type = core_target_type.replace("_", "")
+ for dr_object_type in self.debug_report_object_types:
+ dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower()
+ dr_target_type = dr_target_type[:-4]
+ dr_target_type = dr_target_type.replace("_", "")
+ if core_target_type == dr_target_type:
+ object_types_header += ' } else if (debug_report_obj == %s) {\n' % dr_object_type
+ object_types_header += ' return %s;\n' % core_object_type
+ break
+ object_types_header += ' }\n'
+ object_types_header += ' return VK_OBJECT_TYPE_UNKNOWN;\n'
+ object_types_header += '}\n'
+
+ # Create a function to convert from VkObjectType to VkDebugReportObjectTypeEXT
+ object_types_header += '\n'
+ object_types_header += '// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType\n'
+ object_types_header += 'static VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(VkObjectType core_report_obj){\n'
+ object_types_header += ' if (core_report_obj == VK_OBJECT_TYPE_UNKNOWN) {\n'
+ object_types_header += ' return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n'
+ for core_object_type in self.core_object_types:
+ core_target_type = core_object_type.replace("VK_OBJECT_TYPE_", "").lower()
+ core_target_type = core_target_type.replace("_", "")
+ for dr_object_type in self.debug_report_object_types:
+ dr_target_type = dr_object_type.replace("VK_DEBUG_REPORT_OBJECT_TYPE_", "").lower()
+ dr_target_type = dr_target_type[:-4]
+ dr_target_type = dr_target_type.replace("_", "")
+ if core_target_type == dr_target_type:
+ object_types_header += ' } else if (core_report_obj == %s) {\n' % core_object_type
+ object_types_header += ' return %s;\n' % dr_object_type
+ break
+ object_types_header += ' }\n'
+ object_types_header += ' return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;\n'
+ object_types_header += '}\n'
return object_types_header
#
# Determine if a structure needs a safe_struct helper function
diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py
index a4a3f8f..ae2b3da 100644
--- a/scripts/loader_extension_generator.py
+++ b/scripts/loader_extension_generator.py
@@ -40,14 +40,25 @@
'VK_KHR_swapchain',
'VK_KHR_display_swapchain']
+ADD_INST_CMDS = ['vkCreateInstance',
+ 'vkEnumerateInstanceExtensionProperties',
+ 'vkEnumerateInstanceLayerProperties',
+ 'vkEnumerateInstanceVersion']
+
AVOID_EXT_NAMES = ['VK_EXT_debug_report']
+AVOID_CMD_NAMES = ['vkCreateDebugUtilsMessengerEXT',
+ 'vkDestroyDebugUtilsMessengerEXT',
+ 'vkSubmitDebugUtilsMessageEXT']
+
DEVICE_CMDS_NEED_TERM = ['vkGetDeviceProcAddr',
'vkCreateSwapchainKHR',
'vkCreateSharedSwapchainsKHR',
'vkGetDeviceGroupSurfacePresentModesKHR',
'vkDebugMarkerSetObjectTagEXT',
- 'vkDebugMarkerSetObjectNameEXT']
+ 'vkDebugMarkerSetObjectNameEXT',
+ 'vkSetDebugUtilsObjectNameEXT',
+ 'vkSetDebugUtilsObjectTagEXT']
ALIASED_CMDS = {
'vkEnumeratePhysicalDeviceGroupsKHR': 'vkEnumeratePhysicalDeviceGroups',
@@ -176,7 +187,7 @@
preamble += '#include "vk_loader_extensions.h"\n'
preamble += '#include <vulkan/vk_icd.h>\n'
preamble += '#include "wsi.h"\n'
- preamble += '#include "debug_report.h"\n'
+ preamble += '#include "debug_utils.h"\n'
preamble += '#include "extension_manual.h"\n'
elif self.genOpts.filename == 'vk_layer_dispatch_table.h':
@@ -467,7 +478,9 @@
commands = self.ext_commands
for cur_cmd in commands:
- if cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice':
+ is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+ if is_inst_handle_type:
+
if cur_cmd.ext_name != cur_extension_name:
if 'VK_VERSION_' in cur_cmd.ext_name:
table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:]
@@ -506,7 +519,9 @@
commands = self.ext_commands
for cur_cmd in commands:
- if cur_cmd.handle_type != 'VkInstance' and cur_cmd.handle_type != 'VkPhysicalDevice':
+ is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+ if not is_inst_handle_type:
+
if cur_cmd.ext_name != cur_extension_name:
if 'VK_VERSION_' in cur_cmd.ext_name:
table += '\n // ---- Core %s commands\n' % cur_cmd.ext_name[11:]
@@ -545,7 +560,7 @@
commands = self.ext_commands
for cur_cmd in commands:
- is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+ is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and
(cur_cmd.name != 'vkGetInstanceProcAddr' and cur_cmd.name != 'vkEnumerateDeviceLayerProperties')):
@@ -607,7 +622,7 @@
required = False
for cur_cmd in commands:
- is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+ is_inst_handle_type = cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
if ((is_inst_handle_type or cur_cmd.name in DEVICE_CMDS_NEED_TERM) and (cur_cmd.name not in skip_gipa_commands)):
if cur_cmd.ext_name != cur_extension_name:
@@ -666,7 +681,7 @@
terminators += '// Loader core instance terminators\n'
for cur_cmd in self.core_commands:
- is_inst_handle_type = cur_cmd.ext_type == 'instance' or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
+ is_inst_handle_type = cur_cmd.name in ADD_INST_CMDS or cur_cmd.handle_type == 'VkInstance' or cur_cmd.handle_type == 'VkPhysicalDevice'
if is_inst_handle_type:
mod_string = ''
new_terminator = cur_cmd.cdecl
@@ -878,6 +893,7 @@
for ext_cmd in self.ext_commands:
if (ext_cmd.ext_name in WSI_EXT_NAMES or
ext_cmd.ext_name in AVOID_EXT_NAMES or
+ ext_cmd.name in AVOID_CMD_NAMES or
ext_cmd.name in manual_ext_commands):
continue
@@ -937,8 +953,9 @@
return_prefix += 'return '
has_return_type = True
- if (ext_cmd.ext_type == 'instance' or ext_cmd.handle_type == 'VkPhysicalDevice' or
- 'DebugMarkerSetObject' in ext_cmd.name or ext_cmd.name in DEVICE_CMDS_NEED_TERM):
+ if (ext_cmd.handle_type == 'VkInstance' or ext_cmd.handle_type == 'VkPhysicalDevice' or
+ 'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name or
+ ext_cmd.name in DEVICE_CMDS_NEED_TERM):
requires_terminator = 1
if requires_terminator == 1:
@@ -973,6 +990,22 @@
funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->object;\n'
funcs += ' local_tag_info.object = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
funcs += ' }\n'
+ elif 'SetDebugUtilsObjectName' in ext_cmd.name:
+ funcs += ' VkDebugUtilsObjectNameInfoEXT local_name_info;\n'
+ funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));\n'
+ funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+ funcs += ' if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+ funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pNameInfo->objectHandle;\n'
+ funcs += ' local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
+ funcs += ' }\n'
+ elif 'SetDebugUtilsObjectTag' in ext_cmd.name:
+ funcs += ' VkDebugUtilsObjectTagInfoEXT local_tag_info;\n'
+ funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));\n'
+ funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+ funcs += ' if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+ funcs += ' struct loader_physical_device_tramp *phys_dev_tramp = (struct loader_physical_device_tramp *)(uintptr_t)pTagInfo->objectHandle;\n'
+ funcs += ' local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_tramp->phys_dev;\n'
+ funcs += ' }\n'
funcs += return_prefix
funcs += 'disp->'
@@ -985,9 +1018,9 @@
if param.type == 'VkPhysicalDevice':
funcs += 'unwrapped_phys_dev'
- elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo':
+ elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
funcs += '&local_name_info'
- elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo':
+ elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':
funcs += '&local_tag_info'
else:
funcs += param.name
@@ -1059,7 +1092,7 @@
count += 1
funcs += ');\n'
- elif has_surface == 1 and ext_cmd.ext_type == 'device':
+ elif has_surface == 1 and not (ext_cmd.handle_type == 'VkPhysicalDevice' or ext_cmd.handle_type == 'VkInstance'):
funcs += ' uint32_t icd_index = 0;\n'
funcs += ' struct loader_device *dev;\n'
funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);\n'
@@ -1096,7 +1129,7 @@
elif ext_cmd.handle_type == 'VkInstance':
funcs += '#error("Not implemented. Likely needs to be manually generated!");\n'
- elif 'DebugMarkerSetObject' in ext_cmd.name:
+ elif 'DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name:
funcs += ' uint32_t icd_index = 0;\n'
funcs += ' struct loader_device *dev;\n'
funcs += ' struct loader_icd_term *icd_term = loader_get_icd_and_device(%s, &dev, &icd_index);\n' % (ext_cmd.params[0].name)
@@ -1131,6 +1164,45 @@
funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n'
funcs += ' local_tag_info.object = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
funcs += ' }\n'
+ elif 'SetDebugUtilsObjectName' in ext_cmd.name:
+ funcs += ' VkDebugUtilsObjectNameInfoEXT local_name_info;\n'
+ funcs += ' memcpy(&local_name_info, pNameInfo, sizeof(VkDebugUtilsObjectNameInfoEXT));\n'
+ funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+ funcs += ' if (pNameInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+ funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pNameInfo->objectHandle;\n'
+ funcs += ' local_name_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n'
+ funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n'
+ funcs += ' } else if (pNameInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n'
+ funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
+ funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pNameInfo->objectHandle;\n'
+ funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n'
+ funcs += ' local_name_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
+ funcs += ' }\n'
+ elif 'SetDebugUtilsObjectTag' in ext_cmd.name:
+ funcs += ' VkDebugUtilsObjectTagInfoEXT local_tag_info;\n'
+ funcs += ' memcpy(&local_tag_info, pTagInfo, sizeof(VkDebugUtilsObjectTagInfoEXT));\n'
+ funcs += ' // If this is a physical device, we have to replace it with the proper one for the next call.\n'
+ funcs += ' if (pTagInfo->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n'
+ funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)pTagInfo->objectHandle;\n'
+ funcs += ' local_tag_info.objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n'
+ funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n'
+ funcs += ' } else if (pTagInfo->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n'
+ funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
+ funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pTagInfo->objectHandle;\n'
+ funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n'
+ funcs += ' local_tag_info.objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n'
+ funcs += ' }\n'
+ else:
+ funcs += ' if (%s->objectType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) {\n' % (ext_cmd.params[1].name)
+ funcs += ' struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)(uintptr_t)%s->objectHandle;\n' % (ext_cmd.params[1].name)
+ funcs += ' %s->objectHandle = (uint64_t)(uintptr_t)phys_dev_term->phys_dev;\n' % (ext_cmd.params[1].name)
+ funcs += ' // If this is a KHR_surface, and the ICD has created its own, we have to replace it with the proper one for the next call.\n'
+ funcs += ' } else if (%s->objectType == VK_OBJECT_TYPE_SURFACE_KHR) {\n' % (ext_cmd.params[1].name)
+ funcs += ' if (NULL != icd_term && NULL != icd_term->dispatch.CreateSwapchainKHR) {\n'
+ funcs += ' VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)%s->objectHandle;\n' % (ext_cmd.params[1].name)
+ funcs += ' if (NULL != icd_surface->real_icd_surfaces) {\n'
+ funcs += ' %s->objectHandle = (uint64_t)icd_surface->real_icd_surfaces[icd_index];\n' % (ext_cmd.params[1].name)
+ funcs += ' }\n'
funcs += ' }\n'
funcs += ' }\n'
funcs += ' return icd_term->dispatch.'
@@ -1145,9 +1217,9 @@
funcs += 'phys_dev_term->phys_dev'
elif param.type == 'VkSurfaceKHR':
funcs += 'icd_surface->real_icd_surfaces[icd_index]'
- elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pNameInfo':
+ elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pNameInfo':
funcs += '&local_name_info'
- elif 'DebugMarkerSetObject' in ext_cmd.name and param.name == 'pTagInfo':
+ elif ('DebugMarkerSetObject' in ext_cmd.name or 'SetDebugUtilsObject' in ext_cmd.name) and param.name == 'pTagInfo':
funcs += '&local_tag_info'
else:
funcs += param.name
@@ -1202,7 +1274,8 @@
for cur_cmd in self.ext_commands:
if ('VK_VERSION_' in cur_cmd.ext_name or
cur_cmd.ext_name in WSI_EXT_NAMES or
- cur_cmd.ext_name in AVOID_EXT_NAMES):
+ cur_cmd.ext_name in AVOID_EXT_NAMES or
+ cur_cmd.name in AVOID_CMD_NAMES ):
continue
if cur_cmd.ext_name != cur_extension_name:
@@ -1252,8 +1325,8 @@
create_func += ' for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {\n'
for ext in entries:
if ('VK_VERSION_' in ext.name or ext.name in WSI_EXT_NAMES or
- ext.name in AVOID_EXT_NAMES or ext.type == 'device' or
- ext.num_commands == 0):
+ ext.name in AVOID_EXT_NAMES or ext.name in AVOID_CMD_NAMES or
+ ext.type == 'device' or ext.num_commands == 0):
continue
if ext.name != cur_extension_name:
diff --git a/scripts/object_tracker_generator.py b/scripts/object_tracker_generator.py
index 405a5b7..26c1105 100644
--- a/scripts/object_tracker_generator.py
+++ b/scripts/object_tracker_generator.py
@@ -172,6 +172,17 @@
'vkGetDeviceQueue',
'vkGetSwapchainImagesKHR',
'vkCreateDescriptorSetLayout',
+ 'vkCreateDebugUtilsMessengerEXT',
+ 'vkDestroyDebugUtilsMessengerEXT',
+ 'vkSubmitDebugUtilsMessageEXT',
+ 'vkSetDebugUtilsObjectNameEXT',
+ 'vkSetDebugUtilsObjectTagEXT',
+ 'vkQueueBeginDebugUtilsLabelEXT',
+ 'vkQueueEndDebugUtilsLabelEXT',
+ 'vkQueueInsertDebugUtilsLabelEXT',
+ 'vkCmdBeginDebugUtilsLabelEXT',
+ 'vkCmdEndDebugUtilsLabelEXT',
+ 'vkCmdInsertDebugUtilsLabelEXT',
]
# These VUIDS are not implicit, but are best handled in this layer. Codegen for vkDestroy calls will generate a key
# which is translated here into a good VU. Saves ~40 checks.
diff --git a/scripts/parameter_validation_generator.py b/scripts/parameter_validation_generator.py
index edd49b5..4246eea 100644
--- a/scripts/parameter_validation_generator.py
+++ b/scripts/parameter_validation_generator.py
@@ -127,17 +127,12 @@
self.blacklist = [
'vkGetInstanceProcAddr',
'vkGetDeviceProcAddr',
- 'vkEnumerateInstanceLayerProperties',
- 'vkEnumerateInstanceExtensionsProperties',
- 'vkEnumerateDeviceLayerProperties',
- 'vkEnumerateDeviceExtensionsProperties',
- 'vkCreateDebugReportCallbackKHR',
- 'vkDestroyDebugReportCallbackKHR',
+ 'vkEnumerateInstanceVersion',
'vkEnumerateInstanceLayerProperties',
'vkEnumerateInstanceExtensionProperties',
'vkEnumerateDeviceLayerProperties',
- 'vkCmdDebugMarkerEndEXT',
'vkEnumerateDeviceExtensionProperties',
+ 'vkCmdDebugMarkerEndEXT',
]
self.validate_only = [
'vkCreateInstance',
@@ -150,6 +145,8 @@
'vkCreateCommandPool',
'vkCreateRenderPass',
'vkDestroyRenderPass',
+ 'vkCreateDebugUtilsMessengerEXT',
+ 'vkDestroyDebugUtilsMessengerEXT',
]
# Structure fields to ignore
self.structMemberBlacklist = { 'VkWriteDescriptorSet' : ['dstSet'] }
diff --git a/scripts/threading_generator.py b/scripts/threading_generator.py
index fd88909..4ac65d6 100644
--- a/scripts/threading_generator.py
+++ b/scripts/threading_generator.py
@@ -384,6 +384,8 @@
'vkEnumerateInstanceExtensionProperties',
'vkEnumerateDeviceLayerProperties',
'vkEnumerateDeviceExtensionProperties',
+ 'vkCreateDebugUtilsMessengerEXT',
+ 'vkDestroyDebugUtilsMessengerEXT',
]
if name in special_functions:
decls = self.makeCDecls(cmdinfo.elem)
@@ -392,7 +394,7 @@
self.appendSection('command', decls[0])
self.intercepts += [ ' {"%s", (void*)%s},' % (name,name[2:]) ]
return
- if "QueuePresentKHR" in name or ("DebugMarker" in name and "EXT" in name):
+ if "QueuePresentKHR" in name or (("DebugMarker" in name or "DebugUtilsObject" in name) and "EXT" in name):
self.appendSection('command', '// TODO - not wrapping EXT function ' + name)
return
# Determine first if this function needs to be intercepted
diff --git a/scripts/unique_objects_generator.py b/scripts/unique_objects_generator.py
index 78526a3..289a5bb 100644
--- a/scripts/unique_objects_generator.py
+++ b/scripts/unique_objects_generator.py
@@ -157,6 +157,8 @@
'vkGetDisplayModeProperties2KHR',
'vkCreateRenderPass',
'vkDestroyRenderPass',
+ 'vkSetDebugUtilsObjectNameEXT',
+ 'vkSetDebugUtilsObjectTagEXT',
]
# Commands shadowed by interface functions and are not implemented
self.interface_functions = [
@@ -165,10 +167,14 @@
'vkGetDisplayPlaneSupportedDisplaysKHR',
'vkGetDisplayModePropertiesKHR',
'vkGetDisplayPlaneCapabilitiesKHR',
- # DebugReport APIs are hooked, but handled separately in the source file
+ # VK_EXT_debug_report APIs are hooked, but handled separately in the source file
'vkCreateDebugReportCallbackEXT',
'vkDestroyDebugReportCallbackEXT',
'vkDebugReportMessageEXT',
+ # VK_EXT_debug_utils APIs are hooked, but handled separately in the source file
+ 'vkCreateDebugUtilsMessengerEXT',
+ 'vkDestroyDebugUtilsMessengerEXT',
+ 'vkSubmitDebugUtilsMessageEXT',
]
self.headerVersion = None
# Internal state - accumulators for different inner block text
diff --git a/scripts/vuid_mapping.py b/scripts/vuid_mapping.py
index e3dbfdf..88df867 100644
--- a/scripts/vuid_mapping.py
+++ b/scripts/vuid_mapping.py
@@ -1104,7 +1104,7 @@
# Convert a string VUID into numerical value
# See "VUID Mapping Details" comment above for more info
def convertVUID(vuid_string):
- """Convert a string-based VUID into a numberical value"""
+ """Convert a string-based VUID into a numerical value"""
#func_struct_update = False
#imp_param_update = False
if vuid_string in ['', None]: