Better track color buffer usage in Vulkan

Sometimes guest renders to an AHB without calling
vkQueueSignalReleaseImageANDROIDAsyncGOOGLE. This would result in the
color buffer not being updated from Vulkan.

This commit tracks the situation that AHB is rendered to, and copies its
content to color buffer.

Note that it adds extra wait, which could hurt performance.

Bug: 327522469
Test: run Chrome with -gpu swiftshader
Change-Id: I3687a68eb222039291c6f73fc65fb0e9ec0b443b
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py
index c0e5637..ac7ec3e 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/decoder.py
@@ -700,6 +700,10 @@
     "vkDestroyRenderPass" : emit_global_state_wrapped_decoding,
     "vkCreateFramebuffer" : emit_global_state_wrapped_decoding,
     "vkDestroyFramebuffer" : emit_global_state_wrapped_decoding,
+    "vkDestroyFramebuffer" : emit_global_state_wrapped_decoding,
+    "vkCmdBeginRenderPass" : emit_global_state_wrapped_decoding,
+    "vkCmdBeginRenderPass2" : emit_global_state_wrapped_decoding,
+    "vkCmdBeginRenderPass2KHR" : emit_global_state_wrapped_decoding,
 
     "vkCreateSamplerYcbcrConversion": emit_global_state_wrapped_decoding,
     "vkDestroySamplerYcbcrConversion": emit_global_state_wrapped_decoding,
diff --git a/codegen/vulkan/vulkan-docs-next/scripts/cereal/subdecode.py b/codegen/vulkan/vulkan-docs-next/scripts/cereal/subdecode.py
index 3de2213..3a22dd1 100644
--- a/codegen/vulkan/vulkan-docs-next/scripts/cereal/subdecode.py
+++ b/codegen/vulkan/vulkan-docs-next/scripts/cereal/subdecode.py
@@ -310,6 +310,9 @@
     "vkEndCommandBufferAsyncGOOGLE": emit_global_state_wrapped_decoding_with_context,
     "vkResetCommandBufferAsyncGOOGLE": emit_global_state_wrapped_decoding,
     "vkCommandBufferHostSyncGOOGLE": emit_global_state_wrapped_decoding,
+    "vkCmdBeginRenderPass" : emit_global_state_wrapped_decoding,
+    "vkCmdBeginRenderPass2" : emit_global_state_wrapped_decoding,
+    "vkCmdBeginRenderPass2KHR" : emit_global_state_wrapped_decoding,
 }
 
 
diff --git a/guest/vulkan_enc/func_table.cpp b/guest/vulkan_enc/func_table.cpp
index 4dcfcc4..f3632ca 100644
--- a/guest/vulkan_enc/func_table.cpp
+++ b/guest/vulkan_enc/func_table.cpp
@@ -34,6 +34,7 @@
 
 #include <cstring>
 
+#include "../OpenglSystemCommon/HostConnection.h"
 #include "ResourceTracker.h"
 #include "VkEncoder.h"
 #include "gfxstream_vk_entrypoints.h"
diff --git a/host/vulkan/VkDecoder.cpp b/host/vulkan/VkDecoder.cpp
index 8e965de..837cd22 100644
--- a/host/vulkan/VkDecoder.cpp
+++ b/host/vulkan/VkDecoder.cpp
@@ -8623,15 +8623,12 @@
                 VkCommandBuffer commandBuffer;
                 const VkRenderPassBeginInfo* pRenderPassBegin;
                 VkSubpassContents contents;
-                // Begin non wrapped dispatchable handle unboxing for commandBuffer;
+                // Begin global wrapped dispatchable handle unboxing for commandBuffer;
                 uint64_t cgen_var_0;
                 memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
                 *readStreamPtrPtr += 1 * 8;
                 *(VkCommandBuffer*)&commandBuffer =
                     (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)(*&cgen_var_0));
-                auto unboxed_commandBuffer = unbox_VkCommandBuffer(commandBuffer);
-                auto vk = dispatch_VkCommandBuffer(commandBuffer);
-                // End manual dispatchable handle unboxing for commandBuffer;
                 vkReadStream->alloc((void**)&pRenderPassBegin, sizeof(const VkRenderPassBeginInfo));
                 reservedunmarshal_VkRenderPassBeginInfo(vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
                                                         (VkRenderPassBeginInfo*)(pRenderPassBegin),
@@ -8647,7 +8644,8 @@
                             ioStream, (unsigned long long)commandBuffer,
                             (unsigned long long)pRenderPassBegin, (unsigned long long)contents);
                 }
-                vk->vkCmdBeginRenderPass(unboxed_commandBuffer, pRenderPassBegin, contents);
+                m_state->on_vkCmdBeginRenderPass(&m_pool, commandBuffer, pRenderPassBegin,
+                                                 contents);
                 vkStream->unsetHandleMapping();
                 vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
                                          (uintptr_t)snapshotTraceBegin);
@@ -10833,15 +10831,12 @@
                 VkCommandBuffer commandBuffer;
                 const VkRenderPassBeginInfo* pRenderPassBegin;
                 const VkSubpassBeginInfo* pSubpassBeginInfo;
-                // Begin non wrapped dispatchable handle unboxing for commandBuffer;
+                // Begin global wrapped dispatchable handle unboxing for commandBuffer;
                 uint64_t cgen_var_0;
                 memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
                 *readStreamPtrPtr += 1 * 8;
                 *(VkCommandBuffer*)&commandBuffer =
                     (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)(*&cgen_var_0));
-                auto unboxed_commandBuffer = unbox_VkCommandBuffer(commandBuffer);
-                auto vk = dispatch_VkCommandBuffer(commandBuffer);
-                // End manual dispatchable handle unboxing for commandBuffer;
                 vkReadStream->alloc((void**)&pRenderPassBegin, sizeof(const VkRenderPassBeginInfo));
                 reservedunmarshal_VkRenderPassBeginInfo(vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
                                                         (VkRenderPassBeginInfo*)(pRenderPassBegin),
@@ -10864,8 +10859,8 @@
                             (unsigned long long)pRenderPassBegin,
                             (unsigned long long)pSubpassBeginInfo);
                 }
-                vk->vkCmdBeginRenderPass2(unboxed_commandBuffer, pRenderPassBegin,
-                                          pSubpassBeginInfo);
+                m_state->on_vkCmdBeginRenderPass2(&m_pool, commandBuffer, pRenderPassBegin,
+                                                  pSubpassBeginInfo);
                 vkStream->unsetHandleMapping();
                 vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
                                          (uintptr_t)snapshotTraceBegin);
@@ -15002,15 +14997,12 @@
                 VkCommandBuffer commandBuffer;
                 const VkRenderPassBeginInfo* pRenderPassBegin;
                 const VkSubpassBeginInfo* pSubpassBeginInfo;
-                // Begin non wrapped dispatchable handle unboxing for commandBuffer;
+                // Begin global wrapped dispatchable handle unboxing for commandBuffer;
                 uint64_t cgen_var_0;
                 memcpy((uint64_t*)&cgen_var_0, *readStreamPtrPtr, 1 * 8);
                 *readStreamPtrPtr += 1 * 8;
                 *(VkCommandBuffer*)&commandBuffer =
                     (VkCommandBuffer)(VkCommandBuffer)((VkCommandBuffer)(*&cgen_var_0));
-                auto unboxed_commandBuffer = unbox_VkCommandBuffer(commandBuffer);
-                auto vk = dispatch_VkCommandBuffer(commandBuffer);
-                // End manual dispatchable handle unboxing for commandBuffer;
                 vkReadStream->alloc((void**)&pRenderPassBegin, sizeof(const VkRenderPassBeginInfo));
                 reservedunmarshal_VkRenderPassBeginInfo(vkReadStream, VK_STRUCTURE_TYPE_MAX_ENUM,
                                                         (VkRenderPassBeginInfo*)(pRenderPassBegin),
@@ -15034,8 +15026,8 @@
                             (unsigned long long)pRenderPassBegin,
                             (unsigned long long)pSubpassBeginInfo);
                 }
-                vk->vkCmdBeginRenderPass2KHR(unboxed_commandBuffer, pRenderPassBegin,
-                                             pSubpassBeginInfo);
+                m_state->on_vkCmdBeginRenderPass2KHR(&m_pool, commandBuffer, pRenderPassBegin,
+                                                     pSubpassBeginInfo);
                 vkStream->unsetHandleMapping();
                 vkReadStream->setReadPos((uintptr_t)(*readStreamPtrPtr) -
                                          (uintptr_t)snapshotTraceBegin);
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 4c26a28..da7122d 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -2711,6 +2711,7 @@
                 }
                 if (imgViewInfo->boundColorBuffer) {
                     // TODO(igorc): Move this to vkQueueSubmit time.
+                    // Likely can be removed after b/323596143
                     auto fb = FrameBuffer::getFB();
                     if (fb) {
                         fb->invalidateColorBufferForVk(*imgViewInfo->boundColorBuffer);
@@ -3454,6 +3455,22 @@
         if (!deviceInfo) return;
 
         // TODO: update image layout in ImageInfo
+        for (uint32_t i = 0; i < imageMemoryBarrierCount; i++) {
+            const VkImageMemoryBarrier& barrier = pImageMemoryBarriers[i];
+            auto* imageInfo = android::base::find(mImageInfo, barrier.image);
+            if (!imageInfo || !imageInfo->boundColorBuffer.has_value()) {
+                continue;
+            }
+            HandleType cb = imageInfo->boundColorBuffer.value();
+            if (barrier.srcQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL) {
+                cmdBufferInfo->acquiredColorBuffers.insert(cb);
+            }
+            if (barrier.dstQueueFamilyIndex == VK_QUEUE_FAMILY_EXTERNAL) {
+                cmdBufferInfo->releasedColorBuffers.insert(cb);
+            }
+            cmdBufferInfo->cbLayouts[cb] = barrier.newLayout;
+        }
+
         if (!deviceInfo->emulateTextureEtc2 && !deviceInfo->emulateTextureAstc) {
             vk->vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
                                      memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
@@ -4548,6 +4565,22 @@
         return vk->vkQueueSubmit2(unboxed_queue, submitCount, pSubmits, fence);
     }
 
+    int getCommandBufferCount(const VkSubmitInfo& submitInfo) {
+        return submitInfo.commandBufferCount;
+    }
+
+    VkCommandBuffer getCommandBuffer(const VkSubmitInfo& submitInfo, int idx) {
+        return submitInfo.pCommandBuffers[idx];
+    }
+
+    int getCommandBufferCount(const VkSubmitInfo2& submitInfo) {
+        return submitInfo.commandBufferInfoCount;
+    }
+
+    VkCommandBuffer getCommandBuffer(const VkSubmitInfo2& submitInfo, int idx) {
+        return submitInfo.pCommandBufferInfos[idx].commandBuffer;
+    }
+
     template <typename VkSubmitInfoType>
     VkResult on_vkQueueSubmit(android::base::BumpPool* pool, VkQueue boxed_queue,
                               uint32_t submitCount, const VkSubmitInfoType* pSubmits,
@@ -4555,6 +4588,37 @@
         auto queue = unbox_VkQueue(boxed_queue);
         auto vk = dispatch_VkQueue(boxed_queue);
 
+        std::unordered_set<HandleType> acquiredColorBuffers;
+        std::unordered_set<HandleType> releasedColorBuffers;
+        bool vulkanOnly = mGuestUsesAngle;
+        if (!vulkanOnly) {
+            {
+                std::lock_guard<std::recursive_mutex> lock(mLock);
+                for (int i = 0; i < submitCount; i++) {
+                    for (int j = 0; j < getCommandBufferCount(pSubmits[i]); j++) {
+                        VkCommandBuffer cmdBuffer = getCommandBuffer(pSubmits[i], j);
+                        CommandBufferInfo* cmdBufferInfo =
+                            android::base::find(mCmdBufferInfo, cmdBuffer);
+                        if (!cmdBufferInfo) {
+                            continue;
+                        }
+                        acquiredColorBuffers.merge(cmdBufferInfo->acquiredColorBuffers);
+                        releasedColorBuffers.merge(cmdBufferInfo->releasedColorBuffers);
+                        for (const auto& ite : cmdBufferInfo->cbLayouts) {
+                            setColorBufferCurrentLayout(ite.first, ite.second);
+                        }
+                    }
+                }
+            }
+            auto fb = FrameBuffer::getFB();
+            if (fb) {
+                for (HandleType cb : acquiredColorBuffers) {
+                    fb->invalidateColorBufferForVk(cb);
+                }
+            }
+        }
+
+        VkDevice device = VK_NULL_HANDLE;
         Lock* ql;
         {
             std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -4562,7 +4626,8 @@
             {
                 auto* queueInfo = android::base::find(mQueueInfo, queue);
                 if (queueInfo) {
-                    sBoxedHandleManager.processDelayedRemovesGlobalStateLocked(queueInfo->device);
+                    device = queueInfo->device;
+                    sBoxedHandleManager.processDelayedRemovesGlobalStateLocked(device);
                 }
             }
 
@@ -4575,8 +4640,18 @@
             ql = queueInfo->lock;
         }
 
+        VkFence localFence = VK_NULL_HANDLE;
+        if (!releasedColorBuffers.empty() && fence == VK_NULL_HANDLE) {
+            // Need to manually inject a fence so that we could update color buffer
+            // after queue submits..
+            // This should almost never happen.
+            VkFenceCreateInfo fenceCreateInfo{
+                .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+            };
+            vk->vkCreateFence(device, &fenceCreateInfo, nullptr, &localFence);
+        }
         AutoLock qlock(*ql);
-        auto result = dispatchVkQueueSubmit(vk, queue, submitCount, pSubmits, fence);
+        auto result = dispatchVkQueueSubmit(vk, queue, submitCount, pSubmits, localFence ?: fence);
 
         // After vkQueueSubmit is called, we can signal the conditional variable
         // in FenceInfo, so that other threads (e.g. SyncThread) can call
@@ -4590,6 +4665,19 @@
                 fenceInfo->cv.signalAndUnlock(&fenceInfo->lock);
             }
         }
+        if (!releasedColorBuffers.empty()) {
+            vk->vkWaitForFences(device, 1, localFence ? &localFence : &fence, VK_TRUE,
+                                /* 1 sec */ 1000000000L);
+            auto fb = FrameBuffer::getFB();
+            if (fb) {
+                for (HandleType cb : releasedColorBuffers) {
+                    fb->flushColorBufferFromVk(cb);
+                }
+            }
+        }
+        if (localFence) {
+            vk->vkDestroyFence(device, localFence, nullptr);
+        }
 
         return result;
     }
@@ -5117,6 +5205,41 @@
         destroyRenderPassLocked(device, deviceDispatch, renderPass, pAllocator);
     }
 
+    void registerRenderPassBeginInfo(VkCommandBuffer commandBuffer,
+                                     const VkRenderPassBeginInfo* pRenderPassBegin) {
+        CommandBufferInfo* cmdBufferInfo = android::base::find(mCmdBufferInfo, commandBuffer);
+        FramebufferInfo* fbInfo =
+            android::base::find(mFramebufferInfo, pRenderPassBegin->framebuffer);
+        cmdBufferInfo->releasedColorBuffers.insert(fbInfo->attachedColorBuffers.begin(),
+                                                   fbInfo->attachedColorBuffers.end());
+    }
+
+    void on_vkCmdBeginRenderPass(android::base::BumpPool* pool, VkCommandBuffer boxed_commandBuffer,
+                                 const VkRenderPassBeginInfo* pRenderPassBegin,
+                                 VkSubpassContents contents) {
+        auto commandBuffer = unbox_VkCommandBuffer(boxed_commandBuffer);
+        auto vk = dispatch_VkCommandBuffer(boxed_commandBuffer);
+        registerRenderPassBeginInfo(commandBuffer, pRenderPassBegin);
+        vk->vkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
+    }
+
+    void on_vkCmdBeginRenderPass2(android::base::BumpPool* pool,
+                                  VkCommandBuffer boxed_commandBuffer,
+                                  const VkRenderPassBeginInfo* pRenderPassBegin,
+                                  const VkSubpassBeginInfo* pSubpassBeginInfo) {
+        auto commandBuffer = unbox_VkCommandBuffer(boxed_commandBuffer);
+        auto vk = dispatch_VkCommandBuffer(boxed_commandBuffer);
+        registerRenderPassBeginInfo(commandBuffer, pRenderPassBegin);
+        vk->vkCmdBeginRenderPass2(commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
+    }
+
+    void on_vkCmdBeginRenderPass2KHR(android::base::BumpPool* pool,
+                                     VkCommandBuffer boxed_commandBuffer,
+                                     const VkRenderPassBeginInfo* pRenderPassBegin,
+                                     const VkSubpassBeginInfo* pSubpassBeginInfo) {
+        on_vkCmdBeginRenderPass2(pool, boxed_commandBuffer, pRenderPassBegin, pSubpassBeginInfo);
+    }
+
     void on_vkCmdCopyQueryPoolResults(android::base::BumpPool* pool,
                                       VkCommandBuffer boxed_commandBuffer, VkQueryPool queryPool,
                                       uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer,
@@ -5152,6 +5275,18 @@
         auto& framebufferInfo = mFramebufferInfo[*pFramebuffer];
         framebufferInfo.device = device;
 
+        // b/327522469
+        // Track the Colorbuffers that would be written to.
+        // It might be better to check for VK_QUEUE_FAMILY_EXTERNAL in pipeline barrier.
+        // But the guest does not always add it to pipeline barrier.
+        for (int i = 0; i < pCreateInfo->attachmentCount; i++) {
+            auto* imageViewInfo = android::base::find(mImageViewInfo, pCreateInfo->pAttachments[i]);
+            if (imageViewInfo->boundColorBuffer.has_value()) {
+                framebufferInfo.attachedColorBuffers.push_back(
+                    imageViewInfo->boundColorBuffer.value());
+            }
+        }
+
         *pFramebuffer = new_boxed_non_dispatchable_VkFramebuffer(*pFramebuffer);
 
         return result;
@@ -6545,6 +6680,9 @@
         VkPipelineLayout descriptorLayout = VK_NULL_HANDLE;
         std::vector<VkDescriptorSet> descriptorSets;
         std::vector<uint32_t> dynamicOffsets;
+        std::unordered_set<HandleType> acquiredColorBuffers;
+        std::unordered_set<HandleType> releasedColorBuffers;
+        std::unordered_map<HandleType, VkImageLayout> cbLayouts;
 
         void reset() {
             preprocessFuncs.clear();
@@ -6554,6 +6692,9 @@
             descriptorLayout = VK_NULL_HANDLE;
             descriptorSets.clear();
             dynamicOffsets.clear();
+            acquiredColorBuffers.clear();
+            releasedColorBuffers.clear();
+            cbLayouts.clear();
         }
     };
 
@@ -7818,6 +7959,28 @@
     mImpl->on_vkDestroyRenderPass(pool, boxed_device, renderPass, pAllocator);
 }
 
+void VkDecoderGlobalState::on_vkCmdBeginRenderPass(android::base::BumpPool* pool,
+                                                   VkCommandBuffer commandBuffer,
+                                                   const VkRenderPassBeginInfo* pRenderPassBegin,
+                                                   VkSubpassContents contents) {
+    return mImpl->on_vkCmdBeginRenderPass(pool, commandBuffer, pRenderPassBegin, contents);
+}
+
+void VkDecoderGlobalState::on_vkCmdBeginRenderPass2(android::base::BumpPool* pool,
+                                                    VkCommandBuffer commandBuffer,
+                                                    const VkRenderPassBeginInfo* pRenderPassBegin,
+                                                    const VkSubpassBeginInfo* pSubpassBeginInfo) {
+    return mImpl->on_vkCmdBeginRenderPass2(pool, commandBuffer, pRenderPassBegin,
+                                           pSubpassBeginInfo);
+}
+
+void VkDecoderGlobalState::on_vkCmdBeginRenderPass2KHR(
+    android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+    const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo) {
+    return mImpl->on_vkCmdBeginRenderPass2(pool, commandBuffer, pRenderPassBegin,
+                                           pSubpassBeginInfo);
+}
+
 VkResult VkDecoderGlobalState::on_vkCreateFramebuffer(android::base::BumpPool* pool,
                                                       VkDevice boxed_device,
                                                       const VkFramebufferCreateInfo* pCreateInfo,
diff --git a/host/vulkan/VkDecoderGlobalState.h b/host/vulkan/VkDecoderGlobalState.h
index b7d02da..14fdc32 100644
--- a/host/vulkan/VkDecoderGlobalState.h
+++ b/host/vulkan/VkDecoderGlobalState.h
@@ -599,6 +599,16 @@
                                        VkRenderPass* pRenderPass);
     void on_vkDestroyRenderPass(android::base::BumpPool* pool, VkDevice device,
                                 VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
+    void on_vkCmdBeginRenderPass(android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                                 const VkRenderPassBeginInfo* pRenderPassBegin,
+                                 VkSubpassContents contents);
+    void on_vkCmdBeginRenderPass2(android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                                  const VkRenderPassBeginInfo* pRenderPassBegin,
+                                  const VkSubpassBeginInfo* pSubpassBeginInfo);
+    void on_vkCmdBeginRenderPass2KHR(android::base::BumpPool* pool, VkCommandBuffer commandBuffer,
+                                     const VkRenderPassBeginInfo* pRenderPassBegin,
+                                     const VkSubpassBeginInfo* pSubpassBeginInfo);
+
     VkResult on_vkCreateFramebuffer(android::base::BumpPool* pool, VkDevice device,
                                     const VkFramebufferCreateInfo* pCreateInfo,
                                     const VkAllocationCallbacks* pAllocator,
diff --git a/host/vulkan/VkDecoderInternalStructs.h b/host/vulkan/VkDecoderInternalStructs.h
index bf1e55f..578e65e 100644
--- a/host/vulkan/VkDecoderInternalStructs.h
+++ b/host/vulkan/VkDecoderInternalStructs.h
@@ -337,6 +337,7 @@
 
 struct FramebufferInfo {
     VkDevice device;
+    std::vector<HandleType> attachedColorBuffers;
 };
 }  // namespace vk
 }  // namespace gfxstream
diff --git a/host/vulkan/VkSubDecoder.cpp b/host/vulkan/VkSubDecoder.cpp
index c89cd81..f49f53e 100644
--- a/host/vulkan/VkSubDecoder.cpp
+++ b/host/vulkan/VkSubDecoder.cpp
@@ -1319,8 +1319,8 @@
                     transform_tohost_VkRenderPassBeginInfo(
                         globalstate, (VkRenderPassBeginInfo*)(pRenderPassBegin));
                 }
-                vk->vkCmdBeginRenderPass((VkCommandBuffer)dispatchHandle, pRenderPassBegin,
-                                         contents);
+                this->on_vkCmdBeginRenderPass(pool, (VkCommandBuffer)(boxed_dispatchHandle),
+                                              pRenderPassBegin, contents);
                 android::base::endTrace();
                 break;
             }
@@ -1486,8 +1486,8 @@
                     transform_tohost_VkSubpassBeginInfo(globalstate,
                                                         (VkSubpassBeginInfo*)(pSubpassBeginInfo));
                 }
-                vk->vkCmdBeginRenderPass2((VkCommandBuffer)dispatchHandle, pRenderPassBegin,
-                                          pSubpassBeginInfo);
+                this->on_vkCmdBeginRenderPass2(pool, (VkCommandBuffer)(boxed_dispatchHandle),
+                                               pRenderPassBegin, pSubpassBeginInfo);
                 android::base::endTrace();
                 break;
             }
@@ -2121,8 +2121,8 @@
                     transform_tohost_VkSubpassBeginInfo(globalstate,
                                                         (VkSubpassBeginInfo*)(pSubpassBeginInfo));
                 }
-                vk->vkCmdBeginRenderPass2KHR((VkCommandBuffer)dispatchHandle, pRenderPassBegin,
-                                             pSubpassBeginInfo);
+                this->on_vkCmdBeginRenderPass2KHR(pool, (VkCommandBuffer)(boxed_dispatchHandle),
+                                                  pRenderPassBegin, pSubpassBeginInfo);
                 android::base::endTrace();
                 break;
             }