1 // Copyright 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "VkCommonOperations.h"
15 
16 #include <GLES2/gl2.h>
17 #include <GLES2/gl2ext.h>
18 #include <GLES3/gl3.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <vulkan/vk_enum_string_helper.h>
22 
23 #include <iomanip>
24 #include <ostream>
25 #include <sstream>
26 #include <unordered_set>
27 
28 #include "VkDecoderGlobalState.h"
29 #include "VkEmulatedPhysicalDeviceMemory.h"
30 #include "VkFormatUtils.h"
31 #include "VulkanDispatch.h"
32 #include "aemu/base/Optional.h"
33 #include "aemu/base/Tracing.h"
34 #include "aemu/base/containers/Lookup.h"
35 #include "aemu/base/containers/StaticMap.h"
36 #include "aemu/base/synchronization/Lock.h"
37 #include "aemu/base/system/System.h"
38 #include "common/goldfish_vk_dispatch.h"
39 #include "host-common/GfxstreamFatalError.h"
40 #include "host-common/emugl_vm_operations.h"
41 #include "host-common/vm_operations.h"
42 
43 #ifdef _WIN32
44 #include <windows.h>
45 #else
46 #include <fcntl.h>
47 #include <unistd.h>
48 #endif
49 
50 #ifdef __APPLE__
51 #include <CoreFoundation/CoreFoundation.h>
52 #include <vulkan/vulkan_beta.h> // for MoltenVK portability extensions
53 #endif
54 
55 namespace gfxstream {
56 namespace vk {
57 namespace {
58 
59 #define VK_COMMON_ERROR(fmt, ...) \
60     fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
61 #define VK_COMMON_LOG(fmt, ...) \
62     fprintf(stdout, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
63 #define VK_COMMON_VERBOSE(fmt, ...)        \
64     if (android::base::isVerboseLogging()) \
65         fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
66 
67 using android::base::AutoLock;
68 using android::base::kNullopt;
69 using android::base::ManagedDescriptor;
70 using android::base::Optional;
71 using android::base::StaticLock;
72 using android::base::StaticMap;
73 using emugl::ABORT_REASON_OTHER;
74 using emugl::FatalError;
75 
76 constexpr size_t kPageBits = 12;
77 constexpr size_t kPageSize = 1u << kPageBits;
78 
79 static int kMaxDebugMarkerAnnotations = 10;
80 
81 static std::optional<std::string> sMemoryLogPath = std::nullopt;
82 
string_AstcEmulationMode(AstcEmulationMode mode)83 const char* string_AstcEmulationMode(AstcEmulationMode mode) {
84     switch (mode) {
85         case AstcEmulationMode::Disabled:
86             return "Disabled";
87         case AstcEmulationMode::Cpu:
88             return "Cpu";
89         case AstcEmulationMode::Gpu:
90             return "Gpu";
91     }
92     return "Unknown";
93 }
94 
95 }  // namespace
96 
97 static StaticMap<VkDevice, uint32_t> sKnownStagingTypeIndices;
98 
99 static android::base::StaticLock sVkEmulationLock;
100 
101 static bool updateColorBufferFromBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y,
102                                              uint32_t w, uint32_t h, const void* pixels,
103                                              size_t inputPixelsSize);
104 
105 #if !defined(__QNX__)
dupExternalMemory(VK_EXT_MEMORY_HANDLE h)106 VK_EXT_MEMORY_HANDLE dupExternalMemory(VK_EXT_MEMORY_HANDLE h) {
107 #ifdef _WIN32
108     auto myProcessHandle = GetCurrentProcess();
109     VK_EXT_MEMORY_HANDLE res;
110     DuplicateHandle(myProcessHandle, h,     // source process and handle
111                     myProcessHandle, &res,  // target process and pointer to handle
112                     0 /* desired access (ignored) */, true /* inherit */,
113                     DUPLICATE_SAME_ACCESS /* same access option */);
114     return res;
115 #else
116     return dup(h);
117 #endif
118 }
119 #endif
120 
getStagingMemoryTypeIndex(VulkanDispatch * vk,VkDevice device,const VkPhysicalDeviceMemoryProperties * memProps,uint32_t * typeIndex)121 bool getStagingMemoryTypeIndex(VulkanDispatch* vk, VkDevice device,
122                                const VkPhysicalDeviceMemoryProperties* memProps,
123                                uint32_t* typeIndex) {
124     auto res = sKnownStagingTypeIndices.get(device);
125 
126     if (res) {
127         *typeIndex = *res;
128         return true;
129     }
130 
131     VkBufferCreateInfo testCreateInfo = {
132         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
133         0,
134         0,
135         4096,
136         // To be a staging buffer, it must support being
137         // both a transfer src and dst.
138         VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
139         // TODO: See if buffers over shared queues need to be
140         // considered separately
141         VK_SHARING_MODE_EXCLUSIVE,
142         0,
143         nullptr,
144     };
145 
146     VkBuffer testBuffer;
147     VkResult testBufferCreateRes =
148         vk->vkCreateBuffer(device, &testCreateInfo, nullptr, &testBuffer);
149 
150     if (testBufferCreateRes != VK_SUCCESS) {
151         VK_COMMON_ERROR(
152             "Could not create test buffer "
153             "for staging buffer query. VkResult: %s",
154             string_VkResult(testBufferCreateRes));
155         return false;
156     }
157 
158     VkMemoryRequirements memReqs;
159     vk->vkGetBufferMemoryRequirements(device, testBuffer, &memReqs);
160 
161     // To be a staging buffer, we need to allow CPU read/write access.
162     // Thus, we need the memory type index both to be host visible
163     // and to be supported in the memory requirements of the buffer.
164     bool foundSuitableStagingMemoryType = false;
165     uint32_t stagingMemoryTypeIndex = 0;
166 
167     for (uint32_t i = 0; i < memProps->memoryTypeCount; ++i) {
168         const auto& typeInfo = memProps->memoryTypes[i];
169         bool hostVisible = typeInfo.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
170         bool hostCached = typeInfo.propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
171         bool allowedInBuffer = (1 << i) & memReqs.memoryTypeBits;
172         if (hostVisible && hostCached && allowedInBuffer) {
173             foundSuitableStagingMemoryType = true;
174             stagingMemoryTypeIndex = i;
175             break;
176         }
177     }
178 
179     // If the previous loop failed, try to accept a type that is not HOST_CACHED.
180     if (!foundSuitableStagingMemoryType) {
181         for (uint32_t i = 0; i < memProps->memoryTypeCount; ++i) {
182             const auto& typeInfo = memProps->memoryTypes[i];
183             bool hostVisible = typeInfo.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
184             bool allowedInBuffer = (1 << i) & memReqs.memoryTypeBits;
185             if (hostVisible && allowedInBuffer) {
186                 VK_COMMON_ERROR("Warning: using non-cached HOST_VISIBLE type for staging memory");
187                 foundSuitableStagingMemoryType = true;
188                 stagingMemoryTypeIndex = i;
189                 break;
190             }
191         }
192     }
193 
194     vk->vkDestroyBuffer(device, testBuffer, nullptr);
195 
196     if (!foundSuitableStagingMemoryType) {
197         std::stringstream ss;
198         ss << "Could not find suitable memory type index "
199            << "for staging buffer. Memory type bits: " << std::hex << memReqs.memoryTypeBits << "\n"
200            << "Available host visible memory type indices:"
201            << "\n";
202         for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
203             if (memProps->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
204                 ss << "Host visible memory type index: %u" << i << "\n";
205             }
206             if (memProps->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
207                 ss << "Host cached memory type index: %u" << i << "\n";
208             }
209         }
210 
211         VK_COMMON_ERROR("Error: %s", ss.str().c_str());
212 
213         return false;
214     }
215 
216     sKnownStagingTypeIndices.set(device, stagingMemoryTypeIndex);
217     *typeIndex = stagingMemoryTypeIndex;
218 
219     return true;
220 }
221 
222 static VkEmulation* sVkEmulation = nullptr;
223 
extensionsSupported(const std::vector<VkExtensionProperties> & currentProps,const std::vector<const char * > & wantedExtNames)224 static bool extensionsSupported(const std::vector<VkExtensionProperties>& currentProps,
225                                 const std::vector<const char*>& wantedExtNames) {
226     std::vector<bool> foundExts(wantedExtNames.size(), false);
227 
228     for (uint32_t i = 0; i < currentProps.size(); ++i) {
229         VK_COMMON_VERBOSE("has extension: %s", currentProps[i].extensionName);
230         for (size_t j = 0; j < wantedExtNames.size(); ++j) {
231             if (!strcmp(wantedExtNames[j], currentProps[i].extensionName)) {
232                 foundExts[j] = true;
233             }
234         }
235     }
236 
237     for (size_t i = 0; i < wantedExtNames.size(); ++i) {
238         bool found = foundExts[i];
239         VK_COMMON_VERBOSE("needed extension: %s, found %d", wantedExtNames[i], found);
240         if (!found) {
241             VK_COMMON_LOG("%s not found, bailing.", wantedExtNames[i]);
242             return false;
243         }
244     }
245 
246     return true;
247 }
248 
249 // For a given ImageSupportInfo, populates usageWithExternalHandles and
250 // requiresDedicatedAllocation. memoryTypeBits are populated later once the
251 // device is created, because that needs a test image to be created.
252 // If we don't support external memory, it's assumed dedicated allocations are
253 // not needed.
254 // Precondition: sVkEmulation instance has been created and ext memory caps known.
255 // Returns false if the query failed.
getImageFormatExternalMemorySupportInfo(VulkanDispatch * vk,VkPhysicalDevice physdev,VkEmulation::ImageSupportInfo * info)256 static bool getImageFormatExternalMemorySupportInfo(VulkanDispatch* vk, VkPhysicalDevice physdev,
257                                                     VkEmulation::ImageSupportInfo* info) {
258     // Currently there is nothing special we need to do about
259     // VkFormatProperties2, so just use the normal version
260     // and put it in the format2 struct.
261     VkFormatProperties outFormatProps;
262     vk->vkGetPhysicalDeviceFormatProperties(physdev, info->format, &outFormatProps);
263 
264     info->formatProps2 = {
265         VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
266         0,
267         outFormatProps,
268     };
269 
270     if (!sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
271         info->supportsExternalMemory = false;
272         info->requiresDedicatedAllocation = false;
273 
274         VkImageFormatProperties outImageFormatProps;
275         VkResult res = vk->vkGetPhysicalDeviceImageFormatProperties(
276             physdev, info->format, info->type, info->tiling, info->usageFlags, info->createFlags,
277             &outImageFormatProps);
278 
279         if (res != VK_SUCCESS) {
280             if (res == VK_ERROR_FORMAT_NOT_SUPPORTED) {
281                 info->supported = false;
282                 return true;
283             } else {
284                 VK_COMMON_ERROR("vkGetPhysicalDeviceImageFormatProperties query "
285                         "failed with %s"
286                         "for format 0x%x type 0x%x usage 0x%x flags 0x%x",
287                         string_VkResult(res), info->format, info->type, info->usageFlags,
288                         info->createFlags);
289                 return false;
290             }
291         }
292 
293         info->supported = true;
294 
295         info->imageFormatProps2 = {
296             VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
297             0,
298             outImageFormatProps,
299         };
300 
301         VK_COMMON_VERBOSE("Supported (not externally): %s %s %s %s",
302              string_VkFormat(info->format),
303              string_VkImageType(info->type),
304              string_VkImageTiling(info->tiling),
305              string_VkImageUsageFlagBits((VkImageUsageFlagBits)info->usageFlags));
306 
307         return true;
308     }
309 
310     VkPhysicalDeviceExternalImageFormatInfo extInfo = {
311         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
312         0,
313         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
314     };
315 
316     VkPhysicalDeviceImageFormatInfo2 formatInfo2 = {
317         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
318         &extInfo,
319         info->format,
320         info->type,
321         info->tiling,
322         info->usageFlags,
323         info->createFlags,
324     };
325 
326     VkExternalImageFormatProperties outExternalProps = {
327         VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
328         0,
329         {
330             (VkExternalMemoryFeatureFlags)0,
331             (VkExternalMemoryHandleTypeFlags)0,
332             (VkExternalMemoryHandleTypeFlags)0,
333         },
334     };
335 
336     VkImageFormatProperties2 outProps2 = {VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
337                                           &outExternalProps,
338                                           {
339                                               {0, 0, 0},
340                                               0,
341                                               0,
342                                               1,
343                                               0,
344                                           }};
345 
346     VkResult res = sVkEmulation->getImageFormatProperties2Func(physdev, &formatInfo2, &outProps2);
347 
348     if (res != VK_SUCCESS) {
349         if (res == VK_ERROR_FORMAT_NOT_SUPPORTED) {
350             info->supported = false;
351             return true;
352         } else {
353             VK_COMMON_ERROR("vkGetPhysicalDeviceImageFormatProperties2KHR query "
354                     "failed with %s "
355                     "for format 0x%x type 0x%x usage 0x%x flags 0x%x",
356                     string_VkResult(res), info->format, info->type, info->usageFlags, info->createFlags);
357             return false;
358         }
359     }
360 
361     info->supported = true;
362 
363     VkExternalMemoryFeatureFlags featureFlags =
364         outExternalProps.externalMemoryProperties.externalMemoryFeatures;
365 
366     VkExternalMemoryHandleTypeFlags exportImportedFlags =
367         outExternalProps.externalMemoryProperties.exportFromImportedHandleTypes;
368 
369     // Don't really care about export form imported handle types yet
370     (void)exportImportedFlags;
371 
372     VkExternalMemoryHandleTypeFlags compatibleHandleTypes =
373         outExternalProps.externalMemoryProperties.compatibleHandleTypes;
374 
375     info->supportsExternalMemory = (VK_EXT_MEMORY_HANDLE_TYPE_BIT & compatibleHandleTypes) &&
376                                    (VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT & featureFlags) &&
377                                    (VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT & featureFlags);
378 
379     info->requiresDedicatedAllocation =
380         (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT & featureFlags);
381 
382     info->imageFormatProps2 = outProps2;
383     info->extFormatProps = outExternalProps;
384     info->imageFormatProps2.pNext = &info->extFormatProps;
385 
386     VK_COMMON_VERBOSE("Supported: %s %s %s %s, supportsExternalMemory? %d, requiresDedicated? %d",
387                         string_VkFormat(info->format),
388                         string_VkImageType(info->type),
389                         string_VkImageTiling(info->tiling),
390                         string_VkImageUsageFlagBits((VkImageUsageFlagBits)info->usageFlags),
391                         info->supportsExternalMemory,
392                         info->requiresDedicatedAllocation);
393 
394     return true;
395 }
396 
397 // Vulkan driverVersions are bit-shift packs of their dotted versions
398 // For example, nvidia driverversion 1934229504 unpacks to 461.40
399 // note: while this is equivalent to VkPhysicalDeviceDriverProperties.driverInfo on NVIDIA,
400 // on intel that value is simply "Intel driver".
decodeDriverVersion(uint32_t vendorId,uint32_t driverVersion)401 static std::string decodeDriverVersion(uint32_t vendorId, uint32_t driverVersion) {
402     std::stringstream result;
403     switch (vendorId) {
404         case 0x10DE: {
405             // Nvidia. E.g. driverVersion = 1934229504(0x734a0000) maps to 461.40
406             uint32_t major = driverVersion >> 22;
407             uint32_t minor = (driverVersion >> 14) & 0xff;
408             uint32_t build = (driverVersion >> 6) & 0xff;
409             uint32_t revision = driverVersion & 0x3f;
410             result << major << '.' << minor << '.' << build << '.' << revision;
411             break;
412         }
413         case 0x8086: {
414             // Intel. E.g. driverVersion = 1647866(0x1924fa) maps to 100.9466 (27.20.100.9466)
415             uint32_t high = driverVersion >> 14;
416             uint32_t low = driverVersion & 0x3fff;
417             result << high << '.' << low;
418             break;
419         }
420         case 0x002:  // amd
421         default: {
422             uint32_t major = VK_VERSION_MAJOR(driverVersion);
423             uint32_t minor = VK_VERSION_MINOR(driverVersion);
424             uint32_t patch = VK_VERSION_PATCH(driverVersion);
425             result << major << "." << minor << "." << patch;
426             break;
427         }
428     }
429     return result.str();
430 }
431 
getBasicImageSupportList()432 static std::vector<VkEmulation::ImageSupportInfo> getBasicImageSupportList() {
433     struct ImageFeatureCombo {
434         VkFormat format;
435         VkImageCreateFlags createFlags = 0;
436     };
437     // Set the mutable flag for RGB UNORM formats so that the created image can also be sampled in
438     // the sRGB Colorspace. See
439     // https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/3827672/comments/77db9cb3_60663a6a
440     // for details.
441     std::vector<ImageFeatureCombo> combos = {
442         // Cover all the gralloc formats
443         {VK_FORMAT_R8G8B8A8_UNORM,
444          VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
445         {VK_FORMAT_R8G8B8_UNORM,
446          VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
447 
448         {VK_FORMAT_R5G6B5_UNORM_PACK16},
449 
450         {VK_FORMAT_R16G16B16A16_SFLOAT},
451         {VK_FORMAT_R16G16B16_SFLOAT},
452 
453         {VK_FORMAT_B8G8R8A8_UNORM,
454          VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
455 
456         {VK_FORMAT_R8_UNORM,
457          VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
458         {VK_FORMAT_R16_UNORM,
459          VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
460 
461         {VK_FORMAT_A2R10G10B10_UINT_PACK32},
462         {VK_FORMAT_A2R10G10B10_UNORM_PACK32},
463         {VK_FORMAT_A2B10G10R10_UNORM_PACK32},
464 
465         // Compressed texture formats
466         {VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK},
467         {VK_FORMAT_ASTC_4x4_UNORM_BLOCK},
468 
469         // TODO: YUV formats used in Android
470         // Fails on Mac
471         {VK_FORMAT_G8_B8R8_2PLANE_420_UNORM},
472         {VK_FORMAT_G8_B8R8_2PLANE_422_UNORM},
473         {VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM},
474         {VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM},
475         {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16},
476 
477     };
478 
479     std::vector<VkImageType> types = {
480         VK_IMAGE_TYPE_2D,
481     };
482 
483     std::vector<VkImageTiling> tilings = {
484         VK_IMAGE_TILING_LINEAR,
485         VK_IMAGE_TILING_OPTIMAL,
486     };
487 
488     std::vector<VkImageUsageFlags> usageFlags = {
489         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
490         VK_IMAGE_USAGE_SAMPLED_BIT,          VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
491         VK_IMAGE_USAGE_TRANSFER_DST_BIT,
492     };
493 
494     std::vector<VkEmulation::ImageSupportInfo> res;
495 
496     // Currently: 17 format + create flags combo, 2 tilings, 5 usage flags -> 170 cases to check.
497     for (auto combo : combos) {
498         for (auto t : types) {
499             for (auto ti : tilings) {
500                 for (auto u : usageFlags) {
501                     VkEmulation::ImageSupportInfo info;
502                     info.format = combo.format;
503                     info.type = t;
504                     info.tiling = ti;
505                     info.usageFlags = u;
506                     info.createFlags = combo.createFlags;
507                     res.push_back(info);
508                 }
509             }
510         }
511     }
512 
513     return res;
514 }
515 
createGlobalVkEmulation(VulkanDispatch * vk,gfxstream::host::FeatureSet features)516 VkEmulation* createGlobalVkEmulation(VulkanDispatch* vk, gfxstream::host::FeatureSet features) {
517 // Downstream branches can provide abort logic or otherwise use result without a new macro
518 #define VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(res, ...) \
519     do {                                               \
520         (void)res; /* no-op of unused param*/          \
521         ERR(__VA_ARGS__);                              \
522         return nullptr;                                \
523     } while (0)
524 
525     AutoLock lock(sVkEmulationLock);
526 
527     if (sVkEmulation) return sVkEmulation;
528 
529     if (!vkDispatchValid(vk)) {
530         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER, "Dispatch is invalid.");
531     }
532 
533     sVkEmulation = new VkEmulation;
534 
535     sVkEmulation->features = features;
536 
537     sVkEmulation->gvk = vk;
538     auto gvk = vk;
539 
540     std::vector<const char*> externalMemoryInstanceExtNames = {
541         VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
542         VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
543     };
544 
545     std::vector<const char*> externalMemoryDeviceExtNames = {
546         VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
547         VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
548         VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
549 #ifdef _WIN32
550         VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
551 #elif defined(__QNX__)
552         VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_EXTENSION_NAME,
553         VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME,
554 #else
555         VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
556 #endif
557     };
558 
559     std::vector<const char*> externalSemaphoreInstanceExtNames = {
560         VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
561     };
562 
563     std::vector<const char*> surfaceInstanceExtNames = {
564         VK_KHR_SURFACE_EXTENSION_NAME,
565     };
566 
567 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
568     std::vector<const char*> moltenVkInstanceExtNames = {
569         VK_MVK_MACOS_SURFACE_EXTENSION_NAME,
570         VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
571     };
572     std::vector<const char*> moltenVkDeviceExtNames = {
573         VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
574         VK_EXT_METAL_OBJECTS_EXTENSION_NAME,
575     };
576 #endif
577 
578     uint32_t instanceExtCount = 0;
579     gvk->vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr);
580     std::vector<VkExtensionProperties>& instanceExts = sVkEmulation->instanceExtensions;
581     instanceExts.resize(instanceExtCount);
582     gvk->vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, instanceExts.data());
583 
584     bool externalMemoryCapabilitiesSupported =
585         extensionsSupported(instanceExts, externalMemoryInstanceExtNames);
586     bool externalSemaphoreCapabilitiesSupported =
587         extensionsSupported(instanceExts, externalSemaphoreInstanceExtNames);
588     bool surfaceSupported =
589         extensionsSupported(instanceExts, surfaceInstanceExtNames);
590 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
591     bool moltenVKSupported = (vk->vkGetMTLTextureMVK != nullptr) &&
592                              (vk->vkSetMTLTextureMVK != nullptr) &&
593                              extensionsSupported(instanceExts, moltenVkInstanceExtNames);
594     if (moltenVKSupported) {
595         // We don't need both moltenVK and external memory. Disable
596         // external memory if moltenVK is supported.
597         externalMemoryCapabilitiesSupported = false;
598     }
599 #endif
600 
601     VkInstanceCreateInfo instCi = {
602         VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, nullptr, 0, nullptr, 0, nullptr,
603     };
604 
605     std::unordered_set<const char*> selectedInstanceExtensionNames;
606 
607     const bool debugUtilsSupported = extensionsSupported(instanceExts, {VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
608     const bool debugUtilsRequested = false; // TODO: enable via a feature or env var?
609     const bool debugUtilsAvailableAndRequested = debugUtilsSupported && debugUtilsRequested;
610     if (debugUtilsAvailableAndRequested) {
611         selectedInstanceExtensionNames.emplace(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
612     }
613 
614     if (externalMemoryCapabilitiesSupported) {
615         for (auto extension : externalMemoryInstanceExtNames) {
616             selectedInstanceExtensionNames.emplace(extension);
617         }
618     }
619 
620     if (surfaceSupported) {
621         for (auto extension : surfaceInstanceExtNames) {
622             selectedInstanceExtensionNames.emplace(extension);
623         }
624     }
625 
626     if (sVkEmulation->features.VulkanNativeSwapchain.enabled) {
627         for (auto extension : SwapChainStateVk::getRequiredInstanceExtensions()) {
628             selectedInstanceExtensionNames.emplace(extension);
629         }
630     }
631 
632 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
633     if (moltenVKSupported) {
634         instCi.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
635         for (auto extension : moltenVkInstanceExtNames) {
636             selectedInstanceExtensionNames.emplace(extension);
637         }
638     }
639 #endif
640 
641     std::vector<const char*> selectedInstanceExtensionNames_(selectedInstanceExtensionNames.begin(), selectedInstanceExtensionNames.end());
642     instCi.enabledExtensionCount = static_cast<uint32_t>(selectedInstanceExtensionNames_.size());
643     instCi.ppEnabledExtensionNames = selectedInstanceExtensionNames_.data();
644 
645     VkApplicationInfo appInfo = {
646         VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, "AEMU", 1, "AEMU", 1, VK_MAKE_VERSION(1, 0, 0),
647     };
648 
649     instCi.pApplicationInfo = &appInfo;
650 
651     // Can we know instance version early?
652     if (gvk->vkEnumerateInstanceVersion) {
653         VK_COMMON_VERBOSE("global loader has vkEnumerateInstanceVersion.");
654         uint32_t instanceVersion;
655         VkResult res = gvk->vkEnumerateInstanceVersion(&instanceVersion);
656         if (VK_SUCCESS == res) {
657             if (instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
658                 VK_COMMON_VERBOSE("global loader has vkEnumerateInstanceVersion returning >= 1.1.");
659                 appInfo.apiVersion = VK_MAKE_VERSION(1, 1, 0);
660             }
661         }
662     }
663 
664     VK_COMMON_VERBOSE("Creating instance, asking for version %d.%d.%d ...",
665                       VK_VERSION_MAJOR(appInfo.apiVersion), VK_VERSION_MINOR(appInfo.apiVersion),
666                       VK_VERSION_PATCH(appInfo.apiVersion));
667 
668     VkResult res = gvk->vkCreateInstance(&instCi, nullptr, &sVkEmulation->instance);
669 
670     if (res != VK_SUCCESS) {
671         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(res, "Failed to create Vulkan instance. Error %s.",
672                                              string_VkResult(res));
673     }
674 
675     // Create instance level dispatch.
676     sVkEmulation->ivk = new VulkanDispatch;
677     init_vulkan_dispatch_from_instance(vk, sVkEmulation->instance, sVkEmulation->ivk);
678 
679     auto ivk = sVkEmulation->ivk;
680 
681     if (!vulkan_dispatch_check_instance_VK_VERSION_1_0(ivk)) {
682         VK_COMMON_ERROR("Warning: Vulkan 1.0 APIs missing from instance");
683     }
684 
685     if (ivk->vkEnumerateInstanceVersion) {
686         uint32_t instanceVersion;
687         VkResult enumInstanceRes = ivk->vkEnumerateInstanceVersion(&instanceVersion);
688         if ((VK_SUCCESS == enumInstanceRes) && instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
689             if (!vulkan_dispatch_check_instance_VK_VERSION_1_1(ivk)) {
690                 VK_COMMON_ERROR("Warning: Vulkan 1.1 APIs missing from instance (1st try)");
691             }
692         }
693 
694         if (appInfo.apiVersion < VK_MAKE_VERSION(1, 1, 0) &&
695             instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
696             VK_COMMON_VERBOSE("Found out that we can create a higher version instance.");
697             appInfo.apiVersion = VK_MAKE_VERSION(1, 1, 0);
698 
699             gvk->vkDestroyInstance(sVkEmulation->instance, nullptr);
700 
701             VkResult res = gvk->vkCreateInstance(&instCi, nullptr, &sVkEmulation->instance);
702 
703             if (res != VK_SUCCESS) {
704                 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
705                     res, "Failed to create Vulkan 1.1 instance. Error %s.", string_VkResult(res));
706             }
707 
708             init_vulkan_dispatch_from_instance(vk, sVkEmulation->instance, sVkEmulation->ivk);
709 
710             VK_COMMON_VERBOSE("Created Vulkan 1.1 instance on second try.");
711 
712             if (!vulkan_dispatch_check_instance_VK_VERSION_1_1(ivk)) {
713                 VK_COMMON_ERROR("Warning: Vulkan 1.1 APIs missing from instance (2nd try)");
714             }
715         }
716     }
717 
718     sVkEmulation->vulkanInstanceVersion = appInfo.apiVersion;
719 
720     sVkEmulation->instanceSupportsExternalMemoryCapabilities = externalMemoryCapabilitiesSupported;
721     sVkEmulation->instanceSupportsExternalSemaphoreCapabilities =
722         externalSemaphoreCapabilitiesSupported;
723     sVkEmulation->instanceSupportsSurface = surfaceSupported;
724 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
725     sVkEmulation->instanceSupportsMoltenVK = moltenVKSupported;
726 #endif
727 
728     if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
729         sVkEmulation->getImageFormatProperties2Func = vk_util::getVkInstanceProcAddrWithFallback<
730             vk_util::vk_fn_info::GetPhysicalDeviceImageFormatProperties2>(
731             {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance);
732         sVkEmulation->getPhysicalDeviceProperties2Func = vk_util::getVkInstanceProcAddrWithFallback<
733             vk_util::vk_fn_info::GetPhysicalDeviceProperties2>(
734             {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance);
735     }
736     sVkEmulation->getPhysicalDeviceFeatures2Func =
737         vk_util::getVkInstanceProcAddrWithFallback<vk_util::vk_fn_info::GetPhysicalDeviceFeatures2>(
738             {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance);
739 
740 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
741     if (sVkEmulation->instanceSupportsMoltenVK) {
742         // These functions are directly loaded from the shared molten library
743         // and are not available via vkGetInstanceProcAddr
744         sVkEmulation->setMTLTextureFunc = gvk->vkSetMTLTextureMVK;
745         if (!sVkEmulation->setMTLTextureFunc) {
746             VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
747                                                  "Cannot find vkSetMTLTextureMVK.");
748         }
749         sVkEmulation->getMTLTextureFunc = gvk->vkGetMTLTextureMVK;
750         if (!sVkEmulation->getMTLTextureFunc) {
751             VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
752                                                  "Cannot find vkGetMTLTextureMVK.");
753         }
754         VK_COMMON_LOG("Instance supports VK_MVK_moltenvk.");
755     }
756 #endif
757 
758     uint32_t physdevCount = 0;
759     ivk->vkEnumeratePhysicalDevices(sVkEmulation->instance, &physdevCount, nullptr);
760     std::vector<VkPhysicalDevice> physdevs(physdevCount);
761     ivk->vkEnumeratePhysicalDevices(sVkEmulation->instance, &physdevCount, physdevs.data());
762 
763     VK_COMMON_VERBOSE("Found %d Vulkan physical devices.", physdevCount);
764 
765     if (physdevCount == 0) {
766         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER, "No physical devices available.");
767     }
768 
769     std::vector<VkEmulation::DeviceSupportInfo> deviceInfos(physdevCount);
770 
771     for (int i = 0; i < physdevCount; ++i) {
772         ivk->vkGetPhysicalDeviceProperties(physdevs[i], &deviceInfos[i].physdevProps);
773 
774         VK_COMMON_VERBOSE("Considering Vulkan physical device %d : %s", i, deviceInfos[i].physdevProps.deviceName);
775 
776         // It's easier to figure out the staging buffer along with
777         // external memories if we have the memory properties on hand.
778         ivk->vkGetPhysicalDeviceMemoryProperties(physdevs[i], &deviceInfos[i].memProps);
779 
780         uint32_t deviceExtensionCount = 0;
781         ivk->vkEnumerateDeviceExtensionProperties(physdevs[i], nullptr, &deviceExtensionCount,
782                                                   nullptr);
783         std::vector<VkExtensionProperties>& deviceExts = deviceInfos[i].extensions;
784         deviceExts.resize(deviceExtensionCount);
785         ivk->vkEnumerateDeviceExtensionProperties(physdevs[i], nullptr, &deviceExtensionCount,
786                                                   deviceExts.data());
787 
788         deviceInfos[i].supportsExternalMemoryImport = false;
789         deviceInfos[i].supportsExternalMemoryExport = false;
790         deviceInfos[i].glInteropSupported = 0;  // set later
791 
792 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
793         if (moltenVKSupported && !extensionsSupported(deviceExts, moltenVkDeviceExtNames)) {
794             VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
795                 ABORT_REASON_OTHER,
796                 "MoltenVK enabled but necessary device extensions are not supported.");
797         }
798 #endif
799 
800         if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
801             deviceInfos[i].supportsExternalMemoryExport =
802                 deviceInfos[i].supportsExternalMemoryImport =
803                     extensionsSupported(deviceExts, externalMemoryDeviceExtNames);
804 #if defined(__QNX__)
805             // External memory export not supported on QNX
806             deviceInfos[i].supportsExternalMemoryExport = false;
807 #endif
808             deviceInfos[i].supportsIdProperties =
809                 sVkEmulation->getPhysicalDeviceProperties2Func != nullptr;
810             deviceInfos[i].supportsDriverProperties =
811                 extensionsSupported(deviceExts, {VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME}) ||
812                 (deviceInfos[i].physdevProps.apiVersion >= VK_API_VERSION_1_2);
813 
814             if (!sVkEmulation->getPhysicalDeviceProperties2Func) {
815                 VK_COMMON_ERROR("Warning: device claims to support ID properties "
816                         "but vkGetPhysicalDeviceProperties2 could not be found");
817             }
818         }
819 
820         if (sVkEmulation->getPhysicalDeviceProperties2Func) {
821             VkPhysicalDeviceProperties2 deviceProps = {
822                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
823             };
824             VkPhysicalDeviceIDProperties idProps = {
825                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR,
826             };
827             VkPhysicalDeviceDriverPropertiesKHR driverProps = {
828                 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
829             };
830 
831             auto devicePropsChain = vk_make_chain_iterator(&deviceProps);
832 
833             if (deviceInfos[i].supportsIdProperties) {
834                 vk_append_struct(&devicePropsChain, &idProps);
835             }
836 
837             if (deviceInfos[i].supportsDriverProperties) {
838                 vk_append_struct(&devicePropsChain, &driverProps);
839             }
840 
841             sVkEmulation->getPhysicalDeviceProperties2Func(physdevs[i], &deviceProps);
842 
843             deviceInfos[i].idProps = vk_make_orphan_copy(idProps);
844 
845             std::stringstream driverVendorBuilder;
846             driverVendorBuilder << "Vendor " << std::hex << std::setfill('0') << std::showbase
847                                 << deviceInfos[i].physdevProps.vendorID;
848 
849             std::string decodedDriverVersion = decodeDriverVersion(
850                 deviceInfos[i].physdevProps.vendorID, deviceInfos[i].physdevProps.driverVersion);
851 
852             std::stringstream driverVersionBuilder;
853             driverVersionBuilder << "Driver Version " << std::hex << std::setfill('0')
854                                  << std::showbase << deviceInfos[i].physdevProps.driverVersion
855                                  << " Decoded As " << decodedDriverVersion;
856 
857             std::string driverVendor = driverVendorBuilder.str();
858             std::string driverVersion = driverVersionBuilder.str();
859             if (deviceInfos[i].supportsDriverProperties && driverProps.driverID) {
860                 driverVendor = std::string{driverProps.driverName} + " (" + driverVendor + ")";
861                 driverVersion = std::string{driverProps.driverInfo} + " (" +
862                                 string_VkDriverId(driverProps.driverID) + " " + driverVersion + ")";
863             }
864 
865             deviceInfos[i].driverVendor = driverVendor;
866             deviceInfos[i].driverVersion = driverVersion;
867         }
868 
869         deviceInfos[i].hasSamplerYcbcrConversionExtension =
870             extensionsSupported(deviceExts, {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME});
871         if (sVkEmulation->getPhysicalDeviceFeatures2Func) {
872             VkPhysicalDeviceFeatures2 features2 = {
873                 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
874             };
875             auto features2Chain = vk_make_chain_iterator(&features2);
876             VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYcbcrConversionFeatures = {
877                 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
878             };
879             vk_append_struct(&features2Chain, &samplerYcbcrConversionFeatures);
880 #if defined(__QNX__)
881             VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX extMemScreenBufferFeatures = {
882                 .sType =
883                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX,
884             };
885             vk_append_struct(&features2Chain, &extMemScreenBufferFeatures);
886 #endif
887             sVkEmulation->getPhysicalDeviceFeatures2Func(physdevs[i], &features2);
888 
889             deviceInfos[i].supportsSamplerYcbcrConversion =
890                 samplerYcbcrConversionFeatures.samplerYcbcrConversion == VK_TRUE;
891 #if defined(__QNX__)
892             deviceInfos[i].supportsExternalMemoryImport =
893                 extMemScreenBufferFeatures.screenBufferImport == VK_TRUE;
894         } else {
895             deviceInfos[i].supportsExternalMemoryImport = false;
896 #endif
897         }
898 
899         uint32_t queueFamilyCount = 0;
900         ivk->vkGetPhysicalDeviceQueueFamilyProperties(physdevs[i], &queueFamilyCount, nullptr);
901         std::vector<VkQueueFamilyProperties> queueFamilyProps(queueFamilyCount);
902         ivk->vkGetPhysicalDeviceQueueFamilyProperties(physdevs[i], &queueFamilyCount,
903                                                       queueFamilyProps.data());
904 
905         for (uint32_t j = 0; j < queueFamilyCount; ++j) {
906             auto count = queueFamilyProps[j].queueCount;
907             auto flags = queueFamilyProps[j].queueFlags;
908 
909             bool hasGraphicsQueueFamily = (count > 0 && (flags & VK_QUEUE_GRAPHICS_BIT));
910             bool hasComputeQueueFamily = (count > 0 && (flags & VK_QUEUE_COMPUTE_BIT));
911 
912             deviceInfos[i].hasGraphicsQueueFamily =
913                 deviceInfos[i].hasGraphicsQueueFamily || hasGraphicsQueueFamily;
914 
915             deviceInfos[i].hasComputeQueueFamily =
916                 deviceInfos[i].hasComputeQueueFamily || hasComputeQueueFamily;
917 
918             if (hasGraphicsQueueFamily) {
919                 deviceInfos[i].graphicsQueueFamilyIndices.push_back(j);
920                 VK_COMMON_VERBOSE("Graphics queue family index: %d", j);
921             }
922 
923             if (hasComputeQueueFamily) {
924                 deviceInfos[i].computeQueueFamilyIndices.push_back(j);
925                 VK_COMMON_VERBOSE("Compute queue family index: %d", j);
926             }
927         }
928     }
929 
930     // Of all the devices enumerated, find the best one. Try to find a device
931     // with graphics queue as the highest priority, then ext memory, then
932     // compute.
933 
934     // Graphics queue is highest priority since without that, we really
935     // shouldn't be using the driver. Although, one could make a case for doing
936     // some sorts of things if only a compute queue is available (such as for
937     // AI), that's not really the priority yet.
938 
939     // As for external memory, we really should not be running on any driver
940     // without external memory support, but we might be able to pull it off, and
941     // single Vulkan apps might work via CPU transfer of the rendered frames.
942 
943     // Compute support is treated as icing on the cake and not relied upon yet
944     // for anything critical to emulation. However, we might potentially use it
945     // to perform image format conversion on GPUs where that's not natively
946     // supported.
947 
948     // Another implicit choice is to select only one Vulkan device. This makes
949     // things simple for now, but we could consider utilizing multiple devices
950     // in use cases that make sense, if/when they come up.
951 
952     std::vector<uint32_t> deviceScores(physdevCount, 0);
953 
954     for (uint32_t i = 0; i < physdevCount; ++i) {
955         uint32_t deviceScore = 0;
956         if (deviceInfos[i].hasGraphicsQueueFamily) deviceScore += 10000;
957         if (deviceInfos[i].supportsExternalMemoryImport ||
958             deviceInfos[i].supportsExternalMemoryExport)
959             deviceScore += 1000;
960         if (deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ||
961             deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
962             deviceScore += 100;
963         }
964         if (deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
965             deviceScore += 50;
966         }
967         deviceScores[i] = deviceScore;
968     }
969 
970     uint32_t maxScoringIndex = 0;
971     uint32_t maxScore = 0;
972 
973     // If we don't support physical device ID properties,
974     // just pick the first physical device.
975     if (!sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
976         VK_COMMON_ERROR("Warning: instance doesn't support "
977                 "external memory capabilities, picking first physical device");
978         maxScoringIndex = 0;
979     } else {
980         for (uint32_t i = 0; i < physdevCount; ++i) {
981             if (deviceScores[i] > maxScore) {
982                 maxScoringIndex = i;
983                 maxScore = deviceScores[i];
984             }
985         }
986     }
987 
988     sVkEmulation->physdev = physdevs[maxScoringIndex];
989     sVkEmulation->physicalDeviceIndex = maxScoringIndex;
990     sVkEmulation->deviceInfo = deviceInfos[maxScoringIndex];
991     // Postcondition: sVkEmulation has valid device support info
992 
993     // Ask about image format support here.
994     // TODO: May have to first ask when selecting physical devices
995     // (e.g., choose between Intel or NVIDIA GPU for certain image format
996     // support)
997     sVkEmulation->imageSupportInfo = getBasicImageSupportList();
998     for (size_t i = 0; i < sVkEmulation->imageSupportInfo.size(); ++i) {
999         getImageFormatExternalMemorySupportInfo(ivk, sVkEmulation->physdev,
1000                                                 &sVkEmulation->imageSupportInfo[i]);
1001     }
1002 
1003     if (!sVkEmulation->deviceInfo.hasGraphicsQueueFamily) {
1004         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1005                                              "No Vulkan devices with graphics queues found.");
1006     }
1007 
1008     auto deviceVersion = sVkEmulation->deviceInfo.physdevProps.apiVersion;
1009     VK_COMMON_LOG("Selecting Vulkan device: %s, Version: %d.%d.%d",
1010                 sVkEmulation->deviceInfo.physdevProps.deviceName,
1011                 VK_VERSION_MAJOR(deviceVersion),
1012                 VK_VERSION_MINOR(deviceVersion),
1013                 VK_VERSION_PATCH(deviceVersion));
1014 
1015     VK_COMMON_VERBOSE("deviceInfo: \n"
1016                         "hasGraphicsQueueFamily = %d\n"
1017                         "hasComputeQueueFamily = %d\n"
1018                         "supportsExternalMemoryImport = %d\n"
1019                         "supportsExternalMemoryExport = %d\n"
1020                         "supportsIdProperties = %d\n"
1021                         "supportsDriverProperties = %d\n"
1022                         "hasSamplerYcbcrConversionExtension = %d\n"
1023                         "supportsSamplerYcbcrConversion = %d\n"
1024                         "glInteropSupported = %d",
1025                         sVkEmulation->deviceInfo.hasGraphicsQueueFamily,
1026                         sVkEmulation->deviceInfo.hasComputeQueueFamily,
1027                         sVkEmulation->deviceInfo.supportsExternalMemoryImport,
1028                         sVkEmulation->deviceInfo.supportsExternalMemoryExport,
1029                         sVkEmulation->deviceInfo.supportsIdProperties,
1030                         sVkEmulation->deviceInfo.supportsDriverProperties,
1031                         sVkEmulation->deviceInfo.hasSamplerYcbcrConversionExtension,
1032                         sVkEmulation->deviceInfo.supportsSamplerYcbcrConversion,
1033                         sVkEmulation->deviceInfo.glInteropSupported);
1034 
1035     float priority = 1.0f;
1036     VkDeviceQueueCreateInfo dqCi = {
1037         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1038         0,
1039         0,
1040         sVkEmulation->deviceInfo.graphicsQueueFamilyIndices[0],
1041         1,
1042         &priority,
1043     };
1044 
1045     std::unordered_set<const char*> selectedDeviceExtensionNames_;
1046 
1047     if (sVkEmulation->deviceInfo.supportsExternalMemoryImport ||
1048         sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
1049         for (auto extension : externalMemoryDeviceExtNames) {
1050             selectedDeviceExtensionNames_.emplace(extension);
1051         }
1052     }
1053 
1054     // We need to always enable swapchain extensions to be able to use this device
1055     // to do VK_IMAGE_LAYOUT_PRESENT_SRC_KHR transition operations done
1056     // in releaseColorBufferForGuestUse for the apps using Vulkan swapchain
1057     selectedDeviceExtensionNames_.emplace(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1058 
1059     if (sVkEmulation->features.VulkanNativeSwapchain.enabled) {
1060         for (auto extension : SwapChainStateVk::getRequiredDeviceExtensions()) {
1061             selectedDeviceExtensionNames_.emplace(extension);
1062         }
1063     }
1064 
1065     if (sVkEmulation->deviceInfo.hasSamplerYcbcrConversionExtension) {
1066         selectedDeviceExtensionNames_.emplace(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
1067     }
1068 
1069 #if defined(__APPLE__) && defined(VK_MVK_moltenvk)
1070     if (moltenVKSupported) {
1071         for (auto extension : moltenVkDeviceExtNames) {
1072             selectedDeviceExtensionNames_.emplace(extension);
1073         }
1074     }
1075 #endif
1076 
1077     std::vector<const char*> selectedDeviceExtensionNames(selectedDeviceExtensionNames_.begin(),
1078                                                           selectedDeviceExtensionNames_.end());
1079 
1080     VkDeviceCreateInfo dCi = {};
1081     dCi.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
1082     dCi.queueCreateInfoCount = 1;
1083     dCi.pQueueCreateInfos = &dqCi;
1084     dCi.enabledExtensionCount = static_cast<uint32_t>(selectedDeviceExtensionNames.size());
1085     dCi.ppEnabledExtensionNames = selectedDeviceExtensionNames.data();
1086 
1087     // Setting up VkDeviceCreateInfo::pNext
1088     auto deviceCiChain = vk_make_chain_iterator(&dCi);
1089 
1090     VkPhysicalDeviceFeatures2 physicalDeviceFeatures = {
1091         .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
1092     };
1093     vk_append_struct(&deviceCiChain, &physicalDeviceFeatures);
1094 
1095     std::unique_ptr<VkPhysicalDeviceSamplerYcbcrConversionFeatures> samplerYcbcrConversionFeatures =
1096         nullptr;
1097     if (sVkEmulation->deviceInfo.supportsSamplerYcbcrConversion) {
1098         samplerYcbcrConversionFeatures =
1099             std::make_unique<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
1100                 VkPhysicalDeviceSamplerYcbcrConversionFeatures{
1101                     .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
1102                     .samplerYcbcrConversion = VK_TRUE,
1103                 });
1104         vk_append_struct(&deviceCiChain, samplerYcbcrConversionFeatures.get());
1105     }
1106 #if defined(__QNX__)
1107     std::unique_ptr<VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX>
1108         extMemScreenBufferFeaturesQNX = nullptr;
1109     if (sVkEmulation->deviceInfo.supportsExternalMemoryImport) {
1110         extMemScreenBufferFeaturesQNX = std::make_unique<
1111             VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX>(
1112             VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX{
1113                 .sType =
1114                     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX,
1115                 .screenBufferImport = VK_TRUE,
1116             });
1117         vk_append_struct(&deviceCiChain, extMemScreenBufferFeaturesQNX.get());
1118     }
1119 #endif
1120 
1121     ivk->vkCreateDevice(sVkEmulation->physdev, &dCi, nullptr, &sVkEmulation->device);
1122 
1123     if (res != VK_SUCCESS) {
1124         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(res, "Failed to create Vulkan device. Error %s.",
1125                                              string_VkResult(res));
1126     }
1127 
1128     // device created; populate dispatch table
1129     sVkEmulation->dvk = new VulkanDispatch;
1130     init_vulkan_dispatch_from_device(ivk, sVkEmulation->device, sVkEmulation->dvk);
1131 
1132     auto dvk = sVkEmulation->dvk;
1133 
1134     // Check if the dispatch table has everything 1.1 related
1135     if (!vulkan_dispatch_check_device_VK_VERSION_1_0(dvk)) {
1136         VK_COMMON_ERROR("Warning: Vulkan 1.0 APIs missing from device.");
1137     }
1138     if (deviceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
1139         if (!vulkan_dispatch_check_device_VK_VERSION_1_1(dvk)) {
1140             VK_COMMON_ERROR("Warning: Vulkan 1.1 APIs missing from device");
1141         }
1142     }
1143 
1144     if (sVkEmulation->deviceInfo.supportsExternalMemoryImport) {
1145         sVkEmulation->deviceInfo.getImageMemoryRequirements2Func =
1146             reinterpret_cast<PFN_vkGetImageMemoryRequirements2KHR>(
1147                 dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetImageMemoryRequirements2KHR"));
1148         if (!sVkEmulation->deviceInfo.getImageMemoryRequirements2Func) {
1149             VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1150                                                  "Cannot find vkGetImageMemoryRequirements2KHR.");
1151         }
1152         sVkEmulation->deviceInfo.getBufferMemoryRequirements2Func =
1153             reinterpret_cast<PFN_vkGetBufferMemoryRequirements2KHR>(dvk->vkGetDeviceProcAddr(
1154                 sVkEmulation->device, "vkGetBufferMemoryRequirements2KHR"));
1155         if (!sVkEmulation->deviceInfo.getBufferMemoryRequirements2Func) {
1156             VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1157                                                  "Cannot find vkGetBufferMemoryRequirements2KHR");
1158         }
1159     }
1160     if (sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
1161 #ifdef _WIN32
1162         sVkEmulation->deviceInfo.getMemoryHandleFunc =
1163             reinterpret_cast<PFN_vkGetMemoryWin32HandleKHR>(
1164                 dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetMemoryWin32HandleKHR"));
1165 #else
1166         sVkEmulation->deviceInfo.getMemoryHandleFunc = reinterpret_cast<PFN_vkGetMemoryFdKHR>(
1167             dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetMemoryFdKHR"));
1168 #endif
1169         if (!sVkEmulation->deviceInfo.getMemoryHandleFunc) {
1170             VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1171                                                  "Cannot find vkGetMemory(Fd|Win32Handle)KHR");
1172         }
1173     }
1174 
1175     VK_COMMON_VERBOSE("Vulkan logical device created and extension functions obtained.");
1176 
1177     sVkEmulation->queueLock = std::make_shared<android::base::Lock>();
1178     {
1179         android::base::AutoLock lock(*sVkEmulation->queueLock);
1180         dvk->vkGetDeviceQueue(sVkEmulation->device,
1181                               sVkEmulation->deviceInfo.graphicsQueueFamilyIndices[0], 0,
1182                               &sVkEmulation->queue);
1183     }
1184 
1185     sVkEmulation->queueFamilyIndex = sVkEmulation->deviceInfo.graphicsQueueFamilyIndices[0];
1186 
1187     VK_COMMON_VERBOSE("Vulkan device queue obtained.");
1188 
1189     VkCommandPoolCreateInfo poolCi = {
1190         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1191         0,
1192         VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1193         sVkEmulation->queueFamilyIndex,
1194     };
1195 
1196     VkResult poolCreateRes = dvk->vkCreateCommandPool(sVkEmulation->device, &poolCi, nullptr,
1197                                                       &sVkEmulation->commandPool);
1198 
1199     if (poolCreateRes != VK_SUCCESS) {
1200         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(poolCreateRes,
1201                                              "Failed to create command pool. Error: %s.",
1202                                              string_VkResult(poolCreateRes));
1203     }
1204 
1205     VkCommandBufferAllocateInfo cbAi = {
1206         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1207         0,
1208         sVkEmulation->commandPool,
1209         VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1210         1,
1211     };
1212 
1213     VkResult cbAllocRes =
1214         dvk->vkAllocateCommandBuffers(sVkEmulation->device, &cbAi, &sVkEmulation->commandBuffer);
1215 
1216     if (cbAllocRes != VK_SUCCESS) {
1217         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(cbAllocRes,
1218                                              "Failed to allocate command buffer. Error: %s.",
1219                                              string_VkResult(cbAllocRes));
1220     }
1221 
1222     VkFenceCreateInfo fenceCi = {
1223         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1224         0,
1225         0,
1226     };
1227 
1228     VkResult fenceCreateRes = dvk->vkCreateFence(sVkEmulation->device, &fenceCi, nullptr,
1229                                                  &sVkEmulation->commandBufferFence);
1230 
1231     if (fenceCreateRes != VK_SUCCESS) {
1232         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
1233             fenceCreateRes, "Failed to create fence for command buffer. Error: %s.",
1234             string_VkResult(fenceCreateRes));
1235     }
1236 
1237     // At this point, the global emulation state's logical device can alloc
1238     // memory and send commands. However, it can't really do much yet to
1239     // communicate the results without the staging buffer. Set that up here.
1240     // Note that the staging buffer is meant to use external memory, with a
1241     // non-external-memory fallback.
1242 
1243     VkBufferCreateInfo bufCi = {
1244         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1245         0,
1246         0,
1247         sVkEmulation->staging.size,
1248         VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
1249         VK_SHARING_MODE_EXCLUSIVE,
1250         0,
1251         nullptr,
1252     };
1253 
1254     VkResult bufCreateRes =
1255         dvk->vkCreateBuffer(sVkEmulation->device, &bufCi, nullptr, &sVkEmulation->staging.buffer);
1256 
1257     if (bufCreateRes != VK_SUCCESS) {
1258         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(bufCreateRes,
1259                                              "Failed to create staging buffer index. Error: %s.",
1260                                              string_VkResult(bufCreateRes));
1261     }
1262 
1263     VkMemoryRequirements memReqs;
1264     dvk->vkGetBufferMemoryRequirements(sVkEmulation->device, sVkEmulation->staging.buffer,
1265                                        &memReqs);
1266 
1267     sVkEmulation->staging.memory.size = memReqs.size;
1268 
1269     bool gotStagingTypeIndex =
1270         getStagingMemoryTypeIndex(dvk, sVkEmulation->device, &sVkEmulation->deviceInfo.memProps,
1271                                   &sVkEmulation->staging.memory.typeIndex);
1272 
1273     if (!gotStagingTypeIndex) {
1274         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1275                                              "Failed to determine staging memory type index.");
1276     }
1277 
1278     if (!((1 << sVkEmulation->staging.memory.typeIndex) & memReqs.memoryTypeBits)) {
1279         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
1280             ABORT_REASON_OTHER,
1281             "Failed: Inconsistent determination of memory type index for staging buffer");
1282     }
1283 
1284     if (!allocExternalMemory(dvk, &sVkEmulation->staging.memory, false /* not external */,
1285                              kNullopt /* deviceAlignment */)) {
1286         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1287                                              "Failed to allocate memory for staging buffer.");
1288     }
1289 
1290     VkResult stagingBufferBindRes = dvk->vkBindBufferMemory(
1291         sVkEmulation->device, sVkEmulation->staging.buffer, sVkEmulation->staging.memory.memory, 0);
1292 
1293     if (stagingBufferBindRes != VK_SUCCESS) {
1294         VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(stagingBufferBindRes,
1295                                              "Failed to bind memory for staging buffer. Error %s.",
1296                                              string_VkResult(stagingBufferBindRes));
1297     }
1298 
1299     sVkEmulation->debugUtilsAvailableAndRequested = debugUtilsAvailableAndRequested;
1300     if (sVkEmulation->debugUtilsAvailableAndRequested) {
1301         sVkEmulation->debugUtilsHelper =
1302             DebugUtilsHelper::withUtilsEnabled(sVkEmulation->device, sVkEmulation->ivk);
1303     }
1304 
1305     VK_COMMON_VERBOSE("Vulkan global emulation state successfully initialized.");
1306     sVkEmulation->live = true;
1307 
1308     sVkEmulation->transferQueueCommandBufferPool.resize(0);
1309 
1310     return sVkEmulation;
1311 }
1312 
1313 std::optional<VkEmulation::RepresentativeColorBufferMemoryTypeInfo>
1314 findRepresentativeColorBufferMemoryTypeIndexLocked();
1315 
initVkEmulationFeatures(std::unique_ptr<VkEmulationFeatures> features)1316 void initVkEmulationFeatures(std::unique_ptr<VkEmulationFeatures> features) {
1317     if (!sVkEmulation || !sVkEmulation->live) {
1318         ERR("VkEmulation is either not initialized or destroyed.");
1319         return;
1320     }
1321 
1322     AutoLock lock(sVkEmulationLock);
1323     INFO("Initializing VkEmulation features:");
1324     INFO("    glInteropSupported: %s", features->glInteropSupported ? "true" : "false");
1325     INFO("    useDeferredCommands: %s", features->deferredCommands ? "true" : "false");
1326     INFO("    createResourceWithRequirements: %s",
1327          features->createResourceWithRequirements ? "true" : "false");
1328     INFO("    useVulkanComposition: %s", features->useVulkanComposition ? "true" : "false");
1329     INFO("    useVulkanNativeSwapchain: %s", features->useVulkanNativeSwapchain ? "true" : "false");
1330     INFO("    enable guestRenderDoc: %s", features->guestRenderDoc ? "true" : "false");
1331     INFO("    ASTC LDR emulation mode: %d", features->astcLdrEmulationMode);
1332     INFO("    enable ETC2 emulation: %s", features->enableEtc2Emulation ? "true" : "false");
1333     INFO("    enable Ycbcr emulation: %s", features->enableYcbcrEmulation ? "true" : "false");
1334     INFO("    guestUsesAngle: %s", features->guestUsesAngle ? "true" : "false");
1335     INFO("    useDedicatedAllocations: %s", features->useDedicatedAllocations ? "true" : "false");
1336     sVkEmulation->deviceInfo.glInteropSupported = features->glInteropSupported;
1337     sVkEmulation->useDeferredCommands = features->deferredCommands;
1338     sVkEmulation->useCreateResourcesWithRequirements = features->createResourceWithRequirements;
1339     sVkEmulation->guestRenderDoc = std::move(features->guestRenderDoc);
1340     sVkEmulation->astcLdrEmulationMode = features->astcLdrEmulationMode;
1341     sVkEmulation->enableEtc2Emulation = features->enableEtc2Emulation;
1342     sVkEmulation->enableYcbcrEmulation = features->enableYcbcrEmulation;
1343     sVkEmulation->guestUsesAngle = features->guestUsesAngle;
1344     sVkEmulation->useDedicatedAllocations = features->useDedicatedAllocations;
1345 
1346     if (features->useVulkanComposition) {
1347         if (sVkEmulation->compositorVk) {
1348             ERR("Reset VkEmulation::compositorVk.");
1349         }
1350         sVkEmulation->compositorVk =
1351             CompositorVk::create(*sVkEmulation->ivk, sVkEmulation->device, sVkEmulation->physdev,
1352                                  sVkEmulation->queue, sVkEmulation->queueLock,
1353                                  sVkEmulation->queueFamilyIndex, 3, sVkEmulation->debugUtilsHelper);
1354     }
1355 
1356     if (features->useVulkanNativeSwapchain) {
1357         if (sVkEmulation->displayVk) {
1358             ERR("Reset VkEmulation::displayVk.");
1359         }
1360         sVkEmulation->displayVk = std::make_unique<DisplayVk>(
1361             *sVkEmulation->ivk, sVkEmulation->physdev, sVkEmulation->queueFamilyIndex,
1362             sVkEmulation->queueFamilyIndex, sVkEmulation->device, sVkEmulation->queue,
1363             sVkEmulation->queueLock, sVkEmulation->queue, sVkEmulation->queueLock);
1364     }
1365 
1366     sVkEmulation->representativeColorBufferMemoryTypeInfo =
1367         findRepresentativeColorBufferMemoryTypeIndexLocked();
1368     if (sVkEmulation->representativeColorBufferMemoryTypeInfo) {
1369         VK_COMMON_VERBOSE(
1370             "Representative ColorBuffer memory type using host memory type index %d "
1371             "and guest memory type index :%d",
1372             sVkEmulation->representativeColorBufferMemoryTypeInfo->hostMemoryTypeIndex,
1373             sVkEmulation->representativeColorBufferMemoryTypeInfo->guestMemoryTypeIndex);
1374     } else {
1375         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1376             << "Failed to find memory type for ColorBuffers.";
1377     }
1378 }
1379 
getGlobalVkEmulation()1380 VkEmulation* getGlobalVkEmulation() {
1381     if (sVkEmulation && !sVkEmulation->live) return nullptr;
1382     return sVkEmulation;
1383 }
1384 
teardownGlobalVkEmulation()1385 void teardownGlobalVkEmulation() {
1386     if (!sVkEmulation) return;
1387 
1388     // Don't try to tear down something that did not set up completely; too risky
1389     if (!sVkEmulation->live) return;
1390 
1391     sVkEmulation->compositorVk.reset();
1392     sVkEmulation->displayVk.reset();
1393 
1394     freeExternalMemoryLocked(sVkEmulation->dvk, &sVkEmulation->staging.memory);
1395 
1396     sVkEmulation->dvk->vkDestroyBuffer(sVkEmulation->device, sVkEmulation->staging.buffer, nullptr);
1397 
1398     sVkEmulation->dvk->vkDestroyFence(sVkEmulation->device, sVkEmulation->commandBufferFence,
1399                                       nullptr);
1400 
1401     sVkEmulation->dvk->vkFreeCommandBuffers(sVkEmulation->device, sVkEmulation->commandPool, 1,
1402                                             &sVkEmulation->commandBuffer);
1403 
1404     sVkEmulation->dvk->vkDestroyCommandPool(sVkEmulation->device, sVkEmulation->commandPool,
1405                                             nullptr);
1406 
1407     sVkEmulation->ivk->vkDestroyDevice(sVkEmulation->device, nullptr);
1408     sVkEmulation->gvk->vkDestroyInstance(sVkEmulation->instance, nullptr);
1409 
1410     VkDecoderGlobalState::reset();
1411 
1412     sVkEmulation->live = false;
1413     delete sVkEmulation;
1414     sVkEmulation = nullptr;
1415 }
1416 
createDisplaySurface(FBNativeWindowType window,uint32_t width,uint32_t height)1417 std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window,
1418                                                                 uint32_t width, uint32_t height) {
1419     if (!sVkEmulation || !sVkEmulation->live) {
1420         return nullptr;
1421     }
1422 
1423     auto surfaceVk = DisplaySurfaceVk::create(*sVkEmulation->ivk, sVkEmulation->instance, window);
1424     if (!surfaceVk) {
1425         VK_COMMON_ERROR("Failed to create DisplaySurfaceVk.");
1426         return nullptr;
1427     }
1428 
1429     return std::make_unique<gfxstream::DisplaySurface>(width, height, std::move(surfaceVk));
1430 }
1431 
1432 // Precondition: sVkEmulation has valid device support info
allocExternalMemory(VulkanDispatch * vk,VkEmulation::ExternalMemoryInfo * info,bool actuallyExternal,Optional<uint64_t> deviceAlignment,Optional<VkBuffer> bufferForDedicatedAllocation,Optional<VkImage> imageForDedicatedAllocation)1433 bool allocExternalMemory(VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info,
1434                          bool actuallyExternal, Optional<uint64_t> deviceAlignment,
1435                          Optional<VkBuffer> bufferForDedicatedAllocation,
1436                          Optional<VkImage> imageForDedicatedAllocation) {
1437     VkExportMemoryAllocateInfo exportAi = {
1438         .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
1439         .pNext = nullptr,
1440         .handleTypes = VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1441     };
1442 
1443     VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {
1444         .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1445         .pNext = nullptr,
1446         .image = VK_NULL_HANDLE,
1447         .buffer = VK_NULL_HANDLE,
1448     };
1449 
1450     VkMemoryAllocateInfo allocInfo = {
1451         .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1452         .pNext = nullptr,
1453         .allocationSize = info->size,
1454         .memoryTypeIndex = info->typeIndex,
1455     };
1456 
1457     auto allocInfoChain = vk_make_chain_iterator(&allocInfo);
1458 
1459     if (sVkEmulation->deviceInfo.supportsExternalMemoryExport && actuallyExternal) {
1460         vk_append_struct(&allocInfoChain, &exportAi);
1461     }
1462 
1463     if (bufferForDedicatedAllocation.hasValue() || imageForDedicatedAllocation.hasValue()) {
1464         info->dedicatedAllocation = true;
1465         if (bufferForDedicatedAllocation.hasValue()) {
1466             dedicatedAllocInfo.buffer = *bufferForDedicatedAllocation;
1467         }
1468         if (imageForDedicatedAllocation.hasValue()) {
1469             dedicatedAllocInfo.image = *imageForDedicatedAllocation;
1470         }
1471         vk_append_struct(&allocInfoChain, &dedicatedAllocInfo);
1472     }
1473 
1474     bool memoryAllocated = false;
1475     std::vector<VkDeviceMemory> allocationAttempts;
1476     constexpr size_t kMaxAllocationAttempts = 20u;
1477 
1478     while (!memoryAllocated) {
1479         VkResult allocRes =
1480             vk->vkAllocateMemory(sVkEmulation->device, &allocInfo, nullptr, &info->memory);
1481 
1482         if (allocRes != VK_SUCCESS) {
1483             VK_COMMON_VERBOSE("allocExternalMemory: failed in vkAllocateMemory: %s", string_VkResult(allocRes));
1484             break;
1485         }
1486 
1487         if (sVkEmulation->deviceInfo.memProps.memoryTypes[info->typeIndex].propertyFlags &
1488             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1489             VkResult mapRes = vk->vkMapMemory(sVkEmulation->device, info->memory, 0, info->size, 0,
1490                                               &info->mappedPtr);
1491             if (mapRes != VK_SUCCESS) {
1492                 VK_COMMON_VERBOSE("allocExternalMemory: failed in vkMapMemory: %s", string_VkResult(mapRes));
1493                 break;
1494             }
1495         }
1496 
1497         uint64_t mappedPtrPageOffset = reinterpret_cast<uint64_t>(info->mappedPtr) % kPageSize;
1498 
1499         if (  // don't care about alignment (e.g. device-local memory)
1500             !deviceAlignment.hasValue() ||
1501             // If device has an alignment requirement larger than current
1502             // host pointer alignment (i.e. the lowest 1 bit of mappedPtr),
1503             // the only possible way to make mappedPtr valid is to ensure
1504             // that it is already aligned to page.
1505             mappedPtrPageOffset == 0u ||
1506             // If device has an alignment requirement smaller or equals to
1507             // current host pointer alignment, clients can set a offset
1508             // |kPageSize - mappedPtrPageOffset| in vkBindImageMemory to
1509             // make it aligned to page and compatible with device
1510             // requirements.
1511             (kPageSize - mappedPtrPageOffset) % deviceAlignment.value() == 0) {
1512             // allocation success.
1513             memoryAllocated = true;
1514         } else {
1515             allocationAttempts.push_back(info->memory);
1516 
1517             VK_COMMON_VERBOSE("allocExternalMemory: attempt #%zu failed; deviceAlignment: %" PRIu64  ", mappedPtrPageOffset: %" PRIu64,
1518                                 allocationAttempts.size(), deviceAlignment.valueOr(0), mappedPtrPageOffset);
1519 
1520             if (allocationAttempts.size() >= kMaxAllocationAttempts) {
1521                 VK_COMMON_VERBOSE("allocExternalMemory: unable to allocate memory with CPU mapped ptr aligned to page");
1522                 break;
1523             }
1524         }
1525     }
1526 
1527     // clean up previous failed attempts
1528     for (const auto& mem : allocationAttempts) {
1529         vk->vkFreeMemory(sVkEmulation->device, mem, nullptr /* allocator */);
1530     }
1531     if (!memoryAllocated) {
1532         return false;
1533     }
1534 
1535     if (!sVkEmulation->deviceInfo.supportsExternalMemoryExport || !actuallyExternal) {
1536         return true;
1537     }
1538 
1539     VkResult exportRes = VK_SUCCESS;
1540 #ifdef _WIN32
1541     VkMemoryGetWin32HandleInfoKHR getWin32HandleInfo = {
1542         VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
1543         0,
1544         info->memory,
1545         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1546     };
1547     exportRes = sVkEmulation->deviceInfo.getMemoryHandleFunc(
1548         sVkEmulation->device, &getWin32HandleInfo, &info->externalHandle);
1549 #elif !defined(__QNX__)
1550     VkMemoryGetFdInfoKHR getFdInfo = {
1551         VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
1552         0,
1553         info->memory,
1554         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1555     };
1556     exportRes = sVkEmulation->deviceInfo.getMemoryHandleFunc(sVkEmulation->device, &getFdInfo,
1557                                                              &info->externalHandle);
1558 #endif
1559 
1560     if (exportRes != VK_SUCCESS || VK_EXT_MEMORY_HANDLE_INVALID == info->externalHandle) {
1561         VK_COMMON_VERBOSE("allocExternalMemory: Failed to get external memory, native handle: %s", string_VkResult(exportRes));
1562         return false;
1563     }
1564 
1565     return true;
1566 }
1567 
freeExternalMemoryLocked(VulkanDispatch * vk,VkEmulation::ExternalMemoryInfo * info)1568 void freeExternalMemoryLocked(VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info) {
1569     if (!info->memory) return;
1570 
1571     if (sVkEmulation->deviceInfo.memProps.memoryTypes[info->typeIndex].propertyFlags &
1572         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
1573         if (sVkEmulation->occupiedGpas.find(info->gpa) != sVkEmulation->occupiedGpas.end()) {
1574             sVkEmulation->occupiedGpas.erase(info->gpa);
1575             get_emugl_vm_operations().unmapUserBackedRam(info->gpa, info->sizeToPage);
1576             info->gpa = 0u;
1577         }
1578 
1579         if (info->mappedPtr != nullptr) {
1580             vk->vkUnmapMemory(sVkEmulation->device, info->memory);
1581             info->mappedPtr = nullptr;
1582             info->pageAlignedHva = nullptr;
1583         }
1584     }
1585 
1586     vk->vkFreeMemory(sVkEmulation->device, info->memory, nullptr);
1587 
1588     info->memory = VK_NULL_HANDLE;
1589 
1590     if (info->externalHandle != VK_EXT_MEMORY_HANDLE_INVALID) {
1591 #ifdef _WIN32
1592         CloseHandle(info->externalHandle);
1593 #elif !defined(__QNX__)
1594         close(info->externalHandle);
1595 #endif
1596         info->externalHandle = VK_EXT_MEMORY_HANDLE_INVALID;
1597     }
1598 }
1599 
importExternalMemory(VulkanDispatch * vk,VkDevice targetDevice,const VkEmulation::ExternalMemoryInfo * info,VkDeviceMemory * out)1600 bool importExternalMemory(VulkanDispatch* vk, VkDevice targetDevice,
1601                           const VkEmulation::ExternalMemoryInfo* info, VkDeviceMemory* out) {
1602 #ifdef _WIN32
1603     VkImportMemoryWin32HandleInfoKHR importInfo = {
1604         VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
1605         0,
1606         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1607         info->externalHandle,
1608         0,
1609     };
1610 #elif defined(__QNX__)
1611     VkImportScreenBufferInfoQNX importInfo = {
1612         VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX,
1613         NULL,
1614         info->externalHandle,
1615     };
1616 #else
1617     VkImportMemoryFdInfoKHR importInfo = {
1618         VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
1619         0,
1620         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1621         dupExternalMemory(info->externalHandle),
1622     };
1623 #endif
1624     VkMemoryAllocateInfo allocInfo = {
1625         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1626         &importInfo,
1627         info->size,
1628         info->typeIndex,
1629     };
1630 
1631     VkResult res = vk->vkAllocateMemory(targetDevice, &allocInfo, nullptr, out);
1632 
1633     if (res != VK_SUCCESS) {
1634         VK_COMMON_ERROR("importExternalMemory: Failed with %s", string_VkResult(res));
1635         return false;
1636     }
1637 
1638     return true;
1639 }
1640 
importExternalMemoryDedicatedImage(VulkanDispatch * vk,VkDevice targetDevice,const VkEmulation::ExternalMemoryInfo * info,VkImage image,VkDeviceMemory * out)1641 bool importExternalMemoryDedicatedImage(VulkanDispatch* vk, VkDevice targetDevice,
1642                                         const VkEmulation::ExternalMemoryInfo* info, VkImage image,
1643                                         VkDeviceMemory* out) {
1644     VkMemoryDedicatedAllocateInfo dedicatedInfo = {
1645         VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1646         0,
1647         image,
1648         VK_NULL_HANDLE,
1649     };
1650 
1651 #ifdef _WIN32
1652     VkImportMemoryWin32HandleInfoKHR importInfo = {
1653         VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
1654         &dedicatedInfo,
1655         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1656         info->externalHandle,
1657         0,
1658     };
1659 #elif defined(__QNX__)
1660     VkImportScreenBufferInfoQNX importInfo = {
1661         VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX,
1662         &dedicatedInfo,
1663         info->externalHandle,
1664     };
1665 #else
1666     VkImportMemoryFdInfoKHR importInfo = {
1667         VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
1668         &dedicatedInfo,
1669         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1670         dupExternalMemory(info->externalHandle),
1671     };
1672 #endif
1673     VkMemoryAllocateInfo allocInfo = {
1674         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1675         &importInfo,
1676         info->size,
1677         info->typeIndex,
1678     };
1679 
1680     VkResult res = vk->vkAllocateMemory(targetDevice, &allocInfo, nullptr, out);
1681 
1682     if (res != VK_SUCCESS) {
1683         VK_COMMON_ERROR("importExternalMemoryDedicatedImage: Failed with %s", string_VkResult(res));
1684         return false;
1685     }
1686 
1687     return true;
1688 }
1689 
1690 // From ANGLE "src/common/angleutils.h"
1691 #define GL_BGR10_A2_ANGLEX 0x6AF9
1692 
glFormat2VkFormat(GLint internalFormat)1693 static VkFormat glFormat2VkFormat(GLint internalFormat) {
1694     switch (internalFormat) {
1695         case GL_R8:
1696         case GL_LUMINANCE:
1697             return VK_FORMAT_R8_UNORM;
1698         case GL_RGB:
1699         case GL_RGB8:
1700             // b/281550953
1701             // RGB8 is not supported on many vulkan drivers.
1702             // Try RGBA8 instead.
1703             // Note: copyImageData() performs channel conversion for this case.
1704             return VK_FORMAT_R8G8B8A8_UNORM;
1705         case GL_RGB565:
1706             return VK_FORMAT_R5G6B5_UNORM_PACK16;
1707         case GL_RGB16F:
1708             return VK_FORMAT_R16G16B16_SFLOAT;
1709         case GL_RGBA:
1710         case GL_RGBA8:
1711             return VK_FORMAT_R8G8B8A8_UNORM;
1712         case GL_RGB5_A1_OES:
1713             return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
1714         case GL_RGBA4_OES:
1715             return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
1716         case GL_RGB10_A2:
1717         case GL_UNSIGNED_INT_10_10_10_2_OES:
1718             return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
1719         case GL_BGR10_A2_ANGLEX:
1720             return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
1721         case GL_RGBA16F:
1722             return VK_FORMAT_R16G16B16A16_SFLOAT;
1723         case GL_BGRA_EXT:
1724         case GL_BGRA8_EXT:
1725             return VK_FORMAT_B8G8R8A8_UNORM;
1726         case GL_R16_EXT:
1727             return VK_FORMAT_R16_UNORM;
1728         case GL_RG8_EXT:
1729             return VK_FORMAT_R8G8_UNORM;
1730         default:
1731             VK_COMMON_ERROR("Unhandled format %d, falling back to VK_FORMAT_R8G8B8A8_UNORM",
1732                             internalFormat);
1733             return VK_FORMAT_R8G8B8A8_UNORM;
1734     }
1735 };
1736 
isFormatVulkanCompatible(GLenum internalFormat)1737 static bool isFormatVulkanCompatible(GLenum internalFormat) {
1738     VkFormat vkFormat = glFormat2VkFormat(internalFormat);
1739 
1740     for (const auto& supportInfo : sVkEmulation->imageSupportInfo) {
1741         if (supportInfo.format == vkFormat && supportInfo.supported) {
1742             return true;
1743         }
1744     }
1745 
1746     return false;
1747 }
1748 
getColorBufferShareInfo(uint32_t colorBufferHandle,bool * glExported,bool * externalMemoryCompatible)1749 bool getColorBufferShareInfo(uint32_t colorBufferHandle, bool* glExported,
1750                              bool* externalMemoryCompatible) {
1751     if (!sVkEmulation || !sVkEmulation->live) {
1752         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
1753     }
1754 
1755     AutoLock lock(sVkEmulationLock);
1756 
1757     auto info = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
1758     if (!info) {
1759         return false;
1760     }
1761 
1762     *glExported = info->glExported;
1763     *externalMemoryCompatible = info->externalMemoryCompatible;
1764     return true;
1765 }
1766 
getColorBufferAllocationInfoLocked(uint32_t colorBufferHandle,VkDeviceSize * outSize,uint32_t * outMemoryTypeIndex,bool * outMemoryIsDedicatedAlloc,void ** outMappedPtr)1767 bool getColorBufferAllocationInfoLocked(uint32_t colorBufferHandle, VkDeviceSize* outSize,
1768                                         uint32_t* outMemoryTypeIndex,
1769                                         bool* outMemoryIsDedicatedAlloc, void** outMappedPtr) {
1770     auto info = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
1771     if (!info) {
1772         return false;
1773     }
1774 
1775     if (outSize) {
1776         *outSize = info->memory.size;
1777     }
1778 
1779     if (outMemoryTypeIndex) {
1780         *outMemoryTypeIndex = info->memory.typeIndex;
1781     }
1782 
1783     if (outMemoryIsDedicatedAlloc) {
1784         *outMemoryIsDedicatedAlloc = info->memory.dedicatedAllocation;
1785     }
1786 
1787     if (outMappedPtr) {
1788         *outMappedPtr = info->memory.mappedPtr;
1789     }
1790 
1791     return true;
1792 }
1793 
getColorBufferAllocationInfo(uint32_t colorBufferHandle,VkDeviceSize * outSize,uint32_t * outMemoryTypeIndex,bool * outMemoryIsDedicatedAlloc,void ** outMappedPtr)1794 bool getColorBufferAllocationInfo(uint32_t colorBufferHandle, VkDeviceSize* outSize,
1795                                   uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc,
1796                                   void** outMappedPtr) {
1797     if (!sVkEmulation || !sVkEmulation->live) {
1798         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
1799     }
1800 
1801     AutoLock lock(sVkEmulationLock);
1802     return getColorBufferAllocationInfoLocked(colorBufferHandle, outSize, outMemoryTypeIndex,
1803                                               outMemoryIsDedicatedAlloc, outMappedPtr);
1804 }
1805 
lastGoodTypeIndex(uint32_t indices)1806 static uint32_t lastGoodTypeIndex(uint32_t indices) {
1807     for (int32_t i = 31; i >= 0; --i) {
1808         if (indices & (1 << i)) {
1809             return i;
1810         }
1811     }
1812     return 0;
1813 }
1814 
lastGoodTypeIndexWithMemoryProperties(uint32_t indices,VkMemoryPropertyFlags memoryProperty)1815 static uint32_t lastGoodTypeIndexWithMemoryProperties(uint32_t indices,
1816                                                       VkMemoryPropertyFlags memoryProperty) {
1817     for (int32_t i = 31; i >= 0; --i) {
1818         if ((indices & (1u << i)) &&
1819             (!memoryProperty ||
1820              (sVkEmulation->deviceInfo.memProps.memoryTypes[i].propertyFlags & memoryProperty))) {
1821             return i;
1822         }
1823     }
1824     return 0;
1825 }
1826 
1827 // pNext, sharingMode, queueFamilyIndexCount, pQueueFamilyIndices, and initialLayout won't be
1828 // filled.
generateColorBufferVkImageCreateInfo_locked(VkFormat format,uint32_t width,uint32_t height,VkImageTiling tiling)1829 static std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo_locked(
1830     VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling) {
1831     const VkEmulation::ImageSupportInfo* maybeImageSupportInfo = nullptr;
1832     for (const auto& supportInfo : sVkEmulation->imageSupportInfo) {
1833         if (supportInfo.format == format && supportInfo.supported) {
1834             maybeImageSupportInfo = &supportInfo;
1835             break;
1836         }
1837     }
1838     if (!maybeImageSupportInfo) {
1839         ERR("Format %s is not supported.", string_VkFormat(format));
1840         return nullptr;
1841     }
1842     const VkEmulation::ImageSupportInfo& imageSupportInfo = *maybeImageSupportInfo;
1843     const VkFormatProperties& formatProperties = imageSupportInfo.formatProps2.formatProperties;
1844 
1845     constexpr std::pair<VkFormatFeatureFlags, VkImageUsageFlags> formatUsagePairs[] = {
1846         {VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
1847          VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT},
1848         {VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, VK_IMAGE_USAGE_SAMPLED_BIT},
1849         {VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT},
1850         {VK_FORMAT_FEATURE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT},
1851         {VK_FORMAT_FEATURE_BLIT_SRC_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT},
1852     };
1853     VkFormatFeatureFlags tilingFeatures = (tiling == VK_IMAGE_TILING_OPTIMAL)
1854                                               ? formatProperties.optimalTilingFeatures
1855                                               : formatProperties.linearTilingFeatures;
1856 
1857     VkImageUsageFlags usage = 0;
1858     for (const auto& formatUsage : formatUsagePairs) {
1859         usage |= (tilingFeatures & formatUsage.first) ? formatUsage.second : 0u;
1860     }
1861 
1862     return std::make_unique<VkImageCreateInfo>(VkImageCreateInfo{
1863         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1864         // The caller is responsible to fill pNext.
1865         .pNext = nullptr,
1866         .flags = imageSupportInfo.createFlags,
1867         .imageType = VK_IMAGE_TYPE_2D,
1868         .format = format,
1869         .extent =
1870             {
1871                 .width = width,
1872                 .height = height,
1873                 .depth = 1,
1874             },
1875         .mipLevels = 1,
1876         .arrayLayers = 1,
1877         .samples = VK_SAMPLE_COUNT_1_BIT,
1878         .tiling = tiling,
1879         .usage = usage,
1880         // The caller is responsible to fill sharingMode.
1881         .sharingMode = VK_SHARING_MODE_MAX_ENUM,
1882         // The caller is responsible to fill queueFamilyIndexCount.
1883         .queueFamilyIndexCount = 0,
1884         // The caller is responsible to fill pQueueFamilyIndices.
1885         .pQueueFamilyIndices = nullptr,
1886         // The caller is responsible to fill initialLayout.
1887         .initialLayout = VK_IMAGE_LAYOUT_MAX_ENUM,
1888     });
1889 }
1890 
generateColorBufferVkImageCreateInfo(VkFormat format,uint32_t width,uint32_t height,VkImageTiling tiling)1891 std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo(VkFormat format,
1892                                                                         uint32_t width,
1893                                                                         uint32_t height,
1894                                                                         VkImageTiling tiling) {
1895     if (!sVkEmulation || !sVkEmulation->live) {
1896         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
1897     }
1898     AutoLock lock(sVkEmulationLock);
1899     return generateColorBufferVkImageCreateInfo_locked(format, width, height, tiling);
1900 }
1901 
updateExternalMemoryInfo(VK_EXT_MEMORY_HANDLE extMemHandle,const VkMemoryRequirements * pMemReqs,VkEmulation::ExternalMemoryInfo * pInfo)1902 static bool updateExternalMemoryInfo(VK_EXT_MEMORY_HANDLE extMemHandle,
1903                                      const VkMemoryRequirements* pMemReqs,
1904                                      VkEmulation::ExternalMemoryInfo* pInfo) {
1905     // Set externalHandle on the output info
1906     pInfo->externalHandle = extMemHandle;
1907     pInfo->dedicatedAllocation = true;
1908 
1909 #if defined(__QNX__)
1910     VkScreenBufferPropertiesQNX screenBufferProps = {
1911         VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX,
1912         0,
1913     };
1914     auto vk = sVkEmulation->dvk;
1915     VkResult queryRes =
1916         vk->vkGetScreenBufferPropertiesQNX(sVkEmulation->device, extMemHandle, &screenBufferProps);
1917     if (VK_SUCCESS != queryRes) {
1918         VK_COMMON_ERROR("Failed to get QNX Screen Buffer properties, VK error: %s", string_VkResult(queryRes));
1919         return false;
1920     }
1921     if (!((1 << pInfo->typeIndex) & screenBufferProps.memoryTypeBits)) {
1922         VK_COMMON_ERROR("QNX Screen buffer can not be imported to memory (typeIndex=%d): %d",
1923                         pInfo->typeIndex);
1924         return false;
1925     }
1926     if (screenBufferProps.allocationSize < pMemReqs->size) {
1927         VK_COMMON_ERROR(
1928             "QNX Screen buffer allocationSize (0x%lx) is not large enough for ColorBuffer image "
1929             "size requirements (0x%lx)",
1930             screenBufferProps.allocationSize, pMemReqs->size);
1931         return false;
1932     }
1933     // Use the actual allocationSize for VkDeviceMemory object creation
1934     pInfo->size = screenBufferProps.allocationSize;
1935 #endif
1936 
1937     return true;
1938 }
1939 
1940 // TODO(liyl): Currently we can only specify required memoryProperty
1941 // and initial layout for a color buffer.
1942 //
1943 // Ideally we would like to specify a memory type index directly from
1944 // localAllocInfo.memoryTypeIndex when allocating color buffers in
1945 // vkAllocateMemory(). But this type index mechanism breaks "Modify the
1946 // allocation size and type index to suit the resulting image memory
1947 // size." which seems to be needed to keep the Android/Fuchsia guest
1948 // memory type index consistent across guest allocations, and without
1949 // which those guests might end up import allocating from a color buffer
1950 // with mismatched type indices.
1951 //
1952 // We should make it so the guest can only allocate external images/
1953 // buffers of one type index for image and one type index for buffer
1954 // to begin with, via filtering from the host.
1955 
initializeVkColorBufferLocked(uint32_t colorBufferHandle,VK_EXT_MEMORY_HANDLE extMemHandle=VK_EXT_MEMORY_HANDLE_INVALID)1956 bool initializeVkColorBufferLocked(
1957     uint32_t colorBufferHandle, VK_EXT_MEMORY_HANDLE extMemHandle = VK_EXT_MEMORY_HANDLE_INVALID) {
1958     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
1959     // Not initialized
1960     if (!infoPtr) {
1961         return false;
1962     }
1963     // Already initialized Vulkan memory and other related Vulkan objects
1964     if (infoPtr->initialized) {
1965         return true;
1966     }
1967 
1968     if (!isFormatVulkanCompatible(infoPtr->internalFormat)) {
1969         VK_COMMON_VERBOSE("Failed to create Vk ColorBuffer: format:%d not compatible.",
1970                           infoPtr->internalFormat);
1971         return false;
1972     }
1973 
1974     const bool extMemImport = (VK_EXT_MEMORY_HANDLE_INVALID != extMemHandle);
1975     if (extMemImport && !sVkEmulation->deviceInfo.supportsExternalMemoryImport) {
1976         VK_COMMON_ERROR(
1977             "Failed to initialize Vk ColorBuffer -- extMemHandle provided, but device does "
1978             "not support externalMemoryImport");
1979         return false;
1980     }
1981 
1982     VkFormat vkFormat;
1983     bool glCompatible = (infoPtr->frameworkFormat == FRAMEWORK_FORMAT_GL_COMPATIBLE);
1984     switch (infoPtr->frameworkFormat) {
1985         case FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE:
1986             vkFormat = glFormat2VkFormat(infoPtr->internalFormat);
1987             break;
1988         case FrameworkFormat::FRAMEWORK_FORMAT_NV12:
1989             vkFormat = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
1990             break;
1991         case FrameworkFormat::FRAMEWORK_FORMAT_P010:
1992             vkFormat = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
1993             break;
1994         case FrameworkFormat::FRAMEWORK_FORMAT_YV12:
1995         case FrameworkFormat::FRAMEWORK_FORMAT_YUV_420_888:
1996             vkFormat = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
1997             break;
1998         default:
1999             VK_COMMON_ERROR("WARNING: unhandled framework format %d\n", infoPtr->frameworkFormat);
2000             vkFormat = glFormat2VkFormat(infoPtr->internalFormat);
2001             break;
2002     }
2003 
2004     VkImageTiling tiling = (infoPtr->memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
2005                                ? VK_IMAGE_TILING_LINEAR
2006                                : VK_IMAGE_TILING_OPTIMAL;
2007     std::unique_ptr<VkImageCreateInfo> imageCi = generateColorBufferVkImageCreateInfo_locked(
2008         vkFormat, infoPtr->width, infoPtr->height, tiling);
2009     // pNext will be filled later.
2010     if (imageCi == nullptr) {
2011         // it can happen if the format is not supported
2012         return false;
2013     }
2014     imageCi->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
2015     imageCi->queueFamilyIndexCount = 0;
2016     imageCi->pQueueFamilyIndices = nullptr;
2017     imageCi->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2018 
2019     // Create the image. If external memory is supported, make it external.
2020     VkExternalMemoryImageCreateInfo extImageCi = {
2021         VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
2022         0,
2023         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
2024     };
2025 
2026     VkExternalMemoryImageCreateInfo* extImageCiPtr = nullptr;
2027 
2028     if (extMemImport || sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
2029         extImageCiPtr = &extImageCi;
2030     }
2031 
2032     imageCi->pNext = extImageCiPtr;
2033 
2034     auto vk = sVkEmulation->dvk;
2035 
2036     VkResult createRes =
2037         vk->vkCreateImage(sVkEmulation->device, imageCi.get(), nullptr, &infoPtr->image);
2038     if (createRes != VK_SUCCESS) {
2039         VK_COMMON_VERBOSE("Failed to create Vulkan image for ColorBuffer %d, error: %s", colorBufferHandle, string_VkResult(createRes));
2040         return false;
2041     }
2042 
2043     bool useDedicated = sVkEmulation->useDedicatedAllocations;
2044 
2045     infoPtr->imageCreateInfoShallow = vk_make_orphan_copy(*imageCi);
2046     infoPtr->currentQueueFamilyIndex = sVkEmulation->queueFamilyIndex;
2047 
2048     if (!useDedicated && vk->vkGetImageMemoryRequirements2KHR) {
2049         VkMemoryDedicatedRequirements dedicated_reqs{
2050             VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, nullptr};
2051         VkMemoryRequirements2 reqs{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicated_reqs};
2052 
2053         VkImageMemoryRequirementsInfo2 info{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
2054                                             nullptr, infoPtr->image};
2055         vk->vkGetImageMemoryRequirements2KHR(sVkEmulation->device, &info, &reqs);
2056         useDedicated = dedicated_reqs.requiresDedicatedAllocation;
2057         infoPtr->memReqs = reqs.memoryRequirements;
2058     } else {
2059         vk->vkGetImageMemoryRequirements(sVkEmulation->device, infoPtr->image, &infoPtr->memReqs);
2060     }
2061 
2062     // Currently we only care about two memory properties: DEVICE_LOCAL
2063     // and HOST_VISIBLE; other memory properties specified in
2064     // rcSetColorBufferVulkanMode2() call will be ignored for now.
2065     infoPtr->memoryProperty = infoPtr->memoryProperty & (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
2066                                                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
2067 
2068     infoPtr->memory.size = infoPtr->memReqs.size;
2069 
2070     // Determine memory type.
2071     if (infoPtr->memoryProperty) {
2072         infoPtr->memory.typeIndex = lastGoodTypeIndexWithMemoryProperties(
2073             infoPtr->memReqs.memoryTypeBits, infoPtr->memoryProperty);
2074     } else {
2075         infoPtr->memory.typeIndex = lastGoodTypeIndex(infoPtr->memReqs.memoryTypeBits);
2076     }
2077 
2078     VK_COMMON_VERBOSE("ColorBuffer %d, "
2079                         "allocation size and type index: %lu, %d, "
2080                         "allocated memory property: %d, "
2081                         "requested memory property: %d",
2082                         colorBufferHandle,
2083                         infoPtr->memory.size, infoPtr->memory.typeIndex,
2084                         sVkEmulation->deviceInfo.memProps.memoryTypes[infoPtr->memory.typeIndex].propertyFlags,
2085                         infoPtr->memoryProperty);
2086 
2087     Optional<VkImage> dedicatedImage = useDedicated ? Optional<VkImage>(infoPtr->image) : kNullopt;
2088     if (VK_EXT_MEMORY_HANDLE_INVALID != extMemHandle) {
2089         if (!updateExternalMemoryInfo(extMemHandle, &infoPtr->memReqs, &infoPtr->memory)) {
2090             VK_COMMON_ERROR(
2091                 "Failed to update external memory info for ColorBuffer: %d\n",
2092                 colorBufferHandle);
2093             return false;
2094         }
2095         if (useDedicated) {
2096             if (!importExternalMemoryDedicatedImage(vk, sVkEmulation->device, &infoPtr->memory,
2097                                                     *dedicatedImage, &infoPtr->memory.memory)) {
2098                 VK_COMMON_ERROR(
2099                     "Failed to import external memory with dedicated Image for colorBuffer: %d\n",
2100                     colorBufferHandle);
2101                 return false;
2102             }
2103         } else if (!importExternalMemory(vk, sVkEmulation->device, &infoPtr->memory,
2104                                          &infoPtr->memory.memory)) {
2105             VK_COMMON_ERROR("Failed to import external memory for colorBuffer: %d\n",
2106                             colorBufferHandle);
2107             return false;
2108         }
2109 
2110         infoPtr->externalMemoryCompatible = true;
2111     } else {
2112         bool isHostVisible = infoPtr->memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
2113         Optional<uint64_t> deviceAlignment =
2114             isHostVisible ? Optional<uint64_t>(infoPtr->memReqs.alignment) : kNullopt;
2115         bool allocRes = allocExternalMemory(vk, &infoPtr->memory, true /*actuallyExternal*/,
2116                                             deviceAlignment, kNullopt, dedicatedImage);
2117         if (!allocRes) {
2118             VK_COMMON_VERBOSE("Failed to allocate ColorBuffer with Vulkan backing.");
2119             return false;
2120         }
2121 
2122         infoPtr->externalMemoryCompatible = sVkEmulation->deviceInfo.supportsExternalMemoryExport;
2123     }
2124 
2125     infoPtr->memory.pageOffset = reinterpret_cast<uint64_t>(infoPtr->memory.mappedPtr) % kPageSize;
2126     infoPtr->memory.bindOffset =
2127         infoPtr->memory.pageOffset ? kPageSize - infoPtr->memory.pageOffset : 0u;
2128 
2129     VkResult bindImageMemoryRes = vk->vkBindImageMemory(
2130         sVkEmulation->device, infoPtr->image, infoPtr->memory.memory, infoPtr->memory.bindOffset);
2131 
2132     if (bindImageMemoryRes != VK_SUCCESS) {
2133         VK_COMMON_ERROR("Failed to bind image memory. Error: %s", string_VkResult(bindImageMemoryRes));
2134         return false;
2135     }
2136 
2137     const VkImageViewCreateInfo imageViewCi = {
2138         .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2139         .pNext = nullptr,
2140         .flags = 0,
2141         .image = infoPtr->image,
2142         .viewType = VK_IMAGE_VIEW_TYPE_2D,
2143         .format = infoPtr->imageCreateInfoShallow.format,
2144         .components =
2145             {
2146                 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
2147                 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
2148                 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
2149                 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
2150             },
2151         .subresourceRange =
2152             {
2153                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2154                 .baseMipLevel = 0,
2155                 .levelCount = 1,
2156                 .baseArrayLayer = 0,
2157                 .layerCount = 1,
2158             },
2159     };
2160     createRes =
2161         vk->vkCreateImageView(sVkEmulation->device, &imageViewCi, nullptr, &infoPtr->imageView);
2162     if (createRes != VK_SUCCESS) {
2163         VK_COMMON_VERBOSE("Failed to create Vulkan image for ColorBuffer %d, Error: %s", colorBufferHandle, string_VkResult(createRes));
2164         return false;
2165     }
2166 
2167 #if defined(VK_MVK_moltenvk) && defined(__APPLE__)
2168     if (sVkEmulation->instanceSupportsMoltenVK) {
2169         sVkEmulation->getMTLTextureFunc(infoPtr->image, &infoPtr->mtlTexture);
2170         if (!infoPtr->mtlTexture) {
2171             VK_COMMON_ERROR("Failed to get MTLTexture for Vulkan image %p.", infoPtr->image);
2172         }
2173 
2174         CFRetain(infoPtr->mtlTexture);
2175     }
2176 #endif
2177 
2178     sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->image, "ColorBuffer:%d",
2179                                                  colorBufferHandle);
2180     sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->imageView, "ColorBuffer:%d",
2181                                                  colorBufferHandle);
2182     sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->memory.memory, "ColorBuffer:%d",
2183                                                  colorBufferHandle);
2184 
2185     infoPtr->initialized = true;
2186 
2187     return true;
2188 }
2189 
createVkColorBufferLocked(uint32_t width,uint32_t height,GLenum internalFormat,FrameworkFormat frameworkFormat,uint32_t colorBufferHandle,bool vulkanOnly,uint32_t memoryProperty)2190 static bool createVkColorBufferLocked(uint32_t width, uint32_t height, GLenum internalFormat,
2191                                       FrameworkFormat frameworkFormat, uint32_t colorBufferHandle,
2192                                       bool vulkanOnly, uint32_t memoryProperty) {
2193     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2194     // Already initialized
2195     if (infoPtr) {
2196         return true;
2197     }
2198 
2199     VkEmulation::ColorBufferInfo res;
2200 
2201     res.handle = colorBufferHandle;
2202     res.width = width;
2203     res.height = height;
2204     res.memoryProperty = memoryProperty;
2205     res.internalFormat = internalFormat;
2206     res.frameworkFormat = frameworkFormat;
2207     res.frameworkStride = 0;
2208 
2209     if (vulkanOnly) {
2210         res.vulkanMode = VkEmulation::VulkanMode::VulkanOnly;
2211     }
2212 
2213     sVkEmulation->colorBuffers[colorBufferHandle] = res;
2214     return true;
2215 }
2216 
createVkColorBuffer(uint32_t width,uint32_t height,GLenum internalFormat,FrameworkFormat frameworkFormat,uint32_t colorBufferHandle,bool vulkanOnly,uint32_t memoryProperty)2217 bool createVkColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat,
2218                          FrameworkFormat frameworkFormat, uint32_t colorBufferHandle,
2219                          bool vulkanOnly, uint32_t memoryProperty) {
2220     if (!sVkEmulation || !sVkEmulation->live) {
2221         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "VkEmulation not available.";
2222     }
2223 
2224     AutoLock lock(sVkEmulationLock);
2225     if (!createVkColorBufferLocked(width, height, internalFormat, frameworkFormat,
2226                                    colorBufferHandle, vulkanOnly, memoryProperty)) {
2227         return false;
2228     }
2229 
2230     const auto& deviceInfo = sVkEmulation->deviceInfo;
2231     if (!deviceInfo.supportsExternalMemoryExport && deviceInfo.supportsExternalMemoryImport) {
2232         /* Returns, deferring initialization of the Vulkan components themselves.
2233          * Platforms that support import but not export of external memory must
2234          * use importExtMemoryHandleToVkColorBuffer(). Otherwise, the colorBuffer
2235          * memory can not be externalized.
2236          */
2237         return true;
2238     }
2239 
2240     return initializeVkColorBufferLocked(colorBufferHandle);
2241 }
2242 
exportColorBufferMemory(uint32_t colorBufferHandle)2243 std::optional<VkColorBufferMemoryExport> exportColorBufferMemory(uint32_t colorBufferHandle) {
2244     if (!sVkEmulation || !sVkEmulation->live) {
2245         return std::nullopt;
2246     }
2247 
2248     AutoLock lock(sVkEmulationLock);
2249 
2250     const auto& deviceInfo = sVkEmulation->deviceInfo;
2251     if ((!(deviceInfo.supportsExternalMemoryExport || !deviceInfo.supportsExternalMemoryImport)) ||
2252         (!deviceInfo.glInteropSupported)) {
2253         return std::nullopt;
2254     }
2255 
2256     auto info = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2257     if (!info) {
2258         return std::nullopt;
2259     }
2260 
2261     if (info->frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE) {
2262         return std::nullopt;
2263     }
2264 
2265 #if !defined(__QNX__)
2266     ManagedDescriptor descriptor(dupExternalMemory(info->memory.externalHandle));
2267 
2268     info->glExported = true;
2269 
2270     return VkColorBufferMemoryExport{
2271         .descriptor = std::move(descriptor),
2272         .size = info->memory.size,
2273         .linearTiling = info->imageCreateInfoShallow.tiling == VK_IMAGE_TILING_LINEAR,
2274         .dedicatedAllocation = info->memory.dedicatedAllocation,
2275     };
2276 #else
2277     return std::nullopt;
2278 #endif
2279 }
2280 
teardownVkColorBufferLocked(uint32_t colorBufferHandle)2281 bool teardownVkColorBufferLocked(uint32_t colorBufferHandle) {
2282     if (!sVkEmulation || !sVkEmulation->live) return false;
2283 
2284     auto vk = sVkEmulation->dvk;
2285 
2286     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2287 
2288     if (!infoPtr) return false;
2289 
2290     if (infoPtr->initialized) {
2291         auto& info = *infoPtr;
2292         {
2293             android::base::AutoLock lock(*sVkEmulation->queueLock);
2294             VK_CHECK(vk->vkQueueWaitIdle(sVkEmulation->queue));
2295         }
2296         vk->vkDestroyImageView(sVkEmulation->device, info.imageView, nullptr);
2297         vk->vkDestroyImage(sVkEmulation->device, info.image, nullptr);
2298         freeExternalMemoryLocked(vk, &info.memory);
2299 
2300 #ifdef __APPLE__
2301         if (info.mtlTexture) {
2302             CFRelease(info.mtlTexture);
2303         }
2304 #endif
2305     }
2306 
2307     sVkEmulation->colorBuffers.erase(colorBufferHandle);
2308 
2309     return true;
2310 }
2311 
teardownVkColorBuffer(uint32_t colorBufferHandle)2312 bool teardownVkColorBuffer(uint32_t colorBufferHandle) {
2313     if (!sVkEmulation || !sVkEmulation->live) return false;
2314 
2315     AutoLock lock(sVkEmulationLock);
2316     return teardownVkColorBufferLocked(colorBufferHandle);
2317 }
2318 
importExtMemoryHandleToVkColorBuffer(uint32_t colorBufferHandle,uint32_t type,VK_EXT_MEMORY_HANDLE extMemHandle)2319 bool importExtMemoryHandleToVkColorBuffer(uint32_t colorBufferHandle, uint32_t type,
2320                                           VK_EXT_MEMORY_HANDLE extMemHandle) {
2321     if (!sVkEmulation || !sVkEmulation->live) {
2322         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "VkEmulation not available.";
2323     }
2324     if (VK_EXT_MEMORY_HANDLE_INVALID == extMemHandle) {
2325         return false;
2326     }
2327 
2328     AutoLock lock(sVkEmulationLock);
2329     // Initialize the colorBuffer with the external memory handle
2330     // Note that this will fail if the colorBuffer memory was previously initialized.
2331     return initializeVkColorBufferLocked(colorBufferHandle, extMemHandle);
2332 }
2333 
getColorBufferInfo(uint32_t colorBufferHandle)2334 VkEmulation::ColorBufferInfo getColorBufferInfo(uint32_t colorBufferHandle) {
2335     VkEmulation::ColorBufferInfo res;
2336 
2337     AutoLock lock(sVkEmulationLock);
2338 
2339     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2340 
2341     if (!infoPtr) return res;
2342 
2343     res = *infoPtr;
2344     return res;
2345 }
2346 
colorBufferNeedsUpdateBetweenGlAndVk(const VkEmulation::ColorBufferInfo & colorBufferInfo)2347 bool colorBufferNeedsUpdateBetweenGlAndVk(const VkEmulation::ColorBufferInfo& colorBufferInfo) {
2348     // GL is not used.
2349     if (colorBufferInfo.vulkanMode == VkEmulation::VulkanMode::VulkanOnly) {
2350         return false;
2351     }
2352 
2353     // YUV formats require extra conversions.
2354     if (colorBufferInfo.frameworkFormat != FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE) {
2355         return true;
2356     }
2357 
2358     // GL and VK are sharing the same underlying memory.
2359     if (colorBufferInfo.glExported) {
2360         return false;
2361     }
2362 
2363     return true;
2364 }
2365 
colorBufferNeedsUpdateBetweenGlAndVk(uint32_t colorBufferHandle)2366 bool colorBufferNeedsUpdateBetweenGlAndVk(uint32_t colorBufferHandle) {
2367     if (!sVkEmulation || !sVkEmulation->live) {
2368         return false;
2369     }
2370 
2371     AutoLock lock(sVkEmulationLock);
2372 
2373     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2374     if (!colorBufferInfo) {
2375         return false;
2376     }
2377 
2378     return colorBufferNeedsUpdateBetweenGlAndVk(*colorBufferInfo);
2379 }
2380 
readColorBufferToBytes(uint32_t colorBufferHandle,std::vector<uint8_t> * bytes)2381 bool readColorBufferToBytes(uint32_t colorBufferHandle, std::vector<uint8_t>* bytes) {
2382     if (!sVkEmulation || !sVkEmulation->live) {
2383         VK_COMMON_VERBOSE("VkEmulation not available.");
2384         return false;
2385     }
2386 
2387     AutoLock lock(sVkEmulationLock);
2388 
2389     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2390     if (!colorBufferInfo) {
2391         VK_COMMON_VERBOSE("Failed to read from ColorBuffer:%d, not found.", colorBufferHandle);
2392         bytes->clear();
2393         return false;
2394     }
2395 
2396     VkDeviceSize bytesNeeded = 0;
2397     bool result = getFormatTransferInfo(colorBufferInfo->imageCreateInfoShallow.format,
2398                                         colorBufferInfo->imageCreateInfoShallow.extent.width,
2399                                         colorBufferInfo->imageCreateInfoShallow.extent.height,
2400                                         &bytesNeeded, nullptr);
2401     if (!result) {
2402         VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, failed to get read size.",
2403                         colorBufferHandle);
2404         return false;
2405     }
2406 
2407     bytes->resize(bytesNeeded);
2408 
2409     result = readColorBufferToBytesLocked(
2410         colorBufferHandle, 0, 0, colorBufferInfo->imageCreateInfoShallow.extent.width,
2411         colorBufferInfo->imageCreateInfoShallow.extent.height, bytes->data());
2412     if (!result) {
2413         VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, failed to get read size.",
2414                         colorBufferHandle);
2415         return false;
2416     }
2417 
2418     return true;
2419 }
2420 
readColorBufferToBytes(uint32_t colorBufferHandle,uint32_t x,uint32_t y,uint32_t w,uint32_t h,void * outPixels)2421 bool readColorBufferToBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
2422                             uint32_t h, void* outPixels) {
2423     if (!sVkEmulation || !sVkEmulation->live) {
2424         VK_COMMON_ERROR("VkEmulation not available.");
2425         return false;
2426     }
2427 
2428     AutoLock lock(sVkEmulationLock);
2429     return readColorBufferToBytesLocked(colorBufferHandle, x, y, w, h, outPixels);
2430 }
2431 
readColorBufferToBytesLocked(uint32_t colorBufferHandle,uint32_t x,uint32_t y,uint32_t w,uint32_t h,void * outPixels)2432 bool readColorBufferToBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
2433                                   uint32_t h, void* outPixels) {
2434     if (!sVkEmulation || !sVkEmulation->live) {
2435         VK_COMMON_ERROR("VkEmulation not available.");
2436         return false;
2437     }
2438 
2439     auto vk = sVkEmulation->dvk;
2440 
2441     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2442     if (!colorBufferInfo) {
2443         VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, not found.", colorBufferHandle);
2444         return false;
2445     }
2446 
2447     if (!colorBufferInfo->image) {
2448         VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, no VkImage.", colorBufferHandle);
2449         return false;
2450     }
2451 
2452     if (x != 0 || y != 0 || w != colorBufferInfo->imageCreateInfoShallow.extent.width ||
2453         h != colorBufferInfo->imageCreateInfoShallow.extent.height) {
2454         VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, unhandled subrect.",
2455                         colorBufferHandle);
2456         return false;
2457     }
2458 
2459     VkDeviceSize bufferCopySize = 0;
2460     std::vector<VkBufferImageCopy> bufferImageCopies;
2461     if (!getFormatTransferInfo(colorBufferInfo->imageCreateInfoShallow.format,
2462                                colorBufferInfo->imageCreateInfoShallow.extent.width,
2463                                colorBufferInfo->imageCreateInfoShallow.extent.height,
2464                                &bufferCopySize, &bufferImageCopies)) {
2465         VK_COMMON_ERROR("Failed to read ColorBuffer:%d, unable to get transfer info.",
2466                         colorBufferHandle);
2467         return false;
2468     }
2469 
2470     // Avoid transitioning from VK_IMAGE_LAYOUT_UNDEFINED. Unfortunetly, Android does not
2471     // yet have a mechanism for sharing the expected VkImageLayout. However, the Vulkan
2472     // spec's image layout transition sections says "If the old layout is
2473     // VK_IMAGE_LAYOUT_UNDEFINED, the contents of that range may be discarded." Some
2474     // Vulkan drivers have been observed to actually perform the discard which leads to
2475     // ColorBuffer-s being unintentionally cleared. See go/ahb-vkimagelayout for a more
2476     // thorough write up.
2477     if (colorBufferInfo->currentLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
2478         colorBufferInfo->currentLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
2479     }
2480 
2481     // Record our synchronization commands.
2482     const VkCommandBufferBeginInfo beginInfo = {
2483         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2484         .pNext = nullptr,
2485         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
2486     };
2487 
2488     VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
2489 
2490     VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
2491 
2492     sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
2493         commandBuffer, "readColorBufferToBytes(ColorBuffer:%d)", colorBufferHandle);
2494 
2495     const VkImageMemoryBarrier toTransferSrcImageBarrier = {
2496         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2497         .pNext = nullptr,
2498         .srcAccessMask = 0,
2499         .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
2500         .oldLayout = colorBufferInfo->currentLayout,
2501         .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2502         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2503         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2504         .image = colorBufferInfo->image,
2505         .subresourceRange =
2506             {
2507                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2508                 .baseMipLevel = 0,
2509                 .levelCount = 1,
2510                 .baseArrayLayer = 0,
2511                 .layerCount = 1,
2512             },
2513     };
2514 
2515     vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
2516                              VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
2517                              &toTransferSrcImageBarrier);
2518 
2519     colorBufferInfo->currentLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
2520 
2521     vk->vkCmdCopyImageToBuffer(commandBuffer, colorBufferInfo->image,
2522                                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, sVkEmulation->staging.buffer,
2523                                bufferImageCopies.size(), bufferImageCopies.data());
2524 
2525     sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
2526 
2527     VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
2528 
2529     const VkSubmitInfo submitInfo = {
2530         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
2531         .pNext = nullptr,
2532         .waitSemaphoreCount = 0,
2533         .pWaitSemaphores = nullptr,
2534         .pWaitDstStageMask = nullptr,
2535         .commandBufferCount = 1,
2536         .pCommandBuffers = &commandBuffer,
2537         .signalSemaphoreCount = 0,
2538         .pSignalSemaphores = nullptr,
2539     };
2540 
2541     {
2542         android::base::AutoLock lock(*sVkEmulation->queueLock);
2543         VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
2544                                    sVkEmulation->commandBufferFence));
2545     }
2546 
2547     static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
2548 
2549     VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
2550                                  VK_TRUE, ANB_MAX_WAIT_NS));
2551 
2552     VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
2553 
2554     const VkMappedMemoryRange toInvalidate = {
2555         .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
2556         .pNext = nullptr,
2557         .memory = sVkEmulation->staging.memory.memory,
2558         .offset = 0,
2559         .size = VK_WHOLE_SIZE,
2560     };
2561 
2562     VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
2563 
2564     const auto* stagingBufferPtr = sVkEmulation->staging.memory.mappedPtr;
2565     std::memcpy(outPixels, stagingBufferPtr, bufferCopySize);
2566 
2567     return true;
2568 }
2569 
updateColorBufferFromBytes(uint32_t colorBufferHandle,const std::vector<uint8_t> & bytes)2570 bool updateColorBufferFromBytes(uint32_t colorBufferHandle, const std::vector<uint8_t>& bytes) {
2571     if (!sVkEmulation || !sVkEmulation->live) {
2572         VK_COMMON_VERBOSE("VkEmulation not available.");
2573         return false;
2574     }
2575 
2576     AutoLock lock(sVkEmulationLock);
2577 
2578     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2579     if (!colorBufferInfo) {
2580         VK_COMMON_VERBOSE("Failed to update ColorBuffer:%d, not found.", colorBufferHandle);
2581         return false;
2582     }
2583 
2584     return updateColorBufferFromBytesLocked(
2585         colorBufferHandle, 0, 0, colorBufferInfo->imageCreateInfoShallow.extent.width,
2586         colorBufferInfo->imageCreateInfoShallow.extent.height, bytes.data(), bytes.size());
2587 }
2588 
updateColorBufferFromBytes(uint32_t colorBufferHandle,uint32_t x,uint32_t y,uint32_t w,uint32_t h,const void * pixels)2589 bool updateColorBufferFromBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
2590                                 uint32_t h, const void* pixels) {
2591     if (!sVkEmulation || !sVkEmulation->live) {
2592         VK_COMMON_ERROR("VkEmulation not available.");
2593         return false;
2594     }
2595 
2596     AutoLock lock(sVkEmulationLock);
2597     return updateColorBufferFromBytesLocked(colorBufferHandle, x, y, w, h, pixels, 0);
2598 }
2599 
convertRgbToRgbaPixels(void * dst,const void * src,uint32_t w,uint32_t h)2600 static void convertRgbToRgbaPixels(void* dst, const void* src, uint32_t w, uint32_t h) {
2601     const size_t pixelCount = w * h;
2602     const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(src);
2603     uint32_t* dstPixels = reinterpret_cast<uint32_t*>(dst);
2604     for (size_t i = 0; i < pixelCount; ++i) {
2605         const uint8_t r = *(srcBytes++);
2606         const uint8_t g = *(srcBytes++);
2607         const uint8_t b = *(srcBytes++);
2608         *(dstPixels++) = 0xff000000 | (b << 16) | (g << 8) | r;
2609     }
2610 }
2611 
updateColorBufferFromBytesLocked(uint32_t colorBufferHandle,uint32_t x,uint32_t y,uint32_t w,uint32_t h,const void * pixels,size_t inputPixelsSize)2612 static bool updateColorBufferFromBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y,
2613                                              uint32_t w, uint32_t h, const void* pixels,
2614                                              size_t inputPixelsSize) {
2615     if (!sVkEmulation || !sVkEmulation->live) {
2616         VK_COMMON_ERROR("VkEmulation not available.");
2617         return false;
2618     }
2619 
2620     auto vk = sVkEmulation->dvk;
2621 
2622     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2623     if (!colorBufferInfo) {
2624         VK_COMMON_ERROR("Failed to update ColorBuffer:%d, not found.", colorBufferHandle);
2625         return false;
2626     }
2627 
2628     if (!colorBufferInfo->image) {
2629         VK_COMMON_ERROR("Failed to update ColorBuffer:%d, no VkImage.", colorBufferHandle);
2630         return false;
2631     }
2632 
2633     if (x != 0 || y != 0 || w != colorBufferInfo->imageCreateInfoShallow.extent.width ||
2634         h != colorBufferInfo->imageCreateInfoShallow.extent.height) {
2635         VK_COMMON_ERROR("Failed to update ColorBuffer:%d, unhandled subrect.", colorBufferHandle);
2636         return false;
2637     }
2638 
2639     VkDeviceSize dstBufferSize = 0;
2640     std::vector<VkBufferImageCopy> bufferImageCopies;
2641     if (!getFormatTransferInfo(colorBufferInfo->imageCreateInfoShallow.format,
2642                                colorBufferInfo->imageCreateInfoShallow.extent.width,
2643                                colorBufferInfo->imageCreateInfoShallow.extent.height,
2644                                &dstBufferSize, &bufferImageCopies)) {
2645         VK_COMMON_ERROR("Failed to update ColorBuffer:%d, unable to get transfer info.",
2646                         colorBufferHandle);
2647         return false;
2648     }
2649 
2650     const VkDeviceSize stagingBufferSize = sVkEmulation->staging.size;
2651     if (dstBufferSize > stagingBufferSize) {
2652         VK_COMMON_ERROR("Failed to update ColorBuffer:%d, transfer size %" PRIu64
2653                         " too large for staging buffer size:%" PRIu64 ".",
2654                         colorBufferHandle, dstBufferSize, stagingBufferSize);
2655         return false;
2656     }
2657 
2658     bool isThreeByteRgb = (colorBufferInfo->internalFormat == GL_RGB ||
2659         colorBufferInfo->internalFormat == GL_RGB8);
2660     size_t expectedInputSize = (isThreeByteRgb ? dstBufferSize / 4 * 3 : dstBufferSize);
2661 
2662     if (inputPixelsSize != 0 && inputPixelsSize != expectedInputSize) {
2663         VK_COMMON_ERROR(
2664             "Unexpected contents size when trying to update ColorBuffer:%d, "
2665             "provided:%zu expected:%zu",
2666             colorBufferHandle, inputPixelsSize, expectedInputSize);
2667         return false;
2668     }
2669 
2670     auto* stagingBufferPtr = sVkEmulation->staging.memory.mappedPtr;
2671 
2672     if  (isThreeByteRgb) {
2673         // Convert RGB to RGBA, since only for these types glFormat2VkFormat() makes
2674         // an incompatible choice of 4-byte backing VK_FORMAT_R8G8B8A8_UNORM.
2675         // b/281550953
2676         convertRgbToRgbaPixels(stagingBufferPtr, pixels, w, h);
2677     } else {
2678         std::memcpy(stagingBufferPtr, pixels, dstBufferSize);
2679     }
2680 
2681     // NOTE: Host vulkan state might not know the correct layout of the
2682     // destination image, as guest grallocs are designed to be used by either
2683     // GL or Vulkan. Consequently, we typically avoid image transitions from
2684     // VK_IMAGE_LAYOUT_UNDEFINED as Vulkan spec allows the contents to be
2685     // discarded (and some drivers have been observed doing it). You can
2686     // check go/ahb-vkimagelayout for more information. But since this
2687     // function does not allow subrects (see above), it will write the
2688     // provided contents onto the entirety of the target buffer, meaning this
2689     // risk of discarding data should not impact anything.
2690 
2691     // Record our synchronization commands.
2692     const VkCommandBufferBeginInfo beginInfo = {
2693         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2694         .pNext = nullptr,
2695         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
2696     };
2697 
2698     VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
2699 
2700     VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
2701 
2702     sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
2703         commandBuffer, "updateColorBufferFromBytes(ColorBuffer:%d)", colorBufferHandle);
2704 
2705     bool isSnapshotLoad =
2706         VkDecoderGlobalState::get()->getSnapshotState() == VkDecoderGlobalState::Loading;
2707     VkImageLayout currentLayout = colorBufferInfo->currentLayout;
2708     if (isSnapshotLoad) {
2709         currentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2710     }
2711     const VkImageMemoryBarrier toTransferDstImageBarrier = {
2712         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2713         .pNext = nullptr,
2714         .srcAccessMask = 0,
2715         .dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
2716         .oldLayout = currentLayout,
2717         .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2718         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2719         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2720         .image = colorBufferInfo->image,
2721         .subresourceRange =
2722             {
2723                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2724                 .baseMipLevel = 0,
2725                 .levelCount = 1,
2726                 .baseArrayLayer = 0,
2727                 .layerCount = 1,
2728             },
2729     };
2730 
2731     vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2732                              VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0, nullptr, 1,
2733                              &toTransferDstImageBarrier);
2734 
2735     // Copy to staging buffer
2736     vk->vkCmdCopyBufferToImage(commandBuffer, sVkEmulation->staging.buffer, colorBufferInfo->image,
2737                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, bufferImageCopies.size(),
2738                                bufferImageCopies.data());
2739 
2740     if (isSnapshotLoad && colorBufferInfo->currentLayout != VK_IMAGE_LAYOUT_UNDEFINED) {
2741         const VkImageMemoryBarrier toCurrentLayoutImageBarrier = {
2742             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2743             .pNext = nullptr,
2744             .srcAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
2745             .dstAccessMask = VK_ACCESS_NONE_KHR,
2746             .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2747             .newLayout = colorBufferInfo->currentLayout,
2748             .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2749             .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2750             .image = colorBufferInfo->image,
2751             .subresourceRange =
2752                 {
2753                     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2754                     .baseMipLevel = 0,
2755                     .levelCount = 1,
2756                     .baseArrayLayer = 0,
2757                     .layerCount = 1,
2758                 },
2759         };
2760         vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_HOST_BIT,
2761                                  VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1,
2762                                  &toCurrentLayoutImageBarrier);
2763     } else {
2764         colorBufferInfo->currentLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2765     }
2766 
2767     sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
2768 
2769     VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
2770 
2771     const VkSubmitInfo submitInfo = {
2772         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
2773         .pNext = nullptr,
2774         .waitSemaphoreCount = 0,
2775         .pWaitSemaphores = nullptr,
2776         .pWaitDstStageMask = nullptr,
2777         .commandBufferCount = 1,
2778         .pCommandBuffers = &commandBuffer,
2779         .signalSemaphoreCount = 0,
2780         .pSignalSemaphores = nullptr,
2781     };
2782 
2783     {
2784         android::base::AutoLock lock(*sVkEmulation->queueLock);
2785         VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
2786                                    sVkEmulation->commandBufferFence));
2787     }
2788 
2789     static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
2790 
2791     VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
2792                                  VK_TRUE, ANB_MAX_WAIT_NS));
2793 
2794     VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
2795 
2796     const VkMappedMemoryRange toInvalidate = {
2797         .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
2798         .pNext = nullptr,
2799         .memory = sVkEmulation->staging.memory.memory,
2800         .offset = 0,
2801         .size = VK_WHOLE_SIZE,
2802     };
2803     VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
2804 
2805     return true;
2806 }
2807 
getColorBufferExtMemoryHandle(uint32_t colorBuffer)2808 VK_EXT_MEMORY_HANDLE getColorBufferExtMemoryHandle(uint32_t colorBuffer) {
2809     if (!sVkEmulation || !sVkEmulation->live) return VK_EXT_MEMORY_HANDLE_INVALID;
2810 
2811     AutoLock lock(sVkEmulationLock);
2812 
2813     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBuffer);
2814 
2815     if (!infoPtr) {
2816         // Color buffer not found; this is usually OK.
2817         return VK_EXT_MEMORY_HANDLE_INVALID;
2818     }
2819 
2820     return infoPtr->memory.externalHandle;
2821 }
2822 
setColorBufferVulkanMode(uint32_t colorBuffer,uint32_t vulkanMode)2823 bool setColorBufferVulkanMode(uint32_t colorBuffer, uint32_t vulkanMode) {
2824     if (!sVkEmulation || !sVkEmulation->live) return VK_EXT_MEMORY_HANDLE_INVALID;
2825 
2826     AutoLock lock(sVkEmulationLock);
2827 
2828     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBuffer);
2829 
2830     if (!infoPtr) {
2831         return false;
2832     }
2833 
2834     infoPtr->vulkanMode = static_cast<VkEmulation::VulkanMode>(vulkanMode);
2835 
2836     return true;
2837 }
2838 
getColorBufferMTLTexture(uint32_t colorBuffer)2839 MTLTextureRef getColorBufferMTLTexture(uint32_t colorBuffer) {
2840     if (!sVkEmulation || !sVkEmulation->live) return nullptr;
2841 
2842     AutoLock lock(sVkEmulationLock);
2843 
2844     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBuffer);
2845 
2846     if (!infoPtr) {
2847         // Color buffer not found; this is usually OK.
2848         return nullptr;
2849     }
2850 
2851 #ifdef __APPLE__
2852     CFRetain(infoPtr->mtlTexture);
2853 #endif
2854     return infoPtr->mtlTexture;
2855 }
2856 
mapGpaToBufferHandle(uint32_t bufferHandle,uint64_t gpa,uint64_t size)2857 int32_t mapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa, uint64_t size) {
2858     if (!sVkEmulation || !sVkEmulation->live) return VK_ERROR_DEVICE_LOST;
2859 
2860     AutoLock lock(sVkEmulationLock);
2861 
2862     VkEmulation::ExternalMemoryInfo* memoryInfoPtr = nullptr;
2863 
2864     auto colorBufferInfoPtr = android::base::find(sVkEmulation->colorBuffers, bufferHandle);
2865     if (colorBufferInfoPtr) {
2866         memoryInfoPtr = &colorBufferInfoPtr->memory;
2867     }
2868     auto bufferInfoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
2869     if (bufferInfoPtr) {
2870         memoryInfoPtr = &bufferInfoPtr->memory;
2871     }
2872 
2873     if (!memoryInfoPtr) {
2874         return VK_ERROR_INVALID_EXTERNAL_HANDLE;
2875     }
2876 
2877     // memory should be already mapped to host.
2878     if (!memoryInfoPtr->mappedPtr) {
2879         return VK_ERROR_MEMORY_MAP_FAILED;
2880     }
2881 
2882     memoryInfoPtr->gpa = gpa;
2883     memoryInfoPtr->pageAlignedHva =
2884         reinterpret_cast<uint8_t*>(memoryInfoPtr->mappedPtr) + memoryInfoPtr->bindOffset;
2885 
2886     size_t rawSize = memoryInfoPtr->size + memoryInfoPtr->pageOffset;
2887     if (size && size < rawSize) {
2888         rawSize = size;
2889     }
2890 
2891     memoryInfoPtr->sizeToPage = ((rawSize + kPageSize - 1) >> kPageBits) << kPageBits;
2892 
2893     VK_COMMON_VERBOSE("mapGpaToColorBuffer: hva = %p, pageAlignedHva = %p -> [ 0x%" PRIxPTR ", 0x%" PRIxPTR " ]",
2894                         memoryInfoPtr->mappedPtr,
2895                         memoryInfoPtr->pageAlignedHva,
2896                         memoryInfoPtr->gpa, memoryInfoPtr->gpa + memoryInfoPtr->sizeToPage);
2897 
2898     if (sVkEmulation->occupiedGpas.find(gpa) != sVkEmulation->occupiedGpas.end()) {
2899         // emugl::emugl_crash_reporter("FATAL: already mapped gpa 0x%lx! ", gpa);
2900         return VK_ERROR_MEMORY_MAP_FAILED;
2901     }
2902 
2903     get_emugl_vm_operations().mapUserBackedRam(gpa, memoryInfoPtr->pageAlignedHva,
2904                                                memoryInfoPtr->sizeToPage);
2905 
2906     sVkEmulation->occupiedGpas.insert(gpa);
2907 
2908     return memoryInfoPtr->pageOffset;
2909 }
2910 
getBufferAllocationInfo(uint32_t bufferHandle,VkDeviceSize * outSize,uint32_t * outMemoryTypeIndex,bool * outMemoryIsDedicatedAlloc)2911 bool getBufferAllocationInfo(uint32_t bufferHandle, VkDeviceSize* outSize,
2912                              uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc) {
2913     if (!sVkEmulation || !sVkEmulation->live) {
2914         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
2915     }
2916 
2917     AutoLock lock(sVkEmulationLock);
2918 
2919     auto info = android::base::find(sVkEmulation->buffers, bufferHandle);
2920     if (!info) {
2921         return false;
2922     }
2923 
2924     if (outSize) {
2925         *outSize = info->memory.size;
2926     }
2927 
2928     if (outMemoryTypeIndex) {
2929         *outMemoryTypeIndex = info->memory.typeIndex;
2930     }
2931 
2932     if (outMemoryIsDedicatedAlloc) {
2933         *outMemoryIsDedicatedAlloc = info->memory.dedicatedAllocation;
2934     }
2935 
2936     return true;
2937 }
2938 
setupVkBuffer(uint64_t size,uint32_t bufferHandle,bool vulkanOnly,uint32_t memoryProperty)2939 bool setupVkBuffer(uint64_t size, uint32_t bufferHandle, bool vulkanOnly, uint32_t memoryProperty) {
2940     if (vulkanOnly == false) {
2941         VK_COMMON_ERROR("Data buffers should be vulkanOnly. Setup failed.");
2942         return false;
2943     }
2944 
2945     auto vk = sVkEmulation->dvk;
2946 
2947     AutoLock lock(sVkEmulationLock);
2948 
2949     auto infoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
2950 
2951     // Already setup
2952     if (infoPtr) {
2953         return true;
2954     }
2955 
2956     VkEmulation::BufferInfo res;
2957 
2958     res.handle = bufferHandle;
2959 
2960     res.size = size;
2961     res.usageFlags = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
2962                      VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
2963                      VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2964     res.createFlags = 0;
2965 
2966     res.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
2967 
2968     // Create the image. If external memory is supported, make it external.
2969     VkExternalMemoryBufferCreateInfo extBufferCi = {
2970         VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
2971         0,
2972         VK_EXT_MEMORY_HANDLE_TYPE_BIT,
2973     };
2974 
2975     VkExternalMemoryBufferCreateInfo* extBufferCiPtr = nullptr;
2976     if (sVkEmulation->deviceInfo.supportsExternalMemoryImport ||
2977         sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
2978         extBufferCiPtr = &extBufferCi;
2979     }
2980 
2981     VkBufferCreateInfo bufferCi = {
2982         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2983         extBufferCiPtr,
2984         res.createFlags,
2985         res.size,
2986         res.usageFlags,
2987         res.sharingMode,
2988         /* queueFamilyIndexCount */ 0,
2989         /* pQueueFamilyIndices */ nullptr,
2990     };
2991 
2992     VkResult createRes = vk->vkCreateBuffer(sVkEmulation->device, &bufferCi, nullptr, &res.buffer);
2993 
2994     if (createRes != VK_SUCCESS) {
2995         VK_COMMON_LOG("Failed to create Vulkan Buffer for Buffer %d, Error: %s", bufferHandle, string_VkResult(createRes));
2996         return false;
2997     }
2998     bool useDedicated = false;
2999     if (vk->vkGetBufferMemoryRequirements2KHR) {
3000         VkMemoryDedicatedRequirements dedicated_reqs{
3001             VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, nullptr};
3002         VkMemoryRequirements2 reqs{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicated_reqs};
3003 
3004         VkBufferMemoryRequirementsInfo2 info{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
3005                                              nullptr, res.buffer};
3006         vk->vkGetBufferMemoryRequirements2KHR(sVkEmulation->device, &info, &reqs);
3007         useDedicated = dedicated_reqs.requiresDedicatedAllocation;
3008         res.memReqs = reqs.memoryRequirements;
3009     } else {
3010         vk->vkGetBufferMemoryRequirements(sVkEmulation->device, res.buffer, &res.memReqs);
3011     }
3012 
3013     // Currently we only care about two memory properties: DEVICE_LOCAL
3014     // and HOST_VISIBLE; other memory properties specified in
3015     // rcSetColorBufferVulkanMode2() call will be ignored for now.
3016     memoryProperty = memoryProperty &
3017                      (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
3018 
3019     res.memory.size = res.memReqs.size;
3020 
3021     // Determine memory type.
3022     if (memoryProperty) {
3023         res.memory.typeIndex =
3024             lastGoodTypeIndexWithMemoryProperties(res.memReqs.memoryTypeBits, memoryProperty);
3025     } else {
3026         res.memory.typeIndex = lastGoodTypeIndex(res.memReqs.memoryTypeBits);
3027     }
3028 
3029     VK_COMMON_VERBOSE("Buffer %d "
3030                         "allocation size and type index: %lu, %d, "
3031                         "allocated memory property: %d, "
3032                         "requested memory property: %d",
3033                         bufferHandle,
3034                         res.memory.size, res.memory.typeIndex,
3035                         sVkEmulation->deviceInfo.memProps.memoryTypes[res.memory.typeIndex].propertyFlags,
3036                         memoryProperty);
3037 
3038     bool isHostVisible = memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
3039     Optional<uint64_t> deviceAlignment =
3040         isHostVisible ? Optional<uint64_t>(res.memReqs.alignment) : kNullopt;
3041     Optional<VkBuffer> dedicated_buffer = useDedicated ? Optional<VkBuffer>(res.buffer) : kNullopt;
3042     bool allocRes = allocExternalMemory(vk, &res.memory, true /* actuallyExternal */,
3043                                         deviceAlignment, dedicated_buffer);
3044 
3045     if (!allocRes) {
3046         VK_COMMON_LOG("Failed to allocate ColorBuffer with Vulkan backing.");
3047     }
3048 
3049     res.memory.pageOffset = reinterpret_cast<uint64_t>(res.memory.mappedPtr) % kPageSize;
3050     res.memory.bindOffset = res.memory.pageOffset ? kPageSize - res.memory.pageOffset : 0u;
3051 
3052     VkResult bindBufferMemoryRes =
3053         vk->vkBindBufferMemory(sVkEmulation->device, res.buffer, res.memory.memory, 0);
3054 
3055     if (bindBufferMemoryRes != VK_SUCCESS) {
3056         VK_COMMON_ERROR("Failed to bind buffer memory. Error: %s\n", string_VkResult(bindBufferMemoryRes));
3057         return bindBufferMemoryRes;
3058     }
3059 
3060     bool isHostVisibleMemory = memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
3061 
3062     if (isHostVisibleMemory) {
3063         VkResult mapMemoryRes = vk->vkMapMemory(sVkEmulation->device, res.memory.memory, 0,
3064                                                 res.memory.size, {}, &res.memory.mappedPtr);
3065 
3066         if (mapMemoryRes != VK_SUCCESS) {
3067             VK_COMMON_ERROR("Failed to map image memory. Error: %s\n", string_VkResult(mapMemoryRes));
3068             return false;
3069         }
3070     }
3071 
3072     res.glExported = false;
3073 
3074     sVkEmulation->buffers[bufferHandle] = res;
3075 
3076     sVkEmulation->debugUtilsHelper.addDebugLabel(res.buffer, "Buffer:%d", bufferHandle);
3077     sVkEmulation->debugUtilsHelper.addDebugLabel(res.memory.memory, "Buffer:%d", bufferHandle);
3078 
3079     return allocRes;
3080 }
3081 
teardownVkBuffer(uint32_t bufferHandle)3082 bool teardownVkBuffer(uint32_t bufferHandle) {
3083     if (!sVkEmulation || !sVkEmulation->live) return false;
3084 
3085     auto vk = sVkEmulation->dvk;
3086     AutoLock lock(sVkEmulationLock);
3087 
3088     auto infoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
3089     if (!infoPtr) return false;
3090     {
3091         android::base::AutoLock lock(*sVkEmulation->queueLock);
3092         VK_CHECK(vk->vkQueueWaitIdle(sVkEmulation->queue));
3093     }
3094     auto& info = *infoPtr;
3095 
3096     vk->vkDestroyBuffer(sVkEmulation->device, info.buffer, nullptr);
3097     freeExternalMemoryLocked(vk, &info.memory);
3098     sVkEmulation->buffers.erase(bufferHandle);
3099 
3100     return true;
3101 }
3102 
getBufferExtMemoryHandle(uint32_t bufferHandle)3103 VK_EXT_MEMORY_HANDLE getBufferExtMemoryHandle(uint32_t bufferHandle) {
3104     if (!sVkEmulation || !sVkEmulation->live) return VK_EXT_MEMORY_HANDLE_INVALID;
3105 
3106     AutoLock lock(sVkEmulationLock);
3107 
3108     auto infoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
3109     if (!infoPtr) {
3110         // Color buffer not found; this is usually OK.
3111         return VK_EXT_MEMORY_HANDLE_INVALID;
3112     }
3113 
3114     return infoPtr->memory.externalHandle;
3115 }
3116 
readBufferToBytes(uint32_t bufferHandle,uint64_t offset,uint64_t size,void * outBytes)3117 bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes) {
3118     if (!sVkEmulation || !sVkEmulation->live) {
3119         VK_COMMON_ERROR("VkEmulation not available.");
3120         return false;
3121     }
3122 
3123     auto vk = sVkEmulation->dvk;
3124 
3125     AutoLock lock(sVkEmulationLock);
3126 
3127     auto bufferInfo = android::base::find(sVkEmulation->buffers, bufferHandle);
3128     if (!bufferInfo) {
3129         VK_COMMON_ERROR("Failed to read from Buffer:%d, not found.", bufferHandle);
3130         return false;
3131     }
3132 
3133     const auto& stagingBufferInfo = sVkEmulation->staging;
3134     if (size > stagingBufferInfo.size) {
3135         VK_COMMON_ERROR("Failed to read from Buffer:%d, staging buffer too small.", bufferHandle);
3136         return false;
3137     }
3138 
3139     const VkCommandBufferBeginInfo beginInfo = {
3140         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3141         .pNext = nullptr,
3142         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3143     };
3144 
3145     VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
3146 
3147     VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
3148 
3149     sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(commandBuffer, "readBufferToBytes(Buffer:%d)",
3150                                                       bufferHandle);
3151 
3152     const VkBufferCopy bufferCopy = {
3153         .srcOffset = offset,
3154         .dstOffset = 0,
3155         .size = size,
3156     };
3157     vk->vkCmdCopyBuffer(commandBuffer, bufferInfo->buffer, stagingBufferInfo.buffer, 1,
3158                         &bufferCopy);
3159 
3160     sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
3161 
3162     VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
3163 
3164     const VkSubmitInfo submitInfo = {
3165         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3166         .pNext = nullptr,
3167         .waitSemaphoreCount = 0,
3168         .pWaitSemaphores = nullptr,
3169         .pWaitDstStageMask = nullptr,
3170         .commandBufferCount = 1,
3171         .pCommandBuffers = &commandBuffer,
3172         .signalSemaphoreCount = 0,
3173         .pSignalSemaphores = nullptr,
3174     };
3175 
3176     {
3177         android::base::AutoLock lock(*sVkEmulation->queueLock);
3178         VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
3179                                    sVkEmulation->commandBufferFence));
3180     }
3181 
3182     static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
3183 
3184     VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
3185                                  VK_TRUE, ANB_MAX_WAIT_NS));
3186 
3187     VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
3188 
3189     const VkMappedMemoryRange toInvalidate = {
3190         .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
3191         .pNext = nullptr,
3192         .memory = stagingBufferInfo.memory.memory,
3193         .offset = 0,
3194         .size = size,
3195     };
3196 
3197     VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
3198 
3199     const void* srcPtr = reinterpret_cast<const void*>(
3200         reinterpret_cast<const char*>(stagingBufferInfo.memory.mappedPtr));
3201     void* dstPtr = outBytes;
3202     void* dstPtrOffset = reinterpret_cast<void*>(reinterpret_cast<char*>(dstPtr) + offset);
3203     std::memcpy(dstPtrOffset, srcPtr, size);
3204 
3205     return true;
3206 }
3207 
updateBufferFromBytes(uint32_t bufferHandle,uint64_t offset,uint64_t size,const void * bytes)3208 bool updateBufferFromBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size,
3209                            const void* bytes) {
3210     if (!sVkEmulation || !sVkEmulation->live) {
3211         VK_COMMON_ERROR("VkEmulation not available.");
3212         return false;
3213     }
3214 
3215     auto vk = sVkEmulation->dvk;
3216 
3217     AutoLock lock(sVkEmulationLock);
3218 
3219     auto bufferInfo = android::base::find(sVkEmulation->buffers, bufferHandle);
3220     if (!bufferInfo) {
3221         VK_COMMON_ERROR("Failed to update Buffer:%d, not found.", bufferHandle);
3222         return false;
3223     }
3224 
3225     const auto& stagingBufferInfo = sVkEmulation->staging;
3226     if (size > stagingBufferInfo.size) {
3227         VK_COMMON_ERROR("Failed to update Buffer:%d, staging buffer too small.", bufferHandle);
3228         return false;
3229     }
3230 
3231     const void* srcPtr = bytes;
3232     const void* srcPtrOffset =
3233         reinterpret_cast<const void*>(reinterpret_cast<const char*>(srcPtr) + offset);
3234     void* dstPtr = stagingBufferInfo.memory.mappedPtr;
3235     std::memcpy(dstPtr, srcPtrOffset, size);
3236 
3237     const VkMappedMemoryRange toFlush = {
3238         .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
3239         .pNext = nullptr,
3240         .memory = stagingBufferInfo.memory.memory,
3241         .offset = 0,
3242         .size = size,
3243     };
3244     VK_CHECK(vk->vkFlushMappedMemoryRanges(sVkEmulation->device, 1, &toFlush));
3245 
3246     const VkCommandBufferBeginInfo beginInfo = {
3247         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3248         .pNext = nullptr,
3249         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3250     };
3251 
3252     VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
3253 
3254     VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
3255 
3256     sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
3257         commandBuffer, "updateBufferFromBytes(Buffer:%d)", bufferHandle);
3258 
3259     const VkBufferCopy bufferCopy = {
3260         .srcOffset = 0,
3261         .dstOffset = offset,
3262         .size = size,
3263     };
3264     vk->vkCmdCopyBuffer(commandBuffer, stagingBufferInfo.buffer, bufferInfo->buffer, 1,
3265                         &bufferCopy);
3266 
3267     sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
3268 
3269     VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
3270 
3271     const VkSubmitInfo submitInfo = {
3272         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3273         .pNext = nullptr,
3274         .waitSemaphoreCount = 0,
3275         .pWaitSemaphores = nullptr,
3276         .pWaitDstStageMask = nullptr,
3277         .commandBufferCount = 1,
3278         .pCommandBuffers = &commandBuffer,
3279         .signalSemaphoreCount = 0,
3280         .pSignalSemaphores = nullptr,
3281     };
3282 
3283     {
3284         android::base::AutoLock lock(*sVkEmulation->queueLock);
3285         VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
3286                                    sVkEmulation->commandBufferFence));
3287     }
3288 
3289     static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
3290 
3291     VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
3292                                  VK_TRUE, ANB_MAX_WAIT_NS));
3293 
3294     VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
3295 
3296     return true;
3297 }
3298 
transformExternalMemoryHandleTypeFlags_tohost(VkExternalMemoryHandleTypeFlags bits)3299 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_tohost(
3300     VkExternalMemoryHandleTypeFlags bits) {
3301     VkExternalMemoryHandleTypeFlags res = bits;
3302 
3303     // Transform Android/Fuchsia/Linux bits to host bits.
3304     if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) {
3305         res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
3306     }
3307 
3308 #ifdef _WIN32
3309     res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
3310     res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
3311 #endif
3312 
3313     if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
3314         res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
3315         res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3316     }
3317 
3318     if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA) {
3319         res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
3320         res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3321     }
3322 
3323 #if defined(__QNX__)
3324     // QNX only: Replace DMA_BUF_BIT_EXT with SCREEN_BUFFER_BIT_QNX for host calls
3325     if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) {
3326         res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
3327         res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3328     }
3329 #endif
3330 
3331     return res;
3332 }
3333 
transformExternalMemoryHandleTypeFlags_fromhost(VkExternalMemoryHandleTypeFlags hostBits,VkExternalMemoryHandleTypeFlags wantedGuestHandleType)3334 VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_fromhost(
3335     VkExternalMemoryHandleTypeFlags hostBits,
3336     VkExternalMemoryHandleTypeFlags wantedGuestHandleType) {
3337     VkExternalMemoryHandleTypeFlags res = hostBits;
3338 
3339     if (res & VK_EXT_MEMORY_HANDLE_TYPE_BIT) {
3340         res &= ~VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3341         res |= wantedGuestHandleType;
3342     }
3343 
3344 #ifdef _WIN32
3345     res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
3346     res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
3347 #endif
3348 
3349     return res;
3350 }
3351 
transformExternalMemoryProperties_tohost(VkExternalMemoryProperties props)3352 VkExternalMemoryProperties transformExternalMemoryProperties_tohost(
3353     VkExternalMemoryProperties props) {
3354     VkExternalMemoryProperties res = props;
3355     res.exportFromImportedHandleTypes =
3356         transformExternalMemoryHandleTypeFlags_tohost(props.exportFromImportedHandleTypes);
3357     res.compatibleHandleTypes =
3358         transformExternalMemoryHandleTypeFlags_tohost(props.compatibleHandleTypes);
3359     return res;
3360 }
3361 
transformExternalMemoryProperties_fromhost(VkExternalMemoryProperties props,VkExternalMemoryHandleTypeFlags wantedGuestHandleType)3362 VkExternalMemoryProperties transformExternalMemoryProperties_fromhost(
3363     VkExternalMemoryProperties props, VkExternalMemoryHandleTypeFlags wantedGuestHandleType) {
3364     VkExternalMemoryProperties res = props;
3365     res.exportFromImportedHandleTypes = transformExternalMemoryHandleTypeFlags_fromhost(
3366         props.exportFromImportedHandleTypes, wantedGuestHandleType);
3367     res.compatibleHandleTypes = transformExternalMemoryHandleTypeFlags_fromhost(
3368         props.compatibleHandleTypes, wantedGuestHandleType);
3369     return res;
3370 }
3371 
setColorBufferCurrentLayout(uint32_t colorBufferHandle,VkImageLayout layout)3372 void setColorBufferCurrentLayout(uint32_t colorBufferHandle, VkImageLayout layout) {
3373     AutoLock lock(sVkEmulationLock);
3374 
3375     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3376     if (!infoPtr) {
3377         VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
3378         return;
3379     }
3380     infoPtr->currentLayout = layout;
3381 }
3382 
getColorBufferCurrentLayout(uint32_t colorBufferHandle)3383 VkImageLayout getColorBufferCurrentLayout(uint32_t colorBufferHandle) {
3384     AutoLock lock(sVkEmulationLock);
3385 
3386     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3387     if (!infoPtr) {
3388         VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
3389         return VK_IMAGE_LAYOUT_UNDEFINED;
3390     }
3391     return infoPtr->currentLayout;
3392 }
3393 
3394 // Allocate a ready to use VkCommandBuffer for queue transfer. The caller needs
3395 // to signal the returned VkFence when the VkCommandBuffer completes.
allocateQueueTransferCommandBuffer_locked()3396 static std::tuple<VkCommandBuffer, VkFence> allocateQueueTransferCommandBuffer_locked() {
3397     auto vk = sVkEmulation->dvk;
3398     // Check if a command buffer in the pool is ready to use. If the associated
3399     // VkFence is ready, vkGetFenceStatus will return VK_SUCCESS, and the
3400     // associated command buffer should be ready to use, so we return that
3401     // command buffer with the associated VkFence. If the associated VkFence is
3402     // not ready, vkGetFenceStatus will return VK_NOT_READY, we will continue to
3403     // search and test the next command buffer. If the VkFence is in an error
3404     // state, vkGetFenceStatus will return with other VkResult variants, we will
3405     // abort.
3406     for (auto& [commandBuffer, fence] : sVkEmulation->transferQueueCommandBufferPool) {
3407         auto res = vk->vkGetFenceStatus(sVkEmulation->device, fence);
3408         if (res == VK_SUCCESS) {
3409             VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &fence));
3410             VK_CHECK(vk->vkResetCommandBuffer(commandBuffer,
3411                                               VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT));
3412             return std::make_tuple(commandBuffer, fence);
3413         }
3414         if (res == VK_NOT_READY) {
3415             continue;
3416         }
3417         // We either have a device lost, or an invalid fence state. For the device lost case,
3418         // VK_CHECK will ensure we capture the relevant streams.
3419         VK_CHECK(res);
3420     }
3421     VkCommandBuffer commandBuffer;
3422     VkCommandBufferAllocateInfo allocateInfo = {
3423         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
3424         .pNext = nullptr,
3425         .commandPool = sVkEmulation->commandPool,
3426         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
3427         .commandBufferCount = 1,
3428     };
3429     VK_CHECK(vk->vkAllocateCommandBuffers(sVkEmulation->device, &allocateInfo, &commandBuffer));
3430     VkFence fence;
3431     VkFenceCreateInfo fenceCi = {
3432         .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
3433         .pNext = nullptr,
3434         .flags = 0,
3435     };
3436     VK_CHECK(vk->vkCreateFence(sVkEmulation->device, &fenceCi, nullptr, &fence));
3437 
3438     sVkEmulation->transferQueueCommandBufferPool.emplace_back(commandBuffer, fence);
3439 
3440     VK_COMMON_VERBOSE(
3441         "Create a new command buffer for queue transfer for a total of %d "
3442         "transfer command buffers",
3443         static_cast<int>(sVkEmulation->transferQueueCommandBufferPool.size()));
3444 
3445     return std::make_tuple(commandBuffer, fence);
3446 }
3447 
3448 const VkImageLayout kGuestUseDefaultImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
3449 
releaseColorBufferForGuestUse(uint32_t colorBufferHandle)3450 void releaseColorBufferForGuestUse(uint32_t colorBufferHandle) {
3451     if (!sVkEmulation || !sVkEmulation->live) {
3452         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
3453     }
3454 
3455     AutoLock lock(sVkEmulationLock);
3456 
3457     auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3458     if (!infoPtr) {
3459         VK_COMMON_ERROR("Failed to find ColorBuffer handle %d.",
3460                         static_cast<int>(colorBufferHandle));
3461         return;
3462     }
3463 
3464     std::optional<VkImageMemoryBarrier> layoutTransitionBarrier;
3465     if (infoPtr->currentLayout != kGuestUseDefaultImageLayout) {
3466         layoutTransitionBarrier = VkImageMemoryBarrier{
3467             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3468             .pNext = nullptr,
3469             .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3470             .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3471             .oldLayout = infoPtr->currentLayout,
3472             .newLayout = kGuestUseDefaultImageLayout,
3473             .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
3474             .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
3475             .image = infoPtr->image,
3476             .subresourceRange =
3477                 {
3478                     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3479                     .baseMipLevel = 0,
3480                     .levelCount = 1,
3481                     .baseArrayLayer = 0,
3482                     .layerCount = 1,
3483                 },
3484         };
3485         infoPtr->currentLayout = kGuestUseDefaultImageLayout;
3486     }
3487 
3488     std::optional<VkImageMemoryBarrier> queueTransferBarrier;
3489     if (infoPtr->currentQueueFamilyIndex != VK_QUEUE_FAMILY_EXTERNAL) {
3490         queueTransferBarrier = VkImageMemoryBarrier{
3491             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3492             .pNext = nullptr,
3493             .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3494             .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3495             .oldLayout = infoPtr->currentLayout,
3496             .newLayout = infoPtr->currentLayout,
3497             .srcQueueFamilyIndex = infoPtr->currentQueueFamilyIndex,
3498             .dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
3499             .image = infoPtr->image,
3500             .subresourceRange =
3501                 {
3502                     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3503                     .baseMipLevel = 0,
3504                     .levelCount = 1,
3505                     .baseArrayLayer = 0,
3506                     .layerCount = 1,
3507                 },
3508         };
3509         infoPtr->currentQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
3510     }
3511 
3512     if (!layoutTransitionBarrier && !queueTransferBarrier) {
3513         return;
3514     }
3515 
3516     auto vk = sVkEmulation->dvk;
3517     auto [commandBuffer, fence] = allocateQueueTransferCommandBuffer_locked();
3518 
3519     VK_CHECK(vk->vkResetCommandBuffer(commandBuffer, 0));
3520 
3521     const VkCommandBufferBeginInfo beginInfo = {
3522         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3523         .pNext = nullptr,
3524         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3525         .pInheritanceInfo = nullptr,
3526     };
3527     VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
3528 
3529     sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
3530         commandBuffer, "releaseColorBufferForGuestUse(ColorBuffer:%d)", colorBufferHandle);
3531 
3532     if (layoutTransitionBarrier) {
3533         vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
3534                                  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
3535                                  &layoutTransitionBarrier.value());
3536     }
3537     if (queueTransferBarrier) {
3538         vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
3539                                  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
3540                                  &queueTransferBarrier.value());
3541     }
3542 
3543     sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
3544 
3545     VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
3546 
3547     const VkSubmitInfo submitInfo = {
3548         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3549         .pNext = nullptr,
3550         .waitSemaphoreCount = 0,
3551         .pWaitSemaphores = nullptr,
3552         .pWaitDstStageMask = nullptr,
3553         .commandBufferCount = 1,
3554         .pCommandBuffers = &commandBuffer,
3555         .signalSemaphoreCount = 0,
3556         .pSignalSemaphores = nullptr,
3557     };
3558     {
3559         android::base::AutoLock lock(*sVkEmulation->queueLock);
3560         VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo, fence));
3561     }
3562 
3563     static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
3564     VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &fence, VK_TRUE, ANB_MAX_WAIT_NS));
3565 }
3566 
borrowColorBufferForComposition(uint32_t colorBufferHandle,bool colorBufferIsTarget)3567 std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForComposition(uint32_t colorBufferHandle,
3568                                                                      bool colorBufferIsTarget) {
3569     AutoLock lock(sVkEmulationLock);
3570 
3571     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3572     if (!colorBufferInfo) {
3573         VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
3574         return nullptr;
3575     }
3576 
3577     auto compositorInfo = std::make_unique<BorrowedImageInfoVk>();
3578     compositorInfo->id = colorBufferInfo->handle;
3579     compositorInfo->width = colorBufferInfo->imageCreateInfoShallow.extent.width;
3580     compositorInfo->height = colorBufferInfo->imageCreateInfoShallow.extent.height;
3581     compositorInfo->image = colorBufferInfo->image;
3582     compositorInfo->imageView = colorBufferInfo->imageView;
3583     compositorInfo->imageCreateInfo = colorBufferInfo->imageCreateInfoShallow;
3584     compositorInfo->preBorrowLayout = colorBufferInfo->currentLayout;
3585     compositorInfo->preBorrowQueueFamilyIndex = colorBufferInfo->currentQueueFamilyIndex;
3586     if (colorBufferIsTarget && sVkEmulation->displayVk) {
3587         // Instruct the compositor to perform the layout transition after use so
3588         // that it is ready to be blitted to the display.
3589         compositorInfo->postBorrowQueueFamilyIndex = sVkEmulation->queueFamilyIndex;
3590         compositorInfo->postBorrowLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
3591     } else {
3592         // Instruct the compositor to perform the queue transfer release after use
3593         // so that the color buffer can be acquired by the guest.
3594         compositorInfo->postBorrowQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
3595         compositorInfo->postBorrowLayout = colorBufferInfo->currentLayout;
3596 
3597         if (compositorInfo->postBorrowLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
3598             compositorInfo->postBorrowLayout = kGuestUseDefaultImageLayout;
3599         }
3600     }
3601 
3602     colorBufferInfo->currentLayout = compositorInfo->postBorrowLayout;
3603     colorBufferInfo->currentQueueFamilyIndex = compositorInfo->postBorrowQueueFamilyIndex;
3604 
3605     return compositorInfo;
3606 }
3607 
borrowColorBufferForDisplay(uint32_t colorBufferHandle)3608 std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForDisplay(uint32_t colorBufferHandle) {
3609     AutoLock lock(sVkEmulationLock);
3610 
3611     auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3612     if (!colorBufferInfo) {
3613         VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
3614         return nullptr;
3615     }
3616 
3617     auto compositorInfo = std::make_unique<BorrowedImageInfoVk>();
3618     compositorInfo->id = colorBufferInfo->handle;
3619     compositorInfo->width = colorBufferInfo->imageCreateInfoShallow.extent.width;
3620     compositorInfo->height = colorBufferInfo->imageCreateInfoShallow.extent.height;
3621     compositorInfo->image = colorBufferInfo->image;
3622     compositorInfo->imageView = colorBufferInfo->imageView;
3623     compositorInfo->imageCreateInfo = colorBufferInfo->imageCreateInfoShallow;
3624     compositorInfo->preBorrowLayout = colorBufferInfo->currentLayout;
3625     compositorInfo->preBorrowQueueFamilyIndex = sVkEmulation->queueFamilyIndex;
3626 
3627     // Instruct the display to perform the queue transfer release after use so
3628     // that the color buffer can be acquired by the guest.
3629     compositorInfo->postBorrowQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
3630     compositorInfo->postBorrowLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
3631 
3632     colorBufferInfo->currentLayout = compositorInfo->postBorrowLayout;
3633     colorBufferInfo->currentQueueFamilyIndex = compositorInfo->postBorrowQueueFamilyIndex;
3634 
3635     return compositorInfo;
3636 }
3637 
3638 std::optional<VkEmulation::RepresentativeColorBufferMemoryTypeInfo>
findRepresentativeColorBufferMemoryTypeIndexLocked()3639 findRepresentativeColorBufferMemoryTypeIndexLocked() {
3640     constexpr const uint32_t kArbitraryWidth = 64;
3641     constexpr const uint32_t kArbitraryHeight = 64;
3642     constexpr const uint32_t kArbitraryHandle = std::numeric_limits<uint32_t>::max();
3643     if (!createVkColorBufferLocked(kArbitraryWidth, kArbitraryHeight, GL_RGBA8,
3644                                    FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE,
3645                                    kArbitraryHandle, true, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
3646         ERR("Failed to setup memory type index test ColorBuffer.");
3647         return std::nullopt;
3648     }
3649     if (!initializeVkColorBufferLocked(kArbitraryHandle)) {
3650         ERR("Failed to initialize memory type index test ColorBuffer.");
3651         return std::nullopt;
3652     }
3653 
3654     uint32_t hostMemoryTypeIndex = 0;
3655     if (!getColorBufferAllocationInfoLocked(kArbitraryHandle, nullptr, &hostMemoryTypeIndex,
3656                                             nullptr, nullptr)) {
3657         ERR("Failed to lookup memory type index test ColorBuffer.");
3658         return std::nullopt;
3659     }
3660 
3661     if (!teardownVkColorBufferLocked(kArbitraryHandle)) {
3662         ERR("Failed to clean up memory type index test ColorBuffer.");
3663         return std::nullopt;
3664     }
3665 
3666     EmulatedPhysicalDeviceMemoryProperties helper(sVkEmulation->deviceInfo.memProps,
3667                                                   hostMemoryTypeIndex, sVkEmulation->features);
3668     uint32_t guestMemoryTypeIndex = helper.getGuestColorBufferMemoryTypeIndex();
3669 
3670     return VkEmulation::RepresentativeColorBufferMemoryTypeInfo{
3671         .hostMemoryTypeIndex = hostMemoryTypeIndex,
3672         .guestMemoryTypeIndex = guestMemoryTypeIndex,
3673     };
3674 }
3675 
3676 }  // namespace vk
3677 }  // namespace gfxstream
3678