vulkan: always tear down host visible memory blocks properly

in reverse order of how they were set up.

This is accomplished by introducing a new api, vkFreeMemorySyncGOOGLE,
that waits for the host to be done first before returning to the guest,
so that the gpa range is guaranteed to be torn down by the guest
afterwards not before.

Test: Chrome Fuchsia cc_unittests don't flake
Change-Id: Ica42e6197ba34e87cc9e3c2109f0e03cbb7517d9
diff --git a/registry/vulkan/xml/cereal/common/vulkantypes.py b/registry/vulkan/xml/cereal/common/vulkantypes.py
index e13d5b3..ffa3b44 100644
--- a/registry/vulkan/xml/cereal/common/vulkantypes.py
+++ b/registry/vulkan/xml/cereal/common/vulkantypes.py
@@ -112,7 +112,7 @@
         if h == "VkDeviceMemory":
             HANDLE_INFO[h] = \
                 HandleInfo("VkDeviceMemory",
-                           "vkAllocateMemory", "vkFreeMemory")
+                           "vkAllocateMemory", ["vkFreeMemory", "vkFreeMemorySyncGOOGLE"])
         if h == "VkDescriptorSet":
             HANDLE_INFO[h] = \
                 HandleInfo("VkDescriptorSet", "vkAllocateDescriptorSets",
diff --git a/registry/vulkan/xml/cereal/decoder.py b/registry/vulkan/xml/cereal/decoder.py
index a0613cc..071e440 100644
--- a/registry/vulkan/xml/cereal/decoder.py
+++ b/registry/vulkan/xml/cereal/decoder.py
@@ -509,6 +509,9 @@
     "vkImportSemaphoreFdKHR" : emit_global_state_wrapped_decoding,
     "vkDestroySemaphore" : emit_global_state_wrapped_decoding,
 
+    # VK_GOOGLE_free_memory_sync
+    "vkFreeMemorySyncGOOGLE" : emit_global_state_wrapped_decoding,
+
     # VK_GOOGLE_address_space
     "vkMapMemoryIntoAddressSpaceGOOGLE" : emit_global_state_wrapped_decoding,
     "vkGetMemoryHostAddressInfoGOOGLE" : emit_global_state_wrapped_decoding,
diff --git a/registry/vulkan/xml/vk.xml b/registry/vulkan/xml/vk.xml
index ec78661..89bd7c2 100644
--- a/registry/vulkan/xml/vk.xml
+++ b/registry/vulkan/xml/vk.xml
@@ -6372,6 +6372,12 @@
             <param optional="false,true"><type>uint64_t</type>* <name>pSize</name></param>
             <param optional="false,true"><type>uint64_t</type>* <name>pHostmemId</name></param>
         </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkFreeMemorySyncGOOGLE</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param optional="true" externsync="true" devicememoryhandle="1"><type>VkDeviceMemory</type> <name>memory</name></param>
+            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+        </command>
     </commands>
 
     <feature api="vulkan" name="VK_VERSION_1_0" number="1.0" comment="Vulkan core API interface definitions">
@@ -9237,5 +9243,13 @@
                 <command name="vkGetMemoryHostAddressInfoGOOGLE"/>
             </require>
         </extension>
+        <extension name="VK_GOOGLE_free_memory_sync" number="224" author="GOOGLE" contact="Lingfeng Yang @frank" supported="vulkan">
+            <require>
+                <enum value="0"                                             name="VK_GOOGLE_FREE_MEMORY_SYNC_SPEC_VERSION"/>
+                <enum value="224"                                           name="VK_GOOGLE_FREE_MEMORY_SYNC_NUMBER"/>
+                <enum value="&quot;VK_GOOGLE_free_memory_sync&quot;"           name="VK_GOOGLE_FREE_MEMORY_SYNC_EXTENSION_NAME"/>
+                <command name="vkFreeMemorySyncGOOGLE"/>
+            </require>
+        </extension>
     </extensions>
 </registry>