[vulkan] Allow custom logic in guest to access encoder/resourcetracker

bug: 120118806

+ do not alloc in guest if memory is not host visible.
+ extend host-visible allocs to be multiple of nonCoherentAtomSize if
necessary.

Change-Id: I4030d3f120627a18c7bc62da31e6db46a0544d9b
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index d827289..4def37d 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -17,6 +17,13 @@
 
 #include "Resources.h"
 
+#include "android/base/synchronization/AndroidLock.h"
+
+#include <unordered_map>
+
+using android::base::guest::AutoLock;
+using android::base::guest::Lock;
+
 namespace goldfish_vk {
 
 #define MAKE_HANDLE_MAPPING_FOREACH(type_name, map_impl, map_to_u64_impl, map_from_u64_impl) \
@@ -45,9 +52,9 @@
 
 #define CREATE_MAPPING_IMPL_FOR_TYPE(type_name) \
     MAKE_HANDLE_MAPPING_FOREACH(type_name, \
-        handles[i] = new_from_host_##type_name(handles[i]), \
+        handles[i] = new_from_host_##type_name(handles[i]); ResourceTracker::get()->register_##type_name(handles[i]);, \
         handle_u64s[i] = (uint64_t)(uintptr_t)new_from_host_##type_name(handles[i]), \
-        handles[i] = (type_name)(uintptr_t)new_from_host_u64_##type_name(handle_u64s[i]))
+        handles[i] = (type_name)(uintptr_t)new_from_host_u64_##type_name(handle_u64s[i]); ResourceTracker::get()->register_##type_name(handles[i]);)
 
 #define UNWRAP_MAPPING_IMPL_FOR_TYPE(type_name) \
     MAKE_HANDLE_MAPPING_FOREACH(type_name, \
@@ -57,7 +64,7 @@
 
 #define DESTROY_MAPPING_IMPL_FOR_TYPE(type_name) \
     MAKE_HANDLE_MAPPING_FOREACH(type_name, \
-        delete_goldfish_##type_name(handles[i]), \
+        ResourceTracker::get()->unregister_##type_name(handles[i]); delete_goldfish_##type_name(handles[i]), \
         (void)handle_u64s[i]; delete_goldfish_##type_name(handles[i]), \
         (void)handles[i]; delete_goldfish_##type_name((type_name)(uintptr_t)handle_u64s[i]))
 
@@ -72,6 +79,76 @@
     UnwrapMapping unwrapMapping;
     DestroyMapping destroyMapping;
     DefaultHandleMapping defaultMapping;
+
+#define HANDLE_DEFINE_TRIVIAL_INFO_STRUCT(type) \
+    struct type##_Info { \
+        uint32_t unused; \
+    }; \
+
+    GOLDFISH_VK_LIST_TRIVIAL_HANDLE_TYPES(HANDLE_DEFINE_TRIVIAL_INFO_STRUCT)
+
+    struct VkDevice_Info {
+        VkPhysicalDevice physdev;
+        VkPhysicalDeviceProperties props;
+        VkPhysicalDeviceMemoryProperties memProps;
+    };
+
+    struct VkDeviceMemory_Info {
+        VkDeviceSize allocationSize;
+        uint32_t memoryTypeIndex;
+    };
+
+#define HANDLE_REGISTER_IMPL_IMPL(type) \
+    std::unordered_map<type, type##_Info> info_##type; \
+    void register_##type(type obj) { \
+        AutoLock lock(mLock); \
+        info_##type[obj] = type##_Info(); \
+    } \
+    void unregister_##type(type obj) { \
+        AutoLock lock(mLock); \
+        info_##type.erase(obj); \
+    } \
+
+    GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL_IMPL)
+
+    void setDeviceInfo(VkDevice device,
+                       VkPhysicalDevice physdev,
+                       VkPhysicalDeviceProperties props,
+                       VkPhysicalDeviceMemoryProperties memProps) {
+        AutoLock lock(mLock);
+        auto& info = info_VkDevice[device];
+        info.physdev = physdev;
+        info.props = props;
+        info.memProps = memProps;
+    }
+
+    bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const {
+        AutoLock lock(mLock);
+        const auto it = info_VkDevice.find(device);
+
+        if (it == info_VkDevice.end()) return false;
+
+        const auto& info = it->second;
+        return info.memProps.memoryTypes[typeIndex].propertyFlags & 
+               VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+    }
+
+    VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const {
+        AutoLock lock(mLock);
+        const auto it = info_VkDevice.find(device);
+        if (it == info_VkDevice.end()) return basicSize;
+        const auto& info = it->second;
+
+        VkDeviceSize nonCoherentAtomSize =
+            info.props.limits.nonCoherentAtomSize;
+        VkDeviceSize atoms =
+            (basicSize + nonCoherentAtomSize - 1) / nonCoherentAtomSize;
+        return atoms * nonCoherentAtomSize;
+    }
+
+private:
+    mutable Lock mLock;
+
 };
 ResourceTracker::ResourceTracker() : mImpl(new ResourceTracker::Impl()) { }
 ResourceTracker::~ResourceTracker() { }
@@ -97,4 +174,31 @@
     return sTracker;
 }
 
+#define HANDLE_REGISTER_IMPL(type) \
+    void ResourceTracker::register_##type(type obj) { \
+        mImpl->register_##type(obj); \
+    } \
+    void ResourceTracker::unregister_##type(type obj) { \
+        mImpl->unregister_##type(obj); \
+    } \
+
+GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_IMPL)
+
+void ResourceTracker::setDeviceInfo(
+    VkDevice device,
+    VkPhysicalDevice physdev,
+    VkPhysicalDeviceProperties props,
+    VkPhysicalDeviceMemoryProperties memProps) {
+    mImpl->setDeviceInfo(device, physdev, props, memProps);
+}
+
+bool ResourceTracker::isMemoryTypeHostVisible(
+    VkDevice device, uint32_t typeIndex) const {
+    return mImpl->isMemoryTypeHostVisible(device, typeIndex);
+}
+
+VkDeviceSize ResourceTracker::getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const {
+    return mImpl->getNonCoherentExtendedSize(device, basicSize);
+}
+
 } // namespace goldfish_vk
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index ed061f3..07dd421 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -17,6 +17,7 @@
 #include <vulkan/vulkan.h>
 
 #include "VulkanHandleMapping.h"
+#include "VulkanHandles.h"
 #include <memory>
 
 namespace goldfish_vk {
@@ -30,7 +31,18 @@
     VulkanHandleMapping* unwrapMapping();
     VulkanHandleMapping* destroyMapping();
     VulkanHandleMapping* defaultMapping();
-private:
+
+#define HANDLE_REGISTER_DECL(type) \
+    void register_##type(type); \
+    void unregister_##type(type); \
+
+    GOLDFISH_VK_LIST_HANDLE_TYPES(HANDLE_REGISTER_DECL)
+
+    void setDeviceInfo(VkDevice device, VkPhysicalDevice physdev, VkPhysicalDeviceProperties props, VkPhysicalDeviceMemoryProperties memProps);
+    bool isMemoryTypeHostVisible(VkDevice device, uint32_t typeIndex) const;
+    VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const;
+
+  private:
     class Impl;
     std::unique_ptr<Impl> mImpl;
 };
diff --git a/system/vulkan_enc/Resources.cpp b/system/vulkan_enc/Resources.cpp
index ab5c7b7..2b8f890 100644
--- a/system/vulkan_enc/Resources.cpp
+++ b/system/vulkan_enc/Resources.cpp
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 #include "Resources.h"
+#include "ResourceTracker.h"
+#include "VkEncoder.h"
 
 #include "android/base/AlignedBuf.h"
 
@@ -29,6 +31,8 @@
 #define D(fmt,...)
 #endif
 
+using goldfish_vk::ResourceTracker;
+
 extern "C" {
 
 #define GOLDFISH_VK_NEW_DISPATCHABLE_FROM_HOST_IMPL(type) \
@@ -125,7 +129,10 @@
 
 // Custom definitions///////////////////////////////////////////////////////////
 
-VkResult goldfish_vkEnumerateInstanceVersion(uint32_t* apiVersion) {
+VkResult goldfish_vkEnumerateInstanceVersion(
+    void*,
+    VkResult,
+    uint32_t* apiVersion) {
     if (apiVersion) {
         *apiVersion = VK_MAKE_VERSION(1, 0, 0);
     }
@@ -133,6 +140,8 @@
 }
 
 VkResult goldfish_vkEnumerateDeviceExtensionProperties(
+    void*,
+    VkResult,
     VkPhysicalDevice, const char*,
     uint32_t *pPropertyCount, VkExtensionProperties *) {
     *pPropertyCount = 0;
@@ -140,12 +149,35 @@
 }
 
 void goldfish_vkGetPhysicalDeviceProperties2(
+    void*,
     VkPhysicalDevice,
     VkPhysicalDeviceProperties2*)
 {
     // no-op
 }
 
+VkResult goldfish_vkCreateDevice(
+    void* opaque,
+    VkResult host_return,
+    VkPhysicalDevice physicalDevice,
+    const VkDeviceCreateInfo*,
+    const VkAllocationCallbacks*,
+    VkDevice* pDevice) {
+
+    if (host_return != VK_SUCCESS) return host_return;
+
+    VkEncoder* enc = (VkEncoder*)opaque;
+
+    VkPhysicalDeviceProperties props;
+    VkPhysicalDeviceMemoryProperties memProps;
+    enc->vkGetPhysicalDeviceProperties(physicalDevice, &props);
+    enc->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps);
+
+    ResourceTracker::get()->setDeviceInfo(*pDevice, physicalDevice, props, memProps);
+
+    return host_return;
+}
+
 VkDeviceMemory new_from_host_VkDeviceMemory(VkDeviceMemory mem) {
     struct goldfish_VkDeviceMemory *res =
         (struct goldfish_VkDeviceMemory *)malloc(sizeof(goldfish_VkDeviceMemory));
@@ -193,38 +225,55 @@
 }
 
 VkResult goldfish_vkAllocateMemory(
-    VkDevice,
+    void*,
+    VkResult host_return,
+    VkDevice device,
     const VkMemoryAllocateInfo* pAllocateInfo,
     const VkAllocationCallbacks*,
     VkDeviceMemory* pMemory) {
+    
+    if (host_return != VK_SUCCESS) return host_return;
 
     // Assumes pMemory has already been allocated.
     goldfish_VkDeviceMemory* mem = as_goldfish_VkDeviceMemory(*pMemory);
-
     VkDeviceSize size = pAllocateInfo->allocationSize;
 
+    // assume memory is not host visible.
+    mem->ptr = nullptr;
+    mem->size = size;
+    mem->mappedSize = ResourceTracker::get()->getNonCoherentExtendedSize(device, size);
+
+    if (!ResourceTracker::get()->isMemoryTypeHostVisible(device, pAllocateInfo->memoryTypeIndex)) {
+        return host_return;
+    }
+
     // This is a strict alignment; we do not expect any
     // actual device to have more stringent requirements
     // than this.
-    mem->ptr = (uint8_t*)aligned_buf_alloc(4096, size);
-    mem->size = size;
+    mem->ptr = (uint8_t*)aligned_buf_alloc(4096, mem->mappedSize);
+    D("host visible alloc: size 0x%llx host ptr %p mapped size 0x%llx",
+      (unsigned long long)size, mem->ptr,
+      (unsigned long long)mem->mappedSize);
 
-    return VK_SUCCESS;
+    return host_return;
 }
 
 VkResult goldfish_vkMapMemory(
+    void*,
+    VkResult host_result,
     VkDevice,
     VkDeviceMemory memory,
     VkDeviceSize offset,
     VkDeviceSize size,
     VkMemoryMapFlags,
     void** ppData) {
+    
+    if (host_result != VK_SUCCESS) return host_result;
 
     goldfish_VkDeviceMemory* mem = as_goldfish_VkDeviceMemory(memory);
 
     if (!mem->ptr) {
-        ALOGE("%s: Did not allocate host pointer for device memory!", __func__);
-        abort();
+        return VK_ERROR_MEMORY_MAP_FAILED;
     }
 
     if (size != VK_WHOLE_SIZE &&
@@ -234,10 +283,11 @@
 
     *ppData = mem->ptr + offset;
 
-    return VK_SUCCESS;
+    return host_result;
 }
 
 void goldfish_vkUnmapMemory(
+    void*,
     VkDevice,
     VkDeviceMemory) {
     // no-op
diff --git a/system/vulkan_enc/Resources.h b/system/vulkan_enc/Resources.h
index 30299f9..8928d73 100644
--- a/system/vulkan_enc/Resources.h
+++ b/system/vulkan_enc/Resources.h
@@ -75,29 +75,48 @@
 
 // Custom definitions///////////////////////////////////////////////////////////
 
-VkResult goldfish_vkEnumerateInstanceVersion(uint32_t* apiVersion);
+VkResult goldfish_vkEnumerateInstanceVersion(
+    void* opaque,
+    VkResult host_return,
+    uint32_t* apiVersion);
 
 VkResult goldfish_vkEnumerateDeviceExtensionProperties(
+    void* opaque,
+    VkResult host_return,
     VkPhysicalDevice physicalDevice, const char *pLayerName,
     uint32_t *pPropertyCount, VkExtensionProperties *pProperties);
 
 void goldfish_vkGetPhysicalDeviceProperties2(
+    void* opaque,
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceProperties2* pProperties);
 
+VkResult goldfish_vkCreateDevice(
+    void* opaque,
+    VkResult host_return,
+    VkPhysicalDevice physicalDevice,
+    const VkDeviceCreateInfo* pCreateInfo,
+    const VkAllocationCallbacks* pAllocator,
+    VkDevice* pDevice);
+
 struct goldfish_VkDeviceMemory {
     uint64_t underlying;
     uint8_t* ptr;
     VkDeviceSize size;
+    VkDeviceSize mappedSize;
 };
 
 VkResult goldfish_vkAllocateMemory(
+    void* opaque,
+    VkResult host_return,
     VkDevice device,
     const VkMemoryAllocateInfo* pAllocateInfo,
     const VkAllocationCallbacks* pAllocator,
     VkDeviceMemory* pMemory);
 
 VkResult goldfish_vkMapMemory(
+    void* opaque,
+    VkResult host_return,
     VkDevice device,
     VkDeviceMemory memory,
     VkDeviceSize offset,
@@ -106,7 +125,7 @@
     void** ppData);
 
 void goldfish_vkUnmapMemory(
+    void* opaque,
     VkDevice device,
     VkDeviceMemory memory);
-
 } // extern "C"
diff --git a/system/vulkan_enc/VkEncoder.cpp b/system/vulkan_enc/VkEncoder.cpp
index cb51ac9..f51744c 100644
--- a/system/vulkan_enc/VkEncoder.cpp
+++ b/system/vulkan_enc/VkEncoder.cpp
@@ -721,6 +721,7 @@
     countingStream->clearPool();
     stream->clearPool();
     pool->freeAll();
+    goldfish_vkCreateDevice(this, vkCreateDevice_VkResult_return, physicalDevice, pCreateInfo, pAllocator, pDevice);
     return vkCreateDevice_VkResult_return;
 }
 
@@ -874,7 +875,7 @@
     VkExtensionProperties* pProperties)
 {
     VkResult vkEnumerateDeviceExtensionProperties_VkResult_return = (VkResult)0;
-    vkEnumerateDeviceExtensionProperties_VkResult_return = goldfish_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+    vkEnumerateDeviceExtensionProperties_VkResult_return = goldfish_vkEnumerateDeviceExtensionProperties(this, vkEnumerateDeviceExtensionProperties_VkResult_return, physicalDevice, pLayerName, pPropertyCount, pProperties);
     return vkEnumerateDeviceExtensionProperties_VkResult_return;
 }
 
@@ -1305,12 +1306,12 @@
     stream->read((uint64_t*)&cgen_var_92, 8);
     stream->handleMapping()->mapHandles_u64_VkDeviceMemory(&cgen_var_92, (VkDeviceMemory*)pMemory, 1);
     stream->unsetHandleMapping();
-    goldfish_vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
     VkResult vkAllocateMemory_VkResult_return = (VkResult)0;
     stream->read(&vkAllocateMemory_VkResult_return, sizeof(VkResult));
     countingStream->clearPool();
     stream->clearPool();
     pool->freeAll();
+    goldfish_vkAllocateMemory(this, vkAllocateMemory_VkResult_return, device, pAllocateInfo, pAllocator, pMemory);
     return vkAllocateMemory_VkResult_return;
 }
 
@@ -1382,7 +1383,7 @@
     void** ppData)
 {
     VkResult vkMapMemory_VkResult_return = (VkResult)0;
-    vkMapMemory_VkResult_return = goldfish_vkMapMemory(device, memory, offset, size, flags, ppData);
+    vkMapMemory_VkResult_return = goldfish_vkMapMemory(this, vkMapMemory_VkResult_return, device, memory, offset, size, flags, ppData);
     return vkMapMemory_VkResult_return;
 }
 
@@ -1390,7 +1391,7 @@
     VkDevice device,
     VkDeviceMemory memory)
 {
-    goldfish_vkUnmapMemory(device, memory);
+    goldfish_vkUnmapMemory(this, device, memory);
 }
 
 VkResult VkEncoder::vkFlushMappedMemoryRanges(
@@ -5033,15 +5034,15 @@
             stream->write((uint64_t*)cgen_var_424, ((descriptorSetCount)) * 8);
         }
     }
-    if (pDescriptorSets)
-    {
-        resources->destroyMapping()->mapHandles_VkDescriptorSet((VkDescriptorSet*)pDescriptorSets, ((descriptorSetCount)));
-    }
     VkResult vkFreeDescriptorSets_VkResult_return = (VkResult)0;
     stream->read(&vkFreeDescriptorSets_VkResult_return, sizeof(VkResult));
     countingStream->clearPool();
     stream->clearPool();
     pool->freeAll();
+    if (pDescriptorSets)
+    {
+        resources->destroyMapping()->mapHandles_VkDescriptorSet((VkDescriptorSet*)pDescriptorSets, ((descriptorSetCount)));
+    }
     return vkFreeDescriptorSets_VkResult_return;
 }
 
@@ -8310,7 +8311,7 @@
     uint32_t* pApiVersion)
 {
     VkResult vkEnumerateInstanceVersion_VkResult_return = (VkResult)0;
-    vkEnumerateInstanceVersion_VkResult_return = goldfish_vkEnumerateInstanceVersion(pApiVersion);
+    vkEnumerateInstanceVersion_VkResult_return = goldfish_vkEnumerateInstanceVersion(this, vkEnumerateInstanceVersion_VkResult_return, pApiVersion);
     return vkEnumerateInstanceVersion_VkResult_return;
 }
 
@@ -8862,7 +8863,7 @@
     VkPhysicalDevice physicalDevice,
     VkPhysicalDeviceProperties2* pProperties)
 {
-    goldfish_vkGetPhysicalDeviceProperties2(physicalDevice, pProperties);
+    goldfish_vkGetPhysicalDeviceProperties2(this, physicalDevice, pProperties);
 }
 
 void VkEncoder::vkGetPhysicalDeviceFormatProperties2(
diff --git a/system/vulkan_enc/VulkanHandles.h b/system/vulkan_enc/VulkanHandles.h
index 498fae2..af130eb 100644
--- a/system/vulkan_enc/VulkanHandles.h
+++ b/system/vulkan_enc/VulkanHandles.h
@@ -16,13 +16,16 @@
 
 #include <vulkan/vulkan.h>
 
-#define GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
+#define GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkInstance) \
     f(VkPhysicalDevice) \
-    f(VkDevice) \
     f(VkQueue) \
     f(VkCommandBuffer) \
 
+#define GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
+    f(VkDevice) \
+    GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f)
+
 #define GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f) \
     f(VkBuffer) \
     f(VkBufferView) \
@@ -62,3 +65,7 @@
 #define GOLDFISH_VK_LIST_HANDLE_TYPES(f) \
     GOLDFISH_VK_LIST_DISPATCHABLE_HANDLE_TYPES(f) \
     GOLDFISH_VK_LIST_NON_DISPATCHABLE_HANDLE_TYPES(f)
+
+#define GOLDFISH_VK_LIST_TRIVIAL_HANDLE_TYPES(f) \
+    GOLDFISH_VK_LIST_TRIVIAL_DISPATCHABLE_HANDLE_TYPES(f) \
+    GOLDFISH_VK_LIST_TRIVIAL_NON_DISPATCHABLE_HANDLE_TYPES(f)