layers: Add memory manager queue validation to object tracker

Validate that sparse-memory binding operations only take place on queues
with MEMMGR capability.
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 1e419cd..8aa499a 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -844,16 +844,17 @@
         header_txt.append('//  per-Object list which just links objects of a given type')
         header_txt.append('// The object node has both pointers so the actual nodes are shared between the two lists')
         header_txt.append('typedef struct _objNode {')
-        header_txt.append('    OBJTRACK_NODE   obj;')
+        header_txt.append('    OBJTRACK_NODE    obj;')
         header_txt.append('    struct _objNode *pNextObj;')
         header_txt.append('    struct _objNode *pNextGlobal;')
         header_txt.append('} objNode;')
         header_txt.append('')
-        header_txt.append('static objNode *pObjectHead[VkNumObjectType] = {0};')
-        header_txt.append('static objNode *pGlobalHead = NULL;')
-        header_txt.append('static uint64_t numObjs[VkNumObjectType] = {0};')
-        header_txt.append('static uint64_t numTotalObjs = 0;')
-        header_txt.append('static uint32_t maxMemReferences = 0;')
+        header_txt.append('static objNode                         *pObjectHead[VkNumObjectType] = {0};')
+        header_txt.append('static objNode                         *pGlobalHead                  = NULL;')
+        header_txt.append('static uint64_t                         numObjs[VkNumObjectType]     = {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 {')
@@ -865,21 +866,23 @@
         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('    VkQueue               queue;')
-        header_txt.append('    uint32_t               refCount;')
+        header_txt.append('    OT_MEM_INFO                     *pMemRefList;')
+        header_txt.append('    struct _OT_QUEUE_INFO           *pNextQI;')
+        header_txt.append('    VkPhysicalDeviceQueueProperties *pQueueProps;')
+        header_txt.append('    VkQueue                          queue;')
+        header_txt.append('    uint32_t                         refCount;')
         header_txt.append('} OT_QUEUE_INFO;')
         header_txt.append('')
         header_txt.append('// Global list of QueueInfo structures, one per queue')
         header_txt.append('static OT_QUEUE_INFO *g_pQueueInfo;')
         header_txt.append('')
         header_txt.append('// Add new queue to head of global queue list')
-        header_txt.append('static void addQueueInfo(VkQueue queue)')
+        header_txt.append('static void addQueueInfo(uint32_t queueNodeIndex, VkQueue queue)')
         header_txt.append('{')
         header_txt.append('    OT_QUEUE_INFO *pQueueInfo = malloc(sizeof(OT_QUEUE_INFO));')
         header_txt.append('    memset(pQueueInfo, 0, sizeof(OT_QUEUE_INFO));')
-        header_txt.append('    pQueueInfo->queue = queue;')
+        header_txt.append('    pQueueInfo->queue       = queue;')
+        header_txt.append('    pQueueInfo->pQueueProps = &queueInfo[queueNodeIndex];')
         header_txt.append('')
         header_txt.append('    if (pQueueInfo != NULL) {')
         header_txt.append('        pQueueInfo->pNextQI   = g_pQueueInfo;')
@@ -1083,6 +1086,27 @@
         header_txt.append('    layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);')
         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*)malloc(sizeof(pDataSize));')
+        header_txt.append('    memcpy(queueInfo, pData, *pDataSize);')
+        header_txt.append('}')
+        header_txt.append('')
+        header_txt.append('// Check object status for selected flag state')
+        header_txt.append('static bool32_t validateQueueFlags(VkQueue queue) {')
+        header_txt.append('    bool32_t result = VK_TRUE;')
+        header_txt.append('    OT_QUEUE_INFO *pQueueInfo = g_pQueueInfo;')
+        header_txt.append('    while (pQueueInfo->queue != queue) {')
+        header_txt.append('        pQueueInfo = pQueueInfo->pNextQI;')
+        header_txt.append('    }')
+        header_txt.append('    if (pQueueInfo != NULL) {')
+        header_txt.append('        if ((pQueueInfo->pQueueProps->queueFlags & VK_QUEUE_MEMMGR_BIT) == 0) {')
+        header_txt.append('            result = VK_FALSE;')
+        header_txt.append('        }')
+        header_txt.append('    }')
+        header_txt.append('    return result;')
+        header_txt.append('}')
+        header_txt.append('')
         header_txt.append('// Check object status for selected flag state')
         header_txt.append('static bool32_t validate_status(VkObject vkObj, VK_OBJECT_TYPE objType, OBJECT_STATUS status_mask, OBJECT_STATUS status_flag, VK_DBG_MSG_TYPE error_level, OBJECT_TRACK_ERROR error_code, char* fail_msg) {')
         header_txt.append('    objNode *pTrav = pObjectHead[objType];')
@@ -1115,9 +1139,6 @@
         header_txt.append('    validate_status(vkObj, VkObjectTypeCmdBuffer, 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('}')
         header_txt.append('')
-        header_txt.append('static void setGpuQueueInfoState(void *pData) {')
-        header_txt.append('    maxMemReferences = ((VkPhysicalDeviceQueueProperties *)pData)->maxMemReferences;')
-        header_txt.append('}')
         return "\n".join(header_txt)
 
     def generate_intercept(self, proto, qual):
@@ -1147,6 +1168,14 @@
             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'
+        elif 'MemoryRange' in proto.name:
+            using_line = '    loader_platform_thread_lock_mutex(&objLock);\n'
+            using_line += '    if (validateQueueFlags(queue) == VK_FALSE) {\n'
+            using_line += '        char str[1024];\n'
+            using_line += '        sprintf(str, "Attempting %s on a non-memory-management capable queue -- VK_QUEUE_MEMMGR_BIT not set");\n' % (proto.name)
+            using_line += '        layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, queue, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);\n'
+            using_line += '    }\n'
+            using_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
         elif 'GetFenceStatus' in proto.name:
             using_line += '    // Warn if submitted_flag is not set\n'
             using_line += '    validate_status(fence, VkObjectTypeFence, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_MSG_ERROR, OBJTRACK_INVALID_FENCE, "Status Requested for Unsubmitted Fence");\n'
@@ -1215,7 +1244,7 @@
                 destroy_line += '    // Clean up Queue\'s MemRef Linked Lists\n'
                 destroy_line += '    destroyQueueMemRefLists();\n'
             if 'GetDeviceQueue' in proto.name:
-                destroy_line = '    addQueueInfo(*pQueue);\n'
+                destroy_line = '    addQueueInfo(queueNodeIndex, *pQueue);\n'
         ret_val = ''
         stmt = ''
         if proto.ret != "void":
@@ -1263,7 +1292,7 @@
         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 += '            setGpuQueueInfoState(pData);\n'
+            gpu_state += '            setGpuQueueInfoState(pDataSize, pData);\n'
             gpu_state += '        }\n'
             gpu_state += '    }\n'
             funcs.append('%s%s\n'