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