aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Lobodzinski <mark@lunarg.com>2015-06-23 11:35:12 -0600
committerMark Lobodzinski <mark@lunarg.com>2015-06-23 11:35:12 -0600
commit85bc15acd850ec9dc9d21df0a9910129dd852f8e (patch)
treec89e5c1a71eb2af26cfa71553c89c6742ba7664a
parentf6e73a22d772a15c11d3da2087a5115295f6a749 (diff)
downloadusermoji-85bc15acd850ec9dc9d21df0a9910129dd852f8e.tar.xz
layers: ObjectTracker per-instance storage, updated logging
o Moved non-generated code into object_track.h header file o Added support for per-instance storage o Updated for new debug logging mechanism/callbacks
-rw-r--r--layers/object_track.h854
-rwxr-xr-xvk-layer-generate.py771
2 files changed, 1065 insertions, 560 deletions
diff --git a/layers/object_track.h b/layers/object_track.h
index da481717..428bee39 100644
--- a/layers/object_track.h
+++ b/layers/object_track.h
@@ -22,9 +22,9 @@
* DEALINGS IN THE SOFTWARE.
*/
-#include "vulkan.h"
#include "vkLayer.h"
#include "vk_enum_string_helper.h"
+
// Object Tracker ERROR codes
typedef enum _OBJECT_TRACK_ERROR
{
@@ -67,13 +67,849 @@ typedef struct _OBJTRACK_NODE {
} OBJTRACK_NODE;
// prototype for extension functions
-uint64_t objTrackGetObjectCount(VkObjectType type);
-VkResult objTrackGetObjects(VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
-uint64_t objTrackGetObjectsOfTypeCount(VkObjectType type);
-VkResult objTrackGetObjectsOfType(VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
+uint64_t objTrackGetObjectCount(VkDevice device);
+VkResult objTrackGetObjects(VkDevice device, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
+uint64_t objTrackGetObjectsOfTypeCount(VkDevice, VkObjectType type);
+VkResult objTrackGetObjectsOfType(VkDevice, VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray);
// Func ptr typedefs
-typedef uint64_t (*OBJ_TRACK_GET_OBJECT_COUNT)(VkObjectType);
-typedef VkResult (*OBJ_TRACK_GET_OBJECTS)(VkObjectType, uint64_t, OBJTRACK_NODE*);
-typedef uint64_t (*OBJ_TRACK_GET_OBJECTS_OF_TYPE_COUNT)(VkObjectType);
-typedef VkResult (*OBJ_TRACK_GET_OBJECTS_OF_TYPE)(VkObjectType, uint64_t, OBJTRACK_NODE*);
+typedef uint64_t (*OBJ_TRACK_GET_OBJECT_COUNT)(VkDevice);
+typedef VkResult (*OBJ_TRACK_GET_OBJECTS)(VkDevice, VkObjectType, uint64_t, OBJTRACK_NODE*);
+typedef uint64_t (*OBJ_TRACK_GET_OBJECTS_OF_TYPE_COUNT)(VkDevice, VkObjectType);
+typedef VkResult (*OBJ_TRACK_GET_OBJECTS_OF_TYPE)(VkDevice, VkObjectType, uint64_t, OBJTRACK_NODE*);
+
+typedef struct _layer_data {
+ debug_report_data *report_data;
+ //TODO: put instance data here
+ VkDbgMsgCallback logging_callback;
+} layer_data;
+
+static std::unordered_map<void*, layer_data *> layer_data_map;
+static device_table_map ObjectTracker_device_table_map;
+static instance_table_map ObjectTracker_instance_table_map;
+
+static long long unsigned int object_track_index = 0;
+static int objLockInitialized = 0;
+static loader_platform_thread_mutex objLock;
+
+// Objects stored in a global map w/ struct containing basic info
+unordered_map<VkObject, OBJTRACK_NODE*> objMap;
+
+#define NUM_OBJECT_TYPES (VK_NUM_OBJECT_TYPE + (VK_OBJECT_TYPE_SWAP_CHAIN_WSI - VK_OBJECT_TYPE_DISPLAY_WSI))
+
+static uint64_t numObjs[NUM_OBJECT_TYPES] = {0};
+static uint64_t numTotalObjs = 0;
+static VkPhysicalDeviceQueueProperties *queueInfo = NULL;
+static uint32_t queueCount = 0;
+
+template layer_data *get_my_data_ptr<layer_data>(
+ void *data_key, std::unordered_map<void *, layer_data *> &data_map);
+
+//
+// Internal Object Tracker Functions
+//
+
+struct devExts {
+ bool wsi_lunarg_enabled;
+};
+
+static std::unordered_map<void *, struct devExts> deviceExtMap;
+
+static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
+{
+ uint32_t i, ext_idx;
+ VkLayerDispatchTable *pDisp = device_dispatch_table(device);
+ deviceExtMap[pDisp].wsi_lunarg_enabled = false;
+ for (i = 0; i < pCreateInfo->extensionCount; i++) {
+ if (strcmp(pCreateInfo->pEnabledExtensions[i].name, VK_WSI_LUNARG_EXTENSION_NAME) == 0)
+ deviceExtMap[pDisp].wsi_lunarg_enabled = true;
+
+ }
+}
+
+// Indicate device or instance dispatch table type
+typedef enum _DispTableType
+{
+ DISP_TBL_TYPE_INSTANCE,
+ DISP_TBL_TYPE_DEVICE,
+} DispTableType;
+
+debug_report_data *mdd(VkObject object)
+{
+ dispatch_key key = get_dispatch_key(object);
+ layer_data *my_data = get_my_data_ptr(key, layer_data_map);
+ assert(my_data->report_data != NULL);
+ return my_data->report_data;
+}
+
+debug_report_data *mid(VkInstance object)
+{
+// return mdd((VkObject) object);
+ dispatch_key key = get_dispatch_key(object);
+ layer_data *my_data = get_my_data_ptr(key, layer_data_map);
+ assert(my_data->report_data != NULL);
+ return my_data->report_data;
+}
+
+// For each Queue's doubly linked-list of mem refs
+typedef struct _OT_MEM_INFO {
+ VkDeviceMemory mem;
+ struct _OT_MEM_INFO *pNextMI;
+ struct _OT_MEM_INFO *pPrevMI;
+
+} OT_MEM_INFO;
+
+// Track Queue information
+typedef struct _OT_QUEUE_INFO {
+ OT_MEM_INFO *pMemRefList;
+ struct _OT_QUEUE_INFO *pNextQI;
+ uint32_t queueNodeIndex;
+ VkQueue queue;
+ uint32_t refCount;
+} OT_QUEUE_INFO;
+
+// Global list of QueueInfo structures, one per queue
+static OT_QUEUE_INFO *g_pQueueInfo = NULL;
+
+// Convert an object type enum to an object type array index
+static uint32_t
+objTypeToIndex(
+ uint32_t objType)
+{
+ uint32_t index = objType;
+ if (objType > VK_OBJECT_TYPE_END_RANGE) {
+ // These come from vk_wsi_lunarg.h, rebase
+ index = (index -(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000)) + VK_OBJECT_TYPE_END_RANGE;
+ }
+ return index;
+}
+
+// Validate that object is in the object map
+static void
+validate_object(
+ const VkObject dispatchable_object,
+ const VkObject object)
+{
+ if (objMap.find(object) == objMap.end()) {
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, object, 0, OBJTRACK_OBJECT_TYPE_MISMATCH, "OBJTRACK",
+ "Invalid Object %p", object);
+ }
+}
+
+// Validate that object parameter matches designated object type
+static void
+validateObjectType(
+ VkObject dispatchable_object,
+ const char *apiName,
+ VkObjectType objType,
+ VkObject object)
+{
+ if (objMap.find(object) != objMap.end()) {
+ OBJTRACK_NODE* pNode = objMap[object];
+ // Found our object, check type
+ if (strcmp(string_VkObjectType(pNode->objType), string_VkObjectType(objType)) != 0) {
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, objType, object, 0, OBJTRACK_OBJECT_TYPE_MISMATCH, "OBJTRACK",
+ "ERROR: Object Parameter Type %s does not match designated type %s", string_VkObjectType(pNode->objType), string_VkObjectType(objType));
+ }
+ }
+}
+
+// Add new queue to head of global queue list
+static void
+addQueueInfo(
+ uint32_t queueNodeIndex,
+ VkQueue queue)
+{
+ OT_QUEUE_INFO *pQueueInfo = new OT_QUEUE_INFO;
+
+ if (pQueueInfo != NULL) {
+ memset(pQueueInfo, 0, sizeof(OT_QUEUE_INFO));
+ pQueueInfo->queue = queue;
+ pQueueInfo->queueNodeIndex = queueNodeIndex;
+ pQueueInfo->pNextQI = g_pQueueInfo;
+ g_pQueueInfo = pQueueInfo;
+ }
+ else {
+ log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK",
+ "ERROR: VK_ERROR_OUT_OF_HOST_MEMORY -- could not allocate memory for Queue Information");
+ }
+}
+
+// Destroy memRef lists and free all memory
+static void
+destroyQueueMemRefLists(void)
+{
+ OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;
+ OT_QUEUE_INFO *pDelQueueInfo = NULL;
+ while (pQueueInfo != NULL) {
+ OT_MEM_INFO *pMemInfo = pQueueInfo->pMemRefList;
+ while (pMemInfo != NULL) {
+ OT_MEM_INFO *pDelMemInfo = pMemInfo;
+ pMemInfo = pMemInfo->pNextMI;
+ delete pDelMemInfo;
+ }
+ pDelQueueInfo = pQueueInfo;
+ pQueueInfo = pQueueInfo->pNextQI;
+ delete pDelQueueInfo;
+ }
+ g_pQueueInfo = pQueueInfo;
+}
+
+
+static void
+create_obj(
+ VkObject dispatchable_object,
+ VkObject vkObj,
+ VkObjectType objType)
+{
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_INFO_BIT, objType, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
+ "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkObjectType(objType),
+ reinterpret_cast<VkUintPtrLeast64>(vkObj));
+
+ OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;
+ pNewObjNode->vkObj = vkObj;
+ pNewObjNode->objType = objType;
+ pNewObjNode->status = OBJSTATUS_NONE;
+ objMap[vkObj] = pNewObjNode;
+ uint32_t objIndex = objTypeToIndex(objType);
+ numObjs[objIndex]++;
+ numTotalObjs++;
+}
+
+// Parse global list to find obj type, then remove obj from obj type list, finally
+// remove obj from global list
+static void
+destroy_obj(
+ VkObject dispatchable_object,
+ VkObject vkObj)
+{
+ if (objMap.find(vkObj) != objMap.end()) {
+ OBJTRACK_NODE* pNode = objMap[vkObj];
+ uint32_t objIndex = objTypeToIndex(pNode->objType);
+ assert(numTotalObjs > 0);
+ numTotalObjs--;
+ assert(numObjs[objIndex] > 0);
+ numObjs[objIndex]--;
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_INFO_BIT, pNode->objType, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
+ "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%lu total objs remain & %lu %s objs).",
+ string_VkObjectType(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj), numTotalObjs, numObjs[objIndex],
+ string_VkObjectType(pNode->objType));
+
+ delete pNode;
+ objMap.erase(vkObj);
+ } else {
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
+ "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
+ reinterpret_cast<VkUintPtrLeast64>(vkObj));
+ }
+}
+
+// Set selected flag state for an object node
+static void
+set_status(
+ VkObject dispatchable_object,
+ VkObject vkObj,
+ VkObjectType objType,
+ ObjectStatusFlags status_flag)
+{
+ if (vkObj != VK_NULL_HANDLE) {
+ if (objMap.find(vkObj) != objMap.end()) {
+ OBJTRACK_NODE* pNode = objMap[vkObj];
+ pNode->status |= status_flag;
+ return;
+ }
+ else {
+ // If we do not find it print an error
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK",
+ "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type",
+ reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));
+ }
+ }
+}
+
+// Reset selected flag state for an object node
+static void
+reset_status(
+ VkObject dispatchable_object,
+ VkObject vkObj,
+ VkObjectType objType,
+ ObjectStatusFlags status_flag)
+{
+ if (objMap.find(vkObj) != objMap.end()) {
+ OBJTRACK_NODE* pNode = objMap[vkObj];
+ pNode->status &= ~status_flag;
+ return;
+ }
+ else {
+ // If we do not find it print an error
+ log_msg(mdd(dispatchable_object), VK_DBG_REPORT_ERROR_BIT, objType, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
+ "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type",
+ reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));
+ }
+}
+
+static void
+setGpuQueueInfoState(
+ size_t *pDataSize,
+ void *pData)
+{
+ queueCount = ((uint32_t)*pDataSize / sizeof(VkPhysicalDeviceQueueProperties));
+ queueInfo = (VkPhysicalDeviceQueueProperties*)realloc((void*)queueInfo, *pDataSize);
+ if (queueInfo != NULL) {
+ memcpy(queueInfo, pData, *pDataSize);
+ }
+}
+
+// Check Queue type flags for selected queue operations
+static void
+validateQueueFlags(
+ VkQueue queue,
+ const char *function)
+{
+ OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;
+ while ((pQueueInfo != NULL) && (pQueueInfo->queue != queue)) {
+ pQueueInfo = pQueueInfo->pNextQI;
+ }
+ if (pQueueInfo != NULL) {
+ if ((queueInfo != NULL) && (queueInfo[pQueueInfo->queueNodeIndex].queueFlags & VK_QUEUE_SPARSE_MEMMGR_BIT) == 0) {
+ log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
+ "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not set", function);
+ } else {
+ log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
+ "Attempting %s on a possibly non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not known", function);
+ }
+ }
+}
+
+// Check object status for selected flag state
+static bool32_t
+validate_status(
+ VkObject dispatchable_object,
+ VkObject vkObj,
+ VkObjectType objType,
+ ObjectStatusFlags status_mask,
+ ObjectStatusFlags status_flag,
+ VkFlags msg_flags,
+ OBJECT_TRACK_ERROR error_code,
+ const char *fail_msg)
+{
+ if (objMap.find(vkObj) != objMap.end()) {
+ OBJTRACK_NODE* pNode = objMap[vkObj];
+ if ((pNode->status & status_mask) != status_flag) {
+ char str[1024];
+ log_msg(mdd(dispatchable_object), msg_flags, pNode->objType, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
+ "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkObjectType(objType),
+ reinterpret_cast<VkUintPtrLeast64>(vkObj), fail_msg);
+ return VK_FALSE;
+ }
+ return VK_TRUE;
+ }
+ else {
+ // If we do not find it print an error
+ log_msg(mdd(dispatchable_object), msg_flags, (VkObjectType) 0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK",
+ "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type",
+ reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));
+ return VK_FALSE;
+ }
+}
+
+#include "vk_dispatch_table_helper.h"
+static void
+initObjectTracker(
+ layer_data *my_data)
+{
+ uint32_t report_flags = 0;
+ uint32_t debug_action = 0;
+ FILE *log_output = NULL;
+ const char *option_str;
+ // initialize ObjectTracker options
+ report_flags = getLayerOptionFlags("ObjectTrackerReportFlags", 0);
+ getLayerOptionEnum("ObjectTrackerDebugAction", (uint32_t *) &debug_action);
+
+ if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
+ {
+ option_str = getLayerOption("ObjectTrackerLogFilename");
+ if (option_str) {
+ log_output = fopen(option_str, "w");
+ }
+ if (log_output == NULL) {
+ log_output = stdout;
+ }
+
+ layer_create_msg_callback(my_data->report_data, report_flags, log_callback, (void *) log_output, &my_data->logging_callback);
+ }
+
+ if (!objLockInitialized)
+ {
+ // TODO/TBD: Need to delete this mutex sometime. How??? One
+ // suggestion is to call this during vkCreateInstance(), and then we
+ // can clean it up during vkDestroyInstance(). However, that requires
+ // that the layer have per-instance locks. We need to come back and
+ // address this soon.
+ loader_platform_thread_create_mutex(&objLock);
+ objLockInitialized = 1;
+ }
+}
+
+
+//
+// Non-auto-generated API functions called by generated code
+//
+
+VkResult
+explicit_CreateInstance(
+ const VkInstanceCreateInfo *pCreateInfo,
+ VkInstance * pInstance)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, *pInstance);
+ VkResult result = pInstanceTable->CreateInstance(pCreateInfo, pInstance);
+
+ if (result == VK_SUCCESS) {
+ layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+ my_data->report_data = debug_report_create_instance(
+ pInstanceTable,
+ *pInstance,
+ pCreateInfo->extensionCount,
+ pCreateInfo->pEnabledExtensions);
+
+ initObjectTracker(my_data);
+ }
+ loader_platform_thread_unlock_mutex(&objLock);
+ return result;
+}
+
+VkResult
+explicit_DestroyInstance(
+ VkInstance instance)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validate_object(instance, instance);
+
+ destroy_obj(instance, instance);
+ // Report any remaining objects in LL
+ for (auto it = objMap.begin(); it != objMap.end(); ++it) {
+ OBJTRACK_NODE* pNode = it->second; if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {
+ // Cannot destroy physical device so ignore
+ } else {
+ log_msg(mid(instance), VK_DBG_REPORT_ERROR_BIT, pNode->objType, pNode->vkObj, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK",
+ "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType),
+ reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));
+ }
+ }
+
+ dispatch_key key = get_dispatch_key(instance);
+ VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, instance);
+ VkResult result = pInstanceTable->DestroyInstance(instance);
+
+ // Clean up logging callback, if any
+ layer_data *my_data = get_my_data_ptr(key, layer_data_map);
+ if (my_data->logging_callback) {
+ layer_destroy_msg_callback(my_data->report_data, my_data->logging_callback);
+ }
+
+ layer_debug_report_destroy_instance(mid(instance));
+ layer_data_map.erase(pInstanceTable);
+
+ ObjectTracker_instance_table_map.erase(key);
+ assert(ObjectTracker_instance_table_map.size() == 0 && "Should not have any instance mappings hanging around");
+
+ loader_platform_thread_unlock_mutex(&objLock);
+ return result;
+}
+
+VkResult
+explicit_GetPhysicalDeviceInfo(
+ VkPhysicalDevice gpu,
+ VkPhysicalDeviceInfoType infoType,
+ size_t *pDataSize,
+ void *pData)
+{
+ VkResult result = get_dispatch_table(ObjectTracker_instance_table_map, gpu)->GetPhysicalDeviceInfo(gpu, infoType, pDataSize, pData);
+ if (infoType == VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PROPERTIES) {
+ if (pData != NULL) {
+ loader_platform_thread_lock_mutex(&objLock);
+ setGpuQueueInfoState(pDataSize, pData);
+ loader_platform_thread_unlock_mutex(&objLock);
+ }
+ }
+ return result;
+}
+
+VkResult
+explicit_CreateDevice(
+ VkPhysicalDevice gpu,
+ const VkDeviceCreateInfo *pCreateInfo,
+ VkDevice *pDevice)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(ObjectTracker_instance_table_map, gpu);
+ VkResult result = pInstanceTable->CreateDevice(gpu, pCreateInfo, pDevice);
+ if (result == VK_SUCCESS) {
+ layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
+ //// VkLayerDispatchTable *pTable = get_dispatch_table(ObjectTracker_device_table_map, *pDevice);
+ layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
+ my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
+ create_obj(gpu, *pDevice, VK_OBJECT_TYPE_DEVICE);
+ }
+
+ loader_platform_thread_unlock_mutex(&objLock);
+ return result;
+}
+
+VkResult
+explicit_DestroyDevice(
+ VkDevice device)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validate_object(device, device);
+ destroy_obj(device, device);
+ // Report any remaining objects
+ for (auto it = objMap.begin(); it != objMap.end(); ++it) {
+ OBJTRACK_NODE* pNode = it->second;
+ if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {
+ // Cannot destroy physical device so ignore
+ } else {
+ log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE, device, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK",
+ "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType),
+ reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));
+ }
+ }
+ // Clean up Queue's MemRef Linked Lists
+ destroyQueueMemRefLists();
+
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ dispatch_key key = get_dispatch_key(device);
+ VkLayerDispatchTable *pDisp = get_dispatch_table(ObjectTracker_device_table_map, device);
+ VkResult result = pDisp->DestroyDevice(device);
+ deviceExtMap.erase(pDisp);
+ ObjectTracker_device_table_map.erase(key);
+ assert(ObjectTracker_device_table_map.size() == 0 && "Should not have any instance mappings hanging around");
+
+ return result;
+}
+
+VkResult
+explicit_GetDeviceQueue(
+ VkDevice device,
+ uint32_t queueNodeIndex,
+ uint32_t queueIndex,
+ VkQueue *pQueue)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validate_object(device, device);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
+
+ loader_platform_thread_lock_mutex(&objLock);
+ addQueueInfo(queueNodeIndex, *pQueue);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ return result;
+}
+
+VkResult
+explicit_QueueSubmit(
+ VkQueue queue,
+ uint32_t cmdBufferCount,
+ const VkCmdBuffer *pCmdBuffers,
+ VkFence fence)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ set_status(queue, fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);
+ // TODO: Fix for updated memory reference mechanism
+ // validate_memory_mapping_status(pMemRefs, memRefCount);
+ // validate_mem_ref_count(memRefCount);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueSubmit(queue, cmdBufferCount, pCmdBuffers, fence);
+
+ return result;
+}
+
+VkResult
+explicit_MapMemory(
+ VkDevice device,
+ VkDeviceMemory mem,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkFlags flags,
+ void **ppData)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ set_status(device, mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);
+ validate_object(device, device);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->MapMemory(device, mem, offset, size, flags, ppData);
+
+ return result;
+}
+
+VkResult
+explicit_UnmapMemory(
+ VkDevice device,
+ VkDeviceMemory mem)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ reset_status(device, mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);
+ validate_object(device, device);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->UnmapMemory(device, mem);
+
+ return result;
+}
+
+VkResult
+explicit_DestroyObject(
+ VkDevice device,
+ VkObjectType objType,
+ VkObject object)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validate_object(device, device);
+ validate_object(device, object);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->DestroyObject(device, objType, object);
+
+ loader_platform_thread_lock_mutex(&objLock);
+ validateObjectType(device, "vkDestroyObject", objType, object);
+ destroy_obj(device, object);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ return result;
+}
+
+VkResult
+explicit_GetObjectInfo(
+ VkDevice device,
+ VkObjectType objType,
+ VkObject object,
+ VkObjectInfoType infoType,
+ size_t *pDataSize,
+ void *pData)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validateObjectType(device, "vkGetObjectInfo", objType, object);
+ validate_object(device, device);
+ validate_object(device, object);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetObjectInfo(device, objType, object, infoType, pDataSize, pData);
+
+ return result;
+}
+
+VkResult
+explicit_QueueBindSparseBufferMemory(
+ VkQueue queue,
+ VkBuffer buffer,
+ VkDeviceSize rangeOffset,
+ VkDeviceSize rangeSize,
+ VkDeviceMemory mem,
+ VkDeviceSize memOffset)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validateQueueFlags(queue, "QueueBindSparseBufferMemory");
+ validate_object(queue, buffer);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueBindSparseBufferMemory(queue, buffer, rangeOffset, rangeSize, mem, memOffset);
+ return result;
+}
+
+VkResult
+explicit_QueueBindSparseImageMemory(
+ VkQueue queue,
+ VkImage image,
+ const VkImageMemoryBindInfo *pBindInfo,
+ VkDeviceMemory mem,
+ VkDeviceSize memOffset)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validateQueueFlags(queue, "QueueBindSparseImageMemory");
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, queue)->QueueBindSparseImageMemory(queue, image, pBindInfo, mem, memOffset);
+ return result;
+}
+
+
+VkResult
+explicit_GetFenceStatus(
+ VkDevice device,
+ VkFence fence)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ // Warn if submitted_flag is not set
+ validate_status(device, fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED,
+ VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");
+ validate_object(device, device);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->GetFenceStatus(device, fence);
+
+ return result;
+}
+
+VkResult
+explicit_WaitForFences(
+ VkDevice device,
+ uint32_t fenceCount,
+ const VkFence *pFences,
+ bool32_t waitAll,
+ uint64_t timeout)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ // Warn if waiting on unsubmitted fence
+ for (uint32_t i = 0; i < fenceCount; i++) {
+ validate_status(device, pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED,
+ VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");
+ }
+ validate_object(device, device);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
+
+ return result;
+}
+
+VkResult
+explicit_AllocDescriptorSets(
+ VkDevice device,
+ VkDescriptorPool descriptorPool,
+ VkDescriptorSetUsage setUsage,
+ uint32_t count,
+ const VkDescriptorSetLayout *pSetLayouts,
+ VkDescriptorSet *pDescriptorSets,
+ uint32_t *pCount)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validate_object(device, device);
+ validate_object(device, descriptorPool);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->AllocDescriptorSets(
+ device, descriptorPool, setUsage, count, pSetLayouts, pDescriptorSets, pCount);
+
+ loader_platform_thread_lock_mutex(&objLock);
+ for (uint32_t i = 0; i < *pCount; i++) {
+ create_obj(device, pDescriptorSets[i], VK_OBJECT_TYPE_DESCRIPTOR_SET);
+ }
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ return result;
+}
+
+VkResult
+explicit_DestroySwapChainWSI(
+ VkSwapChainWSI swapChain)
+{
+
+ loader_platform_thread_lock_mutex(&objLock);
+ destroy_obj(swapChain, swapChain);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, swapChain)->DestroySwapChainWSI(swapChain);
+
+ return result;
+}
+
+VkResult
+explicit_FreeMemory(
+ VkDevice device,
+ VkDeviceMemory mem)
+{
+ loader_platform_thread_lock_mutex(&objLock);
+ validate_object(device, device);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ VkResult result = get_dispatch_table(ObjectTracker_device_table_map, device)->FreeMemory(device, mem);
+
+ loader_platform_thread_lock_mutex(&objLock);
+ destroy_obj(device, mem);
+ loader_platform_thread_unlock_mutex(&objLock);
+
+ return result;
+}
+
+
+// ObjectTracker Extensions
+
+uint64_t
+objTrackGetObjectsCount(
+ VkDevice device)
+{
+ return numTotalObjs;
+}
+
+VkResult
+objTrackGetObjects(
+ VkDevice device,
+ uint64_t objCount,
+ OBJTRACK_NODE *pObjNodeArray)
+{
+ // This bool flags if we're pulling all objs or just a single class of objs
+ // Check the count first thing
+ uint64_t maxObjCount = numTotalObjs;
+ if (objCount > maxObjCount) {
+ log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, device, 0, OBJTRACK_OBJCOUNT_MAX_EXCEEDED, "OBJTRACK",
+ "OBJ ERROR : Received objTrackGetObjects() request for %lu objs, but there are only %lu total objs", objCount, maxObjCount);
+ return VK_ERROR_INVALID_VALUE;
+ }
+ auto it = objMap.begin();
+ for (uint64_t i = 0; i < objCount; i++) {
+ if (objMap.end() == it) {
+ log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, device, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK",
+ "OBJ INTERNAL ERROR : Ran out of objs! Should have %lu, but only copied %lu and not the requested %lu.", maxObjCount, i, objCount);
+ return VK_ERROR_UNKNOWN;
+ }
+ memcpy(&pObjNodeArray[i], it->second, sizeof(OBJTRACK_NODE));
+ ++it;
+ }
+ return VK_SUCCESS;
+}
+
+uint64_t
+objTrackGetObjectsOfTypeCount(
+ VkDevice device,
+ VkObjectType type)
+{
+ return numObjs[type];
+}
+
+VkResult
+objTrackGetObjectsOfType(
+ VkDevice device,
+ VkObjectType type,
+ uint64_t objCount,
+ OBJTRACK_NODE *pObjNodeArray)
+{
+ // Check the count first thing
+ uint64_t maxObjCount = numObjs[type];
+ if (objCount > maxObjCount) {
+ log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, device, 0, OBJTRACK_OBJCOUNT_MAX_EXCEEDED, "OBJTRACK",
+ "OBJ ERROR : Received objTrackGetObjects() request for %lu objs, but there are only %lu objs of type %s",
+ objCount, maxObjCount, string_VkObjectType(type));
+ return VK_ERROR_INVALID_VALUE;
+ }
+ auto it = objMap.begin();
+ for (uint64_t i = 0; i < objCount; i++) {
+ // Get next object of correct type
+ while ((objMap.end() != it) && (it->second->objType != type))
+ ++it;
+ if (objMap.end() == it) {
+ log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, device, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK",
+ "OBJ INTERNAL ERROR : Ran out of %s objs! Should have %lu, but only copied %lu and not the requested %lu.",
+ string_VkObjectType(type), maxObjCount, i, objCount);
+ return VK_ERROR_UNKNOWN;
+ }
+ memcpy(&pObjNodeArray[i], it->second, sizeof(OBJTRACK_NODE));
+ }
+ return VK_SUCCESS;
+}
+
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 3431d897..bbe6e989 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -164,7 +164,18 @@ class Subcommand(object):
r_body.append('%s' % self.lineinfo.get())
r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)')
r_body.append('{')
- r_body.append(' return layer_create_msg_callback(instance, instance_dispatch_table(instance), msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
+ # Switch to this code section for the new per-instance storage and debug callbacks
+ if self.layer_name == 'ObjectTracker':
+ r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
+ r_body.append(' VkResult result = pInstanceTable->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
+ r_body.append(' if (VK_SUCCESS == result) {')
+ r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
+ r_body.append(' result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
+ r_body.append(' }')
+ r_body.append(' return result;')
+ else:
+ # Old version of callbacks for compatibility
+ r_body.append(' return layer_create_msg_callback(instance, instance_dispatch_table(instance), msgFlags, pfnMsgCallback, pUserData, pMsgCallback);')
r_body.append('}')
return "\n".join(r_body)
@@ -173,7 +184,16 @@ class Subcommand(object):
r_body.append('%s' % self.lineinfo.get())
r_body.append('VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)')
r_body.append('{')
- r_body.append(' return layer_destroy_msg_callback(instance, instance_dispatch_table(instance), msgCallback);')
+ # Switch to this code section for the new per-instance storage and debug callbacks
+ if self.layer_name == 'ObjectTracker':
+ r_body.append(' VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(%s_instance_table_map, instance);' % self.layer_name )
+ r_body.append(' VkResult result = pInstanceTable->DbgDestroyMsgCallback(instance, msgCallback);')
+ r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
+ r_body.append(' layer_destroy_msg_callback(my_data->report_data, msgCallback);')
+ r_body.append(' return result;')
+ else:
+ # Old version of callbacks for compatibility
+ r_body.append(' return layer_destroy_msg_callback(instance, instance_dispatch_table(instance), msgCallback);')
r_body.append('}')
return "\n".join(r_body)
@@ -397,145 +417,148 @@ class Subcommand(object):
funcs.append("\n".join(body))
return "\n\n".join(funcs)
-
def _generate_extensions(self):
exts = []
+ exts.append('%s' % self.lineinfo.get())
exts.append(self._gen_create_msg_callback())
exts.append(self._gen_destroy_msg_callback())
- exts.append('%s' % self.lineinfo.get())
- exts.append('uint64_t objTrackGetObjectsCount(VkObjectType type)')
- exts.append('{')
- exts.append(' return numTotalObjs;')
- exts.append('}')
- exts.append('')
- exts.append('VkResult objTrackGetObjects(VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray)')
- exts.append('{')
- exts.append(" // This bool flags if we're pulling all objs or just a single class of objs")
- exts.append(' // Check the count first thing')
- exts.append(' uint64_t maxObjCount = numTotalObjs;')
- exts.append(' if (objCount > maxObjCount) {')
- exts.append(' char str[1024];')
- exts.append(' sprintf(str, "OBJ ERROR : Received objTrackGetObjects() request for %lu objs, but there are only %lu total objs", objCount, maxObjCount);')
- exts.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, type, 0, 0, OBJTRACK_OBJCOUNT_MAX_EXCEEDED, "OBJTRACK", str);')
- exts.append(' return VK_ERROR_INVALID_VALUE;')
- exts.append(' }')
- exts.append(' auto it = objMap.begin();')
- exts.append(' for (uint64_t i = 0; i < objCount; i++) {')
- exts.append(' if (objMap.end() == it) {')
- exts.append(' char str[1024];')
- exts.append(' sprintf(str, "OBJ INTERNAL ERROR : Ran out of objs! Should have %lu, but only copied %lu and not the requested %lu.", maxObjCount, i, objCount);')
- exts.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, type, 0, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK", str);')
- exts.append(' return VK_ERROR_UNKNOWN;')
- exts.append(' }')
- exts.append(' memcpy(&pObjNodeArray[i], it->second, sizeof(OBJTRACK_NODE));')
- exts.append(' ++it;')
- exts.append(' }')
- exts.append(' return VK_SUCCESS;')
- exts.append('}')
- exts.append('%s' % self.lineinfo.get())
- exts.append('uint64_t objTrackGetObjectsOfTypeCount(VkObjectType type)')
- exts.append('{')
- exts.append(' return numObjs[type];')
- exts.append('}')
- exts.append('')
- exts.append('VkResult objTrackGetObjectsOfType(VkObjectType type, uint64_t objCount, OBJTRACK_NODE* pObjNodeArray)')
- exts.append('{')
- exts.append(' // Check the count first thing')
- exts.append(' uint64_t maxObjCount = numObjs[type];')
- exts.append(' if (objCount > maxObjCount) {')
- exts.append(' char str[1024];')
- exts.append(' sprintf(str, "OBJ ERROR : Received objTrackGetObjects() request for %lu objs, but there are only %lu objs of type %s", objCount, maxObjCount, string_VkObjectType(type));')
- exts.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, type, 0, 0, OBJTRACK_OBJCOUNT_MAX_EXCEEDED, "OBJTRACK", str);')
- exts.append(' return VK_ERROR_INVALID_VALUE;')
- exts.append(' }')
- exts.append(' auto it = objMap.begin();')
- exts.append(' for (uint64_t i = 0; i < objCount; i++) {')
- exts.append(' // Get next object of correct type')
- exts.append(' while ((objMap.end() != it) && (it->second->objType != type))')
- exts.append(' ++it;')
- exts.append(' if (objMap.end() == it) {')
- exts.append(' char str[1024];')
- exts.append(' sprintf(str, "OBJ INTERNAL ERROR : Ran out of %s objs! Should have %lu, but only copied %lu and not the requested %lu.", string_VkObjectType(type), maxObjCount, i, objCount);')
- exts.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, type, 0, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK", str);')
- exts.append(' return VK_ERROR_UNKNOWN;')
- exts.append(' }')
- exts.append(' memcpy(&pObjNodeArray[i], it->second, sizeof(OBJTRACK_NODE));')
- exts.append(' }')
- exts.append(' return VK_SUCCESS;')
- exts.append('}')
return "\n".join(exts)
def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
func_body = []
- func_body.append('%s' % self.lineinfo.get())
- func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
- "{\n"
- " void* addr;\n"
- " if (device == VK_NULL_HANDLE) {\n"
- " return NULL;\n"
- " }\n"
- " loader_platform_thread_once(&initOnce, init%s);\n\n"
- " /* loader uses this to force layer initialization; device object is wrapped */\n"
- " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
- " initDeviceTable((const VkBaseLayerObject *) device);\n"
- " return (void *) vkGetDeviceProcAddr;\n"
- " }\n\n"
- " addr = layer_intercept_proc(funcName);\n"
- " if (addr)\n"
- " return addr;" % self.layer_name)
+#
+# New style fo GPA Functions for the new layer_data/layer_logging changes
+#
+ if self.layer_name == 'ObjectTracker':
+ func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
+ "{\n"
+ " void* addr;\n"
+ " if (device == VK_NULL_HANDLE) {\n"
+ " return NULL;\n"
+ " }\n"
+ " /* loader uses this to force layer initialization; device object is wrapped */\n"
+ " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
+ " initDeviceTable(%s_device_table_map, (const VkBaseLayerObject *) device);\n"
+ " return (void *) vkGetDeviceProcAddr;\n"
+ " }\n\n"
+ " addr = layer_intercept_proc(funcName);\n"
+ " if (addr)\n"
+ " return addr;" % self.layer_name)
+ if 0 != len(extensions):
+ for (ext_enable, ext_list) in extensions:
+ extra_space = ""
+ if 0 != len(ext_enable):
+ func_body.append(' if (deviceExtMap.size() == 0 || deviceExtMap[get_dispatch_table(ObjectTracker_device_table_map, device)].%s)' % ext_enable)
+ func_body.append(' {')
+ extra_space = " "
+ for ext_name in ext_list:
+ func_body.append(' %sif (!strcmp("%s", funcName))\n'
+ ' %sreturn reinterpret_cast<void*>(%s);' % (extra_space, ext_name, extra_space, ext_name))
+ if 0 != len(ext_enable):
+ func_body.append(' }\n')
+ func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
+ " return NULL;\n"
+ " return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
+ "}\n" % (self.layer_name, self.layer_name))
+ func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
+ "{\n"
+ " void* addr;\n"
+ " if (instance == VK_NULL_HANDLE) {\n"
+ " return NULL;\n"
+ " }\n"
+ " /* loader uses this to force layer initialization; instance object is wrapped */\n"
+ " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
+ " initInstanceTable(%s_instance_table_map, (const VkBaseLayerObject *) instance);\n"
+ " return (void *) vkGetInstanceProcAddr;\n"
+ " }\n\n"
+ " addr = layer_intercept_instance_proc(funcName);\n"
+ " if (addr) {\n"
+ " return addr;"
+ " }\n" % self.layer_name)
- func_body.append('')
- func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
- if 0 != len(extensions):
- cpp_prefix = "reinterpret_cast<void*>("
- cpp_postfix = ")"
- extra_space = ""
- for (ext_enable, ext_list) in extensions:
- if 0 != len(ext_enable):
- func_body.append(' if (deviceExtMap.size() == 0 || deviceExtMap[pDisp].%s)' % ext_enable)
- func_body.append(' {')
- extra_space = " "
- for ext_name in ext_list:
- func_body.append(' %sif (!strcmp("%s", funcName))\n'
- ' return %s%s%s;' % (extra_space, ext_name, cpp_prefix, ext_name, cpp_postfix))
- if 0 != len(ext_enable):
- func_body.append(' }')
- func_body.append('%s' % self.lineinfo.get())
- func_body.append(" {\n"
- " if (pDisp->GetDeviceProcAddr == NULL)\n"
- " return NULL;\n"
- " return pDisp->GetDeviceProcAddr(device, funcName);\n"
- " }\n"
- "}\n")
- func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
- "{\n"
- " void* addr;\n"
- " if (instance == VK_NULL_HANDLE) {\n"
- " return NULL;\n"
- " }\n"
- " loader_platform_thread_once(&initOnce, init%s);\n\n"
- " /* loader uses this to force layer initialization; instance object is wrapped */\n"
- " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
- " initInstanceTable((const VkBaseLayerObject *) instance);\n"
- " return (void *) vkGetInstanceProcAddr;\n"
- " }\n\n"
- " addr = layer_intercept_instance_proc(funcName);\n"
- " if (addr)\n"
- " return addr;" % self.layer_name)
+ if 0 != len(instance_extensions):
+ for ext_name in instance_extensions:
+ func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
+ " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
+ " if (addr) {\n"
+ " return addr;\n"
+ " }\n"
+ " if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
+ " return NULL;\n"
+ " }\n"
+ " return get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);\n"
+ "}\n" % (self.layer_name, self.layer_name))
+ return "\n".join(func_body)
+ else:
+#
+# TODO:: Old-style GPA Functions -- no local storage, no new logging mechanism. Left for compatibility.
+#
+ func_body.append('%s' % self.lineinfo.get())
+ func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
+ "{\n"
+ " void* addr;\n"
+ " if (device == VK_NULL_HANDLE) {\n"
+ " return NULL;\n"
+ " }\n"
+ " loader_platform_thread_once(&initOnce, init%s);\n\n"
+ " /* loader uses this to force layer initialization; device object is wrapped */\n"
+ " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
+ " initDeviceTable((const VkBaseLayerObject *) device);\n"
+ " return (void *) vkGetDeviceProcAddr;\n"
+ " }\n\n"
+ " addr = layer_intercept_proc(funcName);\n"
+ " if (addr)\n"
+ " return addr;" % self.layer_name)
+ func_body.append('')
+ func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
+ if 0 != len(extensions):
+ extra_space = ""
+ for (ext_enable, ext_list) in extensions:
+ if 0 != len(ext_enable):
+ func_body.append(' if (deviceExtMap.size() == 0 || deviceExtMap[pDisp].%s)' % ext_enable)
+ func_body.append(' {')
+ extra_space = " "
+ for ext_name in ext_list:
+ func_body.append(' %sif (!strcmp("%s", funcName))\n'
+ ' return reinterpret_cast<void*>(%s);' % (extra_space, ext_name, ext_name))
+ if 0 != len(ext_enable):
+ func_body.append(' }')
+ func_body.append('%s' % self.lineinfo.get())
+ func_body.append(" {\n"
+ " if (pDisp->GetDeviceProcAddr == NULL)\n"
+ " return NULL;\n"
+ " return pDisp->GetDeviceProcAddr(device, funcName);\n"
+ " }\n"
+ "}\n")
+ func_body.append("VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
+ "{\n"
+ " void* addr;\n"
+ " if (instance == VK_NULL_HANDLE) {\n"
+ " return NULL;\n"
+ " }\n"
+ " loader_platform_thread_once(&initOnce, init%s);\n\n"
+ " /* loader uses this to force layer initialization; instance object is wrapped */\n"
+ " if (!strcmp(\"vkGetInstanceProcAddr\", funcName)) {\n"
+ " initInstanceTable((const VkBaseLayerObject *) instance);\n"
+ " return (void *) vkGetInstanceProcAddr;\n"
+ " }\n\n"
+ " addr = layer_intercept_instance_proc(funcName);\n"
+ " if (addr)\n"
+ " return addr;" % self.layer_name)
+ if 0 != len(instance_extensions):
+ for ext_name in instance_extensions:
+ func_body.append(" {\n"
+ " void *fptr;\n"
+ " fptr = %s(funcName);\n"
+ " if (fptr) return fptr;\n"
+ " }\n" % ext_name)
+ func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n"
+ " if (pTable->GetInstanceProcAddr == NULL)\n"
+ " return NULL;\n"
+ " return pTable->GetInstanceProcAddr(instance, funcName);\n"
+ "}\n")
+ return "\n".join(func_body)
- if 0 != len(instance_extensions):
- for ext_name in instance_extensions:
- func_body.append(" {\n"
- " void *fptr;\n"
- " fptr = %s(funcName);\n"
- " if (fptr) return fptr;\n"
- " }\n" % ext_name)
- func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n"
- " if (pTable->GetInstanceProcAddr == NULL)\n"
- " return NULL;\n"
- " return pTable->GetInstanceProcAddr(instance, funcName);\n"
- "}\n")
- return "\n".join(func_body)
def _generate_layer_initialization(self, init_opts=False, prefix='vk', lockname=None, condname=None):
func_body = ["#include \"vk_dispatch_table_helper.h\""]
@@ -1060,9 +1083,14 @@ class ObjectTrackerSubcommand(Subcommand):
def generate_header(self):
header_txt = []
header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <inttypes.h>\n')
- header_txt.append('#include "loader_platform.h"\n')
- header_txt.append('#include "object_track.h"\n\n')
+ header_txt.append('#include <stdio.h>')
+ header_txt.append('#include <stdlib.h>')
+ header_txt.append('#include <string.h>')
+ header_txt.append('#include <inttypes.h>')
+ header_txt.append('')
+ header_txt.append('#include "vulkan.h"')
+ header_txt.append('#include "loader_platform.h"')
+ header_txt.append('')
header_txt.append('#include <unordered_map>')
header_txt.append('using namespace std;')
header_txt.append('// The following is #included again to catch certain OS-specific functions being used:')
@@ -1071,251 +1099,13 @@ class ObjectTrackerSubcommand(Subcommand):
header_txt.append('#include "layers_msg.h"')
header_txt.append('#include "vk_debug_report_lunarg.h"')
header_txt.append('#include "layers_table.h"')
+ header_txt.append('#include "layer_data.h"')
+ header_txt.append('#include "layer_logging.h"')
header_txt.append('')
- header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
- header_txt.append('')
- header_txt.append('static long long unsigned int object_track_index = 0;')
- header_txt.append('static int objLockInitialized = 0;')
- header_txt.append('static loader_platform_thread_mutex objLock;')
- header_txt.append('// Objects stored in a global map w/ struct containing basic info')
- header_txt.append('unordered_map<VkObject, OBJTRACK_NODE*> objMap;')
- header_txt.append('')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('#define NUM_OBJECT_TYPES (VK_NUM_OBJECT_TYPE + (VK_OBJECT_TYPE_SWAP_CHAIN_WSI - VK_OBJECT_TYPE_DISPLAY_WSI))')
- header_txt.append('')
- header_txt.append('static uint64_t numObjs[NUM_OBJECT_TYPES] = {0};')
- header_txt.append('static uint64_t numTotalObjs = 0;')
- header_txt.append('static VkPhysicalDeviceQueueProperties *queueInfo = NULL;')
- header_txt.append('static uint32_t queueCount = 0;')
- header_txt.append('')
- header_txt.append('// For each Queue\'s doubly linked-list of mem refs')
- header_txt.append('typedef struct _OT_MEM_INFO {')
- header_txt.append(' VkDeviceMemory mem;')
- header_txt.append(' struct _OT_MEM_INFO *pNextMI;')
- header_txt.append(' struct _OT_MEM_INFO *pPrevMI;')
- header_txt.append('')
- header_txt.append('} OT_MEM_INFO;')
- header_txt.append('')
- header_txt.append('// Track Queue information')
- header_txt.append('typedef struct _OT_QUEUE_INFO {')
- header_txt.append(' OT_MEM_INFO *pMemRefList;')
- header_txt.append(' struct _OT_QUEUE_INFO *pNextQI;')
- header_txt.append(' uint32_t queueNodeIndex;')
- header_txt.append(' VkQueue queue;')
- header_txt.append(' uint32_t refCount;')
- header_txt.append('} OT_QUEUE_INFO;')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('// Global list of QueueInfo structures, one per queue')
- header_txt.append('static OT_QUEUE_INFO *g_pQueueInfo = NULL;')
+# NOTE: The non-autoGenerated code is in the object_track.h header file
+ header_txt.append('#include "object_track.h"')
header_txt.append('')
- header_txt.append('// Convert an object type enum to an object type array index')
- header_txt.append('static uint32_t objTypeToIndex(uint32_t objType)')
- header_txt.append('{')
- header_txt.append(' uint32_t index = objType;')
- header_txt.append(' if (objType > VK_OBJECT_TYPE_END_RANGE) {')
- header_txt.append(' // These come from vk_wsi_lunarg.h, rebase')
- header_txt.append(' index = (index -(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000)) + VK_OBJECT_TYPE_END_RANGE;')
- header_txt.append(' }')
- header_txt.append(' return index;')
- header_txt.append('}')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('// Validate that object is in the object map')
- header_txt.append('static void validate_object(const VkObject object)')
- header_txt.append('{')
- header_txt.append(' if (objMap.find(object) == objMap.end()) {')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "Invalid Object %p", (void*)object);')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, object, 0, OBJTRACK_OBJECT_TYPE_MISMATCH, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('')
- header_txt.append('// Validate that object parameter matches designated object type')
- header_txt.append('static void validateObjectType(')
- header_txt.append(' const char *apiName,')
- header_txt.append(' VkObjectType objType,')
- header_txt.append(' VkObject object)')
- header_txt.append('{')
- header_txt.append(' if (objMap.find(object) != objMap.end()) {')
- header_txt.append(' OBJTRACK_NODE* pNode = objMap[object];')
- header_txt.append(' // Found our object, check type')
- header_txt.append(' if (strcmp(string_VkObjectType(pNode->objType), string_VkObjectType(objType)) != 0) {')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "ERROR: Object Parameter Type %s does not match designated type %s",')
- header_txt.append(' string_VkObjectType(pNode->objType), string_VkObjectType(objType));')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, objType, object, 0, OBJTRACK_OBJECT_TYPE_MISMATCH, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('// Add new queue to head of global queue list')
- header_txt.append('static void addQueueInfo(uint32_t queueNodeIndex, VkQueue queue)')
- header_txt.append('{')
- header_txt.append(' OT_QUEUE_INFO *pQueueInfo = new OT_QUEUE_INFO;')
- header_txt.append('')
- header_txt.append(' if (pQueueInfo != NULL) {')
- header_txt.append(' memset(pQueueInfo, 0, sizeof(OT_QUEUE_INFO));')
- header_txt.append(' pQueueInfo->queue = queue;')
- header_txt.append(' pQueueInfo->queueNodeIndex = queueNodeIndex;')
- header_txt.append(' pQueueInfo->pNextQI = g_pQueueInfo;')
- header_txt.append(' g_pQueueInfo = pQueueInfo;')
- header_txt.append(' }')
- header_txt.append(' else {')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "ERROR: VK_ERROR_OUT_OF_HOST_MEMORY -- could not allocate memory for Queue Information");')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_INTERNAL_ERROR, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('')
- header_txt.append('// Destroy memRef lists and free all memory')
- header_txt.append('static void destroyQueueMemRefLists()')
- header_txt.append('{')
- header_txt.append(' OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;')
- header_txt.append(' OT_QUEUE_INFO *pDelQueueInfo = NULL;')
- header_txt.append(' while (pQueueInfo != NULL) {')
- header_txt.append(' OT_MEM_INFO *pMemInfo = pQueueInfo->pMemRefList;')
- header_txt.append(' while (pMemInfo != NULL) {')
- header_txt.append(' OT_MEM_INFO *pDelMemInfo = pMemInfo;')
- header_txt.append(' pMemInfo = pMemInfo->pNextMI;')
- header_txt.append(' delete pDelMemInfo;')
- header_txt.append(' }')
- header_txt.append(' pDelQueueInfo = pQueueInfo;')
- header_txt.append(' pQueueInfo = pQueueInfo->pNextQI;')
- header_txt.append(' delete pDelQueueInfo;')
- header_txt.append(' }')
- header_txt.append(' g_pQueueInfo = pQueueInfo;')
- header_txt.append('}')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('static void create_obj(VkObject vkObj, VkObjectType objType) {')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkObjectType(objType), reinterpret_cast<VkUintPtrLeast64>(vkObj));')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_INFO_BIT, objType, vkObj, 0, OBJTRACK_NONE, "OBJTRACK", str);')
- header_txt.append(' OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;')
- header_txt.append(' pNewObjNode->vkObj = vkObj;')
- header_txt.append(' pNewObjNode->objType = objType;')
- header_txt.append(' pNewObjNode->status = OBJSTATUS_NONE;')
- header_txt.append(' objMap[vkObj] = pNewObjNode;')
- header_txt.append(' uint32_t objIndex = objTypeToIndex(objType);')
- header_txt.append(' numObjs[objIndex]++;')
- header_txt.append(' numTotalObjs++;')
- header_txt.append('}')
- header_txt.append('// Parse global list to find obj type, then remove obj from obj type list, finally')
- header_txt.append('// remove obj from global list')
- header_txt.append('static void destroy_obj(VkObject vkObj) {')
- header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
- header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
- header_txt.append(' uint32_t objIndex = objTypeToIndex(pNode->objType);')
- header_txt.append(' assert(numTotalObjs > 0);')
- header_txt.append(' numTotalObjs--;')
- header_txt.append(' assert(numObjs[objIndex] > 0);')
- header_txt.append(' numObjs[objIndex]--;')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%lu total objs remain & %lu %s objs).", string_VkObjectType(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj), numTotalObjs, numObjs[objIndex], string_VkObjectType(pNode->objType));')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_INFO_BIT, pNode->objType, vkObj, 0, OBJTRACK_NONE, "OBJTRACK", str);')
- header_txt.append(' delete pNode;')
- header_txt.append(' objMap.erase(vkObj);')
- header_txt.append(' }')
- header_txt.append(' else {')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?", reinterpret_cast<VkUintPtrLeast64>(vkObj));')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('// Set selected flag state for an object node')
- header_txt.append('static void set_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_flag) {')
- header_txt.append(' if (vkObj != VK_NULL_HANDLE) {')
- header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
- header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
- header_txt.append(' pNode->status |= status_flag;')
- header_txt.append(' return;')
- header_txt.append(' }')
- header_txt.append(' else {')
- header_txt.append(' // If we do not find it print an error')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "Unable to set status for non-existent object 0x%" PRIxLEAST64 " of %s type", reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, (VkObjectType) 0, vkObj, 0, OBJTRACK_NONE, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('// Reset selected flag state for an object node')
- header_txt.append('static void reset_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_flag) {')
- header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
- header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
- header_txt.append(' pNode->status &= ~status_flag;')
- header_txt.append(' return;')
- header_txt.append(' }')
- header_txt.append(' else {')
- header_txt.append(' // If we do not find it print an error')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "Unable to reset status for non-existent object 0x%" PRIxLEAST64 " of %s type", reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, objType, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('')
- header_txt.append('static void setGpuQueueInfoState(size_t* pDataSize, void *pData) {')
- header_txt.append(' queueCount = ((uint32_t)*pDataSize / sizeof(VkPhysicalDeviceQueueProperties));')
- header_txt.append(' queueInfo = (VkPhysicalDeviceQueueProperties*)realloc((void*)queueInfo, *pDataSize);')
- header_txt.append(' if (queueInfo != NULL) {')
- header_txt.append(' memcpy(queueInfo, pData, *pDataSize);')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('')
- header_txt.append('// Check Queue type flags for selected queue operations')
- header_txt.append('static void validateQueueFlags(VkQueue queue, const char *function) {')
- header_txt.append(' OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;')
- header_txt.append(' while ((pQueueInfo != NULL) && (pQueueInfo->queue != queue)) {')
- header_txt.append(' pQueueInfo = pQueueInfo->pNextQI;')
- header_txt.append(' }')
- header_txt.append(' if (pQueueInfo != NULL) {')
- header_txt.append(' char str[1024];\n')
- header_txt.append(' if ((queueInfo != NULL) && (queueInfo[pQueueInfo->queueNodeIndex].queueFlags & VK_QUEUE_SPARSE_MEMMGR_BIT) == 0) {')
- header_txt.append(' sprintf(str, "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not set", function);')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
- header_txt.append(' } else {')
- header_txt.append(' sprintf(str, "Attempting %s on a possibly non-memory-management capable queue -- VK_QUEUE_SPARSE_MEMMGR_BIT not known", function);')
- header_txt.append(' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_QUEUE, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
- header_txt.append(' }')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('%s' % self.lineinfo.get())
- header_txt.append('// Check object status for selected flag state')
- header_txt.append('static bool32_t validate_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_mask, ObjectStatusFlags status_flag, VkFlags msg_flags, OBJECT_TRACK_ERROR error_code, const char* fail_msg) {')
- header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {')
- header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];')
- header_txt.append(' if ((pNode->status & status_mask) != status_flag) {')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "OBJECT VALIDATION WARNING: %s object 0x%" PRIxLEAST64 ": %s", string_VkObjectType(objType), reinterpret_cast<VkUintPtrLeast64>(vkObj), fail_msg);')
- header_txt.append(' layerCbMsg(msg_flags, pNode->objType, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
- header_txt.append(' return VK_FALSE;')
- header_txt.append(' }')
- header_txt.append(' return VK_TRUE;')
- header_txt.append(' }')
- header_txt.append(' else {')
- header_txt.append(' // If we do not find it print an error')
- header_txt.append(' char str[1024];')
- header_txt.append(' sprintf(str, "Unable to obtain status for non-existent object 0x%" PRIxLEAST64 " of %s type", reinterpret_cast<VkUintPtrLeast64>(vkObj), string_VkObjectType(objType));')
- header_txt.append(' layerCbMsg(msg_flags, (VkObjectType) 0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
- header_txt.append(' return VK_FALSE;')
- header_txt.append(' }')
- header_txt.append('}')
- header_txt.append('')
- header_txt.append('struct devExts {')
- header_txt.append(' bool wsi_lunarg_enabled;')
- header_txt.append('};')
- header_txt.append('')
- header_txt.append('static std::unordered_map<void *, struct devExts> deviceExtMap;')
- header_txt.append('')
- header_txt.append('static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)')
- header_txt.append('{')
- header_txt.append(' uint32_t i, ext_idx;')
- header_txt.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
- header_txt.append(' deviceExtMap[pDisp].wsi_lunarg_enabled = false;')
- header_txt.append(' for (i = 0; i < pCreateInfo->extensionCount; i++) {')
- header_txt.append(' if (strcmp(pCreateInfo->pEnabledExtensions[i].name, VK_WSI_LUNARG_EXTENSION_NAME) == 0)')
- header_txt.append(' deviceExtMap[pDisp].wsi_lunarg_enabled = true;')
- header_txt.append('')
- header_txt.append(' }')
- header_txt.append('}')
+ header_txt.append('static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);')
header_txt.append('')
return "\n".join(header_txt)
@@ -1332,11 +1122,30 @@ class ObjectTrackerSubcommand(Subcommand):
# Command Buffer Object doesn't follow the rule.
obj_type_mapping['VkCmdBuffer'] = "VK_OBJECT_TYPE_COMMAND_BUFFER"
+ explicit_object_tracker_functions = [
+ "CreateInstance",
+ "DestroyInstance",
+ "GetPhysicalDeviceInfo",
+ "CreateDevice",
+ "DestroyDevice",
+ "GetDeviceQueue",
+ "QueueSubmit",
+ "DestroyObject",
+ "GetObjectInfo",
+ "QueueBindSparseImageMemory",
+ "QueueBindSparseBufferMemory",
+ "GetFenceStatus",
+ "WaitForFences",
+ "AllocDescriptorSets",
+ "MapMemory",
+ "UnmapMemory",
+ "FreeMemory",
+ "DestroySwapChainWSI"
+ ]
decl = proto.c_func(prefix="vk", attr="VKAPI")
param0_name = proto.params[0].name
using_line = ''
create_line = ''
- destroy_line = ''
object_params = []
# TODO : Should also check through struct params & add any objects embedded in struct chains
# TODO : A few of the skipped types are just "hard" cases that need some more work to support
@@ -1346,190 +1155,51 @@ class ObjectTrackerSubcommand(Subcommand):
object_params.append(p.name)
funcs = []
mutex_unlock = False
- if 'QueueSubmit' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' set_status(fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED);\n'
- using_line += ' // TODO: Fix for updated memory reference mechanism\n'
- using_line += ' // validate_memory_mapping_status(pMemRefs, memRefCount);\n'
- using_line += ' // validate_mem_ref_count(memRefCount);\n'
- mutex_unlock = True
- elif 'QueueBindSparse' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' validateQueueFlags(queue, "%s");\n' % (proto.name)
- mutex_unlock = True
- elif 'QueueBindObject' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' validateObjectType("vk%s", objType, object);\n' % (proto.name)
- mutex_unlock = True
- elif 'GetObjectInfo' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' validateObjectType("vk%s", objType, object);\n' % (proto.name)
- mutex_unlock = True
- elif 'GetFenceStatus' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' // Warn if submitted_flag is not set\n'
- using_line += ' validate_status(fence, VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");\n'
- mutex_unlock = True
- elif 'WaitForFences' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' // Warn if waiting on unsubmitted fence\n'
- using_line += ' for (uint32_t i = 0; i < fenceCount; i++) {\n'
- using_line += ' validate_status(pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_REPORT_ERROR_BIT, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");\n'
- using_line += ' }\n'
- mutex_unlock = True
- elif 'MapMemory' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' set_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n'
- mutex_unlock = True
- elif 'UnmapMemory' in proto.name:
- using_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- using_line += '%s\n' % self.lineinfo.get()
- using_line += ' reset_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n'
- mutex_unlock = True
- elif 'AllocDescriptor' in proto.name: # Allocates array of DSs
- create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- create_line += '%s\n' % self.lineinfo.get()
- create_line += ' for (uint32_t i = 0; i < *pCount; i++) {\n'
- create_line += ' create_obj(pDescriptorSets[i], VK_OBJECT_TYPE_DESCRIPTOR_SET);\n'
- create_line += ' }\n'
- create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- elif 'Create' in proto.name or 'Alloc' in proto.name:
- create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- create_line += ' if (result == VK_SUCCESS) {\n'
- if 'CreateDevice' in proto.name:
- create_line += '%s\n' % self.lineinfo.get()
- create_line += ' enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n'
- create_line += ' createDeviceRegisterExtensions(pCreateInfo, *pDevice);\n'
- elif 'CreateInstance' in proto.name:
- create_line += '%s\n' % self.lineinfo.get()
- create_line += ' enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions);\n'
- create_line += ' VkLayerInstanceDispatchTable *pTable = instance_dispatch_table(*pInstance);\n'
- create_line += ' debug_report_init_instance_extension_dispatch_table(\n'
- create_line += ' pTable,\n'
- create_line += ' pTable->GetInstanceProcAddr,\n'
- create_line += ' *pInstance);\n'
- create_line += ' create_obj(*%s, %s);\n' % (proto.params[-1].name, obj_type_mapping[proto.params[-1].ty.strip('*').replace('const ', '')])
- create_line += ' }\n'
- create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
-
- if 'GetDeviceQueue' in proto.name:
- destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += '%s\n' % self.lineinfo.get()
- destroy_line += ' addQueueInfo(queueNodeIndex, *pQueue);\n'
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- elif 'DestroyObject' in proto.name:
- destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += '%s\n' % self.lineinfo.get()
- destroy_line += ' validateObjectType("vk%s", objType, object);\n' % (proto.name)
- destroy_line += ' destroy_obj(%s);\n' % (proto.params[2].name)
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- elif 'DestroyDevice' in proto.name:
- using_line = ' dispatch_key key = get_dispatch_key(device);\n'
- using_line += ' VkLayerDispatchTable *pDisp = device_dispatch_table(device);\n'
- destroy_line = ' deviceExtMap.erase(pDisp);\n'
- destroy_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += '%s\n' % self.lineinfo.get()
- destroy_line += ' destroy_obj(device);\n'
- destroy_line += ' // Report any remaining objects\n'
- destroy_line += ' for (auto it = objMap.begin(); it != objMap.end(); ++it) {\n'
- destroy_line += ' OBJTRACK_NODE* pNode = it->second;'
- destroy_line += ' if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {\n'
- destroy_line += ' // Cannot destroy physical device so ignore\n'
- destroy_line += ' } else {\n'
- destroy_line += ' char str[1024];\n'
- destroy_line += ' sprintf(str, "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));\n'
- destroy_line += ' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE, device, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK", str);\n'
- destroy_line += ' }\n'
- destroy_line += ' }\n'
- destroy_line += ' // Clean up Queue\'s MemRef Linked Lists\n'
- destroy_line += ' destroyQueueMemRefLists();\n'
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- destroy_line += ' destroy_device_dispatch_table(key);\n'
- elif 'DestroyInstance' in proto.name:
- using_line = ' dispatch_key key = get_dispatch_key(instance);\n'
- destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += ' destroy_obj(%s);\n' % (param0_name)
- destroy_line += ' // Report any remaining objects in LL\n'
- destroy_line += ' for (auto it = objMap.begin(); it != objMap.end(); ++it) {\n'
- destroy_line += ' OBJTRACK_NODE* pNode = it->second; if ((pNode->objType == VK_OBJECT_TYPE_PHYSICAL_DEVICE) || (pNode->objType == VK_OBJECT_TYPE_QUEUE)) {\n'
- destroy_line += ' // Cannot destroy physical device so ignore\n'
- destroy_line += ' } else {\n'
- destroy_line += ' char str[1024];\n'
- destroy_line += ' sprintf(str, "OBJ ERROR : %s object 0x%" PRIxLEAST64 " has not been destroyed.", string_VkObjectType(pNode->objType), reinterpret_cast<VkUintPtrLeast64>(pNode->vkObj));\n'
- destroy_line += ' layerCbMsg(VK_DBG_REPORT_ERROR_BIT, pNode->objType, pNode->vkObj, 0, OBJTRACK_OBJECT_LEAK, "OBJTRACK", str);\n'
- destroy_line += ' }\n'
- destroy_line += ' }\n'
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- destroy_line += ' destroy_instance_dispatch_table(key);\n'
- elif 'Free' in proto.name:
- destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += '%s\n' % self.lineinfo.get()
- destroy_line += ' destroy_obj(%s);\n' % (proto.params[1].name)
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- elif 'Destroy' in proto.name:
- destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
- destroy_line += '%s\n' % self.lineinfo.get()
- destroy_line += ' destroy_obj(%s);\n' % (param0_name)
- destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- if len(object_params) > 0:
- if not mutex_unlock:
- using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
- mutex_unlock = True
- for opn in object_params:
- using_line += ' validate_object(%s);\n' % (opn)
- if mutex_unlock:
- using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- ret_val = ''
- stmt = ''
- table = ''
- if proto.ret != "void":
- ret_val = "%s result = " % proto.ret
- stmt = " return result;\n"
- if proto_is_global(proto):
- table = 'Instance'
-
- if 'GetPhysicalDeviceInfo' in proto.name:
- gpu_state = ' if (infoType == VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PROPERTIES) {\n'
- gpu_state += ' if (pData != NULL) {\n'
- gpu_state += ' loader_platform_thread_lock_mutex(&objLock);\n'
- gpu_state += ' setGpuQueueInfoState(pDataSize, pData);\n'
- gpu_state += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- gpu_state += ' }\n'
- gpu_state += ' }\n'
+ if proto.name in explicit_object_tracker_functions:
funcs.append('%s%s\n'
'{\n'
- '%s'
- ' %sinstance_dispatch_table(gpu)->%s;\n'
- '%s%s'
- '%s'
- '%s'
- '}' % (qual, decl, using_line, ret_val, proto.c_call(), create_line, destroy_line, gpu_state, stmt))
+ ' return explicit_%s;\n'
+ '}' % (qual, decl, proto.c_call()))
+ return "".join(funcs)
else:
- # CreateInstance needs to use the second parm instead of the first to set the correct dispatch table
- dispatch_param = param0_name
+ if 'Create' in proto.name or 'Alloc' in proto.name:
+ create_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
+ create_line += ' if (result == VK_SUCCESS) {\n'
+ create_line += ' create_obj(%s, *%s, %s);\n' % (param0_name, proto.params[-1].name, obj_type_mapping[proto.params[-1].ty.strip('*').replace('const ', '')])
+ create_line += ' }\n'
+ create_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
+ if len(object_params) > 0:
+ if not mutex_unlock:
+ using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
+ mutex_unlock = True
+ for opn in object_params:
+ using_line += ' validate_object(%s, %s);\n' % (param0_name, opn)
+ if mutex_unlock:
+ using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
+ ret_val = ''
+ stmt = ''
+ table = ''
+ if proto.ret != "void":
+ ret_val = "%s result = " % proto.ret
+ stmt = " return result;\n"
+
+ dispatch_param = proto.params[0].name
+ if 'CreateInstance' in proto.name:
+ dispatch_param = '*' + proto.params[1].name
+
# Must use 'instance' table for these APIs, 'device' table otherwise
table_type = ""
if proto_is_global(proto):
table_type = "instance"
else:
table_type = "device"
- if 'CreateInstance' in proto.name:
- dispatch_param = '*' + proto.params[1].name
- funcs.append('%s' % self.lineinfo.get())
funcs.append('%s%s\n'
'{\n'
'%s'
- ' %s%s_dispatch_table(%s)->%s;\n'
- '%s%s'
+ ' %sget_dispatch_table(ObjectTracker_%s_table_map, %s)->%s;\n'
'%s'
- '}' % (qual, decl, using_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, destroy_line, stmt))
+ '%s'
+ '}' % (qual, decl, using_line, ret_val, table_type, dispatch_param, proto.c_call(), create_line, stmt))
return "\n\n".join(funcs)
def generate_body(self):
@@ -1540,8 +1210,7 @@ class ObjectTrackerSubcommand(Subcommand):
('',
['objTrackGetObjectsCount', 'objTrackGetObjects',
'objTrackGetObjectsOfTypeCount', 'objTrackGetObjectsOfType'])]
- body = [self._generate_layer_initialization(True, lockname='obj'),
- self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
+ body = [self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
self._generate_extensions(),
self._generate_layer_gpa_function(extensions,
instance_extensions=['msg_callback_get_proc_addr'])]