xgl: Add QueueMemReference functions
diff --git a/icd/intel/queue.c b/icd/intel/queue.c
index 0bef4e3..354efe7 100644
--- a/icd/intel/queue.c
+++ b/icd/intel/queue.c
@@ -324,7 +324,29 @@
     const XGL_MEMORY_REF*                       pMemRefs)
 {
     /*
-     * The winwys maintains the list of memory references.  These are ignored
+     * The winsys maintains the list of memory references.  These are ignored
+     * until we move away from the winsys.
+     */
+    return XGL_SUCCESS;
+}
+
+ICD_EXPORT XGL_RESULT XGLAPI xglQueueAddMemReference(
+    XGL_QUEUE                                   queue,
+    XGL_GPU_MEMORY                              mem)
+{
+    /*
+     * The winsys maintains the list of memory references.  These are ignored
+     * until we move away from the winsys.
+     */
+    return XGL_SUCCESS;
+}
+
+ICD_EXPORT XGL_RESULT XGLAPI xglQueueRemoveMemReference(
+    XGL_QUEUE                                   queue,
+    XGL_GPU_MEMORY                              mem)
+{
+    /*
+     * The winsys maintains the list of memory references.  These are ignored
      * until we move away from the winsys.
      */
     return XGL_SUCCESS;
diff --git a/icd/nulldrv/nulldrv.c b/icd/nulldrv/nulldrv.c
index 4943922..84e3197 100644
--- a/icd/nulldrv/nulldrv.c
+++ b/icd/nulldrv/nulldrv.c
@@ -1727,6 +1727,22 @@
     return XGL_SUCCESS;
 }
 
+ICD_EXPORT XGL_RESULT XGLAPI xglQueueAddMemReference(
+    XGL_QUEUE                                   queue,
+    XGL_GPU_MEMORY                              mem)
+{
+    NULLDRV_LOG_FUNC;
+    return XGL_SUCCESS;
+}
+
+ICD_EXPORT XGL_RESULT XGLAPI xglQueueRemoveMemReference(
+    XGL_QUEUE                                   queue,
+    XGL_GPU_MEMORY                              mem)
+{
+    NULLDRV_LOG_FUNC;
+    return XGL_SUCCESS;
+}
+
 ICD_EXPORT XGL_RESULT XGLAPI xglQueueWaitIdle(
     XGL_QUEUE                                   queue_)
 {
diff --git a/include/xgl.h b/include/xgl.h
index bae9c3f..05c2d2c 100644
--- a/include/xgl.h
+++ b/include/xgl.h
@@ -33,7 +33,7 @@
 #include "xglPlatform.h"
 
 // XGL API version supported by this file
-#define XGL_API_VERSION XGL_MAKE_VERSION(0, 64, 0)
+#define XGL_API_VERSION XGL_MAKE_VERSION(0, 65, 0)
 
 #ifdef __cplusplus
 extern "C"
@@ -2271,6 +2271,8 @@
 typedef XGL_RESULT (XGLAPI *xglGetDeviceQueueType)(XGL_DEVICE device, uint32_t queueNodeIndex, uint32_t queueIndex, XGL_QUEUE* pQueue);
 typedef XGL_RESULT (XGLAPI *xglQueueSubmitType)(XGL_QUEUE queue, uint32_t cmdBufferCount, const XGL_CMD_BUFFER* pCmdBuffers, uint32_t memRefCount, const XGL_MEMORY_REF* pMemRefs, XGL_FENCE fence);
 typedef XGL_RESULT (XGLAPI *xglQueueSetGlobalMemReferencesType)(XGL_QUEUE queue, uint32_t memRefCount, const XGL_MEMORY_REF* pMemRefs);
+typedef XGL_RESULT (XGLAPI *xglQueueAddMemReferenceType)(XGL_QUEUE queue, XGL_GPU_MEMORY mem);
+typedef XGL_RESULT (XGLAPI *xglQueueRemoveMemReferenceType)(XGL_QUEUE queue, XGL_GPU_MEMORY mem);
 typedef XGL_RESULT (XGLAPI *xglQueueWaitIdleType)(XGL_QUEUE queue);
 typedef XGL_RESULT (XGLAPI *xglDeviceWaitIdleType)(XGL_DEVICE device);
 typedef XGL_RESULT (XGLAPI *xglAllocMemoryType)(XGL_DEVICE device, const XGL_MEMORY_ALLOC_INFO* pAllocInfo, XGL_GPU_MEMORY* pMem);
@@ -2447,6 +2449,14 @@
     uint32_t                                    memRefCount,
     const XGL_MEMORY_REF*                       pMemRefs);
 
+XGL_RESULT XGLAPI xglQueueAddMemReference(
+    XGL_QUEUE                                   queue,
+    XGL_GPU_MEMORY                              mem);
+
+XGL_RESULT XGLAPI xglQueueRemoveMemReference(
+    XGL_QUEUE                                   queue,
+    XGL_GPU_MEMORY                              mem);
+
 XGL_RESULT XGLAPI xglQueueWaitIdle(
     XGL_QUEUE                                   queue);
 
diff --git a/include/xglLayer.h b/include/xglLayer.h
index 6111bcb..e569aa9 100644
--- a/include/xglLayer.h
+++ b/include/xglLayer.h
@@ -39,6 +39,8 @@
     xglGetDeviceQueueType GetDeviceQueue;
     xglQueueSubmitType QueueSubmit;
     xglQueueSetGlobalMemReferencesType QueueSetGlobalMemReferences;
+    xglQueueAddMemReferenceType QueueAddMemReference;
+    xglQueueRemoveMemReferenceType QueueRemoveMemReference;
     xglQueueWaitIdleType QueueWaitIdle;
     xglDeviceWaitIdleType DeviceWaitIdle;
     xglAllocMemoryType AllocMemory;
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 6bd2b77..38a4ff1 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -97,6 +97,70 @@
     return pCBInfo;
 }
 
+// Add new Queue node for this cb at end of global CB LL
+static void insertGlobalQueue(const XGL_QUEUE queue)
+{
+#if 0 // TODO: Add tracking of Queue's
+    MT_QUEUE_NODE* pTrav = pGlobalQueueHead;
+    if (!pTrav) {
+        pTrav = (MT_QUEUE_NODE*)malloc(sizeof(MT_QUEUE_NODE));
+        pGlobalQueueHead = pTrav;
+    }
+    else {
+        while (NULL != pTrav->pNextGlobalQueueNode)
+            pTrav = pTrav->pNextGlobalQueueNode;
+        pTrav->pNextGlobalQueueNode = (MT_QUEUE_NODE*)malloc(sizeof(MT_QUEUE_NODE));
+        pTrav = pTrav->pNextGlobalQueueNode;
+    }
+    if (!pTrav) {
+        char str[1024];
+        sprintf(str, "Malloc failed to alloc node for Queue %p", (void*)queue);
+        layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_OUT_OF_MEMORY_ERROR, "MEM", str);
+    }
+    else {
+        numQueueNodes++;
+        memset(pTrav, 0, sizeof(MT_QUEUE_NODE));
+        pTrav->queue = queue;
+    }
+#endif
+}
+
+// Return ptr to node in global LL containing cb, or NULL if not found
+static MT_QUEUE_NODE* getGlobalQueueNode(const XGL_QUEUE queue)
+{
+#if 0
+    MT_QUEUE_NODE* pTrav = pGlobalQueueHead;
+    while (pTrav && (pTrav->queue != queue)) {
+        pTrav = pTrav->pNextGlobalQueueNode;
+    }
+    return pTrav;
+#endif
+}
+
+static void insertQueueMemRef(MT_QUEUE_NODE *pQueueNode, XGL_GPU_MEMORY mem)
+{
+#if 0
+    if (pQueueNode->numMemRefs >= pQueueNode->refListSize) {
+        pQueueNode->refListSize += 16;
+        pQueueNode->pMemRefList = realloc(pQueueNode->pMemRefList, pQueueNode->refListSize);
+    }
+    pQueueNode->pMemRefList[pQueueNode->numMemRefs++] = mem;
+#endif
+}
+
+static void removeQueueMemRef(MT_QUEUE_NODE *pQueueNode, XGL_GPU_MEMORY mem)
+{
+    uint32_t idx;
+
+    for (idx = 0; idx < pQueueNode->numMemRefs; idx++) {
+        if (pQueueNode->pMemRefList[idx] == mem) {
+            pQueueNode->numMemRefs--;
+            memcpy(&pQueueNode->pMemRefList[idx], pQueueNode->pMemRefList[idx+1],
+                    pQueueNode->numMemRefs * sizeof(XGL_GPU_MEMORY));
+        }
+    }
+}
+
 // Add a fence, creating one if necessary to our list of fences/fenceIds
 static uint64_t addFenceInfo(XGL_FENCE fence, XGL_QUEUE queue)
 {
@@ -859,13 +923,6 @@
     }
 }
 
-XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglGetDeviceQueue(XGL_DEVICE device, uint32_t queueNodeIndex, uint32_t queueIndex, XGL_QUEUE* pQueue)
-{
-    XGL_RESULT result = nextTable.GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
-    addQueueInfo(*pQueue);
-    return result;
-}
-
 XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueSubmit(XGL_QUEUE queue, uint32_t cmdBufferCount, const XGL_CMD_BUFFER* pCmdBuffers,
     uint32_t memRefCount, const XGL_MEMORY_REF* pMemRefs, XGL_FENCE fence)
 {
@@ -901,6 +958,76 @@
     return result;
 }
 
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglGetDeviceQueue(
+    XGL_DEVICE                                  device,
+    uint32_t                                    queueNodeIndex,
+    uint32_t                                    queueIndex,
+    XGL_QUEUE*                                  pQueue)
+{
+    XGL_RESULT result = nextTable.GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
+    if (result == XGL_SUCCESS) {
+        loader_platform_thread_lock_mutex(&globalLock);
+        MT_QUEUE_NODE *pQueueNode = getGlobalQueueNode(*pQueue);
+        if (pQueueNode == NULL) {
+            addQueueInfo(*pQueue);
+            insertGlobalQueue(*pQueue);
+        }
+        loader_platform_thread_unlock_mutex(&globalLock);
+    }
+    return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueAddMemReference(XGL_QUEUE queue, XGL_GPU_MEMORY mem)
+{
+    XGL_RESULT result = nextTable.QueueAddMemReference(queue, mem);
+    if (result == XGL_SUCCESS) {
+        loader_platform_thread_lock_mutex(&globalLock);
+        MT_QUEUE_NODE *pQueueNode = getGlobalQueueNode(queue);
+        if (pQueueNode == NULL) {
+            char str[1024];
+            sprintf(str, "Unknown Queue %p", queue);
+            layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_INVALID_QUEUE, "MEM", str);
+        } else {
+            MT_MEM_OBJ_INFO *pMem = getMemObjInfo(mem);
+            if (pMem == NULL) {
+                char str[1024];
+                sprintf(str, "Unknown GPU Memory Object %p", mem);
+                layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_MEM_OBJ, "MEM", str);
+            } else {
+                insertQueueMemRef(pQueueNode, mem);
+            }
+        }
+        loader_platform_thread_unlock_mutex(&globalLock);
+    }
+    return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglQueueRemoveMemReference(XGL_QUEUE queue, XGL_GPU_MEMORY mem)
+{
+    // TODO : Decrement ref count for this memory reference on this queue. Remove if ref count is zero.
+    XGL_RESULT result = nextTable.QueueRemoveMemReference(queue, mem);
+    if (result == XGL_SUCCESS) {
+        loader_platform_thread_lock_mutex(&globalLock);
+        MT_QUEUE_NODE *pQueueNode = getGlobalQueueNode(queue);
+        if (pQueueNode == NULL) {
+            char str[1024];
+            sprintf(str, "Unknown Queue %p", queue);
+            layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_INVALID_QUEUE, "MEM", str);
+        } else {
+            MT_MEM_OBJ_INFO *pMem = getMemObjInfo(mem);
+            if (pMem == NULL) {
+                char str[1024];
+                sprintf(str, "Unknown GPU Memory Object %p", mem);
+                layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_MEM_OBJ, "MEM", str);
+            } else {
+                removeQueueMemRef(pQueueNode, mem);
+            }
+        }
+        loader_platform_thread_unlock_mutex(&globalLock);
+    }
+    return result;
+}
+
 XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglAllocMemory(XGL_DEVICE device, const XGL_MEMORY_ALLOC_INFO* pAllocInfo, XGL_GPU_MEMORY* pMem)
 {
     XGL_RESULT result = nextTable.AllocMemory(device, pAllocInfo, pMem);
@@ -1797,6 +1924,12 @@
         return (void*) xglQueueSubmit;
     if (!strcmp(funcName, "xglQueueSetGlobalMemReferences"))
         return (void*) xglQueueSetGlobalMemReferences;
+    if (!strcmp(funcName, "xglGetDeviceQueue"))
+        return (void*) xglGetDeviceQueue;
+    if (!strcmp(funcName, "xglQueueAddMemReference"))
+        return (void*) xglQueueAddMemReference;
+    if (!strcmp(funcName, "xglQueueRemoveMemReference"))
+        return (void*) xglQueueRemoveMemReference;
     if (!strcmp(funcName, "xglAllocMemory"))
         return (void*) xglAllocMemory;
     if (!strcmp(funcName, "xglFreeMemory"))
@@ -1919,8 +2052,6 @@
         return (void*) xglDbgRegisterMsgCallback;
     if (!strcmp(funcName, "xglDbgUnregisterMsgCallback"))
         return (void*) xglDbgUnregisterMsgCallback;
-    if (!strcmp(funcName, "xglGetDeviceQueue"))
-        return (void*) xglGetDeviceQueue;
 #if !defined(WIN32)
     if (!strcmp(funcName, "xglWsiX11CreatePresentableImage"))
         return (void*) xglWsiX11CreatePresentableImage;
diff --git a/layers/mem_tracker.h b/layers/mem_tracker.h
index eb4deb4..7d23fac 100644
--- a/layers/mem_tracker.h
+++ b/layers/mem_tracker.h
@@ -48,6 +48,7 @@
     MEMTRACK_MEMORY_LEAK                   = 14, // Failure to call xglFreeMemory on Mem Obj prior to DestroyDevice
     MEMTRACK_INVALID_STATE                 = 15, // Memory not in the correct state
     MEMTRACK_RESET_CB_WHILE_IN_FLIGHT      = 16, // xglResetCommandBuffer() called on a CB that hasn't completed
+    MEMTRACK_INVALID_QUEUE                 = 17, // Unknown Queue object
 } MEM_TRACK_ERROR;
 
 /*
@@ -140,6 +141,14 @@
     list<XGL_CMD_BUFFER>          pQueueCmdBuffers;
 };
 
+struct MT_QUEUE_NODE {
+    struct _MT_QUEUE_NODE*      pNextGlobalQueueNode;
+    XGL_QUEUE                       queue;
+    uint32_t                        numMemRefs;
+    uint32_t                        refListSize;
+    XGL_GPU_MEMORY                 *pMemRefList;
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/xgl-layer-generate.py b/xgl-layer-generate.py
index afeb55b..881bd2c 100755
--- a/xgl-layer-generate.py
+++ b/xgl-layer-generate.py
@@ -1283,7 +1283,7 @@
         destroy_line = ''
         funcs = []
         # Special cases for API funcs that don't use an object as first arg
-        if True in [no_use_proto in proto.name for no_use_proto in ['GlobalOption', 'CreateInstance', 'QueueSubmit', 'QueueSetGlobalMemReferences', 'QueueWaitIdle', 'CreateDevice', 'GetGpuInfo', 'QueueSignalSemaphore', 'QueueWaitSemaphore', 'WsiX11QueuePresent']]:
+        if True in [no_use_proto in proto.name for no_use_proto in ['GlobalOption', 'CreateInstance', 'QueueSubmit', 'QueueSetGlobalMemReferences', 'QueueAddMemReference', 'QueueRemoveMemReference', 'QueueWaitIdle', 'CreateDevice', 'GetGpuInfo', 'QueueSignalSemaphore', 'QueueWaitSemaphore', 'WsiX11QueuePresent']]:
             using_line = ''
         else:
             using_line = '    loader_platform_thread_lock_mutex(&objLock);\n'
diff --git a/xgl.py b/xgl.py
index 02e386a..6cc463f 100644
--- a/xgl.py
+++ b/xgl.py
@@ -280,6 +280,14 @@
              Param("uint32_t", "memRefCount"),
              Param("const XGL_MEMORY_REF*", "pMemRefs")]),
 
+        Proto("XGL_RESULT", "QueueAddMemReference",
+            [Param("XGL_QUEUE", "queue"),
+             Param("XGL_GPU_MEMORY", "mem")]),
+
+        Proto("XGL_RESULT", "QueueRemoveMemReference",
+            [Param("XGL_QUEUE", "queue"),
+             Param("XGL_GPU_MEMORY", "mem")]),
+
         Proto("XGL_RESULT", "QueueWaitIdle",
             [Param("XGL_QUEUE", "queue")]),