vulkan/gles interop: ensure consistent selection of physdevs / interop

This should solve two potential issues:

1. Use VkPhysicalDeviceIDProperties to advertise only the physical
device we selected to the guest. If we ended up selecting a different
physical device in VkCommonOperations versus on_vkCreateDevice from the
guest, problems can happen.

2. Ensure device UUID between gles/vk match. If they don't, we can't use
interop, even if the gl side reports support for the interop extensions
(think NV gl alongside Intel vk). The gles side should have a way to
query the UUID of the device (tested with native GL and GLES on Linux
and native GL on Windows); otherwise, we can't use zero-copy interop.

Bug: 190561902

Change-Id: I6c6e217a3c09566ab4c0d47a91432c58343efc54
diff --git a/stream-servers/vulkan/VkCommonOperations.cpp b/stream-servers/vulkan/VkCommonOperations.cpp
index b0b37bf..18bda70 100644
--- a/stream-servers/vulkan/VkCommonOperations.cpp
+++ b/stream-servers/vulkan/VkCommonOperations.cpp
@@ -602,6 +602,18 @@
                 ivk->vkGetInstanceProcAddr(
                         sVkEmulation->instance,
                         "vkGetPhysicalDeviceImageFormatProperties2KHR"));
+        sVkEmulation->getPhysicalDeviceProperties2Func = reinterpret_cast<
+                PFN_vkGetPhysicalDeviceProperties2KHR>(
+                ivk->vkGetInstanceProcAddr(
+                        sVkEmulation->instance,
+                        "vkGetPhysicalDeviceProperties2KHR"));
+        if (!sVkEmulation->getPhysicalDeviceProperties2Func) {
+            sVkEmulation->getPhysicalDeviceProperties2Func = reinterpret_cast<
+                    PFN_vkGetPhysicalDeviceProperties2KHR>(
+                    ivk->vkGetInstanceProcAddr(
+                            sVkEmulation->instance,
+                            "vkGetPhysicalDeviceProperties2"));
+        }
     }
 
     if (sVkEmulation->instanceSupportsMoltenVK) {
@@ -664,6 +676,25 @@
         if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
             deviceInfos[i].supportsExternalMemory = extensionsSupported(
                     deviceExts, externalMemoryDeviceExtNames);
+            deviceInfos[i].supportsIdProperties =
+                sVkEmulation->getPhysicalDeviceProperties2Func != nullptr;
+            if (!sVkEmulation->getPhysicalDeviceProperties2Func) {
+                fprintf(stderr, "%s: warning: device should support ID properties "
+                        "but vkGetPhysicalDeviceProperties2 could not be found\n", __func__);
+            }
+        }
+
+        if (deviceInfos[i].supportsIdProperties) {
+            VkPhysicalDeviceIDPropertiesKHR idProps = {
+                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR, nullptr,
+            };
+            VkPhysicalDeviceProperties2KHR propsWithId = {
+                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, &idProps,
+            };
+            sVkEmulation->getPhysicalDeviceProperties2Func(
+                physdevs[i],
+                &propsWithId);
+            deviceInfos[i].idProps = idProps;
         }
 
         uint32_t queueFamilyCount = 0;
@@ -728,19 +759,33 @@
 
     for (uint32_t i = 0; i < physdevCount; ++i) {
         uint32_t deviceScore = 0;
-        if (deviceInfos[i].hasGraphicsQueueFamily) deviceScore += 100;
-        if (deviceInfos[i].supportsExternalMemory) deviceScore += 10;
-        if (deviceInfos[i].hasComputeQueueFamily) deviceScore += 1;
+        if (deviceInfos[i].hasGraphicsQueueFamily) deviceScore += 10000;
+        if (deviceInfos[i].supportsExternalMemory) deviceScore += 1000;
+        if (deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ||
+            deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
+            deviceScore += 100;
+        }
+        if (deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
+            deviceScore += 50;
+        }
         deviceScores[i] = deviceScore;
     }
 
     uint32_t maxScoringIndex = 0;
     uint32_t maxScore = 0;
 
-    for (uint32_t i = 0; i < physdevCount; ++i) {
-        if (deviceScores[i] > maxScore) {
-            maxScoringIndex = i;
-            maxScore = deviceScores[i];
+    // If we don't support physical device ID properties,
+    // just pick the first physical device.
+    if (!sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
+        fprintf(stderr, "%s: warning: instance doesn't support "
+            "external memory capabilities, picking first physical device\n", __func__);
+        maxScoringIndex = 0;
+    } else {
+        for (uint32_t i = 0; i < physdevCount; ++i) {
+            if (deviceScores[i] > maxScore) {
+                maxScoringIndex = i;
+                maxScore = deviceScores[i];
+            }
         }
     }