Merge "Fix GCH preview not working w/ minigbm"
diff --git a/android-emu/android/base/Pool.h b/android-emu/android/base/Pool.h
index bce2cc1..b5b1d1b 100644
--- a/android-emu/android/base/Pool.h
+++ b/android-emu/android/base/Pool.h
@@ -36,9 +36,9 @@
     //
     // Rough space cost formula:
     // O(chunksPerSize * log2(maxSize / minSize) * maxSize)
-    Pool(size_t minSize = 8,
+    Pool(size_t minSize = 4,
          size_t maxSize = 4096,
-         size_t chunksPerSize = 256);
+         size_t chunksPerSize = 1024);
 
     // All memory allocated by this pool
     // is automatically deleted when the pool
diff --git a/android-emu/android/base/ring_buffer.c b/android-emu/android/base/ring_buffer.c
index 527d2ea..fb6845f 100644
--- a/android-emu/android/base/ring_buffer.c
+++ b/android-emu/android/base/ring_buffer.c
@@ -407,19 +407,10 @@
 
 void ring_buffer_yield() { }
 
-static void ring_buffer_sleep() {
-#ifdef _WIN32
-    Sleep(2);
-#else
-    usleep(2000);
-#endif
-}
-
 bool ring_buffer_wait_write(
     const struct ring_buffer* r,
     const struct ring_buffer_view* v,
-    uint32_t bytes,
-    uint64_t timeout_us) {
+    uint32_t bytes) {
 
     bool can_write =
         v ? ring_buffer_view_can_write(r, v, bytes) :
@@ -438,8 +429,7 @@
 bool ring_buffer_wait_read(
     const struct ring_buffer* r,
     const struct ring_buffer_view* v,
-    uint32_t bytes,
-    uint64_t timeout_us) {
+    uint32_t bytes) {
 
     bool can_read =
         v ? ring_buffer_view_can_read(r, v, bytes) :
@@ -457,7 +447,6 @@
 }
 
 static uint32_t get_step_size(
-    struct ring_buffer* r,
     struct ring_buffer_view* v,
     uint32_t bytes) {
 
@@ -491,7 +480,7 @@
     uint32_t abort_value,
     const volatile uint32_t* abort_ptr) {
 
-    uint32_t candidate_step = get_step_size(r, v, bytes);
+    uint32_t candidate_step = get_step_size(v, bytes);
     uint32_t processed = 0;
 
     uint8_t* dst = (uint8_t*)data;
@@ -502,7 +491,7 @@
         }
 
         long processed_here = 0;
-        ring_buffer_wait_write(r, v, candidate_step, (uint64_t)(-1));
+        ring_buffer_wait_write(r, v, candidate_step);
 
         if (v) {
             processed_here = ring_buffer_view_write(r, v, dst + processed, candidate_step, 1);
@@ -528,7 +517,7 @@
     uint32_t abort_value,
     const volatile uint32_t* abort_ptr) {
 
-    uint32_t candidate_step = get_step_size(r, v, bytes);
+    uint32_t candidate_step = get_step_size(v, bytes);
     uint32_t processed = 0;
 
     uint8_t* dst = (uint8_t*)data;
@@ -540,7 +529,7 @@
         }
 
         long processed_here = 0;
-        ring_buffer_wait_read(r, v, candidate_step, (uint64_t)(-1));
+        ring_buffer_wait_read(r, v, candidate_step);
 
         if (v) {
             processed_here = ring_buffer_view_read(r, v, dst + processed, candidate_step, 1);
diff --git a/android-emu/android/base/ring_buffer.h b/android-emu/android/base/ring_buffer.h
index 390a758..7007a87 100644
--- a/android-emu/android/base/ring_buffer.h
+++ b/android-emu/android/base/ring_buffer.h
@@ -116,13 +116,11 @@
 bool ring_buffer_wait_write(
     const struct ring_buffer* r,
     const struct ring_buffer_view* v,
-    uint32_t bytes,
-    uint64_t timeout_us);
+    uint32_t bytes);
 bool ring_buffer_wait_read(
     const struct ring_buffer* r,
     const struct ring_buffer_view* v,
-    uint32_t bytes,
-    uint64_t timeout_us);
+    uint32_t bytes);
 
 // read/write fully, blocking if there is nothing to read/write.
 void ring_buffer_write_fully(
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index e1c414a..d0ae853 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -111,6 +111,9 @@
 // Vulkan extension that required a protocol update (new marshaling structs)
 static const char kVulkanShaderFloat16Int8[] = "ANDROID_EMU_vulkan_shader_float16_int8";
 
+// Vulkan async queue submit
+static const char kVulkanAsyncQueueSubmit[] = "ANDROID_EMU_vulkan_async_queue_submit";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -131,7 +134,8 @@
         hasSharedSlotsHostMemoryAllocator(false),
         hasVulkanFreeMemorySync(false),
         hasVirtioGpuNativeSync(false),
-        hasVulkanShaderFloat16Int8(false)
+        hasVulkanShaderFloat16Int8(false),
+        hasVulkanAsyncQueueSubmit(false)
     { }
 
     SyncImpl syncImpl;
@@ -151,6 +155,7 @@
     bool hasVulkanFreeMemorySync;
     bool hasVirtioGpuNativeSync;
     bool hasVulkanShaderFloat16Int8;
+    bool hasVulkanAsyncQueueSubmit;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index d7478d2..c371742 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -639,6 +639,7 @@
         queryAndSetVulkanFreeMemorySync(rcEnc);
         queryAndSetVirtioGpuNativeSync(rcEnc);
         queryAndSetVulkanShaderFloat16Int8Support(rcEnc);
+        queryAndSetVulkanAsyncQueueSubmitSupport(rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, rcEnc);
         }
@@ -894,3 +895,10 @@
         rcEnc->featureInfo()->hasVulkanShaderFloat16Int8 = true;
     }
 }
+
+void HostConnection::queryAndSetVulkanAsyncQueueSubmitSupport(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kVulkanAsyncQueueSubmit) != std::string::npos) {
+        rcEnc->featureInfo()->hasVulkanAsyncQueueSubmit = true;
+    }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 4ccd5a7..69d8a16 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -216,6 +216,7 @@
     void queryAndSetVulkanFreeMemorySync(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVirtioGpuNativeSync(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanShaderFloat16Int8Support(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetVulkanAsyncQueueSubmitSupport(ExtendedRCEncoderContext *rcEnc);
 
 private:
     HostConnectionType m_connectionType;
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index 50e8a62..51913e8 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -240,6 +240,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueSubmit");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     VkResult vkQueueSubmit_VkResult_return = (VkResult)0;
     auto resources = ResourceTracker::get();
     vkQueueSubmit_VkResult_return = resources->on_vkQueueSubmit(vkEnc, VK_SUCCESS, queue, submitCount, pSubmits, fence);
@@ -250,6 +251,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueWaitIdle");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     VkResult vkQueueWaitIdle_VkResult_return = (VkResult)0;
     auto resources = ResourceTracker::get();
     vkQueueWaitIdle_VkResult_return = resources->on_vkQueueWaitIdle(vkEnc, VK_SUCCESS, queue);
@@ -418,6 +420,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueBindSparse");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     VkResult vkQueueBindSparse_VkResult_return = (VkResult)0;
     vkQueueBindSparse_VkResult_return = vkEnc->vkQueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
     return vkQueueBindSparse_VkResult_return;
@@ -2258,6 +2261,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueuePresentKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     VkResult vkQueuePresentKHR_VkResult_return = (VkResult)0;
     vkQueuePresentKHR_VkResult_return = vkEnc->vkQueuePresentKHR(queue, pPresentInfo);
     return vkQueuePresentKHR_VkResult_return;
@@ -3751,6 +3755,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueSignalReleaseImageANDROID");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     VkResult vkQueueSignalReleaseImageANDROID_VkResult_return = (VkResult)0;
     vkQueueSignalReleaseImageANDROID_VkResult_return = vkEnc->vkQueueSignalReleaseImageANDROID(queue, waitSemaphoreCount, pWaitSemaphores, image, pNativeFenceFd);
     return vkQueueSignalReleaseImageANDROID_VkResult_return;
@@ -4633,6 +4638,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueBeginDebugUtilsLabelEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     vkEnc->vkQueueBeginDebugUtilsLabelEXT(queue, pLabelInfo);
 }
 static void entry_vkQueueEndDebugUtilsLabelEXT(
@@ -4640,6 +4646,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueEndDebugUtilsLabelEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     vkEnc->vkQueueEndDebugUtilsLabelEXT(queue);
 }
 static void entry_vkQueueInsertDebugUtilsLabelEXT(
@@ -4648,6 +4655,7 @@
 {
     AEMU_SCOPED_TRACE("vkQueueInsertDebugUtilsLabelEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     vkEnc->vkQueueInsertDebugUtilsLabelEXT(queue, pLabelInfo);
 }
 static void entry_vkCmdBeginDebugUtilsLabelEXT(
@@ -4992,6 +5000,7 @@
 {
     AEMU_SCOPED_TRACE("vkGetQueueCheckpointDataNV");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
     vkEnc->vkGetQueueCheckpointDataNV(queue, pCheckpointDataCount, pCheckpointData);
 }
 #endif
@@ -5287,6 +5296,48 @@
     return vkFreeMemorySyncGOOGLE_VkResult_return;
 }
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+static void entry_vkQueueHostSyncGOOGLE(
+    VkQueue queue,
+    uint32_t needHostSync,
+    uint32_t sequenceNumber)
+{
+    AEMU_SCOPED_TRACE("vkQueueHostSyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
+    vkEnc->vkQueueHostSyncGOOGLE(queue, needHostSync, sequenceNumber);
+}
+static void entry_vkQueueSubmitAsyncGOOGLE(
+    VkQueue queue,
+    uint32_t submitCount,
+    const VkSubmitInfo* pSubmits,
+    VkFence fence)
+{
+    AEMU_SCOPED_TRACE("vkQueueSubmitAsyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
+    vkEnc->vkQueueSubmitAsyncGOOGLE(queue, submitCount, pSubmits, fence);
+}
+static void entry_vkQueueWaitIdleAsyncGOOGLE(
+    VkQueue queue)
+{
+    AEMU_SCOPED_TRACE("vkQueueWaitIdleAsyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
+    vkEnc->vkQueueWaitIdleAsyncGOOGLE(queue);
+}
+static void entry_vkQueueBindSparseAsyncGOOGLE(
+    VkQueue queue,
+    uint32_t bindInfoCount,
+    const VkBindSparseInfo* pBindInfo,
+    VkFence fence)
+{
+    AEMU_SCOPED_TRACE("vkQueueBindSparseAsyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForQueue(queue, vkEnc);
+    vkEnc->vkQueueBindSparseAsyncGOOGLE(queue, bindInfoCount, pBindInfo, fence);
+}
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
     if (!strcmp(name, "vkCreateInstance"))
@@ -6744,6 +6795,24 @@
         return nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+    if (!strcmp(name, "vkQueueHostSyncGOOGLE"))
+    {
+        return nullptr;
+    }
+    if (!strcmp(name, "vkQueueSubmitAsyncGOOGLE"))
+    {
+        return nullptr;
+    }
+    if (!strcmp(name, "vkQueueWaitIdleAsyncGOOGLE"))
+    {
+        return nullptr;
+    }
+    if (!strcmp(name, "vkQueueBindSparseAsyncGOOGLE"))
+    {
+        return nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name){
@@ -8298,6 +8367,28 @@
         return (void*)dynCheck_entry_vkFreeMemorySyncGOOGLE;
     }
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+    if (!strcmp(name, "vkQueueHostSyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueHostSyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkQueueSubmitAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueSubmitAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkQueueWaitIdleAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueWaitIdleAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkQueueBindSparseAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueBindSparseAsyncGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name){
@@ -9923,6 +10014,28 @@
         return hasExt ? (void*)entry_vkFreeMemorySyncGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+    if (!strcmp(name, "vkQueueHostSyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueHostSyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkQueueSubmitAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueSubmitAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkQueueWaitIdleAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueWaitIdleAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkQueueBindSparseAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_queue_submit");
+        return hasExt ? (void*)entry_vkQueueBindSparseAsyncGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 
diff --git a/system/vulkan/func_table.h b/system/vulkan/func_table.h
index 3c0e457..9c2e5be 100644
--- a/system/vulkan/func_table.h
+++ b/system/vulkan/func_table.h
@@ -292,6 +292,8 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name);
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name);
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name);
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index e7ff088..2293df0 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -275,6 +275,11 @@
         uint32_t sequenceNumber = 0;
     };
 
+    struct VkQueue_Info {
+        VkEncoder** lastUsedEncoderPtr = nullptr;
+        uint32_t sequenceNumber = 0;
+    };
+
     // custom guest-side structs for images/buffers because of AHardwareBuffer :((
     struct VkImage_Info {
         VkDevice device;
@@ -394,13 +399,31 @@
             *(info.lastUsedEncoderPtr) : nullptr;
 
         if (lastUsedEncoder) {
-            lastUsedEncoder->unregisterCleanupCallback(commandBuffer);
             delete info.lastUsedEncoderPtr;
+            info.lastUsedEncoderPtr = nullptr;
         }
 
         info_VkCommandBuffer.erase(commandBuffer);
     }
 
+    void unregister_VkQueue(VkQueue queue) {
+        AutoLock lock(mLock);
+
+        auto it = info_VkQueue.find(queue);
+        if (it == info_VkQueue.end()) return;
+        auto& info = it->second;
+        auto lastUsedEncoder =
+            info.lastUsedEncoderPtr ?
+            *(info.lastUsedEncoderPtr) : nullptr;
+
+        if (lastUsedEncoder) {
+            delete info.lastUsedEncoderPtr;
+            info.lastUsedEncoderPtr = nullptr;
+        }
+
+        info_VkQueue.erase(queue);
+    }
+
     void unregister_VkDeviceMemory(VkDeviceMemory mem) {
         AutoLock lock(mLock);
 
@@ -839,6 +862,11 @@
         return mFeatureInfo->hasDeferredVulkanCommands;
     }
 
+    bool supportsAsyncQueueSubmit() const {
+        if (!mFeatureInfo) return false;
+        return mFeatureInfo->hasVulkanAsyncQueueSubmit;
+    }
+
     bool supportsCreateResourcesWithRequirements() const {
         if (!mFeatureInfo) return false;
         return mFeatureInfo->hasVulkanCreateResourcesWithRequirements;
@@ -4101,8 +4129,13 @@
         lock.unlock();
 
         if (pre_signal_semaphores.empty()) {
-            input_result = enc->vkQueueSubmit(queue, submitCount, pSubmits, fence);
-            if (input_result != VK_SUCCESS) return input_result;
+            if (supportsAsyncQueueSubmit()) {
+                enc->vkQueueSubmitAsyncGOOGLE(queue, submitCount, pSubmits, fence);
+                input_result = VK_SUCCESS;
+            } else {
+                input_result = enc->vkQueueSubmit(queue, submitCount, pSubmits, fence);
+                if (input_result != VK_SUCCESS) return input_result;
+            }
         } else {
             // Schedule waits on the OS external objects and
             // signal the wait semaphores
@@ -4137,10 +4170,20 @@
                 .pWaitDstStageMask = nullptr,
                 .signalSemaphoreCount = static_cast<uint32_t>(pre_signal_semaphores.size()),
                 .pSignalSemaphores = pre_signal_semaphores.data()};
-            enc->vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
 
-            input_result = enc->vkQueueSubmit(queue, submitCount, pSubmits, fence);
-            if (input_result != VK_SUCCESS) return input_result;
+            if (supportsAsyncQueueSubmit()) {
+                enc->vkQueueSubmitAsyncGOOGLE(queue, 1, &submit_info, VK_NULL_HANDLE);
+            } else {
+                enc->vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
+            }
+
+            if (supportsAsyncQueueSubmit()) {
+                enc->vkQueueSubmitAsyncGOOGLE(queue, submitCount, pSubmits, fence);
+                input_result = VK_SUCCESS;
+            } else {
+                input_result = enc->vkQueueSubmit(queue, submitCount, pSubmits, fence);
+                if (input_result != VK_SUCCESS) return input_result;
+            }
         }
 
         lock.lock();
@@ -4587,6 +4630,31 @@
             physicalDevice, pImageFormatInfo, pImageFormatProperties);
     }
 
+    void registerEncoderCleanupCallback(const VkEncoder* encoder, void* object, CleanupCallback callback) {
+        AutoLock lock(mLock);
+        auto& callbacks = mEncoderCleanupCallbacks[encoder];
+        callbacks[object] = callback;
+    }
+    
+    void unregisterEncoderCleanupCallback(const VkEncoder* encoder, void* object) {
+        AutoLock lock(mLock);
+        mEncoderCleanupCallbacks[encoder].erase(object);
+    }
+
+    void onEncoderDeleted(const VkEncoder* encoder) {
+        AutoLock lock(mLock);
+        if (mEncoderCleanupCallbacks.find(encoder) == mEncoderCleanupCallbacks.end()) return;
+
+        std::unordered_map<void*, CleanupCallback> callbackCopies = mEncoderCleanupCallbacks[encoder];
+
+        mEncoderCleanupCallbacks.erase(encoder);
+        lock.unlock();
+
+        for (auto it : callbackCopies) {
+            it.second();
+        }
+    }
+
     uint32_t syncEncodersForCommandBuffer(VkCommandBuffer commandBuffer, VkEncoder* currentEncoder) {
         AutoLock lock(mLock);
 
@@ -4612,17 +4680,87 @@
         if (!lastEncoder) return 0;
         if (lastEncoder == currentEncoder) return 0;
 
-        info.sequenceNumber++;
-        lastEncoder->vkCommandBufferHostSyncGOOGLE(commandBuffer, false, info.sequenceNumber);
+        auto oldSeq = info.sequenceNumber;
+
+        lock.unlock();
+
+        lastEncoder->vkCommandBufferHostSyncGOOGLE(commandBuffer, false, oldSeq + 1);
         lastEncoder->flush();
-        info.sequenceNumber++;
-        currentEncoder->vkCommandBufferHostSyncGOOGLE(commandBuffer, true, info.sequenceNumber);
+        currentEncoder->vkCommandBufferHostSyncGOOGLE(commandBuffer, true, oldSeq + 2);
 
-        lastEncoder->unregisterCleanupCallback(commandBuffer);
+        unregisterEncoderCleanupCallback(lastEncoder, commandBuffer);
 
-        currentEncoder->registerCleanupCallback(commandBuffer, [currentEncoder, lastUsedEncoderPtr]() {
-            if (*(lastUsedEncoderPtr) == currentEncoder) {
-                *(lastUsedEncoderPtr) = nullptr;
+        registerEncoderCleanupCallback(currentEncoder, commandBuffer, [this, currentEncoder, commandBuffer]() {
+            AutoLock lock(mLock);
+            auto it = info_VkCommandBuffer.find(commandBuffer);
+            if (it == info_VkCommandBuffer.end()) return;
+
+            auto& info = it->second;
+            if (!info.lastUsedEncoderPtr) return;
+            if (!*(info.lastUsedEncoderPtr)) return;
+
+            if (currentEncoder == *(info.lastUsedEncoderPtr)) {
+                *(info.lastUsedEncoderPtr) = nullptr;
+            }
+        });
+
+        return 1;
+    }
+
+    uint32_t syncEncodersForQueue(VkQueue queue, VkEncoder* currentEncoder) {
+        if (!supportsAsyncQueueSubmit()) {
+            return 0;
+        }
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkQueue.find(queue);
+        if (it == info_VkQueue.end()) return 0;
+
+        auto& info = it->second;
+
+        if (!info.lastUsedEncoderPtr) {
+            info.lastUsedEncoderPtr = new VkEncoder*;
+            *(info.lastUsedEncoderPtr) = currentEncoder;
+        }
+
+        auto lastUsedEncoderPtr = info.lastUsedEncoderPtr;
+
+        auto lastEncoder = *(lastUsedEncoderPtr);
+
+        // We always make lastUsedEncoderPtr track
+        // the current encoder, even if the last encoder
+        // is null.
+        *(lastUsedEncoderPtr) = currentEncoder;
+
+        if (!lastEncoder) return 0;
+        if (lastEncoder == currentEncoder) return 0;
+
+        auto oldSeq = info.sequenceNumber;
+
+        info.sequenceNumber += 2;
+
+        lock.unlock();
+
+        // at this point the seqno for the old thread is determined
+
+        lastEncoder->vkQueueHostSyncGOOGLE(queue, false, oldSeq + 1);
+        lastEncoder->flush();
+        currentEncoder->vkQueueHostSyncGOOGLE(queue, true, oldSeq + 2);
+
+        unregisterEncoderCleanupCallback(lastEncoder, queue);
+
+        registerEncoderCleanupCallback(currentEncoder, queue, [this, currentEncoder, queue]() {
+            AutoLock lock(mLock);
+            auto it = info_VkQueue.find(queue);
+            if (it == info_VkQueue.end()) return;
+
+            auto& info = it->second;
+            if (!info.lastUsedEncoderPtr) return;
+            if (!*(info.lastUsedEncoderPtr)) return;
+
+            if (currentEncoder == *(info.lastUsedEncoderPtr)) {
+                *(info.lastUsedEncoderPtr) = nullptr;
             }
         });
 
@@ -4773,6 +4911,9 @@
     WorkPool mWorkPool { 4 };
     std::unordered_map<VkQueue, std::vector<WorkPool::WaitGroupHandle>>
         mQueueSensitiveWorkPoolItems;
+
+    std::unordered_map<const VkEncoder*, std::unordered_map<void*, CleanupCallback>> mEncoderCleanupCallbacks;
+
 };
 
 ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { }
@@ -5556,10 +5697,27 @@
         pImageFormatProperties);
 }
 
+void ResourceTracker::registerEncoderCleanupCallback(const VkEncoder* encoder, void* handle, ResourceTracker::CleanupCallback callback) {
+    mImpl->registerEncoderCleanupCallback(encoder, handle, callback);
+}
+
+void ResourceTracker::unregisterEncoderCleanupCallback(const VkEncoder* encoder, void* handle) {
+    mImpl->unregisterEncoderCleanupCallback(encoder, handle);
+}
+
+void ResourceTracker::onEncoderDeleted(const VkEncoder* encoder) {
+    mImpl->onEncoderDeleted(encoder);
+}
+
 uint32_t ResourceTracker::syncEncodersForCommandBuffer(VkCommandBuffer commandBuffer, VkEncoder* current) {
     return mImpl->syncEncodersForCommandBuffer(commandBuffer, current);
 }
 
+uint32_t ResourceTracker::syncEncodersForQueue(VkQueue queue, VkEncoder* current) {
+    return mImpl->syncEncodersForQueue(queue, current);
+}
+
+
 VkResult ResourceTracker::on_vkBeginCommandBuffer(
     void* context, VkResult input_result,
     VkCommandBuffer commandBuffer,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index db33285..200150f 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -20,6 +20,7 @@
 
 #include "VulkanHandleMapping.h"
 #include "VulkanHandles.h"
+#include <functional>
 #include <memory>
 
 #include "goldfish_vk_transform_guest.h"
@@ -44,6 +45,7 @@
 
     using HostConnectionGetFunc = HostConnection* (*)();
     using VkEncoderGetFunc = VkEncoder* (*)(HostConnection*);
+    using CleanupCallback = std::function<void()>;
 
     struct ThreadingCallbacks {
         HostConnectionGetFunc hostConnectionGetFunc = 0;
@@ -480,7 +482,12 @@
         const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
         VkImageFormatProperties2* pImageFormatProperties);
 
+    void registerEncoderCleanupCallback(const VkEncoder* encoder, void* handle, CleanupCallback callback);
+    void unregisterEncoderCleanupCallback(const VkEncoder* encoder, void* handle);
+    void onEncoderDeleted(const VkEncoder* encoder);
+
     uint32_t syncEncodersForCommandBuffer(VkCommandBuffer commandBuffer, VkEncoder* current);
+    uint32_t syncEncodersForQueue(VkQueue queue, VkEncoder* current);
 
     VkResult on_vkBeginCommandBuffer(
         void* context, VkResult input_result,
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index 8a76c92..0eeba15 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -69,12 +69,7 @@
         }
     }
 
-    ~Impl() {
-        for (auto it : mCleanupCallbacks) {
-            fprintf(stderr, "%s: run cleanup callback for %p\n", __func__, it.first);
-            it.second();
-        }
-    }
+    ~Impl() { }
 
     VulkanCountingStream* countingStream() { return &m_countingStream; }
     VulkanStreamGuest* stream() { return &m_stream; }
@@ -88,25 +83,35 @@
     }
 
     void flush() {
-        AutoLock encoderLock(lock);
+        lock();
         m_stream.flush();
+        unlock();
     }
 
-    // Assume the lock for the current encoder is held.
-    void registerCleanupCallback(void* handle, VkEncoder::CleanupCallback cb) {
-        if (mCleanupCallbacks.end() == mCleanupCallbacks.find(handle)) {
-            mCleanupCallbacks[handle] = cb;
-        } else {
+    // can be recursive
+    void lock() {
+        if (this == sAcquiredEncoderThreadLocal) {
+            ++sAcquiredEncoderThreadLockLevels;
+            return; // recursive
+        }
+        while (mLock.test_and_set(std::memory_order_acquire));
+        sAcquiredEncoderThreadLocal = this;
+        sAcquiredEncoderThreadLockLevels = 1;
+    }
+
+    void unlock() {
+        if (this != sAcquiredEncoderThreadLocal) {
+            // error, trying to unlock without having locked first
             return;
         }
-    }
 
-    void unregisterCleanupCallback(void* handle) {
-        mCleanupCallbacks.erase(handle);
+        --sAcquiredEncoderThreadLockLevels;
+        if (0 == sAcquiredEncoderThreadLockLevels) {
+            mLock.clear(std::memory_order_release);
+            sAcquiredEncoderThreadLocal = nullptr;
+        }
     }
 
-    Lock lock;
-
 private:
     VulkanCountingStream m_countingStream;
     VulkanStreamGuest m_stream;
@@ -114,25 +119,44 @@
 
     Validation m_validation;
     bool m_logEncodes;
+    std::atomic_flag mLock = ATOMIC_FLAG_INIT;
+    static thread_local Impl* sAcquiredEncoderThreadLocal;
+    static thread_local uint32_t sAcquiredEncoderThreadLockLevels;
+};
 
-    std::unordered_map<void*, VkEncoder::CleanupCallback> mCleanupCallbacks;
+VkEncoder::~VkEncoder() {
+    auto rt = ResourceTracker::get();
+    if (!rt) return;
+    rt->onEncoderDeleted(this);
+}
+
+// static
+thread_local VkEncoder::Impl* VkEncoder::Impl::sAcquiredEncoderThreadLocal = nullptr;
+thread_local uint32_t VkEncoder::Impl::sAcquiredEncoderThreadLockLevels = 0;
+
+struct EncoderAutoLock {
+    EncoderAutoLock(VkEncoder* enc) : mEnc(enc) {
+        mEnc->lock();
+    }
+    ~EncoderAutoLock() {
+        mEnc->unlock();
+    }
+    VkEncoder* mEnc;
 };
 
 VkEncoder::VkEncoder(IOStream *stream) :
     mImpl(new VkEncoder::Impl(stream)) { }
 
-VkEncoder::~VkEncoder() = default;
-
 void VkEncoder::flush() {
     mImpl->flush();
 }
 
-void VkEncoder::registerCleanupCallback(void* handle, VkEncoder::CleanupCallback cb) {
-    mImpl->registerCleanupCallback(handle, cb);
+void VkEncoder::lock() {
+    mImpl->lock();
 }
 
-void VkEncoder::unregisterCleanupCallback(void* handle) {
-    mImpl->unregisterCleanupCallback(handle);
+void VkEncoder::unlock() {
+    mImpl->unlock();
 }
 
 #define VALIDATE_RET(retType, success, validate) \
@@ -149,7 +173,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkInstance* pInstance)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateInstance encode");
     mImpl->log("start vkCreateInstance");
     auto stream = mImpl->stream();
@@ -221,12 +245,10 @@
     AEMU_SCOPED_TRACE("vkCreateInstance returnUnmarshal");
     VkResult vkCreateInstance_VkResult_return = (VkResult)0;
     stream->read(&vkCreateInstance_VkResult_return, sizeof(VkResult));
+    mImpl->resources()->on_vkCreateInstance(this, vkCreateInstance_VkResult_return, pCreateInfo, pAllocator, pInstance);
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
-    encoderLock.unlock();
-    mImpl->resources()->on_vkCreateInstance(this, vkCreateInstance_VkResult_return, pCreateInfo, pAllocator, pInstance);
-    encoderLock.lock();
     mImpl->log("finish vkCreateInstance");;
     return vkCreateInstance_VkResult_return;
 }
@@ -235,7 +257,7 @@
     VkInstance instance,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyInstance encode");
     mImpl->log("start vkDestroyInstance");
     auto stream = mImpl->stream();
@@ -288,6 +310,9 @@
     AEMU_SCOPED_TRACE("vkDestroyInstance readParams");
     AEMU_SCOPED_TRACE("vkDestroyInstance returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkInstance((VkInstance*)&instance);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyInstance");;
 }
 
@@ -296,7 +321,7 @@
     uint32_t* pPhysicalDeviceCount,
     VkPhysicalDevice* pPhysicalDevices)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumeratePhysicalDevices encode");
     mImpl->log("start vkEnumeratePhysicalDevices");
     auto stream = mImpl->stream();
@@ -396,9 +421,9 @@
     AEMU_SCOPED_TRACE("vkEnumeratePhysicalDevices returnUnmarshal");
     VkResult vkEnumeratePhysicalDevices_VkResult_return = (VkResult)0;
     stream->read(&vkEnumeratePhysicalDevices_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumeratePhysicalDevices");;
     return vkEnumeratePhysicalDevices_VkResult_return;
 }
@@ -407,7 +432,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceFeatures* pFeatures)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures encode");
     mImpl->log("start vkGetPhysicalDeviceFeatures");
     auto stream = mImpl->stream();
@@ -440,6 +465,9 @@
         transform_fromhost_VkPhysicalDeviceFeatures(mImpl->resources(), (VkPhysicalDeviceFeatures*)(pFeatures));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceFeatures");;
 }
 
@@ -448,7 +476,7 @@
     VkFormat format,
     VkFormatProperties* pFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties encode");
     mImpl->log("start vkGetPhysicalDeviceFormatProperties");
     auto stream = mImpl->stream();
@@ -485,6 +513,9 @@
         transform_fromhost_VkFormatProperties(mImpl->resources(), (VkFormatProperties*)(pFormatProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceFormatProperties");;
 }
 
@@ -497,7 +528,7 @@
     VkImageCreateFlags flags,
     VkImageFormatProperties* pImageFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties encode");
     mImpl->log("start vkGetPhysicalDeviceImageFormatProperties");
     auto stream = mImpl->stream();
@@ -552,9 +583,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties returnUnmarshal");
     VkResult vkGetPhysicalDeviceImageFormatProperties_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceImageFormatProperties_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceImageFormatProperties");;
     return vkGetPhysicalDeviceImageFormatProperties_VkResult_return;
 }
@@ -563,7 +594,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceProperties* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties encode");
     mImpl->log("start vkGetPhysicalDeviceProperties");
     auto stream = mImpl->stream();
@@ -596,9 +627,10 @@
         transform_fromhost_VkPhysicalDeviceProperties(mImpl->resources(), (VkPhysicalDeviceProperties*)(pProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties returnUnmarshal");
-    encoderLock.unlock();
     mImpl->resources()->on_vkGetPhysicalDeviceProperties(this, physicalDevice, pProperties);
-    encoderLock.lock();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceProperties");;
 }
 
@@ -607,7 +639,7 @@
     uint32_t* pQueueFamilyPropertyCount,
     VkQueueFamilyProperties* pQueueFamilyProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties encode");
     mImpl->log("start vkGetPhysicalDeviceQueueFamilyProperties");
     auto stream = mImpl->stream();
@@ -699,6 +731,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceQueueFamilyProperties");;
 }
 
@@ -706,7 +741,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceMemoryProperties* pMemoryProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties encode");
     mImpl->log("start vkGetPhysicalDeviceMemoryProperties");
     auto stream = mImpl->stream();
@@ -739,9 +774,10 @@
         transform_fromhost_VkPhysicalDeviceMemoryProperties(mImpl->resources(), (VkPhysicalDeviceMemoryProperties*)(pMemoryProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties returnUnmarshal");
-    encoderLock.unlock();
     mImpl->resources()->on_vkGetPhysicalDeviceMemoryProperties(this, physicalDevice, pMemoryProperties);
-    encoderLock.lock();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceMemoryProperties");;
 }
 
@@ -749,7 +785,7 @@
     VkInstance instance,
     const char* pName)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetInstanceProcAddr encode");
     mImpl->log("start vkGetInstanceProcAddr");
     auto stream = mImpl->stream();
@@ -785,9 +821,9 @@
     AEMU_SCOPED_TRACE("vkGetInstanceProcAddr returnUnmarshal");
     PFN_vkVoidFunction vkGetInstanceProcAddr_PFN_vkVoidFunction_return = (PFN_vkVoidFunction)0;
     stream->read(&vkGetInstanceProcAddr_PFN_vkVoidFunction_return, sizeof(PFN_vkVoidFunction));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetInstanceProcAddr");;
     return vkGetInstanceProcAddr_PFN_vkVoidFunction_return;
 }
@@ -796,7 +832,7 @@
     VkDevice device,
     const char* pName)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceProcAddr encode");
     mImpl->log("start vkGetDeviceProcAddr");
     auto stream = mImpl->stream();
@@ -832,9 +868,9 @@
     AEMU_SCOPED_TRACE("vkGetDeviceProcAddr returnUnmarshal");
     PFN_vkVoidFunction vkGetDeviceProcAddr_PFN_vkVoidFunction_return = (PFN_vkVoidFunction)0;
     stream->read(&vkGetDeviceProcAddr_PFN_vkVoidFunction_return, sizeof(PFN_vkVoidFunction));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDeviceProcAddr");;
     return vkGetDeviceProcAddr_PFN_vkVoidFunction_return;
 }
@@ -845,7 +881,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDevice* pDevice)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDevice encode");
     mImpl->log("start vkCreateDevice");
     auto stream = mImpl->stream();
@@ -925,12 +961,10 @@
     AEMU_SCOPED_TRACE("vkCreateDevice returnUnmarshal");
     VkResult vkCreateDevice_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDevice_VkResult_return, sizeof(VkResult));
+    mImpl->resources()->on_vkCreateDevice(this, vkCreateDevice_VkResult_return, physicalDevice, pCreateInfo, pAllocator, pDevice);
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
-    encoderLock.unlock();
-    mImpl->resources()->on_vkCreateDevice(this, vkCreateDevice_VkResult_return, physicalDevice, pCreateInfo, pAllocator, pDevice);
-    encoderLock.lock();
     mImpl->log("finish vkCreateDevice");;
     return vkCreateDevice_VkResult_return;
 }
@@ -939,12 +973,10 @@
     VkDevice device,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDevice encode");
     mImpl->log("start vkDestroyDevice");
-    encoderLock.unlock();
     mImpl->resources()->on_vkDestroyDevice_pre(this, device, pAllocator);
-    encoderLock.lock();
     auto stream = mImpl->stream();
     auto countingStream = mImpl->countingStream();
     auto resources = mImpl->resources();
@@ -996,6 +1028,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDevice returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDevice((VkDevice*)&device);
     stream->flush();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDevice");;
 }
 
@@ -1004,7 +1039,7 @@
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumerateInstanceExtensionProperties encode");
     mImpl->log("start vkEnumerateInstanceExtensionProperties");
     auto stream = mImpl->stream();
@@ -1124,9 +1159,9 @@
     AEMU_SCOPED_TRACE("vkEnumerateInstanceExtensionProperties returnUnmarshal");
     VkResult vkEnumerateInstanceExtensionProperties_VkResult_return = (VkResult)0;
     stream->read(&vkEnumerateInstanceExtensionProperties_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumerateInstanceExtensionProperties");;
     return vkEnumerateInstanceExtensionProperties_VkResult_return;
 }
@@ -1137,7 +1172,7 @@
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumerateDeviceExtensionProperties encode");
     mImpl->log("start vkEnumerateDeviceExtensionProperties");
     auto stream = mImpl->stream();
@@ -1265,9 +1300,9 @@
     AEMU_SCOPED_TRACE("vkEnumerateDeviceExtensionProperties returnUnmarshal");
     VkResult vkEnumerateDeviceExtensionProperties_VkResult_return = (VkResult)0;
     stream->read(&vkEnumerateDeviceExtensionProperties_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumerateDeviceExtensionProperties");;
     return vkEnumerateDeviceExtensionProperties_VkResult_return;
 }
@@ -1276,7 +1311,7 @@
     uint32_t* pPropertyCount,
     VkLayerProperties* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumerateInstanceLayerProperties encode");
     mImpl->log("start vkEnumerateInstanceLayerProperties");
     auto stream = mImpl->stream();
@@ -1362,9 +1397,9 @@
     AEMU_SCOPED_TRACE("vkEnumerateInstanceLayerProperties returnUnmarshal");
     VkResult vkEnumerateInstanceLayerProperties_VkResult_return = (VkResult)0;
     stream->read(&vkEnumerateInstanceLayerProperties_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumerateInstanceLayerProperties");;
     return vkEnumerateInstanceLayerProperties_VkResult_return;
 }
@@ -1374,7 +1409,7 @@
     uint32_t* pPropertyCount,
     VkLayerProperties* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumerateDeviceLayerProperties encode");
     mImpl->log("start vkEnumerateDeviceLayerProperties");
     auto stream = mImpl->stream();
@@ -1468,9 +1503,9 @@
     AEMU_SCOPED_TRACE("vkEnumerateDeviceLayerProperties returnUnmarshal");
     VkResult vkEnumerateDeviceLayerProperties_VkResult_return = (VkResult)0;
     stream->read(&vkEnumerateDeviceLayerProperties_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumerateDeviceLayerProperties");;
     return vkEnumerateDeviceLayerProperties_VkResult_return;
 }
@@ -1481,7 +1516,7 @@
     uint32_t queueIndex,
     VkQueue* pQueue)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceQueue encode");
     mImpl->log("start vkGetDeviceQueue");
     auto stream = mImpl->stream();
@@ -1528,6 +1563,9 @@
     stream->handleMapping()->mapHandles_u64_VkQueue(&cgen_var_89, (VkQueue*)pQueue, 1);
     stream->unsetHandleMapping();
     AEMU_SCOPED_TRACE("vkGetDeviceQueue returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDeviceQueue");;
 }
 
@@ -1537,7 +1575,7 @@
     const VkSubmitInfo* pSubmits,
     VkFence fence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueSubmit encode");
     mImpl->log("start vkQueueSubmit");
     auto stream = mImpl->stream();
@@ -1602,9 +1640,9 @@
     AEMU_SCOPED_TRACE("vkQueueSubmit returnUnmarshal");
     VkResult vkQueueSubmit_VkResult_return = (VkResult)0;
     stream->read(&vkQueueSubmit_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkQueueSubmit");;
     return vkQueueSubmit_VkResult_return;
 }
@@ -1612,7 +1650,7 @@
 VkResult VkEncoder::vkQueueWaitIdle(
     VkQueue queue)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueWaitIdle encode");
     mImpl->log("start vkQueueWaitIdle");
     auto stream = mImpl->stream();
@@ -1640,9 +1678,9 @@
     AEMU_SCOPED_TRACE("vkQueueWaitIdle returnUnmarshal");
     VkResult vkQueueWaitIdle_VkResult_return = (VkResult)0;
     stream->read(&vkQueueWaitIdle_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkQueueWaitIdle");;
     return vkQueueWaitIdle_VkResult_return;
 }
@@ -1650,7 +1688,7 @@
 VkResult VkEncoder::vkDeviceWaitIdle(
     VkDevice device)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDeviceWaitIdle encode");
     mImpl->log("start vkDeviceWaitIdle");
     auto stream = mImpl->stream();
@@ -1678,9 +1716,9 @@
     AEMU_SCOPED_TRACE("vkDeviceWaitIdle returnUnmarshal");
     VkResult vkDeviceWaitIdle_VkResult_return = (VkResult)0;
     stream->read(&vkDeviceWaitIdle_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkDeviceWaitIdle");;
     return vkDeviceWaitIdle_VkResult_return;
 }
@@ -1691,7 +1729,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDeviceMemory* pMemory)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAllocateMemory encode");
     mImpl->log("start vkAllocateMemory");
     auto stream = mImpl->stream();
@@ -1771,9 +1809,9 @@
     AEMU_SCOPED_TRACE("vkAllocateMemory returnUnmarshal");
     VkResult vkAllocateMemory_VkResult_return = (VkResult)0;
     stream->read(&vkAllocateMemory_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAllocateMemory");;
     return vkAllocateMemory_VkResult_return;
 }
@@ -1783,7 +1821,7 @@
     VkDeviceMemory memory,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkFreeMemory encode");
     mImpl->log("start vkFreeMemory");
     auto stream = mImpl->stream();
@@ -1841,6 +1879,9 @@
     AEMU_SCOPED_TRACE("vkFreeMemory readParams");
     AEMU_SCOPED_TRACE("vkFreeMemory returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDeviceMemory((VkDeviceMemory*)&memory);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkFreeMemory");;
 }
 
@@ -1872,7 +1913,7 @@
     uint32_t memoryRangeCount,
     const VkMappedMemoryRange* pMemoryRanges)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkFlushMappedMemoryRanges encode");
     mImpl->log("start vkFlushMappedMemoryRanges");
     VALIDATE_RET(VkResult, VK_SUCCESS, mImpl->validation()->on_vkFlushMappedMemoryRanges(this, VK_SUCCESS, device, memoryRangeCount, pMemoryRanges));
@@ -1968,9 +2009,9 @@
     AEMU_SCOPED_TRACE("vkFlushMappedMemoryRanges returnUnmarshal");
     VkResult vkFlushMappedMemoryRanges_VkResult_return = (VkResult)0;
     stream->read(&vkFlushMappedMemoryRanges_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkFlushMappedMemoryRanges");;
     return vkFlushMappedMemoryRanges_VkResult_return;
 }
@@ -1980,7 +2021,7 @@
     uint32_t memoryRangeCount,
     const VkMappedMemoryRange* pMemoryRanges)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkInvalidateMappedMemoryRanges encode");
     mImpl->log("start vkInvalidateMappedMemoryRanges");
     VALIDATE_RET(VkResult, VK_SUCCESS, mImpl->validation()->on_vkInvalidateMappedMemoryRanges(this, VK_SUCCESS, device, memoryRangeCount, pMemoryRanges));
@@ -2038,9 +2079,6 @@
     AEMU_SCOPED_TRACE("vkInvalidateMappedMemoryRanges returnUnmarshal");
     VkResult vkInvalidateMappedMemoryRanges_VkResult_return = (VkResult)0;
     stream->read(&vkInvalidateMappedMemoryRanges_VkResult_return, sizeof(VkResult));
-    countingStream->clearPool();
-    stream->clearPool();
-    pool->freeAll();
     if (!resources->usingDirectMapping())
     {
         for (uint32_t i = 0; i < memoryRangeCount; ++i)
@@ -2060,6 +2098,9 @@
             stream->read(targetRange, actualSize);
         }
     }
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkInvalidateMappedMemoryRanges");;
     return vkInvalidateMappedMemoryRanges_VkResult_return;
 }
@@ -2069,7 +2110,7 @@
     VkDeviceMemory memory,
     VkDeviceSize* pCommittedMemoryInBytes)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceMemoryCommitment encode");
     mImpl->log("start vkGetDeviceMemoryCommitment");
     auto stream = mImpl->stream();
@@ -2107,6 +2148,9 @@
     AEMU_SCOPED_TRACE("vkGetDeviceMemoryCommitment readParams");
     stream->read((VkDeviceSize*)pCommittedMemoryInBytes, sizeof(VkDeviceSize));
     AEMU_SCOPED_TRACE("vkGetDeviceMemoryCommitment returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDeviceMemoryCommitment");;
 }
 
@@ -2116,7 +2160,7 @@
     VkDeviceMemory memory,
     VkDeviceSize memoryOffset)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBindBufferMemory encode");
     mImpl->log("start vkBindBufferMemory");
     auto stream = mImpl->stream();
@@ -2165,9 +2209,9 @@
     AEMU_SCOPED_TRACE("vkBindBufferMemory returnUnmarshal");
     VkResult vkBindBufferMemory_VkResult_return = (VkResult)0;
     stream->read(&vkBindBufferMemory_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBindBufferMemory");;
     return vkBindBufferMemory_VkResult_return;
 }
@@ -2178,7 +2222,7 @@
     VkDeviceMemory memory,
     VkDeviceSize memoryOffset)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBindImageMemory encode");
     mImpl->log("start vkBindImageMemory");
     auto stream = mImpl->stream();
@@ -2227,9 +2271,9 @@
     AEMU_SCOPED_TRACE("vkBindImageMemory returnUnmarshal");
     VkResult vkBindImageMemory_VkResult_return = (VkResult)0;
     stream->read(&vkBindImageMemory_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBindImageMemory");;
     return vkBindImageMemory_VkResult_return;
 }
@@ -2239,7 +2283,7 @@
     VkBuffer buffer,
     VkMemoryRequirements* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements encode");
     mImpl->log("start vkGetBufferMemoryRequirements");
     auto stream = mImpl->stream();
@@ -2280,6 +2324,9 @@
         transform_fromhost_VkMemoryRequirements(mImpl->resources(), (VkMemoryRequirements*)(pMemoryRequirements));
     }
     AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetBufferMemoryRequirements");;
 }
 
@@ -2288,7 +2335,7 @@
     VkImage image,
     VkMemoryRequirements* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements encode");
     mImpl->log("start vkGetImageMemoryRequirements");
     auto stream = mImpl->stream();
@@ -2329,6 +2376,9 @@
         transform_fromhost_VkMemoryRequirements(mImpl->resources(), (VkMemoryRequirements*)(pMemoryRequirements));
     }
     AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageMemoryRequirements");;
 }
 
@@ -2338,7 +2388,7 @@
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements* pSparseMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements encode");
     mImpl->log("start vkGetImageSparseMemoryRequirements");
     auto stream = mImpl->stream();
@@ -2438,6 +2488,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageSparseMemoryRequirements");;
 }
 
@@ -2451,7 +2504,7 @@
     uint32_t* pPropertyCount,
     VkSparseImageFormatProperties* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties encode");
     mImpl->log("start vkGetPhysicalDeviceSparseImageFormatProperties");
     auto stream = mImpl->stream();
@@ -2563,6 +2616,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceSparseImageFormatProperties");;
 }
 
@@ -2572,7 +2628,7 @@
     const VkBindSparseInfo* pBindInfo,
     VkFence fence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueBindSparse encode");
     mImpl->log("start vkQueueBindSparse");
     auto stream = mImpl->stream();
@@ -2637,9 +2693,9 @@
     AEMU_SCOPED_TRACE("vkQueueBindSparse returnUnmarshal");
     VkResult vkQueueBindSparse_VkResult_return = (VkResult)0;
     stream->read(&vkQueueBindSparse_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkQueueBindSparse");;
     return vkQueueBindSparse_VkResult_return;
 }
@@ -2650,7 +2706,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkFence* pFence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateFence encode");
     mImpl->log("start vkCreateFence");
     auto stream = mImpl->stream();
@@ -2730,9 +2786,9 @@
     AEMU_SCOPED_TRACE("vkCreateFence returnUnmarshal");
     VkResult vkCreateFence_VkResult_return = (VkResult)0;
     stream->read(&vkCreateFence_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateFence");;
     return vkCreateFence_VkResult_return;
 }
@@ -2742,7 +2798,7 @@
     VkFence fence,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyFence encode");
     mImpl->log("start vkDestroyFence");
     auto stream = mImpl->stream();
@@ -2803,6 +2859,9 @@
     AEMU_SCOPED_TRACE("vkDestroyFence readParams");
     AEMU_SCOPED_TRACE("vkDestroyFence returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkFence((VkFence*)&fence);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyFence");;
 }
 
@@ -2811,7 +2870,7 @@
     uint32_t fenceCount,
     const VkFence* pFences)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkResetFences encode");
     mImpl->log("start vkResetFences");
     auto stream = mImpl->stream();
@@ -2863,9 +2922,9 @@
     AEMU_SCOPED_TRACE("vkResetFences returnUnmarshal");
     VkResult vkResetFences_VkResult_return = (VkResult)0;
     stream->read(&vkResetFences_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkResetFences");;
     return vkResetFences_VkResult_return;
 }
@@ -2874,7 +2933,7 @@
     VkDevice device,
     VkFence fence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetFenceStatus encode");
     mImpl->log("start vkGetFenceStatus");
     auto stream = mImpl->stream();
@@ -2910,9 +2969,9 @@
     AEMU_SCOPED_TRACE("vkGetFenceStatus returnUnmarshal");
     VkResult vkGetFenceStatus_VkResult_return = (VkResult)0;
     stream->read(&vkGetFenceStatus_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetFenceStatus");;
     return vkGetFenceStatus_VkResult_return;
 }
@@ -2924,7 +2983,7 @@
     VkBool32 waitAll,
     uint64_t timeout)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkWaitForFences encode");
     mImpl->log("start vkWaitForFences");
     auto stream = mImpl->stream();
@@ -2984,9 +3043,9 @@
     AEMU_SCOPED_TRACE("vkWaitForFences returnUnmarshal");
     VkResult vkWaitForFences_VkResult_return = (VkResult)0;
     stream->read(&vkWaitForFences_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkWaitForFences");;
     return vkWaitForFences_VkResult_return;
 }
@@ -2997,7 +3056,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSemaphore* pSemaphore)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateSemaphore encode");
     mImpl->log("start vkCreateSemaphore");
     auto stream = mImpl->stream();
@@ -3077,9 +3136,9 @@
     AEMU_SCOPED_TRACE("vkCreateSemaphore returnUnmarshal");
     VkResult vkCreateSemaphore_VkResult_return = (VkResult)0;
     stream->read(&vkCreateSemaphore_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateSemaphore");;
     return vkCreateSemaphore_VkResult_return;
 }
@@ -3089,7 +3148,7 @@
     VkSemaphore semaphore,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroySemaphore encode");
     mImpl->log("start vkDestroySemaphore");
     auto stream = mImpl->stream();
@@ -3150,6 +3209,9 @@
     AEMU_SCOPED_TRACE("vkDestroySemaphore readParams");
     AEMU_SCOPED_TRACE("vkDestroySemaphore returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkSemaphore((VkSemaphore*)&semaphore);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroySemaphore");;
 }
 
@@ -3159,7 +3221,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkEvent* pEvent)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateEvent encode");
     mImpl->log("start vkCreateEvent");
     auto stream = mImpl->stream();
@@ -3239,9 +3301,9 @@
     AEMU_SCOPED_TRACE("vkCreateEvent returnUnmarshal");
     VkResult vkCreateEvent_VkResult_return = (VkResult)0;
     stream->read(&vkCreateEvent_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateEvent");;
     return vkCreateEvent_VkResult_return;
 }
@@ -3251,7 +3313,7 @@
     VkEvent event,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyEvent encode");
     mImpl->log("start vkDestroyEvent");
     auto stream = mImpl->stream();
@@ -3312,6 +3374,9 @@
     AEMU_SCOPED_TRACE("vkDestroyEvent readParams");
     AEMU_SCOPED_TRACE("vkDestroyEvent returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkEvent((VkEvent*)&event);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyEvent");;
 }
 
@@ -3319,7 +3384,7 @@
     VkDevice device,
     VkEvent event)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetEventStatus encode");
     mImpl->log("start vkGetEventStatus");
     auto stream = mImpl->stream();
@@ -3355,9 +3420,9 @@
     AEMU_SCOPED_TRACE("vkGetEventStatus returnUnmarshal");
     VkResult vkGetEventStatus_VkResult_return = (VkResult)0;
     stream->read(&vkGetEventStatus_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetEventStatus");;
     return vkGetEventStatus_VkResult_return;
 }
@@ -3366,7 +3431,7 @@
     VkDevice device,
     VkEvent event)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkSetEvent encode");
     mImpl->log("start vkSetEvent");
     auto stream = mImpl->stream();
@@ -3402,9 +3467,9 @@
     AEMU_SCOPED_TRACE("vkSetEvent returnUnmarshal");
     VkResult vkSetEvent_VkResult_return = (VkResult)0;
     stream->read(&vkSetEvent_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkSetEvent");;
     return vkSetEvent_VkResult_return;
 }
@@ -3413,7 +3478,7 @@
     VkDevice device,
     VkEvent event)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkResetEvent encode");
     mImpl->log("start vkResetEvent");
     auto stream = mImpl->stream();
@@ -3449,9 +3514,9 @@
     AEMU_SCOPED_TRACE("vkResetEvent returnUnmarshal");
     VkResult vkResetEvent_VkResult_return = (VkResult)0;
     stream->read(&vkResetEvent_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkResetEvent");;
     return vkResetEvent_VkResult_return;
 }
@@ -3462,7 +3527,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkQueryPool* pQueryPool)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateQueryPool encode");
     mImpl->log("start vkCreateQueryPool");
     auto stream = mImpl->stream();
@@ -3542,9 +3607,9 @@
     AEMU_SCOPED_TRACE("vkCreateQueryPool returnUnmarshal");
     VkResult vkCreateQueryPool_VkResult_return = (VkResult)0;
     stream->read(&vkCreateQueryPool_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateQueryPool");;
     return vkCreateQueryPool_VkResult_return;
 }
@@ -3554,7 +3619,7 @@
     VkQueryPool queryPool,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyQueryPool encode");
     mImpl->log("start vkDestroyQueryPool");
     auto stream = mImpl->stream();
@@ -3615,6 +3680,9 @@
     AEMU_SCOPED_TRACE("vkDestroyQueryPool readParams");
     AEMU_SCOPED_TRACE("vkDestroyQueryPool returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkQueryPool((VkQueryPool*)&queryPool);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyQueryPool");;
 }
 
@@ -3628,7 +3696,7 @@
     VkDeviceSize stride,
     VkQueryResultFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetQueryPoolResults encode");
     mImpl->log("start vkGetQueryPoolResults");
     auto stream = mImpl->stream();
@@ -3689,9 +3757,9 @@
     AEMU_SCOPED_TRACE("vkGetQueryPoolResults returnUnmarshal");
     VkResult vkGetQueryPoolResults_VkResult_return = (VkResult)0;
     stream->read(&vkGetQueryPoolResults_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetQueryPoolResults");;
     return vkGetQueryPoolResults_VkResult_return;
 }
@@ -3702,7 +3770,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkBuffer* pBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateBuffer encode");
     mImpl->log("start vkCreateBuffer");
     auto stream = mImpl->stream();
@@ -3782,9 +3850,9 @@
     AEMU_SCOPED_TRACE("vkCreateBuffer returnUnmarshal");
     VkResult vkCreateBuffer_VkResult_return = (VkResult)0;
     stream->read(&vkCreateBuffer_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateBuffer");;
     return vkCreateBuffer_VkResult_return;
 }
@@ -3794,7 +3862,7 @@
     VkBuffer buffer,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyBuffer encode");
     mImpl->log("start vkDestroyBuffer");
     auto stream = mImpl->stream();
@@ -3855,6 +3923,9 @@
     AEMU_SCOPED_TRACE("vkDestroyBuffer readParams");
     AEMU_SCOPED_TRACE("vkDestroyBuffer returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkBuffer((VkBuffer*)&buffer);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyBuffer");;
 }
 
@@ -3864,7 +3935,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkBufferView* pView)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateBufferView encode");
     mImpl->log("start vkCreateBufferView");
     auto stream = mImpl->stream();
@@ -3944,9 +4015,9 @@
     AEMU_SCOPED_TRACE("vkCreateBufferView returnUnmarshal");
     VkResult vkCreateBufferView_VkResult_return = (VkResult)0;
     stream->read(&vkCreateBufferView_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateBufferView");;
     return vkCreateBufferView_VkResult_return;
 }
@@ -3956,7 +4027,7 @@
     VkBufferView bufferView,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyBufferView encode");
     mImpl->log("start vkDestroyBufferView");
     auto stream = mImpl->stream();
@@ -4017,6 +4088,9 @@
     AEMU_SCOPED_TRACE("vkDestroyBufferView readParams");
     AEMU_SCOPED_TRACE("vkDestroyBufferView returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkBufferView((VkBufferView*)&bufferView);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyBufferView");;
 }
 
@@ -4026,7 +4100,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkImage* pImage)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateImage encode");
     mImpl->log("start vkCreateImage");
     auto stream = mImpl->stream();
@@ -4107,9 +4181,9 @@
     AEMU_SCOPED_TRACE("vkCreateImage returnUnmarshal");
     VkResult vkCreateImage_VkResult_return = (VkResult)0;
     stream->read(&vkCreateImage_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateImage");;
     return vkCreateImage_VkResult_return;
 }
@@ -4119,7 +4193,7 @@
     VkImage image,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyImage encode");
     mImpl->log("start vkDestroyImage");
     auto stream = mImpl->stream();
@@ -4180,6 +4254,9 @@
     AEMU_SCOPED_TRACE("vkDestroyImage readParams");
     AEMU_SCOPED_TRACE("vkDestroyImage returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkImage((VkImage*)&image);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyImage");;
 }
 
@@ -4189,7 +4266,7 @@
     const VkImageSubresource* pSubresource,
     VkSubresourceLayout* pLayout)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageSubresourceLayout encode");
     mImpl->log("start vkGetImageSubresourceLayout");
     auto stream = mImpl->stream();
@@ -4243,6 +4320,9 @@
         transform_fromhost_VkSubresourceLayout(mImpl->resources(), (VkSubresourceLayout*)(pLayout));
     }
     AEMU_SCOPED_TRACE("vkGetImageSubresourceLayout returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageSubresourceLayout");;
 }
 
@@ -4252,7 +4332,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkImageView* pView)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateImageView encode");
     mImpl->log("start vkCreateImageView");
     auto stream = mImpl->stream();
@@ -4332,9 +4412,9 @@
     AEMU_SCOPED_TRACE("vkCreateImageView returnUnmarshal");
     VkResult vkCreateImageView_VkResult_return = (VkResult)0;
     stream->read(&vkCreateImageView_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateImageView");;
     return vkCreateImageView_VkResult_return;
 }
@@ -4344,7 +4424,7 @@
     VkImageView imageView,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyImageView encode");
     mImpl->log("start vkDestroyImageView");
     auto stream = mImpl->stream();
@@ -4405,6 +4485,9 @@
     AEMU_SCOPED_TRACE("vkDestroyImageView readParams");
     AEMU_SCOPED_TRACE("vkDestroyImageView returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkImageView((VkImageView*)&imageView);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyImageView");;
 }
 
@@ -4414,7 +4497,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkShaderModule* pShaderModule)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateShaderModule encode");
     mImpl->log("start vkCreateShaderModule");
     auto stream = mImpl->stream();
@@ -4494,9 +4577,9 @@
     AEMU_SCOPED_TRACE("vkCreateShaderModule returnUnmarshal");
     VkResult vkCreateShaderModule_VkResult_return = (VkResult)0;
     stream->read(&vkCreateShaderModule_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateShaderModule");;
     return vkCreateShaderModule_VkResult_return;
 }
@@ -4506,7 +4589,7 @@
     VkShaderModule shaderModule,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyShaderModule encode");
     mImpl->log("start vkDestroyShaderModule");
     auto stream = mImpl->stream();
@@ -4567,6 +4650,9 @@
     AEMU_SCOPED_TRACE("vkDestroyShaderModule readParams");
     AEMU_SCOPED_TRACE("vkDestroyShaderModule returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkShaderModule((VkShaderModule*)&shaderModule);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyShaderModule");;
 }
 
@@ -4576,7 +4662,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkPipelineCache* pPipelineCache)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreatePipelineCache encode");
     mImpl->log("start vkCreatePipelineCache");
     auto stream = mImpl->stream();
@@ -4656,9 +4742,9 @@
     AEMU_SCOPED_TRACE("vkCreatePipelineCache returnUnmarshal");
     VkResult vkCreatePipelineCache_VkResult_return = (VkResult)0;
     stream->read(&vkCreatePipelineCache_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreatePipelineCache");;
     return vkCreatePipelineCache_VkResult_return;
 }
@@ -4668,7 +4754,7 @@
     VkPipelineCache pipelineCache,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyPipelineCache encode");
     mImpl->log("start vkDestroyPipelineCache");
     auto stream = mImpl->stream();
@@ -4729,6 +4815,9 @@
     AEMU_SCOPED_TRACE("vkDestroyPipelineCache readParams");
     AEMU_SCOPED_TRACE("vkDestroyPipelineCache returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkPipelineCache((VkPipelineCache*)&pipelineCache);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyPipelineCache");;
 }
 
@@ -4738,7 +4827,7 @@
     size_t* pDataSize,
     void* pData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPipelineCacheData encode");
     mImpl->log("start vkGetPipelineCacheData");
     auto stream = mImpl->stream();
@@ -4826,9 +4915,9 @@
     AEMU_SCOPED_TRACE("vkGetPipelineCacheData returnUnmarshal");
     VkResult vkGetPipelineCacheData_VkResult_return = (VkResult)0;
     stream->read(&vkGetPipelineCacheData_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPipelineCacheData");;
     return vkGetPipelineCacheData_VkResult_return;
 }
@@ -4839,7 +4928,7 @@
     uint32_t srcCacheCount,
     const VkPipelineCache* pSrcCaches)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkMergePipelineCaches encode");
     mImpl->log("start vkMergePipelineCaches");
     auto stream = mImpl->stream();
@@ -4899,9 +4988,9 @@
     AEMU_SCOPED_TRACE("vkMergePipelineCaches returnUnmarshal");
     VkResult vkMergePipelineCaches_VkResult_return = (VkResult)0;
     stream->read(&vkMergePipelineCaches_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkMergePipelineCaches");;
     return vkMergePipelineCaches_VkResult_return;
 }
@@ -4914,7 +5003,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkPipeline* pPipelines)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateGraphicsPipelines encode");
     mImpl->log("start vkCreateGraphicsPipelines");
     auto stream = mImpl->stream();
@@ -5030,9 +5119,9 @@
     AEMU_SCOPED_TRACE("vkCreateGraphicsPipelines returnUnmarshal");
     VkResult vkCreateGraphicsPipelines_VkResult_return = (VkResult)0;
     stream->read(&vkCreateGraphicsPipelines_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateGraphicsPipelines");;
     return vkCreateGraphicsPipelines_VkResult_return;
 }
@@ -5045,7 +5134,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkPipeline* pPipelines)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateComputePipelines encode");
     mImpl->log("start vkCreateComputePipelines");
     auto stream = mImpl->stream();
@@ -5161,9 +5250,9 @@
     AEMU_SCOPED_TRACE("vkCreateComputePipelines returnUnmarshal");
     VkResult vkCreateComputePipelines_VkResult_return = (VkResult)0;
     stream->read(&vkCreateComputePipelines_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateComputePipelines");;
     return vkCreateComputePipelines_VkResult_return;
 }
@@ -5173,7 +5262,7 @@
     VkPipeline pipeline,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyPipeline encode");
     mImpl->log("start vkDestroyPipeline");
     auto stream = mImpl->stream();
@@ -5234,6 +5323,9 @@
     AEMU_SCOPED_TRACE("vkDestroyPipeline readParams");
     AEMU_SCOPED_TRACE("vkDestroyPipeline returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkPipeline((VkPipeline*)&pipeline);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyPipeline");;
 }
 
@@ -5243,7 +5335,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkPipelineLayout* pPipelineLayout)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreatePipelineLayout encode");
     mImpl->log("start vkCreatePipelineLayout");
     auto stream = mImpl->stream();
@@ -5323,9 +5415,9 @@
     AEMU_SCOPED_TRACE("vkCreatePipelineLayout returnUnmarshal");
     VkResult vkCreatePipelineLayout_VkResult_return = (VkResult)0;
     stream->read(&vkCreatePipelineLayout_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreatePipelineLayout");;
     return vkCreatePipelineLayout_VkResult_return;
 }
@@ -5335,7 +5427,7 @@
     VkPipelineLayout pipelineLayout,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyPipelineLayout encode");
     mImpl->log("start vkDestroyPipelineLayout");
     auto stream = mImpl->stream();
@@ -5396,6 +5488,9 @@
     AEMU_SCOPED_TRACE("vkDestroyPipelineLayout readParams");
     AEMU_SCOPED_TRACE("vkDestroyPipelineLayout returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkPipelineLayout((VkPipelineLayout*)&pipelineLayout);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyPipelineLayout");;
 }
 
@@ -5405,7 +5500,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSampler* pSampler)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateSampler encode");
     mImpl->log("start vkCreateSampler");
     auto stream = mImpl->stream();
@@ -5485,9 +5580,9 @@
     AEMU_SCOPED_TRACE("vkCreateSampler returnUnmarshal");
     VkResult vkCreateSampler_VkResult_return = (VkResult)0;
     stream->read(&vkCreateSampler_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateSampler");;
     return vkCreateSampler_VkResult_return;
 }
@@ -5497,7 +5592,7 @@
     VkSampler sampler,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroySampler encode");
     mImpl->log("start vkDestroySampler");
     auto stream = mImpl->stream();
@@ -5558,6 +5653,9 @@
     AEMU_SCOPED_TRACE("vkDestroySampler readParams");
     AEMU_SCOPED_TRACE("vkDestroySampler returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkSampler((VkSampler*)&sampler);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroySampler");;
 }
 
@@ -5567,7 +5665,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDescriptorSetLayout* pSetLayout)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDescriptorSetLayout encode");
     mImpl->log("start vkCreateDescriptorSetLayout");
     auto stream = mImpl->stream();
@@ -5647,9 +5745,9 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorSetLayout returnUnmarshal");
     VkResult vkCreateDescriptorSetLayout_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDescriptorSetLayout_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateDescriptorSetLayout");;
     return vkCreateDescriptorSetLayout_VkResult_return;
 }
@@ -5659,7 +5757,7 @@
     VkDescriptorSetLayout descriptorSetLayout,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDescriptorSetLayout encode");
     mImpl->log("start vkDestroyDescriptorSetLayout");
     auto stream = mImpl->stream();
@@ -5720,6 +5818,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDescriptorSetLayout readParams");
     AEMU_SCOPED_TRACE("vkDestroyDescriptorSetLayout returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDescriptorSetLayout((VkDescriptorSetLayout*)&descriptorSetLayout);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDescriptorSetLayout");;
 }
 
@@ -5729,7 +5830,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDescriptorPool* pDescriptorPool)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDescriptorPool encode");
     mImpl->log("start vkCreateDescriptorPool");
     auto stream = mImpl->stream();
@@ -5809,9 +5910,9 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorPool returnUnmarshal");
     VkResult vkCreateDescriptorPool_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDescriptorPool_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateDescriptorPool");;
     return vkCreateDescriptorPool_VkResult_return;
 }
@@ -5821,7 +5922,7 @@
     VkDescriptorPool descriptorPool,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDescriptorPool encode");
     mImpl->log("start vkDestroyDescriptorPool");
     auto stream = mImpl->stream();
@@ -5882,6 +5983,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDescriptorPool readParams");
     AEMU_SCOPED_TRACE("vkDestroyDescriptorPool returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDescriptorPool((VkDescriptorPool*)&descriptorPool);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDescriptorPool");;
 }
 
@@ -5890,7 +5994,7 @@
     VkDescriptorPool descriptorPool,
     VkDescriptorPoolResetFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkResetDescriptorPool encode");
     mImpl->log("start vkResetDescriptorPool");
     auto stream = mImpl->stream();
@@ -5930,9 +6034,9 @@
     AEMU_SCOPED_TRACE("vkResetDescriptorPool returnUnmarshal");
     VkResult vkResetDescriptorPool_VkResult_return = (VkResult)0;
     stream->read(&vkResetDescriptorPool_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkResetDescriptorPool");;
     return vkResetDescriptorPool_VkResult_return;
 }
@@ -5942,7 +6046,7 @@
     const VkDescriptorSetAllocateInfo* pAllocateInfo,
     VkDescriptorSet* pDescriptorSets)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAllocateDescriptorSets encode");
     mImpl->log("start vkAllocateDescriptorSets");
     auto stream = mImpl->stream();
@@ -6008,9 +6112,9 @@
     AEMU_SCOPED_TRACE("vkAllocateDescriptorSets returnUnmarshal");
     VkResult vkAllocateDescriptorSets_VkResult_return = (VkResult)0;
     stream->read(&vkAllocateDescriptorSets_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAllocateDescriptorSets");;
     return vkAllocateDescriptorSets_VkResult_return;
 }
@@ -6021,7 +6125,7 @@
     uint32_t descriptorSetCount,
     const VkDescriptorSet* pDescriptorSets)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkFreeDescriptorSets encode");
     mImpl->log("start vkFreeDescriptorSets");
     auto stream = mImpl->stream();
@@ -6093,13 +6197,13 @@
     AEMU_SCOPED_TRACE("vkFreeDescriptorSets returnUnmarshal");
     VkResult vkFreeDescriptorSets_VkResult_return = (VkResult)0;
     stream->read(&vkFreeDescriptorSets_VkResult_return, sizeof(VkResult));
-    countingStream->clearPool();
-    stream->clearPool();
-    pool->freeAll();
     if (pDescriptorSets)
     {
         resources->destroyMapping()->mapHandles_VkDescriptorSet((VkDescriptorSet*)pDescriptorSets, ((descriptorSetCount)));
     }
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkFreeDescriptorSets");;
     return vkFreeDescriptorSets_VkResult_return;
 }
@@ -6111,7 +6215,7 @@
     uint32_t descriptorCopyCount,
     const VkCopyDescriptorSet* pDescriptorCopies)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSets encode");
     mImpl->log("start vkUpdateDescriptorSets");
     auto stream = mImpl->stream();
@@ -6195,6 +6299,9 @@
     }
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSets readParams");
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSets returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkUpdateDescriptorSets");;
 }
 
@@ -6204,7 +6311,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkFramebuffer* pFramebuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateFramebuffer encode");
     mImpl->log("start vkCreateFramebuffer");
     auto stream = mImpl->stream();
@@ -6284,9 +6391,9 @@
     AEMU_SCOPED_TRACE("vkCreateFramebuffer returnUnmarshal");
     VkResult vkCreateFramebuffer_VkResult_return = (VkResult)0;
     stream->read(&vkCreateFramebuffer_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateFramebuffer");;
     return vkCreateFramebuffer_VkResult_return;
 }
@@ -6296,7 +6403,7 @@
     VkFramebuffer framebuffer,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyFramebuffer encode");
     mImpl->log("start vkDestroyFramebuffer");
     auto stream = mImpl->stream();
@@ -6357,6 +6464,9 @@
     AEMU_SCOPED_TRACE("vkDestroyFramebuffer readParams");
     AEMU_SCOPED_TRACE("vkDestroyFramebuffer returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkFramebuffer((VkFramebuffer*)&framebuffer);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyFramebuffer");;
 }
 
@@ -6366,7 +6476,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkRenderPass* pRenderPass)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateRenderPass encode");
     mImpl->log("start vkCreateRenderPass");
     auto stream = mImpl->stream();
@@ -6446,9 +6556,9 @@
     AEMU_SCOPED_TRACE("vkCreateRenderPass returnUnmarshal");
     VkResult vkCreateRenderPass_VkResult_return = (VkResult)0;
     stream->read(&vkCreateRenderPass_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateRenderPass");;
     return vkCreateRenderPass_VkResult_return;
 }
@@ -6458,7 +6568,7 @@
     VkRenderPass renderPass,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyRenderPass encode");
     mImpl->log("start vkDestroyRenderPass");
     auto stream = mImpl->stream();
@@ -6519,6 +6629,9 @@
     AEMU_SCOPED_TRACE("vkDestroyRenderPass readParams");
     AEMU_SCOPED_TRACE("vkDestroyRenderPass returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkRenderPass((VkRenderPass*)&renderPass);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyRenderPass");;
 }
 
@@ -6527,7 +6640,7 @@
     VkRenderPass renderPass,
     VkExtent2D* pGranularity)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetRenderAreaGranularity encode");
     mImpl->log("start vkGetRenderAreaGranularity");
     auto stream = mImpl->stream();
@@ -6568,6 +6681,9 @@
         transform_fromhost_VkExtent2D(mImpl->resources(), (VkExtent2D*)(pGranularity));
     }
     AEMU_SCOPED_TRACE("vkGetRenderAreaGranularity returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetRenderAreaGranularity");;
 }
 
@@ -6577,7 +6693,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkCommandPool* pCommandPool)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateCommandPool encode");
     mImpl->log("start vkCreateCommandPool");
     auto stream = mImpl->stream();
@@ -6657,9 +6773,9 @@
     AEMU_SCOPED_TRACE("vkCreateCommandPool returnUnmarshal");
     VkResult vkCreateCommandPool_VkResult_return = (VkResult)0;
     stream->read(&vkCreateCommandPool_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateCommandPool");;
     return vkCreateCommandPool_VkResult_return;
 }
@@ -6669,7 +6785,7 @@
     VkCommandPool commandPool,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyCommandPool encode");
     mImpl->log("start vkDestroyCommandPool");
     auto stream = mImpl->stream();
@@ -6730,6 +6846,9 @@
     AEMU_SCOPED_TRACE("vkDestroyCommandPool readParams");
     AEMU_SCOPED_TRACE("vkDestroyCommandPool returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkCommandPool((VkCommandPool*)&commandPool);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyCommandPool");;
 }
 
@@ -6738,7 +6857,7 @@
     VkCommandPool commandPool,
     VkCommandPoolResetFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkResetCommandPool encode");
     mImpl->log("start vkResetCommandPool");
     auto stream = mImpl->stream();
@@ -6778,9 +6897,9 @@
     AEMU_SCOPED_TRACE("vkResetCommandPool returnUnmarshal");
     VkResult vkResetCommandPool_VkResult_return = (VkResult)0;
     stream->read(&vkResetCommandPool_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkResetCommandPool");;
     return vkResetCommandPool_VkResult_return;
 }
@@ -6790,7 +6909,7 @@
     const VkCommandBufferAllocateInfo* pAllocateInfo,
     VkCommandBuffer* pCommandBuffers)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAllocateCommandBuffers encode");
     mImpl->log("start vkAllocateCommandBuffers");
     auto stream = mImpl->stream();
@@ -6856,9 +6975,9 @@
     AEMU_SCOPED_TRACE("vkAllocateCommandBuffers returnUnmarshal");
     VkResult vkAllocateCommandBuffers_VkResult_return = (VkResult)0;
     stream->read(&vkAllocateCommandBuffers_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAllocateCommandBuffers");;
     return vkAllocateCommandBuffers_VkResult_return;
 }
@@ -6869,7 +6988,7 @@
     uint32_t commandBufferCount,
     const VkCommandBuffer* pCommandBuffers)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkFreeCommandBuffers encode");
     mImpl->log("start vkFreeCommandBuffers");
     auto stream = mImpl->stream();
@@ -6943,6 +7062,9 @@
     {
         resources->destroyMapping()->mapHandles_VkCommandBuffer((VkCommandBuffer*)pCommandBuffers, ((commandBufferCount)));
     }
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkFreeCommandBuffers");;
 }
 
@@ -6950,7 +7072,7 @@
     VkCommandBuffer commandBuffer,
     const VkCommandBufferBeginInfo* pBeginInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBeginCommandBuffer encode");
     mImpl->log("start vkBeginCommandBuffer");
     auto stream = mImpl->stream();
@@ -6991,9 +7113,9 @@
     AEMU_SCOPED_TRACE("vkBeginCommandBuffer returnUnmarshal");
     VkResult vkBeginCommandBuffer_VkResult_return = (VkResult)0;
     stream->read(&vkBeginCommandBuffer_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBeginCommandBuffer");;
     return vkBeginCommandBuffer_VkResult_return;
 }
@@ -7001,7 +7123,7 @@
 VkResult VkEncoder::vkEndCommandBuffer(
     VkCommandBuffer commandBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEndCommandBuffer encode");
     mImpl->log("start vkEndCommandBuffer");
     auto stream = mImpl->stream();
@@ -7029,9 +7151,9 @@
     AEMU_SCOPED_TRACE("vkEndCommandBuffer returnUnmarshal");
     VkResult vkEndCommandBuffer_VkResult_return = (VkResult)0;
     stream->read(&vkEndCommandBuffer_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEndCommandBuffer");;
     return vkEndCommandBuffer_VkResult_return;
 }
@@ -7040,7 +7162,7 @@
     VkCommandBuffer commandBuffer,
     VkCommandBufferResetFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkResetCommandBuffer encode");
     mImpl->log("start vkResetCommandBuffer");
     auto stream = mImpl->stream();
@@ -7072,9 +7194,9 @@
     AEMU_SCOPED_TRACE("vkResetCommandBuffer returnUnmarshal");
     VkResult vkResetCommandBuffer_VkResult_return = (VkResult)0;
     stream->read(&vkResetCommandBuffer_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkResetCommandBuffer");;
     return vkResetCommandBuffer_VkResult_return;
 }
@@ -7084,7 +7206,7 @@
     VkPipelineBindPoint pipelineBindPoint,
     VkPipeline pipeline)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBindPipeline encode");
     mImpl->log("start vkCmdBindPipeline");
     auto stream = mImpl->stream();
@@ -7122,6 +7244,9 @@
     stream->write((uint64_t*)&cgen_var_508, 1 * 8);
     AEMU_SCOPED_TRACE("vkCmdBindPipeline readParams");
     AEMU_SCOPED_TRACE("vkCmdBindPipeline returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBindPipeline");;
 }
 
@@ -7131,7 +7256,7 @@
     uint32_t viewportCount,
     const VkViewport* pViewports)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetViewport encode");
     mImpl->log("start vkCmdSetViewport");
     auto stream = mImpl->stream();
@@ -7190,6 +7315,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdSetViewport readParams");
     AEMU_SCOPED_TRACE("vkCmdSetViewport returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetViewport");;
 }
 
@@ -7199,7 +7327,7 @@
     uint32_t scissorCount,
     const VkRect2D* pScissors)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetScissor encode");
     mImpl->log("start vkCmdSetScissor");
     auto stream = mImpl->stream();
@@ -7258,6 +7386,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdSetScissor readParams");
     AEMU_SCOPED_TRACE("vkCmdSetScissor returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetScissor");;
 }
 
@@ -7265,7 +7396,7 @@
     VkCommandBuffer commandBuffer,
     float lineWidth)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetLineWidth encode");
     mImpl->log("start vkCmdSetLineWidth");
     auto stream = mImpl->stream();
@@ -7295,6 +7426,9 @@
     stream->write((float*)&local_lineWidth, sizeof(float));
     AEMU_SCOPED_TRACE("vkCmdSetLineWidth readParams");
     AEMU_SCOPED_TRACE("vkCmdSetLineWidth returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetLineWidth");;
 }
 
@@ -7304,7 +7438,7 @@
     float depthBiasClamp,
     float depthBiasSlopeFactor)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetDepthBias encode");
     mImpl->log("start vkCmdSetDepthBias");
     auto stream = mImpl->stream();
@@ -7342,6 +7476,9 @@
     stream->write((float*)&local_depthBiasSlopeFactor, sizeof(float));
     AEMU_SCOPED_TRACE("vkCmdSetDepthBias readParams");
     AEMU_SCOPED_TRACE("vkCmdSetDepthBias returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetDepthBias");;
 }
 
@@ -7349,7 +7486,7 @@
     VkCommandBuffer commandBuffer,
     const float blendConstants[4])
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetBlendConstants encode");
     mImpl->log("start vkCmdSetBlendConstants");
     auto stream = mImpl->stream();
@@ -7379,6 +7516,9 @@
     stream->write((float*)local_blendConstants, 4 * sizeof(float));
     AEMU_SCOPED_TRACE("vkCmdSetBlendConstants readParams");
     AEMU_SCOPED_TRACE("vkCmdSetBlendConstants returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetBlendConstants");;
 }
 
@@ -7387,7 +7527,7 @@
     float minDepthBounds,
     float maxDepthBounds)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetDepthBounds encode");
     mImpl->log("start vkCmdSetDepthBounds");
     auto stream = mImpl->stream();
@@ -7421,6 +7561,9 @@
     stream->write((float*)&local_maxDepthBounds, sizeof(float));
     AEMU_SCOPED_TRACE("vkCmdSetDepthBounds readParams");
     AEMU_SCOPED_TRACE("vkCmdSetDepthBounds returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetDepthBounds");;
 }
 
@@ -7429,7 +7572,7 @@
     VkStencilFaceFlags faceMask,
     uint32_t compareMask)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetStencilCompareMask encode");
     mImpl->log("start vkCmdSetStencilCompareMask");
     auto stream = mImpl->stream();
@@ -7463,6 +7606,9 @@
     stream->write((uint32_t*)&local_compareMask, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdSetStencilCompareMask readParams");
     AEMU_SCOPED_TRACE("vkCmdSetStencilCompareMask returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetStencilCompareMask");;
 }
 
@@ -7471,7 +7617,7 @@
     VkStencilFaceFlags faceMask,
     uint32_t writeMask)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetStencilWriteMask encode");
     mImpl->log("start vkCmdSetStencilWriteMask");
     auto stream = mImpl->stream();
@@ -7505,6 +7651,9 @@
     stream->write((uint32_t*)&local_writeMask, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdSetStencilWriteMask readParams");
     AEMU_SCOPED_TRACE("vkCmdSetStencilWriteMask returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetStencilWriteMask");;
 }
 
@@ -7513,7 +7662,7 @@
     VkStencilFaceFlags faceMask,
     uint32_t reference)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetStencilReference encode");
     mImpl->log("start vkCmdSetStencilReference");
     auto stream = mImpl->stream();
@@ -7547,6 +7696,9 @@
     stream->write((uint32_t*)&local_reference, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdSetStencilReference readParams");
     AEMU_SCOPED_TRACE("vkCmdSetStencilReference returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetStencilReference");;
 }
 
@@ -7560,7 +7712,7 @@
     uint32_t dynamicOffsetCount,
     const uint32_t* pDynamicOffsets)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBindDescriptorSets encode");
     mImpl->log("start vkCmdBindDescriptorSets");
     auto stream = mImpl->stream();
@@ -7638,6 +7790,9 @@
     stream->write((uint32_t*)local_pDynamicOffsets, ((dynamicOffsetCount)) * sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdBindDescriptorSets readParams");
     AEMU_SCOPED_TRACE("vkCmdBindDescriptorSets returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBindDescriptorSets");;
 }
 
@@ -7647,7 +7802,7 @@
     VkDeviceSize offset,
     VkIndexType indexType)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBindIndexBuffer encode");
     mImpl->log("start vkCmdBindIndexBuffer");
     auto stream = mImpl->stream();
@@ -7689,6 +7844,9 @@
     stream->write((VkIndexType*)&local_indexType, sizeof(VkIndexType));
     AEMU_SCOPED_TRACE("vkCmdBindIndexBuffer readParams");
     AEMU_SCOPED_TRACE("vkCmdBindIndexBuffer returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBindIndexBuffer");;
 }
 
@@ -7699,7 +7857,7 @@
     const VkBuffer* pBuffers,
     const VkDeviceSize* pOffsets)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers encode");
     mImpl->log("start vkCmdBindVertexBuffers");
     auto stream = mImpl->stream();
@@ -7761,6 +7919,9 @@
     stream->write((VkDeviceSize*)local_pOffsets, ((bindingCount)) * sizeof(VkDeviceSize));
     AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers readParams");
     AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBindVertexBuffers");;
 }
 
@@ -7771,7 +7932,7 @@
     uint32_t firstVertex,
     uint32_t firstInstance)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDraw encode");
     mImpl->log("start vkCmdDraw");
     auto stream = mImpl->stream();
@@ -7813,6 +7974,9 @@
     stream->write((uint32_t*)&local_firstInstance, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDraw readParams");
     AEMU_SCOPED_TRACE("vkCmdDraw returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDraw");;
 }
 
@@ -7824,7 +7988,7 @@
     int32_t vertexOffset,
     uint32_t firstInstance)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndexed encode");
     mImpl->log("start vkCmdDrawIndexed");
     auto stream = mImpl->stream();
@@ -7870,6 +8034,9 @@
     stream->write((uint32_t*)&local_firstInstance, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndexed readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndexed returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndexed");;
 }
 
@@ -7880,7 +8047,7 @@
     uint32_t drawCount,
     uint32_t stride)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndirect encode");
     mImpl->log("start vkCmdDrawIndirect");
     auto stream = mImpl->stream();
@@ -7926,6 +8093,9 @@
     stream->write((uint32_t*)&local_stride, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndirect readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndirect returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndirect");;
 }
 
@@ -7936,7 +8106,7 @@
     uint32_t drawCount,
     uint32_t stride)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirect encode");
     mImpl->log("start vkCmdDrawIndexedIndirect");
     auto stream = mImpl->stream();
@@ -7982,6 +8152,9 @@
     stream->write((uint32_t*)&local_stride, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirect readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirect returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndexedIndirect");;
 }
 
@@ -7991,7 +8164,7 @@
     uint32_t groupCountY,
     uint32_t groupCountZ)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDispatch encode");
     mImpl->log("start vkCmdDispatch");
     auto stream = mImpl->stream();
@@ -8029,6 +8202,9 @@
     stream->write((uint32_t*)&local_groupCountZ, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDispatch readParams");
     AEMU_SCOPED_TRACE("vkCmdDispatch returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDispatch");;
 }
 
@@ -8037,7 +8213,7 @@
     VkBuffer buffer,
     VkDeviceSize offset)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDispatchIndirect encode");
     mImpl->log("start vkCmdDispatchIndirect");
     auto stream = mImpl->stream();
@@ -8075,6 +8251,9 @@
     stream->write((VkDeviceSize*)&local_offset, sizeof(VkDeviceSize));
     AEMU_SCOPED_TRACE("vkCmdDispatchIndirect readParams");
     AEMU_SCOPED_TRACE("vkCmdDispatchIndirect returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDispatchIndirect");;
 }
 
@@ -8085,7 +8264,7 @@
     uint32_t regionCount,
     const VkBufferCopy* pRegions)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdCopyBuffer encode");
     mImpl->log("start vkCmdCopyBuffer");
     auto stream = mImpl->stream();
@@ -8156,6 +8335,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdCopyBuffer readParams");
     AEMU_SCOPED_TRACE("vkCmdCopyBuffer returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdCopyBuffer");;
 }
 
@@ -8168,7 +8350,7 @@
     uint32_t regionCount,
     const VkImageCopy* pRegions)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdCopyImage encode");
     mImpl->log("start vkCmdCopyImage");
     auto stream = mImpl->stream();
@@ -8247,6 +8429,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdCopyImage readParams");
     AEMU_SCOPED_TRACE("vkCmdCopyImage returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdCopyImage");;
 }
 
@@ -8260,7 +8445,7 @@
     const VkImageBlit* pRegions,
     VkFilter filter)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBlitImage encode");
     mImpl->log("start vkCmdBlitImage");
     auto stream = mImpl->stream();
@@ -8343,6 +8528,9 @@
     stream->write((VkFilter*)&local_filter, sizeof(VkFilter));
     AEMU_SCOPED_TRACE("vkCmdBlitImage readParams");
     AEMU_SCOPED_TRACE("vkCmdBlitImage returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBlitImage");;
 }
 
@@ -8354,7 +8542,7 @@
     uint32_t regionCount,
     const VkBufferImageCopy* pRegions)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage encode");
     mImpl->log("start vkCmdCopyBufferToImage");
     auto stream = mImpl->stream();
@@ -8429,6 +8617,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage readParams");
     AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdCopyBufferToImage");;
 }
 
@@ -8440,7 +8631,7 @@
     uint32_t regionCount,
     const VkBufferImageCopy* pRegions)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer encode");
     mImpl->log("start vkCmdCopyImageToBuffer");
     auto stream = mImpl->stream();
@@ -8515,6 +8706,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer readParams");
     AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdCopyImageToBuffer");;
 }
 
@@ -8525,7 +8719,7 @@
     VkDeviceSize dataSize,
     const void* pData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdUpdateBuffer encode");
     mImpl->log("start vkCmdUpdateBuffer");
     auto stream = mImpl->stream();
@@ -8575,6 +8769,9 @@
     stream->write((void*)local_pData, ((dataSize)) * sizeof(uint8_t));
     AEMU_SCOPED_TRACE("vkCmdUpdateBuffer readParams");
     AEMU_SCOPED_TRACE("vkCmdUpdateBuffer returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdUpdateBuffer");;
 }
 
@@ -8585,7 +8782,7 @@
     VkDeviceSize size,
     uint32_t data)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdFillBuffer encode");
     mImpl->log("start vkCmdFillBuffer");
     auto stream = mImpl->stream();
@@ -8631,6 +8828,9 @@
     stream->write((uint32_t*)&local_data, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdFillBuffer readParams");
     AEMU_SCOPED_TRACE("vkCmdFillBuffer returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdFillBuffer");;
 }
 
@@ -8642,7 +8842,7 @@
     uint32_t rangeCount,
     const VkImageSubresourceRange* pRanges)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdClearColorImage encode");
     mImpl->log("start vkCmdClearColorImage");
     auto stream = mImpl->stream();
@@ -8722,6 +8922,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdClearColorImage readParams");
     AEMU_SCOPED_TRACE("vkCmdClearColorImage returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdClearColorImage");;
 }
 
@@ -8733,7 +8936,7 @@
     uint32_t rangeCount,
     const VkImageSubresourceRange* pRanges)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdClearDepthStencilImage encode");
     mImpl->log("start vkCmdClearDepthStencilImage");
     auto stream = mImpl->stream();
@@ -8813,6 +9016,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdClearDepthStencilImage readParams");
     AEMU_SCOPED_TRACE("vkCmdClearDepthStencilImage returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdClearDepthStencilImage");;
 }
 
@@ -8823,7 +9029,7 @@
     uint32_t rectCount,
     const VkClearRect* pRects)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdClearAttachments encode");
     mImpl->log("start vkCmdClearAttachments");
     auto stream = mImpl->stream();
@@ -8907,6 +9113,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdClearAttachments readParams");
     AEMU_SCOPED_TRACE("vkCmdClearAttachments returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdClearAttachments");;
 }
 
@@ -8919,7 +9128,7 @@
     uint32_t regionCount,
     const VkImageResolve* pRegions)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdResolveImage encode");
     mImpl->log("start vkCmdResolveImage");
     auto stream = mImpl->stream();
@@ -8998,6 +9207,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdResolveImage readParams");
     AEMU_SCOPED_TRACE("vkCmdResolveImage returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdResolveImage");;
 }
 
@@ -9006,7 +9218,7 @@
     VkEvent event,
     VkPipelineStageFlags stageMask)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetEvent encode");
     mImpl->log("start vkCmdSetEvent");
     auto stream = mImpl->stream();
@@ -9044,6 +9256,9 @@
     stream->write((VkPipelineStageFlags*)&local_stageMask, sizeof(VkPipelineStageFlags));
     AEMU_SCOPED_TRACE("vkCmdSetEvent readParams");
     AEMU_SCOPED_TRACE("vkCmdSetEvent returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetEvent");;
 }
 
@@ -9052,7 +9267,7 @@
     VkEvent event,
     VkPipelineStageFlags stageMask)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdResetEvent encode");
     mImpl->log("start vkCmdResetEvent");
     auto stream = mImpl->stream();
@@ -9090,6 +9305,9 @@
     stream->write((VkPipelineStageFlags*)&local_stageMask, sizeof(VkPipelineStageFlags));
     AEMU_SCOPED_TRACE("vkCmdResetEvent readParams");
     AEMU_SCOPED_TRACE("vkCmdResetEvent returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdResetEvent");;
 }
 
@@ -9106,7 +9324,7 @@
     uint32_t imageMemoryBarrierCount,
     const VkImageMemoryBarrier* pImageMemoryBarriers)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdWaitEvents encode");
     mImpl->log("start vkCmdWaitEvents");
     auto stream = mImpl->stream();
@@ -9251,6 +9469,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdWaitEvents readParams");
     AEMU_SCOPED_TRACE("vkCmdWaitEvents returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdWaitEvents");;
 }
 
@@ -9266,7 +9487,7 @@
     uint32_t imageMemoryBarrierCount,
     const VkImageMemoryBarrier* pImageMemoryBarriers)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdPipelineBarrier encode");
     mImpl->log("start vkCmdPipelineBarrier");
     auto stream = mImpl->stream();
@@ -9391,6 +9612,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdPipelineBarrier readParams");
     AEMU_SCOPED_TRACE("vkCmdPipelineBarrier returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdPipelineBarrier");;
 }
 
@@ -9400,7 +9624,7 @@
     uint32_t query,
     VkQueryControlFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBeginQuery encode");
     mImpl->log("start vkCmdBeginQuery");
     auto stream = mImpl->stream();
@@ -9442,6 +9666,9 @@
     stream->write((VkQueryControlFlags*)&local_flags, sizeof(VkQueryControlFlags));
     AEMU_SCOPED_TRACE("vkCmdBeginQuery readParams");
     AEMU_SCOPED_TRACE("vkCmdBeginQuery returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBeginQuery");;
 }
 
@@ -9450,7 +9677,7 @@
     VkQueryPool queryPool,
     uint32_t query)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdEndQuery encode");
     mImpl->log("start vkCmdEndQuery");
     auto stream = mImpl->stream();
@@ -9488,6 +9715,9 @@
     stream->write((uint32_t*)&local_query, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdEndQuery readParams");
     AEMU_SCOPED_TRACE("vkCmdEndQuery returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdEndQuery");;
 }
 
@@ -9497,7 +9727,7 @@
     uint32_t firstQuery,
     uint32_t queryCount)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdResetQueryPool encode");
     mImpl->log("start vkCmdResetQueryPool");
     auto stream = mImpl->stream();
@@ -9539,6 +9769,9 @@
     stream->write((uint32_t*)&local_queryCount, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdResetQueryPool readParams");
     AEMU_SCOPED_TRACE("vkCmdResetQueryPool returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdResetQueryPool");;
 }
 
@@ -9548,7 +9781,7 @@
     VkQueryPool queryPool,
     uint32_t query)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdWriteTimestamp encode");
     mImpl->log("start vkCmdWriteTimestamp");
     auto stream = mImpl->stream();
@@ -9590,6 +9823,9 @@
     stream->write((uint32_t*)&local_query, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdWriteTimestamp readParams");
     AEMU_SCOPED_TRACE("vkCmdWriteTimestamp returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdWriteTimestamp");;
 }
 
@@ -9603,7 +9839,7 @@
     VkDeviceSize stride,
     VkQueryResultFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdCopyQueryPoolResults encode");
     mImpl->log("start vkCmdCopyQueryPoolResults");
     auto stream = mImpl->stream();
@@ -9665,6 +9901,9 @@
     stream->write((VkQueryResultFlags*)&local_flags, sizeof(VkQueryResultFlags));
     AEMU_SCOPED_TRACE("vkCmdCopyQueryPoolResults readParams");
     AEMU_SCOPED_TRACE("vkCmdCopyQueryPoolResults returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdCopyQueryPoolResults");;
 }
 
@@ -9676,7 +9915,7 @@
     uint32_t size,
     const void* pValues)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdPushConstants encode");
     mImpl->log("start vkCmdPushConstants");
     auto stream = mImpl->stream();
@@ -9730,6 +9969,9 @@
     stream->write((void*)local_pValues, ((size)) * sizeof(uint8_t));
     AEMU_SCOPED_TRACE("vkCmdPushConstants readParams");
     AEMU_SCOPED_TRACE("vkCmdPushConstants returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdPushConstants");;
 }
 
@@ -9738,7 +9980,7 @@
     const VkRenderPassBeginInfo* pRenderPassBegin,
     VkSubpassContents contents)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass encode");
     mImpl->log("start vkCmdBeginRenderPass");
     auto stream = mImpl->stream();
@@ -9781,6 +10023,9 @@
     stream->write((VkSubpassContents*)&local_contents, sizeof(VkSubpassContents));
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass readParams");
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBeginRenderPass");;
 }
 
@@ -9788,7 +10033,7 @@
     VkCommandBuffer commandBuffer,
     VkSubpassContents contents)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdNextSubpass encode");
     mImpl->log("start vkCmdNextSubpass");
     auto stream = mImpl->stream();
@@ -9818,13 +10063,16 @@
     stream->write((VkSubpassContents*)&local_contents, sizeof(VkSubpassContents));
     AEMU_SCOPED_TRACE("vkCmdNextSubpass readParams");
     AEMU_SCOPED_TRACE("vkCmdNextSubpass returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdNextSubpass");;
 }
 
 void VkEncoder::vkCmdEndRenderPass(
     VkCommandBuffer commandBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass encode");
     mImpl->log("start vkCmdEndRenderPass");
     auto stream = mImpl->stream();
@@ -9850,6 +10098,9 @@
     stream->write((uint64_t*)&cgen_var_658, 1 * 8);
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass readParams");
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdEndRenderPass");;
 }
 
@@ -9858,7 +10109,7 @@
     uint32_t commandBufferCount,
     const VkCommandBuffer* pCommandBuffers)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdExecuteCommands encode");
     mImpl->log("start vkCmdExecuteCommands");
     auto stream = mImpl->stream();
@@ -9908,6 +10159,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdExecuteCommands readParams");
     AEMU_SCOPED_TRACE("vkCmdExecuteCommands returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdExecuteCommands");;
 }
 
@@ -9916,7 +10170,7 @@
 VkResult VkEncoder::vkEnumerateInstanceVersion(
     uint32_t* pApiVersion)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumerateInstanceVersion encode");
     mImpl->log("start vkEnumerateInstanceVersion");
     auto stream = mImpl->stream();
@@ -9939,9 +10193,9 @@
     AEMU_SCOPED_TRACE("vkEnumerateInstanceVersion returnUnmarshal");
     VkResult vkEnumerateInstanceVersion_VkResult_return = (VkResult)0;
     stream->read(&vkEnumerateInstanceVersion_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumerateInstanceVersion");;
     return vkEnumerateInstanceVersion_VkResult_return;
 }
@@ -9951,7 +10205,7 @@
     uint32_t bindInfoCount,
     const VkBindBufferMemoryInfo* pBindInfos)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBindBufferMemory2 encode");
     mImpl->log("start vkBindBufferMemory2");
     auto stream = mImpl->stream();
@@ -10008,9 +10262,9 @@
     AEMU_SCOPED_TRACE("vkBindBufferMemory2 returnUnmarshal");
     VkResult vkBindBufferMemory2_VkResult_return = (VkResult)0;
     stream->read(&vkBindBufferMemory2_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBindBufferMemory2");;
     return vkBindBufferMemory2_VkResult_return;
 }
@@ -10020,7 +10274,7 @@
     uint32_t bindInfoCount,
     const VkBindImageMemoryInfo* pBindInfos)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBindImageMemory2 encode");
     mImpl->log("start vkBindImageMemory2");
     auto stream = mImpl->stream();
@@ -10077,9 +10331,9 @@
     AEMU_SCOPED_TRACE("vkBindImageMemory2 returnUnmarshal");
     VkResult vkBindImageMemory2_VkResult_return = (VkResult)0;
     stream->read(&vkBindImageMemory2_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBindImageMemory2");;
     return vkBindImageMemory2_VkResult_return;
 }
@@ -10091,7 +10345,7 @@
     uint32_t remoteDeviceIndex,
     VkPeerMemoryFeatureFlags* pPeerMemoryFeatures)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeatures encode");
     mImpl->log("start vkGetDeviceGroupPeerMemoryFeatures");
     auto stream = mImpl->stream();
@@ -10132,6 +10386,9 @@
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeatures readParams");
     stream->read((VkPeerMemoryFeatureFlags*)pPeerMemoryFeatures, sizeof(VkPeerMemoryFeatureFlags));
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeatures returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDeviceGroupPeerMemoryFeatures");;
 }
 
@@ -10139,7 +10396,7 @@
     VkCommandBuffer commandBuffer,
     uint32_t deviceMask)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMask encode");
     mImpl->log("start vkCmdSetDeviceMask");
     auto stream = mImpl->stream();
@@ -10169,6 +10426,9 @@
     stream->write((uint32_t*)&local_deviceMask, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMask readParams");
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMask returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetDeviceMask");;
 }
 
@@ -10181,7 +10441,7 @@
     uint32_t groupCountY,
     uint32_t groupCountZ)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDispatchBase encode");
     mImpl->log("start vkCmdDispatchBase");
     auto stream = mImpl->stream();
@@ -10231,6 +10491,9 @@
     stream->write((uint32_t*)&local_groupCountZ, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDispatchBase readParams");
     AEMU_SCOPED_TRACE("vkCmdDispatchBase returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDispatchBase");;
 }
 
@@ -10239,7 +10502,7 @@
     uint32_t* pPhysicalDeviceGroupCount,
     VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumeratePhysicalDeviceGroups encode");
     mImpl->log("start vkEnumeratePhysicalDeviceGroups");
     auto stream = mImpl->stream();
@@ -10333,9 +10596,9 @@
     AEMU_SCOPED_TRACE("vkEnumeratePhysicalDeviceGroups returnUnmarshal");
     VkResult vkEnumeratePhysicalDeviceGroups_VkResult_return = (VkResult)0;
     stream->read(&vkEnumeratePhysicalDeviceGroups_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumeratePhysicalDeviceGroups");;
     return vkEnumeratePhysicalDeviceGroups_VkResult_return;
 }
@@ -10345,7 +10608,7 @@
     const VkImageMemoryRequirementsInfo2* pInfo,
     VkMemoryRequirements2* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements2 encode");
     mImpl->log("start vkGetImageMemoryRequirements2");
     auto stream = mImpl->stream();
@@ -10391,6 +10654,9 @@
         transform_fromhost_VkMemoryRequirements2(mImpl->resources(), (VkMemoryRequirements2*)(pMemoryRequirements));
     }
     AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageMemoryRequirements2");;
 }
 
@@ -10399,7 +10665,7 @@
     const VkBufferMemoryRequirementsInfo2* pInfo,
     VkMemoryRequirements2* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements2 encode");
     mImpl->log("start vkGetBufferMemoryRequirements2");
     auto stream = mImpl->stream();
@@ -10445,6 +10711,9 @@
         transform_fromhost_VkMemoryRequirements2(mImpl->resources(), (VkMemoryRequirements2*)(pMemoryRequirements));
     }
     AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetBufferMemoryRequirements2");;
 }
 
@@ -10454,7 +10723,7 @@
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements2 encode");
     mImpl->log("start vkGetImageSparseMemoryRequirements2");
     auto stream = mImpl->stream();
@@ -10559,6 +10828,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageSparseMemoryRequirements2");;
 }
 
@@ -10566,7 +10838,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceFeatures2* pFeatures)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures2 encode");
     mImpl->log("start vkGetPhysicalDeviceFeatures2");
     auto stream = mImpl->stream();
@@ -10599,6 +10871,9 @@
         transform_fromhost_VkPhysicalDeviceFeatures2(mImpl->resources(), (VkPhysicalDeviceFeatures2*)(pFeatures));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceFeatures2");;
 }
 
@@ -10606,7 +10881,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceProperties2* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties2 encode");
     mImpl->log("start vkGetPhysicalDeviceProperties2");
     auto stream = mImpl->stream();
@@ -10639,9 +10914,10 @@
         transform_fromhost_VkPhysicalDeviceProperties2(mImpl->resources(), (VkPhysicalDeviceProperties2*)(pProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties2 returnUnmarshal");
-    encoderLock.unlock();
     mImpl->resources()->on_vkGetPhysicalDeviceProperties2(this, physicalDevice, pProperties);
-    encoderLock.lock();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceProperties2");;
 }
 
@@ -10650,7 +10926,7 @@
     VkFormat format,
     VkFormatProperties2* pFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties2 encode");
     mImpl->log("start vkGetPhysicalDeviceFormatProperties2");
     auto stream = mImpl->stream();
@@ -10687,6 +10963,9 @@
         transform_fromhost_VkFormatProperties2(mImpl->resources(), (VkFormatProperties2*)(pFormatProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceFormatProperties2");;
 }
 
@@ -10695,7 +10974,7 @@
     const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
     VkImageFormatProperties2* pImageFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties2 encode");
     mImpl->log("start vkGetPhysicalDeviceImageFormatProperties2");
     auto stream = mImpl->stream();
@@ -10743,9 +11022,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties2 returnUnmarshal");
     VkResult vkGetPhysicalDeviceImageFormatProperties2_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceImageFormatProperties2_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceImageFormatProperties2");;
     return vkGetPhysicalDeviceImageFormatProperties2_VkResult_return;
 }
@@ -10755,7 +11034,7 @@
     uint32_t* pQueueFamilyPropertyCount,
     VkQueueFamilyProperties2* pQueueFamilyProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties2 encode");
     mImpl->log("start vkGetPhysicalDeviceQueueFamilyProperties2");
     auto stream = mImpl->stream();
@@ -10847,6 +11126,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceQueueFamilyProperties2");;
 }
 
@@ -10854,7 +11136,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceMemoryProperties2* pMemoryProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties2 encode");
     mImpl->log("start vkGetPhysicalDeviceMemoryProperties2");
     auto stream = mImpl->stream();
@@ -10887,9 +11169,10 @@
         transform_fromhost_VkPhysicalDeviceMemoryProperties2(mImpl->resources(), (VkPhysicalDeviceMemoryProperties2*)(pMemoryProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties2 returnUnmarshal");
-    encoderLock.unlock();
     mImpl->resources()->on_vkGetPhysicalDeviceMemoryProperties2(this, physicalDevice, pMemoryProperties);
-    encoderLock.lock();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceMemoryProperties2");;
 }
 
@@ -10899,7 +11182,7 @@
     uint32_t* pPropertyCount,
     VkSparseImageFormatProperties2* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties2 encode");
     mImpl->log("start vkGetPhysicalDeviceSparseImageFormatProperties2");
     auto stream = mImpl->stream();
@@ -11004,6 +11287,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceSparseImageFormatProperties2");;
 }
 
@@ -11012,7 +11298,7 @@
     VkCommandPool commandPool,
     VkCommandPoolTrimFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkTrimCommandPool encode");
     mImpl->log("start vkTrimCommandPool");
     auto stream = mImpl->stream();
@@ -11050,6 +11336,9 @@
     stream->write((VkCommandPoolTrimFlags*)&local_flags, sizeof(VkCommandPoolTrimFlags));
     AEMU_SCOPED_TRACE("vkTrimCommandPool readParams");
     AEMU_SCOPED_TRACE("vkTrimCommandPool returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkTrimCommandPool");;
 }
 
@@ -11058,7 +11347,7 @@
     const VkDeviceQueueInfo2* pQueueInfo,
     VkQueue* pQueue)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceQueue2 encode");
     mImpl->log("start vkGetDeviceQueue2");
     auto stream = mImpl->stream();
@@ -11108,6 +11397,9 @@
     stream->read((uint64_t*)&cgen_var_727, 8);
     stream->handleMapping()->mapHandles_u64_VkQueue(&cgen_var_727, (VkQueue*)pQueue, 1);
     AEMU_SCOPED_TRACE("vkGetDeviceQueue2 returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDeviceQueue2");;
 }
 
@@ -11117,7 +11409,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSamplerYcbcrConversion* pYcbcrConversion)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversion encode");
     mImpl->log("start vkCreateSamplerYcbcrConversion");
     auto stream = mImpl->stream();
@@ -11197,9 +11489,9 @@
     AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversion returnUnmarshal");
     VkResult vkCreateSamplerYcbcrConversion_VkResult_return = (VkResult)0;
     stream->read(&vkCreateSamplerYcbcrConversion_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateSamplerYcbcrConversion");;
     return vkCreateSamplerYcbcrConversion_VkResult_return;
 }
@@ -11209,7 +11501,7 @@
     VkSamplerYcbcrConversion ycbcrConversion,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversion encode");
     mImpl->log("start vkDestroySamplerYcbcrConversion");
     auto stream = mImpl->stream();
@@ -11270,6 +11562,9 @@
     AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversion readParams");
     AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversion returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkSamplerYcbcrConversion((VkSamplerYcbcrConversion*)&ycbcrConversion);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroySamplerYcbcrConversion");;
 }
 
@@ -11279,7 +11574,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDescriptorUpdateTemplate encode");
     mImpl->log("start vkCreateDescriptorUpdateTemplate");
     auto stream = mImpl->stream();
@@ -11359,12 +11654,10 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorUpdateTemplate returnUnmarshal");
     VkResult vkCreateDescriptorUpdateTemplate_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDescriptorUpdateTemplate_VkResult_return, sizeof(VkResult));
+    mImpl->resources()->on_vkCreateDescriptorUpdateTemplate(this, vkCreateDescriptorUpdateTemplate_VkResult_return, device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
-    encoderLock.unlock();
-    mImpl->resources()->on_vkCreateDescriptorUpdateTemplate(this, vkCreateDescriptorUpdateTemplate_VkResult_return, device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
-    encoderLock.lock();
     mImpl->log("finish vkCreateDescriptorUpdateTemplate");;
     return vkCreateDescriptorUpdateTemplate_VkResult_return;
 }
@@ -11374,7 +11667,7 @@
     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplate encode");
     mImpl->log("start vkDestroyDescriptorUpdateTemplate");
     auto stream = mImpl->stream();
@@ -11435,6 +11728,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplate readParams");
     AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplate returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDescriptorUpdateTemplate((VkDescriptorUpdateTemplate*)&descriptorUpdateTemplate);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDescriptorUpdateTemplate");;
 }
 
@@ -11444,7 +11740,7 @@
     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
     const void* pData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplate encode");
     mImpl->log("start vkUpdateDescriptorSetWithTemplate");
     auto stream = mImpl->stream();
@@ -11506,6 +11802,9 @@
     }
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplate readParams");
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplate returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkUpdateDescriptorSetWithTemplate");;
 }
 
@@ -11514,7 +11813,7 @@
     const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
     VkExternalBufferProperties* pExternalBufferProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalBufferProperties encode");
     mImpl->log("start vkGetPhysicalDeviceExternalBufferProperties");
     auto stream = mImpl->stream();
@@ -11562,6 +11861,9 @@
         transform_fromhost_VkExternalBufferProperties(mImpl->resources(), (VkExternalBufferProperties*)(pExternalBufferProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalBufferProperties returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceExternalBufferProperties");;
 }
 
@@ -11570,7 +11872,7 @@
     const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
     VkExternalFenceProperties* pExternalFenceProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalFenceProperties encode");
     mImpl->log("start vkGetPhysicalDeviceExternalFenceProperties");
     auto stream = mImpl->stream();
@@ -11616,6 +11918,9 @@
         transform_fromhost_VkExternalFenceProperties(mImpl->resources(), (VkExternalFenceProperties*)(pExternalFenceProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalFenceProperties returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceExternalFenceProperties");;
 }
 
@@ -11624,7 +11929,7 @@
     const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
     VkExternalSemaphoreProperties* pExternalSemaphoreProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalSemaphoreProperties encode");
     mImpl->log("start vkGetPhysicalDeviceExternalSemaphoreProperties");
     auto stream = mImpl->stream();
@@ -11670,6 +11975,9 @@
         transform_fromhost_VkExternalSemaphoreProperties(mImpl->resources(), (VkExternalSemaphoreProperties*)(pExternalSemaphoreProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalSemaphoreProperties returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceExternalSemaphoreProperties");;
 }
 
@@ -11678,7 +11986,7 @@
     const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
     VkDescriptorSetLayoutSupport* pSupport)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDescriptorSetLayoutSupport encode");
     mImpl->log("start vkGetDescriptorSetLayoutSupport");
     auto stream = mImpl->stream();
@@ -11724,6 +12032,9 @@
         transform_fromhost_VkDescriptorSetLayoutSupport(mImpl->resources(), (VkDescriptorSetLayoutSupport*)(pSupport));
     }
     AEMU_SCOPED_TRACE("vkGetDescriptorSetLayoutSupport returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDescriptorSetLayoutSupport");;
 }
 
@@ -11734,7 +12045,7 @@
     VkSurfaceKHR surface,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroySurfaceKHR encode");
     mImpl->log("start vkDestroySurfaceKHR");
     auto stream = mImpl->stream();
@@ -11795,6 +12106,9 @@
     AEMU_SCOPED_TRACE("vkDestroySurfaceKHR readParams");
     AEMU_SCOPED_TRACE("vkDestroySurfaceKHR returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkSurfaceKHR((VkSurfaceKHR*)&surface);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroySurfaceKHR");;
 }
 
@@ -11804,7 +12118,7 @@
     VkSurfaceKHR surface,
     VkBool32* pSupported)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceSupportKHR encode");
     mImpl->log("start vkGetPhysicalDeviceSurfaceSupportKHR");
     auto stream = mImpl->stream();
@@ -11847,9 +12161,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceSupportKHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfaceSupportKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfaceSupportKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfaceSupportKHR");;
     return vkGetPhysicalDeviceSurfaceSupportKHR_VkResult_return;
 }
@@ -11859,7 +12173,7 @@
     VkSurfaceKHR surface,
     VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
     auto stream = mImpl->stream();
@@ -11902,9 +12216,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceCapabilitiesKHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfaceCapabilitiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfaceCapabilitiesKHR");;
     return vkGetPhysicalDeviceSurfaceCapabilitiesKHR_VkResult_return;
 }
@@ -11915,7 +12229,7 @@
     uint32_t* pSurfaceFormatCount,
     VkSurfaceFormatKHR* pSurfaceFormats)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceFormatsKHR encode");
     mImpl->log("start vkGetPhysicalDeviceSurfaceFormatsKHR");
     auto stream = mImpl->stream();
@@ -12017,9 +12331,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceFormatsKHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfaceFormatsKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfaceFormatsKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfaceFormatsKHR");;
     return vkGetPhysicalDeviceSurfaceFormatsKHR_VkResult_return;
 }
@@ -12030,7 +12344,7 @@
     uint32_t* pPresentModeCount,
     VkPresentModeKHR* pPresentModes)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfacePresentModesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceSurfacePresentModesKHR");
     auto stream = mImpl->stream();
@@ -12116,9 +12430,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfacePresentModesKHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfacePresentModesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfacePresentModesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfacePresentModesKHR");;
     return vkGetPhysicalDeviceSurfacePresentModesKHR_VkResult_return;
 }
@@ -12131,7 +12445,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSwapchainKHR* pSwapchain)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateSwapchainKHR encode");
     mImpl->log("start vkCreateSwapchainKHR");
     auto stream = mImpl->stream();
@@ -12211,9 +12525,9 @@
     AEMU_SCOPED_TRACE("vkCreateSwapchainKHR returnUnmarshal");
     VkResult vkCreateSwapchainKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateSwapchainKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateSwapchainKHR");;
     return vkCreateSwapchainKHR_VkResult_return;
 }
@@ -12223,7 +12537,7 @@
     VkSwapchainKHR swapchain,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroySwapchainKHR encode");
     mImpl->log("start vkDestroySwapchainKHR");
     auto stream = mImpl->stream();
@@ -12284,6 +12598,9 @@
     AEMU_SCOPED_TRACE("vkDestroySwapchainKHR readParams");
     AEMU_SCOPED_TRACE("vkDestroySwapchainKHR returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkSwapchainKHR((VkSwapchainKHR*)&swapchain);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroySwapchainKHR");;
 }
 
@@ -12293,7 +12610,7 @@
     uint32_t* pSwapchainImageCount,
     VkImage* pSwapchainImages)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetSwapchainImagesKHR encode");
     mImpl->log("start vkGetSwapchainImagesKHR");
     auto stream = mImpl->stream();
@@ -12399,9 +12716,9 @@
     AEMU_SCOPED_TRACE("vkGetSwapchainImagesKHR returnUnmarshal");
     VkResult vkGetSwapchainImagesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetSwapchainImagesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetSwapchainImagesKHR");;
     return vkGetSwapchainImagesKHR_VkResult_return;
 }
@@ -12414,7 +12731,7 @@
     VkFence fence,
     uint32_t* pImageIndex)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAcquireNextImageKHR encode");
     mImpl->log("start vkAcquireNextImageKHR");
     auto stream = mImpl->stream();
@@ -12473,9 +12790,9 @@
     AEMU_SCOPED_TRACE("vkAcquireNextImageKHR returnUnmarshal");
     VkResult vkAcquireNextImageKHR_VkResult_return = (VkResult)0;
     stream->read(&vkAcquireNextImageKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAcquireNextImageKHR");;
     return vkAcquireNextImageKHR_VkResult_return;
 }
@@ -12484,7 +12801,7 @@
     VkQueue queue,
     const VkPresentInfoKHR* pPresentInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueuePresentKHR encode");
     mImpl->log("start vkQueuePresentKHR");
     auto stream = mImpl->stream();
@@ -12525,9 +12842,9 @@
     AEMU_SCOPED_TRACE("vkQueuePresentKHR returnUnmarshal");
     VkResult vkQueuePresentKHR_VkResult_return = (VkResult)0;
     stream->read(&vkQueuePresentKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkQueuePresentKHR");;
     return vkQueuePresentKHR_VkResult_return;
 }
@@ -12536,7 +12853,7 @@
     VkDevice device,
     VkDeviceGroupPresentCapabilitiesKHR* pDeviceGroupPresentCapabilities)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPresentCapabilitiesKHR encode");
     mImpl->log("start vkGetDeviceGroupPresentCapabilitiesKHR");
     auto stream = mImpl->stream();
@@ -12571,9 +12888,9 @@
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPresentCapabilitiesKHR returnUnmarshal");
     VkResult vkGetDeviceGroupPresentCapabilitiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDeviceGroupPresentCapabilitiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDeviceGroupPresentCapabilitiesKHR");;
     return vkGetDeviceGroupPresentCapabilitiesKHR_VkResult_return;
 }
@@ -12583,7 +12900,7 @@
     VkSurfaceKHR surface,
     VkDeviceGroupPresentModeFlagsKHR* pModes)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceGroupSurfacePresentModesKHR encode");
     mImpl->log("start vkGetDeviceGroupSurfacePresentModesKHR");
     auto stream = mImpl->stream();
@@ -12644,9 +12961,9 @@
     AEMU_SCOPED_TRACE("vkGetDeviceGroupSurfacePresentModesKHR returnUnmarshal");
     VkResult vkGetDeviceGroupSurfacePresentModesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDeviceGroupSurfacePresentModesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDeviceGroupSurfacePresentModesKHR");;
     return vkGetDeviceGroupSurfacePresentModesKHR_VkResult_return;
 }
@@ -12657,7 +12974,7 @@
     uint32_t* pRectCount,
     VkRect2D* pRects)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDevicePresentRectanglesKHR encode");
     mImpl->log("start vkGetPhysicalDevicePresentRectanglesKHR");
     auto stream = mImpl->stream();
@@ -12759,9 +13076,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDevicePresentRectanglesKHR returnUnmarshal");
     VkResult vkGetPhysicalDevicePresentRectanglesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDevicePresentRectanglesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDevicePresentRectanglesKHR");;
     return vkGetPhysicalDevicePresentRectanglesKHR_VkResult_return;
 }
@@ -12771,7 +13088,7 @@
     const VkAcquireNextImageInfoKHR* pAcquireInfo,
     uint32_t* pImageIndex)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAcquireNextImage2KHR encode");
     mImpl->log("start vkAcquireNextImage2KHR");
     auto stream = mImpl->stream();
@@ -12815,9 +13132,9 @@
     AEMU_SCOPED_TRACE("vkAcquireNextImage2KHR returnUnmarshal");
     VkResult vkAcquireNextImage2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkAcquireNextImage2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAcquireNextImage2KHR");;
     return vkAcquireNextImage2KHR_VkResult_return;
 }
@@ -12829,7 +13146,7 @@
     uint32_t* pPropertyCount,
     VkDisplayPropertiesKHR* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayPropertiesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceDisplayPropertiesKHR");
     auto stream = mImpl->stream();
@@ -12923,9 +13240,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayPropertiesKHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceDisplayPropertiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceDisplayPropertiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceDisplayPropertiesKHR");;
     return vkGetPhysicalDeviceDisplayPropertiesKHR_VkResult_return;
 }
@@ -12935,7 +13252,7 @@
     uint32_t* pPropertyCount,
     VkDisplayPlanePropertiesKHR* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayPlanePropertiesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
     auto stream = mImpl->stream();
@@ -13029,9 +13346,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayPlanePropertiesKHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceDisplayPlanePropertiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceDisplayPlanePropertiesKHR");;
     return vkGetPhysicalDeviceDisplayPlanePropertiesKHR_VkResult_return;
 }
@@ -13042,7 +13359,7 @@
     uint32_t* pDisplayCount,
     VkDisplayKHR* pDisplays)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDisplayPlaneSupportedDisplaysKHR encode");
     mImpl->log("start vkGetDisplayPlaneSupportedDisplaysKHR");
     auto stream = mImpl->stream();
@@ -13144,9 +13461,9 @@
     AEMU_SCOPED_TRACE("vkGetDisplayPlaneSupportedDisplaysKHR returnUnmarshal");
     VkResult vkGetDisplayPlaneSupportedDisplaysKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDisplayPlaneSupportedDisplaysKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDisplayPlaneSupportedDisplaysKHR");;
     return vkGetDisplayPlaneSupportedDisplaysKHR_VkResult_return;
 }
@@ -13157,7 +13474,7 @@
     uint32_t* pPropertyCount,
     VkDisplayModePropertiesKHR* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDisplayModePropertiesKHR encode");
     mImpl->log("start vkGetDisplayModePropertiesKHR");
     auto stream = mImpl->stream();
@@ -13259,9 +13576,9 @@
     AEMU_SCOPED_TRACE("vkGetDisplayModePropertiesKHR returnUnmarshal");
     VkResult vkGetDisplayModePropertiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDisplayModePropertiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDisplayModePropertiesKHR");;
     return vkGetDisplayModePropertiesKHR_VkResult_return;
 }
@@ -13273,7 +13590,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDisplayModeKHR* pMode)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDisplayModeKHR encode");
     mImpl->log("start vkCreateDisplayModeKHR");
     auto stream = mImpl->stream();
@@ -13361,9 +13678,9 @@
     AEMU_SCOPED_TRACE("vkCreateDisplayModeKHR returnUnmarshal");
     VkResult vkCreateDisplayModeKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDisplayModeKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateDisplayModeKHR");;
     return vkCreateDisplayModeKHR_VkResult_return;
 }
@@ -13374,7 +13691,7 @@
     uint32_t planeIndex,
     VkDisplayPlaneCapabilitiesKHR* pCapabilities)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDisplayPlaneCapabilitiesKHR encode");
     mImpl->log("start vkGetDisplayPlaneCapabilitiesKHR");
     auto stream = mImpl->stream();
@@ -13421,9 +13738,9 @@
     AEMU_SCOPED_TRACE("vkGetDisplayPlaneCapabilitiesKHR returnUnmarshal");
     VkResult vkGetDisplayPlaneCapabilitiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDisplayPlaneCapabilitiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDisplayPlaneCapabilitiesKHR");;
     return vkGetDisplayPlaneCapabilitiesKHR_VkResult_return;
 }
@@ -13434,7 +13751,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDisplayPlaneSurfaceKHR encode");
     mImpl->log("start vkCreateDisplayPlaneSurfaceKHR");
     auto stream = mImpl->stream();
@@ -13512,9 +13829,9 @@
     AEMU_SCOPED_TRACE("vkCreateDisplayPlaneSurfaceKHR returnUnmarshal");
     VkResult vkCreateDisplayPlaneSurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDisplayPlaneSurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateDisplayPlaneSurfaceKHR");;
     return vkCreateDisplayPlaneSurfaceKHR_VkResult_return;
 }
@@ -13528,7 +13845,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSwapchainKHR* pSwapchains)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateSharedSwapchainsKHR encode");
     mImpl->log("start vkCreateSharedSwapchainsKHR");
     auto stream = mImpl->stream();
@@ -13634,9 +13951,9 @@
     AEMU_SCOPED_TRACE("vkCreateSharedSwapchainsKHR returnUnmarshal");
     VkResult vkCreateSharedSwapchainsKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateSharedSwapchainsKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateSharedSwapchainsKHR");;
     return vkCreateSharedSwapchainsKHR_VkResult_return;
 }
@@ -13649,7 +13966,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateXlibSurfaceKHR encode");
     mImpl->log("start vkCreateXlibSurfaceKHR");
     auto stream = mImpl->stream();
@@ -13727,9 +14044,9 @@
     AEMU_SCOPED_TRACE("vkCreateXlibSurfaceKHR returnUnmarshal");
     VkResult vkCreateXlibSurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateXlibSurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateXlibSurfaceKHR");;
     return vkCreateXlibSurfaceKHR_VkResult_return;
 }
@@ -13740,7 +14057,7 @@
     Display* dpy,
     VisualID visualID)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceXlibPresentationSupportKHR encode");
     mImpl->log("start vkGetPhysicalDeviceXlibPresentationSupportKHR");
     auto stream = mImpl->stream();
@@ -13779,9 +14096,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceXlibPresentationSupportKHR returnUnmarshal");
     VkBool32 vkGetPhysicalDeviceXlibPresentationSupportKHR_VkBool32_return = (VkBool32)0;
     stream->read(&vkGetPhysicalDeviceXlibPresentationSupportKHR_VkBool32_return, sizeof(VkBool32));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceXlibPresentationSupportKHR");;
     return vkGetPhysicalDeviceXlibPresentationSupportKHR_VkBool32_return;
 }
@@ -13794,7 +14111,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateXcbSurfaceKHR encode");
     mImpl->log("start vkCreateXcbSurfaceKHR");
     auto stream = mImpl->stream();
@@ -13872,9 +14189,9 @@
     AEMU_SCOPED_TRACE("vkCreateXcbSurfaceKHR returnUnmarshal");
     VkResult vkCreateXcbSurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateXcbSurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateXcbSurfaceKHR");;
     return vkCreateXcbSurfaceKHR_VkResult_return;
 }
@@ -13885,7 +14202,7 @@
     xcb_connection_t* connection,
     xcb_visualid_t visual_id)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceXcbPresentationSupportKHR encode");
     mImpl->log("start vkGetPhysicalDeviceXcbPresentationSupportKHR");
     auto stream = mImpl->stream();
@@ -13924,9 +14241,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceXcbPresentationSupportKHR returnUnmarshal");
     VkBool32 vkGetPhysicalDeviceXcbPresentationSupportKHR_VkBool32_return = (VkBool32)0;
     stream->read(&vkGetPhysicalDeviceXcbPresentationSupportKHR_VkBool32_return, sizeof(VkBool32));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceXcbPresentationSupportKHR");;
     return vkGetPhysicalDeviceXcbPresentationSupportKHR_VkBool32_return;
 }
@@ -13939,7 +14256,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateWaylandSurfaceKHR encode");
     mImpl->log("start vkCreateWaylandSurfaceKHR");
     auto stream = mImpl->stream();
@@ -14017,9 +14334,9 @@
     AEMU_SCOPED_TRACE("vkCreateWaylandSurfaceKHR returnUnmarshal");
     VkResult vkCreateWaylandSurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateWaylandSurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateWaylandSurfaceKHR");;
     return vkCreateWaylandSurfaceKHR_VkResult_return;
 }
@@ -14029,7 +14346,7 @@
     uint32_t queueFamilyIndex,
     wl_display* display)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceWaylandPresentationSupportKHR encode");
     mImpl->log("start vkGetPhysicalDeviceWaylandPresentationSupportKHR");
     auto stream = mImpl->stream();
@@ -14064,9 +14381,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceWaylandPresentationSupportKHR returnUnmarshal");
     VkBool32 vkGetPhysicalDeviceWaylandPresentationSupportKHR_VkBool32_return = (VkBool32)0;
     stream->read(&vkGetPhysicalDeviceWaylandPresentationSupportKHR_VkBool32_return, sizeof(VkBool32));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceWaylandPresentationSupportKHR");;
     return vkGetPhysicalDeviceWaylandPresentationSupportKHR_VkBool32_return;
 }
@@ -14079,7 +14396,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateMirSurfaceKHR encode");
     mImpl->log("start vkCreateMirSurfaceKHR");
     auto stream = mImpl->stream();
@@ -14157,9 +14474,9 @@
     AEMU_SCOPED_TRACE("vkCreateMirSurfaceKHR returnUnmarshal");
     VkResult vkCreateMirSurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateMirSurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateMirSurfaceKHR");;
     return vkCreateMirSurfaceKHR_VkResult_return;
 }
@@ -14169,7 +14486,7 @@
     uint32_t queueFamilyIndex,
     MirConnection* connection)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMirPresentationSupportKHR encode");
     mImpl->log("start vkGetPhysicalDeviceMirPresentationSupportKHR");
     auto stream = mImpl->stream();
@@ -14204,9 +14521,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMirPresentationSupportKHR returnUnmarshal");
     VkBool32 vkGetPhysicalDeviceMirPresentationSupportKHR_VkBool32_return = (VkBool32)0;
     stream->read(&vkGetPhysicalDeviceMirPresentationSupportKHR_VkBool32_return, sizeof(VkBool32));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceMirPresentationSupportKHR");;
     return vkGetPhysicalDeviceMirPresentationSupportKHR_VkBool32_return;
 }
@@ -14219,7 +14536,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateAndroidSurfaceKHR encode");
     mImpl->log("start vkCreateAndroidSurfaceKHR");
     auto stream = mImpl->stream();
@@ -14297,9 +14614,9 @@
     AEMU_SCOPED_TRACE("vkCreateAndroidSurfaceKHR returnUnmarshal");
     VkResult vkCreateAndroidSurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateAndroidSurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateAndroidSurfaceKHR");;
     return vkCreateAndroidSurfaceKHR_VkResult_return;
 }
@@ -14312,7 +14629,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateWin32SurfaceKHR encode");
     mImpl->log("start vkCreateWin32SurfaceKHR");
     auto stream = mImpl->stream();
@@ -14390,9 +14707,9 @@
     AEMU_SCOPED_TRACE("vkCreateWin32SurfaceKHR returnUnmarshal");
     VkResult vkCreateWin32SurfaceKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateWin32SurfaceKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateWin32SurfaceKHR");;
     return vkCreateWin32SurfaceKHR_VkResult_return;
 }
@@ -14401,7 +14718,7 @@
     VkPhysicalDevice physicalDevice,
     uint32_t queueFamilyIndex)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceWin32PresentationSupportKHR encode");
     mImpl->log("start vkGetPhysicalDeviceWin32PresentationSupportKHR");
     auto stream = mImpl->stream();
@@ -14433,9 +14750,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceWin32PresentationSupportKHR returnUnmarshal");
     VkBool32 vkGetPhysicalDeviceWin32PresentationSupportKHR_VkBool32_return = (VkBool32)0;
     stream->read(&vkGetPhysicalDeviceWin32PresentationSupportKHR_VkBool32_return, sizeof(VkBool32));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceWin32PresentationSupportKHR");;
     return vkGetPhysicalDeviceWin32PresentationSupportKHR_VkBool32_return;
 }
@@ -14450,7 +14767,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceFeatures2* pFeatures)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceFeatures2KHR");
     auto stream = mImpl->stream();
@@ -14483,6 +14800,9 @@
         transform_fromhost_VkPhysicalDeviceFeatures2(mImpl->resources(), (VkPhysicalDeviceFeatures2*)(pFeatures));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFeatures2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceFeatures2KHR");;
 }
 
@@ -14490,7 +14810,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceProperties2* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceProperties2KHR");
     auto stream = mImpl->stream();
@@ -14523,9 +14843,10 @@
         transform_fromhost_VkPhysicalDeviceProperties2(mImpl->resources(), (VkPhysicalDeviceProperties2*)(pProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceProperties2KHR returnUnmarshal");
-    encoderLock.unlock();
     mImpl->resources()->on_vkGetPhysicalDeviceProperties2KHR(this, physicalDevice, pProperties);
-    encoderLock.lock();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceProperties2KHR");;
 }
 
@@ -14534,7 +14855,7 @@
     VkFormat format,
     VkFormatProperties2* pFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceFormatProperties2KHR");
     auto stream = mImpl->stream();
@@ -14571,6 +14892,9 @@
         transform_fromhost_VkFormatProperties2(mImpl->resources(), (VkFormatProperties2*)(pFormatProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceFormatProperties2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceFormatProperties2KHR");;
 }
 
@@ -14579,7 +14903,7 @@
     const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
     VkImageFormatProperties2* pImageFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceImageFormatProperties2KHR");
     auto stream = mImpl->stream();
@@ -14627,9 +14951,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceImageFormatProperties2KHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceImageFormatProperties2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceImageFormatProperties2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceImageFormatProperties2KHR");;
     return vkGetPhysicalDeviceImageFormatProperties2KHR_VkResult_return;
 }
@@ -14639,7 +14963,7 @@
     uint32_t* pQueueFamilyPropertyCount,
     VkQueueFamilyProperties2* pQueueFamilyProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceQueueFamilyProperties2KHR");
     auto stream = mImpl->stream();
@@ -14731,6 +15055,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceQueueFamilyProperties2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceQueueFamilyProperties2KHR");;
 }
 
@@ -14738,7 +15065,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceMemoryProperties2* pMemoryProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceMemoryProperties2KHR");
     auto stream = mImpl->stream();
@@ -14771,9 +15098,10 @@
         transform_fromhost_VkPhysicalDeviceMemoryProperties2(mImpl->resources(), (VkPhysicalDeviceMemoryProperties2*)(pMemoryProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMemoryProperties2KHR returnUnmarshal");
-    encoderLock.unlock();
     mImpl->resources()->on_vkGetPhysicalDeviceMemoryProperties2KHR(this, physicalDevice, pMemoryProperties);
-    encoderLock.lock();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceMemoryProperties2KHR");;
 }
 
@@ -14783,7 +15111,7 @@
     uint32_t* pPropertyCount,
     VkSparseImageFormatProperties2* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
     auto stream = mImpl->stream();
@@ -14888,6 +15216,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSparseImageFormatProperties2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceSparseImageFormatProperties2KHR");;
 }
 
@@ -14900,7 +15231,7 @@
     uint32_t remoteDeviceIndex,
     VkPeerMemoryFeatureFlags* pPeerMemoryFeatures)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeaturesKHR encode");
     mImpl->log("start vkGetDeviceGroupPeerMemoryFeaturesKHR");
     auto stream = mImpl->stream();
@@ -14941,6 +15272,9 @@
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeaturesKHR readParams");
     stream->read((VkPeerMemoryFeatureFlags*)pPeerMemoryFeatures, sizeof(VkPeerMemoryFeatureFlags));
     AEMU_SCOPED_TRACE("vkGetDeviceGroupPeerMemoryFeaturesKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDeviceGroupPeerMemoryFeaturesKHR");;
 }
 
@@ -14948,7 +15282,7 @@
     VkCommandBuffer commandBuffer,
     uint32_t deviceMask)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMaskKHR encode");
     mImpl->log("start vkCmdSetDeviceMaskKHR");
     auto stream = mImpl->stream();
@@ -14978,6 +15312,9 @@
     stream->write((uint32_t*)&local_deviceMask, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMaskKHR readParams");
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMaskKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetDeviceMaskKHR");;
 }
 
@@ -14990,7 +15327,7 @@
     uint32_t groupCountY,
     uint32_t groupCountZ)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDispatchBaseKHR encode");
     mImpl->log("start vkCmdDispatchBaseKHR");
     auto stream = mImpl->stream();
@@ -15040,6 +15377,9 @@
     stream->write((uint32_t*)&local_groupCountZ, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDispatchBaseKHR readParams");
     AEMU_SCOPED_TRACE("vkCmdDispatchBaseKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDispatchBaseKHR");;
 }
 
@@ -15052,7 +15392,7 @@
     VkCommandPool commandPool,
     VkCommandPoolTrimFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkTrimCommandPoolKHR encode");
     mImpl->log("start vkTrimCommandPoolKHR");
     auto stream = mImpl->stream();
@@ -15090,6 +15430,9 @@
     stream->write((VkCommandPoolTrimFlags*)&local_flags, sizeof(VkCommandPoolTrimFlags));
     AEMU_SCOPED_TRACE("vkTrimCommandPoolKHR readParams");
     AEMU_SCOPED_TRACE("vkTrimCommandPoolKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkTrimCommandPoolKHR");;
 }
 
@@ -15100,7 +15443,7 @@
     uint32_t* pPhysicalDeviceGroupCount,
     VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEnumeratePhysicalDeviceGroupsKHR encode");
     mImpl->log("start vkEnumeratePhysicalDeviceGroupsKHR");
     auto stream = mImpl->stream();
@@ -15194,9 +15537,9 @@
     AEMU_SCOPED_TRACE("vkEnumeratePhysicalDeviceGroupsKHR returnUnmarshal");
     VkResult vkEnumeratePhysicalDeviceGroupsKHR_VkResult_return = (VkResult)0;
     stream->read(&vkEnumeratePhysicalDeviceGroupsKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkEnumeratePhysicalDeviceGroupsKHR");;
     return vkEnumeratePhysicalDeviceGroupsKHR_VkResult_return;
 }
@@ -15208,7 +15551,7 @@
     const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
     VkExternalBufferProperties* pExternalBufferProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalBufferPropertiesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceExternalBufferPropertiesKHR");
     auto stream = mImpl->stream();
@@ -15256,6 +15599,9 @@
         transform_fromhost_VkExternalBufferProperties(mImpl->resources(), (VkExternalBufferProperties*)(pExternalBufferProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalBufferPropertiesKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceExternalBufferPropertiesKHR");;
 }
 
@@ -15268,7 +15614,7 @@
     const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo,
     HANDLE* pHandle)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryWin32HandleKHR encode");
     mImpl->log("start vkGetMemoryWin32HandleKHR");
     auto stream = mImpl->stream();
@@ -15312,9 +15658,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryWin32HandleKHR returnUnmarshal");
     VkResult vkGetMemoryWin32HandleKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryWin32HandleKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryWin32HandleKHR");;
     return vkGetMemoryWin32HandleKHR_VkResult_return;
 }
@@ -15325,7 +15671,7 @@
     HANDLE handle,
     VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryWin32HandlePropertiesKHR encode");
     mImpl->log("start vkGetMemoryWin32HandlePropertiesKHR");
     auto stream = mImpl->stream();
@@ -15368,9 +15714,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryWin32HandlePropertiesKHR returnUnmarshal");
     VkResult vkGetMemoryWin32HandlePropertiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryWin32HandlePropertiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryWin32HandlePropertiesKHR");;
     return vkGetMemoryWin32HandlePropertiesKHR_VkResult_return;
 }
@@ -15382,7 +15728,7 @@
     const VkMemoryGetFdInfoKHR* pGetFdInfo,
     int* pFd)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryFdKHR encode");
     mImpl->log("start vkGetMemoryFdKHR");
     auto stream = mImpl->stream();
@@ -15426,9 +15772,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryFdKHR returnUnmarshal");
     VkResult vkGetMemoryFdKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryFdKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryFdKHR");;
     return vkGetMemoryFdKHR_VkResult_return;
 }
@@ -15439,7 +15785,7 @@
     int fd,
     VkMemoryFdPropertiesKHR* pMemoryFdProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryFdPropertiesKHR encode");
     mImpl->log("start vkGetMemoryFdPropertiesKHR");
     auto stream = mImpl->stream();
@@ -15482,9 +15828,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryFdPropertiesKHR returnUnmarshal");
     VkResult vkGetMemoryFdPropertiesKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryFdPropertiesKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryFdPropertiesKHR");;
     return vkGetMemoryFdPropertiesKHR_VkResult_return;
 }
@@ -15498,7 +15844,7 @@
     const VkPhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo,
     VkExternalSemaphoreProperties* pExternalSemaphoreProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");
     auto stream = mImpl->stream();
@@ -15544,6 +15890,9 @@
         transform_fromhost_VkExternalSemaphoreProperties(mImpl->resources(), (VkExternalSemaphoreProperties*)(pExternalSemaphoreProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalSemaphorePropertiesKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceExternalSemaphorePropertiesKHR");;
 }
 
@@ -15555,7 +15904,7 @@
     VkDevice device,
     const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkImportSemaphoreWin32HandleKHR encode");
     mImpl->log("start vkImportSemaphoreWin32HandleKHR");
     auto stream = mImpl->stream();
@@ -15596,9 +15945,9 @@
     AEMU_SCOPED_TRACE("vkImportSemaphoreWin32HandleKHR returnUnmarshal");
     VkResult vkImportSemaphoreWin32HandleKHR_VkResult_return = (VkResult)0;
     stream->read(&vkImportSemaphoreWin32HandleKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkImportSemaphoreWin32HandleKHR");;
     return vkImportSemaphoreWin32HandleKHR_VkResult_return;
 }
@@ -15608,7 +15957,7 @@
     const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
     HANDLE* pHandle)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetSemaphoreWin32HandleKHR encode");
     mImpl->log("start vkGetSemaphoreWin32HandleKHR");
     auto stream = mImpl->stream();
@@ -15652,9 +16001,9 @@
     AEMU_SCOPED_TRACE("vkGetSemaphoreWin32HandleKHR returnUnmarshal");
     VkResult vkGetSemaphoreWin32HandleKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetSemaphoreWin32HandleKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetSemaphoreWin32HandleKHR");;
     return vkGetSemaphoreWin32HandleKHR_VkResult_return;
 }
@@ -15665,7 +16014,7 @@
     VkDevice device,
     const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkImportSemaphoreFdKHR encode");
     mImpl->log("start vkImportSemaphoreFdKHR");
     auto stream = mImpl->stream();
@@ -15706,9 +16055,9 @@
     AEMU_SCOPED_TRACE("vkImportSemaphoreFdKHR returnUnmarshal");
     VkResult vkImportSemaphoreFdKHR_VkResult_return = (VkResult)0;
     stream->read(&vkImportSemaphoreFdKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkImportSemaphoreFdKHR");;
     return vkImportSemaphoreFdKHR_VkResult_return;
 }
@@ -15718,7 +16067,7 @@
     const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
     int* pFd)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetSemaphoreFdKHR encode");
     mImpl->log("start vkGetSemaphoreFdKHR");
     auto stream = mImpl->stream();
@@ -15762,9 +16111,9 @@
     AEMU_SCOPED_TRACE("vkGetSemaphoreFdKHR returnUnmarshal");
     VkResult vkGetSemaphoreFdKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetSemaphoreFdKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetSemaphoreFdKHR");;
     return vkGetSemaphoreFdKHR_VkResult_return;
 }
@@ -15779,7 +16128,7 @@
     uint32_t descriptorWriteCount,
     const VkWriteDescriptorSet* pDescriptorWrites)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetKHR encode");
     mImpl->log("start vkCmdPushDescriptorSetKHR");
     auto stream = mImpl->stream();
@@ -15850,6 +16199,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetKHR readParams");
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdPushDescriptorSetKHR");;
 }
 
@@ -15860,7 +16212,7 @@
     uint32_t set,
     const void* pData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetWithTemplateKHR encode");
     mImpl->log("start vkCmdPushDescriptorSetWithTemplateKHR");
     auto stream = mImpl->stream();
@@ -15926,6 +16278,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetWithTemplateKHR readParams");
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetWithTemplateKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdPushDescriptorSetWithTemplateKHR");;
 }
 
@@ -15941,7 +16296,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDescriptorUpdateTemplateKHR encode");
     mImpl->log("start vkCreateDescriptorUpdateTemplateKHR");
     auto stream = mImpl->stream();
@@ -16021,12 +16376,10 @@
     AEMU_SCOPED_TRACE("vkCreateDescriptorUpdateTemplateKHR returnUnmarshal");
     VkResult vkCreateDescriptorUpdateTemplateKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDescriptorUpdateTemplateKHR_VkResult_return, sizeof(VkResult));
+    mImpl->resources()->on_vkCreateDescriptorUpdateTemplateKHR(this, vkCreateDescriptorUpdateTemplateKHR_VkResult_return, device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
-    encoderLock.unlock();
-    mImpl->resources()->on_vkCreateDescriptorUpdateTemplateKHR(this, vkCreateDescriptorUpdateTemplateKHR_VkResult_return, device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate);
-    encoderLock.lock();
     mImpl->log("finish vkCreateDescriptorUpdateTemplateKHR");;
     return vkCreateDescriptorUpdateTemplateKHR_VkResult_return;
 }
@@ -16036,7 +16389,7 @@
     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplateKHR encode");
     mImpl->log("start vkDestroyDescriptorUpdateTemplateKHR");
     auto stream = mImpl->stream();
@@ -16097,6 +16450,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplateKHR readParams");
     AEMU_SCOPED_TRACE("vkDestroyDescriptorUpdateTemplateKHR returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDescriptorUpdateTemplate((VkDescriptorUpdateTemplate*)&descriptorUpdateTemplate);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDescriptorUpdateTemplateKHR");;
 }
 
@@ -16106,7 +16462,7 @@
     VkDescriptorUpdateTemplate descriptorUpdateTemplate,
     const void* pData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateKHR encode");
     mImpl->log("start vkUpdateDescriptorSetWithTemplateKHR");
     auto stream = mImpl->stream();
@@ -16168,6 +16524,9 @@
     }
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateKHR readParams");
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkUpdateDescriptorSetWithTemplateKHR");;
 }
 
@@ -16179,7 +16538,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkRenderPass* pRenderPass)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateRenderPass2KHR encode");
     mImpl->log("start vkCreateRenderPass2KHR");
     auto stream = mImpl->stream();
@@ -16257,9 +16616,9 @@
     AEMU_SCOPED_TRACE("vkCreateRenderPass2KHR returnUnmarshal");
     VkResult vkCreateRenderPass2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateRenderPass2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateRenderPass2KHR");;
     return vkCreateRenderPass2KHR_VkResult_return;
 }
@@ -16269,7 +16628,7 @@
     const VkRenderPassBeginInfo* pRenderPassBegin,
     const VkSubpassBeginInfoKHR* pSubpassBeginInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2KHR encode");
     mImpl->log("start vkCmdBeginRenderPass2KHR");
     auto stream = mImpl->stream();
@@ -16321,6 +16680,9 @@
     marshal_VkSubpassBeginInfoKHR(stream, (VkSubpassBeginInfoKHR*)(local_pSubpassBeginInfo));
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2KHR readParams");
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBeginRenderPass2KHR");;
 }
 
@@ -16329,7 +16691,7 @@
     const VkSubpassBeginInfoKHR* pSubpassBeginInfo,
     const VkSubpassEndInfoKHR* pSubpassEndInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdNextSubpass2KHR encode");
     mImpl->log("start vkCmdNextSubpass2KHR");
     auto stream = mImpl->stream();
@@ -16381,6 +16743,9 @@
     marshal_VkSubpassEndInfoKHR(stream, (VkSubpassEndInfoKHR*)(local_pSubpassEndInfo));
     AEMU_SCOPED_TRACE("vkCmdNextSubpass2KHR readParams");
     AEMU_SCOPED_TRACE("vkCmdNextSubpass2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdNextSubpass2KHR");;
 }
 
@@ -16388,7 +16753,7 @@
     VkCommandBuffer commandBuffer,
     const VkSubpassEndInfoKHR* pSubpassEndInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass2KHR encode");
     mImpl->log("start vkCmdEndRenderPass2KHR");
     auto stream = mImpl->stream();
@@ -16427,6 +16792,9 @@
     marshal_VkSubpassEndInfoKHR(stream, (VkSubpassEndInfoKHR*)(local_pSubpassEndInfo));
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass2KHR readParams");
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdEndRenderPass2KHR");;
 }
 
@@ -16436,7 +16804,7 @@
     VkDevice device,
     VkSwapchainKHR swapchain)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetSwapchainStatusKHR encode");
     mImpl->log("start vkGetSwapchainStatusKHR");
     auto stream = mImpl->stream();
@@ -16472,9 +16840,9 @@
     AEMU_SCOPED_TRACE("vkGetSwapchainStatusKHR returnUnmarshal");
     VkResult vkGetSwapchainStatusKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetSwapchainStatusKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetSwapchainStatusKHR");;
     return vkGetSwapchainStatusKHR_VkResult_return;
 }
@@ -16486,7 +16854,7 @@
     const VkPhysicalDeviceExternalFenceInfo* pExternalFenceInfo,
     VkExternalFenceProperties* pExternalFenceProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalFencePropertiesKHR encode");
     mImpl->log("start vkGetPhysicalDeviceExternalFencePropertiesKHR");
     auto stream = mImpl->stream();
@@ -16532,6 +16900,9 @@
         transform_fromhost_VkExternalFenceProperties(mImpl->resources(), (VkExternalFenceProperties*)(pExternalFenceProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalFencePropertiesKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceExternalFencePropertiesKHR");;
 }
 
@@ -16543,7 +16914,7 @@
     VkDevice device,
     const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkImportFenceWin32HandleKHR encode");
     mImpl->log("start vkImportFenceWin32HandleKHR");
     auto stream = mImpl->stream();
@@ -16584,9 +16955,9 @@
     AEMU_SCOPED_TRACE("vkImportFenceWin32HandleKHR returnUnmarshal");
     VkResult vkImportFenceWin32HandleKHR_VkResult_return = (VkResult)0;
     stream->read(&vkImportFenceWin32HandleKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkImportFenceWin32HandleKHR");;
     return vkImportFenceWin32HandleKHR_VkResult_return;
 }
@@ -16596,7 +16967,7 @@
     const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
     HANDLE* pHandle)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetFenceWin32HandleKHR encode");
     mImpl->log("start vkGetFenceWin32HandleKHR");
     auto stream = mImpl->stream();
@@ -16640,9 +17011,9 @@
     AEMU_SCOPED_TRACE("vkGetFenceWin32HandleKHR returnUnmarshal");
     VkResult vkGetFenceWin32HandleKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetFenceWin32HandleKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetFenceWin32HandleKHR");;
     return vkGetFenceWin32HandleKHR_VkResult_return;
 }
@@ -16653,7 +17024,7 @@
     VkDevice device,
     const VkImportFenceFdInfoKHR* pImportFenceFdInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkImportFenceFdKHR encode");
     mImpl->log("start vkImportFenceFdKHR");
     auto stream = mImpl->stream();
@@ -16694,9 +17065,9 @@
     AEMU_SCOPED_TRACE("vkImportFenceFdKHR returnUnmarshal");
     VkResult vkImportFenceFdKHR_VkResult_return = (VkResult)0;
     stream->read(&vkImportFenceFdKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkImportFenceFdKHR");;
     return vkImportFenceFdKHR_VkResult_return;
 }
@@ -16706,7 +17077,7 @@
     const VkFenceGetFdInfoKHR* pGetFdInfo,
     int* pFd)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetFenceFdKHR encode");
     mImpl->log("start vkGetFenceFdKHR");
     auto stream = mImpl->stream();
@@ -16750,9 +17121,9 @@
     AEMU_SCOPED_TRACE("vkGetFenceFdKHR returnUnmarshal");
     VkResult vkGetFenceFdKHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetFenceFdKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetFenceFdKHR");;
     return vkGetFenceFdKHR_VkResult_return;
 }
@@ -16766,7 +17137,7 @@
     const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
     VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceCapabilities2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceSurfaceCapabilities2KHR");
     auto stream = mImpl->stream();
@@ -16814,9 +17185,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceCapabilities2KHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfaceCapabilities2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfaceCapabilities2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfaceCapabilities2KHR");;
     return vkGetPhysicalDeviceSurfaceCapabilities2KHR_VkResult_return;
 }
@@ -16827,7 +17198,7 @@
     uint32_t* pSurfaceFormatCount,
     VkSurfaceFormat2KHR* pSurfaceFormats)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceFormats2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceSurfaceFormats2KHR");
     auto stream = mImpl->stream();
@@ -16934,9 +17305,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceFormats2KHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfaceFormats2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfaceFormats2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfaceFormats2KHR");;
     return vkGetPhysicalDeviceSurfaceFormats2KHR_VkResult_return;
 }
@@ -16950,7 +17321,7 @@
     uint32_t* pPropertyCount,
     VkDisplayProperties2KHR* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceDisplayProperties2KHR");
     auto stream = mImpl->stream();
@@ -17044,9 +17415,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayProperties2KHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceDisplayProperties2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceDisplayProperties2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceDisplayProperties2KHR");;
     return vkGetPhysicalDeviceDisplayProperties2KHR_VkResult_return;
 }
@@ -17056,7 +17427,7 @@
     uint32_t* pPropertyCount,
     VkDisplayPlaneProperties2KHR* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayPlaneProperties2KHR encode");
     mImpl->log("start vkGetPhysicalDeviceDisplayPlaneProperties2KHR");
     auto stream = mImpl->stream();
@@ -17150,9 +17521,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceDisplayPlaneProperties2KHR returnUnmarshal");
     VkResult vkGetPhysicalDeviceDisplayPlaneProperties2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceDisplayPlaneProperties2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceDisplayPlaneProperties2KHR");;
     return vkGetPhysicalDeviceDisplayPlaneProperties2KHR_VkResult_return;
 }
@@ -17163,7 +17534,7 @@
     uint32_t* pPropertyCount,
     VkDisplayModeProperties2KHR* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDisplayModeProperties2KHR encode");
     mImpl->log("start vkGetDisplayModeProperties2KHR");
     auto stream = mImpl->stream();
@@ -17265,9 +17636,9 @@
     AEMU_SCOPED_TRACE("vkGetDisplayModeProperties2KHR returnUnmarshal");
     VkResult vkGetDisplayModeProperties2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDisplayModeProperties2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDisplayModeProperties2KHR");;
     return vkGetDisplayModeProperties2KHR_VkResult_return;
 }
@@ -17277,7 +17648,7 @@
     const VkDisplayPlaneInfo2KHR* pDisplayPlaneInfo,
     VkDisplayPlaneCapabilities2KHR* pCapabilities)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDisplayPlaneCapabilities2KHR encode");
     mImpl->log("start vkGetDisplayPlaneCapabilities2KHR");
     auto stream = mImpl->stream();
@@ -17325,9 +17696,9 @@
     AEMU_SCOPED_TRACE("vkGetDisplayPlaneCapabilities2KHR returnUnmarshal");
     VkResult vkGetDisplayPlaneCapabilities2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkGetDisplayPlaneCapabilities2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetDisplayPlaneCapabilities2KHR");;
     return vkGetDisplayPlaneCapabilities2KHR_VkResult_return;
 }
@@ -17345,7 +17716,7 @@
     const VkImageMemoryRequirementsInfo2* pInfo,
     VkMemoryRequirements2* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements2KHR encode");
     mImpl->log("start vkGetImageMemoryRequirements2KHR");
     auto stream = mImpl->stream();
@@ -17391,6 +17762,9 @@
         transform_fromhost_VkMemoryRequirements2(mImpl->resources(), (VkMemoryRequirements2*)(pMemoryRequirements));
     }
     AEMU_SCOPED_TRACE("vkGetImageMemoryRequirements2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageMemoryRequirements2KHR");;
 }
 
@@ -17399,7 +17773,7 @@
     const VkBufferMemoryRequirementsInfo2* pInfo,
     VkMemoryRequirements2* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements2KHR encode");
     mImpl->log("start vkGetBufferMemoryRequirements2KHR");
     auto stream = mImpl->stream();
@@ -17445,6 +17819,9 @@
         transform_fromhost_VkMemoryRequirements2(mImpl->resources(), (VkMemoryRequirements2*)(pMemoryRequirements));
     }
     AEMU_SCOPED_TRACE("vkGetBufferMemoryRequirements2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetBufferMemoryRequirements2KHR");;
 }
 
@@ -17454,7 +17831,7 @@
     uint32_t* pSparseMemoryRequirementCount,
     VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements2KHR encode");
     mImpl->log("start vkGetImageSparseMemoryRequirements2KHR");
     auto stream = mImpl->stream();
@@ -17559,6 +17936,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetImageSparseMemoryRequirements2KHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetImageSparseMemoryRequirements2KHR");;
 }
 
@@ -17572,7 +17952,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSamplerYcbcrConversion* pYcbcrConversion)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversionKHR encode");
     mImpl->log("start vkCreateSamplerYcbcrConversionKHR");
     auto stream = mImpl->stream();
@@ -17652,9 +18032,9 @@
     AEMU_SCOPED_TRACE("vkCreateSamplerYcbcrConversionKHR returnUnmarshal");
     VkResult vkCreateSamplerYcbcrConversionKHR_VkResult_return = (VkResult)0;
     stream->read(&vkCreateSamplerYcbcrConversionKHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateSamplerYcbcrConversionKHR");;
     return vkCreateSamplerYcbcrConversionKHR_VkResult_return;
 }
@@ -17664,7 +18044,7 @@
     VkSamplerYcbcrConversion ycbcrConversion,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversionKHR encode");
     mImpl->log("start vkDestroySamplerYcbcrConversionKHR");
     auto stream = mImpl->stream();
@@ -17725,6 +18105,9 @@
     AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversionKHR readParams");
     AEMU_SCOPED_TRACE("vkDestroySamplerYcbcrConversionKHR returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkSamplerYcbcrConversion((VkSamplerYcbcrConversion*)&ycbcrConversion);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroySamplerYcbcrConversionKHR");;
 }
 
@@ -17735,7 +18118,7 @@
     uint32_t bindInfoCount,
     const VkBindBufferMemoryInfo* pBindInfos)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBindBufferMemory2KHR encode");
     mImpl->log("start vkBindBufferMemory2KHR");
     auto stream = mImpl->stream();
@@ -17792,9 +18175,9 @@
     AEMU_SCOPED_TRACE("vkBindBufferMemory2KHR returnUnmarshal");
     VkResult vkBindBufferMemory2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkBindBufferMemory2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBindBufferMemory2KHR");;
     return vkBindBufferMemory2KHR_VkResult_return;
 }
@@ -17804,7 +18187,7 @@
     uint32_t bindInfoCount,
     const VkBindImageMemoryInfo* pBindInfos)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBindImageMemory2KHR encode");
     mImpl->log("start vkBindImageMemory2KHR");
     auto stream = mImpl->stream();
@@ -17861,9 +18244,9 @@
     AEMU_SCOPED_TRACE("vkBindImageMemory2KHR returnUnmarshal");
     VkResult vkBindImageMemory2KHR_VkResult_return = (VkResult)0;
     stream->read(&vkBindImageMemory2KHR_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkBindImageMemory2KHR");;
     return vkBindImageMemory2KHR_VkResult_return;
 }
@@ -17875,7 +18258,7 @@
     const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
     VkDescriptorSetLayoutSupport* pSupport)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetDescriptorSetLayoutSupportKHR encode");
     mImpl->log("start vkGetDescriptorSetLayoutSupportKHR");
     auto stream = mImpl->stream();
@@ -17921,6 +18304,9 @@
         transform_fromhost_VkDescriptorSetLayoutSupport(mImpl->resources(), (VkDescriptorSetLayoutSupport*)(pSupport));
     }
     AEMU_SCOPED_TRACE("vkGetDescriptorSetLayoutSupportKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetDescriptorSetLayoutSupportKHR");;
 }
 
@@ -17935,7 +18321,7 @@
     uint32_t maxDrawCount,
     uint32_t stride)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountKHR encode");
     mImpl->log("start vkCmdDrawIndirectCountKHR");
     auto stream = mImpl->stream();
@@ -17993,6 +18379,9 @@
     stream->write((uint32_t*)&local_stride, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountKHR readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndirectCountKHR");;
 }
 
@@ -18005,7 +18394,7 @@
     uint32_t maxDrawCount,
     uint32_t stride)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountKHR encode");
     mImpl->log("start vkCmdDrawIndexedIndirectCountKHR");
     auto stream = mImpl->stream();
@@ -18063,6 +18452,9 @@
     stream->write((uint32_t*)&local_stride, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountKHR readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountKHR returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndexedIndirectCountKHR");;
 }
 
@@ -18078,7 +18470,7 @@
     VkImageUsageFlags imageUsage,
     int* grallocUsage)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetSwapchainGrallocUsageANDROID encode");
     mImpl->log("start vkGetSwapchainGrallocUsageANDROID");
     auto stream = mImpl->stream();
@@ -18117,9 +18509,9 @@
     AEMU_SCOPED_TRACE("vkGetSwapchainGrallocUsageANDROID returnUnmarshal");
     VkResult vkGetSwapchainGrallocUsageANDROID_VkResult_return = (VkResult)0;
     stream->read(&vkGetSwapchainGrallocUsageANDROID_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetSwapchainGrallocUsageANDROID");;
     return vkGetSwapchainGrallocUsageANDROID_VkResult_return;
 }
@@ -18131,7 +18523,7 @@
     VkSemaphore semaphore,
     VkFence fence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAcquireImageANDROID encode");
     mImpl->log("start vkAcquireImageANDROID");
     auto stream = mImpl->stream();
@@ -18188,9 +18580,9 @@
     AEMU_SCOPED_TRACE("vkAcquireImageANDROID returnUnmarshal");
     VkResult vkAcquireImageANDROID_VkResult_return = (VkResult)0;
     stream->read(&vkAcquireImageANDROID_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAcquireImageANDROID");;
     return vkAcquireImageANDROID_VkResult_return;
 }
@@ -18202,7 +18594,7 @@
     VkImage image,
     int* pNativeFenceFd)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueSignalReleaseImageANDROID encode");
     mImpl->log("start vkQueueSignalReleaseImageANDROID");
     auto stream = mImpl->stream();
@@ -18277,9 +18669,10 @@
     AEMU_SCOPED_TRACE("vkQueueSignalReleaseImageANDROID returnUnmarshal");
     VkResult vkQueueSignalReleaseImageANDROID_VkResult_return = (VkResult)0;
     stream->read(&vkQueueSignalReleaseImageANDROID_VkResult_return, sizeof(VkResult));
+    stream->flush();
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkQueueSignalReleaseImageANDROID");;
     return vkQueueSignalReleaseImageANDROID_VkResult_return;
 }
@@ -18292,7 +18685,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDebugReportCallbackEXT* pCallback)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDebugReportCallbackEXT encode");
     mImpl->log("start vkCreateDebugReportCallbackEXT");
     auto stream = mImpl->stream();
@@ -18372,9 +18765,9 @@
     AEMU_SCOPED_TRACE("vkCreateDebugReportCallbackEXT returnUnmarshal");
     VkResult vkCreateDebugReportCallbackEXT_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDebugReportCallbackEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateDebugReportCallbackEXT");;
     return vkCreateDebugReportCallbackEXT_VkResult_return;
 }
@@ -18384,7 +18777,7 @@
     VkDebugReportCallbackEXT callback,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDebugReportCallbackEXT encode");
     mImpl->log("start vkDestroyDebugReportCallbackEXT");
     auto stream = mImpl->stream();
@@ -18445,6 +18838,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDebugReportCallbackEXT readParams");
     AEMU_SCOPED_TRACE("vkDestroyDebugReportCallbackEXT returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDebugReportCallbackEXT((VkDebugReportCallbackEXT*)&callback);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDebugReportCallbackEXT");;
 }
 
@@ -18458,7 +18854,7 @@
     const char* pLayerPrefix,
     const char* pMessage)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDebugReportMessageEXT encode");
     mImpl->log("start vkDebugReportMessageEXT");
     auto stream = mImpl->stream();
@@ -18522,6 +18918,9 @@
     stream->putString(local_pMessage);
     AEMU_SCOPED_TRACE("vkDebugReportMessageEXT readParams");
     AEMU_SCOPED_TRACE("vkDebugReportMessageEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDebugReportMessageEXT");;
 }
 
@@ -18543,7 +18942,7 @@
     VkDevice device,
     const VkDebugMarkerObjectTagInfoEXT* pTagInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDebugMarkerSetObjectTagEXT encode");
     mImpl->log("start vkDebugMarkerSetObjectTagEXT");
     auto stream = mImpl->stream();
@@ -18584,9 +18983,9 @@
     AEMU_SCOPED_TRACE("vkDebugMarkerSetObjectTagEXT returnUnmarshal");
     VkResult vkDebugMarkerSetObjectTagEXT_VkResult_return = (VkResult)0;
     stream->read(&vkDebugMarkerSetObjectTagEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkDebugMarkerSetObjectTagEXT");;
     return vkDebugMarkerSetObjectTagEXT_VkResult_return;
 }
@@ -18595,7 +18994,7 @@
     VkDevice device,
     const VkDebugMarkerObjectNameInfoEXT* pNameInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDebugMarkerSetObjectNameEXT encode");
     mImpl->log("start vkDebugMarkerSetObjectNameEXT");
     auto stream = mImpl->stream();
@@ -18636,9 +19035,9 @@
     AEMU_SCOPED_TRACE("vkDebugMarkerSetObjectNameEXT returnUnmarshal");
     VkResult vkDebugMarkerSetObjectNameEXT_VkResult_return = (VkResult)0;
     stream->read(&vkDebugMarkerSetObjectNameEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkDebugMarkerSetObjectNameEXT");;
     return vkDebugMarkerSetObjectNameEXT_VkResult_return;
 }
@@ -18647,7 +19046,7 @@
     VkCommandBuffer commandBuffer,
     const VkDebugMarkerMarkerInfoEXT* pMarkerInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerBeginEXT encode");
     mImpl->log("start vkCmdDebugMarkerBeginEXT");
     auto stream = mImpl->stream();
@@ -18686,13 +19085,16 @@
     marshal_VkDebugMarkerMarkerInfoEXT(stream, (VkDebugMarkerMarkerInfoEXT*)(local_pMarkerInfo));
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerBeginEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerBeginEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDebugMarkerBeginEXT");;
 }
 
 void VkEncoder::vkCmdDebugMarkerEndEXT(
     VkCommandBuffer commandBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerEndEXT encode");
     mImpl->log("start vkCmdDebugMarkerEndEXT");
     auto stream = mImpl->stream();
@@ -18718,6 +19120,9 @@
     stream->write((uint64_t*)&cgen_var_1224, 1 * 8);
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerEndEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerEndEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDebugMarkerEndEXT");;
 }
 
@@ -18725,7 +19130,7 @@
     VkCommandBuffer commandBuffer,
     const VkDebugMarkerMarkerInfoEXT* pMarkerInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerInsertEXT encode");
     mImpl->log("start vkCmdDebugMarkerInsertEXT");
     auto stream = mImpl->stream();
@@ -18764,6 +19169,9 @@
     marshal_VkDebugMarkerMarkerInfoEXT(stream, (VkDebugMarkerMarkerInfoEXT*)(local_pMarkerInfo));
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerInsertEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerInsertEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDebugMarkerInsertEXT");;
 }
 
@@ -18782,7 +19190,7 @@
     uint32_t maxDrawCount,
     uint32_t stride)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountAMD encode");
     mImpl->log("start vkCmdDrawIndirectCountAMD");
     auto stream = mImpl->stream();
@@ -18840,6 +19248,9 @@
     stream->write((uint32_t*)&local_stride, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountAMD readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountAMD returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndirectCountAMD");;
 }
 
@@ -18852,7 +19263,7 @@
     uint32_t maxDrawCount,
     uint32_t stride)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountAMD encode");
     mImpl->log("start vkCmdDrawIndexedIndirectCountAMD");
     auto stream = mImpl->stream();
@@ -18910,6 +19321,9 @@
     stream->write((uint32_t*)&local_stride, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountAMD readParams");
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountAMD returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdDrawIndexedIndirectCountAMD");;
 }
 
@@ -18931,7 +19345,7 @@
     size_t* pInfoSize,
     void* pInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetShaderInfoAMD encode");
     mImpl->log("start vkGetShaderInfoAMD");
     auto stream = mImpl->stream();
@@ -19027,9 +19441,9 @@
     AEMU_SCOPED_TRACE("vkGetShaderInfoAMD returnUnmarshal");
     VkResult vkGetShaderInfoAMD_VkResult_return = (VkResult)0;
     stream->read(&vkGetShaderInfoAMD_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetShaderInfoAMD");;
     return vkGetShaderInfoAMD_VkResult_return;
 }
@@ -19050,7 +19464,7 @@
     VkExternalMemoryHandleTypeFlagsNV externalHandleType,
     VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalImageFormatPropertiesNV encode");
     mImpl->log("start vkGetPhysicalDeviceExternalImageFormatPropertiesNV");
     auto stream = mImpl->stream();
@@ -19109,9 +19523,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceExternalImageFormatPropertiesNV returnUnmarshal");
     VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceExternalImageFormatPropertiesNV_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceExternalImageFormatPropertiesNV");;
     return vkGetPhysicalDeviceExternalImageFormatPropertiesNV_VkResult_return;
 }
@@ -19126,7 +19540,7 @@
     VkExternalMemoryHandleTypeFlagsNV handleType,
     HANDLE* pHandle)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryWin32HandleNV encode");
     mImpl->log("start vkGetMemoryWin32HandleNV");
     auto stream = mImpl->stream();
@@ -19170,9 +19584,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryWin32HandleNV returnUnmarshal");
     VkResult vkGetMemoryWin32HandleNV_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryWin32HandleNV_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryWin32HandleNV");;
     return vkGetMemoryWin32HandleNV_VkResult_return;
 }
@@ -19189,7 +19603,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateViSurfaceNN encode");
     mImpl->log("start vkCreateViSurfaceNN");
     auto stream = mImpl->stream();
@@ -19267,9 +19681,9 @@
     AEMU_SCOPED_TRACE("vkCreateViSurfaceNN returnUnmarshal");
     VkResult vkCreateViSurfaceNN_VkResult_return = (VkResult)0;
     stream->read(&vkCreateViSurfaceNN_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateViSurfaceNN");;
     return vkCreateViSurfaceNN_VkResult_return;
 }
@@ -19284,7 +19698,7 @@
     VkCommandBuffer commandBuffer,
     const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBeginConditionalRenderingEXT encode");
     mImpl->log("start vkCmdBeginConditionalRenderingEXT");
     auto stream = mImpl->stream();
@@ -19323,13 +19737,16 @@
     marshal_VkConditionalRenderingBeginInfoEXT(stream, (VkConditionalRenderingBeginInfoEXT*)(local_pConditionalRenderingBegin));
     AEMU_SCOPED_TRACE("vkCmdBeginConditionalRenderingEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdBeginConditionalRenderingEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBeginConditionalRenderingEXT");;
 }
 
 void VkEncoder::vkCmdEndConditionalRenderingEXT(
     VkCommandBuffer commandBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdEndConditionalRenderingEXT encode");
     mImpl->log("start vkCmdEndConditionalRenderingEXT");
     auto stream = mImpl->stream();
@@ -19355,6 +19772,9 @@
     stream->write((uint64_t*)&cgen_var_1268, 1 * 8);
     AEMU_SCOPED_TRACE("vkCmdEndConditionalRenderingEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdEndConditionalRenderingEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdEndConditionalRenderingEXT");;
 }
 
@@ -19364,7 +19784,7 @@
     VkCommandBuffer commandBuffer,
     const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdProcessCommandsNVX encode");
     mImpl->log("start vkCmdProcessCommandsNVX");
     auto stream = mImpl->stream();
@@ -19403,6 +19823,9 @@
     marshal_VkCmdProcessCommandsInfoNVX(stream, (VkCmdProcessCommandsInfoNVX*)(local_pProcessCommandsInfo));
     AEMU_SCOPED_TRACE("vkCmdProcessCommandsNVX readParams");
     AEMU_SCOPED_TRACE("vkCmdProcessCommandsNVX returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdProcessCommandsNVX");;
 }
 
@@ -19410,7 +19833,7 @@
     VkCommandBuffer commandBuffer,
     const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdReserveSpaceForCommandsNVX encode");
     mImpl->log("start vkCmdReserveSpaceForCommandsNVX");
     auto stream = mImpl->stream();
@@ -19449,6 +19872,9 @@
     marshal_VkCmdReserveSpaceForCommandsInfoNVX(stream, (VkCmdReserveSpaceForCommandsInfoNVX*)(local_pReserveSpaceInfo));
     AEMU_SCOPED_TRACE("vkCmdReserveSpaceForCommandsNVX readParams");
     AEMU_SCOPED_TRACE("vkCmdReserveSpaceForCommandsNVX returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdReserveSpaceForCommandsNVX");;
 }
 
@@ -19458,7 +19884,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateIndirectCommandsLayoutNVX encode");
     mImpl->log("start vkCreateIndirectCommandsLayoutNVX");
     auto stream = mImpl->stream();
@@ -19538,9 +19964,9 @@
     AEMU_SCOPED_TRACE("vkCreateIndirectCommandsLayoutNVX returnUnmarshal");
     VkResult vkCreateIndirectCommandsLayoutNVX_VkResult_return = (VkResult)0;
     stream->read(&vkCreateIndirectCommandsLayoutNVX_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateIndirectCommandsLayoutNVX");;
     return vkCreateIndirectCommandsLayoutNVX_VkResult_return;
 }
@@ -19550,7 +19976,7 @@
     VkIndirectCommandsLayoutNVX indirectCommandsLayout,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyIndirectCommandsLayoutNVX encode");
     mImpl->log("start vkDestroyIndirectCommandsLayoutNVX");
     auto stream = mImpl->stream();
@@ -19611,6 +20037,9 @@
     AEMU_SCOPED_TRACE("vkDestroyIndirectCommandsLayoutNVX readParams");
     AEMU_SCOPED_TRACE("vkDestroyIndirectCommandsLayoutNVX returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkIndirectCommandsLayoutNVX((VkIndirectCommandsLayoutNVX*)&indirectCommandsLayout);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyIndirectCommandsLayoutNVX");;
 }
 
@@ -19620,7 +20049,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkObjectTableNVX* pObjectTable)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateObjectTableNVX encode");
     mImpl->log("start vkCreateObjectTableNVX");
     auto stream = mImpl->stream();
@@ -19700,9 +20129,9 @@
     AEMU_SCOPED_TRACE("vkCreateObjectTableNVX returnUnmarshal");
     VkResult vkCreateObjectTableNVX_VkResult_return = (VkResult)0;
     stream->read(&vkCreateObjectTableNVX_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateObjectTableNVX");;
     return vkCreateObjectTableNVX_VkResult_return;
 }
@@ -19712,7 +20141,7 @@
     VkObjectTableNVX objectTable,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyObjectTableNVX encode");
     mImpl->log("start vkDestroyObjectTableNVX");
     auto stream = mImpl->stream();
@@ -19773,6 +20202,9 @@
     AEMU_SCOPED_TRACE("vkDestroyObjectTableNVX readParams");
     AEMU_SCOPED_TRACE("vkDestroyObjectTableNVX returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkObjectTableNVX((VkObjectTableNVX*)&objectTable);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyObjectTableNVX");;
 }
 
@@ -19783,7 +20215,7 @@
     const VkObjectTableEntryNVX* const* ppObjectTableEntries,
     const uint32_t* pObjectIndices)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkRegisterObjectsNVX encode");
     mImpl->log("start vkRegisterObjectsNVX");
     auto stream = mImpl->stream();
@@ -19836,9 +20268,9 @@
     AEMU_SCOPED_TRACE("vkRegisterObjectsNVX returnUnmarshal");
     VkResult vkRegisterObjectsNVX_VkResult_return = (VkResult)0;
     stream->read(&vkRegisterObjectsNVX_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkRegisterObjectsNVX");;
     return vkRegisterObjectsNVX_VkResult_return;
 }
@@ -19850,7 +20282,7 @@
     const VkObjectEntryTypeNVX* pObjectEntryTypes,
     const uint32_t* pObjectIndices)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkUnregisterObjectsNVX encode");
     mImpl->log("start vkUnregisterObjectsNVX");
     auto stream = mImpl->stream();
@@ -19906,9 +20338,9 @@
     AEMU_SCOPED_TRACE("vkUnregisterObjectsNVX returnUnmarshal");
     VkResult vkUnregisterObjectsNVX_VkResult_return = (VkResult)0;
     stream->read(&vkUnregisterObjectsNVX_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkUnregisterObjectsNVX");;
     return vkUnregisterObjectsNVX_VkResult_return;
 }
@@ -19918,7 +20350,7 @@
     VkDeviceGeneratedCommandsFeaturesNVX* pFeatures,
     VkDeviceGeneratedCommandsLimitsNVX* pLimits)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX encode");
     mImpl->log("start vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX");
     auto stream = mImpl->stream();
@@ -19958,6 +20390,9 @@
         transform_fromhost_VkDeviceGeneratedCommandsLimitsNVX(mImpl->resources(), (VkDeviceGeneratedCommandsLimitsNVX*)(pLimits));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX");;
 }
 
@@ -19969,7 +20404,7 @@
     uint32_t viewportCount,
     const VkViewportWScalingNV* pViewportWScalings)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetViewportWScalingNV encode");
     mImpl->log("start vkCmdSetViewportWScalingNV");
     auto stream = mImpl->stream();
@@ -20028,6 +20463,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdSetViewportWScalingNV readParams");
     AEMU_SCOPED_TRACE("vkCmdSetViewportWScalingNV returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetViewportWScalingNV");;
 }
 
@@ -20037,7 +20475,7 @@
     VkPhysicalDevice physicalDevice,
     VkDisplayKHR display)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkReleaseDisplayEXT encode");
     mImpl->log("start vkReleaseDisplayEXT");
     auto stream = mImpl->stream();
@@ -20073,9 +20511,9 @@
     AEMU_SCOPED_TRACE("vkReleaseDisplayEXT returnUnmarshal");
     VkResult vkReleaseDisplayEXT_VkResult_return = (VkResult)0;
     stream->read(&vkReleaseDisplayEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkReleaseDisplayEXT");;
     return vkReleaseDisplayEXT_VkResult_return;
 }
@@ -20087,7 +20525,7 @@
     Display* dpy,
     VkDisplayKHR display)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkAcquireXlibDisplayEXT encode");
     mImpl->log("start vkAcquireXlibDisplayEXT");
     auto stream = mImpl->stream();
@@ -20126,9 +20564,9 @@
     AEMU_SCOPED_TRACE("vkAcquireXlibDisplayEXT returnUnmarshal");
     VkResult vkAcquireXlibDisplayEXT_VkResult_return = (VkResult)0;
     stream->read(&vkAcquireXlibDisplayEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkAcquireXlibDisplayEXT");;
     return vkAcquireXlibDisplayEXT_VkResult_return;
 }
@@ -20139,7 +20577,7 @@
     RROutput rrOutput,
     VkDisplayKHR* pDisplay)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetRandROutputDisplayEXT encode");
     mImpl->log("start vkGetRandROutputDisplayEXT");
     auto stream = mImpl->stream();
@@ -20185,9 +20623,9 @@
     AEMU_SCOPED_TRACE("vkGetRandROutputDisplayEXT returnUnmarshal");
     VkResult vkGetRandROutputDisplayEXT_VkResult_return = (VkResult)0;
     stream->read(&vkGetRandROutputDisplayEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetRandROutputDisplayEXT");;
     return vkGetRandROutputDisplayEXT_VkResult_return;
 }
@@ -20199,7 +20637,7 @@
     VkSurfaceKHR surface,
     VkSurfaceCapabilities2EXT* pSurfaceCapabilities)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceCapabilities2EXT encode");
     mImpl->log("start vkGetPhysicalDeviceSurfaceCapabilities2EXT");
     auto stream = mImpl->stream();
@@ -20242,9 +20680,9 @@
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceSurfaceCapabilities2EXT returnUnmarshal");
     VkResult vkGetPhysicalDeviceSurfaceCapabilities2EXT_VkResult_return = (VkResult)0;
     stream->read(&vkGetPhysicalDeviceSurfaceCapabilities2EXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPhysicalDeviceSurfaceCapabilities2EXT");;
     return vkGetPhysicalDeviceSurfaceCapabilities2EXT_VkResult_return;
 }
@@ -20256,7 +20694,7 @@
     VkDisplayKHR display,
     const VkDisplayPowerInfoEXT* pDisplayPowerInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDisplayPowerControlEXT encode");
     mImpl->log("start vkDisplayPowerControlEXT");
     auto stream = mImpl->stream();
@@ -20305,9 +20743,9 @@
     AEMU_SCOPED_TRACE("vkDisplayPowerControlEXT returnUnmarshal");
     VkResult vkDisplayPowerControlEXT_VkResult_return = (VkResult)0;
     stream->read(&vkDisplayPowerControlEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkDisplayPowerControlEXT");;
     return vkDisplayPowerControlEXT_VkResult_return;
 }
@@ -20318,7 +20756,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkFence* pFence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkRegisterDeviceEventEXT encode");
     mImpl->log("start vkRegisterDeviceEventEXT");
     auto stream = mImpl->stream();
@@ -20396,9 +20834,9 @@
     AEMU_SCOPED_TRACE("vkRegisterDeviceEventEXT returnUnmarshal");
     VkResult vkRegisterDeviceEventEXT_VkResult_return = (VkResult)0;
     stream->read(&vkRegisterDeviceEventEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkRegisterDeviceEventEXT");;
     return vkRegisterDeviceEventEXT_VkResult_return;
 }
@@ -20410,7 +20848,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkFence* pFence)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkRegisterDisplayEventEXT encode");
     mImpl->log("start vkRegisterDisplayEventEXT");
     auto stream = mImpl->stream();
@@ -20496,9 +20934,9 @@
     AEMU_SCOPED_TRACE("vkRegisterDisplayEventEXT returnUnmarshal");
     VkResult vkRegisterDisplayEventEXT_VkResult_return = (VkResult)0;
     stream->read(&vkRegisterDisplayEventEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkRegisterDisplayEventEXT");;
     return vkRegisterDisplayEventEXT_VkResult_return;
 }
@@ -20509,7 +20947,7 @@
     VkSurfaceCounterFlagBitsEXT counter,
     uint64_t* pCounterValue)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetSwapchainCounterEXT encode");
     mImpl->log("start vkGetSwapchainCounterEXT");
     auto stream = mImpl->stream();
@@ -20552,9 +20990,9 @@
     AEMU_SCOPED_TRACE("vkGetSwapchainCounterEXT returnUnmarshal");
     VkResult vkGetSwapchainCounterEXT_VkResult_return = (VkResult)0;
     stream->read(&vkGetSwapchainCounterEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetSwapchainCounterEXT");;
     return vkGetSwapchainCounterEXT_VkResult_return;
 }
@@ -20566,7 +21004,7 @@
     VkSwapchainKHR swapchain,
     VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetRefreshCycleDurationGOOGLE encode");
     mImpl->log("start vkGetRefreshCycleDurationGOOGLE");
     auto stream = mImpl->stream();
@@ -20609,9 +21047,9 @@
     AEMU_SCOPED_TRACE("vkGetRefreshCycleDurationGOOGLE returnUnmarshal");
     VkResult vkGetRefreshCycleDurationGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkGetRefreshCycleDurationGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetRefreshCycleDurationGOOGLE");;
     return vkGetRefreshCycleDurationGOOGLE_VkResult_return;
 }
@@ -20622,7 +21060,7 @@
     uint32_t* pPresentationTimingCount,
     VkPastPresentationTimingGOOGLE* pPresentationTimings)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPastPresentationTimingGOOGLE encode");
     mImpl->log("start vkGetPastPresentationTimingGOOGLE");
     auto stream = mImpl->stream();
@@ -20724,9 +21162,9 @@
     AEMU_SCOPED_TRACE("vkGetPastPresentationTimingGOOGLE returnUnmarshal");
     VkResult vkGetPastPresentationTimingGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkGetPastPresentationTimingGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetPastPresentationTimingGOOGLE");;
     return vkGetPastPresentationTimingGOOGLE_VkResult_return;
 }
@@ -20749,7 +21187,7 @@
     uint32_t discardRectangleCount,
     const VkRect2D* pDiscardRectangles)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetDiscardRectangleEXT encode");
     mImpl->log("start vkCmdSetDiscardRectangleEXT");
     auto stream = mImpl->stream();
@@ -20808,6 +21246,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdSetDiscardRectangleEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdSetDiscardRectangleEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetDiscardRectangleEXT");;
 }
 
@@ -20823,7 +21264,7 @@
     const VkSwapchainKHR* pSwapchains,
     const VkHdrMetadataEXT* pMetadata)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkSetHdrMetadataEXT encode");
     mImpl->log("start vkSetHdrMetadataEXT");
     auto stream = mImpl->stream();
@@ -20898,6 +21339,9 @@
     }
     AEMU_SCOPED_TRACE("vkSetHdrMetadataEXT readParams");
     AEMU_SCOPED_TRACE("vkSetHdrMetadataEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkSetHdrMetadataEXT");;
 }
 
@@ -20909,7 +21353,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateIOSSurfaceMVK encode");
     mImpl->log("start vkCreateIOSSurfaceMVK");
     auto stream = mImpl->stream();
@@ -20987,9 +21431,9 @@
     AEMU_SCOPED_TRACE("vkCreateIOSSurfaceMVK returnUnmarshal");
     VkResult vkCreateIOSSurfaceMVK_VkResult_return = (VkResult)0;
     stream->read(&vkCreateIOSSurfaceMVK_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateIOSSurfaceMVK");;
     return vkCreateIOSSurfaceMVK_VkResult_return;
 }
@@ -21002,7 +21446,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkSurfaceKHR* pSurface)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateMacOSSurfaceMVK encode");
     mImpl->log("start vkCreateMacOSSurfaceMVK");
     auto stream = mImpl->stream();
@@ -21080,9 +21524,9 @@
     AEMU_SCOPED_TRACE("vkCreateMacOSSurfaceMVK returnUnmarshal");
     VkResult vkCreateMacOSSurfaceMVK_VkResult_return = (VkResult)0;
     stream->read(&vkCreateMacOSSurfaceMVK_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateMacOSSurfaceMVK");;
     return vkCreateMacOSSurfaceMVK_VkResult_return;
 }
@@ -21097,7 +21541,7 @@
     VkDevice device,
     const VkDebugUtilsObjectNameInfoEXT* pNameInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkSetDebugUtilsObjectNameEXT encode");
     mImpl->log("start vkSetDebugUtilsObjectNameEXT");
     auto stream = mImpl->stream();
@@ -21138,9 +21582,9 @@
     AEMU_SCOPED_TRACE("vkSetDebugUtilsObjectNameEXT returnUnmarshal");
     VkResult vkSetDebugUtilsObjectNameEXT_VkResult_return = (VkResult)0;
     stream->read(&vkSetDebugUtilsObjectNameEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkSetDebugUtilsObjectNameEXT");;
     return vkSetDebugUtilsObjectNameEXT_VkResult_return;
 }
@@ -21149,7 +21593,7 @@
     VkDevice device,
     const VkDebugUtilsObjectTagInfoEXT* pTagInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkSetDebugUtilsObjectTagEXT encode");
     mImpl->log("start vkSetDebugUtilsObjectTagEXT");
     auto stream = mImpl->stream();
@@ -21190,9 +21634,9 @@
     AEMU_SCOPED_TRACE("vkSetDebugUtilsObjectTagEXT returnUnmarshal");
     VkResult vkSetDebugUtilsObjectTagEXT_VkResult_return = (VkResult)0;
     stream->read(&vkSetDebugUtilsObjectTagEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkSetDebugUtilsObjectTagEXT");;
     return vkSetDebugUtilsObjectTagEXT_VkResult_return;
 }
@@ -21201,7 +21645,7 @@
     VkQueue queue,
     const VkDebugUtilsLabelEXT* pLabelInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueBeginDebugUtilsLabelEXT encode");
     mImpl->log("start vkQueueBeginDebugUtilsLabelEXT");
     auto stream = mImpl->stream();
@@ -21240,13 +21684,16 @@
     marshal_VkDebugUtilsLabelEXT(stream, (VkDebugUtilsLabelEXT*)(local_pLabelInfo));
     AEMU_SCOPED_TRACE("vkQueueBeginDebugUtilsLabelEXT readParams");
     AEMU_SCOPED_TRACE("vkQueueBeginDebugUtilsLabelEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkQueueBeginDebugUtilsLabelEXT");;
 }
 
 void VkEncoder::vkQueueEndDebugUtilsLabelEXT(
     VkQueue queue)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueEndDebugUtilsLabelEXT encode");
     mImpl->log("start vkQueueEndDebugUtilsLabelEXT");
     auto stream = mImpl->stream();
@@ -21272,6 +21719,9 @@
     stream->write((uint64_t*)&cgen_var_1393, 1 * 8);
     AEMU_SCOPED_TRACE("vkQueueEndDebugUtilsLabelEXT readParams");
     AEMU_SCOPED_TRACE("vkQueueEndDebugUtilsLabelEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkQueueEndDebugUtilsLabelEXT");;
 }
 
@@ -21279,7 +21729,7 @@
     VkQueue queue,
     const VkDebugUtilsLabelEXT* pLabelInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkQueueInsertDebugUtilsLabelEXT encode");
     mImpl->log("start vkQueueInsertDebugUtilsLabelEXT");
     auto stream = mImpl->stream();
@@ -21318,6 +21768,9 @@
     marshal_VkDebugUtilsLabelEXT(stream, (VkDebugUtilsLabelEXT*)(local_pLabelInfo));
     AEMU_SCOPED_TRACE("vkQueueInsertDebugUtilsLabelEXT readParams");
     AEMU_SCOPED_TRACE("vkQueueInsertDebugUtilsLabelEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkQueueInsertDebugUtilsLabelEXT");;
 }
 
@@ -21325,7 +21778,7 @@
     VkCommandBuffer commandBuffer,
     const VkDebugUtilsLabelEXT* pLabelInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdBeginDebugUtilsLabelEXT encode");
     mImpl->log("start vkCmdBeginDebugUtilsLabelEXT");
     auto stream = mImpl->stream();
@@ -21364,13 +21817,16 @@
     marshal_VkDebugUtilsLabelEXT(stream, (VkDebugUtilsLabelEXT*)(local_pLabelInfo));
     AEMU_SCOPED_TRACE("vkCmdBeginDebugUtilsLabelEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdBeginDebugUtilsLabelEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdBeginDebugUtilsLabelEXT");;
 }
 
 void VkEncoder::vkCmdEndDebugUtilsLabelEXT(
     VkCommandBuffer commandBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdEndDebugUtilsLabelEXT encode");
     mImpl->log("start vkCmdEndDebugUtilsLabelEXT");
     auto stream = mImpl->stream();
@@ -21396,6 +21852,9 @@
     stream->write((uint64_t*)&cgen_var_1399, 1 * 8);
     AEMU_SCOPED_TRACE("vkCmdEndDebugUtilsLabelEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdEndDebugUtilsLabelEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdEndDebugUtilsLabelEXT");;
 }
 
@@ -21403,7 +21862,7 @@
     VkCommandBuffer commandBuffer,
     const VkDebugUtilsLabelEXT* pLabelInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdInsertDebugUtilsLabelEXT encode");
     mImpl->log("start vkCmdInsertDebugUtilsLabelEXT");
     auto stream = mImpl->stream();
@@ -21442,6 +21901,9 @@
     marshal_VkDebugUtilsLabelEXT(stream, (VkDebugUtilsLabelEXT*)(local_pLabelInfo));
     AEMU_SCOPED_TRACE("vkCmdInsertDebugUtilsLabelEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdInsertDebugUtilsLabelEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdInsertDebugUtilsLabelEXT");;
 }
 
@@ -21451,7 +21913,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkDebugUtilsMessengerEXT* pMessenger)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateDebugUtilsMessengerEXT encode");
     mImpl->log("start vkCreateDebugUtilsMessengerEXT");
     auto stream = mImpl->stream();
@@ -21531,9 +21993,9 @@
     AEMU_SCOPED_TRACE("vkCreateDebugUtilsMessengerEXT returnUnmarshal");
     VkResult vkCreateDebugUtilsMessengerEXT_VkResult_return = (VkResult)0;
     stream->read(&vkCreateDebugUtilsMessengerEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateDebugUtilsMessengerEXT");;
     return vkCreateDebugUtilsMessengerEXT_VkResult_return;
 }
@@ -21543,7 +22005,7 @@
     VkDebugUtilsMessengerEXT messenger,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyDebugUtilsMessengerEXT encode");
     mImpl->log("start vkDestroyDebugUtilsMessengerEXT");
     auto stream = mImpl->stream();
@@ -21604,6 +22066,9 @@
     AEMU_SCOPED_TRACE("vkDestroyDebugUtilsMessengerEXT readParams");
     AEMU_SCOPED_TRACE("vkDestroyDebugUtilsMessengerEXT returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkDebugUtilsMessengerEXT((VkDebugUtilsMessengerEXT*)&messenger);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyDebugUtilsMessengerEXT");;
 }
 
@@ -21613,7 +22078,7 @@
     VkDebugUtilsMessageTypeFlagsEXT messageTypes,
     const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkSubmitDebugUtilsMessageEXT encode");
     mImpl->log("start vkSubmitDebugUtilsMessageEXT");
     auto stream = mImpl->stream();
@@ -21660,6 +22125,9 @@
     marshal_VkDebugUtilsMessengerCallbackDataEXT(stream, (VkDebugUtilsMessengerCallbackDataEXT*)(local_pCallbackData));
     AEMU_SCOPED_TRACE("vkSubmitDebugUtilsMessageEXT readParams");
     AEMU_SCOPED_TRACE("vkSubmitDebugUtilsMessageEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkSubmitDebugUtilsMessageEXT");;
 }
 
@@ -21670,7 +22138,7 @@
     const AHardwareBuffer* buffer,
     VkAndroidHardwareBufferPropertiesANDROID* pProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetAndroidHardwareBufferPropertiesANDROID encode");
     mImpl->log("start vkGetAndroidHardwareBufferPropertiesANDROID");
     auto stream = mImpl->stream();
@@ -21713,9 +22181,9 @@
     AEMU_SCOPED_TRACE("vkGetAndroidHardwareBufferPropertiesANDROID returnUnmarshal");
     VkResult vkGetAndroidHardwareBufferPropertiesANDROID_VkResult_return = (VkResult)0;
     stream->read(&vkGetAndroidHardwareBufferPropertiesANDROID_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetAndroidHardwareBufferPropertiesANDROID");;
     return vkGetAndroidHardwareBufferPropertiesANDROID_VkResult_return;
 }
@@ -21725,7 +22193,7 @@
     const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
     AHardwareBuffer** pBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryAndroidHardwareBufferANDROID encode");
     mImpl->log("start vkGetMemoryAndroidHardwareBufferANDROID");
     auto stream = mImpl->stream();
@@ -21769,9 +22237,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryAndroidHardwareBufferANDROID returnUnmarshal");
     VkResult vkGetMemoryAndroidHardwareBufferANDROID_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryAndroidHardwareBufferANDROID_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryAndroidHardwareBufferANDROID");;
     return vkGetMemoryAndroidHardwareBufferANDROID_VkResult_return;
 }
@@ -21792,7 +22260,7 @@
     VkCommandBuffer commandBuffer,
     const VkSampleLocationsInfoEXT* pSampleLocationsInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetSampleLocationsEXT encode");
     mImpl->log("start vkCmdSetSampleLocationsEXT");
     auto stream = mImpl->stream();
@@ -21831,6 +22299,9 @@
     marshal_VkSampleLocationsInfoEXT(stream, (VkSampleLocationsInfoEXT*)(local_pSampleLocationsInfo));
     AEMU_SCOPED_TRACE("vkCmdSetSampleLocationsEXT readParams");
     AEMU_SCOPED_TRACE("vkCmdSetSampleLocationsEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetSampleLocationsEXT");;
 }
 
@@ -21839,7 +22310,7 @@
     VkSampleCountFlagBits samples,
     VkMultisamplePropertiesEXT* pMultisampleProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMultisamplePropertiesEXT encode");
     mImpl->log("start vkGetPhysicalDeviceMultisamplePropertiesEXT");
     auto stream = mImpl->stream();
@@ -21876,6 +22347,9 @@
         transform_fromhost_VkMultisamplePropertiesEXT(mImpl->resources(), (VkMultisamplePropertiesEXT*)(pMultisampleProperties));
     }
     AEMU_SCOPED_TRACE("vkGetPhysicalDeviceMultisamplePropertiesEXT returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetPhysicalDeviceMultisamplePropertiesEXT");;
 }
 
@@ -21897,7 +22371,7 @@
     const VkAllocationCallbacks* pAllocator,
     VkValidationCacheEXT* pValidationCache)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateValidationCacheEXT encode");
     mImpl->log("start vkCreateValidationCacheEXT");
     auto stream = mImpl->stream();
@@ -21977,9 +22451,9 @@
     AEMU_SCOPED_TRACE("vkCreateValidationCacheEXT returnUnmarshal");
     VkResult vkCreateValidationCacheEXT_VkResult_return = (VkResult)0;
     stream->read(&vkCreateValidationCacheEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateValidationCacheEXT");;
     return vkCreateValidationCacheEXT_VkResult_return;
 }
@@ -21989,7 +22463,7 @@
     VkValidationCacheEXT validationCache,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkDestroyValidationCacheEXT encode");
     mImpl->log("start vkDestroyValidationCacheEXT");
     auto stream = mImpl->stream();
@@ -22050,6 +22524,9 @@
     AEMU_SCOPED_TRACE("vkDestroyValidationCacheEXT readParams");
     AEMU_SCOPED_TRACE("vkDestroyValidationCacheEXT returnUnmarshal");
     resources->destroyMapping()->mapHandles_VkValidationCacheEXT((VkValidationCacheEXT*)&validationCache);
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkDestroyValidationCacheEXT");;
 }
 
@@ -22059,7 +22536,7 @@
     uint32_t srcCacheCount,
     const VkValidationCacheEXT* pSrcCaches)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkMergeValidationCachesEXT encode");
     mImpl->log("start vkMergeValidationCachesEXT");
     auto stream = mImpl->stream();
@@ -22119,9 +22596,9 @@
     AEMU_SCOPED_TRACE("vkMergeValidationCachesEXT returnUnmarshal");
     VkResult vkMergeValidationCachesEXT_VkResult_return = (VkResult)0;
     stream->read(&vkMergeValidationCachesEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkMergeValidationCachesEXT");;
     return vkMergeValidationCachesEXT_VkResult_return;
 }
@@ -22132,7 +22609,7 @@
     size_t* pDataSize,
     void* pData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetValidationCacheDataEXT encode");
     mImpl->log("start vkGetValidationCacheDataEXT");
     auto stream = mImpl->stream();
@@ -22220,9 +22697,9 @@
     AEMU_SCOPED_TRACE("vkGetValidationCacheDataEXT returnUnmarshal");
     VkResult vkGetValidationCacheDataEXT_VkResult_return = (VkResult)0;
     stream->read(&vkGetValidationCacheDataEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetValidationCacheDataEXT");;
     return vkGetValidationCacheDataEXT_VkResult_return;
 }
@@ -22241,7 +22718,7 @@
     const void* pHostPointer,
     VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryHostPointerPropertiesEXT encode");
     mImpl->log("start vkGetMemoryHostPointerPropertiesEXT");
     auto stream = mImpl->stream();
@@ -22300,9 +22777,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryHostPointerPropertiesEXT returnUnmarshal");
     VkResult vkGetMemoryHostPointerPropertiesEXT_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryHostPointerPropertiesEXT_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryHostPointerPropertiesEXT");;
     return vkGetMemoryHostPointerPropertiesEXT_VkResult_return;
 }
@@ -22316,7 +22793,7 @@
     VkDeviceSize dstOffset,
     uint32_t marker)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdWriteBufferMarkerAMD encode");
     mImpl->log("start vkCmdWriteBufferMarkerAMD");
     auto stream = mImpl->stream();
@@ -22362,6 +22839,9 @@
     stream->write((uint32_t*)&local_marker, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCmdWriteBufferMarkerAMD readParams");
     AEMU_SCOPED_TRACE("vkCmdWriteBufferMarkerAMD returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdWriteBufferMarkerAMD");;
 }
 
@@ -22377,7 +22857,7 @@
     VkCommandBuffer commandBuffer,
     const void* pCheckpointMarker)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCmdSetCheckpointNV encode");
     mImpl->log("start vkCmdSetCheckpointNV");
     auto stream = mImpl->stream();
@@ -22423,6 +22903,9 @@
     }
     AEMU_SCOPED_TRACE("vkCmdSetCheckpointNV readParams");
     AEMU_SCOPED_TRACE("vkCmdSetCheckpointNV returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCmdSetCheckpointNV");;
 }
 
@@ -22431,7 +22914,7 @@
     uint32_t* pCheckpointDataCount,
     VkCheckpointDataNV* pCheckpointData)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetQueueCheckpointDataNV encode");
     mImpl->log("start vkGetQueueCheckpointDataNV");
     auto stream = mImpl->stream();
@@ -22523,6 +23006,9 @@
         }
     }
     AEMU_SCOPED_TRACE("vkGetQueueCheckpointDataNV returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkGetQueueCheckpointDataNV");;
 }
 
@@ -22533,12 +23019,10 @@
     VkDeviceMemory memory,
     uint64_t* pAddress)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkMapMemoryIntoAddressSpaceGOOGLE encode");
     mImpl->log("start vkMapMemoryIntoAddressSpaceGOOGLE");
-    encoderLock.unlock();
     mImpl->resources()->on_vkMapMemoryIntoAddressSpaceGOOGLE_pre(this, VK_SUCCESS, device, memory, pAddress);
-    encoderLock.lock();
     auto stream = mImpl->stream();
     auto countingStream = mImpl->countingStream();
     auto resources = mImpl->resources();
@@ -22598,12 +23082,10 @@
     AEMU_SCOPED_TRACE("vkMapMemoryIntoAddressSpaceGOOGLE returnUnmarshal");
     VkResult vkMapMemoryIntoAddressSpaceGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkMapMemoryIntoAddressSpaceGOOGLE_VkResult_return, sizeof(VkResult));
+    mImpl->resources()->on_vkMapMemoryIntoAddressSpaceGOOGLE(this, vkMapMemoryIntoAddressSpaceGOOGLE_VkResult_return, device, memory, pAddress);
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
-    encoderLock.unlock();
-    mImpl->resources()->on_vkMapMemoryIntoAddressSpaceGOOGLE(this, vkMapMemoryIntoAddressSpaceGOOGLE_VkResult_return, device, memory, pAddress);
-    encoderLock.lock();
     mImpl->log("finish vkMapMemoryIntoAddressSpaceGOOGLE");;
     return vkMapMemoryIntoAddressSpaceGOOGLE_VkResult_return;
 }
@@ -22615,7 +23097,7 @@
     VkImage image,
     uint32_t colorBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkRegisterImageColorBufferGOOGLE encode");
     mImpl->log("start vkRegisterImageColorBufferGOOGLE");
     auto stream = mImpl->stream();
@@ -22655,9 +23137,9 @@
     AEMU_SCOPED_TRACE("vkRegisterImageColorBufferGOOGLE returnUnmarshal");
     VkResult vkRegisterImageColorBufferGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkRegisterImageColorBufferGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkRegisterImageColorBufferGOOGLE");;
     return vkRegisterImageColorBufferGOOGLE_VkResult_return;
 }
@@ -22667,7 +23149,7 @@
     VkBuffer buffer,
     uint32_t colorBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkRegisterBufferColorBufferGOOGLE encode");
     mImpl->log("start vkRegisterBufferColorBufferGOOGLE");
     auto stream = mImpl->stream();
@@ -22707,9 +23189,9 @@
     AEMU_SCOPED_TRACE("vkRegisterBufferColorBufferGOOGLE returnUnmarshal");
     VkResult vkRegisterBufferColorBufferGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkRegisterBufferColorBufferGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkRegisterBufferColorBufferGOOGLE");;
     return vkRegisterBufferColorBufferGOOGLE_VkResult_return;
 }
@@ -22730,7 +23212,7 @@
     const VkDescriptorBufferInfo* pBufferInfos,
     const VkBufferView* pBufferViews)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE encode");
     mImpl->log("start vkUpdateDescriptorSetWithTemplateSizedGOOGLE");
     auto stream = mImpl->stream();
@@ -22950,6 +23432,9 @@
     }
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE readParams");
     AEMU_SCOPED_TRACE("vkUpdateDescriptorSetWithTemplateSizedGOOGLE returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkUpdateDescriptorSetWithTemplateSizedGOOGLE");;
 }
 
@@ -22959,7 +23444,7 @@
     VkCommandBuffer commandBuffer,
     const VkCommandBufferBeginInfo* pBeginInfo)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE encode");
     mImpl->log("start vkBeginCommandBufferAsyncGOOGLE");
     auto stream = mImpl->stream();
@@ -22998,13 +23483,16 @@
     marshal_VkCommandBufferBeginInfo(stream, (VkCommandBufferBeginInfo*)(local_pBeginInfo));
     AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE readParams");
     AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkBeginCommandBufferAsyncGOOGLE");;
 }
 
 void VkEncoder::vkEndCommandBufferAsyncGOOGLE(
     VkCommandBuffer commandBuffer)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE encode");
     mImpl->log("start vkEndCommandBufferAsyncGOOGLE");
     auto stream = mImpl->stream();
@@ -23030,6 +23518,10 @@
     stream->write((uint64_t*)&cgen_var_1515, 1 * 8);
     AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE readParams");
     AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE returnUnmarshal");
+    stream->flush();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkEndCommandBufferAsyncGOOGLE");;
 }
 
@@ -23037,7 +23529,7 @@
     VkCommandBuffer commandBuffer,
     VkCommandBufferResetFlags flags)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE encode");
     mImpl->log("start vkResetCommandBufferAsyncGOOGLE");
     auto stream = mImpl->stream();
@@ -23067,6 +23559,9 @@
     stream->write((VkCommandBufferResetFlags*)&local_flags, sizeof(VkCommandBufferResetFlags));
     AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE readParams");
     AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkResetCommandBufferAsyncGOOGLE");;
 }
 
@@ -23075,7 +23570,7 @@
     uint32_t needHostSync,
     uint32_t sequenceNumber)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCommandBufferHostSyncGOOGLE encode");
     mImpl->log("start vkCommandBufferHostSyncGOOGLE");
     auto stream = mImpl->stream();
@@ -23109,6 +23604,9 @@
     stream->write((uint32_t*)&local_sequenceNumber, sizeof(uint32_t));
     AEMU_SCOPED_TRACE("vkCommandBufferHostSyncGOOGLE readParams");
     AEMU_SCOPED_TRACE("vkCommandBufferHostSyncGOOGLE returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
     mImpl->log("finish vkCommandBufferHostSyncGOOGLE");;
 }
 
@@ -23121,7 +23619,7 @@
     VkImage* pImage,
     VkMemoryRequirements* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE encode");
     mImpl->log("start vkCreateImageWithRequirementsGOOGLE");
     auto stream = mImpl->stream();
@@ -23209,9 +23707,9 @@
     AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE returnUnmarshal");
     VkResult vkCreateImageWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkCreateImageWithRequirementsGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateImageWithRequirementsGOOGLE");;
     return vkCreateImageWithRequirementsGOOGLE_VkResult_return;
 }
@@ -23223,7 +23721,7 @@
     VkBuffer* pBuffer,
     VkMemoryRequirements* pMemoryRequirements)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE encode");
     mImpl->log("start vkCreateBufferWithRequirementsGOOGLE");
     auto stream = mImpl->stream();
@@ -23310,9 +23808,9 @@
     AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE returnUnmarshal");
     VkResult vkCreateBufferWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkCreateBufferWithRequirementsGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkCreateBufferWithRequirementsGOOGLE");;
     return vkCreateBufferWithRequirementsGOOGLE_VkResult_return;
 }
@@ -23326,7 +23824,7 @@
     uint64_t* pSize,
     uint64_t* pHostmemId)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE encode");
     mImpl->log("start vkGetMemoryHostAddressInfoGOOGLE");
     auto stream = mImpl->stream();
@@ -23438,9 +23936,9 @@
     AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE returnUnmarshal");
     VkResult vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkGetMemoryHostAddressInfoGOOGLE_VkResult_return, sizeof(VkResult));
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
     mImpl->log("finish vkGetMemoryHostAddressInfoGOOGLE");;
     return vkGetMemoryHostAddressInfoGOOGLE_VkResult_return;
 }
@@ -23452,7 +23950,7 @@
     VkDeviceMemory memory,
     const VkAllocationCallbacks* pAllocator)
 {
-    AutoLock encoderLock(mImpl->lock);
+    EncoderAutoLock encoderLock(this);
     AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE encode");
     mImpl->log("start vkFreeMemorySyncGOOGLE");
     auto stream = mImpl->stream();
@@ -23511,14 +24009,249 @@
     AEMU_SCOPED_TRACE("vkFreeMemorySyncGOOGLE returnUnmarshal");
     VkResult vkFreeMemorySyncGOOGLE_VkResult_return = (VkResult)0;
     stream->read(&vkFreeMemorySyncGOOGLE_VkResult_return, sizeof(VkResult));
+    resources->destroyMapping()->mapHandles_VkDeviceMemory((VkDeviceMemory*)&memory);
+    pool->freeAll();
     countingStream->clearPool();
     stream->clearPool();
-    pool->freeAll();
-    resources->destroyMapping()->mapHandles_VkDeviceMemory((VkDeviceMemory*)&memory);
     mImpl->log("finish vkFreeMemorySyncGOOGLE");;
     return vkFreeMemorySyncGOOGLE_VkResult_return;
 }
 
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+void VkEncoder::vkQueueHostSyncGOOGLE(
+    VkQueue queue,
+    uint32_t needHostSync,
+    uint32_t sequenceNumber)
+{
+    EncoderAutoLock encoderLock(this);
+    AEMU_SCOPED_TRACE("vkQueueHostSyncGOOGLE encode");
+    mImpl->log("start vkQueueHostSyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkQueue local_queue;
+    uint32_t local_needHostSync;
+    uint32_t local_sequenceNumber;
+    local_queue = queue;
+    local_needHostSync = needHostSync;
+    local_sequenceNumber = sequenceNumber;
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1553;
+        countingStream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1553, 1);
+        countingStream->write((uint64_t*)&cgen_var_1553, 1 * 8);
+        countingStream->write((uint32_t*)&local_needHostSync, sizeof(uint32_t));
+        countingStream->write((uint32_t*)&local_sequenceNumber, sizeof(uint32_t));
+    }
+    uint32_t packetSize_vkQueueHostSyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkQueueHostSyncGOOGLE = OP_vkQueueHostSyncGOOGLE;
+    stream->write(&opcode_vkQueueHostSyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkQueueHostSyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1554;
+    stream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1554, 1);
+    stream->write((uint64_t*)&cgen_var_1554, 1 * 8);
+    stream->write((uint32_t*)&local_needHostSync, sizeof(uint32_t));
+    stream->write((uint32_t*)&local_sequenceNumber, sizeof(uint32_t));
+    AEMU_SCOPED_TRACE("vkQueueHostSyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkQueueHostSyncGOOGLE returnUnmarshal");
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
+    mImpl->log("finish vkQueueHostSyncGOOGLE");;
+}
+
+void VkEncoder::vkQueueSubmitAsyncGOOGLE(
+    VkQueue queue,
+    uint32_t submitCount,
+    const VkSubmitInfo* pSubmits,
+    VkFence fence)
+{
+    EncoderAutoLock encoderLock(this);
+    AEMU_SCOPED_TRACE("vkQueueSubmitAsyncGOOGLE encode");
+    mImpl->log("start vkQueueSubmitAsyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkQueue local_queue;
+    uint32_t local_submitCount;
+    VkSubmitInfo* local_pSubmits;
+    VkFence local_fence;
+    local_queue = queue;
+    local_submitCount = submitCount;
+    local_pSubmits = nullptr;
+    if (pSubmits)
+    {
+        local_pSubmits = (VkSubmitInfo*)pool->alloc(((submitCount)) * sizeof(const VkSubmitInfo));
+        for (uint32_t i = 0; i < (uint32_t)((submitCount)); ++i)
+        {
+            deepcopy_VkSubmitInfo(pool, pSubmits + i, (VkSubmitInfo*)(local_pSubmits + i));
+        }
+    }
+    local_fence = fence;
+    if (local_pSubmits)
+    {
+        for (uint32_t i = 0; i < (uint32_t)((submitCount)); ++i)
+        {
+            transform_tohost_VkSubmitInfo(mImpl->resources(), (VkSubmitInfo*)(local_pSubmits + i));
+        }
+    }
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1555;
+        countingStream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1555, 1);
+        countingStream->write((uint64_t*)&cgen_var_1555, 1 * 8);
+        countingStream->write((uint32_t*)&local_submitCount, sizeof(uint32_t));
+        for (uint32_t i = 0; i < (uint32_t)((submitCount)); ++i)
+        {
+            marshal_VkSubmitInfo(countingStream, (VkSubmitInfo*)(local_pSubmits + i));
+        }
+        uint64_t cgen_var_1556;
+        countingStream->handleMapping()->mapHandles_VkFence_u64(&local_fence, &cgen_var_1556, 1);
+        countingStream->write((uint64_t*)&cgen_var_1556, 1 * 8);
+    }
+    uint32_t packetSize_vkQueueSubmitAsyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkQueueSubmitAsyncGOOGLE = OP_vkQueueSubmitAsyncGOOGLE;
+    stream->write(&opcode_vkQueueSubmitAsyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkQueueSubmitAsyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1557;
+    stream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1557, 1);
+    stream->write((uint64_t*)&cgen_var_1557, 1 * 8);
+    stream->write((uint32_t*)&local_submitCount, sizeof(uint32_t));
+    for (uint32_t i = 0; i < (uint32_t)((submitCount)); ++i)
+    {
+        marshal_VkSubmitInfo(stream, (VkSubmitInfo*)(local_pSubmits + i));
+    }
+    uint64_t cgen_var_1558;
+    stream->handleMapping()->mapHandles_VkFence_u64(&local_fence, &cgen_var_1558, 1);
+    stream->write((uint64_t*)&cgen_var_1558, 1 * 8);
+    AEMU_SCOPED_TRACE("vkQueueSubmitAsyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkQueueSubmitAsyncGOOGLE returnUnmarshal");
+    stream->flush();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
+    mImpl->log("finish vkQueueSubmitAsyncGOOGLE");;
+}
+
+void VkEncoder::vkQueueWaitIdleAsyncGOOGLE(
+    VkQueue queue)
+{
+    EncoderAutoLock encoderLock(this);
+    AEMU_SCOPED_TRACE("vkQueueWaitIdleAsyncGOOGLE encode");
+    mImpl->log("start vkQueueWaitIdleAsyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkQueue local_queue;
+    local_queue = queue;
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1559;
+        countingStream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1559, 1);
+        countingStream->write((uint64_t*)&cgen_var_1559, 1 * 8);
+    }
+    uint32_t packetSize_vkQueueWaitIdleAsyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkQueueWaitIdleAsyncGOOGLE = OP_vkQueueWaitIdleAsyncGOOGLE;
+    stream->write(&opcode_vkQueueWaitIdleAsyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkQueueWaitIdleAsyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1560;
+    stream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1560, 1);
+    stream->write((uint64_t*)&cgen_var_1560, 1 * 8);
+    AEMU_SCOPED_TRACE("vkQueueWaitIdleAsyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkQueueWaitIdleAsyncGOOGLE returnUnmarshal");
+    stream->flush();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
+    mImpl->log("finish vkQueueWaitIdleAsyncGOOGLE");;
+}
+
+void VkEncoder::vkQueueBindSparseAsyncGOOGLE(
+    VkQueue queue,
+    uint32_t bindInfoCount,
+    const VkBindSparseInfo* pBindInfo,
+    VkFence fence)
+{
+    EncoderAutoLock encoderLock(this);
+    AEMU_SCOPED_TRACE("vkQueueBindSparseAsyncGOOGLE encode");
+    mImpl->log("start vkQueueBindSparseAsyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkQueue local_queue;
+    uint32_t local_bindInfoCount;
+    VkBindSparseInfo* local_pBindInfo;
+    VkFence local_fence;
+    local_queue = queue;
+    local_bindInfoCount = bindInfoCount;
+    local_pBindInfo = nullptr;
+    if (pBindInfo)
+    {
+        local_pBindInfo = (VkBindSparseInfo*)pool->alloc(((bindInfoCount)) * sizeof(const VkBindSparseInfo));
+        for (uint32_t i = 0; i < (uint32_t)((bindInfoCount)); ++i)
+        {
+            deepcopy_VkBindSparseInfo(pool, pBindInfo + i, (VkBindSparseInfo*)(local_pBindInfo + i));
+        }
+    }
+    local_fence = fence;
+    if (local_pBindInfo)
+    {
+        for (uint32_t i = 0; i < (uint32_t)((bindInfoCount)); ++i)
+        {
+            transform_tohost_VkBindSparseInfo(mImpl->resources(), (VkBindSparseInfo*)(local_pBindInfo + i));
+        }
+    }
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1561;
+        countingStream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1561, 1);
+        countingStream->write((uint64_t*)&cgen_var_1561, 1 * 8);
+        countingStream->write((uint32_t*)&local_bindInfoCount, sizeof(uint32_t));
+        for (uint32_t i = 0; i < (uint32_t)((bindInfoCount)); ++i)
+        {
+            marshal_VkBindSparseInfo(countingStream, (VkBindSparseInfo*)(local_pBindInfo + i));
+        }
+        uint64_t cgen_var_1562;
+        countingStream->handleMapping()->mapHandles_VkFence_u64(&local_fence, &cgen_var_1562, 1);
+        countingStream->write((uint64_t*)&cgen_var_1562, 1 * 8);
+    }
+    uint32_t packetSize_vkQueueBindSparseAsyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkQueueBindSparseAsyncGOOGLE = OP_vkQueueBindSparseAsyncGOOGLE;
+    stream->write(&opcode_vkQueueBindSparseAsyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkQueueBindSparseAsyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1563;
+    stream->handleMapping()->mapHandles_VkQueue_u64(&local_queue, &cgen_var_1563, 1);
+    stream->write((uint64_t*)&cgen_var_1563, 1 * 8);
+    stream->write((uint32_t*)&local_bindInfoCount, sizeof(uint32_t));
+    for (uint32_t i = 0; i < (uint32_t)((bindInfoCount)); ++i)
+    {
+        marshal_VkBindSparseInfo(stream, (VkBindSparseInfo*)(local_pBindInfo + i));
+    }
+    uint64_t cgen_var_1564;
+    stream->handleMapping()->mapHandles_VkFence_u64(&local_fence, &cgen_var_1564, 1);
+    stream->write((uint64_t*)&cgen_var_1564, 1 * 8);
+    AEMU_SCOPED_TRACE("vkQueueBindSparseAsyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkQueueBindSparseAsyncGOOGLE returnUnmarshal");
+    stream->flush();
+    pool->freeAll();
+    countingStream->clearPool();
+    stream->clearPool();
+    mImpl->log("finish vkQueueBindSparseAsyncGOOGLE");;
+}
+
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h
index 7e2e739..bde9ab8 100644
--- a/system/vulkan_enc/VkEncoder.h
+++ b/system/vulkan_enc/VkEncoder.h
@@ -28,7 +28,6 @@
 
 
 #include "goldfish_vk_private_defs.h"
-#include <functional>
 #include <memory>
 class IOStream;
 
@@ -42,10 +41,8 @@
     ~VkEncoder();
 
     void flush();
-
-    using CleanupCallback = std::function<void()>;
-    void registerCleanupCallback(void* handle, CleanupCallback cb);
-    void unregisterCleanupCallback(void* handle);
+    void lock();
+    void unlock();
 #ifdef VK_VERSION_1_0
     VkResult vkCreateInstance(
     const VkInstanceCreateInfo* pCreateInfo,
@@ -1823,6 +1820,24 @@
         VkDeviceMemory memory,
         const VkAllocationCallbacks* pAllocator);
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+    void vkQueueHostSyncGOOGLE(
+    VkQueue queue,
+        uint32_t needHostSync,
+        uint32_t sequenceNumber);
+    void vkQueueSubmitAsyncGOOGLE(
+    VkQueue queue,
+        uint32_t submitCount,
+        const VkSubmitInfo* pSubmits,
+        VkFence fence);
+    void vkQueueWaitIdleAsyncGOOGLE(
+    VkQueue queue);
+    void vkQueueBindSparseAsyncGOOGLE(
+    VkQueue queue,
+        uint32_t bindInfoCount,
+        const VkBindSparseInfo* pBindInfo,
+        VkFence fence);
+#endif
 
 private:
     class Impl;
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index 54699aa..ca1e5f2 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -18,12 +18,12 @@
 
 #define GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkPhysicalDevice) \
-    f(VkQueue) \
 
 #define GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkInstance) \
     f(VkDevice) \
     f(VkCommandBuffer) \
+    f(VkQueue) \
     GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
 
 #ifdef VK_NVX_device_generated_commands
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
index 62fc0f0..4f59d21 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6424,6 +6424,8 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 void deepcopy_extension_struct(
     Pool* pool,
     const void* structExtension,
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
index 07c2650..243240a 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -2044,5 +2044,7 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
index 9d8253b..1bc69fa 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -290,6 +290,8 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 uint32_t goldfish_vk_struct_type(
     const void* structExtension)
 {
diff --git a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
index d615608..9d91cdc 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -311,5 +311,7 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
index 65af4b3..2e22fb0 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
@@ -4780,6 +4780,8 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 void handlemap_extension_struct(
     VulkanHandleMapping* handlemap,
     void* structExtension_out)
diff --git a/system/vulkan_enc/goldfish_vk_handlemap_guest.h b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
index 49eafa2..79eeaf6 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.h
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
@@ -1695,5 +1695,7 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
index 706bb91..f857a2a 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -10368,6 +10368,8 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 void marshal_extension_struct(
     VulkanStreamGuest* vkStream,
     const void* structExtension)
@@ -13221,6 +13223,24 @@
             return "OP_vkFreeMemorySyncGOOGLE";
         }
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+        case OP_vkQueueHostSyncGOOGLE:
+        {
+            return "OP_vkQueueHostSyncGOOGLE";
+        }
+        case OP_vkQueueSubmitAsyncGOOGLE:
+        {
+            return "OP_vkQueueSubmitAsyncGOOGLE";
+        }
+        case OP_vkQueueWaitIdleAsyncGOOGLE:
+        {
+            return "OP_vkQueueWaitIdleAsyncGOOGLE";
+        }
+        case OP_vkQueueBindSparseAsyncGOOGLE:
+        {
+            return "OP_vkQueueBindSparseAsyncGOOGLE";
+        }
+#endif
         default:
         {
             return "OP_UNKNOWN_API_CALL";
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.h b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
index 88ae45e..df07272 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -3418,6 +3418,12 @@
 #ifdef VK_GOOGLE_free_memory_sync
 #define OP_vkFreeMemorySyncGOOGLE 20328
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#define OP_vkQueueHostSyncGOOGLE 20329
+#define OP_vkQueueSubmitAsyncGOOGLE 20330
+#define OP_vkQueueWaitIdleAsyncGOOGLE 20331
+#define OP_vkQueueBindSparseAsyncGOOGLE 20332
+#endif
 const char* api_opcode_to_string(
     const uint32_t opcode);
 
diff --git a/system/vulkan_enc/goldfish_vk_private_defs.h b/system/vulkan_enc/goldfish_vk_private_defs.h
index e7b0622..dc4b7c6 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -608,6 +608,16 @@
 
 #endif
 
+#define VK_GOOGLE_async_queue_submit 1
+
+typedef void (VKAPI_PTR *PFN_vkQueueHostSyncGOOGLE)(
+    VkQueue queue, uint32_t needHostSync, uint32_t sequenceNumber);
+typedef void (VKAPI_PTR *PFN_vkQueueSubmitAsyncGOOGLE)(
+    VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
+typedef void (VKAPI_PTR *PFN_vkQueueWaitIdleAsyncGOOGLE)(VkQueue queue);
+typedef void (VKAPI_PTR *PFN_vkQueueBindSparseAsyncGOOGLE)(
+    VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.cpp b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
index 4bf4032..6fc3e46 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -9001,6 +9001,8 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 void transform_tohost_extension_struct(
     ResourceTracker* resourceTracker,
     void* structExtension_out)
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.h b/system/vulkan_enc/goldfish_vk_transform_guest.h
index 1779eae..b969958 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.h
@@ -3091,5 +3091,7 @@
 #endif
 #ifdef VK_GOOGLE_free_memory_sync
 #endif
+#ifdef VK_GOOGLE_async_queue_submit
+#endif
 
 } // namespace goldfish_vk