diff options
| author | Mark Lobodzinski <mark@lunarg.com> | 2015-06-23 11:35:12 -0600 |
|---|---|---|
| committer | Mark Lobodzinski <mark@lunarg.com> | 2015-06-23 11:35:12 -0600 |
| commit | 85bc15acd850ec9dc9d21df0a9910129dd852f8e (patch) | |
| tree | c89e5c1a71eb2af26cfa71553c89c6742ba7664a | |
| parent | f6e73a22d772a15c11d3da2087a5115295f6a749 (diff) | |
| download | usermoji-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.h | 854 | ||||
| -rwxr-xr-x | vk-layer-generate.py | 771 |
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'])] |
