Merge changes Ic7af82de,I461327ce into main

* changes:
  Add VkFence snapshot
  Add guest ANGLE to allowlist for vulkan snapshot
diff --git a/guest/platform/kumquat/VirtGpuKumquat.h b/guest/platform/kumquat/VirtGpuKumquat.h
index d940ffd..d22f210 100644
--- a/guest/platform/kumquat/VirtGpuKumquat.h
+++ b/guest/platform/kumquat/VirtGpuKumquat.h
@@ -17,7 +17,13 @@
 #pragma once
 
 #include "VirtGpu.h"
+
+// Blueprint and Meson builds place things differently
+#if defined(ANDROID)
+#include "virtgpu_kumquat_ffi.h"
+#else
 #include "virtgpu_kumquat/virtgpu_kumquat_ffi.h"
+#endif
 
 class VirtGpuKumquatResource : public std::enable_shared_from_this<VirtGpuKumquatResource>,
                                public VirtGpuResource {
diff --git a/guest/platform/kumquat/VirtGpuKumquatBlob.cpp b/guest/platform/kumquat/VirtGpuKumquatBlob.cpp
index cd0e3e0..991d53d 100644
--- a/guest/platform/kumquat/VirtGpuKumquatBlob.cpp
+++ b/guest/platform/kumquat/VirtGpuKumquatBlob.cpp
@@ -23,7 +23,6 @@
 #include <cstring>
 
 #include "VirtGpuKumquat.h"
-#include "virtgpu_kumquat/virtgpu_kumquat_ffi.h"
 
 VirtGpuKumquatResource::VirtGpuKumquatResource(struct virtgpu_kumquat* virtGpu, uint32_t blobHandle,
                                                uint32_t resourceHandle, uint64_t size)
@@ -53,7 +52,8 @@
 
     ret = virtgpu_kumquat_resource_map(mVirtGpu, &map);
     if (ret < 0) {
-        ALOGE("Mapping failed with %s", strerror(errno));
+        ALOGE("Mapping failed with %s for resource %u blob %u", strerror(errno), mResourceHandle,
+              mBlobHandle);
         return nullptr;
     }
 
diff --git a/guest/platform/kumquat/VirtGpuKumquatDevice.cpp b/guest/platform/kumquat/VirtGpuKumquatDevice.cpp
index 6101cc1..774c9dc 100644
--- a/guest/platform/kumquat/VirtGpuKumquatDevice.cpp
+++ b/guest/platform/kumquat/VirtGpuKumquatDevice.cpp
@@ -26,15 +26,13 @@
 
 #include "VirtGpuKumquat.h"
 #include "virtgpu_gfxstream_protocol.h"
-#include "virtgpu_kumquat/virtgpu_kumquat_ffi.h"
 
 #define PARAM(x) \
     (struct VirtGpuParam) { x, #x, 0 }
 
 static inline uint32_t align_up(uint32_t n, uint32_t a) { return ((n + a - 1) / a) * a; }
 
-VirtGpuKumquatDevice::VirtGpuKumquatDevice(enum VirtGpuCapset capset, int fd)
-    : VirtGpuDevice(capset) {
+VirtGpuKumquatDevice::VirtGpuKumquatDevice(enum VirtGpuCapset capset, int) : VirtGpuDevice(capset) {
     struct VirtGpuParam params[] = {
         PARAM(VIRTGPU_KUMQUAT_PARAM_3D_FEATURES),
         PARAM(VIRTGPU_KUMQUAT_PARAM_CAPSET_QUERY_FIX),
@@ -60,7 +58,7 @@
     processName = getprogname();
 #endif
 
-    ret = virtgpu_kumquat_init(&mVirtGpu);
+    ret = virtgpu_kumquat_init(&mVirtGpu, nullptr);
     if (ret) {
         ALOGV("Failed to init virtgpu kumquat");
         return;
diff --git a/guest/platform/kumquat/VirtGpuKumquatSync.cpp b/guest/platform/kumquat/VirtGpuKumquatSync.cpp
index d152bff..47884fc 100644
--- a/guest/platform/kumquat/VirtGpuKumquatSync.cpp
+++ b/guest/platform/kumquat/VirtGpuKumquatSync.cpp
@@ -23,9 +23,24 @@
 VirtGpuKumquatSyncHelper::VirtGpuKumquatSyncHelper() {}
 
 int VirtGpuKumquatSyncHelper::wait(int syncFd, int timeoutMilliseconds) {
-    (void)syncFd;
     (void)timeoutMilliseconds;
-    return -1;
+    // So far, syncfds are EventFd in the Kumquat layer. This may change
+    uint64_t count = 1;
+    ssize_t bytes_read = read(syncFd, &count, sizeof(count));
+
+    if (bytes_read < 0) {
+        return bytes_read;
+    }
+
+    // A successful read decrements the eventfd's counter to zero.  In
+    // case the eventfd is waited on again, or a dup is waited on, we
+    // have to write to the eventfd for the next read.
+    ssize_t bytes_written = write(syncFd, &count, sizeof(count));
+    if (bytes_written < 0) {
+        return bytes_written;
+    }
+
+    return 0;
 }
 
 int VirtGpuKumquatSyncHelper::dup(int syncFd) { return ::dup(syncFd); }
diff --git a/host/ColorBuffer.cpp b/host/ColorBuffer.cpp
index 92414e7..2b68fbf 100644
--- a/host/ColorBuffer.cpp
+++ b/host/ColorBuffer.cpp
@@ -226,7 +226,6 @@
     if (mColorBufferGl) {
         mColorBufferGl->subUpdateFromFrameworkFormat(x, y, width, height, frameworkFormat,
                                                      pixelsFormat, pixelsType, pixels, metadata);
-        return true;
     }
 #endif
 
@@ -234,8 +233,7 @@
         return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
     }
 
-    GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "No ColorBuffer impl?";
-    return false;
+    return true;
 }
 
 bool ColorBuffer::updateFromBytes(int x, int y, int width, int height, GLenum pixelsFormat,
diff --git a/host/vulkan/VkCommonOperations.cpp b/host/vulkan/VkCommonOperations.cpp
index 21b1ff7..529dd1b 100644
--- a/host/vulkan/VkCommonOperations.cpp
+++ b/host/vulkan/VkCommonOperations.cpp
@@ -826,16 +826,20 @@
             deviceInfos[i].supportsDriverProperties =
                 extensionsSupported(deviceExts, {VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME}) ||
                 (deviceInfos[i].physdevProps.apiVersion >= VK_API_VERSION_1_2);
+            deviceInfos[i].supportsExternalMemoryHostProps = extensionsSupported(deviceExts, {VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME});
 
             if (!sVkEmulation->getPhysicalDeviceProperties2Func) {
                 ERR("Warning: device claims to support ID properties "
                     "but vkGetPhysicalDeviceProperties2 could not be found");
             }
         }
-
         if (sVkEmulation->getPhysicalDeviceProperties2Func) {
+            VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProps = {
+                .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,
+            };
             VkPhysicalDeviceProperties2 deviceProps = {
-                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
+                .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
+
             };
             VkPhysicalDeviceIDProperties idProps = {
                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR,
@@ -854,9 +858,12 @@
                 vk_append_struct(&devicePropsChain, &driverProps);
             }
 
+            if(deviceInfos[i].supportsExternalMemoryHostProps) {
+                vk_append_struct(&devicePropsChain, &externalMemoryHostProps);
+            }
             sVkEmulation->getPhysicalDeviceProperties2Func(physdevs[i], &deviceProps);
-
             deviceInfos[i].idProps = vk_make_orphan_copy(idProps);
+            deviceInfos[i].externalMemoryHostProps = vk_make_orphan_copy(externalMemoryHostProps);
 
             std::stringstream driverVendorBuilder;
             driverVendorBuilder << "Vendor " << std::hex << std::setfill('0') << std::showbase
@@ -990,7 +997,6 @@
     // in use cases that make sense, if/when they come up.
 
     std::vector<uint32_t> deviceScores(physdevCount, 0);
-
     for (uint32_t i = 0; i < physdevCount; ++i) {
         uint32_t deviceScore = 0;
         if (deviceInfos[i].hasGraphicsQueueFamily) deviceScore += 10000;
diff --git a/host/vulkan/VkCommonOperations.h b/host/vulkan/VkCommonOperations.h
index 43ebc91..a896a2a 100644
--- a/host/vulkan/VkCommonOperations.h
+++ b/host/vulkan/VkCommonOperations.h
@@ -206,6 +206,7 @@
         bool supportsDmaBuf = false;
         bool supportsIdProperties = false;
         bool supportsDriverProperties = false;
+        bool supportsExternalMemoryHostProps = false;
         bool hasSamplerYcbcrConversionExtension = false;
         bool supportsSamplerYcbcrConversion = false;
         bool glInteropSupported = false;
@@ -220,6 +221,7 @@
         VkPhysicalDeviceProperties physdevProps;
         VkPhysicalDeviceMemoryProperties memProps;
         VkPhysicalDeviceIDPropertiesKHR idProps;
+        VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProps;
 
         std::string driverVendor;
         std::string driverVersion;
diff --git a/host/vulkan/VkDecoderGlobalState.cpp b/host/vulkan/VkDecoderGlobalState.cpp
index 5904468..81fb1e1 100644
--- a/host/vulkan/VkDecoderGlobalState.cpp
+++ b/host/vulkan/VkDecoderGlobalState.cpp
@@ -4844,10 +4844,16 @@
         VkImportMemoryHostPointerInfoEXT importHostInfoPrivate{};
         if (hostVisible && m_emu->features.VulkanAllocateHostMemory.enabled &&
             localAllocInfo.pNext == nullptr) {
-            VkDeviceSize alignedSize = __ALIGN(localAllocInfo.allocationSize, kPageSizeforBlob);
+            if (!m_emu || !m_emu->deviceInfo.supportsExternalMemoryHostProps) {
+                ERR("VK_EXT_EXTERNAL_MEMORY_HOST is not supported, cannot use "
+                    "VulkanAllocateHostMemory");
+                return VK_ERROR_INCOMPATIBLE_DRIVER;
+            }
+            VkDeviceSize alignmentSize = m_emu->deviceInfo.externalMemoryHostProps.minImportedHostPointerAlignment;
+            VkDeviceSize alignedSize = __ALIGN(localAllocInfo.allocationSize, alignmentSize);
             localAllocInfo.allocationSize = alignedSize;
             privateMemory =
-                std::make_shared<PrivateMemory>(kPageSizeforBlob, localAllocInfo.allocationSize);
+                std::make_shared<PrivateMemory>(alignmentSize, localAllocInfo.allocationSize);
             mappedPtr = privateMemory->getAddr();
             importHostInfoPrivate = {
                 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
@@ -4855,25 +4861,28 @@
                 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
                 .pHostPointer = mappedPtr};
 
-            VkMemoryHostPointerPropertiesEXT pMemoryHostPointerProperties = {
+            VkMemoryHostPointerPropertiesEXT memoryHostPointerProperties = {
                 .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT,
                 .pNext = NULL,
                 .memoryTypeBits = 0,
             };
-            vk->vkGetMemoryHostPointerPropertiesEXT(device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, mappedPtr, &pMemoryHostPointerProperties);
 
-            if (pMemoryHostPointerProperties.memoryTypeBits == 0) {
-                // Memory import operation not supported by the driver.
+            vk->vkGetMemoryHostPointerPropertiesEXT(
+                device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, mappedPtr,
+                &memoryHostPointerProperties);
+
+            if (memoryHostPointerProperties.memoryTypeBits == 0) {
+                ERR("Cannot find suitable memory type for VulkanAllocateHostMemory");
                 return VK_ERROR_INCOMPATIBLE_DRIVER;
             }
 
-            if (((1u << localAllocInfo.memoryTypeIndex) & pMemoryHostPointerProperties.memoryTypeBits) == 0) {
+            if (((1u << localAllocInfo.memoryTypeIndex) & memoryHostPointerProperties.memoryTypeBits) == 0) {
 
                 // TODO Consider assigning the correct memory index earlier, instead of switching right before allocation.
 
                 // Look for the first available supported memory index and assign it.
                 for(uint32_t i =0; i<= 31; ++i) {
-                    if ((pMemoryHostPointerProperties.memoryTypeBits & (1u << i)) == 0) {
+                    if ((memoryHostPointerProperties.memoryTypeBits & (1u << i)) == 0) {
                         continue;
                     }
                     localAllocInfo.memoryTypeIndex = i;
@@ -6861,15 +6870,13 @@
     }
 
     VkResult waitForFence(VkFence boxed_fence, uint64_t timeout) {
-        VkFence fence;
+        VkFence fence = unbox_VkFence(boxed_fence);
         VkDevice device;
         VulkanDispatch* vk;
         StaticLock* fenceLock;
         ConditionVariable* cv;
         {
             std::lock_guard<std::recursive_mutex> lock(mLock);
-
-            fence = unbox_VkFence(boxed_fence);
             if (fence == VK_NULL_HANDLE || mFenceInfo.find(fence) == mFenceInfo.end()) {
                 // No fence, could be a semaphore.
                 // TODO: Async wait for semaphores
@@ -6917,13 +6924,11 @@
     }
 
     VkResult getFenceStatus(VkFence boxed_fence) {
+        VkFence fence = unbox_VkFence(boxed_fence);
         VkDevice device;
-        VkFence fence;
         VulkanDispatch* vk;
         {
             std::lock_guard<std::recursive_mutex> lock(mLock);
-
-            fence = unbox_VkFence(boxed_fence);
             if (fence == VK_NULL_HANDLE || mFenceInfo.find(fence) == mFenceInfo.end()) {
                 // No fence, could be a semaphore.
                 // TODO: Async get status for semaphores
diff --git a/host/vulkan/VulkanDispatch.cpp b/host/vulkan/VulkanDispatch.cpp
index ea51459..9ca5211 100644
--- a/host/vulkan/VulkanDispatch.cpp
+++ b/host/vulkan/VulkanDispatch.cpp
@@ -94,7 +94,7 @@
         // 4: Log errors, warnings, infos and debug messages.
         const bool verboseLogs =
             (android::base::getEnvironmentVariable("ANDROID_EMUGL_VERBOSE") == "1");
-        const char* logLevelValue = verboseLogs ? "4" : "2";
+        const char* logLevelValue = verboseLogs ? "4" : "1";
         android::base::setEnvironmentVariable("MVK_CONFIG_LOG_LEVEL", logLevelValue);
 
         //  Limit MoltenVK to use single queue, as some older ANGLE versions
diff --git a/host/vulkan/cereal/common/vk_struct_id.h b/host/vulkan/cereal/common/vk_struct_id.h
index c526dc1..54641fc 100644
--- a/host/vulkan/cereal/common/vk_struct_id.h
+++ b/host/vulkan/cereal/common/vk_struct_id.h
@@ -99,6 +99,8 @@
                       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT)
 REGISTER_VK_STRUCT_ID(VkPhysicalDeviceProtectedMemoryFeatures,
                       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES);
+REGISTER_VK_STRUCT_ID(VkPhysicalDeviceExternalMemoryHostPropertiesEXT,
+                      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT);
 
 #if defined(VK_USE_PLATFORM_SCREEN_QNX)
 REGISTER_VK_STRUCT_ID(VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX,