virtio-gpu: hostmem

bug: 146066070
Change-Id: I1c06293804e800694f355716f608b76e9bfdb428
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index e20c129..4edf1fd 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -97,6 +97,9 @@
 // GL protocol v2
 static const char kAsyncUnmapBuffer[] = "ANDROID_EMU_async_unmap_buffer";
 
+// virtio-gpu-next
+static const char kVirtioGpuNext[] = "ANDROID_EMU_virtio_gpu_next";
+
 // Struct describing available emulator features
 struct EmulatorFeatureInfo {
 
@@ -112,7 +115,8 @@
         hasVulkanCreateResourcesWithRequirements(false),
         hasVulkanIgnoredHandles(false),
         hasYUVCache (false),
-        hasAsyncUnmapBuffer (false) { }
+        hasAsyncUnmapBuffer (false),
+        hasVirtioGpuNext (false) { }
 
     SyncImpl syncImpl;
     DmaImpl dmaImpl;
@@ -126,6 +130,7 @@
     bool hasVulkanIgnoredHandles;
     bool hasYUVCache;
     bool hasAsyncUnmapBuffer;
+    bool hasVirtioGpuNext;
 };
 
 enum HostConnectionType {
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index f69b1d5..bbe2857 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -613,6 +613,7 @@
         queryAndSetVulkanIgnoredHandles(m_rcEnc);
         queryAndSetYUVCache(m_rcEnc);
         queryAndSetAsyncUnmapBuffer(m_rcEnc);
+        queryAndSetVirtioGpuNext(m_rcEnc);
         if (m_processPipe) {
             m_processPipe->processPipeInit(m_connectionType, m_rcEnc);
         }
@@ -810,3 +811,9 @@
     }
 }
 
+void HostConnection::queryAndSetVirtioGpuNext(ExtendedRCEncoderContext* rcEnc) {
+    std::string glExtensions = queryGLExtensions(rcEnc);
+    if (glExtensions.find(kVirtioGpuNext) != std::string::npos) {
+        rcEnc->featureInfo()->hasVirtioGpuNext = true;
+    }
+}
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index 0f262a3..c91af0b 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -203,6 +203,7 @@
     void queryAndSetVulkanIgnoredHandles(ExtendedRCEncoderContext *rcEnc);
     void queryAndSetYUVCache(ExtendedRCEncoderContext *mrcEnc);
     void queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext *rcEnc);
+    void queryAndSetVirtioGpuNext(ExtendedRCEncoderContext *rcEnc);
 
 private:
     HostConnectionType m_connectionType;
diff --git a/system/vulkan/func_table.cpp b/system/vulkan/func_table.cpp
index c9dd80d..80f586f 100644
--- a/system/vulkan/func_table.cpp
+++ b/system/vulkan/func_table.cpp
@@ -5216,6 +5216,39 @@
     return vkCreateBufferWithRequirementsGOOGLE_VkResult_return;
 }
 #endif
+#ifdef VK_GOOGLE_address_space_info
+static VkResult entry_vkGetMemoryHostAddressInfoGOOGLE(
+    VkDevice device,
+    VkDeviceMemory memory,
+    uint64_t* pAddress,
+    uint64_t* pSize,
+    uint64_t* pHostmemId)
+{
+    AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    VkResult vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = (VkResult)0;
+    vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = vkEnc->vkGetMemoryHostAddressInfoGOOGLE(device, memory, pAddress, pSize, pHostmemId);
+    return vkGetMemoryHostAddressInfoGOOGLE_VkResult_return;
+}
+static VkResult dynCheck_entry_vkGetMemoryHostAddressInfoGOOGLE(
+    VkDevice device,
+    VkDeviceMemory memory,
+    uint64_t* pAddress,
+    uint64_t* pSize,
+    uint64_t* pHostmemId)
+{
+    auto resources = ResourceTracker::get();
+    if (!resources->hasDeviceExtension(device, "VK_GOOGLE_address_space_info"))
+    {
+        sOnInvalidDynamicallyCheckedCall("vkGetMemoryHostAddressInfoGOOGLE", "VK_GOOGLE_address_space_info");
+    }
+    AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE");
+    auto vkEnc = HostConnection::get()->vkEncoder();
+    VkResult vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = (VkResult)0;
+    vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = vkEnc->vkGetMemoryHostAddressInfoGOOGLE(device, memory, pAddress, pSize, pHostmemId);
+    return vkGetMemoryHostAddressInfoGOOGLE_VkResult_return;
+}
+#endif
 void* goldfish_vulkan_get_proc_address(const char* name){
 #ifdef VK_VERSION_1_0
     if (!strcmp(name, "vkCreateInstance"))
@@ -6661,6 +6694,12 @@
         return nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_address_space_info
+    if (!strcmp(name, "vkGetMemoryHostAddressInfoGOOGLE"))
+    {
+        return nullptr;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_instance_proc_address(VkInstance instance, const char* name){
@@ -8203,6 +8242,12 @@
         return (void*)dynCheck_entry_vkCreateBufferWithRequirementsGOOGLE;
     }
 #endif
+#ifdef VK_GOOGLE_address_space_info
+    if (!strcmp(name, "vkGetMemoryHostAddressInfoGOOGLE"))
+    {
+        return (void*)dynCheck_entry_vkGetMemoryHostAddressInfoGOOGLE;
+    }
+#endif
     return nullptr;
 }
 void* goldfish_vulkan_get_device_proc_address(VkDevice device, const char* name){
@@ -9814,6 +9859,13 @@
         return hasExt ? (void*)entry_vkCreateBufferWithRequirementsGOOGLE : nullptr;
     }
 #endif
+#ifdef VK_GOOGLE_address_space_info
+    if (!strcmp(name, "vkGetMemoryHostAddressInfoGOOGLE"))
+    {
+        bool hasExt = resources->hasDeviceExtension(device, "VK_GOOGLE_address_space_info");
+        return hasExt ? (void*)entry_vkGetMemoryHostAddressInfoGOOGLE : nullptr;
+    }
+#endif
     return nullptr;
 }
 
diff --git a/system/vulkan/func_table.h b/system/vulkan/func_table.h
index 05658cf..91ffd65 100644
--- a/system/vulkan/func_table.h
+++ b/system/vulkan/func_table.h
@@ -286,6 +286,8 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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/Android.mk b/system/vulkan_enc/Android.mk
index 2d280be..984db7f 100644
--- a/system/vulkan_enc/Android.mk
+++ b/system/vulkan_enc/Android.mk
@@ -26,11 +26,15 @@
 LOCAL_C_INCLUDES += \
     $(LOCAL_PATH) \
     $(LOCAL_PATH)/../vulkan_enc \
+    external/libdrm \
+    external/minigbm/cros_gralloc \
 
 LOCAL_HEADER_LIBRARIES += \
     hwvulkan_headers \
     vulkan_headers \
 
+LOCAL_SHARED_LIBRARIES += libdrm
+
 endif
 
 LOCAL_CFLAGS += \
diff --git a/system/vulkan_enc/CMakeLists.txt b/system/vulkan_enc/CMakeLists.txt
index 39cd64a..dec0c66 100644
--- a/system/vulkan_enc/CMakeLists.txt
+++ b/system/vulkan_enc/CMakeLists.txt
@@ -1,7 +1,7 @@
 # This is an autogenerated file! Do not edit!
 # instead run make from .../device/generic/goldfish-opengl
 # which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc/Android.mk" "c6bf087d25d8e5fa86d79a5ace0bde2b5b79a583e6cc12f0f2ab6a2131e29ab8")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc/Android.mk" "a4b1fb11cf3e68cc49f055258b6b590798eeecb2d3e6e565c78549a39a341911")
 set(vulkan_enc_src AndroidHardwareBuffer.cpp HostVisibleMemoryVirtualization.cpp Resources.cpp Validation.cpp VulkanStreamGuest.cpp VulkanHandleMapping.cpp ResourceTracker.cpp VkEncoder.cpp goldfish_vk_extension_structs_guest.cpp goldfish_vk_marshaling_guest.cpp goldfish_vk_deepcopy_guest.cpp goldfish_vk_handlemap_guest.cpp goldfish_vk_transform_guest.cpp)
 android_add_library(TARGET vulkan_enc SHARED LICENSE Apache-2.0 SRC AndroidHardwareBuffer.cpp HostVisibleMemoryVirtualization.cpp Resources.cpp Validation.cpp VulkanStreamGuest.cpp VulkanHandleMapping.cpp ResourceTracker.cpp VkEncoder.cpp goldfish_vk_extension_structs_guest.cpp goldfish_vk_marshaling_guest.cpp goldfish_vk_deepcopy_guest.cpp goldfish_vk_handlemap_guest.cpp goldfish_vk_transform_guest.cpp)
 target_include_directories(vulkan_enc PRIVATE ${GOLDFISH_DEVICE_ROOT}/system/renderControl_enc ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/shared/OpenglCodecCommon ${GOLDFISH_DEVICE_ROOT}/system/vulkan_enc ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/host/include/vulkan)
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
index b6bd91a..2db7e6a 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
@@ -19,6 +19,8 @@
 #include "Resources.h"
 #include "VkEncoder.h"
 
+#include "../OpenglSystemCommon/EmulatorFeatureInfo.h"
+
 #include <log/log.h>
 
 #include <set>
@@ -62,7 +64,7 @@
 void initHostVisibleMemoryVirtualizationInfo(
     VkPhysicalDevice physicalDevice,
     const VkPhysicalDeviceMemoryProperties* memoryProperties,
-    bool hasDirectMem,
+    const EmulatorFeatureInfo* featureInfo,
     HostVisibleMemoryVirtualizationInfo* info_out) {
 
     if (info_out->initialized) return;
@@ -73,10 +75,12 @@
     info_out->memoryPropertiesSupported =
         canFitVirtualHostVisibleMemoryInfo(memoryProperties);
 
-    info_out->directMemSupported = hasDirectMem;
+    info_out->directMemSupported = featureInfo->hasDirectMem;
+    info_out->virtioGpuNextSupported = featureInfo->hasVirtioGpuNext;
 
     if (!info_out->memoryPropertiesSupported ||
-        !info_out->directMemSupported) {
+        (!info_out->directMemSupported &&
+         !info_out->virtioGpuNextSupported)) {
         info_out->virtualizationSupported = false;
         return;
     }
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.h b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
index 84e39bb..305dca2 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.h
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.h
@@ -18,6 +18,8 @@
 
 #define VIRTUAL_HOST_VISIBLE_HEAP_SIZE 512ULL * (1048576ULL)
 
+struct EmulatorFeatureInfo;
+
 namespace android {
 namespace base {
 namespace guest {
@@ -37,6 +39,7 @@
     bool memoryPropertiesSupported;
     bool directMemSupported;
     bool virtualizationSupported;
+    bool virtioGpuNextSupported;
 
     VkPhysicalDevice physicalDevice;
 
@@ -58,7 +61,7 @@
 void initHostVisibleMemoryVirtualizationInfo(
     VkPhysicalDevice physicalDevice,
     const VkPhysicalDeviceMemoryProperties* memoryProperties,
-    bool directMemSupported,
+    const EmulatorFeatureInfo* featureInfo,
     HostVisibleMemoryVirtualizationInfo* info_out);
 
 bool isHostVisibleMemoryTypeIndexForGuest(
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index 84e41fc..809732c 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -33,6 +33,13 @@
 
 #include "AndroidHardwareBuffer.h"
 
+#ifndef HOST_BUILD
+#include <drm/virtgpu_drm.h>
+#include <xf86drm.h>
+#endif
+
+#include "VirtioGpuNext.h"
+
 #endif // VK_USE_PLATFORM_ANDROID_KHR
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
@@ -240,6 +247,11 @@
         std::set<std::string> enabledExtensions;
     };
 
+    struct VirtioGpuHostmemResourceInfo {
+        uint32_t resourceId = 0;
+        int primeFd = -1;
+    };
+
     struct VkDeviceMemory_Info {
         VkDeviceSize allocationSize = 0;
         VkDeviceSize mappedSize = 0;
@@ -249,6 +261,7 @@
         bool directMapped = false;
         GoldfishAddressSpaceBlock*
             goldfishAddressSpaceBlock = nullptr;
+        VirtioGpuHostmemResourceInfo resInfo;
         SubAlloc subAlloc;
         AHardwareBuffer* ahw = nullptr;
         zx_handle_t vmoHandle = ZX_HANDLE_INVALID;
@@ -487,7 +500,7 @@
         info.memProps = memProps;
         initHostVisibleMemoryVirtualizationInfo(
             physdev, &memProps,
-            mFeatureInfo->hasDirectMem,
+            mFeatureInfo.get(),
             &mHostVisibleMemoryVirtInfo);
         info.apiVersion = props.apiVersion;
 
@@ -622,6 +635,13 @@
         if (mFeatureInfo->hasVulkanIgnoredHandles) {
             mStreamFeatureBits |= VULKAN_STREAM_FEATURE_IGNORED_HANDLES_BIT;
         }
+
+#if !defined(HOST_BUILD) && defined(VK_USE_PLATFORM_ANDROID_KHR)
+        if (mFeatureInfo->hasVirtioGpuNext) {
+            ALOGD("%s: has virtio-gpu-next; create hostmem rendernode\n", __func__);
+            mRendernodeFd = drmOpenRender(128 /* RENDERNODE_MINOR */);
+        }
+#endif
     }
 
     void setThreadingCallbacks(const ResourceTracker::ThreadingCallbacks& callbacks) {
@@ -1145,7 +1165,7 @@
         initHostVisibleMemoryVirtualizationInfo(
             physdev,
             out,
-            mFeatureInfo->hasDirectMem,
+            mFeatureInfo.get(),
             &mHostVisibleMemoryVirtInfo);
 
         if (mHostVisibleMemoryVirtInfo.virtualizationSupported) {
@@ -1161,7 +1181,7 @@
         initHostVisibleMemoryVirtualizationInfo(
             physdev,
             &out->memoryProperties,
-            mFeatureInfo->hasDirectMem,
+            mFeatureInfo.get(),
             &mHostVisibleMemoryVirtInfo);
 
         if (mHostVisibleMemoryVirtInfo.virtualizationSupported) {
@@ -1631,11 +1651,67 @@
 
             uint64_t directMappedAddr = 0;
 
-            mLock.unlock();
-            VkResult directMapResult =
-                enc->vkMapMemoryIntoAddressSpaceGOOGLE(
-                    device, hostMemAlloc.memory, &directMappedAddr);
-            mLock.lock();
+
+            VkResult directMapResult = VK_SUCCESS;
+            if (mFeatureInfo->hasDirectMem) {
+                mLock.unlock();
+                directMapResult =
+                    enc->vkMapMemoryIntoAddressSpaceGOOGLE(
+                            device, hostMemAlloc.memory, &directMappedAddr);
+                mLock.lock();
+            } else if (mFeatureInfo->hasVirtioGpuNext) {
+#if !defined(HOST_BUILD) && defined(VK_USE_PLATFORM_ANDROID_KHR)
+                uint64_t hvaSizeId[3];
+
+                mLock.unlock();
+                enc->vkGetMemoryHostAddressInfoGOOGLE(
+                        device, hostMemAlloc.memory,
+                        &hvaSizeId[0], &hvaSizeId[1], &hvaSizeId[2]);
+                ALOGD("%s: hvaOff, size: 0x%llx 0x%llx id: 0x%llx\n", __func__,
+                        (unsigned long long)hvaSizeId[0],
+                        (unsigned long long)hvaSizeId[1],
+                        (unsigned long long)hvaSizeId[2]);
+                mLock.lock();
+
+                struct drm_virtgpu_resource_create_v2 drm_rc_v2 = { 0 };
+                drm_rc_v2.args = (uint64_t)&hvaSizeId[2];
+                drm_rc_v2.args_size = sizeof(uint64_t);
+                drm_rc_v2.size = hvaSizeId[1];
+                drm_rc_v2.flags = VIRTGPU_RESOURCE_TYPE_HOST;
+
+                int res = drmIoctl(
+                    mRendernodeFd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_V2, &drm_rc_v2);
+
+                if (res) {
+                    ALOGE("%s: Failed to resource create v2: sterror: %s errno: %d\n", __func__,
+                            strerror(errno), errno);
+                    abort();
+                }
+
+                struct drm_virtgpu_map map_info = {
+                    .handle = drm_rc_v2.bo_handle,
+                };
+
+                res = drmIoctl(mRendernodeFd, DRM_IOCTL_VIRTGPU_MAP, &map_info);
+                if (res) {
+                    ALOGE("%s: Failed to virtgpu map: sterror: %s errno: %d\n", __func__,
+                            strerror(errno), errno);
+                    abort();
+                }
+
+                directMappedAddr = (uint64_t)(uintptr_t)
+                    mmap64(0, hvaSizeId[1], PROT_WRITE, MAP_SHARED, mRendernodeFd, map_info.offset);
+
+                if (!directMappedAddr) {
+                    ALOGE("%s: mmap of virtio gpu resource failed\n", __func__);
+                    abort();
+                }
+
+                // add the host's page offset
+                directMappedAddr += (uint64_t)(uintptr_t)(hvaSizeId[0]) & (PAGE_SIZE - 1);
+				directMapResult = VK_SUCCESS;
+#endif // VK_USE_PLATFORM_ANDROID_KHR
+            }
 
             if (directMapResult != VK_SUCCESS) {
                 hostMemAlloc.initialized = true;
@@ -4024,6 +4100,9 @@
     std::vector<VkExtensionProperties> mHostDeviceExtensions;
 
     int mSyncDeviceFd = -1;
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+    int mRendernodeFd = -1;
+#endif
 
 #ifdef VK_USE_PLATFORM_FUCHSIA
     fuchsia::hardware::goldfish::ControlDeviceSyncPtr mControlDevice;
diff --git a/system/vulkan_enc/VirtioGpuNext.h b/system/vulkan_enc/VirtioGpuNext.h
new file mode 100644
index 0000000..4037973
--- /dev/null
+++ b/system/vulkan_enc/VirtioGpuNext.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2020 The Android Open Source Project
+// Copyright (C) 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#ifndef HOST_BUILD
+#include "drm.h"
+#endif
+
+#define DRM_VIRTGPU_RESOURCE_CREATE_V2 0x0a
+
+struct drm_virtgpu_resource_create_v2 {
+#define VIRTGPU_RESOURCE_TYPE_MASK       0x0000f
+#define VIRTGPU_RESOURCE_TYPE_DEFAULT_V1 0x00001
+#define VIRTGPU_RESOURCE_TYPE_DEFAULT_V2 0x00002
+#define VIRTGPU_RESOURCE_TYPE_HOST       0x00003
+#define VIRTGPU_RESOURCE_TYPE_GUEST      0x00004
+/*
+ * Error cases:
+ * HOST_VISIBLE_BIT without VIRTGPU_RESOURCE_TYPE_HOST
+ */
+#define VIRTGPU_RESOURCE_HOST_MASK            0x000f0
+#define VIRTGPU_RESOURCE_HOST_VISIBLE_BIT     0x00010
+
+#define VIRTGPU_RESOURCE_GUEST_MASK                  0x00f00
+#define VIRTGPU_RESOURCE_GUEST_SHARED_BIT            0x00100
+#define VIRTGPU_RESOURCE_GUEST_EMULATED_COHERENT_BIT 0x00200
+
+#define VIRTGPU_RESOURCE_CACHE_MASK      0x0f000
+#define VIRTGPU_RESOURCE_CACHE_CACHED    0x01000
+#define VIRTGPU_RESOURCE_CACHE_UNCACHED  0x02000
+#define VIRTGPU_RESOURCE_CACHE_WC        0x03000
+/*
+ * VIRTGPU_RESOURCE_EXPORTABLE_BIT - host resource *can* be exported as an fd.
+ */
+#define VIRTGPU_RESOURCE_EXPORT_MASK    0xf0000
+#define VIRTGPU_RESOURCE_EXPORTABLE_BIT 0x10000
+	uint32_t flags;
+	uint32_t args_size;
+	uint64_t size;
+	uint32_t bo_handle;
+	uint32_t res_handle;
+	uint64_t args;
+};
+
+#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_V2				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_V2,	\
+		struct drm_virtgpu_resource_create_v2)
+
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index 3b57678..b5b6eea 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -23305,5 +23305,133 @@
 }
 
 #endif
+#ifdef VK_GOOGLE_address_space_info
+VkResult VkEncoder::vkGetMemoryHostAddressInfoGOOGLE(
+    VkDevice device,
+    VkDeviceMemory memory,
+    uint64_t* pAddress,
+    uint64_t* pSize,
+    uint64_t* pHostmemId)
+{
+    AutoLock encoderLock(mImpl->lock);
+    AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE encode");
+    mImpl->log("start vkGetMemoryHostAddressInfoGOOGLE");
+    auto stream = mImpl->stream();
+    auto countingStream = mImpl->countingStream();
+    auto resources = mImpl->resources();
+    auto pool = mImpl->pool();
+    stream->setHandleMapping(resources->unwrapMapping());
+    VkDevice local_device;
+    VkDeviceMemory local_memory;
+    local_device = device;
+    local_memory = memory;
+    mImpl->resources()->deviceMemoryTransform_tohost((VkDeviceMemory*)&local_memory, 1, (VkDeviceSize*)nullptr, 0, (VkDeviceSize*)nullptr, 0, (uint32_t*)nullptr, 0, (uint32_t*)nullptr, 0);
+    countingStream->rewind();
+    {
+        uint64_t cgen_var_1534;
+        countingStream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1534, 1);
+        countingStream->write((uint64_t*)&cgen_var_1534, 1 * 8);
+        uint64_t cgen_var_1535;
+        countingStream->handleMapping()->mapHandles_VkDeviceMemory_u64(&local_memory, &cgen_var_1535, 1);
+        countingStream->write((uint64_t*)&cgen_var_1535, 1 * 8);
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1536 = (uint64_t)(uintptr_t)pAddress;
+        countingStream->putBe64(cgen_var_1536);
+        if (pAddress)
+        {
+            countingStream->write((uint64_t*)pAddress, sizeof(uint64_t));
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1537 = (uint64_t)(uintptr_t)pSize;
+        countingStream->putBe64(cgen_var_1537);
+        if (pSize)
+        {
+            countingStream->write((uint64_t*)pSize, sizeof(uint64_t));
+        }
+        // WARNING PTR CHECK
+        uint64_t cgen_var_1538 = (uint64_t)(uintptr_t)pHostmemId;
+        countingStream->putBe64(cgen_var_1538);
+        if (pHostmemId)
+        {
+            countingStream->write((uint64_t*)pHostmemId, sizeof(uint64_t));
+        }
+    }
+    uint32_t packetSize_vkGetMemoryHostAddressInfoGOOGLE = 4 + 4 + (uint32_t)countingStream->bytesWritten();
+    countingStream->rewind();
+    uint32_t opcode_vkGetMemoryHostAddressInfoGOOGLE = OP_vkGetMemoryHostAddressInfoGOOGLE;
+    stream->write(&opcode_vkGetMemoryHostAddressInfoGOOGLE, sizeof(uint32_t));
+    stream->write(&packetSize_vkGetMemoryHostAddressInfoGOOGLE, sizeof(uint32_t));
+    uint64_t cgen_var_1539;
+    stream->handleMapping()->mapHandles_VkDevice_u64(&local_device, &cgen_var_1539, 1);
+    stream->write((uint64_t*)&cgen_var_1539, 1 * 8);
+    uint64_t cgen_var_1540;
+    stream->handleMapping()->mapHandles_VkDeviceMemory_u64(&local_memory, &cgen_var_1540, 1);
+    stream->write((uint64_t*)&cgen_var_1540, 1 * 8);
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1541 = (uint64_t)(uintptr_t)pAddress;
+    stream->putBe64(cgen_var_1541);
+    if (pAddress)
+    {
+        stream->write((uint64_t*)pAddress, sizeof(uint64_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1542 = (uint64_t)(uintptr_t)pSize;
+    stream->putBe64(cgen_var_1542);
+    if (pSize)
+    {
+        stream->write((uint64_t*)pSize, sizeof(uint64_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t cgen_var_1543 = (uint64_t)(uintptr_t)pHostmemId;
+    stream->putBe64(cgen_var_1543);
+    if (pHostmemId)
+    {
+        stream->write((uint64_t*)pHostmemId, sizeof(uint64_t));
+    }
+    AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE readParams");
+    // WARNING PTR CHECK
+    uint64_t* check_pAddress;
+    check_pAddress = (uint64_t*)(uintptr_t)stream->getBe64();
+    if (pAddress)
+    {
+        if (!(check_pAddress))
+        {
+            fprintf(stderr, "fatal: pAddress inconsistent between guest and host\n");
+        }
+        stream->read((uint64_t*)pAddress, sizeof(uint64_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t* check_pSize;
+    check_pSize = (uint64_t*)(uintptr_t)stream->getBe64();
+    if (pSize)
+    {
+        if (!(check_pSize))
+        {
+            fprintf(stderr, "fatal: pSize inconsistent between guest and host\n");
+        }
+        stream->read((uint64_t*)pSize, sizeof(uint64_t));
+    }
+    // WARNING PTR CHECK
+    uint64_t* check_pHostmemId;
+    check_pHostmemId = (uint64_t*)(uintptr_t)stream->getBe64();
+    if (pHostmemId)
+    {
+        if (!(check_pHostmemId))
+        {
+            fprintf(stderr, "fatal: pHostmemId inconsistent between guest and host\n");
+        }
+        stream->read((uint64_t*)pHostmemId, sizeof(uint64_t));
+    }
+    AEMU_SCOPED_TRACE("vkGetMemoryHostAddressInfoGOOGLE returnUnmarshal");
+    VkResult vkGetMemoryHostAddressInfoGOOGLE_VkResult_return = (VkResult)0;
+    stream->read(&vkGetMemoryHostAddressInfoGOOGLE_VkResult_return, sizeof(VkResult));
+    countingStream->clearPool();
+    stream->clearPool();
+    pool->freeAll();
+    mImpl->log("finish vkGetMemoryHostAddressInfoGOOGLE");;
+    return vkGetMemoryHostAddressInfoGOOGLE_VkResult_return;
+}
+
+#endif
 
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/VkEncoder.h b/system/vulkan_enc/VkEncoder.h
index dd2cd64..4cab74f 100644
--- a/system/vulkan_enc/VkEncoder.h
+++ b/system/vulkan_enc/VkEncoder.h
@@ -1807,6 +1807,14 @@
         VkBuffer* pBuffer,
         VkMemoryRequirements* pMemoryRequirements);
 #endif
+#ifdef VK_GOOGLE_address_space_info
+    VkResult vkGetMemoryHostAddressInfoGOOGLE(
+    VkDevice device,
+        VkDeviceMemory memory,
+        uint64_t* pAddress,
+        uint64_t* pSize,
+        uint64_t* pHostmemId);
+#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 1513661..917ca59 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.cpp
@@ -6386,6 +6386,8 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 ca6d6dc..b1ffaa6 100644
--- a/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
+++ b/system/vulkan_enc/goldfish_vk_deepcopy_guest.h
@@ -2028,5 +2028,7 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 481ce6c..08bba9f 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.cpp
@@ -284,6 +284,8 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 7df1ac1..4fa4e3c 100644
--- a/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
+++ b/system/vulkan_enc/goldfish_vk_extension_structs_guest.h
@@ -301,5 +301,7 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 fbc6a48..56adc3a 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.cpp
@@ -4750,6 +4750,8 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 911ff2f..8785741 100644
--- a/system/vulkan_enc/goldfish_vk_handlemap_guest.h
+++ b/system/vulkan_enc/goldfish_vk_handlemap_guest.h
@@ -1681,5 +1681,7 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 1ef4d04..24b8112 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.cpp
@@ -13613,6 +13613,8 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#endif
 void marshal_extension_struct(
     VulkanStreamGuest* vkStream,
     const void* structExtension)
@@ -16388,6 +16390,12 @@
             return "OP_vkCreateBufferWithRequirementsGOOGLE";
         }
 #endif
+#ifdef VK_GOOGLE_address_space_info
+        case OP_vkGetMemoryHostAddressInfoGOOGLE:
+        {
+            return "OP_vkGetMemoryHostAddressInfoGOOGLE";
+        }
+#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 ad7f8f3..da9e961 100644
--- a/system/vulkan_enc/goldfish_vk_marshaling_guest.h
+++ b/system/vulkan_enc/goldfish_vk_marshaling_guest.h
@@ -3394,6 +3394,9 @@
 #define OP_vkCreateImageWithRequirementsGOOGLE 20325
 #define OP_vkCreateBufferWithRequirementsGOOGLE 20326
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#define OP_vkGetMemoryHostAddressInfoGOOGLE 20327
+#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 b967d89..dd0c155 100644
--- a/system/vulkan_enc/goldfish_vk_private_defs.h
+++ b/system/vulkan_enc/goldfish_vk_private_defs.h
@@ -115,6 +115,10 @@
 typedef VkResult (VKAPI_PTR *PFN_vkRegisterImageColorBufferGOOGLE)(VkDevice device, VkImage image, uint32_t colorBuffer);
 typedef VkResult (VKAPI_PTR *PFN_vkRegisterBufferColorBufferGOOGLE)(VkDevice device, VkBuffer image, uint32_t colorBuffer);
 
+#define VK_GOOGLE_address_space_info 1
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryHostAddressInfoGOOGLE)(VkDevice device, VkDeviceMemory memory, uint64_t* pAddress, uint64_t* pSize);
+
 #define VK_ANDROID_external_memory_android_hardware_buffer 1
 struct AHardwareBuffer;
 struct VkAndroidHardwareBufferPropertiesANDROID;
diff --git a/system/vulkan_enc/goldfish_vk_transform_guest.cpp b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
index d06135e..9e7fbf5 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.cpp
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.cpp
@@ -8947,6 +8947,8 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#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 217284e..6511666 100644
--- a/system/vulkan_enc/goldfish_vk_transform_guest.h
+++ b/system/vulkan_enc/goldfish_vk_transform_guest.h
@@ -3069,5 +3069,7 @@
 #endif
 #ifdef VK_GOOGLE_create_resources_with_requirements
 #endif
+#ifdef VK_GOOGLE_address_space_info
+#endif
 
 } // namespace goldfish_vk