aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--layers/object_tracker.h208
-rwxr-xr-xvk-layer-generate.py260
2 files changed, 227 insertions, 241 deletions
diff --git a/layers/object_tracker.h b/layers/object_tracker.h
index 54f42351..c5a2452b 100644
--- a/layers/object_tracker.h
+++ b/layers/object_tracker.h
@@ -450,21 +450,19 @@ static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDev
static void create_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType);
static void create_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType);
static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType);
-static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object);
-static VkBool32 validate_image(VkCommandBuffer dispatchable_object, VkImage object);
-static VkBool32 validate_command_buffer(VkQueue dispatchable_object, VkCommandBuffer object);
-static VkBool32 validate_descriptor_set(VkCommandBuffer dispatchable_object, VkDescriptorSet object);
-static VkBool32 validate_instance(VkInstance dispatchable_object, VkInstance object);
-static VkBool32 validate_device(VkDevice dispatchable_object, VkDevice object);
-static VkBool32 validate_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object);
-static VkBool32 validate_descriptor_set_layout(VkDevice dispatchable_object, VkDescriptorSetLayout object);
-static VkBool32 validate_command_pool(VkDevice dispatchable_object, VkCommandPool object);
+static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
+static VkBool32 validate_instance(VkInstance dispatchable_object, VkInstance object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
+static VkBool32 validate_device(VkDevice dispatchable_object, VkDevice object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
+static VkBool32 validate_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
+static VkBool32 validate_descriptor_set_layout(VkDevice dispatchable_object, VkDescriptorSetLayout object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
+static VkBool32 validate_command_pool(VkDevice dispatchable_object, VkCommandPool object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
+static VkBool32 validate_buffer(VkQueue dispatchable_object, VkBuffer object, VkDebugReportObjectTypeEXT objType, bool null_allowed);
static void destroy_command_pool(VkDevice dispatchable_object, VkCommandPool object);
static void destroy_command_buffer(VkCommandBuffer dispatchable_object, VkCommandBuffer object);
static void destroy_descriptor_pool(VkDevice dispatchable_object, VkDescriptorPool object);
static void destroy_descriptor_set(VkDevice dispatchable_object, VkDescriptorSet object);
-static void destroy_instance(VkInstance dispatchable_object, VkInstance object);
static void destroy_device_memory(VkDevice dispatchable_object, VkDeviceMemory object);
+static void destroy_swapchain_khr(VkDevice dispatchable_object, VkSwapchainKHR object);
static VkBool32 set_device_memory_status(VkDevice dispatchable_object, VkDeviceMemory object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag);
static VkBool32 reset_device_memory_status(VkDevice dispatchable_object, VkDeviceMemory object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag);
#if 0
@@ -482,53 +480,7 @@ extern unordered_map<uint64_t, OBJTRACK_NODE*> VkSemaphoreMap;
extern unordered_map<uint64_t, OBJTRACK_NODE*> VkCommandPoolMap;
extern unordered_map<uint64_t, OBJTRACK_NODE*> VkCommandBufferMap;
extern unordered_map<uint64_t, OBJTRACK_NODE*> VkSwapchainKHRMap;
-
-static VkBool32 validate_image(VkQueue dispatchable_object, VkImage object)
-{
- if ((VkImageMap.find(reinterpret_cast<uint64_t>(object)) == VkImageMap.end()) &&
- (swapchainImageMap.find(reinterpret_cast<uint64_t>(object)) == swapchainImageMap.end())) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkImage Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
-
-static VkBool32 validate_image(VkCommandBuffer dispatchable_object, VkImage object)
-{
- if ((VkImageMap.find(reinterpret_cast<uint64_t>(object)) == VkImageMap.end()) &&
- (swapchainImageMap.find(reinterpret_cast<uint64_t>(object)) == swapchainImageMap.end())) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkImage Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
-
-static VkBool32 validate_command_buffer(VkQueue dispatchable_object, VkCommandBuffer object)
-{
- if (VkCommandBufferMap.find(reinterpret_cast<uint64_t>(object)) == VkCommandBufferMap.end()) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkCommandBuffer Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
-
-static VkBool32 validate_descriptor_set(VkCommandBuffer dispatchable_object, VkDescriptorSet object)
-{
- if (VkDescriptorSetMap.find(reinterpret_cast<uint64_t>(object)) == VkDescriptorSetMap.end()) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkDescriptorSet Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
-
-static VkBool32 validate_buffer(VkQueue dispatchable_object, VkBuffer object)
-{
- if (VkBufferMap.find(reinterpret_cast<uint64_t>(object)) != VkBufferMap.end()) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkBuffer Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
+extern unordered_map<uint64_t, OBJTRACK_NODE*> VkSurfaceKHRMap;
static VkBool32 set_status(VkQueue dispatchable_object, VkFence object, VkDebugReportObjectTypeEXT objType, ObjectStatusFlags status_flag)
{
@@ -548,24 +500,6 @@ static VkBool32 set_status(VkQueue dispatchable_object, VkFence object, VkDebugR
return skipCall;
}
-static VkBool32 validate_semaphore(VkQueue dispatchable_object, VkSemaphore object)
-{
- if (VkSemaphoreMap.find(reinterpret_cast<uint64_t>(object)) == VkSemaphoreMap.end()) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkSemaphore Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
-
-static VkBool32 validate_command_buffer(VkDevice dispatchable_object, VkCommandBuffer object)
-{
- if (VkCommandBufferMap.find(reinterpret_cast<uint64_t>(object)) == VkCommandBufferMap.end()) {
- return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",
- "Invalid VkCommandBuffer Object %" PRIu64, reinterpret_cast<uint64_t>(object));
- }
- return VK_FALSE;
-}
-
static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDevice vkObj, VkDebugReportObjectTypeEXT objType)
{
log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",
@@ -582,14 +516,44 @@ static void create_physical_device(VkInstance dispatchable_object, VkPhysicalDev
numTotalObjs++;
}
-static void create_surface_khr(VkInstance instance, VkSurfaceKHR surface, VkDebugReportObjectTypeEXT objType)
+static void create_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR vkObj, VkDebugReportObjectTypeEXT objType)
{
// TODO: Add tracking of surface objects
+ log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",
+ "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),
+ reinterpret_cast<uint64_t>(vkObj));
+
+ OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;
+ pNewObjNode->objType = objType;
+ pNewObjNode->status = OBJSTATUS_NONE;
+ pNewObjNode->vkObj = reinterpret_cast<uint64_t>(vkObj);
+ VkSurfaceKHRMap[(uint64_t)vkObj] = pNewObjNode;
+ uint32_t objIndex = objTypeToIndex(objType);
+ numObjs[objIndex]++;
+ numTotalObjs++;
}
-static void destroy_surface_khr(VkInstance instance, VkSurfaceKHR surface)
+static void destroy_surface_khr(VkInstance dispatchable_object, VkSurfaceKHR object)
{
- // TODO: Add tracking of surface objects
+ uint64_t object_handle = reinterpret_cast<uint64_t>(object);
+ if (VkSurfaceKHRMap.find(object_handle) != VkSurfaceKHRMap.end()) {
+ OBJTRACK_NODE* pNode = VkSurfaceKHRMap[(uint64_t)object];
+ uint32_t objIndex = objTypeToIndex(pNode->objType);
+ assert(numTotalObjs > 0);
+ numTotalObjs--;
+ assert(numObjs[objIndex] > 0);
+ numObjs[objIndex]--;
+ log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, pNode->objType, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",
+ "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",
+ string_VkDebugReportObjectTypeEXT(pNode->objType), reinterpret_cast<uint64_t>(object), numTotalObjs, numObjs[objIndex],
+ string_VkDebugReportObjectTypeEXT(pNode->objType));
+ delete pNode;
+ VkSurfaceKHRMap.erase(object_handle);
+ } else {
+ log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_NONE, "OBJTRACK",
+ "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
+ object_handle);
+ }
}
static void alloc_command_buffer(VkDevice device, VkCommandPool commandPool, VkCommandBuffer vkObj, VkDebugReportObjectTypeEXT objType)
@@ -687,21 +651,6 @@ static void free_descriptor_set(VkDevice device, VkDescriptorPool descriptorPool
}
}
-static void create_swapchain_khr(VkDevice dispatchable_object, VkSwapchainKHR vkObj, VkDebugReportObjectTypeEXT objType)
-{
- log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, (uint64_t) vkObj, __LINE__, OBJTRACK_NONE, "OBJTRACK",
- "OBJ[%llu] : CREATE %s object 0x%" PRIxLEAST64 , object_track_index++, string_VkDebugReportObjectTypeEXT(objType),
- reinterpret_cast<uint64_t>(vkObj));
-
- OBJTRACK_NODE* pNewObjNode = new OBJTRACK_NODE;
- pNewObjNode->objType = objType;
- pNewObjNode->status = OBJSTATUS_NONE;
- pNewObjNode->vkObj = (uint64_t) vkObj;
- VkSwapchainKHRMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode;
- uint32_t objIndex = objTypeToIndex(objType);
- numObjs[objIndex]++;
- numTotalObjs++;
-}
static void create_queue(VkDevice dispatchable_object, VkQueue vkObj, VkDebugReportObjectTypeEXT objType)
{
log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, objType, reinterpret_cast<uint64_t>(vkObj), __LINE__, OBJTRACK_NONE, "OBJTRACK",
@@ -731,35 +680,14 @@ static void create_swapchain_image_obj(VkDevice dispatchable_object, VkImage vkO
swapchainImageMap[reinterpret_cast<uint64_t>(vkObj)] = pNewObjNode;
}
-static void destroy_swapchain(VkDevice dispatchable_object, VkSwapchainKHR object)
-{
- if (VkSwapchainKHRMap.find(reinterpret_cast<uint64_t>(object)) != VkSwapchainKHRMap.end()) {
- OBJTRACK_NODE* pNode = VkSwapchainKHRMap[reinterpret_cast<uint64_t>(object)];
- uint32_t objIndex = objTypeToIndex(pNode->objType);
- assert(numTotalObjs > 0);
- numTotalObjs--;
- assert(numObjs[objIndex] > 0);
- numObjs[objIndex]--;
- log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_INFO_BIT_EXT, pNode->objType, (uint64_t) object, __LINE__, OBJTRACK_NONE, "OBJTRACK",
- "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",
- string_VkDebugReportObjectTypeEXT(pNode->objType), (uint64_t) object, numTotalObjs, numObjs[objIndex],
- string_VkDebugReportObjectTypeEXT(pNode->objType));
- delete pNode;
- VkSwapchainKHRMap.erase(reinterpret_cast<uint64_t>(object));
- } else {
- log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT) 0, (uint64_t) object, __LINE__, OBJTRACK_NONE, "OBJTRACK",
- "Unable to remove obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
- reinterpret_cast<uint64_t>(object));
- }
-}
//
// Non-auto-generated API functions called by generated code
//
VkResult
explicit_CreateInstance(
- const VkInstanceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks * pAllocator,
- VkInstance * pInstance)
+ const VkInstanceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkInstance *pInstance)
{
VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, *pInstance);
@@ -820,7 +748,7 @@ VkResult explicit_EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysi
{
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
- skipCall |= validate_instance(instance, instance);
+ skipCall |= validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall)
return VK_ERROR_VALIDATION_FAILED_EXT;
@@ -845,7 +773,7 @@ explicit_GetDeviceQueue(
VkQueue *pQueue)
{
loader_platform_thread_lock_mutex(&objLock);
- validate_device(device, device);
+ validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
get_dispatch_table(object_tracker_device_table_map, device)->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
@@ -868,7 +796,7 @@ explicit_MapMemory(
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
skipCall |= set_device_memory_status(device, mem, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, OBJSTATUS_GPU_MEM_MAPPED);
- skipCall |= validate_device(device, device);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall == VK_TRUE)
return VK_ERROR_VALIDATION_FAILED_EXT;
@@ -886,7 +814,7 @@ explicit_UnmapMemory(
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
skipCall |= reset_device_memory_status(device, mem, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, OBJSTATUS_GPU_MEM_MAPPED);
- skipCall |= validate_device(device, device);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall == VK_TRUE)
return;
@@ -906,11 +834,11 @@ explicit_QueueBindSparse(
for (uint32_t i = 0; i < bindInfoCount; i++) {
for (uint32_t j = 0; j < pBindInfo[i].bufferBindCount; j++)
- validate_buffer(queue, pBindInfo[i].pBufferBinds[j].buffer);
+ validate_buffer(queue, pBindInfo[i].pBufferBinds[j].buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, false);
for (uint32_t j = 0; j < pBindInfo[i].imageOpaqueBindCount; j++)
- validate_image(queue, pBindInfo[i].pImageOpaqueBinds[j].image);
+ validate_image(queue, pBindInfo[i].pImageOpaqueBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, false);
for (uint32_t j = 0; j < pBindInfo[i].imageBindCount; j++)
- validate_image(queue, pBindInfo[i].pImageBinds[j].image);
+ validate_image(queue, pBindInfo[i].pImageBinds[j].image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, false);
}
loader_platform_thread_unlock_mutex(&objLock);
@@ -927,8 +855,8 @@ explicit_AllocateCommandBuffers(
{
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
- skipCall |= validate_device(device, device);
- skipCall |= validate_command_pool(device, pAllocateInfo->commandPool);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
+ skipCall |= validate_command_pool(device, pAllocateInfo->commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall) {
@@ -955,10 +883,10 @@ explicit_AllocateDescriptorSets(
{
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
- skipCall |= validate_device(device, device);
- skipCall |= validate_descriptor_pool(device, pAllocateInfo->descriptorPool);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
+ skipCall |= validate_descriptor_pool(device, pAllocateInfo->descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false);
for (uint32_t i = 0; i < pAllocateInfo->setLayoutCount; i++) {
- skipCall |= validate_descriptor_set_layout(device, pAllocateInfo->pSetLayouts[i]);
+ skipCall |= validate_descriptor_set_layout(device, pAllocateInfo->pSetLayouts[i], VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, false);
}
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall)
@@ -984,8 +912,8 @@ explicit_FreeCommandBuffers(
const VkCommandBuffer *pCommandBuffers)
{
loader_platform_thread_lock_mutex(&objLock);
- validate_command_pool(device, commandPool);
- validate_device(device, device);
+ validate_command_pool(device, commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false);
+ validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
get_dispatch_table(object_tracker_device_table_map, device)->FreeCommandBuffers(device,
@@ -1018,7 +946,7 @@ explicit_DestroySwapchainKHR(
++itr;
}
}
- destroy_swapchain(device, swapchain);
+ destroy_swapchain_khr(device, swapchain);
loader_platform_thread_unlock_mutex(&objLock);
get_dispatch_table(object_tracker_device_table_map, device)->DestroySwapchainKHR(device, swapchain, pAllocator);
@@ -1031,7 +959,7 @@ explicit_FreeMemory(
const VkAllocationCallbacks* pAllocator)
{
loader_platform_thread_lock_mutex(&objLock);
- validate_device(device, device);
+ validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
get_dispatch_table(object_tracker_device_table_map, device)->FreeMemory(device, mem, pAllocator);
@@ -1049,8 +977,8 @@ explicit_FreeDescriptorSets(
const VkDescriptorSet *pDescriptorSets)
{
loader_platform_thread_lock_mutex(&objLock);
- validate_descriptor_pool(device, descriptorPool);
- validate_device(device, device);
+ validate_descriptor_pool(device, descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false);
+ validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
VkResult result = get_dispatch_table(object_tracker_device_table_map, device)->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
@@ -1071,8 +999,8 @@ explicit_DestroyDescriptorPool(
{
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
- skipCall |= validate_device(device, device);
- skipCall |= validate_descriptor_pool(device, descriptorPool);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
+ skipCall |= validate_descriptor_pool(device, descriptorPool, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall) {
return;
@@ -1101,8 +1029,8 @@ explicit_DestroyCommandPool(
{
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
- skipCall |= validate_device(device, device);
- skipCall |= validate_command_pool(device, commandPool);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
+ skipCall |= validate_command_pool(device, commandPool, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall) {
return;
@@ -1134,7 +1062,7 @@ explicit_GetSwapchainImagesKHR(
{
VkBool32 skipCall = VK_FALSE;
loader_platform_thread_lock_mutex(&objLock);
- skipCall |= validate_device(device, device);
+ skipCall |= validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);
loader_platform_thread_unlock_mutex(&objLock);
if (skipCall)
return VK_ERROR_VALIDATION_FAILED_EXT;
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 54df0a55..2f93a80a 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -1402,14 +1402,41 @@ class ObjectTrackerSubcommand(Subcommand):
def generate_maps(self):
maps_txt = []
- for o in vulkan.core.objects:
+ for o in vulkan.object_type_list:
maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> %sMap;' % (o))
- maps_txt.append('unordered_map<uint64_t, OBJTRACK_NODE*> VkSwapchainKHRMap;')
return "\n".join(maps_txt)
+ def _gather_object_uses(self, obj_list, struct_type, obj_set):
+ # for each member of struct_type
+ # add objs in obj_list to obj_set
+ # call self for structs
+ for m in vk_helper.struct_dict[struct_type]:
+ if vk_helper.struct_dict[struct_type][m]['type'] in obj_list:
+ obj_set.add(vk_helper.struct_dict[struct_type][m]['type'])
+ elif vk_helper.is_type(vk_helper.struct_dict[struct_type][m]['type'], 'struct'):
+ obj_set = obj_set.union(self._gather_object_uses(obj_list, vk_helper.struct_dict[struct_type][m]['type'], obj_set))
+ return obj_set
+
def generate_procs(self):
procs_txt = []
- for o in vulkan.core.objects:
+ # First parse through funcs and gather dict of all objects seen by each call
+ obj_use_dict = {}
+ proto_list = vulkan.core.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_surface.protos + vulkan.ext_khr_win32_surface.protos + vulkan.ext_khr_device_swapchain.protos
+ for proto in proto_list:
+ disp_obj = proto.params[0].ty.strip('*').replace('const ', '')
+ if disp_obj in vulkan.object_dispatch_list:
+ if disp_obj not in obj_use_dict:
+ obj_use_dict[disp_obj] = set()
+ for p in proto.params[1:]:
+ base_type = p.ty.strip('*').replace('const ', '')
+ if base_type in vulkan.object_type_list:
+ obj_use_dict[disp_obj].add(base_type)
+ if vk_helper.is_type(base_type, 'struct'):
+ obj_use_dict[disp_obj] = self._gather_object_uses(vulkan.object_type_list, base_type, obj_use_dict[disp_obj])
+ #for do in obj_use_dict:
+ # print "Disp obj %s has uses for objs: %s" % (do, ', '.join(obj_use_dict[do]))
+
+ for o in vulkan.object_type_list:# vulkan.core.objects:
procs_txt.append('%s' % self.lineinfo.get())
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
@@ -1433,40 +1460,6 @@ class ObjectTrackerSubcommand(Subcommand):
procs_txt.append('}')
procs_txt.append('')
procs_txt.append('%s' % self.lineinfo.get())
- # TODO : This is not complete and currently requires some hand-coded function in the header
- # Really we want to capture the set of all objects and their associated dispatchable objects
- # that are bound by the API calls:
- # foreach API Call
- # foreach object type seen by call
- # create validate_object(disp_obj, object)
- if o in vulkan.object_dispatch_list:
- procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object)' % (name, o, o))
- else:
- procs_txt.append('static VkBool32 validate_%s(VkDevice dispatchable_object, %s object)' % (name, o))
- procs_txt.append('{')
- if o in vulkan.object_dispatch_list:
- procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
- procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
- procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % o)
- else:
- if o == "VkPipelineCache":
- procs_txt.append(' // VkPipelineCache object can be NULL if not caching')
- procs_txt.append(' if (object == VK_NULL_HANDLE) return VK_TRUE;')
- procs_txt.append('')
- if o == "VkImage":
- procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
- procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
- procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
- else:
- procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
- procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, (uint64_t) object, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
- procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o)
- procs_txt.append(' }')
- procs_txt.append(' return VK_FALSE;')
- procs_txt.append('}')
- procs_txt.append('')
- procs_txt.append('')
- procs_txt.append('%s' % self.lineinfo.get())
if o in vulkan.object_dispatch_list:
procs_txt.append('static void destroy_%s(%s dispatchable_object, %s object)' % (name, o, o))
else:
@@ -1568,6 +1561,51 @@ class ObjectTrackerSubcommand(Subcommand):
procs_txt.append(' return VK_FALSE;')
procs_txt.append('}')
procs_txt.append('')
+ procs_txt.append('%s' % self.lineinfo.get())
+ # Generate the permutations of validate_* functions where for each
+ # dispatchable object type, we have a corresponding validate_* function
+ # for that object and all non-dispatchable objects that are used in API
+ # calls with that dispatchable object.
+ procs_txt.append('//%s' % str(obj_use_dict))
+ for do in obj_use_dict:
+ name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', do)
+ name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
+ # First create validate_* func for disp obj
+ procs_txt.append('%s' % self.lineinfo.get())
+ procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, do))
+ procs_txt.append('{')
+ procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
+ procs_txt.append(' return VK_FALSE;')
+ procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (do, do))
+ procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
+ procs_txt.append(' "Invalid %s Object 0x%%" PRIx64 ,reinterpret_cast<uint64_t>(object));' % do)
+ procs_txt.append(' }')
+ procs_txt.append(' return VK_FALSE;')
+ procs_txt.append('}')
+ procs_txt.append('')
+ for o in obj_use_dict[do]:
+ if o == do: # We already generated this case above so skip here
+ continue
+ name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
+ name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
+ procs_txt.append('%s' % self.lineinfo.get())
+ procs_txt.append('static VkBool32 validate_%s(%s dispatchable_object, %s object, VkDebugReportObjectTypeEXT objType, bool null_allowed)' % (name, do, o))
+ procs_txt.append('{')
+ procs_txt.append(' if (null_allowed && (object == VK_NULL_HANDLE))')
+ procs_txt.append(' return VK_FALSE;')
+ if o == "VkImage":
+ procs_txt.append(' // We need to validate normal image objects and those from the swapchain')
+ procs_txt.append(' if ((%sMap.find((uint64_t)object) == %sMap.end()) &&' % (o, o))
+ procs_txt.append(' (swapchainImageMap.find((uint64_t)object) == swapchainImageMap.end())) {')
+ else:
+ procs_txt.append(' if (%sMap.find((uint64_t)object) == %sMap.end()) {' % (o, o))
+ procs_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, objType, reinterpret_cast<uint64_t>(object), __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
+ procs_txt.append(' "Invalid %s Object 0x%%" PRIx64, reinterpret_cast<uint64_t>(object));' % o)
+ procs_txt.append(' }')
+ procs_txt.append(' return VK_FALSE;')
+ procs_txt.append('}')
+ procs_txt.append('')
+ procs_txt.append('')
return "\n".join(procs_txt)
def generate_destroy_instance(self):
@@ -1578,7 +1616,7 @@ class ObjectTrackerSubcommand(Subcommand):
gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
gedi_txt.append('{')
gedi_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
- gedi_txt.append(' validate_instance(instance, instance);')
+ gedi_txt.append(' validate_instance(instance, instance, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, false);')
gedi_txt.append('')
gedi_txt.append(' destroy_instance(instance, instance);')
gedi_txt.append(' // Report any remaining objects in LL')
@@ -1627,7 +1665,7 @@ class ObjectTrackerSubcommand(Subcommand):
gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
gedd_txt.append('{')
gedd_txt.append(' loader_platform_thread_lock_mutex(&objLock);')
- gedd_txt.append(' validate_device(device, device);')
+ gedd_txt.append(' validate_device(device, device, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, false);')
gedd_txt.append('')
gedd_txt.append(' destroy_device(device, device);')
gedd_txt.append(' // Report any remaining objects in LL')
@@ -1658,24 +1696,71 @@ class ObjectTrackerSubcommand(Subcommand):
gedd_txt.append('')
return "\n".join(gedd_txt)
- def generate_command_buffer_validates(self):
- cbv_txt = []
- cbv_txt.append('%s' % self.lineinfo.get())
- for o in ['VkPipeline',
- 'VkPipelineLayout', 'VkBuffer', 'VkEvent', 'VkQueryPool', 'VkRenderPass', 'VkFramebuffer']:
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', o)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- cbv_txt.append('static VkBool32 validate_%s(VkCommandBuffer dispatchable_object, %s object)' % (name, o))
- cbv_txt.append('{')
- cbv_txt.append(' uint64_t object_handle = reinterpret_cast<uint64_t>(object);')
- cbv_txt.append(' if (%sMap.find(object_handle) == %sMap.end()) {' % (o, o))
- cbv_txt.append(' return log_msg(mdd(dispatchable_object), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT ) 0, object_handle, __LINE__, OBJTRACK_INVALID_OBJECT, "OBJTRACK",')
- cbv_txt.append(' "Invalid %s Object 0x%%" PRIx64, object_handle);' % (o))
- cbv_txt.append(' }')
- cbv_txt.append(' return VK_FALSE;')
- cbv_txt.append('}')
- cbv_txt.append('')
- return "\n".join(cbv_txt)
+ def _gen_obj_validate_code(self, struct_uses, obj_type_mapping, func_name, valid_null_dict, param0_name, indent, prefix, array_index):
+ pre_code = ''
+ for obj in sorted(struct_uses):
+ name = obj
+ array = ''
+ if '[' in obj:
+ (name, array) = obj.split('[')
+ array = array.strip(']')
+ if isinstance(struct_uses[obj], dict):
+ local_prefix = ''
+ name = '%s%s' % (prefix, name)
+ ptr_type = False
+ if 'p' == obj[0]:
+ ptr_type = True
+ pre_code += '%sif (%s) {\n' % (indent, name)
+ indent += ' '
+ if array != '':
+ idx = 'idx%s' % str(array_index)
+ array_index += 1
+ pre_code += '%s\n' % self.lineinfo.get()
+ pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
+ indent += ' '
+ local_prefix = '%s[%s].' % (name, idx)
+ elif ptr_type:
+ local_prefix = '%s->' % (name)
+ else:
+ local_prefix = '%s.' % (name)
+ tmp_pre = self._gen_obj_validate_code(struct_uses[obj], obj_type_mapping, func_name, valid_null_dict, param0_name, indent, local_prefix, array_index)
+ pre_code += tmp_pre
+ if array != '':
+ indent = indent[4:]
+ pre_code += '%s}\n' % (indent)
+ if ptr_type:
+ indent = indent[4:]
+ pre_code += '%s}\n' % (indent)
+ else:
+ ptype = struct_uses[obj]
+ dbg_obj_type = obj_type_mapping[ptype]
+ fname = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', ptype)
+ fname = re.sub('([a-z0-9])([A-Z])', r'\1_\2', fname).lower()[3:]
+ full_name = '%s%s' % (prefix, name)
+ null_obj_ok = 'false'
+ # If a valid null param is defined for this func and we have a match, allow NULL
+ if func_name in valid_null_dict and True in [name in pn for pn in valid_null_dict[func_name]]:
+ null_obj_ok = 'true'
+ if (array_index > 0) or '' != array:
+ pre_code += '%sif (%s) {\n' %(indent, full_name)
+ indent += ' '
+ if array != '':
+ idx = 'idx%s' % str(array_index)
+ array_index += 1
+ pre_code += '%sfor (uint32_t %s=0; %s<%s%s; ++%s) {\n' % (indent, idx, idx, prefix, array, idx)
+ indent += ' '
+ full_name = '%s[%s]' % (full_name, idx)
+ pre_code += '%s\n' % self.lineinfo.get()
+ pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
+ if array != '':
+ indent = indent[4:]
+ pre_code += '%s}\n' % (indent)
+ indent = indent[4:]
+ pre_code += '%s}\n' % (indent)
+ else:
+ pre_code += '%s\n' % self.lineinfo.get()
+ pre_code += '%sskipCall |= validate_%s(%s, %s, %s, %s);\n' %(indent, fname, param0_name, full_name, dbg_obj_type, null_obj_ok)
+ return pre_code
def generate_intercept(self, proto, qual):
if proto.name in [ 'CreateDebugReportCallbackEXT', 'EnumerateInstanceLayerProperties', 'EnumerateInstanceExtensionProperties','EnumerateDeviceLayerProperties', 'EnumerateDeviceExtensionProperties' ]:
@@ -1727,7 +1812,9 @@ class ObjectTrackerSubcommand(Subcommand):
'CreateComputePipelines' : ['basePipelineHandle'],
'BeginCommandBuffer' : ['renderPass', 'framebuffer'],
'QueueSubmit' : ['fence'],
+ 'AcquireNextImageKHR' : ['fence'],
'UpdateDescriptorSets' : ['pTexelBufferView'],
+ 'CreateSwapchainKHR' : ['oldSwapchain'],
}
param_count = 'NONE' # keep track of arrays passed directly into API functions
for p in proto.params:
@@ -1778,6 +1865,12 @@ class ObjectTrackerSubcommand(Subcommand):
else:
loop_params[0].append(param_name)
loop_types[0].append('%s' % (vk_helper.struct_dict[struct_type][m]['type']))
+ last_param_index = None
+ create_func = False
+ if True in [create_txt in proto.name for create_txt in ['Create', 'Allocate']]:
+ create_func = True
+ last_param_index = -1 # For create funcs don't validate last object
+ struct_uses = get_object_uses(vulkan.object_type_list, proto.params[:last_param_index])
funcs = []
mutex_unlock = False
funcs.append('%s\n' % self.lineinfo.get())
@@ -1791,7 +1884,7 @@ class ObjectTrackerSubcommand(Subcommand):
elif 'DestroyInstance' in proto.name or 'DestroyDevice' in proto.name:
return ""
else:
- if 'Create' in proto.name or 'Alloc' in proto.name:
+ if create_func:
typ = proto.params[-1].ty.strip('*').replace('const ', '');
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
@@ -1816,53 +1909,19 @@ class ObjectTrackerSubcommand(Subcommand):
name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
funcs.append('%s\n' % self.lineinfo.get())
destroy_line = ' loader_platform_thread_lock_mutex(&objLock);\n'
-# destroy_line += ' if (result == VK_SUCCESS) {\n'
destroy_line += ' destroy_%s(%s, %s);\n' % (name, param0_name, proto.params[-2].name)
-# destroy_line += ' }\n'
destroy_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- if len(loop_params) > 0:
- using_line += ' VkBool32 skipCall = VK_FALSE;\n'
+ indent = ' '
+ if len(struct_uses) > 0:
+ using_line += '%sVkBool32 skipCall = VK_FALSE;\n' % (indent)
if not mutex_unlock:
- using_line += ' loader_platform_thread_lock_mutex(&objLock);\n'
+ using_line += '%sloader_platform_thread_lock_mutex(&objLock);\n' % (indent)
mutex_unlock = True
- for lc,lt in zip(loop_params,loop_types):
- if 0 == lc: # No looping required for these params
- for opn,typ in zip(loop_params[lc],loop_types[lt]):
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- if '->' in opn:
- using_line += ' if (%s)\n' % (opn.split('-')[0])
- using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
- else:
- if 'AcquireNext' in proto.name and 'fence' == name:
- using_line += ' if (fence != VK_NULL_HANDLE) {\n'
- using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
- using_line += ' }\n'
- else:
- using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
- else:
- base_param = loop_params[lc][0].split('-')[0].split('[')[0]
- using_line += ' if (%s) {\n' % base_param
- using_line += ' for (uint32_t i=0; i<%s; i++) {\n' % lc
- for opn,typ in zip(loop_params[lc],loop_types[lt]):
- name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', typ)
- name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()[3:]
- if ',' in opn: # double-embedded loop
- (inner_lc, inner_param) = opn.split(',')
- using_line += ' if (%s) {\n' % inner_param
- using_line += ' for (uint32_t j=0; j<%s; j++) {\n' % inner_lc
- using_line += ' skipCall |= validate_%s(%s, %s[j]);\n' % (name, param0_name, inner_param)
- using_line += ' }\n'
- using_line += ' }\n'
- elif '[' in opn: # API func param is array
- using_line += ' skipCall |= validate_%s(%s, %s);\n' % (name, param0_name, opn)
- else: # struct element is array
- using_line += ' skipCall |= validate_%s(%s, %s[i]);\n' % (name, param0_name, opn)
- using_line += ' }\n'
- using_line += ' }\n'
+ using_line += '// objects to validate: %s\n' % str(struct_uses)
+ using_line += self._gen_obj_validate_code(struct_uses, obj_type_mapping, proto.name, valid_null_object_names, param0_name, ' ', '', 0)
if mutex_unlock:
- using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n'
- if len(loop_params) > 0:
+ using_line += '%sloader_platform_thread_unlock_mutex(&objLock);\n' % (indent)
+ if len(struct_uses) > 0:
using_line += ' if (skipCall)\n'
if proto.ret != "void":
using_line += ' return VK_ERROR_VALIDATION_FAILED_EXT;\n'
@@ -1934,7 +1993,6 @@ class ObjectTrackerSubcommand(Subcommand):
self.generate_procs(),
self.generate_destroy_instance(),
self.generate_destroy_device(),
- self.generate_command_buffer_validates(),
self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
self._generate_extensions(),
self._generate_layer_gpa_function(extensions,