(Reland) Revert "Revert "[vulkan] create resources with requirements (guest)""

This reverts commit 842c59b99c645a2c9f7ad7c60ce29ce17acdb9c2.

Change-Id: I1ca873a07a08c3ed4843d1e013c7c2d083e6704f
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index d3228f5..b2add4a 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -82,6 +82,9 @@
 // Vulkan null optional strings
 static const char kVulkanNullOptionalStrings[] = "ANDROID_EMU_vulkan_null_optional_strings";
 
+// Vulkan create resources with requirements
+static const char kVulkanCreateResourcesWithRequirements[] = "ANDROID_EMU_vulkan_create_resources_with_requirements";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -93,7 +96,8 @@
         hasDirectMem(false),
         hasVulkan(false),
         hasDeferredVulkanCommands(false),
-        hasVulkanNullOptionalStrings(false) { }
+        hasVulkanNullOptionalStrings(false),
+        hasVulkanCreateResourcesWithRequirements(false) { }
 
     SyncImpl syncImpl;
     DmaImpl dmaImpl;
@@ -103,6 +107,7 @@
     bool hasVulkan;
     bool hasDeferredVulkanCommands;
     bool hasVulkanNullOptionalStrings;
+    bool hasVulkanCreateResourcesWithRequirements;
 };
 
 #endif // __COMMON_EMULATOR_FEATURE_INFO_H
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 392b7c6..cfe31b5 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -294,6 +294,7 @@
         queryAndSetVulkanSupport(m_rcEnc);
         queryAndSetDeferredVulkanCommandsSupport(m_rcEnc);
         queryAndSetVulkanNullOptionalStringsSupport(m_rcEnc);
+        queryAndSetVulkanCreateResourcesWithRequirementsSupport(m_rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_rcEnc);
         }
@@ -456,3 +457,10 @@
         rcEnc->featureInfo()->hasVulkanNullOptionalStrings = true;
     }
 }
+
+void HostConnection::queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kVulkanCreateResourcesWithRequirements) != std::string::npos) {
+        rcEnc->featureInfo()->hasVulkanCreateResourcesWithRequirements = true;
+    }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 2f9f83f..f79c11f 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -167,6 +167,7 @@
     void queryAndSetVulkanSupport(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext *rcEnc);
 
 private:
     IOStream *m_stream;
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index f0ed982..64427be 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -3844,6 +3844,34 @@
     vkEnc->vkCommandBufferHostSyncGOOGLE(commandBuffer, needHostSync, sequenceNumber);
 }
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+static VkResult entry_vkCreateImageWithRequirementsGOOGLE(
+    VkDevice device,
+    const VkImageCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkImage* pImage,
+    VkMemoryRequirements* pMemoryRequirements)
+{
+    AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    VkResult vkCreateImageWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
+    vkCreateImageWithRequirementsGOOGLE_VkResult_return = vkEnc->vkCreateImageWithRequirementsGOOGLE(device, pCreateInfo, pAllocator, pImage, pMemoryRequirements);
+    return vkCreateImageWithRequirementsGOOGLE_VkResult_return;
+}
+static VkResult entry_vkCreateBufferWithRequirementsGOOGLE(
+    VkDevice device,
+    const VkBufferCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkBuffer* pBuffer,
+    VkMemoryRequirements* pMemoryRequirements)
+{
+    AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    VkResult vkCreateBufferWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
+    vkCreateBufferWithRequirementsGOOGLE_VkResult_return = vkEnc->vkCreateBufferWithRequirementsGOOGLE(device, pCreateInfo, pAllocator, pBuffer, pMemoryRequirements);
+    return vkCreateBufferWithRequirementsGOOGLE_VkResult_return;
+}
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
     if (!strcmp(name, "vkCreateInstance"))
@@ -5279,6 +5307,16 @@
         return nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+    if (!strcmp(name, "vkCreateImageWithRequirementsGOOGLE"))
+    {
+        return nullptr;
+    }
+    if (!strcmp(name, "vkCreateBufferWithRequirementsGOOGLE"))
+    {
+        return nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name){
@@ -6878,6 +6916,18 @@
         return hasExt ? (void*)entry_vkCommandBufferHostSyncGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+    if (!strcmp(name, "vkCreateImageWithRequirementsGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_create_resources_with_requirements");
+        return hasExt ? (void*)entry_vkCreateImageWithRequirementsGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkCreateBufferWithRequirementsGOOGLE"))
+    {
+        bool hasExt = resources->hasInstanceExtension(instance, "VK_GOOGLE_create_resources_with_requirements");
+        return hasExt ? (void*)entry_vkCreateBufferWithRequirementsGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name){
@@ -8477,6 +8527,18 @@
         return hasExt ? (void*)entry_vkCommandBufferHostSyncGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+    if (!strcmp(name, "vkCreateImageWithRequirementsGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_create_resources_with_requirements");
+        return hasExt ? (void*)entry_vkCreateImageWithRequirementsGOOGLE : nullptr;
+    }
+    if (!strcmp(name, "vkCreateBufferWithRequirementsGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_create_resources_with_requirements");
+        return hasExt ? (void*)entry_vkCreateBufferWithRequirementsGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 
diff --git a/system/vulkan/func_table.h b/system/vulkan/func_table.h
index 4d0e977..05658cf 100644
--- a/system/vulkan/func_table.h
+++ b/system/vulkan/func_table.h
@@ -284,6 +284,8 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 9cd8a79..d085ca4 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -265,6 +265,8 @@
         VkDeviceMemory currentBacking = VK_NULL_HANDLE;
         VkDeviceSize currentBackingOffset = 0;
         VkDeviceSize currentBackingSize = 0;
+        bool baseRequirementsKnown = false;
+        VkMemoryRequirements baseRequirements;
     };
 
     struct VkBuffer_Info {
@@ -275,6 +277,8 @@
         VkDeviceMemory currentBacking = VK_NULL_HANDLE;
         VkDeviceSize currentBackingOffset = 0;
         VkDeviceSize currentBackingSize = 0;
+        bool baseRequirementsKnown = false;
+        VkMemoryRequirements baseRequirements;
     };
 
     struct VkSemaphore_Info {
@@ -611,6 +615,11 @@
         return mFeatureInfo->hasDeferredVulkanCommands;
     }
 
+    bool supportsCreateResourcesWithRequirements() const {
+        if (!mFeatureInfo) return false;
+        return mFeatureInfo->hasVulkanCreateResourcesWithRequirements;
+    }
+
     int getHostInstanceExtensionIndex(const std::string& extName) const {
         int i = 0;
         for (const auto& prop : mHostInstanceExtensions) {
@@ -2060,12 +2069,10 @@
         dedicatedReqs->requiresDedicatedAllocation = VK_TRUE;
     }
 
-    void transformImageMemoryRequirementsForGuest(
+    void transformImageMemoryRequirementsForGuestLocked(
         VkImage image,
         VkMemoryRequirements* reqs) {
 
-        AutoLock lock(mLock);
-
         auto it = info_VkImage.find(image);
         if (it == info_VkImage.end()) return;
 
@@ -2080,12 +2087,10 @@
         transformExternalResourceMemoryRequirementsForGuest(reqs);
     }
 
-    void transformBufferMemoryRequirementsForGuest(
+    void transformBufferMemoryRequirementsForGuestLocked(
         VkBuffer buffer,
         VkMemoryRequirements* reqs) {
 
-        AutoLock lock(mLock);
-
         auto it = info_VkBuffer.find(buffer);
         if (it == info_VkBuffer.end()) return;
 
@@ -2238,7 +2243,14 @@
         }
 #endif
 
-        VkResult res = enc->vkCreateImage(device, &localCreateInfo, pAllocator, pImage);
+        VkResult res;
+        VkMemoryRequirements memReqs;
+
+        if (supportsCreateResourcesWithRequirements()) {
+            res = enc->vkCreateImageWithRequirementsGOOGLE(device, &localCreateInfo, pAllocator, pImage, &memReqs);
+        } else {
+            res = enc->vkCreateImage(device, &localCreateInfo, pAllocator, pImage);
+        }
 
         if (res != VK_SUCCESS) return res;
 
@@ -2253,10 +2265,19 @@
         info.createInfo = *pCreateInfo;
         info.createInfo.pNext = nullptr;
 
-        if (!extImgCiPtr) return res;
+        if (supportsCreateResourcesWithRequirements()) {
+            info.baseRequirementsKnown = true;
+        }
 
-        info.external = true;
-        info.externalCreateInfo = *extImgCiPtr;
+        if (extImgCiPtr) {
+            info.external = true;
+            info.externalCreateInfo = *extImgCiPtr;
+        }
+
+        if (info.baseRequirementsKnown) {
+            transformImageMemoryRequirementsForGuestLocked(*pImage, &memReqs);
+            info.baseRequirements = memReqs;
+        }
 
         return res;
     }
@@ -2321,11 +2342,32 @@
     void on_vkGetImageMemoryRequirements(
         void *context, VkDevice device, VkImage image,
         VkMemoryRequirements *pMemoryRequirements) {
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkImage.find(image);
+        if (it == info_VkImage.end()) return;
+
+        auto& info = it->second;
+
+        if (info.baseRequirementsKnown) {
+            *pMemoryRequirements = info.baseRequirements;
+            return;
+        }
+
+        lock.unlock();
+
         VkEncoder* enc = (VkEncoder*)context;
+
         enc->vkGetImageMemoryRequirements(
             device, image, pMemoryRequirements);
-        transformImageMemoryRequirementsForGuest(
+
+        lock.lock();
+
+        transformImageMemoryRequirementsForGuestLocked(
             image, pMemoryRequirements);
+        info.baseRequirementsKnown = true;
+        info.baseRequirements = *pMemoryRequirements;
     }
 
     void on_vkGetImageMemoryRequirements2(
@@ -2377,7 +2419,14 @@
         VkBuffer *pBuffer) {
         VkEncoder* enc = (VkEncoder*)context;
 
-        VkResult res = enc->vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+        VkResult res;
+        VkMemoryRequirements memReqs;
+
+        if (supportsCreateResourcesWithRequirements()) {
+            res = enc->vkCreateBufferWithRequirementsGOOGLE(device, pCreateInfo, pAllocator, pBuffer, &memReqs);
+        } else {
+            res = enc->vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+        }
 
         if (res != VK_SUCCESS) return res;
 
@@ -2391,13 +2440,22 @@
         info.createInfo = *pCreateInfo;
         info.createInfo.pNext = nullptr;
 
+        if (supportsCreateResourcesWithRequirements()) {
+            info.baseRequirementsKnown = true;
+        }
+
         const VkExternalMemoryBufferCreateInfo* extBufCi =
             vk_find_struct<VkExternalMemoryBufferCreateInfo>(pCreateInfo);
 
-        if (!extBufCi) return res;
+        if (extBufCi) {
+            info.external = true;
+            info.externalCreateInfo = *extBufCi;
+        }
 
-        info.external = true;
-        info.externalCreateInfo = *extBufCi;
+        if (info.baseRequirementsKnown) {
+            transformBufferMemoryRequirementsForGuestLocked(*pBuffer, &memReqs);
+            info.baseRequirements = memReqs;
+        }
 
         return res;
     }
@@ -2411,11 +2469,31 @@
 
     void on_vkGetBufferMemoryRequirements(
         void* context, VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
+
+        AutoLock lock(mLock);
+
+        auto it = info_VkBuffer.find(buffer);
+        if (it == info_VkBuffer.end()) return;
+
+        auto& info = it->second;
+
+        if (info.baseRequirementsKnown) {
+            *pMemoryRequirements = info.baseRequirements;
+            return;
+        }
+
+        lock.unlock();
+
         VkEncoder* enc = (VkEncoder*)context;
         enc->vkGetBufferMemoryRequirements(
             device, buffer, pMemoryRequirements);
-        transformBufferMemoryRequirementsForGuest(
+
+        lock.lock();
+
+        transformBufferMemoryRequirementsForGuestLocked(
             buffer, pMemoryRequirements);
+        info.baseRequirementsKnown = true;
+        info.baseRequirements = *pMemoryRequirements;
     }
 
     void on_vkGetBufferMemoryRequirements2(
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index 732bd21..6f43f7a 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -94,7 +94,11 @@
 
     // Assume the lock for the current encoder is held.
     void registerCleanupCallback(void* handle, VkEncoder::CleanupCallback cb) {
-        mCleanupCallbacks.insert({handle, cb});
+        if (mCleanupCallbacks.end() == mCleanupCallbacks.find(handle)) {
+            mCleanupCallbacks[handle] = cb;
+        } else {
+            return;
+        }
     }
 
     void unregisterCleanupCallback(void* handle) {
@@ -23096,5 +23100,210 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+VkResult VkEncoder::vkCreateImageWithRequirementsGOOGLE(
+    VkDevice device,
+    const VkImageCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkImage* pImage,
+    VkMemoryRequirements* pMemoryRequirements)
+{
+    AutoLock encoderLock(mImpl->lock);
+    AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE encode");
+    mImpl->log("start vkCreateImageWithRequirementsGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkDevice local_device;
+    VkImageCreateInfo* local_pCreateInfo;
+    VkAllocationCallbacks* local_pAllocator;
+    local_device = device;
+    local_pCreateInfo = nullptr;
+    if (pCreateInfo)
+    {
+        local_pCreateInfo = (VkImageCreateInfo*)pool->alloc(sizeof(const VkImageCreateInfo));
+        deepcopy_VkImageCreateInfo(pool, pCreateInfo, (VkImageCreateInfo*)(local_pCreateInfo));
+    }
+    local_pAllocator = nullptr;
+    if (pAllocator)
+    {
+        local_pAllocator = (VkAllocationCallbacks*)pool->alloc(sizeof(const VkAllocationCallbacks));
+        deepcopy_VkAllocationCallbacks(pool, pAllocator, (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    mImpl->resources()->unwrap_VkNativeBufferANDROID(pCreateInfo, local_pCreateInfo);
+    local_pAllocator = nullptr;
+    if (local_pCreateInfo)
+    {
+        transform_tohost_VkImageCreateInfo(mImpl->resources(), (VkImageCreateInfo*)(local_pCreateInfo));
+    }
+    if (local_pAllocator)
+    {
+        transform_tohost_VkAllocationCallbacks(mImpl->resources(), (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1520;
+        countingStream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1520, 1);
+        countingStream->write((uint64_t*)&cgen_var_1520, 1 * 8);
+        marshal_VkImageCreateInfo(countingStream, (VkImageCreateInfo*)(local_pCreateInfo));
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1521 = (uint64_t)(uintptr_t)local_pAllocator;
+        countingStream->putBe64(cgen_var_1521);
+        if (local_pAllocator)
+        {
+            marshal_VkAllocationCallbacks(countingStream, (VkAllocationCallbacks*)(local_pAllocator));
+        }
+        uint64_t cgen_var_1522;
+        countingStream->handleMapping()->mapHandles_VkImage_u64(pImage, &cgen_var_1522, 1);
+        countingStream->write((uint64_t*)&cgen_var_1522, 8);
+        marshal_VkMemoryRequirements(countingStream, (VkMemoryRequirements*)(pMemoryRequirements));
+    }
+    uint32_t packetSize_vkCreateImageWithRequirementsGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkCreateImageWithRequirementsGOOGLE = OP_vkCreateImageWithRequirementsGOOGLE;
+    stream->write(&opcode_vkCreateImageWithRequirementsGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkCreateImageWithRequirementsGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1523;
+    stream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1523, 1);
+    stream->write((uint64_t*)&cgen_var_1523, 1 * 8);
+    marshal_VkImageCreateInfo(stream, (VkImageCreateInfo*)(local_pCreateInfo));
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1524 = (uint64_t)(uintptr_t)local_pAllocator;
+    stream->putBe64(cgen_var_1524);
+    if (local_pAllocator)
+    {
+        marshal_VkAllocationCallbacks(stream, (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    stream->unsetHandleMapping() /* emit_marshal, is handle, possibly out */;
+    uint64_t cgen_var_1525;
+    stream->handleMapping()->mapHandles_VkImage_u64(pImage, &cgen_var_1525, 1);
+    stream->write((uint64_t*)&cgen_var_1525, 8);
+    stream->setHandleMapping(resources->unwrapMapping());
+    marshal_VkMemoryRequirements(stream, (VkMemoryRequirements*)(pMemoryRequirements));
+    AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE readParams");
+    stream->setHandleMapping(resources->createMapping());
+    uint64_t cgen_var_1526;
+    stream->read((uint64_t*)&cgen_var_1526, 8);
+    stream->handleMapping()->mapHandles_u64_VkImage(&cgen_var_1526, (VkImage*)pImage, 1);
+    stream->unsetHandleMapping();
+    unmarshal_VkMemoryRequirements(stream, (VkMemoryRequirements*)(pMemoryRequirements));
+    if (pMemoryRequirements)
+    {
+        transform_fromhost_VkMemoryRequirements(mImpl->resources(), (VkMemoryRequirements*)(pMemoryRequirements));
+    }
+    AEMU_SCOPED_TRACE("vkCreateImageWithRequirementsGOOGLE returnUnmarshal");
+    VkResult vkCreateImageWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
+    stream->read(&vkCreateImageWithRequirementsGOOGLE_VkResult_return, sizeof(VkResult));
+    countingStream->clearPool();
+    stream->clearPool();
+    pool->freeAll();
+    mImpl->log("finish vkCreateImageWithRequirementsGOOGLE");;
+    return vkCreateImageWithRequirementsGOOGLE_VkResult_return;
+}
+
+VkResult VkEncoder::vkCreateBufferWithRequirementsGOOGLE(
+    VkDevice device,
+    const VkBufferCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkBuffer* pBuffer,
+    VkMemoryRequirements* pMemoryRequirements)
+{
+    AutoLock encoderLock(mImpl->lock);
+    AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE encode");
+    mImpl->log("start vkCreateBufferWithRequirementsGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkDevice local_device;
+    VkBufferCreateInfo* local_pCreateInfo;
+    VkAllocationCallbacks* local_pAllocator;
+    local_device = device;
+    local_pCreateInfo = nullptr;
+    if (pCreateInfo)
+    {
+        local_pCreateInfo = (VkBufferCreateInfo*)pool->alloc(sizeof(const VkBufferCreateInfo));
+        deepcopy_VkBufferCreateInfo(pool, pCreateInfo, (VkBufferCreateInfo*)(local_pCreateInfo));
+    }
+    local_pAllocator = nullptr;
+    if (pAllocator)
+    {
+        local_pAllocator = (VkAllocationCallbacks*)pool->alloc(sizeof(const VkAllocationCallbacks));
+        deepcopy_VkAllocationCallbacks(pool, pAllocator, (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    local_pAllocator = nullptr;
+    if (local_pCreateInfo)
+    {
+        transform_tohost_VkBufferCreateInfo(mImpl->resources(), (VkBufferCreateInfo*)(local_pCreateInfo));
+    }
+    if (local_pAllocator)
+    {
+        transform_tohost_VkAllocationCallbacks(mImpl->resources(), (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1527;
+        countingStream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1527, 1);
+        countingStream->write((uint64_t*)&cgen_var_1527, 1 * 8);
+        marshal_VkBufferCreateInfo(countingStream, (VkBufferCreateInfo*)(local_pCreateInfo));
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1528 = (uint64_t)(uintptr_t)local_pAllocator;
+        countingStream->putBe64(cgen_var_1528);
+        if (local_pAllocator)
+        {
+            marshal_VkAllocationCallbacks(countingStream, (VkAllocationCallbacks*)(local_pAllocator));
+        }
+        uint64_t cgen_var_1529;
+        countingStream->handleMapping()->mapHandles_VkBuffer_u64(pBuffer, &cgen_var_1529, 1);
+        countingStream->write((uint64_t*)&cgen_var_1529, 8);
+        marshal_VkMemoryRequirements(countingStream, (VkMemoryRequirements*)(pMemoryRequirements));
+    }
+    uint32_t packetSize_vkCreateBufferWithRequirementsGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkCreateBufferWithRequirementsGOOGLE = OP_vkCreateBufferWithRequirementsGOOGLE;
+    stream->write(&opcode_vkCreateBufferWithRequirementsGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkCreateBufferWithRequirementsGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1530;
+    stream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1530, 1);
+    stream->write((uint64_t*)&cgen_var_1530, 1 * 8);
+    marshal_VkBufferCreateInfo(stream, (VkBufferCreateInfo*)(local_pCreateInfo));
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1531 = (uint64_t)(uintptr_t)local_pAllocator;
+    stream->putBe64(cgen_var_1531);
+    if (local_pAllocator)
+    {
+        marshal_VkAllocationCallbacks(stream, (VkAllocationCallbacks*)(local_pAllocator));
+    }
+    stream->unsetHandleMapping() /* emit_marshal, is handle, possibly out */;
+    uint64_t cgen_var_1532;
+    stream->handleMapping()->mapHandles_VkBuffer_u64(pBuffer, &cgen_var_1532, 1);
+    stream->write((uint64_t*)&cgen_var_1532, 8);
+    stream->setHandleMapping(resources->unwrapMapping());
+    marshal_VkMemoryRequirements(stream, (VkMemoryRequirements*)(pMemoryRequirements));
+    AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE readParams");
+    stream->setHandleMapping(resources->createMapping());
+    uint64_t cgen_var_1533;
+    stream->read((uint64_t*)&cgen_var_1533, 8);
+    stream->handleMapping()->mapHandles_u64_VkBuffer(&cgen_var_1533, (VkBuffer*)pBuffer, 1);
+    stream->unsetHandleMapping();
+    unmarshal_VkMemoryRequirements(stream, (VkMemoryRequirements*)(pMemoryRequirements));
+    if (pMemoryRequirements)
+    {
+        transform_fromhost_VkMemoryRequirements(mImpl->resources(), (VkMemoryRequirements*)(pMemoryRequirements));
+    }
+    AEMU_SCOPED_TRACE("vkCreateBufferWithRequirementsGOOGLE returnUnmarshal");
+    VkResult vkCreateBufferWithRequirementsGOOGLE_VkResult_return = (VkResult)0;
+    stream->read(&vkCreateBufferWithRequirementsGOOGLE_VkResult_return, sizeof(VkResult));
+    countingStream->clearPool();
+    stream->clearPool();
+    pool->freeAll();
+    mImpl->log("finish vkCreateBufferWithRequirementsGOOGLE");;
+    return vkCreateBufferWithRequirementsGOOGLE_VkResult_return;
+}
+
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h
index 65debda..dd2cd64 100644
--- a/system/vulkan_enc/VkEncoder.h
+++ b/system/vulkan_enc/VkEncoder.h
@@ -1793,6 +1793,20 @@
         uint32_t needHostSync,
         uint32_t sequenceNumber);
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+    VkResult vkCreateImageWithRequirementsGOOGLE(
+    VkDevice device,
+        const VkImageCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkImage* pImage,
+        VkMemoryRequirements* pMemoryRequirements);
+    VkResult vkCreateBufferWithRequirementsGOOGLE(
+    VkDevice device,
+        const VkBufferCreateInfo* pCreateInfo,
+        const VkAllocationCallbacks* pAllocator,
+        VkBuffer* pBuffer,
+        VkMemoryRequirements* pMemoryRequirements);
+#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 5b004c0..1513661 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6384,6 +6384,8 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 b367ee0..ca6d6dc 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -2026,5 +2026,7 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 c42f6e8..481ce6c 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -282,6 +282,8 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 1d671f8..7df1ac1 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -299,5 +299,7 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 7d16b31..fbc6a48 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
@@ -4748,6 +4748,8 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 e973064..911ff2f 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.h
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
@@ -1679,5 +1679,7 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 96efd31..0ed32d3 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -13453,6 +13453,8 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#endif
 void marshal_extension_struct(
     VulkanStreamGuest* vkStream,
     const void* structExtension)
@@ -16218,6 +16220,16 @@
             return "OP_vkCommandBufferHostSyncGOOGLE";
         }
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+        case OP_vkCreateImageWithRequirementsGOOGLE:
+        {
+            return "OP_vkCreateImageWithRequirementsGOOGLE";
+        }
+        case OP_vkCreateBufferWithRequirementsGOOGLE:
+        {
+            return "OP_vkCreateBufferWithRequirementsGOOGLE";
+        }
+#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 154b7de..ad7f8f3 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -3390,6 +3390,10 @@
 #define OP_vkResetCommandBufferAsyncGOOGLE 20323
 #define OP_vkCommandBufferHostSyncGOOGLE 20324
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#define OP_vkCreateImageWithRequirementsGOOGLE 20325
+#define OP_vkCreateBufferWithRequirementsGOOGLE 20326
+#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 662b8f0..b180ce8 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -429,6 +429,11 @@
     uint32_t needHostSync,
     uint32_t sequenceNumber);
 
+#define VK_GOOGLE_create_resources_with_requirements 1
+
+typedef void (VKAPI_PTR *PFN_vkCreateImageWithRequirementsGOOGLE)(
+    VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage, VkMemoryRequirements* pMemoryRequirements);
+
 #ifndef VK_FUCHSIA_buffer_collection
 #define VK_FUCHSIA_buffer_collection 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferCollectionFUCHSIA)
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.cpp b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
index aa42af7..d06135e 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -8945,6 +8945,8 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#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 754c033..217284e 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.h
@@ -3067,5 +3067,7 @@
 #endif
 #ifdef VK_GOOGLE_async_command_buffers
 #endif
+#ifdef VK_GOOGLE_create_resources_with_requirements
+#endif
 
 } // namespace goldfish_vk