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