[vulkan] Maintain order of begin/end command buffer in deferred mode

bug: 135464985

If we record command buffers in async mode (no return from
vkBegin/EndCommandBuffer) in several guest threads,
it's possible the commands end up out of order when they arrive on the
host, leading to cool bugs.

To ensure the order when async mode is active, we use a special command

vkCommandBufferHostSyncGOOGLE

when the guest thread used to record to a command buffer switches.

Two issues of vkCommandBufferHostSyncGOOGLE are done:

1. The previous encoder issues vkCommandBufferHostSyncGOOGLE with the
previous sequence number.
2. The current encoder issues vkCommandBufferHostSyncGOOGLE with the
incremented sequence number along with a flag to wait on the host for
the vkCommandBufferHostSyncGOOGLE with the previous sequence number.
3. If the previous encoder is destroyed, we register a cleanup callback
that updates the pointer accordingly, so that we dont perform a stale
access.

By introducing this new command, we can then record command buffers
completely async and avoid having to add sequence numbers
to every command buffer recording API.

Note: We previously explored a solution where all command buffer
recording to be in one pipe, to implicitly accomplish ordering of
command buffer APIs. However, that turned out to be extremely difficult
to synchronize with other Vulkan APIs that were not concerned with
command buffer recording, as they could and sometimes need to run in
their separate threads.

Change-Id: I093be0a1600f22e0a355536d1671acdce3852541
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index f5b380e..f0ed982 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -1021,6 +1021,7 @@
 {
     AEMU_SCOPED_TRACE("vkBeginCommandBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     VkResult vkBeginCommandBuffer_VkResult_return = (VkResult)0;
     auto resources = ResourceTracker::get();
     vkBeginCommandBuffer_VkResult_return = resources->on_vkBeginCommandBuffer(vkEnc, VK_SUCCESS, commandBuffer, pBeginInfo);
@@ -1031,6 +1032,7 @@
 {
     AEMU_SCOPED_TRACE("vkEndCommandBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     VkResult vkEndCommandBuffer_VkResult_return = (VkResult)0;
     auto resources = ResourceTracker::get();
     vkEndCommandBuffer_VkResult_return = resources->on_vkEndCommandBuffer(vkEnc, VK_SUCCESS, commandBuffer);
@@ -1042,6 +1044,7 @@
 {
     AEMU_SCOPED_TRACE("vkResetCommandBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     VkResult vkResetCommandBuffer_VkResult_return = (VkResult)0;
     auto resources = ResourceTracker::get();
     vkResetCommandBuffer_VkResult_return = resources->on_vkResetCommandBuffer(vkEnc, VK_SUCCESS, commandBuffer, flags);
@@ -1054,6 +1057,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBindPipeline");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
 }
 static void entry_vkCmdSetViewport(
@@ -1064,6 +1068,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetViewport");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
 }
 static void entry_vkCmdSetScissor(
@@ -1074,6 +1079,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetScissor");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
 }
 static void entry_vkCmdSetLineWidth(
@@ -1082,6 +1088,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetLineWidth");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetLineWidth(commandBuffer, lineWidth);
 }
 static void entry_vkCmdSetDepthBias(
@@ -1092,6 +1099,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetDepthBias");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
 }
 static void entry_vkCmdSetBlendConstants(
@@ -1100,6 +1108,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetBlendConstants");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetBlendConstants(commandBuffer, blendConstants);
 }
 static void entry_vkCmdSetDepthBounds(
@@ -1109,6 +1118,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetDepthBounds");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
 }
 static void entry_vkCmdSetStencilCompareMask(
@@ -1118,6 +1128,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetStencilCompareMask");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
 }
 static void entry_vkCmdSetStencilWriteMask(
@@ -1127,6 +1138,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetStencilWriteMask");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
 }
 static void entry_vkCmdSetStencilReference(
@@ -1136,6 +1148,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetStencilReference");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetStencilReference(commandBuffer, faceMask, reference);
 }
 static void entry_vkCmdBindDescriptorSets(
@@ -1150,6 +1163,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBindDescriptorSets");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
 }
 static void entry_vkCmdBindIndexBuffer(
@@ -1160,6 +1174,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBindIndexBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
 }
 static void entry_vkCmdBindVertexBuffers(
@@ -1171,6 +1186,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBindVertexBuffers");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
 }
 static void entry_vkCmdDraw(
@@ -1182,6 +1198,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDraw");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
 }
 static void entry_vkCmdDrawIndexed(
@@ -1194,6 +1211,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndexed");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
 }
 static void entry_vkCmdDrawIndirect(
@@ -1205,6 +1223,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndirect");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
 }
 static void entry_vkCmdDrawIndexedIndirect(
@@ -1216,6 +1235,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirect");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
 }
 static void entry_vkCmdDispatch(
@@ -1226,6 +1246,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDispatch");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ);
 }
 static void entry_vkCmdDispatchIndirect(
@@ -1235,6 +1256,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDispatchIndirect");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDispatchIndirect(commandBuffer, buffer, offset);
 }
 static void entry_vkCmdCopyBuffer(
@@ -1246,6 +1268,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdCopyBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
 }
 static void entry_vkCmdCopyImage(
@@ -1259,6 +1282,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdCopyImage");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
 }
 static void entry_vkCmdBlitImage(
@@ -1273,6 +1297,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBlitImage");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
 }
 static void entry_vkCmdCopyBufferToImage(
@@ -1285,6 +1310,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdCopyBufferToImage");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
 }
 static void entry_vkCmdCopyImageToBuffer(
@@ -1297,6 +1323,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdCopyImageToBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
 }
 static void entry_vkCmdUpdateBuffer(
@@ -1308,6 +1335,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdUpdateBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
 }
 static void entry_vkCmdFillBuffer(
@@ -1319,6 +1347,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdFillBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
 }
 static void entry_vkCmdClearColorImage(
@@ -1331,6 +1360,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdClearColorImage");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
 }
 static void entry_vkCmdClearDepthStencilImage(
@@ -1343,6 +1373,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdClearDepthStencilImage");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
 }
 static void entry_vkCmdClearAttachments(
@@ -1354,6 +1385,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdClearAttachments");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
 }
 static void entry_vkCmdResolveImage(
@@ -1367,6 +1399,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdResolveImage");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
 }
 static void entry_vkCmdSetEvent(
@@ -1376,6 +1409,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetEvent");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetEvent(commandBuffer, event, stageMask);
 }
 static void entry_vkCmdResetEvent(
@@ -1385,6 +1419,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdResetEvent");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdResetEvent(commandBuffer, event, stageMask);
 }
 static void entry_vkCmdWaitEvents(
@@ -1402,6 +1437,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdWaitEvents");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
 }
 static void entry_vkCmdPipelineBarrier(
@@ -1418,6 +1454,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdPipelineBarrier");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
 }
 static void entry_vkCmdBeginQuery(
@@ -1428,6 +1465,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBeginQuery");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBeginQuery(commandBuffer, queryPool, query, flags);
 }
 static void entry_vkCmdEndQuery(
@@ -1437,6 +1475,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdEndQuery");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdEndQuery(commandBuffer, queryPool, query);
 }
 static void entry_vkCmdResetQueryPool(
@@ -1447,6 +1486,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdResetQueryPool");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
 }
 static void entry_vkCmdWriteTimestamp(
@@ -1457,6 +1497,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdWriteTimestamp");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, query);
 }
 static void entry_vkCmdCopyQueryPoolResults(
@@ -1471,6 +1512,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdCopyQueryPoolResults");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
 }
 static void entry_vkCmdPushConstants(
@@ -1483,6 +1525,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdPushConstants");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
 }
 static void entry_vkCmdBeginRenderPass(
@@ -1492,6 +1535,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
 }
 static void entry_vkCmdNextSubpass(
@@ -1500,6 +1544,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdNextSubpass");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdNextSubpass(commandBuffer, contents);
 }
 static void entry_vkCmdEndRenderPass(
@@ -1507,6 +1552,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdEndRenderPass(commandBuffer);
 }
 static void entry_vkCmdExecuteCommands(
@@ -1516,6 +1562,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdExecuteCommands");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
 }
 #endif
@@ -1570,6 +1617,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMask");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetDeviceMask(commandBuffer, deviceMask);
 }
 static void entry_vkCmdDispatchBase(
@@ -1583,6 +1631,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDispatchBase");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
 }
 static VkResult entry_vkEnumeratePhysicalDeviceGroups(
@@ -2288,6 +2337,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetDeviceMaskKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetDeviceMaskKHR(commandBuffer, deviceMask);
 }
 static void entry_vkCmdDispatchBaseKHR(
@@ -2301,6 +2351,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDispatchBaseKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDispatchBaseKHR(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ);
 }
 #endif
@@ -2467,6 +2518,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdPushDescriptorSetKHR(commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites);
 }
 static void entry_vkCmdPushDescriptorSetWithTemplateKHR(
@@ -2478,6 +2530,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdPushDescriptorSetWithTemplateKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdPushDescriptorSetWithTemplateKHR(commandBuffer, descriptorUpdateTemplate, layout, set, pData);
 }
 #endif
@@ -2538,6 +2591,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBeginRenderPass2KHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBeginRenderPass2KHR(commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
 }
 static void entry_vkCmdNextSubpass2KHR(
@@ -2547,6 +2601,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdNextSubpass2KHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdNextSubpass2KHR(commandBuffer, pSubpassBeginInfo, pSubpassEndInfo);
 }
 static void entry_vkCmdEndRenderPass2KHR(
@@ -2555,6 +2610,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdEndRenderPass2KHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdEndRenderPass2KHR(commandBuffer, pSubpassEndInfo);
 }
 #endif
@@ -2818,6 +2874,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
 }
 static void entry_vkCmdDrawIndexedIndirectCountKHR(
@@ -2831,6 +2888,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountKHR");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
 }
 #endif
@@ -2952,6 +3010,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerBeginEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDebugMarkerBeginEXT(commandBuffer, pMarkerInfo);
 }
 static void entry_vkCmdDebugMarkerEndEXT(
@@ -2959,6 +3018,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerEndEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDebugMarkerEndEXT(commandBuffer);
 }
 static void entry_vkCmdDebugMarkerInsertEXT(
@@ -2967,6 +3027,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDebugMarkerInsertEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDebugMarkerInsertEXT(commandBuffer, pMarkerInfo);
 }
 #endif
@@ -2986,6 +3047,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndirectCountAMD");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndirectCountAMD(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
 }
 static void entry_vkCmdDrawIndexedIndirectCountAMD(
@@ -2999,6 +3061,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdDrawIndexedIndirectCountAMD");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdDrawIndexedIndirectCountAMD(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
 }
 #endif
@@ -3093,6 +3156,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBeginConditionalRenderingEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBeginConditionalRenderingEXT(commandBuffer, pConditionalRenderingBegin);
 }
 static void entry_vkCmdEndConditionalRenderingEXT(
@@ -3100,6 +3164,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdEndConditionalRenderingEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdEndConditionalRenderingEXT(commandBuffer);
 }
 #endif
@@ -3110,6 +3175,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdProcessCommandsNVX");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdProcessCommandsNVX(commandBuffer, pProcessCommandsInfo);
 }
 static void entry_vkCmdReserveSpaceForCommandsNVX(
@@ -3118,6 +3184,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdReserveSpaceForCommandsNVX");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdReserveSpaceForCommandsNVX(commandBuffer, pReserveSpaceInfo);
 }
 static VkResult entry_vkCreateIndirectCommandsLayoutNVX(
@@ -3207,6 +3274,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetViewportWScalingNV");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetViewportWScalingNV(commandBuffer, firstViewport, viewportCount, pViewportWScalings);
 }
 #endif
@@ -3354,6 +3422,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetDiscardRectangleEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetDiscardRectangleEXT(commandBuffer, firstDiscardRectangle, discardRectangleCount, pDiscardRectangles);
 }
 #endif
@@ -3455,6 +3524,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdBeginDebugUtilsLabelEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdBeginDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
 }
 static void entry_vkCmdEndDebugUtilsLabelEXT(
@@ -3462,6 +3532,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdEndDebugUtilsLabelEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdEndDebugUtilsLabelEXT(commandBuffer);
 }
 static void entry_vkCmdInsertDebugUtilsLabelEXT(
@@ -3470,6 +3541,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdInsertDebugUtilsLabelEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdInsertDebugUtilsLabelEXT(commandBuffer, pLabelInfo);
 }
 static VkResult entry_vkCreateDebugUtilsMessengerEXT(
@@ -3547,6 +3619,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetSampleLocationsEXT");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetSampleLocationsEXT(commandBuffer, pSampleLocationsInfo);
 }
 static void entry_vkGetPhysicalDeviceMultisamplePropertiesEXT(
@@ -3646,6 +3719,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdWriteBufferMarkerAMD");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdWriteBufferMarkerAMD(commandBuffer, pipelineStage, dstBuffer, dstOffset, marker);
 }
 #endif
@@ -3662,6 +3736,7 @@
 {
     AEMU_SCOPED_TRACE("vkCmdSetCheckpointNV");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkCmdSetCheckpointNV(commandBuffer, pCheckpointMarker);
 }
 static void entry_vkGetQueueCheckpointDataNV(
@@ -3738,6 +3813,7 @@
 {
     AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkBeginCommandBufferAsyncGOOGLE(commandBuffer, pBeginInfo);
 }
 static void entry_vkEndCommandBufferAsyncGOOGLE(
@@ -3745,6 +3821,7 @@
 {
     AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkEndCommandBufferAsyncGOOGLE(commandBuffer);
 }
 static void entry_vkResetCommandBufferAsyncGOOGLE(
@@ -3753,8 +3830,19 @@
 {
     AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE");
     auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
     vkEnc->vkResetCommandBufferAsyncGOOGLE(commandBuffer, flags);
 }
+static void entry_vkCommandBufferHostSyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+    uint32_t needHostSync,
+    uint32_t sequenceNumber)
+{
+    AEMU_SCOPED_TRACE("vkCommandBufferHostSyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    ResourceTracker::get()->syncEncodersForCommandBuffer(commandBuffer, vkEnc);
+    vkEnc->vkCommandBufferHostSyncGOOGLE(commandBuffer, needHostSync, sequenceNumber);
+}
 #endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
@@ -5186,6 +5274,10 @@
     {
         return nullptr;
     }
+    if (!strcmp(name, "vkCommandBufferHostSyncGOOGLE"))
+    {
+        return nullptr;
+    }
 #endif
     return nullptr;
 }
@@ -6780,6 +6872,11 @@
         bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_command_buffers");
         return hasExt ? (void*)entry_vkResetCommandBufferAsyncGOOGLE : nullptr;
     }
+    if (!strcmp(name, "vkCommandBufferHostSyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkCommandBufferHostSyncGOOGLE : nullptr;
+    }
 #endif
     return nullptr;
 }
@@ -8374,6 +8471,11 @@
         bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_command_buffers");
         return hasExt ? (void*)entry_vkResetCommandBufferAsyncGOOGLE : nullptr;
     }
+    if (!strcmp(name, "vkCommandBufferHostSyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkCommandBufferHostSyncGOOGLE : nullptr;
+    }
 #endif
     return nullptr;
 }