From 9fde28dffb7e642dfa282e5bb8df44d9f4c2444a Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Thu, 14 May 2015 15:08:13 -0500 Subject: tests: Expand layer validation test coverage Added layer validation tests for several ObjectTracker and MemTracker validation cases. Also improved error handling in object tracker layer to handle validation failures that could cause unrecoverable driver errors. --- layers/mem_tracker.cpp | 24 ++++++++++++------------ vk-layer-generate.py | 27 +++++++++++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp index 3d3a9965..98fdb64c 100644 --- a/layers/mem_tracker.cpp +++ b/layers/mem_tracker.cpp @@ -482,7 +482,7 @@ static void reportMemReferencesAndCleanUp( char str[1024]; sprintf(str, "Attempting to free memory object %p which still contains %lu references", pMemObjInfo->mem, (cmdBufRefCount + objRefCount)); - layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, pMemObjInfo->mem, 0, MEMTRACK_INTERNAL_ERROR, "MEM", str); + layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, pMemObjInfo->mem, 0, MEMTRACK_INTERNAL_ERROR, "MEM", str); } if (cmdBufRefCount > 0 && pMemObjInfo->pCmdBufferBindings.size() > 0) { @@ -504,6 +504,7 @@ static void reportMemReferencesAndCleanUp( // Clear the list of hanging references pMemObjInfo->pObjBindings.clear(); } + } static void deleteMemObjInfo( @@ -583,10 +584,6 @@ static bool32_t freeMemObjInfo( // Now verify that no references to this mem obj remain if (0 != pInfo->refCount) { - // If references remain, report the error and can search CB list to find references - char str[1024]; - sprintf(str, "Freeing mem obj %p while it still has references", (void*)mem); - layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_FREED_MEM_REF, "MEM", str); reportMemReferencesAndCleanUp(pInfo); result = VK_FALSE; } @@ -668,6 +665,7 @@ static bool32_t updateObjectBinding( if (!pInfo) { sprintf(str, "While trying to bind mem for obj %p, couldn't find info for mem obj %p", (void*)object, (void*)mem); layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_MEM_OBJ, "MEM", str); + return VK_FALSE; } else { // Search for object in memory object's binding list bool32_t found = VK_FALSE; @@ -930,7 +928,7 @@ VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo( size_t *pDataSize, void *pData) { - /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */ + // This entrypoint is NOT going to init its own dispatch table since loader calls here early VkExtensionProperties *ext_props; uint32_t *count; @@ -1055,14 +1053,16 @@ VK_LAYER_EXPORT VkResult VKAPI vkFreeMemory( * all API objects referencing it and that it is not referenced by any queued command buffers */ loader_platform_thread_lock_mutex(&globalLock); - if (VK_FALSE == freeMemObjInfo(mem, false)) { - char str[1024]; - sprintf(str, "Issue while freeing mem obj %p", (void*)mem); - layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_FREE_MEM_ERROR, "MEM", str); - } + bool32_t noerror = freeMemObjInfo(mem, false); printMemList(); printObjList(); printCBList(); + // Output an warning message for proper error/warning handling + if (noerror == VK_FALSE) { + char str[1024]; + sprintf(str, "Freeing memory object while it still has references: mem obj %p", (void*)mem); + layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_FREED_MEM_REF, "MEM", str); + } loader_platform_thread_unlock_mutex(&globalLock); VkResult result = nextTable.FreeMemory(device, mem); return result; @@ -1092,7 +1092,7 @@ VK_LAYER_EXPORT VkResult VKAPI vkMapMemory( MT_MEM_OBJ_INFO *pMemObj = getMemObjInfo(mem); if ((pMemObj->allocInfo.memProps & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) { char str[1024]; - sprintf(str, "Mapping Memory (%p) without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set", (void*)mem); + sprintf(str, "Mapping Memory without VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT set: mem obj %p", (void*)mem); layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_STATE, "MEM", str); } loader_platform_thread_unlock_mutex(&globalLock); diff --git a/vk-layer-generate.py b/vk-layer-generate.py index 369d63b1..5c43a942 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -1139,11 +1139,13 @@ class ObjectTrackerSubcommand(Subcommand): header_txt.append(' return VK_FALSE;') header_txt.append('}') header_txt.append('') - header_txt.append('static void validate_draw_state_flags(VkObject vkObj) {') - header_txt.append(' validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_VIEWPORT_BOUND, OBJSTATUS_VIEWPORT_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_VIEWPORT_NOT_BOUND, "Viewport object not bound to this command buffer");') - header_txt.append(' validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_RASTER_BOUND, OBJSTATUS_RASTER_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_RASTER_NOT_BOUND, "Raster object not bound to this command buffer");') - header_txt.append(' validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_COLOR_BLEND_BOUND, OBJSTATUS_COLOR_BLEND_BOUND, VK_DBG_MSG_UNKNOWN, OBJTRACK_COLOR_BLEND_NOT_BOUND, "Color-blend object not bound to this command buffer");') - header_txt.append(' validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_DEPTH_STENCIL_BOUND, OBJSTATUS_DEPTH_STENCIL_BOUND, VK_DBG_MSG_UNKNOWN, OBJTRACK_DEPTH_STENCIL_NOT_BOUND, "Depth-stencil object not bound to this command buffer");') + header_txt.append('static bool32_t validate_draw_state_flags(VkObject vkObj) {') + header_txt.append(' bool32_t result1, result2, result3, result4;') + header_txt.append(' result1 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_VIEWPORT_BOUND, OBJSTATUS_VIEWPORT_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_VIEWPORT_NOT_BOUND, "Viewport object not bound to this command buffer");') + header_txt.append(' result2 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_RASTER_BOUND, OBJSTATUS_RASTER_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_RASTER_NOT_BOUND, "Raster object not bound to this command buffer");') + header_txt.append(' result3 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_COLOR_BLEND_BOUND, OBJSTATUS_COLOR_BLEND_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_COLOR_BLEND_NOT_BOUND, "Color-blend object not bound to this command buffer");') + header_txt.append(' result4 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_DEPTH_STENCIL_BOUND, OBJSTATUS_DEPTH_STENCIL_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_DEPTH_STENCIL_NOT_BOUND, "Depth-stencil object not bound to this command buffer");') + header_txt.append(' return ((result1 == VK_TRUE) && (result2 == VK_TRUE) && (result3 == VK_TRUE) && (result4 == VK_TRUE));') header_txt.append('}') header_txt.append('') return "\n".join(header_txt) @@ -1212,8 +1214,9 @@ class ObjectTrackerSubcommand(Subcommand): using_line += ' track_object_status(cmdBuffer, stateBindPoint);\n' using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n' elif 'CmdDraw' in proto.name: - using_line = ' loader_platform_thread_lock_mutex(&objLock);\n' - using_line += ' validate_draw_state_flags(cmdBuffer);\n' + using_line = ' bool32_t valid;\n' + using_line += ' loader_platform_thread_lock_mutex(&objLock);\n' + using_line += ' valid = validate_draw_state_flags(cmdBuffer);\n' using_line += ' loader_platform_thread_unlock_mutex(&objLock);\n' elif 'MapMemory' in proto.name: using_line = ' loader_platform_thread_lock_mutex(&objLock);\n' @@ -1295,7 +1298,6 @@ class ObjectTrackerSubcommand(Subcommand): ' }\n' '}' % (qual, decl, self.layer_name, ret_val, proto.c_call(), create_line, destroy_line, stmt, self.layer_name)) elif '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' @@ -1312,6 +1314,15 @@ class ObjectTrackerSubcommand(Subcommand): '%s' '%s' '}' % (qual, decl, self.layer_name, ret_val, proto.c_call(), create_line, destroy_line, gpu_state, stmt)) + elif 'CmdDraw' in proto.name: + funcs.append('%s%s\n' + '{\n' + '%s' + ' if (valid == VK_TRUE) {\n' + ' nextTable.%s;\n' + ' }\n' + '%s' + '}' % (qual, decl, using_line, proto.c_call(), stmt)) else: funcs.append('%s%s\n' '{\n' -- cgit v1.2.3