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