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];
+ }
}
}