Merge "[vulkan] deferred command buffers (guest)" am: 42b5610868
am: 09d988a1b7

Change-Id: I7b60a45b8599819a86a840c1b8577383663b06bf
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index ba4111e..518273a 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -76,6 +76,9 @@
 // - Full gralloc interop: External memory, AHB
 static const char kVulkan[] = "ANDROID_EMU_vulkan";
 
+// Deferred Vulkan commands
+static const char kDeferredVulkanCommands[] = "ANDROID_EMU_deferred_vulkan_commands";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -85,7 +88,8 @@
         hostComposition(HOST_COMPOSITION_NONE),
         glesMaxVersion(GLES_MAX_VERSION_2),
         hasDirectMem(false),
-        hasVulkan(false) { }
+        hasVulkan(false),
+        hasDeferredVulkanCommands(false) { }
 
     SyncImpl syncImpl;
     DmaImpl dmaImpl;
@@ -93,6 +97,7 @@
     GLESMaxVersion glesMaxVersion;
     bool hasDirectMem;
     bool hasVulkan;
+    bool hasDeferredVulkanCommands;
 };
 
 #endif // __COMMON_EMULATOR_FEATURE_INFO_H
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 5e05073..b6d465c 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -440,3 +440,10 @@
         rcEnc->featureInfo()->hasVulkan = true;
     }
 }
+
+void HostConnection::queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kDeferredVulkanCommands) != std::string::npos) {
+        rcEnc->featureInfo()->hasDeferredVulkanCommands = true;
+    }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index c58e6d2..922c35c 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -165,6 +165,7 @@
     void queryAndSetHostCompositionImpl(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetDirectMemSupport(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanSupport(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext *rcEnc);
 
 private:
     IOStream *m_stream;
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index 3248d76..14c8c32 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -1021,7 +1021,8 @@
     AEMU_SCOPED_TRACE("vkBeginCommandBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkBeginCommandBuffer_VkResult_return = (VkResult)0;
-    vkBeginCommandBuffer_VkResult_return = vkEnc->vkBeginCommandBuffer(commandBuffer, pBeginInfo);
+    auto resources = ResourceTracker::get();
+    vkBeginCommandBuffer_VkResult_return = resources->on_vkBeginCommandBuffer(vkEnc, VK_SUCCESS, commandBuffer, pBeginInfo);
     return vkBeginCommandBuffer_VkResult_return;
 }
 static VkResult entry_vkEndCommandBuffer(
@@ -1030,7 +1031,8 @@
     AEMU_SCOPED_TRACE("vkEndCommandBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkEndCommandBuffer_VkResult_return = (VkResult)0;
-    vkEndCommandBuffer_VkResult_return = vkEnc->vkEndCommandBuffer(commandBuffer);
+    auto resources = ResourceTracker::get();
+    vkEndCommandBuffer_VkResult_return = resources->on_vkEndCommandBuffer(vkEnc, VK_SUCCESS, commandBuffer);
     return vkEndCommandBuffer_VkResult_return;
 }
 static VkResult entry_vkResetCommandBuffer(
@@ -1040,7 +1042,8 @@
     AEMU_SCOPED_TRACE("vkResetCommandBuffer");
     auto vkEnc = HostConnection::get()->vkEncoder();
     VkResult vkResetCommandBuffer_VkResult_return = (VkResult)0;
-    vkResetCommandBuffer_VkResult_return = vkEnc->vkResetCommandBuffer(commandBuffer, flags);
+    auto resources = ResourceTracker::get();
+    vkResetCommandBuffer_VkResult_return = resources->on_vkResetCommandBuffer(vkEnc, VK_SUCCESS, commandBuffer, flags);
     return vkResetCommandBuffer_VkResult_return;
 }
 static void entry_vkCmdBindPipeline(
@@ -3727,6 +3730,31 @@
     vkEnc->vkUpdateDescriptorSetWithTemplateSizedGOOGLE(device, descriptorSet, descriptorUpdateTemplate, imageInfoCount, bufferInfoCount, bufferViewCount, pImageInfoEntryIndices, pBufferInfoEntryIndices, pBufferViewEntryIndices, pImageInfos, pBufferInfos, pBufferViews);
 }
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+static void entry_vkBeginCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+    const VkCommandBufferBeginInfo* pBeginInfo)
+{
+    AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    vkEnc->vkBeginCommandBufferAsyncGOOGLE(commandBuffer, pBeginInfo);
+}
+static void entry_vkEndCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer)
+{
+    AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    vkEnc->vkEndCommandBufferAsyncGOOGLE(commandBuffer);
+}
+static void entry_vkResetCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+    VkCommandBufferResetFlags flags)
+{
+    AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    vkEnc->vkResetCommandBufferAsyncGOOGLE(commandBuffer, flags);
+}
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
     if (!strcmp(name, "vkCreateInstance"))
@@ -5144,6 +5172,20 @@
         return nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+    if (!strcmp(name, "vkBeginCommandBufferAsyncGOOGLE"))
+    {
+        return nullptr;
+    }
+    if (!strcmp(name, "vkEndCommandBufferAsyncGOOGLE"))
+    {
+        return nullptr;
+    }
+    if (!strcmp(name, "vkResetCommandBufferAsyncGOOGLE"))
+    {
+        return nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name){
@@ -6721,6 +6763,23 @@
         return hasExt ? (void*)entry_vkUpdateDescriptorSetWithTemplateSizedGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+    if (!strcmp(name, "vkBeginCommandBufferAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkBeginCommandBufferAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkEndCommandBufferAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkEndCommandBufferAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkResetCommandBufferAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkResetCommandBufferAsyncGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name){
@@ -8298,6 +8357,23 @@
         return hasExt ? (void*)entry_vkUpdateDescriptorSetWithTemplateSizedGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+    if (!strcmp(name, "vkBeginCommandBufferAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkBeginCommandBufferAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkEndCommandBufferAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkEndCommandBufferAsyncGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkResetCommandBufferAsyncGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_async_command_buffers");
+        return hasExt ? (void*)entry_vkResetCommandBufferAsyncGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 
diff --git a/system/vulkan/func_table.h b/system/vulkan/func_table.h
index 565b12a..4d0e977 100644
--- a/system/vulkan/func_table.h
+++ b/system/vulkan/func_table.h
@@ -282,6 +282,8 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 a26ed5b..a723a72 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -584,6 +584,11 @@
         return mHostVisibleMemoryVirtInfo.virtualizationSupported;
     }
 
+    bool supportsDeferredCommands() const {
+        if (!mFeatureInfo) return false;
+        return mFeatureInfo->hasDeferredVulkanCommands;
+    }
+
     int getHostInstanceExtensionIndex(const std::string& extName) const {
         int i = 0;
         for (const auto& prop : mHostInstanceExtensions) {
@@ -3075,6 +3080,53 @@
             physicalDevice, pImageFormatInfo, pImageFormatProperties);
     }
 
+    VkResult on_vkBeginCommandBuffer(
+        void* context, VkResult input_result,
+        VkCommandBuffer commandBuffer,
+        const VkCommandBufferBeginInfo* pBeginInfo) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+        (void)input_result;
+
+        if (!supportsDeferredCommands()) {
+            return enc->vkBeginCommandBuffer(commandBuffer, pBeginInfo);
+        }
+
+        enc->vkBeginCommandBufferAsyncGOOGLE(commandBuffer, pBeginInfo);
+        return VK_SUCCESS;
+    }
+
+    VkResult on_vkEndCommandBuffer(
+        void* context, VkResult input_result,
+        VkCommandBuffer commandBuffer) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+        (void)input_result;
+
+        if (!supportsDeferredCommands()) {
+            return enc->vkEndCommandBuffer(commandBuffer);
+        }
+
+        enc->vkEndCommandBufferAsyncGOOGLE(commandBuffer);
+        return VK_SUCCESS;
+    }
+
+    VkResult on_vkResetCommandBuffer(
+        void* context, VkResult input_result,
+        VkCommandBuffer commandBuffer,
+        VkCommandBufferResetFlags flags) {
+
+        VkEncoder* enc = (VkEncoder*)context;
+        (void)input_result;
+
+        if (!supportsDeferredCommands()) {
+            return enc->vkResetCommandBuffer(commandBuffer, flags);
+        }
+
+        enc->vkResetCommandBufferAsyncGOOGLE(commandBuffer, flags);
+        return VK_SUCCESS;
+    }
+
     uint32_t getApiVersionFromInstance(VkInstance instance) const {
         AutoLock lock(mLock);
         uint32_t api = kMinApiVersion;
@@ -3693,6 +3745,29 @@
         pImageFormatProperties);
 }
 
+VkResult ResourceTracker::on_vkBeginCommandBuffer(
+    void* context, VkResult input_result,
+    VkCommandBuffer commandBuffer,
+    const VkCommandBufferBeginInfo* pBeginInfo) {
+    return mImpl->on_vkBeginCommandBuffer(
+        context, input_result, commandBuffer, pBeginInfo);
+}
+
+VkResult ResourceTracker::on_vkEndCommandBuffer(
+    void* context, VkResult input_result,
+    VkCommandBuffer commandBuffer) {
+    return mImpl->on_vkEndCommandBuffer(
+        context, input_result, commandBuffer);
+}
+
+VkResult ResourceTracker::on_vkResetCommandBuffer(
+    void* context, VkResult input_result,
+    VkCommandBuffer commandBuffer,
+    VkCommandBufferResetFlags flags) {
+    return mImpl->on_vkResetCommandBuffer(
+        context, input_result, commandBuffer, flags);
+}
+
 void ResourceTracker::deviceMemoryTransform_tohost(
     VkDeviceMemory* memory, uint32_t memoryCount,
     VkDeviceSize* offset, uint32_t offsetCount,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index 3217f45..200bfb6 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -321,6 +321,18 @@
         const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
         VkImageFormatProperties2* pImageFormatProperties);
 
+    VkResult on_vkBeginCommandBuffer(
+        void* context, VkResult input_result,
+        VkCommandBuffer commandBuffer,
+        const VkCommandBufferBeginInfo* pBeginInfo);
+    VkResult on_vkEndCommandBuffer(
+        void* context, VkResult input_result,
+        VkCommandBuffer commandBuffer);
+    VkResult on_vkResetCommandBuffer(
+        void* context, VkResult input_result,
+        VkCommandBuffer commandBuffer,
+        VkCommandBufferResetFlags flags);
+
     bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const;
     uint8_t* getMappedPointer(VkDeviceMemory memory);
     VkDeviceSize getMappedSize(VkDeviceMemory memory);
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index 8f38e54..b97f120 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -22501,5 +22501,119 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+void VkEncoder::vkBeginCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+    const VkCommandBufferBeginInfo* pBeginInfo)
+{
+    AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE encode");
+    mImpl->log("start vkBeginCommandBufferAsyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkCommandBuffer local_commandBuffer;
+    VkCommandBufferBeginInfo* local_pBeginInfo;
+    local_commandBuffer = commandBuffer;
+    local_pBeginInfo = nullptr;
+    if (pBeginInfo)
+    {
+        local_pBeginInfo = (VkCommandBufferBeginInfo*)pool->alloc(sizeof(const VkCommandBufferBeginInfo));
+        deepcopy_VkCommandBufferBeginInfo(pool, pBeginInfo, (VkCommandBufferBeginInfo*)(local_pBeginInfo));
+    }
+    if (local_pBeginInfo)
+    {
+        transform_tohost_VkCommandBufferBeginInfo(mImpl->resources(), (VkCommandBufferBeginInfo*)(local_pBeginInfo));
+    }
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1508;
+        countingStream->handleMapping()->mapHandles_VkCommandBuffer_u64(&local_commandBuffer, &cgen_var_1508, 1);
+        countingStream->write((uint64_t*)&cgen_var_1508, 1 * 8);
+        marshal_VkCommandBufferBeginInfo(countingStream, (VkCommandBufferBeginInfo*)(local_pBeginInfo));
+    }
+    uint32_t packetSize_vkBeginCommandBufferAsyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkBeginCommandBufferAsyncGOOGLE = OP_vkBeginCommandBufferAsyncGOOGLE;
+    stream->write(&opcode_vkBeginCommandBufferAsyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkBeginCommandBufferAsyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1509;
+    stream->handleMapping()->mapHandles_VkCommandBuffer_u64(&local_commandBuffer, &cgen_var_1509, 1);
+    stream->write((uint64_t*)&cgen_var_1509, 1 * 8);
+    marshal_VkCommandBufferBeginInfo(stream, (VkCommandBufferBeginInfo*)(local_pBeginInfo));
+    AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkBeginCommandBufferAsyncGOOGLE returnUnmarshal");
+    mImpl->log("finish vkBeginCommandBufferAsyncGOOGLE");;
+}
+
+void VkEncoder::vkEndCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer)
+{
+    AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE encode");
+    mImpl->log("start vkEndCommandBufferAsyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkCommandBuffer local_commandBuffer;
+    local_commandBuffer = commandBuffer;
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1510;
+        countingStream->handleMapping()->mapHandles_VkCommandBuffer_u64(&local_commandBuffer, &cgen_var_1510, 1);
+        countingStream->write((uint64_t*)&cgen_var_1510, 1 * 8);
+    }
+    uint32_t packetSize_vkEndCommandBufferAsyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkEndCommandBufferAsyncGOOGLE = OP_vkEndCommandBufferAsyncGOOGLE;
+    stream->write(&opcode_vkEndCommandBufferAsyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkEndCommandBufferAsyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1511;
+    stream->handleMapping()->mapHandles_VkCommandBuffer_u64(&local_commandBuffer, &cgen_var_1511, 1);
+    stream->write((uint64_t*)&cgen_var_1511, 1 * 8);
+    AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkEndCommandBufferAsyncGOOGLE returnUnmarshal");
+    mImpl->log("finish vkEndCommandBufferAsyncGOOGLE");;
+}
+
+void VkEncoder::vkResetCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+    VkCommandBufferResetFlags flags)
+{
+    AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE encode");
+    mImpl->log("start vkResetCommandBufferAsyncGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkCommandBuffer local_commandBuffer;
+    VkCommandBufferResetFlags local_flags;
+    local_commandBuffer = commandBuffer;
+    local_flags = flags;
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1512;
+        countingStream->handleMapping()->mapHandles_VkCommandBuffer_u64(&local_commandBuffer, &cgen_var_1512, 1);
+        countingStream->write((uint64_t*)&cgen_var_1512, 1 * 8);
+        countingStream->write((VkCommandBufferResetFlags*)&local_flags, sizeof(VkCommandBufferResetFlags));
+    }
+    uint32_t packetSize_vkResetCommandBufferAsyncGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkResetCommandBufferAsyncGOOGLE = OP_vkResetCommandBufferAsyncGOOGLE;
+    stream->write(&opcode_vkResetCommandBufferAsyncGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkResetCommandBufferAsyncGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1513;
+    stream->handleMapping()->mapHandles_VkCommandBuffer_u64(&local_commandBuffer, &cgen_var_1513, 1);
+    stream->write((uint64_t*)&cgen_var_1513, 1 * 8);
+    stream->write((VkCommandBufferResetFlags*)&local_flags, sizeof(VkCommandBufferResetFlags));
+    AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE readParams");
+    AEMU_SCOPED_TRACE("vkResetCommandBufferAsyncGOOGLE returnUnmarshal");
+    mImpl->log("finish vkResetCommandBufferAsyncGOOGLE");;
+}
+
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h
index 36b768c..16df497 100644
--- a/system/vulkan_enc/VkEncoder.h
+++ b/system/vulkan_enc/VkEncoder.h
@@ -1772,6 +1772,16 @@
         const VkDescriptorBufferInfo* pBufferInfos,
         const VkBufferView* pBufferViews);
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+    void vkBeginCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+        const VkCommandBufferBeginInfo* pBeginInfo);
+    void vkEndCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer);
+    void vkResetCommandBufferAsyncGOOGLE(
+    VkCommandBuffer commandBuffer,
+        VkCommandBufferResetFlags flags);
+#endif
 
 private:
     class Impl;
diff --git a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
index 962a6be..5b004c0 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6382,6 +6382,8 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 fbddca8..b367ee0 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -2024,5 +2024,7 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 ffe1af5..c42f6e8 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -280,6 +280,8 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 1d9c327..1d671f8 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -297,5 +297,7 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 3110cb5..7d16b31 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
@@ -4746,6 +4746,8 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 8fc6584..e973064 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.h
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
@@ -1677,5 +1677,7 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 77d3be3..a67e9ad 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -13331,6 +13331,8 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#endif
 void marshal_extension_struct(
     VulkanStreamGuest* vkStream,
     const void* structExtension)
diff --git a/system/vulkan_enc/goldfish_vk_marshaling_guest.h b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
index 0a908d9..283e0ad 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -3384,5 +3384,10 @@
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #define OP_vkUpdateDescriptorSetWithTemplateSizedGOOGLE 20320
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#define OP_vkBeginCommandBufferAsyncGOOGLE 20321
+#define OP_vkEndCommandBufferAsyncGOOGLE 20322
+#define OP_vkResetCommandBufferAsyncGOOGLE 20323
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/goldfish_vk_private_defs.h b/system/vulkan_enc/goldfish_vk_private_defs.h
index 89a355e..3eed244 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -414,6 +414,17 @@
     const VkDescriptorBufferInfo* pBufferInfos,
     const VkBufferView* pBufferViews);
 
+#define VK_GOOGLE_async_command_buffers 1
+
+typedef void (VKAPI_PTR *PFN_vkBeginCommandBufferAsyncGOOGLE)(
+    VkCommandBuffer commandBuffer,
+    const VkCommandBufferBeginInfo* pBeginInfo);
+typedef void (VKAPI_PTR *PFN_vkEndCommandBufferAsyncGOOGLE)(
+    VkCommandBuffer commandBuffer);
+typedef void (VKAPI_PTR *PFN_vkResetCommandBufferAsyncGOOGLE)(
+    VkCommandBuffer commandBuffer,
+    VkCommandBufferResetFlags flags);
+
 #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 2c651db..aa42af7 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -8943,6 +8943,8 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#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 0f7aea5..754c033 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.h
@@ -3065,5 +3065,7 @@
 #endif
 #ifdef VK_GOOGLE_sized_descriptor_update_template
 #endif
+#ifdef VK_GOOGLE_async_command_buffers
+#endif
 
 } // namespace goldfish_vk