vulkan: Updated vulkan.h for revision 79 -- Bug #13464

Implemented the changes required for adding fine-grained synchronization
to vkBindMemoryObject and related APIs.
diff --git a/demos/cube.c b/demos/cube.c
index dab663c..637cd31 100644
--- a/demos/cube.c
+++ b/demos/cube.c
@@ -641,7 +641,7 @@
         assert(!err);
 
         /* bind memory */
-        err = vkBindObjectMemory(demo->depth.image, i,
+        err = vkQueueBindObjectMemory(demo->queue, demo->depth.image, i,
                 demo->depth.mem[i], 0);
         assert(!err);
     }
@@ -874,7 +874,7 @@
         assert(!err);
 
         /* bind memory */
-        err = vkBindObjectMemory(tex_obj->image, j, tex_obj->mem[j], 0);
+        err = vkQueueBindObjectMemory(demo->queue, tex_obj->image, j, tex_obj->mem[j], 0);
         assert(!err);
     }
     free(mem_reqs);
@@ -917,11 +917,11 @@
     /* setting the image layout does not reference the actual memory so no need to add a mem ref */
 }
 
-static void demo_destroy_texture_image(struct texture_object *tex_objs)
+static void demo_destroy_texture_image(struct demo *demo, struct texture_object *tex_objs)
 {
     /* clean up staging resources */
     for (uint32_t j = 0; j < tex_objs->num_mem; j ++) {
-        vkBindObjectMemory(tex_objs->image, j, VK_NULL_HANDLE, 0);
+        vkQueueBindObjectMemory(demo->queue, tex_objs->image, j, VK_NULL_HANDLE, 0);
         vkFreeMemory(tex_objs->mem[j]);
     }
 
@@ -988,7 +988,7 @@
 
             demo_flush_init_cmd(demo);
 
-            demo_destroy_texture_image(&staging_texture);
+            demo_destroy_texture_image(demo, &staging_texture);
             demo_remove_mem_refs(demo, staging_texture.num_mem, staging_texture.mem);
         } else {
             /* Can't support VK_FMT_B8G8R8A8_UNORM !? */
@@ -1108,7 +1108,7 @@
         err = vkUnmapMemory(demo->uniform_data.mem[i]);
         assert(!err);
 
-        err = vkBindObjectMemory(demo->uniform_data.buf, i,
+        err = vkQueueBindObjectMemory(demo->queue, demo->uniform_data.buf, i,
                     demo->uniform_data.mem[i], 0);
         assert(!err);
     }
@@ -1752,8 +1752,12 @@
 	queue_count = (uint32_t)(data_size / sizeof(VkPhysicalGpuQueueProperties));
     assert(queue_count >= 1);
 
+    // Graphics queue and MemMgr queue can be separate.
+    // TODO: Add support for separate queues, including synchronization,
+    //       and appropriate tracking for QueueSubmit and QueueBindObjectMemory
     for (i = 0; i < queue_count; i++) {
-        if (demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+        if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) &&
+            (demo->queue_props[i].queueFlags & VK_QUEUE_MEMMGR_BIT)      )
             break;
     }
     assert(i < queue_count);
@@ -1833,7 +1837,7 @@
 
     for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
         vkDestroyObject(demo->textures[i].view);
-        vkBindObjectMemory(demo->textures[i].image, 0, VK_NULL_HANDLE, 0);
+        vkQueueBindObjectMemory(demo->queue, demo->textures[i].image, 0, VK_NULL_HANDLE, 0);
         vkDestroyObject(demo->textures[i].image);
         demo_remove_mem_refs(demo, demo->textures[i].num_mem, demo->textures[i].mem);
         for (j = 0; j < demo->textures[i].num_mem; j++)
@@ -1842,7 +1846,7 @@
     }
 
     vkDestroyObject(demo->depth.view);
-    vkBindObjectMemory(demo->depth.image, 0, VK_NULL_HANDLE, 0);
+    vkQueueBindObjectMemory(demo->queue, demo->depth.image, 0, VK_NULL_HANDLE, 0);
     vkDestroyObject(demo->depth.image);
     demo_remove_mem_refs(demo, demo->depth.num_mem, demo->depth.mem);
     for (j = 0; j < demo->depth.num_mem; j++) {
@@ -1850,7 +1854,7 @@
     }
 
     vkDestroyObject(demo->uniform_data.view);
-    vkBindObjectMemory(demo->uniform_data.buf, 0, VK_NULL_HANDLE, 0);
+    vkQueueBindObjectMemory(demo->queue, demo->uniform_data.buf, 0, VK_NULL_HANDLE, 0);
     vkDestroyObject(demo->uniform_data.buf);
     demo_remove_mem_refs(demo, demo->uniform_data.num_mem, demo->uniform_data.mem);
     for (j = 0; j < demo->uniform_data.num_mem; j++)
diff --git a/demos/tri.c b/demos/tri.c
index 8d21209..f1156d2 100644
--- a/demos/tri.c
+++ b/demos/tri.c
@@ -450,7 +450,7 @@
         assert(!err);
 
         /* bind memory */
-        err = vkBindObjectMemory(demo->depth.image, i,
+        err = vkQueueBindObjectMemory(demo->queue, demo->depth.image, i,
                 demo->depth.mem[i], 0);
         assert(!err);
     }
@@ -532,7 +532,7 @@
         assert(!err);
 
         /* bind memory */
-        err = vkBindObjectMemory(tex_obj->image, j, tex_obj->mem[j], 0);
+        err = vkQueueBindObjectMemory(demo->queue, tex_obj->image, j, tex_obj->mem[j], 0);
         assert(!err);
     }
     free(mem_reqs);
@@ -578,11 +578,11 @@
     /* setting the image layout does not reference the actual memory so no need to add a mem ref */
 }
 
-static void demo_destroy_texture_image(struct texture_object *tex_obj)
+static void demo_destroy_texture_image(struct demo *demo, struct texture_object *tex_obj)
 {
     /* clean up staging resources */
     for (uint32_t j = 0; j < tex_obj->num_mem; j ++) {
-        vkBindObjectMemory(tex_obj->image, j, VK_NULL_HANDLE, 0);
+        vkQueueBindObjectMemory(demo->queue, tex_obj->image, j, VK_NULL_HANDLE, 0);
         vkFreeMemory(tex_obj->mem[j]);
     }
 
@@ -651,7 +651,7 @@
 
             demo_flush_init_cmd(demo);
 
-            demo_destroy_texture_image(&staging_texture);
+            demo_destroy_texture_image(demo, &staging_texture);
             demo_remove_mem_refs(demo, staging_texture.num_mem, staging_texture.mem);
         } else {
             /* Can't support VK_FMT_B8G8R8A8_UNORM !? */
@@ -760,7 +760,7 @@
         err = vkUnmapMemory(demo->vertices.mem[i]);
         assert(!err);
 
-        err = vkBindObjectMemory(demo->vertices.buf, i, demo->vertices.mem[i], 0);
+        err = vkQueueBindObjectMemory(demo->queue, demo->vertices.buf, i, demo->vertices.mem[i], 0);
         assert(!err);
     }
 
@@ -1296,6 +1296,8 @@
     for (i = 0; i < queue_count; i++) {
         if (demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
             break;
+        if (demo->queue_props[i].queueFlags & VK_QUEUE_MEMMGR_BIT)
+            break;
     }
     assert(i < queue_count);
     demo->graphics_queue_node_index = i;
@@ -1362,7 +1364,7 @@
     vkDestroyObject(demo->desc_layout_chain);
     vkDestroyObject(demo->desc_layout);
 
-    vkBindObjectMemory(demo->vertices.buf, 0, VK_NULL_HANDLE, 0);
+    vkQueueBindObjectMemory(demo->queue, demo->vertices.buf, 0, VK_NULL_HANDLE, 0);
     vkDestroyObject(demo->vertices.buf);
     demo_remove_mem_refs(demo, demo->vertices.num_mem, demo->vertices.mem);
     for (j = 0; j < demo->vertices.num_mem; j++)
@@ -1370,7 +1372,7 @@
 
     for (i = 0; i < DEMO_TEXTURE_COUNT; i++) {
         vkDestroyObject(demo->textures[i].view);
-        vkBindObjectMemory(demo->textures[i].image, 0, VK_NULL_HANDLE, 0);
+        vkQueueBindObjectMemory(demo->queue, demo->textures[i].image, 0, VK_NULL_HANDLE, 0);
         vkDestroyObject(demo->textures[i].image);
         demo_remove_mem_refs(demo, demo->textures[i].num_mem, demo->textures[i].mem);
         for (j = 0; j < demo->textures[i].num_mem; j++)
@@ -1380,7 +1382,7 @@
     }
 
     vkDestroyObject(demo->depth.view);
-    vkBindObjectMemory(demo->depth.image, 0, VK_NULL_HANDLE, 0);
+    vkQueueBindObjectMemory(demo->queue, demo->depth.image, 0, VK_NULL_HANDLE, 0);
     demo_remove_mem_refs(demo, demo->depth.num_mem, demo->depth.mem);
     vkDestroyObject(demo->depth.image);
     for (j = 0; j < demo->depth.num_mem; j++)
diff --git a/icd/intel/gpu.c b/icd/intel/gpu.c
index 2f297e0..03fbe5b 100644
--- a/icd/intel/gpu.c
+++ b/icd/intel/gpu.c
@@ -271,7 +271,7 @@
 {
     switch (engine) {
     case INTEL_GPU_ENGINE_3D:
-        props->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
+        props->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_MEMMGR_BIT;
         props->queueCount = 1;
         props->maxAtomicCounters = INTEL_QUEUE_ATOMIC_COUNTER_COUNT;
         props->supportsTimestamps = true;
diff --git a/icd/intel/obj.c b/icd/intel/obj.c
index d6cf6e4..62c45c9 100644
--- a/icd/intel/obj.c
+++ b/icd/intel/obj.c
@@ -364,9 +364,10 @@
     return base->get_info(base, infoType, pDataSize, pData);
 }
 
-ICD_EXPORT VkResult VKAPI vkBindObjectMemory(
-    VkObject                                  object,
-    uint32_t                                    allocationIdx,
+ICD_EXPORT VkResult VKAPI vkQueueBindObjectMemory(
+    VkQueue                                  queue,
+    VkObject                                 object,
+    uint32_t                                 allocationIdx,
     VkGpuMemory                              mem_,
     VkGpuSize                                memOffset)
 {
@@ -378,7 +379,8 @@
     return VK_SUCCESS;
 }
 
-ICD_EXPORT VkResult VKAPI vkBindObjectMemoryRange(
+ICD_EXPORT VkResult VKAPI vkQueueBindObjectMemoryRange(
+    VkQueue                                   queue,
     VkObject                                  object,
     uint32_t                                    allocationIdx,
     VkGpuSize                                rangeOffset,
@@ -389,7 +391,8 @@
     return VK_ERROR_UNKNOWN;
 }
 
-ICD_EXPORT VkResult VKAPI vkBindImageMemoryRange(
+ICD_EXPORT VkResult VKAPI vkQueueBindImageMemoryRange(
+    VkQueue                                   queue,
     VkImage                                   image,
     uint32_t                                    allocationIdx,
     const VkImageMemoryBindInfo*           bindInfo,
diff --git a/icd/nulldrv/nulldrv.c b/icd/nulldrv/nulldrv.c
index e80ec02..38102c1 100644
--- a/icd/nulldrv/nulldrv.c
+++ b/icd/nulldrv/nulldrv.c
@@ -1579,7 +1579,8 @@
     return base->get_info(base, infoType, pDataSize, pData);
 }
 
-ICD_EXPORT VkResult VKAPI vkBindObjectMemory(
+ICD_EXPORT VkResult VKAPI vkQueueBindObjectMemory(
+    VkQueue                                   queue,
     VkObject                                  object,
     uint32_t                                    allocationIdx,
     VkGpuMemory                              mem_,
@@ -1589,7 +1590,8 @@
     return VK_SUCCESS;
 }
 
-ICD_EXPORT VkResult VKAPI vkBindObjectMemoryRange(
+ICD_EXPORT VkResult VKAPI vkQueueBindObjectMemoryRange(
+    VkQueue                                   queue,
     VkObject                                  object,
     uint32_t                                    allocationIdx,
     VkGpuSize                                rangeOffset,
@@ -1601,7 +1603,8 @@
     return VK_SUCCESS;
 }
 
-ICD_EXPORT VkResult VKAPI vkBindImageMemoryRange(
+ICD_EXPORT VkResult VKAPI vkQueueBindImageMemoryRange(
+    VkQueue                                   queue,
     VkImage                                   image,
     uint32_t                                    allocationIdx,
     const VkImageMemoryBindInfo*           bindInfo,
diff --git a/include/vkLayer.h b/include/vkLayer.h
index e58ccdc..c15237e 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -56,9 +56,9 @@
     PFN_vkOpenPeerImage OpenPeerImage;
     PFN_vkDestroyObject DestroyObject;
     PFN_vkGetObjectInfo GetObjectInfo;
-    PFN_vkBindObjectMemory BindObjectMemory;
-    PFN_vkBindObjectMemoryRange BindObjectMemoryRange;
-    PFN_vkBindImageMemoryRange BindImageMemoryRange;
+    PFN_vkQueueBindObjectMemory QueueBindObjectMemory;
+    PFN_vkQueueBindObjectMemoryRange QueueBindObjectMemoryRange;
+    PFN_vkQueueBindImageMemoryRange QueueBindImageMemoryRange;
     PFN_vkCreateFence CreateFence;
     PFN_vkGetFenceStatus GetFenceStatus;
     PFN_vkResetFences ResetFences;
diff --git a/include/vulkan.h b/include/vulkan.h
index 8d0d5d5..2c53857 100644
--- a/include/vulkan.h
+++ b/include/vulkan.h
@@ -1075,6 +1075,7 @@
     VK_QUEUE_GRAPHICS_BIT                                   = 0x00000001,   // Queue supports graphics operations
     VK_QUEUE_COMPUTE_BIT                                    = 0x00000002,   // Queue supports compute operations
     VK_QUEUE_DMA_BIT                                        = 0x00000004,   // Queue supports DMA operations
+    VK_QUEUE_MEMMGR_BIT                                     = 0x00000008,   // Queue supports memory management operations
     VK_QUEUE_EXTENDED_BIT                                   = 0x40000000,   // Extended queue
     VK_MAX_ENUM(VkQueueFlags)
 } VkQueueFlags;
@@ -1427,7 +1428,7 @@
 {
     VkGpuSize                                   size;                       // Specified in bytes
     VkGpuSize                                   alignment;                  // Specified in bytes
-    VkGpuSize                                   granularity;                // Granularity on which vkBindObjectMemoryRange can bind sub-ranges of memory specified in bytes (usually the page size)
+    VkGpuSize                                   granularity;                // Granularity on which vkQueueBindObjectMemoryRange can bind sub-ranges of memory specified in bytes (usually the page size)
     VkFlags                                     memProps;                   // VkMemoryPropertyFlags
 } VkMemoryRequirements;
 
@@ -2213,9 +2214,9 @@
 typedef VkResult (VKAPI *PFN_vkOpenPeerImage)(VkDevice device, const VkPeerImageOpenInfo* pOpenInfo, VkImage* pImage, VkGpuMemory* pMem);
 typedef VkResult (VKAPI *PFN_vkDestroyObject)(VkObject object);
 typedef VkResult (VKAPI *PFN_vkGetObjectInfo)(VkBaseObject object, VkObjectInfoType infoType, size_t* pDataSize, void* pData);
-typedef VkResult (VKAPI *PFN_vkBindObjectMemory)(VkObject object, uint32_t allocationIdx, VkGpuMemory mem, VkGpuSize offset);
-typedef VkResult (VKAPI *PFN_vkBindObjectMemoryRange)(VkObject object, uint32_t allocationIdx, VkGpuSize rangeOffset,VkGpuSize rangeSize, VkGpuMemory mem, VkGpuSize memOffset);
-typedef VkResult (VKAPI *PFN_vkBindImageMemoryRange)(VkImage image, uint32_t allocationIdx, const VkImageMemoryBindInfo* bindInfo, VkGpuMemory mem, VkGpuSize memOffset);
+typedef VkResult (VKAPI *PFN_vkQueueBindObjectMemory)(VkQueue queue, VkObject object, uint32_t allocationIdx, VkGpuMemory mem, VkGpuSize offset);
+typedef VkResult (VKAPI *PFN_vkQueueBindObjectMemoryRange)(VkQueue queue, VkObject object, uint32_t allocationIdx, VkGpuSize rangeOffset,VkGpuSize rangeSize, VkGpuMemory mem, VkGpuSize memOffset);
+typedef VkResult (VKAPI *PFN_vkQueueBindImageMemoryRange)(VkQueue queue, VkImage image, uint32_t allocationIdx, const VkImageMemoryBindInfo* bindInfo, VkGpuMemory mem, VkGpuSize memOffset);
 typedef VkResult (VKAPI *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, VkFence* pFence);
 typedef VkResult (VKAPI *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, VkFence* pFences);
 typedef VkResult (VKAPI *PFN_vkGetFenceStatus)(VkFence fence);
@@ -2453,13 +2454,17 @@
     size_t*                                     pDataSize,
     void*                                       pData);
 
-VkResult VKAPI vkBindObjectMemory(
+// Memory namagement API functions
+
+VkResult VKAPI vkQueueBindObjectMemory(
+    VkQueue                                     queue,
     VkObject                                    object,
     uint32_t                                    allocationIdx,
     VkGpuMemory                                 mem,
     VkGpuSize                                   memOffset);
 
-VkResult VKAPI vkBindObjectMemoryRange(
+VkResult VKAPI vkQueueBindObjectMemoryRange(
+    VkQueue                                     queue,
     VkObject                                    object,
     uint32_t                                    allocationIdx,
     VkGpuSize                                   rangeOffset,
@@ -2467,7 +2472,8 @@
     VkGpuMemory                                 mem,
     VkGpuSize                                   memOffset);
 
-VkResult VKAPI vkBindImageMemoryRange(
+VkResult VKAPI vkQueueBindImageMemoryRange(
+    VkQueue                                     queue,
     VkImage                                     image,
     uint32_t                                    allocationIdx,
     const VkImageMemoryBindInfo*                bindInfo,
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index c5f83d2..d67887e 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -490,36 +490,50 @@
 }
 
 // For given MemObjInfo, report Obj & CB bindings
-static void reportMemReferences(const MT_MEM_OBJ_INFO* pMemObjInfo)
+static void reportMemReferencesAndCleanUp(MT_MEM_OBJ_INFO* pMemObjInfo)
 {
-    uint32_t refCount = 0; // Count found references
+    uint32_t cmdBufRefCount = pMemObjInfo->pCmdBufferBindings.size();
+    uint32_t objRefCount    = pMemObjInfo->pObjBindings.size();
 
-    for (list<VkCmdBuffer>::const_iterator it = pMemObjInfo->pCmdBufferBindings.begin(); it != pMemObjInfo->pCmdBufferBindings.end(); ++it) {
-        refCount++;
+    if ((pMemObjInfo->pCmdBufferBindings.size() + pMemObjInfo->pObjBindings.size()) != 0) {
         char str[1024];
-        sprintf(str, "Command Buffer %p has reference to mem obj %p", (*it), pMemObjInfo->mem);
-        layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, (*it), 0, MEMTRACK_NONE, "MEM", str);
-    }
-    for (list<VkObject>::const_iterator it = pMemObjInfo->pObjBindings.begin(); it != pMemObjInfo->pObjBindings.end(); ++it) {
-        char str[1024];
-        sprintf(str, "VK Object %p has reference to mem obj %p", (*it), pMemObjInfo->mem);
-        layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, (*it), 0, MEMTRACK_NONE, "MEM", str);
-    }
-    if (refCount != pMemObjInfo->refCount) {
-        char str[1024];
-        sprintf(str, "Refcount of %u for Mem Obj %p does't match reported refs of %u", pMemObjInfo->refCount, pMemObjInfo->mem, refCount);
+        sprintf(str, "Attempting to free memory object %p which still contains %d references", pMemObjInfo->mem, (cmdBufRefCount + objRefCount));
         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, pMemObjInfo->mem, 0, MEMTRACK_INTERNAL_ERROR, "MEM", str);
     }
+
+    if (cmdBufRefCount > 0) {
+        for (list<VkCmdBuffer>::const_iterator it = pMemObjInfo->pCmdBufferBindings.begin(); it != pMemObjInfo->pCmdBufferBindings.end(); ++it) {
+            char str[1024];
+            sprintf(str, "Command Buffer %p still has a reference to mem obj %p", (*it), pMemObjInfo->mem);
+            layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, (*it), 0, MEMTRACK_NONE, "MEM", str);
+        }
+        // Clear the list of hanging references
+        pMemObjInfo->pCmdBufferBindings.clear();
+    }
+
+    if (objRefCount > 0) {
+        for (list<VkObject>::const_iterator it = pMemObjInfo->pObjBindings.begin(); it != pMemObjInfo->pObjBindings.end(); ++it) {
+            char str[1024];
+            sprintf(str, "VK Object %p still has a reference to mem obj %p", (*it), pMemObjInfo->mem);
+            layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, (*it), 0, MEMTRACK_NONE, "MEM", str);
+        }
+        // Clear the list of hanging references
+        pMemObjInfo->pObjBindings.clear();
+    }
 }
 
 static void deleteMemObjInfo(VkGpuMemory mem)
 {
-    MT_MEM_OBJ_INFO* pDelInfo = memObjMap[mem];
     if (memObjMap.find(mem) != memObjMap.end()) {
         MT_MEM_OBJ_INFO* pDelInfo = memObjMap[mem];
         delete pDelInfo;
         memObjMap.erase(mem);
     }
+    else {
+        char str[1024];
+        sprintf(str, "Request to delete memory object %p not present in memory Object Map", mem);
+        layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_MEM_OBJ, "MEM", str);
+    }
 }
 
 // Check if fence for given CB is completed
@@ -582,7 +596,7 @@
                 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);
-                reportMemReferences(pInfo);
+                reportMemReferencesAndCleanUp(pInfo);
                 result = VK_FALSE;
             }
             // Delete mem obj info
@@ -610,12 +624,16 @@
             sprintf(str, "Attempting to clear mem binding on obj %p but it has no binding.", (void*)object);
             layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, object, 0, MEMTRACK_MEM_OBJ_CLEAR_EMPTY_BINDINGS, "MEM", str);
         } else {
+            // This obj is bound to a memory object. Remove the reference to this object in that memory object's list, decrement the memObj's refcount
+            // and set the objects memory binding pointer to NULL.
             for (list<VkObject>::iterator it = pObjInfo->pMemObjInfo->pObjBindings.begin(); it != pObjInfo->pMemObjInfo->pObjBindings.end(); ++it) {
-                pObjInfo->pMemObjInfo->refCount--;
-                pObjInfo->pMemObjInfo = NULL;
-                it = pObjInfo->pMemObjInfo->pObjBindings.erase(it);
-                result = VK_TRUE;
-                break;
+                if ((*it) == object) {
+                    pObjInfo->pMemObjInfo->refCount--;
+                    pObjInfo->pMemObjInfo->pObjBindings.erase(it);
+                    pObjInfo->pMemObjInfo = NULL;
+                    result = VK_TRUE;
+                    break;
+                }
             }
             if (result == VK_FALSE) {
                 char str[1024];
@@ -1168,7 +1186,7 @@
             }
             else {
                 char str[1024];
-                sprintf(str, "Destroying obj %p that is still bound to memory object %p\nYou should first clear binding by calling vkBindObjectMemory(%p, 0, VK_NULL_HANDLE, 0)", object, (void*)pDelInfo->pMemObjInfo->mem, object);
+                sprintf(str, "Destroying obj %p that is still bound to memory object %p\nYou should first clear binding by calling vkQueueBindObjectMemory(queue, %p, 0, VK_NULL_HANDLE, 0)", object, (void*)pDelInfo->pMemObjInfo->mem, object);
                 layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, object, 0, MEMTRACK_DESTROY_OBJECT_ERROR, "MEM", str);
                 // From the spec : If an object has previous memory binding, it is required to unbind memory from an API object before it is destroyed.
                 clearObjectBinding(object);
@@ -1186,15 +1204,15 @@
 VK_LAYER_EXPORT VkResult VKAPI vkGetObjectInfo(VkBaseObject object, VkObjectInfoType infoType, size_t* pDataSize, void* pData)
 {
     // TODO : What to track here?
-    //   Could potentially save returned mem requirements and validate values passed into BindObjectMemory for this object
+    //   Could potentially save returned mem requirements and validate values passed into QueueBindObjectMemory for this object
     // From spec : The only objects that are guaranteed to have no external memory requirements are devices, queues, command buffers, shaders and memory objects.
     VkResult result = nextTable.GetObjectInfo(object, infoType, pDataSize, pData);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkBindObjectMemory(VkObject object, uint32_t allocationIdx, VkGpuMemory mem, VkGpuSize offset)
+VK_LAYER_EXPORT VkResult VKAPI vkQueueBindObjectMemory(VkQueue queue, VkObject object, uint32_t allocationIdx, VkGpuMemory mem, VkGpuSize offset)
 {
-    VkResult result = nextTable.BindObjectMemory(object, allocationIdx, mem, offset);
+    VkResult result = nextTable.QueueBindObjectMemory(queue, object, allocationIdx, mem, offset);
     loader_platform_thread_lock_mutex(&globalLock);
     // Track objects tied to memory
     if (VK_FALSE == updateObjectBinding(object, mem)) {
@@ -2013,8 +2031,8 @@
         return (void*) vkDestroyObject;
     if (!strcmp(funcName, "vkGetObjectInfo"))
         return (void*) vkGetObjectInfo;
-    if (!strcmp(funcName, "vkBindObjectMemory"))
-        return (void*) vkBindObjectMemory;
+    if (!strcmp(funcName, "vkQueueBindObjectMemory"))
+        return (void*) vkQueueBindObjectMemory;
     if (!strcmp(funcName, "vkCreateFence"))
         return (void*) vkCreateFence;
     if (!strcmp(funcName, "vkGetFenceStatus"))
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index 2fe5ee5..008aa7b 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -514,32 +514,32 @@
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkBindObjectMemory(VkObject object, uint32_t allocationIdx, VkGpuMemory mem, VkGpuSize offset)
+VK_LAYER_EXPORT VkResult VKAPI vkQueueBindObjectMemory(VkQueue queue, VkObject object, uint32_t allocationIdx, VkGpuMemory mem, VkGpuSize offset)
 {
 
-    VkResult result = nextTable.BindObjectMemory(object, allocationIdx, mem, offset);
+    VkResult result = nextTable.QueueBindObjectMemory(queue, object, allocationIdx, mem, offset);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkBindObjectMemoryRange(VkObject object, uint32_t allocationIdx, VkGpuSize rangeOffset, VkGpuSize rangeSize, VkGpuMemory mem, VkGpuSize memOffset)
+VK_LAYER_EXPORT VkResult VKAPI vkQueueBindObjectMemoryRange(VkQueue queue, VkObject object, uint32_t allocationIdx, VkGpuSize rangeOffset, VkGpuSize rangeSize, VkGpuMemory mem, VkGpuSize memOffset)
 {
 
-    VkResult result = nextTable.BindObjectMemoryRange(object, allocationIdx, rangeOffset, rangeSize, mem, memOffset);
+    VkResult result = nextTable.QueueBindObjectMemoryRange(queue, object, allocationIdx, rangeOffset, rangeSize, mem, memOffset);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkBindImageMemoryRange(VkImage image, uint32_t allocationIdx, const VkImageMemoryBindInfo* bindInfo, VkGpuMemory mem, VkGpuSize memOffset)
+VK_LAYER_EXPORT VkResult VKAPI vkQueueBindImageMemoryRange(VkQueue queue, VkImage image, uint32_t allocationIdx, const VkImageMemoryBindInfo* bindInfo, VkGpuMemory mem, VkGpuSize memOffset)
 {
     char str[1024];
     if (!bindInfo) {
-        sprintf(str, "Struct ptr parameter bindInfo to function BindImageMemoryRange is NULL.");
+        sprintf(str, "Struct ptr parameter bindInfo to function QueueBindImageMemoryRange is NULL.");
         layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);
     }
     else if (!vk_validate_vkimagememorybindinfo(bindInfo)) {
         sprintf(str, "Parameter bindInfo to function BindImageMemoryRange contains an invalid value.");
         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, 1, "PARAMCHECK", str);
     }
-    VkResult result = nextTable.BindImageMemoryRange(image, allocationIdx, bindInfo, mem, memOffset);
+    VkResult result = nextTable.QueueBindImageMemoryRange(queue, image, allocationIdx, bindInfo, mem, memOffset);
     return result;
 }
 
diff --git a/tests/blit_tests.cpp b/tests/blit_tests.cpp
index 1118dc9..756e1b3 100644
--- a/tests/blit_tests.cpp
+++ b/tests/blit_tests.cpp
@@ -793,7 +793,7 @@
     err = vkAllocMemory(dev_.obj(), &mem_info, &event_mem);
     ASSERT_VK_SUCCESS(err);
 
-    err = vkBindObjectMemory(event, 0, event_mem, 0);
+    err = vkQueueBindObjectMemory(queue_.obj(), event, 0, event_mem, 0);
     ASSERT_VK_SUCCESS(err);
 
     err = vkResetEvent(event);
@@ -871,7 +871,7 @@
     bufs[2].unmap();
 
     // All done with event memory, clean up
-    err = vkBindObjectMemory(event, 0, VK_NULL_HANDLE, 0);
+    err = vkQueueBindObjectMemory(queue_.obj(), event, 0, VK_NULL_HANDLE, 0);
     ASSERT_VK_SUCCESS(err);
 
     err = vkDestroyObject(event);
diff --git a/tests/image_tests.cpp b/tests/image_tests.cpp
index be0c81a..d2b2e69 100644
--- a/tests/image_tests.cpp
+++ b/tests/image_tests.cpp
@@ -243,7 +243,8 @@
         ASSERT_VK_SUCCESS(err);
 
         /* bind memory */
-        err = vkBindObjectMemory(m_image, i, m_image_mem[i], 0);
+        VkQueue queue = m_device->graphics_queues()[0]->obj();
+        err = vkQueueBindObjectMemory(queue, m_image, i, m_image_mem[i], 0);
         ASSERT_VK_SUCCESS(err);
     }
 }
@@ -252,7 +253,8 @@
 {
     VkResult err;
     // All done with image memory, clean up
-    ASSERT_VK_SUCCESS(vkBindObjectMemory(m_image, 0, VK_NULL_HANDLE, 0));
+    VkQueue queue = m_device->graphics_queues()[0]->obj();
+    ASSERT_VK_SUCCESS(vkQueueBindObjectMemory(queue, m_image, 0, VK_NULL_HANDLE, 0));
 
     for (uint32_t i = 0 ; i < m_num_mem; i++) {
         err = vkFreeMemory(m_image_mem[i]);
diff --git a/tests/init.cpp b/tests/init.cpp
index 5599446..554b9c8 100644
--- a/tests/init.cpp
+++ b/tests/init.cpp
@@ -253,7 +253,8 @@
     err = vkAllocMemory(device(), &mem_info, &event_mem);
     ASSERT_VK_SUCCESS(err);
 
-    err = vkBindObjectMemory(event, 0, event_mem, 0);
+    VkQueue queue = m_device->graphics_queues()[0]->obj();
+    err = vkQueueBindObjectMemory(queue, event, 0, event_mem, 0);
     ASSERT_VK_SUCCESS(err);
 
     err = vkResetEvent(event);
@@ -271,7 +272,7 @@
     // TODO: Test actual synchronization with command buffer event.
 
     // All done with event memory, clean up
-    err = vkBindObjectMemory(event, 0, VK_NULL_HANDLE, 0);
+    err = vkQueueBindObjectMemory(queue, event, 0, VK_NULL_HANDLE, 0);
     ASSERT_VK_SUCCESS(err);
 
     err = vkDestroyObject(event);
@@ -384,7 +385,8 @@
     err = vkAllocMemory(device(), &mem_info, &query_mem);
     ASSERT_VK_SUCCESS(err);
 
-    err = vkBindObjectMemory(query_pool, 0, query_mem, 0);
+    VkQueue queue = m_device->graphics_queues()[0]->obj();
+    err = vkQueueBindObjectMemory(queue, query_pool, 0, query_mem, 0);
     ASSERT_VK_SUCCESS(err);
 
     // TODO: Test actual synchronization with command buffer event.
@@ -409,7 +411,7 @@
     }
 
     // All done with QueryPool memory, clean up
-    err = vkBindObjectMemory(query_pool, 0, VK_NULL_HANDLE, 0);
+    err = vkQueueBindObjectMemory(queue, query_pool, 0, VK_NULL_HANDLE, 0);
     ASSERT_VK_SUCCESS(err);
 
     err = vkDestroyObject(query_pool);
@@ -424,6 +426,7 @@
 
     const VkPhysicalGpuQueueProperties props = device->gpu().queue_properties()[queue_node_index];
     for (que_idx = 0; que_idx < props.queueCount; que_idx++) {
+        // TODO: Need to add support for separate MEMMGR and work queues, including synchronization
         err = vkGetDeviceQueue(device->obj(), queue_node_index, que_idx, &queue);
         ASSERT_EQ(VK_SUCCESS, err) << "vkGetDeviceQueue: " << qname << " queue #" << que_idx << ": Failed with error: " << vk_result_string(err);
     }
@@ -463,6 +466,7 @@
 //                    VK_QUEUE_GRAPHICS_BIT                                  = 0x00000001,   // Queue supports graphics operations
 //                    VK_QUEUE_COMPUTE_BIT                                   = 0x00000002,   // Queue supports compute operations
 //                    VK_QUEUE_DMA_BIT                                       = 0x00000004,   // Queue supports DMA operations
+//                    VK_QUEUE_MEMMGR_BIT                                    = 0x00000008,   // Queue supports MEMMGR operations
 //                    VK_QUEUE_EXTENDED_BIT                                  = 0x80000000    // Extended queue
 //                } VkQueueFlags;
 
@@ -649,7 +653,8 @@
     err = vkAllocMemory(device(), &mem_info, &image_mem);
     ASSERT_VK_SUCCESS(err);
 
-    err = vkBindObjectMemory(image, 0, image_mem, 0);
+    VkQueue queue = m_device->graphics_queues()[0]->obj();
+    err = vkQueueBindObjectMemory(queue, image, 0, image_mem, 0);
     ASSERT_VK_SUCCESS(err);
 
 //    typedef struct VkImageViewCreateInfo_
@@ -692,7 +697,7 @@
     // TODO: Test image memory.
 
     // All done with image memory, clean up
-    ASSERT_VK_SUCCESS(vkBindObjectMemory(image, 0, VK_NULL_HANDLE, 0));
+    ASSERT_VK_SUCCESS(vkQueueBindObjectMemory(queue, image, 0, VK_NULL_HANDLE, 0));
 
     ASSERT_VK_SUCCESS(vkFreeMemory(image_mem));
 
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index d3060de..7e5aa68 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -93,7 +93,7 @@
     }
     while (!m_renderTargets.empty()) {
         vkDestroyObject(m_renderTargets.back()->targetView());
-        vkBindObjectMemory(m_renderTargets.back()->image(), 0, VK_NULL_HANDLE, 0);
+        vkQueueBindObjectMemory(m_device->m_queue, m_renderTargets.back()->image(), 0, VK_NULL_HANDLE, 0);
         vkDestroyObject(m_renderTargets.back()->image());
         vkFreeMemory(m_renderTargets.back()->memory());
         m_renderTargets.pop_back();
@@ -369,7 +369,7 @@
     m_layout_chain.init(*m_device, layouts);
 
     // create VkDescriptorSet
-    m_set = alloc_sets(VK_DESCRIPTOR_SET_USAGE_STATIC, m_layout);
+    m_set = alloc_sets(*m_device, VK_DESCRIPTOR_SET_USAGE_STATIC, m_layout);
 
     // build the update array
     vector<const void *> update_array;
diff --git a/tests/vktestbinding.cpp b/tests/vktestbinding.cpp
index fa4d4fb..eedeef7 100644
--- a/tests/vktestbinding.cpp
+++ b/tests/vktestbinding.cpp
@@ -25,16 +25,18 @@
 #include "vktestbinding.h"
 
 namespace {
-
 #define DERIVED_OBJECT_INIT(create_func, ...)                       \
     do {                                                            \
         obj_type obj;                                               \
-        if (EXPECT(create_func(__VA_ARGS__, &obj) == VK_SUCCESS))  \
+        if (EXPECT(create_func(__VA_ARGS__, &obj) == VK_SUCCESS))   \
             base_type::init(obj);                                   \
     } while (0)
 
 #define STRINGIFY(x) #x
 #define EXPECT(expr) ((expr) ? true : expect_failure(STRINGIFY(expr), __FILE__, __LINE__, __FUNCTION__))
+#define DEV_INIT(device) dev_ = &device;
+
+
 
 vk_testing::ErrorCallback error_callback;
 
@@ -222,7 +224,7 @@
         return;
 
     if(bound) {
-        unbind_memory();
+       unbind_memory(*dev_);
     }
 
     if (internal_mems_) {
@@ -237,28 +239,31 @@
         EXPECT(vkDestroyObject(obj()) == VK_SUCCESS);
 }
 
-void Object::bind_memory(uint32_t alloc_idx, const GpuMemory &mem, VkGpuSize mem_offset)
+void Object::bind_memory(const Device &dev, uint32_t alloc_idx, const GpuMemory &mem, VkGpuSize mem_offset)
 {
     bound = true;
-    EXPECT(vkBindObjectMemory(obj(), alloc_idx, mem.obj(), mem_offset) == VK_SUCCESS);
+    VkQueue queue = dev.graphics_queues()[0]->obj();
+    EXPECT(vkQueueBindObjectMemory(queue, obj(), alloc_idx, mem.obj(), mem_offset) == VK_SUCCESS);
 }
 
-void Object::bind_memory(uint32_t alloc_idx, VkGpuSize offset, VkGpuSize size,
+void Object::bind_memory(const Device &dev, uint32_t alloc_idx, VkGpuSize offset, VkGpuSize size,
                          const GpuMemory &mem, VkGpuSize mem_offset)
 {
     bound = true;
-    EXPECT(!alloc_idx && vkBindObjectMemoryRange(obj(), 0, offset, size, mem.obj(), mem_offset) == VK_SUCCESS);
+    VkQueue queue = dev.graphics_queues()[0]->obj();
+    EXPECT(!alloc_idx && vkQueueBindObjectMemoryRange(queue, obj(), 0, offset, size, mem.obj(), mem_offset) == VK_SUCCESS);
 }
 
-void Object::unbind_memory(uint32_t alloc_idx)
+void Object::unbind_memory(const Device &dev, uint32_t alloc_idx)
 {
-    EXPECT(vkBindObjectMemory(obj(), alloc_idx, VK_NULL_HANDLE, 0) == VK_SUCCESS);
+    VkQueue queue = dev.graphics_queues()[0]->obj();
+    EXPECT(vkQueueBindObjectMemory(queue, obj(), alloc_idx, VK_NULL_HANDLE, 0) == VK_SUCCESS);
 }
 
-void Object::unbind_memory()
+void Object::unbind_memory(const Device &dev)
 {
     for (uint32_t i = 0; i < mem_alloc_count_; i++)
-        unbind_memory(i);
+        unbind_memory(dev, i);
 }
 
 void Object::alloc_memory(const Device &dev)
@@ -275,11 +280,11 @@
         info = GpuMemory::alloc_info(mem_reqs[i], next_info);
         primary_mem_ = &internal_mems_[i];
         internal_mems_[i].init(dev, info);
-        bind_memory(i, internal_mems_[i], 0);
+        bind_memory(dev, i, internal_mems_[i], 0);
     }
 }
 
-void Object::alloc_memory(const std::vector<VkGpuMemory> &mems)
+void Object::alloc_memory(const Device &dev, const std::vector<VkGpuMemory> &mems)
 {
     if (!EXPECT(!internal_mems_) || !mem_alloc_count_)
         return;
@@ -294,7 +299,7 @@
         primary_mem_ = &internal_mems_[i];
 
         internal_mems_[i].init(mems[i]);
-        bind_memory(i, internal_mems_[i], 0);
+        bind_memory(dev, i, internal_mems_[i], 0);
     }
 }
 
@@ -397,6 +402,7 @@
         VkQueue queue;
 
         for (int j = 0; j < queue_props[i].queueCount; j++) {
+            // TODO: Need to add support for separate MEMMGR and work queues, including synchronization
             err = vkGetDeviceQueue(obj(), i, j, &queue);
             EXPECT(err == VK_SUCCESS);
 
@@ -580,17 +586,20 @@
 
 void Semaphore::init(const Device &dev, const VkSemaphoreCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateSemaphore, dev.obj(), &info);
     alloc_memory(dev);
 }
 
 void Semaphore::init(const Device &dev, const VkSemaphoreOpenInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkOpenSharedSemaphore, dev.obj(), &info);
 }
 
 void Event::init(const Device &dev, const VkEventCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateEvent, dev.obj(), &info);
     alloc_memory(dev);
 }
@@ -607,6 +616,7 @@
 
 void QueryPool::init(const Device &dev, const VkQueryPoolCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateQueryPool, dev.obj(), &info);
     alloc_memory(dev);
 }
@@ -633,6 +643,7 @@
 
 void Buffer::init_no_mem(const Device &dev, const VkBufferCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateBuffer, dev.obj(), &info);
     create_info_ = info;
 }
@@ -651,6 +662,7 @@
 
 void Image::init_no_mem(const Device &dev, const VkImageCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateImage, dev.obj(), &info);
     init_info(dev, info);
 }
@@ -663,7 +675,7 @@
     Object::init(img);
 
     init_info(dev, original_info);
-    alloc_memory(std::vector<VkGpuMemory>(1, mem));
+    alloc_memory(dev, std::vector<VkGpuMemory>(1, mem));
 }
 
 void Image::init_info(const Device &dev, const VkImageCreateInfo &info)
@@ -678,10 +690,11 @@
     }
 }
 
-void Image::bind_memory(uint32_t alloc_idx, const VkImageMemoryBindInfo &info,
+void Image::bind_memory(const Device &dev, uint32_t alloc_idx, const VkImageMemoryBindInfo &info,
                         const GpuMemory &mem, VkGpuSize mem_offset)
 {
-    EXPECT(!alloc_idx && vkBindImageMemoryRange(obj(), 0, &info, mem.obj(), mem_offset) == VK_SUCCESS);
+    VkQueue queue = dev.graphics_queues()[0]->obj();
+    EXPECT(!alloc_idx && vkQueueBindImageMemoryRange(queue, obj(), 0, &info, mem.obj(), mem_offset) == VK_SUCCESS);
 }
 
 VkSubresourceLayout Image::subresource_layout(const VkImageSubresource &subres) const
@@ -723,6 +736,7 @@
 
 void Shader::init(const Device &dev, const VkShaderCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateShader, dev.obj(), &info);
 }
 
@@ -738,6 +752,7 @@
 
 void Pipeline::init(const Device &dev, const VkGraphicsPipelineCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateGraphicsPipeline, dev.obj(), &info);
     alloc_memory(dev);
 }
@@ -747,18 +762,21 @@
         const VkGraphicsPipelineCreateInfo &info,
         const VkPipeline basePipeline)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateGraphicsPipelineDerivative, dev.obj(), &info, basePipeline);
     alloc_memory(dev);
 }
 
 void Pipeline::init(const Device &dev, const VkComputePipelineCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateComputePipeline, dev.obj(), &info);
     alloc_memory(dev);
 }
 
 void Pipeline::init(const Device&dev, size_t size, const void *data)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkLoadPipeline, dev.obj(), size, data);
     alloc_memory(dev);
 }
@@ -769,6 +787,7 @@
         const void *data,
         const VkPipeline basePipeline)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkLoadPipelineDerivative, dev.obj(), size, data, basePipeline);
     alloc_memory(dev);
 }
@@ -783,18 +802,21 @@
 
 void Sampler::init(const Device &dev, const VkSamplerCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateSampler, dev.obj(), &info);
     alloc_memory(dev);
 }
 
 void DescriptorSetLayout::init(const Device &dev, const VkDescriptorSetLayoutCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateDescriptorSetLayout, dev.obj(), &info);
     alloc_memory(dev);
 }
 
 void DescriptorSetLayoutChain::init(const Device &dev, const std::vector<const DescriptorSetLayout *> &layouts)
 {
+    DEV_INIT(dev);
     const std::vector<VkDescriptorSetLayout> layout_objs = make_objects<VkDescriptorSetLayout>(layouts);
 
     DERIVED_OBJECT_INIT(vkCreateDescriptorSetLayoutChain, dev.obj(), layout_objs.size(), &layout_objs[0]);
@@ -804,6 +826,7 @@
 void DescriptorPool::init(const Device &dev, VkDescriptorPoolUsage usage,
                           uint32_t max_sets, const VkDescriptorPoolCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateDescriptorPool, dev.obj(), usage, max_sets, &info);
     alloc_memory(dev);
 }
@@ -813,7 +836,7 @@
     EXPECT(vkResetDescriptorPool(obj()) == VK_SUCCESS);
 }
 
-std::vector<DescriptorSet *> DescriptorPool::alloc_sets(VkDescriptorSetUsage usage, const std::vector<const DescriptorSetLayout *> &layouts)
+std::vector<DescriptorSet *> DescriptorPool::alloc_sets(const Device &dev, VkDescriptorSetUsage usage, const std::vector<const DescriptorSetLayout *> &layouts)
 {
     const std::vector<VkDescriptorSetLayout> layout_objs = make_objects<VkDescriptorSetLayout>(layouts);
 
@@ -830,20 +853,21 @@
     sets.reserve(set_count);
     for (std::vector<VkDescriptorSet>::const_iterator it = set_objs.begin(); it != set_objs.end(); it++) {
         // do descriptor sets need memories bound?
-        sets.push_back(new DescriptorSet(*it));
+        DescriptorSet *descriptorSet = new DescriptorSet(*it);
+        descriptorSet->dev_ = &dev;
+        sets.push_back(descriptorSet);
     }
-
     return sets;
 }
 
-std::vector<DescriptorSet *> DescriptorPool::alloc_sets(VkDescriptorSetUsage usage, const DescriptorSetLayout &layout, uint32_t count)
+std::vector<DescriptorSet *> DescriptorPool::alloc_sets(const Device &dev, VkDescriptorSetUsage usage, const DescriptorSetLayout &layout, uint32_t count)
 {
-    return alloc_sets(usage, std::vector<const DescriptorSetLayout *>(count, &layout));
+    return alloc_sets(dev, usage, std::vector<const DescriptorSetLayout *>(count, &layout));
 }
 
-DescriptorSet *DescriptorPool::alloc_sets(VkDescriptorSetUsage usage, const DescriptorSetLayout &layout)
+DescriptorSet *DescriptorPool::alloc_sets(const Device &dev, VkDescriptorSetUsage usage, const DescriptorSetLayout &layout)
 {
-    std::vector<DescriptorSet *> set = alloc_sets(usage, layout, 1);
+    std::vector<DescriptorSet *> set = alloc_sets(dev, usage, layout, 1);
     return (set.empty()) ? NULL : set[0];
 }
 
@@ -884,6 +908,7 @@
 
 void CmdBuffer::init(const Device &dev, const VkCmdBufferCreateInfo &info)
 {
+    DEV_INIT(dev);
     DERIVED_OBJECT_INIT(vkCreateCommandBuffer, dev.obj(), &info);
 }
 
diff --git a/tests/vktestbinding.h b/tests/vktestbinding.h
index cec874e..f036a88 100644
--- a/tests/vktestbinding.h
+++ b/tests/vktestbinding.h
@@ -127,13 +127,13 @@
 public:
     const VkObject &obj() const { return reinterpret_cast<const VkObject &>(BaseObject::obj()); }
 
-    // vkBindObjectMemory()
-    void bind_memory(uint32_t alloc_idx, const GpuMemory &mem, VkGpuSize mem_offset);
-    void unbind_memory(uint32_t alloc_idx);
-    void unbind_memory();
+    // vkQueueBindObjectMemory()
+    void bind_memory(const Device &dev, uint32_t alloc_idx, const GpuMemory &mem, VkGpuSize mem_offset);
+    void unbind_memory(const Device &dev, uint32_t alloc_idx);
+    void unbind_memory(const Device &dev);
 
-    // vkBindObjectMemoryRange()
-    void bind_memory(uint32_t alloc_idx, VkGpuSize offset, VkGpuSize size,
+    // vkQueueBindObjectMemoryRange()
+    void bind_memory(const Device &dev, uint32_t alloc_idx, VkGpuSize offset, VkGpuSize size,
                      const GpuMemory &mem, VkGpuSize mem_offset);
 
     // Unless an object is initialized with init_no_mem(), memories are
@@ -147,6 +147,7 @@
           void *map()       { return map(0); }
 
     void unmap() const;
+    const Device* dev_;
 
 protected:
     explicit Object() : mem_alloc_count_(0), internal_mems_(NULL), primary_mem_(NULL), bound(false) {}
@@ -161,7 +162,7 @@
 
     // allocate and bind internal memories
     void alloc_memory(const Device &dev);
-    void alloc_memory(const std::vector<VkGpuMemory> &mems);
+    void alloc_memory(const Device &dev, const std::vector<VkGpuMemory> &mems);
 
 private:
     void cleanup();
@@ -207,7 +208,7 @@
     const PhysicalGpu &gpu() const { return gpu_; }
 
     // vkGetDeviceQueue()
-    const std::vector<Queue *> &graphics_queues() { return queues_[GRAPHICS]; }
+    const std::vector<Queue *> &graphics_queues() const { return queues_[GRAPHICS]; }
     const std::vector<Queue *> &compute_queues() { return queues_[COMPUTE]; }
     const std::vector<Queue *> &dma_queues() { return queues_[DMA]; }
     uint32_t graphics_queue_node_index_;
@@ -398,8 +399,8 @@
     // vkOpenPeerImage()
     void init(const Device &dev, const VkPeerImageOpenInfo &info, const VkImageCreateInfo &original_info);
 
-    // vkBindImageMemoryRange()
-    void bind_memory(uint32_t alloc_idx, const VkImageMemoryBindInfo &info,
+    // vkQueueBindImageMemoryRange()
+    void bind_memory(const Device &dev, uint32_t alloc_idx, const VkImageMemoryBindInfo &info,
                      const GpuMemory &mem, VkGpuSize mem_offset);
 
     // vkGetImageSubresourceInfo()
@@ -523,9 +524,9 @@
     void reset();
 
     // vkAllocDescriptorSets()
-    std::vector<DescriptorSet *> alloc_sets(VkDescriptorSetUsage usage, const std::vector<const DescriptorSetLayout *> &layouts);
-    std::vector<DescriptorSet *> alloc_sets(VkDescriptorSetUsage usage, const DescriptorSetLayout &layout, uint32_t count);
-    DescriptorSet *alloc_sets(VkDescriptorSetUsage usage, const DescriptorSetLayout &layout);
+    std::vector<DescriptorSet *> alloc_sets(const Device &dev, VkDescriptorSetUsage usage, const std::vector<const DescriptorSetLayout *> &layouts);
+    std::vector<DescriptorSet *> alloc_sets(const Device &dev, VkDescriptorSetUsage usage, const DescriptorSetLayout &layout, uint32_t count);
+    DescriptorSet *alloc_sets(const Device &dev, VkDescriptorSetUsage usage, const DescriptorSetLayout &layout);
 
     // vkClearDescriptorSets()
     void clear_sets(const std::vector<DescriptorSet *> &sets);
diff --git a/vulkan.py b/vulkan.py
index f5da856..a11eabe 100755
--- a/vulkan.py
+++ b/vulkan.py
@@ -354,22 +354,25 @@
              Param("size_t*", "pDataSize"),
              Param("void*", "pData")]),
 
-        Proto("VkResult", "BindObjectMemory",
-            [Param("VkObject", "object"),
+        Proto("VkResult", "QueueBindObjectMemory",
+            [Param("VkQueue", "queue"),
+             Param("VkObject", "object"),
              Param("uint32_t", "allocationIdx"),
              Param("VkGpuMemory", "mem"),
              Param("VkGpuSize", "offset")]),
 
-        Proto("VkResult", "BindObjectMemoryRange",
-            [Param("VkObject", "object"),
+        Proto("VkResult", "QueueBindObjectMemoryRange",
+            [Param("VkQueue", "queue"),
+             Param("VkObject", "object"),
              Param("uint32_t", "allocationIdx"),
              Param("VkGpuSize", "rangeOffset"),
              Param("VkGpuSize", "rangeSize"),
              Param("VkGpuMemory", "mem"),
              Param("VkGpuSize", "memOffset")]),
 
-        Proto("VkResult", "BindImageMemoryRange",
-            [Param("VkImage", "image"),
+        Proto("VkResult", "QueueBindImageMemoryRange",
+            [Param("VkQueue", "queue"),
+             Param("VkImage", "image"),
              Param("uint32_t", "allocationIdx"),
              Param("const VkImageMemoryBindInfo*", "bindInfo"),
              Param("VkGpuMemory", "mem"),