[vulkan] Suballocate host visible memory

bug: 111137294
bug: 121420031

Change-Id: Ied783769ac1a35ed16dfb60e44857daf22d17233
diff --git a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
index 88fbc6e..c1495fb 100644
--- a/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
+++ b/system/vulkan_enc/HostVisibleMemoryVirtualization.cpp
@@ -14,10 +14,17 @@
 // limitations under the License.
 #include "HostVisibleMemoryVirtualization.h"
 
+#include "android/base/SubAllocator.h"
+
+#include "Resources.h"
+#include "VkEncoder.h"
+
 #include <log/log.h>
 
 #include <set>
 
+using android::base::SubAllocator;
+
 namespace goldfish_vk {
 
 bool canFitVirtualHostVisibleMemoryInfo(
@@ -40,21 +47,7 @@
     }
 
     uint32_t numFreeMemoryTypes = VK_MAX_MEMORY_TYPES - typeCount;
-    uint32_t numFreeMemoryHeaps = VK_MAX_MEMORY_HEAPS - heapCount;
-
     uint32_t hostVisibleMemoryTypeCount = 0;
-    uint32_t hostVisibleMemoryHeapCount = 0;
-    std::set<uint32_t> hostVisibleMemoryHeaps;
-
-    for (uint32_t i = 0; i < typeCount; ++i) {
-        const auto& type = memoryProperties->memoryTypes[i];
-        if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
-            ++hostVisibleMemoryTypeCount;
-            hostVisibleMemoryHeaps.insert(type.heapIndex);
-        }
-    }
-    hostVisibleMemoryHeapCount =
-        (uint32_t)hostVisibleMemoryHeaps.size();
 
     if (hostVisibleMemoryTypeCount > numFreeMemoryTypes) {
         ALOGE("Underlying device has too many host visible memory types (%u)"
@@ -63,13 +56,6 @@
         canFit = false;
     }
 
-    if (hostVisibleMemoryHeapCount > numFreeMemoryHeaps) {
-        ALOGE("Underlying device has too many host visible memory types (%u)"
-              "and not enough free types (%u)",
-              hostVisibleMemoryHeapCount, numFreeMemoryHeaps);
-        canFit = false;
-    }
-
     return canFit;
 }
 
@@ -161,7 +147,7 @@
                 ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
 
             // TODO: Figure out how to support bigger sizes
-            newVirtualMemoryHeap.size = 512ULL * 1048576ULL; // 512 MB
+            newVirtualMemoryHeap.size = VIRTUAL_HOST_VISIBLE_HEAP_SIZE;
 
             info_out->memoryTypeIndexMappingToHost[firstFreeTypeIndex] = i;
             info_out->memoryHeapIndexMappingToHost[firstFreeHeapIndex] = i;
@@ -175,12 +161,14 @@
                 type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
 
             ++firstFreeTypeIndex;
-            ++firstFreeHeapIndex;
+
+            // Explicitly only create one new heap.
+            // ++firstFreeHeapIndex;
         }
     }
 
     info_out->guestMemoryProperties.memoryTypeCount = firstFreeTypeIndex;
-    info_out->guestMemoryProperties.memoryHeapCount = firstFreeHeapIndex;
+    info_out->guestMemoryProperties.memoryHeapCount = firstFreeHeapIndex + 1;
 
     for (uint32_t i = info_out->guestMemoryProperties.memoryTypeCount; i < VK_MAX_MEMORY_TYPES; ++i) {
         memset(&info_out->guestMemoryProperties.memoryTypes[i],
@@ -188,4 +176,81 @@
     }
 }
 
+bool isHostVisibleMemoryTypeIndexForGuest(
+    const HostVisibleMemoryVirtualizationInfo* info,
+    uint32_t index) {
+    return info->guestMemoryProperties.memoryTypes[index].propertyFlags &
+           VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+}
+
+VkResult finishHostMemAllocInit(
+    VkEncoder* enc,
+    VkDevice device,
+    uint32_t memoryTypeIndex,
+    VkDeviceSize nonCoherentAtomSize,
+    VkDeviceSize allocSize,
+    VkDeviceSize mappedSize,
+    uint8_t* mappedPtr,
+    HostMemAlloc* out) {
+
+    out->enc = enc;
+    out->device = device;
+    out->memoryTypeIndex = memoryTypeIndex;
+    out->nonCoherentAtomSize = nonCoherentAtomSize;
+    out->allocSize = allocSize;
+    out->mappedSize = mappedSize;
+    out->mappedPtr = mappedPtr;
+
+    out->subAlloc = new
+        SubAllocator(
+            out->mappedPtr,
+            out->mappedSize,
+            out->nonCoherentAtomSize);
+
+    out->initialized = true;
+    out->initResult = VK_SUCCESS;
+    return VK_SUCCESS;
+}
+
+void destroyHostMemAlloc(
+    VkDevice device,
+    HostMemAlloc* toDestroy) {
+
+    if (toDestroy->initResult != VK_SUCCESS) return;
+    if (!toDestroy->initialized) return;
+
+    toDestroy->enc->vkFreeMemory(device, toDestroy->memory, nullptr);
+    delete toDestroy->subAlloc;
+}
+
+void subAllocHostMemory(
+    HostMemAlloc* alloc,
+    const VkMemoryAllocateInfo* pAllocateInfo,
+    SubAlloc* out) {
+
+    VkDeviceSize mappedSize =
+        alloc->nonCoherentAtomSize * (
+            (pAllocateInfo->allocationSize +
+             alloc->nonCoherentAtomSize - 1) /
+            alloc->nonCoherentAtomSize);
+
+    void* subMapped = alloc->subAlloc->alloc(mappedSize);
+    out->mappedPtr = (uint8_t*)subMapped;
+
+    out->subAllocSize = pAllocateInfo->allocationSize;
+    out->subMappedSize = mappedSize;
+
+    out->baseMemory = alloc->memory;
+    out->baseOffset = alloc->subAlloc->getOffset(subMapped);
+
+    out->subMemory = new_from_host_VkDeviceMemory(VK_NULL_HANDLE);
+    out->subAlloc = alloc->subAlloc;
+}
+
+void subFreeHostMemory(SubAlloc* toFree) {
+    delete_goldfish_VkDeviceMemory(toFree->subMemory);
+    toFree->subAlloc->free(toFree->mappedPtr);
+    memset(toFree, 0x0, sizeof(SubAlloc));
+}
+
 } // namespace goldfish_vk