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