blob: 1f5e56bb1429cfa8a4cf69737eeaf4793818d406 [file] [log] [blame]
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001// 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
Lingfeng Yangea978ce2019-12-13 13:42:23 -080016#include <GLES2/gl2.h>
17#include <GLES2/gl2ext.h>
Lingfeng Yangc02cb032020-10-26 14:21:25 -070018#include <GLES3/gl3.h>
Kaiyi Lieac86a72021-02-04 08:09:41 -080019#include <stdio.h>
20#include <string.h>
Lingfeng Yangea978ce2019-12-13 13:42:23 -080021#include <vulkan/vk_enum_string_helper.h>
22
23#include <iomanip>
24#include <ostream>
25#include <sstream>
Kaiyi Lieac86a72021-02-04 08:09:41 -080026#include <unordered_set>
Lingfeng Yangea978ce2019-12-13 13:42:23 -080027
Jason Macnak843b84b2023-05-19 14:19:25 -070028#include "VkDecoderGlobalState.h"
Jason Macnak7b94cd22022-04-19 14:58:35 -070029#include "VkFormatUtils.h"
Kaiyi Lieac86a72021-02-04 08:09:41 -080030#include "VulkanDispatch.h"
Jason Macnak63805b12023-02-22 18:44:05 +000031#include "aemu/base/Optional.h"
Jason Macnak63805b12023-02-22 18:44:05 +000032#include "aemu/base/Tracing.h"
Jason Macnak4c45edb2023-02-23 00:40:01 +000033#include "aemu/base/containers/Lookup.h"
34#include "aemu/base/containers/StaticMap.h"
35#include "aemu/base/synchronization/Lock.h"
36#include "aemu/base/system/System.h"
Kaiyi Lieac86a72021-02-04 08:09:41 -080037#include "common/goldfish_vk_dispatch.h"
Doug Horn0c2ea5a2021-10-29 17:30:16 -070038#include "host-common/GfxstreamFatalError.h"
Joshua Duongc3edd0c2022-12-13 08:07:55 -080039#include "host-common/emugl_vm_operations.h"
Kaiyi Lieac86a72021-02-04 08:09:41 -080040#include "host-common/vm_operations.h"
Lingfeng Yangea978ce2019-12-13 13:42:23 -080041
42#ifdef _WIN32
43#include <windows.h>
44#else
45#include <fcntl.h>
Lingfeng Yangc02cb032020-10-26 14:21:25 -070046#include <unistd.h>
Lingfeng Yangea978ce2019-12-13 13:42:23 -080047#endif
48
49#ifdef __APPLE__
50#include <CoreFoundation/CoreFoundation.h>
51#endif
52
Jason Macnaked0c9e62023-03-30 15:58:24 -070053namespace gfxstream {
54namespace vk {
55namespace {
56
Greg Schlomoffe111d0d2022-05-19 14:40:32 -070057#define VK_COMMON_ERROR(fmt, ...) \
58 fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
59#define VK_COMMON_LOG(fmt, ...) \
60 fprintf(stdout, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
61#define VK_COMMON_VERBOSE(fmt, ...) \
62 if (android::base::isVerboseLogging()) \
63 fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
Lingfeng Yangc02cb032020-10-26 14:21:25 -070064
Lingfeng Yangea978ce2019-12-13 13:42:23 -080065using android::base::AutoLock;
Jason Macnaked0c9e62023-03-30 15:58:24 -070066using android::base::kNullopt;
Kaiyi Li07583e22022-06-23 18:11:18 -070067using android::base::ManagedDescriptor;
Lingfeng Yang76906892020-10-26 11:10:46 -070068using android::base::Optional;
Lingfeng Yangea978ce2019-12-13 13:42:23 -080069using android::base::StaticLock;
70using android::base::StaticMap;
Kaiyi Li4935d312022-01-12 16:57:24 -080071using emugl::ABORT_REASON_OTHER;
72using emugl::FatalError;
Lingfeng Yang76906892020-10-26 11:10:46 -070073
Lingfeng Yang76906892020-10-26 11:10:46 -070074constexpr size_t kPageBits = 12;
75constexpr size_t kPageSize = 1u << kPageBits;
Lingfeng Yang76906892020-10-26 11:10:46 -070076
Greg Schlomoffbf53b102023-04-14 12:08:15 -070077static int kMaxDebugMarkerAnnotations = 10;
78
79static std::optional<std::string> sMemoryLogPath = std::nullopt;
80
81const char* string_AstcEmulationMode(AstcEmulationMode mode) {
82 switch (mode) {
83 case AstcEmulationMode::Disabled:
84 return "Disabled";
85 case AstcEmulationMode::Cpu:
86 return "Cpu";
87 case AstcEmulationMode::Gpu:
88 return "Gpu";
89 }
90 return "Unknown";
91}
92
Lingfeng Yang76906892020-10-26 11:10:46 -070093} // namespace
94
Greg Schlomoffe111d0d2022-05-19 14:40:32 -070095static StaticMap<VkDevice, uint32_t> sKnownStagingTypeIndices;
Lingfeng Yangea978ce2019-12-13 13:42:23 -080096
97static android::base::StaticLock sVkEmulationLock;
98
Igor Chernysheved39a8d2023-12-21 11:03:24 -080099static bool updateColorBufferFromBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y,
100 uint32_t w, uint32_t h, const void* pixels,
101 size_t inputPixelsSize);
102
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500103#if !defined(__QNX__)
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800104VK_EXT_MEMORY_HANDLE dupExternalMemory(VK_EXT_MEMORY_HANDLE h) {
105#ifdef _WIN32
106 auto myProcessHandle = GetCurrentProcess();
107 VK_EXT_MEMORY_HANDLE res;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700108 DuplicateHandle(myProcessHandle, h, // source process and handle
109 myProcessHandle, &res, // target process and pointer to handle
110 0 /* desired access (ignored) */, true /* inherit */,
111 DUPLICATE_SAME_ACCESS /* same access option */);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800112 return res;
113#else
114 return dup(h);
115#endif
116}
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500117#endif
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800118
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700119bool getStagingMemoryTypeIndex(VulkanDispatch* vk, VkDevice device,
120 const VkPhysicalDeviceMemoryProperties* memProps,
121 uint32_t* typeIndex) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700122 auto res = sKnownStagingTypeIndices.get(device);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800123
124 if (res) {
125 *typeIndex = *res;
126 return true;
127 }
128
129 VkBufferCreateInfo testCreateInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700130 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
131 0,
132 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800133 4096,
134 // To be a staging buffer, it must support being
135 // both a transfer src and dst.
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700136 VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800137 // TODO: See if buffers over shared queues need to be
138 // considered separately
139 VK_SHARING_MODE_EXCLUSIVE,
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700140 0,
141 nullptr,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800142 };
143
144 VkBuffer testBuffer;
145 VkResult testBufferCreateRes =
146 vk->vkCreateBuffer(device, &testCreateInfo, nullptr, &testBuffer);
147
148 if (testBufferCreateRes != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700149 VK_COMMON_ERROR(
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800150 "Could not create test buffer "
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700151 "for staging buffer query. VkResult: 0x%llx",
Lingfeng Yang1e4f28a2020-11-09 14:56:56 -0800152 (unsigned long long)testBufferCreateRes);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800153 return false;
154 }
155
156 VkMemoryRequirements memReqs;
157 vk->vkGetBufferMemoryRequirements(device, testBuffer, &memReqs);
158
159 // To be a staging buffer, we need to allow CPU read/write access.
160 // Thus, we need the memory type index both to be host visible
161 // and to be supported in the memory requirements of the buffer.
162 bool foundSuitableStagingMemoryType = false;
163 uint32_t stagingMemoryTypeIndex = 0;
164
Idan Raiter8fd0a0b2022-12-05 07:11:45 -0800165 for (uint32_t i = 0; i < memProps->memoryTypeCount; ++i) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800166 const auto& typeInfo = memProps->memoryTypes[i];
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700167 bool hostVisible = typeInfo.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
168 bool hostCached = typeInfo.propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800169 bool allowedInBuffer = (1 << i) & memReqs.memoryTypeBits;
170 if (hostVisible && hostCached && allowedInBuffer) {
171 foundSuitableStagingMemoryType = true;
172 stagingMemoryTypeIndex = i;
173 break;
174 }
175 }
176
Idan Raiter8fd0a0b2022-12-05 07:11:45 -0800177 // If the previous loop failed, try to accept a type that is not HOST_CACHED.
178 if (!foundSuitableStagingMemoryType) {
179 for (uint32_t i = 0; i < memProps->memoryTypeCount; ++i) {
180 const auto& typeInfo = memProps->memoryTypes[i];
181 bool hostVisible = typeInfo.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
182 bool allowedInBuffer = (1 << i) & memReqs.memoryTypeBits;
183 if (hostVisible && allowedInBuffer) {
184 VK_COMMON_ERROR("Warning: using non-cached HOST_VISIBLE type for staging memory");
185 foundSuitableStagingMemoryType = true;
186 stagingMemoryTypeIndex = i;
187 break;
188 }
189 }
190 }
191
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800192 vk->vkDestroyBuffer(device, testBuffer, nullptr);
193
194 if (!foundSuitableStagingMemoryType) {
195 std::stringstream ss;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700196 ss << "Could not find suitable memory type index "
197 << "for staging buffer. Memory type bits: " << std::hex << memReqs.memoryTypeBits << "\n"
198 << "Available host visible memory type indices:"
199 << "\n";
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800200 for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700201 if (memProps->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800202 ss << "Host visible memory type index: %u" << i << "\n";
203 }
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700204 if (memProps->memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800205 ss << "Host cached memory type index: %u" << i << "\n";
206 }
207 }
208
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700209 VK_COMMON_ERROR("Error: %s", ss.str().c_str());
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800210
211 return false;
212 }
213
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700214 sKnownStagingTypeIndices.set(device, stagingMemoryTypeIndex);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800215 *typeIndex = stagingMemoryTypeIndex;
216
217 return true;
218}
219
220static VkEmulation* sVkEmulation = nullptr;
221
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700222static bool extensionsSupported(const std::vector<VkExtensionProperties>& currentProps,
223 const std::vector<const char*>& wantedExtNames) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800224 std::vector<bool> foundExts(wantedExtNames.size(), false);
225
226 for (uint32_t i = 0; i < currentProps.size(); ++i) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700227 VK_COMMON_VERBOSE("has extension: %s", currentProps[i].extensionName);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800228 for (size_t j = 0; j < wantedExtNames.size(); ++j) {
229 if (!strcmp(wantedExtNames[j], currentProps[i].extensionName)) {
230 foundExts[j] = true;
231 }
232 }
233 }
234
235 for (size_t i = 0; i < wantedExtNames.size(); ++i) {
236 bool found = foundExts[i];
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700237 // LOG(VERBOSE) << "needed extension: " << wantedExtNames[i]
238 // << " found: " << found;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800239 if (!found) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700240 // LOG(VERBOSE) << wantedExtNames[i] << " not found, bailing.";
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800241 return false;
242 }
243 }
244
245 return true;
246}
247
248// For a given ImageSupportInfo, populates usageWithExternalHandles and
249// requiresDedicatedAllocation. memoryTypeBits are populated later once the
250// device is created, beacuse that needs a test image to be created.
251// If we don't support external memory, it's assumed dedicated allocations are
252// not needed.
253// Precondition: sVkEmulation instance has been created and ext memory caps known.
254// Returns false if the query failed.
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700255static bool getImageFormatExternalMemorySupportInfo(VulkanDispatch* vk, VkPhysicalDevice physdev,
256 VkEmulation::ImageSupportInfo* info) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800257 // Currently there is nothing special we need to do about
258 // VkFormatProperties2, so just use the normal version
259 // and put it in the format2 struct.
260 VkFormatProperties outFormatProps;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700261 vk->vkGetPhysicalDeviceFormatProperties(physdev, info->format, &outFormatProps);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800262
263 info->formatProps2 = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700264 VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
265 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800266 outFormatProps,
267 };
268
269 if (!sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
270 info->supportsExternalMemory = false;
271 info->requiresDedicatedAllocation = false;
272
273 VkImageFormatProperties outImageFormatProps;
274 VkResult res = vk->vkGetPhysicalDeviceImageFormatProperties(
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700275 physdev, info->format, info->type, info->tiling, info->usageFlags, info->createFlags,
276 &outImageFormatProps);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800277
278 if (res != VK_SUCCESS) {
279 if (res == VK_ERROR_FORMAT_NOT_SUPPORTED) {
280 info->supported = false;
281 return true;
282 } else {
283 fprintf(stderr,
284 "%s: vkGetPhysicalDeviceImageFormatProperties query "
285 "failed with %d "
286 "for format 0x%x type 0x%x usage 0x%x flags 0x%x\n",
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700287 __func__, res, info->format, info->type, info->usageFlags,
288 info->createFlags);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800289 return false;
290 }
291 }
292
293 info->supported = true;
294
295 info->imageFormatProps2 = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700296 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
297 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800298 outImageFormatProps,
299 };
300
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700301 // LOG(VERBOSE) << "Supported (not externally): "
302 // << string_VkFormat(info->format) << " "
303 // << string_VkImageType(info->type) << " "
304 // << string_VkImageTiling(info->tiling) << " "
305 // << string_VkImageUsageFlagBits(
306 // (VkImageUsageFlagBits)info->usageFlags);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800307
308 return true;
309 }
310
311 VkPhysicalDeviceExternalImageFormatInfo extInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700312 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
313 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800314 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
315 };
316
317 VkPhysicalDeviceImageFormatInfo2 formatInfo2 = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700318 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
319 &extInfo,
320 info->format,
321 info->type,
322 info->tiling,
323 info->usageFlags,
324 info->createFlags,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800325 };
326
327 VkExternalImageFormatProperties outExternalProps = {
328 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
329 0,
330 {
331 (VkExternalMemoryFeatureFlags)0,
332 (VkExternalMemoryHandleTypeFlags)0,
333 (VkExternalMemoryHandleTypeFlags)0,
334 },
335 };
336
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700337 VkImageFormatProperties2 outProps2 = {VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
338 &outExternalProps,
339 {
340 {0, 0, 0},
341 0,
342 0,
343 1,
344 0,
345 }};
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800346
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700347 VkResult res = sVkEmulation->getImageFormatProperties2Func(physdev, &formatInfo2, &outProps2);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800348
349 if (res != VK_SUCCESS) {
350 if (res == VK_ERROR_FORMAT_NOT_SUPPORTED) {
351 info->supported = false;
352 return true;
353 } else {
354 fprintf(stderr,
355 "%s: vkGetPhysicalDeviceImageFormatProperties2KHR query "
356 "failed "
357 "for format 0x%x type 0x%x usage 0x%x flags 0x%x\n",
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700358 __func__, info->format, info->type, info->usageFlags, info->createFlags);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800359 return false;
360 }
361 }
362
363 info->supported = true;
364
365 VkExternalMemoryFeatureFlags featureFlags =
366 outExternalProps.externalMemoryProperties.externalMemoryFeatures;
367
368 VkExternalMemoryHandleTypeFlags exportImportedFlags =
369 outExternalProps.externalMemoryProperties.exportFromImportedHandleTypes;
370
371 // Don't really care about export form imported handle types yet
372 (void)exportImportedFlags;
373
374 VkExternalMemoryHandleTypeFlags compatibleHandleTypes =
375 outExternalProps.externalMemoryProperties.compatibleHandleTypes;
376
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700377 info->supportsExternalMemory = (VK_EXT_MEMORY_HANDLE_TYPE_BIT & compatibleHandleTypes) &&
378 (VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT & featureFlags) &&
379 (VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT & featureFlags);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800380
381 info->requiresDedicatedAllocation =
382 (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT & featureFlags);
383
384 info->imageFormatProps2 = outProps2;
385 info->extFormatProps = outExternalProps;
386 info->imageFormatProps2.pNext = &info->extFormatProps;
387
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700388 // LOG(VERBOSE) << "Supported: "
389 // << string_VkFormat(info->format) << " "
390 // << string_VkImageType(info->type) << " "
391 // << string_VkImageTiling(info->tiling) << " "
392 // << string_VkImageUsageFlagBits(
393 // (VkImageUsageFlagBits)info->usageFlags)
394 // << " "
395 // << "supportsExternalMemory? " << info->supportsExternalMemory
396 // << " "
397 // << "requiresDedicated? " << info->requiresDedicatedAllocation;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800398
399 return true;
400}
401
Michael Yua269bfe2022-03-21 17:50:13 -0700402// Vulkan driverVersions are bit-shift packs of their dotted versions
403// For example, nvidia driverversion 1934229504 unpacks to 461.40
404// note: while this is equivalent to VkPhysicalDeviceDriverProperties.driverInfo on NVIDIA,
405// on intel that value is simply "Intel driver".
406static std::string decodeDriverVersion(uint32_t vendorId, uint32_t driverVersion) {
407 std::stringstream result;
408 switch (vendorId) {
409 case 0x10DE: {
410 // Nvidia. E.g. driverVersion = 1934229504(0x734a0000) maps to 461.40
411 uint32_t major = driverVersion >> 22;
412 uint32_t minor = (driverVersion >> 14) & 0xff;
413 uint32_t build = (driverVersion >> 6) & 0xff;
414 uint32_t revision = driverVersion & 0x3f;
415 result << major << '.' << minor << '.' << build << '.' << revision;
416 break;
417 }
418 case 0x8086: {
419 // Intel. E.g. driverVersion = 1647866(0x1924fa) maps to 100.9466 (27.20.100.9466)
420 uint32_t high = driverVersion >> 14;
421 uint32_t low = driverVersion & 0x3fff;
422 result << high << '.' << low;
423 break;
424 }
425 case 0x002: // amd
426 default: {
427 uint32_t major = VK_VERSION_MAJOR(driverVersion);
428 uint32_t minor = VK_VERSION_MINOR(driverVersion);
429 uint32_t patch = VK_VERSION_PATCH(driverVersion);
430 result << major << "." << minor << "." << patch;
431 break;
432 }
433 }
434 return result.str();
435}
436
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800437static std::vector<VkEmulation::ImageSupportInfo> getBasicImageSupportList() {
Kaiyi Li71874cc2022-08-22 08:40:46 -0700438 struct ImageFeatureCombo {
439 VkFormat format;
440 VkImageCreateFlags createFlags = 0;
441 };
442 // Set the mutable flag for RGB UNORM formats so that the created image can also be sampled in
443 // the sRGB Colorspace. See
444 // https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/3827672/comments/77db9cb3_60663a6a
445 // for details.
446 std::vector<ImageFeatureCombo> combos = {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800447 // Cover all the gralloc formats
Kaiyi Li71874cc2022-08-22 08:40:46 -0700448 {VK_FORMAT_R8G8B8A8_UNORM,
449 VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
450 {VK_FORMAT_R8G8B8_UNORM,
451 VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800452
Kaiyi Li71874cc2022-08-22 08:40:46 -0700453 {VK_FORMAT_R5G6B5_UNORM_PACK16},
Kaiyi Li24596232022-08-11 15:17:43 -0700454
Kaiyi Li71874cc2022-08-22 08:40:46 -0700455 {VK_FORMAT_R16G16B16A16_SFLOAT},
456 {VK_FORMAT_R16G16B16_SFLOAT},
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800457
Kaiyi Li71874cc2022-08-22 08:40:46 -0700458 {VK_FORMAT_B8G8R8A8_UNORM,
459 VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800460
Kaiyi Li71874cc2022-08-22 08:40:46 -0700461 {VK_FORMAT_R8_UNORM,
462 VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
Jason Macnak98d95fa2023-01-09 11:13:45 -0800463 {VK_FORMAT_R16_UNORM,
464 VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT},
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800465
Kaiyi Li71874cc2022-08-22 08:40:46 -0700466 {VK_FORMAT_A2R10G10B10_UINT_PACK32},
467 {VK_FORMAT_A2R10G10B10_UNORM_PACK32},
468 {VK_FORMAT_A2B10G10R10_UNORM_PACK32},
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800469
470 // Compressed texture formats
Kaiyi Li71874cc2022-08-22 08:40:46 -0700471 {VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK},
472 {VK_FORMAT_ASTC_4x4_UNORM_BLOCK},
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800473
474 // TODO: YUV formats used in Android
475 // Fails on Mac
Kaiyi Li71874cc2022-08-22 08:40:46 -0700476 {VK_FORMAT_G8_B8R8_2PLANE_420_UNORM},
477 {VK_FORMAT_G8_B8R8_2PLANE_422_UNORM},
478 {VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM},
479 {VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM},
480 {VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16},
Lingfeng Yang76906892020-10-26 11:10:46 -0700481
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800482 };
483
484 std::vector<VkImageType> types = {
485 VK_IMAGE_TYPE_2D,
486 };
487
488 std::vector<VkImageTiling> tilings = {
489 VK_IMAGE_TILING_LINEAR,
490 VK_IMAGE_TILING_OPTIMAL,
491 };
492
493 std::vector<VkImageUsageFlags> usageFlags = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700494 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
495 VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800496 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
497 };
498
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800499 std::vector<VkEmulation::ImageSupportInfo> res;
500
Kaiyi Li71874cc2022-08-22 08:40:46 -0700501 // Currently: 17 format + create flags combo, 2 tilings, 5 usage flags -> 170 cases to check.
502 for (auto combo : combos) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800503 for (auto t : types) {
504 for (auto ti : tilings) {
505 for (auto u : usageFlags) {
Kaiyi Li71874cc2022-08-22 08:40:46 -0700506 VkEmulation::ImageSupportInfo info;
507 info.format = combo.format;
508 info.type = t;
509 info.tiling = ti;
510 info.usageFlags = u;
511 info.createFlags = combo.createFlags;
512 res.push_back(info);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800513 }
514 }
515 }
516 }
517
518 return res;
519}
520
Aaron Ruby4846dba2024-01-08 13:24:42 -0500521VkEmulation* createGlobalVkEmulation(VulkanDispatch* vk, bool useVulkanNativeSwapchain) {
William Ho6c844be2022-05-09 13:27:46 -0700522// Downstream branches can provide abort logic or otherwise use result without a new macro
523#define VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(res, ...) \
524 do { \
525 (void)res; /* no-op of unused param*/ \
526 ERR(__VA_ARGS__); \
527 return nullptr; \
Kaiyi Li02683992022-02-07 11:09:50 -0800528 } while (0)
529
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800530 AutoLock lock(sVkEmulationLock);
531
532 if (sVkEmulation) return sVkEmulation;
533
Jason Macnaked0c9e62023-03-30 15:58:24 -0700534 if (!vkDispatchValid(vk)) {
William Ho6c844be2022-05-09 13:27:46 -0700535 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER, "Dispatch is invalid.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800536 }
537
538 sVkEmulation = new VkEmulation;
539
540 sVkEmulation->gvk = vk;
541 auto gvk = vk;
542
543 std::vector<const char*> externalMemoryInstanceExtNames = {
Greg Schlomoffcd180b02022-05-12 16:50:56 -0700544 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
545 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800546 };
547
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800548 std::vector<const char*> externalMemoryDeviceExtNames = {
Greg Schlomoffcd180b02022-05-12 16:50:56 -0700549 VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME,
550 VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
551 VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800552#ifdef _WIN32
Greg Schlomoffcd180b02022-05-12 16:50:56 -0700553 VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500554#elif defined(__QNX__)
555 VK_QNX_EXTERNAL_MEMORY_SCREEN_BUFFER_EXTENSION_NAME,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800556#else
Greg Schlomoffcd180b02022-05-12 16:50:56 -0700557 VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800558#endif
559 };
560
Gurchetan Singhf08e59a2022-08-25 16:50:36 -0700561 std::vector<const char*> externalSemaphoreInstanceExtNames = {
562 VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
563 };
564
Yahan Zhouafa9c8b2023-10-16 16:30:28 -0700565 std::vector<const char*> surfaceInstanceExtNames = {
566 VK_KHR_SURFACE_EXTENSION_NAME,
567 };
568
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800569 uint32_t extCount = 0;
570 gvk->vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
Michael Yua269bfe2022-03-21 17:50:13 -0700571 std::vector<VkExtensionProperties>& exts = sVkEmulation->instanceExtensions;
572 exts.resize(extCount);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800573 gvk->vkEnumerateInstanceExtensionProperties(nullptr, &extCount, exts.data());
574
575 bool externalMemoryCapabilitiesSupported =
576 extensionsSupported(exts, externalMemoryInstanceExtNames);
Gurchetan Singhf08e59a2022-08-25 16:50:36 -0700577 bool externalSemaphoreCapabilitiesSupported =
578 extensionsSupported(exts, externalSemaphoreInstanceExtNames);
Yahan Zhouafa9c8b2023-10-16 16:30:28 -0700579 bool surfaceSupported =
580 extensionsSupported(exts, surfaceInstanceExtNames);
Jason Macnakc02837a2023-07-28 14:53:28 -0700581#if defined(__APPLE__) && defined(VK_MVK_moltenvk)
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700582 bool moltenVKSupported =
583 (vk->vkGetMTLTextureMVK != nullptr) && (vk->vkSetMTLTextureMVK != nullptr);
Kaiyi Lia9bf3672022-09-08 18:47:43 -0700584#endif
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800585
586 VkInstanceCreateInfo instCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700587 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, nullptr, 0, nullptr, 0, nullptr,
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800588 };
589
Kaiyi Lieac86a72021-02-04 08:09:41 -0800590 std::unordered_set<const char*> enabledExtensions;
591
Jason Macnake7045482023-04-11 11:24:19 -0700592 const bool debugUtilsSupported = extensionsSupported(exts, {VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
593 const bool debugUtilsRequested = false; // TODO: enable via a feature or env var?
594 const bool debugUtilsAvailableAndRequested = debugUtilsSupported && debugUtilsRequested;
595 if (debugUtilsAvailableAndRequested) {
596 enabledExtensions.emplace(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
597 }
598
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800599 if (externalMemoryCapabilitiesSupported) {
Kaiyi Lieac86a72021-02-04 08:09:41 -0800600 for (auto extension : externalMemoryInstanceExtNames) {
601 enabledExtensions.emplace(extension);
602 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800603 }
604
Jason Macnakc02837a2023-07-28 14:53:28 -0700605#if defined(__APPLE__) && defined(VK_MVK_moltenvk)
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800606 if (moltenVKSupported) {
607 // We don't need both moltenVK and external memory. Disable
608 // external memory if moltenVK is supported.
609 externalMemoryCapabilitiesSupported = false;
Kaiyi Lieac86a72021-02-04 08:09:41 -0800610 enabledExtensions.clear();
Lingfeng Yang76906892020-10-26 11:10:46 -0700611 }
Kaiyi Lia9bf3672022-09-08 18:47:43 -0700612#endif
Lingfeng Yang76906892020-10-26 11:10:46 -0700613
Aaron Ruby4846dba2024-01-08 13:24:42 -0500614 if (useVulkanNativeSwapchain) {
615 for (auto extension : SwapChainStateVk::getRequiredInstanceExtensions()) {
616 enabledExtensions.emplace(extension);
617 }
Kaiyi Lieac86a72021-02-04 08:09:41 -0800618 }
Gurchetan Singhe26be872023-05-09 10:18:44 -0700619
Jason Macnakc02837a2023-07-28 14:53:28 -0700620#if defined(__APPLE__) && defined(VK_MVK_moltenvk)
Gurchetan Singhe26be872023-05-09 10:18:44 -0700621 if (moltenVKSupported) {
622 enabledExtensions.emplace(VK_MVK_MOLTENVK_EXTENSION_NAME);
623 }
624#endif
625
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700626 std::vector<const char*> enabledExtensions_(enabledExtensions.begin(), enabledExtensions.end());
627 instCi.enabledExtensionCount = static_cast<uint32_t>(enabledExtensions_.size());
Kaiyi Lieac86a72021-02-04 08:09:41 -0800628 instCi.ppEnabledExtensionNames = enabledExtensions_.data();
629
Lingfeng Yang76906892020-10-26 11:10:46 -0700630 VkApplicationInfo appInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700631 VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, "AEMU", 1, "AEMU", 1, VK_MAKE_VERSION(1, 0, 0),
Lingfeng Yang76906892020-10-26 11:10:46 -0700632 };
633
634 instCi.pApplicationInfo = &appInfo;
635
636 // Can we know instance version early?
637 if (gvk->vkEnumerateInstanceVersion) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700638 // LOG(VERBOSE) << "global loader has vkEnumerateInstanceVersion.";
Lingfeng Yang76906892020-10-26 11:10:46 -0700639 uint32_t instanceVersion;
640 VkResult res = gvk->vkEnumerateInstanceVersion(&instanceVersion);
641 if (VK_SUCCESS == res) {
642 if (instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700643 // LOG(VERBOSE) << "global loader has vkEnumerateInstanceVersion returning >= 1.1.";
Lingfeng Yang76906892020-10-26 11:10:46 -0700644 appInfo.apiVersion = VK_MAKE_VERSION(1, 1, 0);
645 }
646 }
647 }
648
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700649 // LOG(VERBOSE) << "Creating instance, asking for version "
650 // << VK_VERSION_MAJOR(appInfo.apiVersion) << "."
651 // << VK_VERSION_MINOR(appInfo.apiVersion) << "."
652 // << VK_VERSION_PATCH(appInfo.apiVersion) << " ...";
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800653
654 VkResult res = gvk->vkCreateInstance(&instCi, nullptr, &sVkEmulation->instance);
655
656 if (res != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -0700657 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(res, "Failed to create Vulkan instance. Error %s.",
658 string_VkResult(res));
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800659 }
660
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800661 // Create instance level dispatch.
662 sVkEmulation->ivk = new VulkanDispatch;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700663 init_vulkan_dispatch_from_instance(vk, sVkEmulation->instance, sVkEmulation->ivk);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800664
665 auto ivk = sVkEmulation->ivk;
666
667 if (!vulkan_dispatch_check_instance_VK_VERSION_1_0(ivk)) {
668 fprintf(stderr, "%s: Warning: Vulkan 1.0 APIs missing from instance\n", __func__);
669 }
670
671 if (ivk->vkEnumerateInstanceVersion) {
672 uint32_t instanceVersion;
673 VkResult enumInstanceRes = ivk->vkEnumerateInstanceVersion(&instanceVersion);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700674 if ((VK_SUCCESS == enumInstanceRes) && instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800675 if (!vulkan_dispatch_check_instance_VK_VERSION_1_1(ivk)) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700676 fprintf(stderr, "%s: Warning: Vulkan 1.1 APIs missing from instance (1st try)\n",
677 __func__);
Lingfeng Yang76906892020-10-26 11:10:46 -0700678 }
679 }
680
681 if (appInfo.apiVersion < VK_MAKE_VERSION(1, 1, 0) &&
682 instanceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700683 // LOG(VERBOSE) << "Found out that we can create a higher version instance.";
Lingfeng Yang76906892020-10-26 11:10:46 -0700684 appInfo.apiVersion = VK_MAKE_VERSION(1, 1, 0);
685
686 gvk->vkDestroyInstance(sVkEmulation->instance, nullptr);
687
688 VkResult res = gvk->vkCreateInstance(&instCi, nullptr, &sVkEmulation->instance);
689
690 if (res != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -0700691 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
692 res, "Failed to create Vulkan 1.1 instance. Error %s.", string_VkResult(res));
Lingfeng Yang76906892020-10-26 11:10:46 -0700693 }
694
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700695 init_vulkan_dispatch_from_instance(vk, sVkEmulation->instance, sVkEmulation->ivk);
Lingfeng Yang76906892020-10-26 11:10:46 -0700696
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700697 // LOG(VERBOSE) << "Created Vulkan 1.1 instance on second try.";
Lingfeng Yang76906892020-10-26 11:10:46 -0700698
699 if (!vulkan_dispatch_check_instance_VK_VERSION_1_1(ivk)) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700700 fprintf(stderr, "%s: Warning: Vulkan 1.1 APIs missing from instance (2nd try)\n",
701 __func__);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800702 }
703 }
704 }
705
Michael Yua269bfe2022-03-21 17:50:13 -0700706 sVkEmulation->vulkanInstanceVersion = appInfo.apiVersion;
707
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700708 sVkEmulation->instanceSupportsExternalMemoryCapabilities = externalMemoryCapabilitiesSupported;
Greg Schlomoff83e57ac2022-11-07 12:50:35 -0800709 sVkEmulation->instanceSupportsExternalSemaphoreCapabilities =
710 externalSemaphoreCapabilitiesSupported;
Yahan Zhouafa9c8b2023-10-16 16:30:28 -0700711 sVkEmulation->instanceSupportsSurface = surfaceSupported;
Jason Macnakc02837a2023-07-28 14:53:28 -0700712#if defined(__APPLE__) && defined(VK_MVK_moltenvk)
Lingfeng Yang76906892020-10-26 11:10:46 -0700713 sVkEmulation->instanceSupportsMoltenVK = moltenVKSupported;
Kaiyi Lia9bf3672022-09-08 18:47:43 -0700714#endif
Lingfeng Yang76906892020-10-26 11:10:46 -0700715
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800716 if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
Kaiyi Li31edce62022-02-02 20:11:05 -0800717 sVkEmulation->getImageFormatProperties2Func = vk_util::getVkInstanceProcAddrWithFallback<
718 vk_util::vk_fn_info::GetPhysicalDeviceImageFormatProperties2>(
719 {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance);
720 sVkEmulation->getPhysicalDeviceProperties2Func = vk_util::getVkInstanceProcAddrWithFallback<
721 vk_util::vk_fn_info::GetPhysicalDeviceProperties2>(
722 {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800723 }
Kaiyi Lid5ce0822021-11-20 12:48:27 -0800724 sVkEmulation->getPhysicalDeviceFeatures2Func =
725 vk_util::getVkInstanceProcAddrWithFallback<vk_util::vk_fn_info::GetPhysicalDeviceFeatures2>(
726 {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800727
Jason Macnakc02837a2023-07-28 14:53:28 -0700728#if defined(__APPLE__) && defined(VK_MVK_moltenvk)
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800729 if (sVkEmulation->instanceSupportsMoltenVK) {
Doug Hornefb17962021-01-07 16:17:34 -0800730 sVkEmulation->setMTLTextureFunc = reinterpret_cast<PFN_vkSetMTLTextureMVK>(
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700731 vk->vkGetInstanceProcAddr(sVkEmulation->instance, "vkSetMTLTextureMVK"));
Doug Hornefb17962021-01-07 16:17:34 -0800732
733 if (!sVkEmulation->setMTLTextureFunc) {
William Ho6c844be2022-05-09 13:27:46 -0700734 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
735 "Cannot find vkSetMTLTextureMVK.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800736 }
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700737 sVkEmulation->getMTLTextureFunc = reinterpret_cast<PFN_vkGetMTLTextureMVK>(
738 vk->vkGetInstanceProcAddr(sVkEmulation->instance, "vkGetMTLTextureMVK"));
Doug Hornefb17962021-01-07 16:17:34 -0800739 if (!sVkEmulation->getMTLTextureFunc) {
William Ho6c844be2022-05-09 13:27:46 -0700740 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
741 "Cannot find vkGetMTLTextureMVK.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800742 }
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700743 // LOG(VERBOSE) << "Instance supports VK_MVK_moltenvk.";
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800744 }
Kaiyi Lia9bf3672022-09-08 18:47:43 -0700745#endif
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800746
747 uint32_t physdevCount = 0;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700748 ivk->vkEnumeratePhysicalDevices(sVkEmulation->instance, &physdevCount, nullptr);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800749 std::vector<VkPhysicalDevice> physdevs(physdevCount);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700750 ivk->vkEnumeratePhysicalDevices(sVkEmulation->instance, &physdevCount, physdevs.data());
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800751
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700752 // LOG(VERBOSE) << "Found " << physdevCount << " Vulkan physical devices.";
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800753
754 if (physdevCount == 0) {
William Ho6c844be2022-05-09 13:27:46 -0700755 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER, "No physical devices available.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800756 }
757
758 std::vector<VkEmulation::DeviceSupportInfo> deviceInfos(physdevCount);
759
760 for (int i = 0; i < physdevCount; ++i) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700761 ivk->vkGetPhysicalDeviceProperties(physdevs[i], &deviceInfos[i].physdevProps);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800762
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700763 // LOG(VERBOSE) << "Considering Vulkan physical device " << i << ": "
764 // << deviceInfos[i].physdevProps.deviceName;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800765
766 // It's easier to figure out the staging buffer along with
767 // external memories if we have the memory properties on hand.
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700768 ivk->vkGetPhysicalDeviceMemoryProperties(physdevs[i], &deviceInfos[i].memProps);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800769
770 uint32_t deviceExtensionCount = 0;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700771 ivk->vkEnumerateDeviceExtensionProperties(physdevs[i], nullptr, &deviceExtensionCount,
772 nullptr);
Michael Yua269bfe2022-03-21 17:50:13 -0700773 std::vector<VkExtensionProperties>& deviceExts = deviceInfos[i].extensions;
774 deviceExts.resize(deviceExtensionCount);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700775 ivk->vkEnumerateDeviceExtensionProperties(physdevs[i], nullptr, &deviceExtensionCount,
776 deviceExts.data());
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800777
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500778 deviceInfos[i].supportsExternalMemoryImport = false;
779 deviceInfos[i].supportsExternalMemoryExport = false;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700780 deviceInfos[i].glInteropSupported = 0; // set later
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800781
782 if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500783 deviceInfos[i].supportsExternalMemoryExport =
784 deviceInfos[i].supportsExternalMemoryImport =
785 extensionsSupported(deviceExts, externalMemoryDeviceExtNames);
786#if defined(__QNX__)
787 // External memory export not supported on QNX
788 deviceInfos[i].supportsExternalMemoryExport = false;
789#endif
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700790 deviceInfos[i].supportsIdProperties =
791 sVkEmulation->getPhysicalDeviceProperties2Func != nullptr;
Michael Yua269bfe2022-03-21 17:50:13 -0700792 deviceInfos[i].supportsDriverProperties =
793 extensionsSupported(deviceExts, {VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME}) ||
794 (deviceInfos[i].physdevProps.apiVersion >= VK_API_VERSION_1_2);
795
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700796 if (!sVkEmulation->getPhysicalDeviceProperties2Func) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700797 fprintf(stderr,
798 "%s: warning: device claims to support ID properties "
799 "but vkGetPhysicalDeviceProperties2 could not be found\n",
800 __func__);
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700801 }
802 }
803
Michael Yua269bfe2022-03-21 17:50:13 -0700804 if (sVkEmulation->getPhysicalDeviceProperties2Func) {
805 VkPhysicalDeviceProperties2 deviceProps = {
806 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700807 };
Michael Yua269bfe2022-03-21 17:50:13 -0700808 VkPhysicalDeviceIDProperties idProps = {
809 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR,
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700810 };
Michael Yua269bfe2022-03-21 17:50:13 -0700811 VkPhysicalDeviceDriverPropertiesKHR driverProps = {
812 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
813 };
814
815 auto devicePropsChain = vk_make_chain_iterator(&deviceProps);
816
817 if (deviceInfos[i].supportsIdProperties) {
818 vk_append_struct(&devicePropsChain, &idProps);
819 }
820
821 if (deviceInfos[i].supportsDriverProperties) {
822 vk_append_struct(&devicePropsChain, &driverProps);
823 }
824
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700825 sVkEmulation->getPhysicalDeviceProperties2Func(physdevs[i], &deviceProps);
Michael Yua269bfe2022-03-21 17:50:13 -0700826
827 deviceInfos[i].idProps = vk_make_orphan_copy(idProps);
828
829 std::stringstream driverVendorBuilder;
830 driverVendorBuilder << "Vendor " << std::hex << std::setfill('0') << std::showbase
831 << deviceInfos[i].physdevProps.vendorID;
832
833 std::string decodedDriverVersion = decodeDriverVersion(
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700834 deviceInfos[i].physdevProps.vendorID, deviceInfos[i].physdevProps.driverVersion);
Michael Yua269bfe2022-03-21 17:50:13 -0700835
836 std::stringstream driverVersionBuilder;
837 driverVersionBuilder << "Driver Version " << std::hex << std::setfill('0')
838 << std::showbase << deviceInfos[i].physdevProps.driverVersion
839 << " Decoded As " << decodedDriverVersion;
840
841 std::string driverVendor = driverVendorBuilder.str();
842 std::string driverVersion = driverVersionBuilder.str();
843 if (deviceInfos[i].supportsDriverProperties && driverProps.driverID) {
844 driverVendor = std::string{driverProps.driverName} + " (" + driverVendor + ")";
845 driverVersion = std::string{driverProps.driverInfo} + " (" +
846 string_VkDriverId(driverProps.driverID) + " " + driverVersion + ")";
847 }
848
849 deviceInfos[i].driverVendor = driverVendor;
850 deviceInfos[i].driverVersion = driverVersion;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800851 }
852
Kaiyi Lid5ce0822021-11-20 12:48:27 -0800853 deviceInfos[i].hasSamplerYcbcrConversionExtension =
854 extensionsSupported(deviceExts, {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME});
855 if (sVkEmulation->getPhysicalDeviceFeatures2Func) {
856 VkPhysicalDeviceFeatures2 features2 = {
857 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
858 };
859 auto features2Chain = vk_make_chain_iterator(&features2);
860 VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYcbcrConversionFeatures = {
861 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
862 };
863 vk_append_struct(&features2Chain, &samplerYcbcrConversionFeatures);
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500864#if defined(__QNX__)
865 VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX extMemScreenBufferFeatures = {
866 .sType =
867 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX,
868 };
869 vk_append_struct(&features2Chain, &extMemScreenBufferFeatures);
870#endif
Kaiyi Lid5ce0822021-11-20 12:48:27 -0800871 sVkEmulation->getPhysicalDeviceFeatures2Func(physdevs[i], &features2);
872
873 deviceInfos[i].supportsSamplerYcbcrConversion =
874 samplerYcbcrConversionFeatures.samplerYcbcrConversion == VK_TRUE;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500875#if defined(__QNX__)
876 deviceInfos[i].supportsExternalMemoryImport =
877 extMemScreenBufferFeatures.screenBufferImport == VK_TRUE;
878 } else {
879 deviceInfos[i].supportsExternalMemoryImport = false;
880#endif
Kaiyi Lid5ce0822021-11-20 12:48:27 -0800881 }
882
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800883 uint32_t queueFamilyCount = 0;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700884 ivk->vkGetPhysicalDeviceQueueFamilyProperties(physdevs[i], &queueFamilyCount, nullptr);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800885 std::vector<VkQueueFamilyProperties> queueFamilyProps(queueFamilyCount);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700886 ivk->vkGetPhysicalDeviceQueueFamilyProperties(physdevs[i], &queueFamilyCount,
887 queueFamilyProps.data());
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800888
889 for (uint32_t j = 0; j < queueFamilyCount; ++j) {
890 auto count = queueFamilyProps[j].queueCount;
891 auto flags = queueFamilyProps[j].queueFlags;
892
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700893 bool hasGraphicsQueueFamily = (count > 0 && (flags & VK_QUEUE_GRAPHICS_BIT));
894 bool hasComputeQueueFamily = (count > 0 && (flags & VK_QUEUE_COMPUTE_BIT));
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800895
896 deviceInfos[i].hasGraphicsQueueFamily =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700897 deviceInfos[i].hasGraphicsQueueFamily || hasGraphicsQueueFamily;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800898
899 deviceInfos[i].hasComputeQueueFamily =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700900 deviceInfos[i].hasComputeQueueFamily || hasComputeQueueFamily;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800901
902 if (hasGraphicsQueueFamily) {
903 deviceInfos[i].graphicsQueueFamilyIndices.push_back(j);
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700904 // LOG(VERBOSE) << "Graphics queue family index: " << j;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800905 }
906
907 if (hasComputeQueueFamily) {
908 deviceInfos[i].computeQueueFamilyIndices.push_back(j);
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700909 // LOG(VERBOSE) << "Compute queue family index: " << j;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800910 }
911 }
912 }
913
914 // Of all the devices enumerated, find the best one. Try to find a device
915 // with graphics queue as the highest priority, then ext memory, then
916 // compute.
917
918 // Graphics queue is highest priority since without that, we really
919 // shouldn't be using the driver. Although, one could make a case for doing
920 // some sorts of things if only a compute queue is available (such as for
921 // AI), that's not really the priority yet.
922
923 // As for external memory, we really should not be running on any driver
924 // without external memory support, but we might be able to pull it off, and
925 // single Vulkan apps might work via CPU transfer of the rendered frames.
926
927 // Compute support is treated as icing on the cake and not relied upon yet
928 // for anything critical to emulation. However, we might potentially use it
929 // to perform image format conversion on GPUs where that's not natively
930 // supported.
931
932 // Another implicit choice is to select only one Vulkan device. This makes
933 // things simple for now, but we could consider utilizing multiple devices
934 // in use cases that make sense, if/when they come up.
935
936 std::vector<uint32_t> deviceScores(physdevCount, 0);
937
938 for (uint32_t i = 0; i < physdevCount; ++i) {
939 uint32_t deviceScore = 0;
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700940 if (deviceInfos[i].hasGraphicsQueueFamily) deviceScore += 10000;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -0500941 if (deviceInfos[i].supportsExternalMemoryImport ||
942 deviceInfos[i].supportsExternalMemoryExport)
943 deviceScore += 1000;
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700944 if (deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU ||
945 deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
946 deviceScore += 100;
947 }
948 if (deviceInfos[i].physdevProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
949 deviceScore += 50;
950 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800951 deviceScores[i] = deviceScore;
952 }
953
954 uint32_t maxScoringIndex = 0;
955 uint32_t maxScore = 0;
956
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700957 // If we don't support physical device ID properties,
958 // just pick the first physical device.
959 if (!sVkEmulation->instanceSupportsExternalMemoryCapabilities) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700960 fprintf(stderr,
961 "%s: warning: instance doesn't support "
962 "external memory capabilities, picking first physical device\n",
963 __func__);
Lingfeng Yang273d6be2021-06-08 19:26:52 -0700964 maxScoringIndex = 0;
965 } else {
966 for (uint32_t i = 0; i < physdevCount; ++i) {
967 if (deviceScores[i] > maxScore) {
968 maxScoringIndex = i;
969 maxScore = deviceScores[i];
970 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800971 }
972 }
973
974 sVkEmulation->physdev = physdevs[maxScoringIndex];
Gurchetan Singh424f0672022-08-26 11:10:12 -0700975 sVkEmulation->physicalDeviceIndex = maxScoringIndex;
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800976 sVkEmulation->deviceInfo = deviceInfos[maxScoringIndex];
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800977 // Postcondition: sVkEmulation has valid device support info
978
979 // Ask about image format support here.
980 // TODO: May have to first ask when selecting physical devices
981 // (e.g., choose between Intel or NVIDIA GPU for certain image format
982 // support)
983 sVkEmulation->imageSupportInfo = getBasicImageSupportList();
984 for (size_t i = 0; i < sVkEmulation->imageSupportInfo.size(); ++i) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700985 getImageFormatExternalMemorySupportInfo(ivk, sVkEmulation->physdev,
986 &sVkEmulation->imageSupportInfo[i]);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800987 }
988
989 if (!sVkEmulation->deviceInfo.hasGraphicsQueueFamily) {
William Ho6c844be2022-05-09 13:27:46 -0700990 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
991 "No Vulkan devices with graphics queues found.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800992 }
993
994 auto deviceVersion = sVkEmulation->deviceInfo.physdevProps.apiVersion;
Doug Horna25b5112021-06-03 10:59:00 -0700995 VK_COMMON_LOG("Selecting Vulkan device: %s", sVkEmulation->deviceInfo.physdevProps.deviceName);
Lingfeng Yangea978ce2019-12-13 13:42:23 -0800996
Lingfeng Yangc02cb032020-10-26 14:21:25 -0700997 // LOG(VERBOSE) << "Version: "
Greg Schlomoffe111d0d2022-05-19 14:40:32 -0700998 // << VK_VERSION_MAJOR(deviceVersion) << "." << VK_VERSION_MINOR(deviceVersion) <<
999 // "." << VK_VERSION_PATCH(deviceVersion);
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001000 // LOG(VERBOSE) << "Has graphics queue? "
1001 // << sVkEmulation->deviceInfo.hasGraphicsQueueFamily;
1002 // LOG(VERBOSE) << "Has external memory support? "
1003 // << sVkEmulation->deviceInfo.supportsExternalMemory;
1004 // LOG(VERBOSE) << "Has compute queue? "
1005 // << sVkEmulation->deviceInfo.hasComputeQueueFamily;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001006
1007 float priority = 1.0f;
1008 VkDeviceQueueCreateInfo dqCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001009 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1010 0,
1011 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001012 sVkEmulation->deviceInfo.graphicsQueueFamilyIndices[0],
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001013 1,
1014 &priority,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001015 };
1016
Kaiyi Lieac86a72021-02-04 08:09:41 -08001017 std::unordered_set<const char*> selectedDeviceExtensionNames_;
1018
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001019 if (sVkEmulation->deviceInfo.supportsExternalMemoryImport ||
1020 sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
Kaiyi Lieac86a72021-02-04 08:09:41 -08001021 for (auto extension : externalMemoryDeviceExtNames) {
1022 selectedDeviceExtensionNames_.emplace(extension);
1023 }
1024 }
Aaron Ruby4846dba2024-01-08 13:24:42 -05001025 if (useVulkanNativeSwapchain) {
1026 for (auto extension : SwapChainStateVk::getRequiredDeviceExtensions()) {
1027 selectedDeviceExtensionNames_.emplace(extension);
1028 }
Kaiyi Lieac86a72021-02-04 08:09:41 -08001029 }
Kaiyi Lid5ce0822021-11-20 12:48:27 -08001030 if (sVkEmulation->deviceInfo.hasSamplerYcbcrConversionExtension) {
1031 selectedDeviceExtensionNames_.emplace(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME);
1032 }
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001033 std::vector<const char*> selectedDeviceExtensionNames(selectedDeviceExtensionNames_.begin(),
1034 selectedDeviceExtensionNames_.end());
Kaiyi Lieac86a72021-02-04 08:09:41 -08001035
1036 VkDeviceCreateInfo dCi = {};
1037 dCi.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
Kaiyi Lieac86a72021-02-04 08:09:41 -08001038 dCi.queueCreateInfoCount = 1;
1039 dCi.pQueueCreateInfos = &dqCi;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001040 dCi.enabledExtensionCount = static_cast<uint32_t>(selectedDeviceExtensionNames.size());
Kaiyi Lieac86a72021-02-04 08:09:41 -08001041 dCi.ppEnabledExtensionNames = selectedDeviceExtensionNames.data();
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001042
Kaiyi Lid5ce0822021-11-20 12:48:27 -08001043 // Setting up VkDeviceCreateInfo::pNext
1044 auto deviceCiChain = vk_make_chain_iterator(&dCi);
1045
1046 VkPhysicalDeviceFeatures2 features = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
1047 vk_append_struct(&deviceCiChain, &features);
1048
1049 std::unique_ptr<VkPhysicalDeviceSamplerYcbcrConversionFeatures> samplerYcbcrConversionFeatures =
1050 nullptr;
1051 if (sVkEmulation->deviceInfo.supportsSamplerYcbcrConversion) {
1052 samplerYcbcrConversionFeatures =
1053 std::make_unique<VkPhysicalDeviceSamplerYcbcrConversionFeatures>(
1054 VkPhysicalDeviceSamplerYcbcrConversionFeatures{
1055 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,
1056 .samplerYcbcrConversion = VK_TRUE,
1057 });
1058 vk_append_struct(&deviceCiChain, samplerYcbcrConversionFeatures.get());
1059 }
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001060#if defined(__QNX__)
1061 std::unique_ptr<VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX>
1062 extMemScreenBufferFeaturesQNX = nullptr;
1063 if (sVkEmulation->deviceInfo.supportsExternalMemoryImport) {
1064 extMemScreenBufferFeaturesQNX = std::make_unique<
1065 VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX>(
1066 VkPhysicalDeviceExternalMemoryScreenBufferFeaturesQNX{
1067 .sType =
1068 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_SCREEN_BUFFER_FEATURES_QNX,
1069 .screenBufferImport = VK_TRUE,
1070 });
1071 vk_append_struct(&deviceCiChain, extMemScreenBufferFeaturesQNX.get());
1072 }
1073#endif
Kaiyi Lid5ce0822021-11-20 12:48:27 -08001074
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001075 ivk->vkCreateDevice(sVkEmulation->physdev, &dCi, nullptr, &sVkEmulation->device);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001076
1077 if (res != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -07001078 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(res, "Failed to create Vulkan device. Error %s.",
1079 string_VkResult(res));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001080 }
1081
1082 // device created; populate dispatch table
1083 sVkEmulation->dvk = new VulkanDispatch;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001084 init_vulkan_dispatch_from_device(ivk, sVkEmulation->device, sVkEmulation->dvk);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001085
1086 auto dvk = sVkEmulation->dvk;
1087
1088 // Check if the dispatch table has everything 1.1 related
1089 if (!vulkan_dispatch_check_device_VK_VERSION_1_0(dvk)) {
1090 fprintf(stderr, "%s: Warning: Vulkan 1.0 APIs missing from device.\n", __func__);
1091 }
1092 if (deviceVersion >= VK_MAKE_VERSION(1, 1, 0)) {
1093 if (!vulkan_dispatch_check_device_VK_VERSION_1_1(dvk)) {
1094 fprintf(stderr, "%s: Warning: Vulkan 1.1 APIs missing from device\n", __func__);
1095 }
1096 }
1097
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001098 if (sVkEmulation->deviceInfo.supportsExternalMemoryImport) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001099 sVkEmulation->deviceInfo.getImageMemoryRequirements2Func =
1100 reinterpret_cast<PFN_vkGetImageMemoryRequirements2KHR>(
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001101 dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetImageMemoryRequirements2KHR"));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001102 if (!sVkEmulation->deviceInfo.getImageMemoryRequirements2Func) {
William Ho6c844be2022-05-09 13:27:46 -07001103 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1104 "Cannot find vkGetImageMemoryRequirements2KHR.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001105 }
1106 sVkEmulation->deviceInfo.getBufferMemoryRequirements2Func =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001107 reinterpret_cast<PFN_vkGetBufferMemoryRequirements2KHR>(dvk->vkGetDeviceProcAddr(
1108 sVkEmulation->device, "vkGetBufferMemoryRequirements2KHR"));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001109 if (!sVkEmulation->deviceInfo.getBufferMemoryRequirements2Func) {
William Ho6c844be2022-05-09 13:27:46 -07001110 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1111 "Cannot find vkGetBufferMemoryRequirements2KHR");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001112 }
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001113 }
1114 if (sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001115#ifdef _WIN32
1116 sVkEmulation->deviceInfo.getMemoryHandleFunc =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001117 reinterpret_cast<PFN_vkGetMemoryWin32HandleKHR>(
1118 dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetMemoryWin32HandleKHR"));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001119#else
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001120 sVkEmulation->deviceInfo.getMemoryHandleFunc = reinterpret_cast<PFN_vkGetMemoryFdKHR>(
1121 dvk->vkGetDeviceProcAddr(sVkEmulation->device, "vkGetMemoryFdKHR"));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001122#endif
1123 if (!sVkEmulation->deviceInfo.getMemoryHandleFunc) {
William Ho6c844be2022-05-09 13:27:46 -07001124 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1125 "Cannot find vkGetMemory(Fd|Win32Handle)KHR");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001126 }
1127 }
1128
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001129 // LOG(VERBOSE) << "Vulkan logical device created and extension functions obtained.\n";
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001130
Kaiyi Li263e9f42021-08-20 07:33:05 -07001131 sVkEmulation->queueLock = std::make_shared<android::base::Lock>();
1132 {
1133 android::base::AutoLock lock(*sVkEmulation->queueLock);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001134 dvk->vkGetDeviceQueue(sVkEmulation->device,
1135 sVkEmulation->deviceInfo.graphicsQueueFamilyIndices[0], 0,
1136 &sVkEmulation->queue);
Kaiyi Li263e9f42021-08-20 07:33:05 -07001137 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001138
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001139 sVkEmulation->queueFamilyIndex = sVkEmulation->deviceInfo.graphicsQueueFamilyIndices[0];
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001140
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001141 // LOG(VERBOSE) << "Vulkan device queue obtained.";
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001142
1143 VkCommandPoolCreateInfo poolCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001144 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
1145 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001146 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1147 sVkEmulation->queueFamilyIndex,
1148 };
1149
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001150 VkResult poolCreateRes = dvk->vkCreateCommandPool(sVkEmulation->device, &poolCi, nullptr,
1151 &sVkEmulation->commandPool);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001152
1153 if (poolCreateRes != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -07001154 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(poolCreateRes,
1155 "Failed to create command pool. Error: %s.",
1156 string_VkResult(poolCreateRes));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001157 }
1158
1159 VkCommandBufferAllocateInfo cbAi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001160 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1161 0,
1162 sVkEmulation->commandPool,
1163 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1164 1,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001165 };
1166
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001167 VkResult cbAllocRes =
1168 dvk->vkAllocateCommandBuffers(sVkEmulation->device, &cbAi, &sVkEmulation->commandBuffer);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001169
1170 if (cbAllocRes != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -07001171 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(cbAllocRes,
1172 "Failed to allocate command buffer. Error: %s.",
1173 string_VkResult(cbAllocRes));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001174 }
1175
1176 VkFenceCreateInfo fenceCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001177 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1178 0,
1179 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001180 };
1181
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001182 VkResult fenceCreateRes = dvk->vkCreateFence(sVkEmulation->device, &fenceCi, nullptr,
1183 &sVkEmulation->commandBufferFence);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001184
1185 if (fenceCreateRes != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -07001186 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
1187 fenceCreateRes, "Failed to create fence for command buffer. Error: %s.",
1188 string_VkResult(fenceCreateRes));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001189 }
1190
1191 // At this point, the global emulation state's logical device can alloc
1192 // memory and send commands. However, it can't really do much yet to
1193 // communicate the results without the staging buffer. Set that up here.
1194 // Note that the staging buffer is meant to use external memory, with a
1195 // non-external-memory fallback.
1196
1197 VkBufferCreateInfo bufCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001198 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1199 0,
1200 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001201 sVkEmulation->staging.size,
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001202 VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001203 VK_SHARING_MODE_EXCLUSIVE,
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001204 0,
1205 nullptr,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001206 };
1207
1208 VkResult bufCreateRes =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001209 dvk->vkCreateBuffer(sVkEmulation->device, &bufCi, nullptr, &sVkEmulation->staging.buffer);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001210
1211 if (bufCreateRes != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -07001212 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(bufCreateRes,
1213 "Failed to create staging buffer index. Error: %s.",
1214 string_VkResult(bufCreateRes));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001215 }
1216
1217 VkMemoryRequirements memReqs;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001218 dvk->vkGetBufferMemoryRequirements(sVkEmulation->device, sVkEmulation->staging.buffer,
1219 &memReqs);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001220
1221 sVkEmulation->staging.memory.size = memReqs.size;
1222
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001223 bool gotStagingTypeIndex =
1224 getStagingMemoryTypeIndex(dvk, sVkEmulation->device, &sVkEmulation->deviceInfo.memProps,
1225 &sVkEmulation->staging.memory.typeIndex);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001226
1227 if (!gotStagingTypeIndex) {
William Ho6c844be2022-05-09 13:27:46 -07001228 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1229 "Failed to determine staging memory type index.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001230 }
1231
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001232 if (!((1 << sVkEmulation->staging.memory.typeIndex) & memReqs.memoryTypeBits)) {
William Ho6c844be2022-05-09 13:27:46 -07001233 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(
1234 ABORT_REASON_OTHER,
Kaiyi Li02683992022-02-07 11:09:50 -08001235 "Failed: Inconsistent determination of memory type index for staging buffer");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001236 }
1237
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001238 if (!allocExternalMemory(dvk, &sVkEmulation->staging.memory, false /* not external */,
Lingfeng Yang76906892020-10-26 11:10:46 -07001239 kNullopt /* deviceAlignment */)) {
William Ho6c844be2022-05-09 13:27:46 -07001240 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(ABORT_REASON_OTHER,
1241 "Failed to allocate memory for staging buffer.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001242 }
1243
1244 VkResult stagingBufferBindRes = dvk->vkBindBufferMemory(
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001245 sVkEmulation->device, sVkEmulation->staging.buffer, sVkEmulation->staging.memory.memory, 0);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001246
1247 if (stagingBufferBindRes != VK_SUCCESS) {
William Ho6c844be2022-05-09 13:27:46 -07001248 VK_EMU_INIT_RETURN_OR_ABORT_ON_ERROR(stagingBufferBindRes,
1249 "Failed to bind memory for staging buffer. Error %s.",
1250 string_VkResult(stagingBufferBindRes));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001251 }
1252
Jason Macnake7045482023-04-11 11:24:19 -07001253 sVkEmulation->debugUtilsAvailableAndRequested = debugUtilsAvailableAndRequested;
1254 if (sVkEmulation->debugUtilsAvailableAndRequested) {
1255 sVkEmulation->debugUtilsHelper =
1256 DebugUtilsHelper::withUtilsEnabled(sVkEmulation->device, sVkEmulation->ivk);
1257 }
1258
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001259 // LOG(VERBOSE) << "Vulkan global emulation state successfully initialized.";
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001260 sVkEmulation->live = true;
1261
Kaiyi Li5509d442021-10-18 15:13:46 -07001262 sVkEmulation->transferQueueCommandBufferPool.resize(0);
1263
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001264 return sVkEmulation;
1265}
1266
Jason Macnak12c1c392023-03-14 15:15:38 -07001267std::optional<uint32_t> findRepresentativeColorBufferMemoryTypeIndexLocked();
1268
Kaiyi Lie4159ae2021-11-20 06:58:15 -08001269void initVkEmulationFeatures(std::unique_ptr<VkEmulationFeatures> features) {
Kaiyi Li4ddffd92022-02-15 09:34:55 -08001270 if (!sVkEmulation || !sVkEmulation->live) {
1271 ERR("VkEmulation is either not initialized or destroyed.");
Lingfeng Yang76906892020-10-26 11:10:46 -07001272 return;
1273 }
1274
Kaiyi Li4ddffd92022-02-15 09:34:55 -08001275 AutoLock lock(sVkEmulationLock);
1276 INFO("Initializing VkEmulation features:");
Kaiyi Lie4159ae2021-11-20 06:58:15 -08001277 INFO(" glInteropSupported: %s", features->glInteropSupported ? "true" : "false");
1278 INFO(" useDeferredCommands: %s", features->deferredCommands ? "true" : "false");
Kaiyi Li4ddffd92022-02-15 09:34:55 -08001279 INFO(" createResourceWithRequirements: %s",
Kaiyi Lie4159ae2021-11-20 06:58:15 -08001280 features->createResourceWithRequirements ? "true" : "false");
Jason Macnak741afe72022-04-14 08:19:52 -07001281 INFO(" useVulkanComposition: %s", features->useVulkanComposition ? "true" : "false");
Kaiyi Lie4159ae2021-11-20 06:58:15 -08001282 INFO(" useVulkanNativeSwapchain: %s", features->useVulkanNativeSwapchain ? "true" : "false");
1283 INFO(" enable guestRenderDoc: %s", features->guestRenderDoc ? "true" : "false");
Greg Schlomoff4dbcbd62022-11-16 15:36:56 -08001284 INFO(" ASTC LDR emulation mode: %d", features->astcLdrEmulationMode);
Kaiyi Li696aac22022-08-09 17:59:02 -07001285 INFO(" enable ETC2 emulation: %s", features->enableEtc2Emulation ? "true" : "false");
Kaiyi Lifca91662022-08-08 09:24:51 -07001286 INFO(" enable Ycbcr emulation: %s", features->enableYcbcrEmulation ? "true" : "false");
Jason Macnakcd598382022-07-21 11:06:06 -07001287 INFO(" guestUsesAngle: %s", features->guestUsesAngle ? "true" : "false");
Jason Macnakcc53a202023-02-23 00:40:01 +00001288 INFO(" useDedicatedAllocations: %s", features->useDedicatedAllocations ? "true" : "false");
Kaiyi Lie4159ae2021-11-20 06:58:15 -08001289 sVkEmulation->deviceInfo.glInteropSupported = features->glInteropSupported;
1290 sVkEmulation->useDeferredCommands = features->deferredCommands;
1291 sVkEmulation->useCreateResourcesWithRequirements = features->createResourceWithRequirements;
1292 sVkEmulation->guestRenderDoc = std::move(features->guestRenderDoc);
Greg Schlomoff4dbcbd62022-11-16 15:36:56 -08001293 sVkEmulation->astcLdrEmulationMode = features->astcLdrEmulationMode;
Kaiyi Li696aac22022-08-09 17:59:02 -07001294 sVkEmulation->enableEtc2Emulation = features->enableEtc2Emulation;
Kaiyi Lifca91662022-08-08 09:24:51 -07001295 sVkEmulation->enableYcbcrEmulation = features->enableYcbcrEmulation;
Jason Macnakcd598382022-07-21 11:06:06 -07001296 sVkEmulation->guestUsesAngle = features->guestUsesAngle;
Jason Macnakcc53a202023-02-23 00:40:01 +00001297 sVkEmulation->useDedicatedAllocations = features->useDedicatedAllocations;
Lingfeng Yang76906892020-10-26 11:10:46 -07001298
Jason Macnak741afe72022-04-14 08:19:52 -07001299 if (features->useVulkanComposition) {
1300 if (sVkEmulation->compositorVk) {
1301 ERR("Reset VkEmulation::compositorVk.");
1302 }
Jason Macnak5c76bdb2024-01-30 09:07:34 -08001303 sVkEmulation->compositorVk =
1304 CompositorVk::create(*sVkEmulation->ivk, sVkEmulation->device, sVkEmulation->physdev,
1305 sVkEmulation->queue, sVkEmulation->queueLock,
1306 sVkEmulation->queueFamilyIndex, 3, sVkEmulation->debugUtilsHelper);
Jason Macnak741afe72022-04-14 08:19:52 -07001307 }
1308
Kaiyi Lie4159ae2021-11-20 06:58:15 -08001309 if (features->useVulkanNativeSwapchain) {
Kaiyi Li4ddffd92022-02-15 09:34:55 -08001310 if (sVkEmulation->displayVk) {
1311 ERR("Reset VkEmulation::displayVk.");
1312 }
1313 sVkEmulation->displayVk = std::make_unique<DisplayVk>(
1314 *sVkEmulation->ivk, sVkEmulation->physdev, sVkEmulation->queueFamilyIndex,
1315 sVkEmulation->queueFamilyIndex, sVkEmulation->device, sVkEmulation->queue,
1316 sVkEmulation->queueLock, sVkEmulation->queue, sVkEmulation->queueLock);
1317 }
Jason Macnak12c1c392023-03-14 15:15:38 -07001318
1319 sVkEmulation->representativeColorBufferMemoryTypeIndex =
1320 findRepresentativeColorBufferMemoryTypeIndexLocked();
1321 if (sVkEmulation->representativeColorBufferMemoryTypeIndex) {
1322 VK_COMMON_VERBOSE("Emulated ColorBuffer memory type is based on memory type index %d.",
1323 *sVkEmulation->representativeColorBufferMemoryTypeIndex);
1324 } else {
1325 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1326 << "Failed to find memory type for ColorBuffers.";
1327 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001328}
1329
1330VkEmulation* getGlobalVkEmulation() {
1331 if (sVkEmulation && !sVkEmulation->live) return nullptr;
1332 return sVkEmulation;
1333}
1334
1335void teardownGlobalVkEmulation() {
1336 if (!sVkEmulation) return;
1337
1338 // Don't try to tear down something that did not set up completely; too risky
1339 if (!sVkEmulation->live) return;
1340
Jason Macnak741afe72022-04-14 08:19:52 -07001341 sVkEmulation->compositorVk.reset();
Kaiyi Li4ddffd92022-02-15 09:34:55 -08001342 sVkEmulation->displayVk.reset();
1343
Lingfeng Yang76906892020-10-26 11:10:46 -07001344 freeExternalMemoryLocked(sVkEmulation->dvk, &sVkEmulation->staging.memory);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001345
Greg Schlomoff83e57ac2022-11-07 12:50:35 -08001346 sVkEmulation->dvk->vkDestroyBuffer(sVkEmulation->device, sVkEmulation->staging.buffer, nullptr);
1347
1348 sVkEmulation->dvk->vkDestroyFence(sVkEmulation->device, sVkEmulation->commandBufferFence,
1349 nullptr);
1350
1351 sVkEmulation->dvk->vkFreeCommandBuffers(sVkEmulation->device, sVkEmulation->commandPool, 1,
1352 &sVkEmulation->commandBuffer);
1353
1354 sVkEmulation->dvk->vkDestroyCommandPool(sVkEmulation->device, sVkEmulation->commandPool,
1355 nullptr);
1356
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001357 sVkEmulation->ivk->vkDestroyDevice(sVkEmulation->device, nullptr);
1358 sVkEmulation->gvk->vkDestroyInstance(sVkEmulation->instance, nullptr);
Lingfeng Yangcf627ed2020-11-03 16:37:46 -08001359
Jason Macnak843b84b2023-05-19 14:19:25 -07001360 VkDecoderGlobalState::reset();
1361
Lingfeng Yangcf627ed2020-11-03 16:37:46 -08001362 sVkEmulation->live = false;
1363 delete sVkEmulation;
1364 sVkEmulation = nullptr;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001365}
1366
Jason Macnak32281f72022-10-12 13:00:36 -07001367std::unique_ptr<gfxstream::DisplaySurface> createDisplaySurface(FBNativeWindowType window,
Greg Schlomoff83e57ac2022-11-07 12:50:35 -08001368 uint32_t width, uint32_t height) {
Jason Macnak32281f72022-10-12 13:00:36 -07001369 if (!sVkEmulation || !sVkEmulation->live) {
1370 return nullptr;
1371 }
1372
Greg Schlomoff83e57ac2022-11-07 12:50:35 -08001373 auto surfaceVk = DisplaySurfaceVk::create(*sVkEmulation->ivk, sVkEmulation->instance, window);
Jason Macnak32281f72022-10-12 13:00:36 -07001374 if (!surfaceVk) {
1375 VK_COMMON_ERROR("Failed to create DisplaySurfaceVk.");
1376 return nullptr;
1377 }
1378
1379 return std::make_unique<gfxstream::DisplaySurface>(width, height, std::move(surfaceVk));
1380}
1381
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001382// Precondition: sVkEmulation has valid device support info
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001383bool allocExternalMemory(VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info,
Jason Macnakcc53a202023-02-23 00:40:01 +00001384 bool actuallyExternal, Optional<uint64_t> deviceAlignment,
1385 Optional<VkBuffer> bufferForDedicatedAllocation,
1386 Optional<VkImage> imageForDedicatedAllocation) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001387 VkExportMemoryAllocateInfo exportAi = {
Jason Macnakcc53a202023-02-23 00:40:01 +00001388 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
1389 .pNext = nullptr,
1390 .handleTypes = VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001391 };
1392
Jason Macnakcc53a202023-02-23 00:40:01 +00001393 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {
1394 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1395 .pNext = nullptr,
1396 .image = VK_NULL_HANDLE,
1397 .buffer = VK_NULL_HANDLE,
1398 };
1399
1400 VkMemoryAllocateInfo allocInfo = {
1401 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1402 .pNext = nullptr,
1403 .allocationSize = info->size,
1404 .memoryTypeIndex = info->typeIndex,
1405 };
1406
1407 auto allocInfoChain = vk_make_chain_iterator(&allocInfo);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001408
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001409 if (sVkEmulation->deviceInfo.supportsExternalMemoryExport && actuallyExternal) {
Jason Macnakcc53a202023-02-23 00:40:01 +00001410 vk_append_struct(&allocInfoChain, &exportAi);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001411 }
1412
Jason Macnakcc53a202023-02-23 00:40:01 +00001413 if (bufferForDedicatedAllocation.hasValue() || imageForDedicatedAllocation.hasValue()) {
1414 info->dedicatedAllocation = true;
1415 if (bufferForDedicatedAllocation.hasValue()) {
1416 dedicatedAllocInfo.buffer = *bufferForDedicatedAllocation;
1417 }
1418 if (imageForDedicatedAllocation.hasValue()) {
1419 dedicatedAllocInfo.image = *imageForDedicatedAllocation;
1420 }
1421 vk_append_struct(&allocInfoChain, &dedicatedAllocInfo);
1422 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001423
Lingfeng Yang76906892020-10-26 11:10:46 -07001424 bool memoryAllocated = false;
1425 std::vector<VkDeviceMemory> allocationAttempts;
1426 constexpr size_t kMaxAllocationAttempts = 20u;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001427
Lingfeng Yang76906892020-10-26 11:10:46 -07001428 while (!memoryAllocated) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001429 VkResult allocRes =
1430 vk->vkAllocateMemory(sVkEmulation->device, &allocInfo, nullptr, &info->memory);
Lingfeng Yang76906892020-10-26 11:10:46 -07001431
1432 if (allocRes != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001433 // LOG(VERBOSE) << "allocExternalMemory: failed in vkAllocateMemory: "
1434 // << allocRes;
Lingfeng Yang76906892020-10-26 11:10:46 -07001435 break;
1436 }
1437
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001438 if (sVkEmulation->deviceInfo.memProps.memoryTypes[info->typeIndex].propertyFlags &
Lingfeng Yang76906892020-10-26 11:10:46 -07001439 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
Jason Macnakcc53a202023-02-23 00:40:01 +00001440 VkResult mapRes = vk->vkMapMemory(sVkEmulation->device, info->memory, 0, info->size, 0,
1441 &info->mappedPtr);
Lingfeng Yang76906892020-10-26 11:10:46 -07001442 if (mapRes != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001443 // LOG(VERBOSE) << "allocExternalMemory: failed in vkMapMemory: "
1444 // << mapRes;
Lingfeng Yang76906892020-10-26 11:10:46 -07001445 break;
1446 }
1447 }
1448
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001449 uint64_t mappedPtrPageOffset = reinterpret_cast<uint64_t>(info->mappedPtr) % kPageSize;
Lingfeng Yang76906892020-10-26 11:10:46 -07001450
1451 if ( // don't care about alignment (e.g. device-local memory)
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001452 !deviceAlignment.hasValue() ||
1453 // If device has an alignment requirement larger than current
1454 // host pointer alignment (i.e. the lowest 1 bit of mappedPtr),
1455 // the only possible way to make mappedPtr valid is to ensure
1456 // that it is already aligned to page.
1457 mappedPtrPageOffset == 0u ||
1458 // If device has an alignment requirement smaller or equals to
1459 // current host pointer alignment, clients can set a offset
1460 // |kPageSize - mappedPtrPageOffset| in vkBindImageMemory to
1461 // make it aligned to page and compatible with device
1462 // requirements.
1463 (kPageSize - mappedPtrPageOffset) % deviceAlignment.value() == 0) {
Lingfeng Yang76906892020-10-26 11:10:46 -07001464 // allocation success.
1465 memoryAllocated = true;
1466 } else {
1467 allocationAttempts.push_back(info->memory);
1468
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001469 // LOG(VERBOSE) << "allocExternalMemory: attempt #"
1470 // << allocationAttempts.size()
1471 // << " failed; deviceAlignment: "
1472 // << deviceAlignment.valueOr(0)
1473 // << " mappedPtrPageOffset: " << mappedPtrPageOffset;
Lingfeng Yang76906892020-10-26 11:10:46 -07001474
1475 if (allocationAttempts.size() >= kMaxAllocationAttempts) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001476 // LOG(VERBOSE) << "allocExternalMemory: unable to allocate"
1477 // << " memory with CPU mapped ptr aligned to page";
Lingfeng Yang76906892020-10-26 11:10:46 -07001478 break;
1479 }
1480 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001481 }
1482
Lingfeng Yang76906892020-10-26 11:10:46 -07001483 // clean up previous failed attempts
1484 for (const auto& mem : allocationAttempts) {
1485 vk->vkFreeMemory(sVkEmulation->device, mem, nullptr /* allocator */);
1486 }
1487 if (!memoryAllocated) {
1488 return false;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001489 }
1490
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001491 if (!sVkEmulation->deviceInfo.supportsExternalMemoryExport || !actuallyExternal) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001492 return true;
1493 }
1494
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001495 VkResult exportRes = VK_SUCCESS;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001496#ifdef _WIN32
1497 VkMemoryGetWin32HandleInfoKHR getWin32HandleInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001498 VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
1499 0,
1500 info->memory,
1501 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001502 };
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001503 exportRes = sVkEmulation->deviceInfo.getMemoryHandleFunc(
1504 sVkEmulation->device, &getWin32HandleInfo, &info->externalHandle);
1505#elif !defined(__QNX__)
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001506 VkMemoryGetFdInfoKHR getFdInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001507 VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
1508 0,
1509 info->memory,
1510 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001511 };
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001512 exportRes = sVkEmulation->deviceInfo.getMemoryHandleFunc(sVkEmulation->device, &getFdInfo,
1513 &info->externalHandle);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001514#endif
1515
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001516 if (exportRes != VK_SUCCESS || VK_EXT_MEMORY_HANDLE_INVALID == info->externalHandle) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001517 // LOG(VERBOSE) << "allocExternalMemory: Failed to get external memory "
1518 // "native handle: "
1519 // << exportRes;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001520 return false;
1521 }
1522
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001523 return true;
1524}
1525
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001526void freeExternalMemoryLocked(VulkanDispatch* vk, VkEmulation::ExternalMemoryInfo* info) {
1527 if (!info->memory) return;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001528
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001529 if (sVkEmulation->deviceInfo.memProps.memoryTypes[info->typeIndex].propertyFlags &
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001530 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001531 if (sVkEmulation->occupiedGpas.find(info->gpa) != sVkEmulation->occupiedGpas.end()) {
Lingfeng Yang76906892020-10-26 11:10:46 -07001532 sVkEmulation->occupiedGpas.erase(info->gpa);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001533 get_emugl_vm_operations().unmapUserBackedRam(info->gpa, info->sizeToPage);
Lingfeng Yang76906892020-10-26 11:10:46 -07001534 info->gpa = 0u;
1535 }
1536
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001537 vk->vkUnmapMemory(sVkEmulation->device, info->memory);
1538 info->mappedPtr = nullptr;
Lingfeng Yang76906892020-10-26 11:10:46 -07001539 info->pageAlignedHva = nullptr;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001540 }
1541
1542 vk->vkFreeMemory(sVkEmulation->device, info->memory, nullptr);
1543
1544 info->memory = VK_NULL_HANDLE;
1545
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001546 if (info->externalHandle != VK_EXT_MEMORY_HANDLE_INVALID) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001547#ifdef _WIN32
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001548 CloseHandle(info->externalHandle);
1549#elif !defined(__QNX__)
1550 close(info->externalHandle);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001551#endif
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001552 info->externalHandle = VK_EXT_MEMORY_HANDLE_INVALID;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001553 }
1554}
1555
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001556bool importExternalMemory(VulkanDispatch* vk, VkDevice targetDevice,
1557 const VkEmulation::ExternalMemoryInfo* info, VkDeviceMemory* out) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001558#ifdef _WIN32
1559 VkImportMemoryWin32HandleInfoKHR importInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001560 VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
1561 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001562 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001563 info->externalHandle,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001564 0,
1565 };
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001566#elif defined(__QNX__)
1567 VkImportScreenBufferInfoQNX importInfo = {
1568 VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX,
1569 info->externalHandle,
1570 };
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001571#else
1572 VkImportMemoryFdInfoKHR importInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001573 VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
1574 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001575 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001576 dupExternalMemory(info->externalHandle),
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001577 };
1578#endif
1579 VkMemoryAllocateInfo allocInfo = {
1580 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1581 &importInfo,
Jason Macnakcc53a202023-02-23 00:40:01 +00001582 info->size,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001583 info->typeIndex,
1584 };
1585
1586 VkResult res = vk->vkAllocateMemory(targetDevice, &allocInfo, nullptr, out);
1587
1588 if (res != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001589 // LOG(ERROR) << "importExternalMemory: Failed with " << res;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001590 return false;
1591 }
1592
1593 return true;
1594}
1595
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001596bool importExternalMemoryDedicatedImage(VulkanDispatch* vk, VkDevice targetDevice,
1597 const VkEmulation::ExternalMemoryInfo* info, VkImage image,
1598 VkDeviceMemory* out) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001599 VkMemoryDedicatedAllocateInfo dedicatedInfo = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001600 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1601 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001602 image,
1603 VK_NULL_HANDLE,
1604 };
1605
1606#ifdef _WIN32
1607 VkImportMemoryWin32HandleInfoKHR importInfo = {
1608 VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
1609 &dedicatedInfo,
1610 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001611 info->externalHandle,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001612 0,
1613 };
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001614#elif defined(__QNX__)
1615 VkImportScreenBufferInfoQNX importInfo = {
1616 VK_STRUCTURE_TYPE_IMPORT_SCREEN_BUFFER_INFO_QNX,
1617 &dedicatedInfo,
1618 info->externalHandle,
1619 };
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001620#else
1621 VkImportMemoryFdInfoKHR importInfo = {
1622 VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
1623 &dedicatedInfo,
1624 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Lars Harrison70fe8f82024-02-20 16:13:53 -08001625 dupExternalMemory(info->externalHandle),
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001626 };
1627#endif
1628 VkMemoryAllocateInfo allocInfo = {
1629 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1630 &importInfo,
1631 info->size,
1632 info->typeIndex,
1633 };
1634
1635 VkResult res = vk->vkAllocateMemory(targetDevice, &allocInfo, nullptr, out);
1636
1637 if (res != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07001638 // LOG(ERROR) << "importExternalMemoryDedicatedImage: Failed with " << res;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001639 return false;
1640 }
1641
1642 return true;
1643}
1644
Jason Macnak4c45edb2023-02-23 00:40:01 +00001645// From ANGLE "src/common/angleutils.h"
1646#define GL_BGR10_A2_ANGLEX 0x6AF9
1647
Jason Macnak5fb22712023-02-23 00:40:01 +00001648static VkFormat glFormat2VkFormat(GLint internalFormat) {
1649 switch (internalFormat) {
Jason Macnak6402a1b2022-06-02 15:29:05 -07001650 case GL_R8:
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001651 case GL_LUMINANCE:
1652 return VK_FORMAT_R8_UNORM;
1653 case GL_RGB:
1654 case GL_RGB8:
Yahan Zhou1f77da82023-07-25 15:41:10 -07001655 // b/281550953
1656 // RGB8 is not supported on many vulkan drivers.
1657 // Try RGBA8 instead.
Igor Chernysheved39a8d2023-12-21 11:03:24 -08001658 // Note: copyImageData() performs channel conversion for this case.
Yahan Zhou1f77da82023-07-25 15:41:10 -07001659 return VK_FORMAT_R8G8B8A8_UNORM;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001660 case GL_RGB565:
1661 return VK_FORMAT_R5G6B5_UNORM_PACK16;
1662 case GL_RGB16F:
1663 return VK_FORMAT_R16G16B16_SFLOAT;
1664 case GL_RGBA:
1665 case GL_RGBA8:
1666 return VK_FORMAT_R8G8B8A8_UNORM;
1667 case GL_RGB5_A1_OES:
1668 return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
1669 case GL_RGBA4_OES:
1670 return VK_FORMAT_R4G4B4A4_UNORM_PACK16;
1671 case GL_RGB10_A2:
1672 case GL_UNSIGNED_INT_10_10_10_2_OES:
1673 return VK_FORMAT_A2R10G10B10_UNORM_PACK32;
Yilong Li7179d972021-04-09 09:30:39 -07001674 case GL_BGR10_A2_ANGLEX:
1675 return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001676 case GL_RGBA16F:
1677 return VK_FORMAT_R16G16B16A16_SFLOAT;
1678 case GL_BGRA_EXT:
1679 case GL_BGRA8_EXT:
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001680 return VK_FORMAT_B8G8R8A8_UNORM;
Kaiyi Li2209e382022-08-30 12:47:19 -07001681 case GL_R16_EXT:
1682 return VK_FORMAT_R16_UNORM;
1683 case GL_RG8_EXT:
1684 return VK_FORMAT_R8G8_UNORM;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001685 default:
Jason Macnak6402a1b2022-06-02 15:29:05 -07001686 VK_COMMON_ERROR("Unhandled format %d, falling back to VK_FORMAT_R8G8B8A8_UNORM",
Jason Macnak5fb22712023-02-23 00:40:01 +00001687 internalFormat);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001688 return VK_FORMAT_R8G8B8A8_UNORM;
1689 }
1690};
1691
Jason Macnak9e9c68e2023-02-23 00:40:01 +00001692static bool isFormatVulkanCompatible(GLenum internalFormat) {
1693 VkFormat vkFormat = glFormat2VkFormat(internalFormat);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001694
1695 for (const auto& supportInfo : sVkEmulation->imageSupportInfo) {
1696 if (supportInfo.format == vkFormat && supportInfo.supported) {
1697 return true;
1698 }
1699 }
1700
1701 return false;
1702}
1703
Jason Macnak5fb22712023-02-23 00:40:01 +00001704bool isColorBufferExportedToGl(uint32_t colorBufferHandle, bool* exported) {
1705 if (!sVkEmulation || !sVkEmulation->live) {
1706 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
1707 }
1708
1709 AutoLock lock(sVkEmulationLock);
1710
1711 auto info = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
1712 if (!info) {
1713 return false;
1714 }
1715
1716 *exported = info->glExported;
1717 return true;
1718}
1719
Jason Macnak12c1c392023-03-14 15:15:38 -07001720bool getColorBufferAllocationInfoLocked(uint32_t colorBufferHandle, VkDeviceSize* outSize,
1721 uint32_t* outMemoryTypeIndex,
1722 bool* outMemoryIsDedicatedAlloc, void** outMappedPtr) {
Jason Macnak5fb22712023-02-23 00:40:01 +00001723 auto info = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
1724 if (!info) {
1725 return false;
1726 }
1727
1728 if (outSize) {
1729 *outSize = info->memory.size;
1730 }
1731
1732 if (outMemoryTypeIndex) {
1733 *outMemoryTypeIndex = info->memory.typeIndex;
1734 }
1735
Jason Macnakcc53a202023-02-23 00:40:01 +00001736 if (outMemoryIsDedicatedAlloc) {
1737 *outMemoryIsDedicatedAlloc = info->memory.dedicatedAllocation;
1738 }
1739
Jason Macnak5fb22712023-02-23 00:40:01 +00001740 if (outMappedPtr) {
1741 *outMappedPtr = info->memory.mappedPtr;
1742 }
1743
1744 return true;
1745}
1746
Jason Macnak12c1c392023-03-14 15:15:38 -07001747bool getColorBufferAllocationInfo(uint32_t colorBufferHandle, VkDeviceSize* outSize,
1748 uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc,
1749 void** outMappedPtr) {
1750 if (!sVkEmulation || !sVkEmulation->live) {
1751 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
1752 }
1753
1754 AutoLock lock(sVkEmulationLock);
1755 return getColorBufferAllocationInfoLocked(colorBufferHandle, outSize, outMemoryTypeIndex,
1756 outMemoryIsDedicatedAlloc, outMappedPtr);
1757}
1758
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001759static uint32_t lastGoodTypeIndex(uint32_t indices) {
Lingfeng Yang76906892020-10-26 11:10:46 -07001760 for (int32_t i = 31; i >= 0; --i) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001761 if (indices & (1 << i)) {
1762 return i;
1763 }
1764 }
1765 return 0;
1766}
1767
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001768static uint32_t lastGoodTypeIndexWithMemoryProperties(uint32_t indices,
1769 VkMemoryPropertyFlags memoryProperty) {
Lingfeng Yang76906892020-10-26 11:10:46 -07001770 for (int32_t i = 31; i >= 0; --i) {
1771 if ((indices & (1u << i)) &&
1772 (!memoryProperty ||
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001773 (sVkEmulation->deviceInfo.memProps.memoryTypes[i].propertyFlags & memoryProperty))) {
Lingfeng Yang76906892020-10-26 11:10:46 -07001774 return i;
1775 }
1776 }
1777 return 0;
1778}
1779
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001780// pNext, sharingMode, queueFamilyIndexCount, pQueueFamilyIndices, and initialLayout won't be
1781// filled.
1782static std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo_locked(
1783 VkFormat format, uint32_t width, uint32_t height, VkImageTiling tiling) {
Kaiyi Li71874cc2022-08-22 08:40:46 -07001784 const VkEmulation::ImageSupportInfo* maybeImageSupportInfo = nullptr;
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001785 for (const auto& supportInfo : sVkEmulation->imageSupportInfo) {
1786 if (supportInfo.format == format && supportInfo.supported) {
Kaiyi Li71874cc2022-08-22 08:40:46 -07001787 maybeImageSupportInfo = &supportInfo;
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001788 break;
1789 }
1790 }
Kaiyi Li71874cc2022-08-22 08:40:46 -07001791 if (!maybeImageSupportInfo) {
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001792 ERR("Format %s is not supported.", string_VkFormat(format));
1793 return nullptr;
1794 }
Kaiyi Li71874cc2022-08-22 08:40:46 -07001795 const VkEmulation::ImageSupportInfo& imageSupportInfo = *maybeImageSupportInfo;
1796 const VkFormatProperties& formatProperties = imageSupportInfo.formatProps2.formatProperties;
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001797
1798 constexpr std::pair<VkFormatFeatureFlags, VkImageUsageFlags> formatUsagePairs[] = {
Jason Macnakb9055d72022-04-06 10:40:14 -07001799 {VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT,
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001800 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT},
1801 {VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, VK_IMAGE_USAGE_SAMPLED_BIT},
1802 {VK_FORMAT_FEATURE_TRANSFER_SRC_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT},
1803 {VK_FORMAT_FEATURE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT},
1804 {VK_FORMAT_FEATURE_BLIT_SRC_BIT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT},
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001805 };
1806 VkFormatFeatureFlags tilingFeatures = (tiling == VK_IMAGE_TILING_OPTIMAL)
1807 ? formatProperties.optimalTilingFeatures
1808 : formatProperties.linearTilingFeatures;
1809
1810 VkImageUsageFlags usage = 0;
1811 for (const auto& formatUsage : formatUsagePairs) {
1812 usage |= (tilingFeatures & formatUsage.first) ? formatUsage.second : 0u;
1813 }
1814
1815 return std::make_unique<VkImageCreateInfo>(VkImageCreateInfo{
1816 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1817 // The caller is responsible to fill pNext.
1818 .pNext = nullptr,
Kaiyi Li71874cc2022-08-22 08:40:46 -07001819 .flags = imageSupportInfo.createFlags,
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001820 .imageType = VK_IMAGE_TYPE_2D,
1821 .format = format,
1822 .extent =
1823 {
1824 .width = width,
1825 .height = height,
1826 .depth = 1,
1827 },
1828 .mipLevels = 1,
1829 .arrayLayers = 1,
1830 .samples = VK_SAMPLE_COUNT_1_BIT,
1831 .tiling = tiling,
1832 .usage = usage,
1833 // The caller is responsible to fill sharingMode.
1834 .sharingMode = VK_SHARING_MODE_MAX_ENUM,
1835 // The caller is responsible to fill queueFamilyIndexCount.
1836 .queueFamilyIndexCount = 0,
1837 // The caller is responsible to fill pQueueFamilyIndices.
1838 .pQueueFamilyIndices = nullptr,
1839 // The caller is responsible to fill initialLayout.
1840 .initialLayout = VK_IMAGE_LAYOUT_MAX_ENUM,
1841 });
1842}
1843
1844std::unique_ptr<VkImageCreateInfo> generateColorBufferVkImageCreateInfo(VkFormat format,
1845 uint32_t width,
1846 uint32_t height,
1847 VkImageTiling tiling) {
1848 if (!sVkEmulation || !sVkEmulation->live) {
1849 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
1850 }
1851 AutoLock lock(sVkEmulationLock);
1852 return generateColorBufferVkImageCreateInfo_locked(format, width, height, tiling);
1853}
1854
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001855static bool updateExternalMemoryInfo(VK_EXT_MEMORY_HANDLE extMemHandle,
1856 const VkMemoryRequirements* pMemReqs,
1857 VkEmulation::ExternalMemoryInfo* pInfo) {
1858 // Set externalHandle on the output info
1859 pInfo->externalHandle = extMemHandle;
1860
1861#if defined(__QNX__)
1862 VkScreenBufferPropertiesQNX screenBufferProps = {
1863 VK_STRUCTURE_TYPE_SCREEN_BUFFER_PROPERTIES_QNX,
1864 0,
1865 };
1866 auto vk = sVkEmulation->dvk;
1867 VkResult queryRes =
1868 vk->vkGetScreenBufferPropertiesQNX(sVkEmulation->device, extMemHandle, &screenBufferProps);
1869 if (VK_SUCCESS != queryRes) {
1870 VK_COMMON_ERROR("Failed to get QNX Screen Buffer properties, VK error: %d", queryRes);
1871 return false;
1872 }
1873 if (!((1 << pInfo->typeIndex) & screenBufferProps.memoryTypeBits)) {
1874 VK_COMMON_ERROR("QNX Screen buffer can not be imported to memory (typeIndex=%d): %d",
1875 pInfo->typeIndex);
1876 return false;
1877 }
1878 if (screenBufferProps.allocationSize < pMemReqs->size) {
1879 VK_COMMON_ERROR(
1880 "QNX Screen buffer allocationSize (0x%lx) is not large enough for ColorBuffer image "
1881 "size requirements (0x%lx)",
1882 screenBufferProps.allocationSize, pMemReqs->size);
1883 return false;
1884 }
1885 // Use the actual allocationSize for VkDeviceMemory object creation
1886 pInfo->size = screenBufferProps.allocationSize;
1887#endif
1888
1889 return true;
1890}
1891
Lingfeng Yang76906892020-10-26 11:10:46 -07001892// TODO(liyl): Currently we can only specify required memoryProperty
1893// for a color buffer.
1894//
1895// Ideally we would like to specify a memory type index directly from
1896// localAllocInfo.memoryTypeIndex when allocating color buffers in
1897// vkAllocateMemory(). But this type index mechanism breaks "Modify the
1898// allocation size and type index to suit the resulting image memory
1899// size." which seems to be needed to keep the Android/Fuchsia guest
1900// memory type index consistent across guest allocations, and without
1901// which those guests might end up import allocating from a color buffer
1902// with mismatched type indices.
1903//
1904// We should make it so the guest can only allocate external images/
1905// buffers of one type index for image and one type index for buffer
1906// to begin with, via filtering from the host.
Jason Macnak12c1c392023-03-14 15:15:38 -07001907
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001908bool initializeVkColorBufferLocked(
1909 uint32_t colorBufferHandle, VK_EXT_MEMORY_HANDLE extMemHandle = VK_EXT_MEMORY_HANDLE_INVALID) {
1910 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
1911 // Not initialized
1912 if (!infoPtr) {
Jason Macnak5cd7f792023-02-23 00:40:01 +00001913 return false;
1914 }
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001915 // Already initialized Vulkan memory and other related Vulkan objects
1916 if (infoPtr->initialized) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001917 return true;
1918 }
1919
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001920 if (!isFormatVulkanCompatible(infoPtr->internalFormat)) {
1921 VK_COMMON_VERBOSE("Failed to create Vk ColorBuffer: format:%d not compatible.",
1922 infoPtr->internalFormat);
1923 return false;
1924 }
1925
1926 if ((VK_EXT_MEMORY_HANDLE_INVALID != extMemHandle) &&
1927 (!sVkEmulation->deviceInfo.supportsExternalMemoryImport)) {
1928 VK_COMMON_ERROR(
1929 "Failed to initialize Vk ColorBuffer -- extMemHandle provided, but device does "
1930 "not support externalMemoryImport");
1931 return false;
1932 }
1933
Lingfeng Yang76906892020-10-26 11:10:46 -07001934 VkFormat vkFormat;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001935 bool glCompatible = (infoPtr->frameworkFormat == FRAMEWORK_FORMAT_GL_COMPATIBLE);
1936 switch (infoPtr->frameworkFormat) {
Lingfeng Yang76906892020-10-26 11:10:46 -07001937 case FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE:
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001938 vkFormat = glFormat2VkFormat(infoPtr->internalFormat);
Lingfeng Yang76906892020-10-26 11:10:46 -07001939 break;
1940 case FrameworkFormat::FRAMEWORK_FORMAT_NV12:
1941 vkFormat = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
1942 break;
Jason Macnakedf28582022-06-02 17:46:37 -07001943 case FrameworkFormat::FRAMEWORK_FORMAT_P010:
1944 vkFormat = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
1945 break;
Lingfeng Yang76906892020-10-26 11:10:46 -07001946 case FrameworkFormat::FRAMEWORK_FORMAT_YV12:
1947 case FrameworkFormat::FRAMEWORK_FORMAT_YUV_420_888:
1948 vkFormat = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
1949 break;
1950 default:
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001951 VK_COMMON_ERROR("WARNING: unhandled framework format %d\n", infoPtr->frameworkFormat);
1952 vkFormat = glFormat2VkFormat(infoPtr->internalFormat);
Lingfeng Yang76906892020-10-26 11:10:46 -07001953 break;
1954 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001955
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001956 VkImageTiling tiling = (infoPtr->memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001957 ? VK_IMAGE_TILING_LINEAR
1958 : VK_IMAGE_TILING_OPTIMAL;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001959 std::unique_ptr<VkImageCreateInfo> imageCi = generateColorBufferVkImageCreateInfo_locked(
1960 vkFormat, infoPtr->width, infoPtr->height, tiling);
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001961 // pNext will be filled later.
JP Cottin3a11fc32023-03-22 21:30:22 +00001962 if (imageCi == nullptr) {
1963 // it can happen if the format is not supported
1964 return false;
1965 }
Kaiyi Licd9e14d2021-12-09 22:08:51 +00001966 imageCi->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1967 imageCi->queueFamilyIndexCount = 0;
1968 imageCi->pQueueFamilyIndices = nullptr;
1969 imageCi->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Lingfeng Yang76906892020-10-26 11:10:46 -07001970
Aaron Ruby7f5aaab2023-12-05 17:21:34 -05001971 auto imageCiChain = vk_make_chain_iterator(imageCi.get());
1972
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001973 // Create the image. If external memory is supported, make it external.
1974 VkExternalMemoryImageCreateInfo extImageCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07001975 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
1976 0,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001977 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
1978 };
1979
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05001980 if (sVkEmulation->deviceInfo.supportsExternalMemoryImport ||
1981 sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
Aaron Ruby7f5aaab2023-12-05 17:21:34 -05001982 vk_append_struct(&imageCiChain, &extImageCi);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001983 }
1984
Aaron Ruby7f5aaab2023-12-05 17:21:34 -05001985#if defined(__QNX__)
1986 VkExternalFormatQNX externalFormatQnx = {
1987 .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_QNX,
1988 .pNext = NULL,
1989 .externalFormat = 0, /* Do not override screen format */
1990 };
1991 if (VK_EXT_MEMORY_HANDLE_INVALID != extMemHandle) {
1992 vk_append_struct(&imageCiChain, &externalFormatQnx);
1993 /* Maintain linear tiling on QNX for downstream display controller interaction */
1994 imageCi->tiling = VK_IMAGE_TILING_LINEAR;
1995 }
1996#endif
Lingfeng Yangea978ce2019-12-13 13:42:23 -08001997
Jason Macnak5fb22712023-02-23 00:40:01 +00001998 auto vk = sVkEmulation->dvk;
1999
Kaiyi Licd9e14d2021-12-09 22:08:51 +00002000 VkResult createRes =
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002001 vk->vkCreateImage(sVkEmulation->device, imageCi.get(), nullptr, &infoPtr->image);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002002 if (createRes != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002003 // LOG(VERBOSE) << "Failed to create Vulkan image for ColorBuffer "
2004 // << colorBufferHandle;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002005 return false;
2006 }
2007
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002008 bool useDedicated =
2009 sVkEmulation->useDedicatedAllocations || (VK_EXT_MEMORY_HANDLE_INVALID != extMemHandle);
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002010
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002011 infoPtr->imageCreateInfoShallow = vk_make_orphan_copy(*imageCi);
2012 infoPtr->currentLayout = infoPtr->imageCreateInfoShallow.initialLayout;
2013 infoPtr->currentQueueFamilyIndex = sVkEmulation->queueFamilyIndex;
Jason Macnakb112ade2022-05-06 13:42:07 -07002014
Jason Macnak04b19042023-02-28 15:47:05 -08002015 if (!useDedicated && vk->vkGetImageMemoryRequirements2KHR) {
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002016 VkMemoryDedicatedRequirements dedicated_reqs{
2017 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, nullptr};
2018 VkMemoryRequirements2 reqs{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicated_reqs};
2019
2020 VkImageMemoryRequirementsInfo2 info{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002021 nullptr, infoPtr->image};
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002022 vk->vkGetImageMemoryRequirements2KHR(sVkEmulation->device, &info, &reqs);
Jason Macnak04b19042023-02-28 15:47:05 -08002023 useDedicated = dedicated_reqs.requiresDedicatedAllocation;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002024 infoPtr->memReqs = reqs.memoryRequirements;
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002025 } else {
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002026 vk->vkGetImageMemoryRequirements(sVkEmulation->device, infoPtr->image, &infoPtr->memReqs);
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002027 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002028
Lingfeng Yang76906892020-10-26 11:10:46 -07002029 // Currently we only care about two memory properties: DEVICE_LOCAL
2030 // and HOST_VISIBLE; other memory properties specified in
2031 // rcSetColorBufferVulkanMode2() call will be ignored for now.
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002032 infoPtr->memoryProperty = infoPtr->memoryProperty & (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
2033 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
Lingfeng Yang76906892020-10-26 11:10:46 -07002034
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002035 infoPtr->memory.size = infoPtr->memReqs.size;
Lingfeng Yang76906892020-10-26 11:10:46 -07002036
2037 // Determine memory type.
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002038 if (infoPtr->memoryProperty) {
2039 infoPtr->memory.typeIndex = lastGoodTypeIndexWithMemoryProperties(
2040 infoPtr->memReqs.memoryTypeBits, infoPtr->memoryProperty);
Lingfeng Yang76906892020-10-26 11:10:46 -07002041 } else {
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002042 infoPtr->memory.typeIndex = lastGoodTypeIndex(infoPtr->memReqs.memoryTypeBits);
Lingfeng Yang76906892020-10-26 11:10:46 -07002043 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002044
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002045 // LOG(VERBOSE) << "ColorBuffer " << colorBufferHandle
2046 // << ", allocation size and type index: " << res.memory.size
2047 // << ", " << res.memory.typeIndex
2048 // << ", allocated memory property: "
2049 // << sVkEmulation->deviceInfo.memProps
2050 // .memoryTypes[res.memory.typeIndex]
2051 // .propertyFlags
2052 // << ", requested memory property: " << memoryProperty;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002053
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002054 Optional<VkImage> dedicatedImage = useDedicated ? Optional<VkImage>(infoPtr->image) : kNullopt;
2055 if (VK_EXT_MEMORY_HANDLE_INVALID != extMemHandle) {
2056 if (!updateExternalMemoryInfo(extMemHandle, &infoPtr->memReqs, &infoPtr->memory)) {
2057 VK_COMMON_ERROR(
2058 "Failed to update external memory info for ColorBuffer: %d\n",
2059 colorBufferHandle);
2060 return false;
2061 }
2062 if (!importExternalMemoryDedicatedImage(vk, sVkEmulation->device, &infoPtr->memory,
2063 *dedicatedImage, &infoPtr->memory.memory)) {
2064 VK_COMMON_ERROR(
2065 "Failed to import external memory with dedicated Image for colorBuffer: %d\n",
2066 colorBufferHandle);
2067 return false;
2068 }
2069 } else {
2070 bool isHostVisible = infoPtr->memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
2071 Optional<uint64_t> deviceAlignment =
2072 isHostVisible ? Optional<uint64_t>(infoPtr->memReqs.alignment) : kNullopt;
2073 bool allocRes = allocExternalMemory(vk, &infoPtr->memory, true /*actuallyExternal*/,
2074 deviceAlignment, kNullopt, dedicatedImage);
2075 if (!allocRes) {
2076 // LOG(VERBOSE) << "Failed to allocate ColorBuffer with Vulkan backing.";
2077 return false;
2078 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002079 }
2080
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002081 infoPtr->memory.pageOffset = reinterpret_cast<uint64_t>(infoPtr->memory.mappedPtr) % kPageSize;
2082 infoPtr->memory.bindOffset =
2083 infoPtr->memory.pageOffset ? kPageSize - infoPtr->memory.pageOffset : 0u;
Lingfeng Yang76906892020-10-26 11:10:46 -07002084
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002085 VkResult bindImageMemoryRes = vk->vkBindImageMemory(
2086 sVkEmulation->device, infoPtr->image, infoPtr->memory.memory, infoPtr->memory.bindOffset);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002087
2088 if (bindImageMemoryRes != VK_SUCCESS) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002089 fprintf(stderr, "%s: Failed to bind image memory. %d\n", __func__, bindImageMemoryRes);
Lingfeng Yang76906892020-10-26 11:10:46 -07002090 return false;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002091 }
2092
Jason Macnak741afe72022-04-14 08:19:52 -07002093 const VkImageViewCreateInfo imageViewCi = {
2094 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
2095 .pNext = nullptr,
2096 .flags = 0,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002097 .image = infoPtr->image,
Jason Macnak741afe72022-04-14 08:19:52 -07002098 .viewType = VK_IMAGE_VIEW_TYPE_2D,
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002099 .format = infoPtr->imageCreateInfoShallow.format,
Jason Macnak741afe72022-04-14 08:19:52 -07002100 .components =
2101 {
2102 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
2103 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
2104 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
2105 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
2106 },
2107 .subresourceRange =
2108 {
2109 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2110 .baseMipLevel = 0,
2111 .levelCount = 1,
2112 .baseArrayLayer = 0,
2113 .layerCount = 1,
2114 },
2115 };
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002116 createRes =
2117 vk->vkCreateImageView(sVkEmulation->device, &imageViewCi, nullptr, &infoPtr->imageView);
Jason Macnak741afe72022-04-14 08:19:52 -07002118 if (createRes != VK_SUCCESS) {
2119 // LOG(VERBOSE) << "Failed to create Vulkan image for ColorBuffer "
2120 // << colorBufferHandle;
2121 return false;
2122 }
2123
Kaiyi Lia9bf3672022-09-08 18:47:43 -07002124#if defined(VK_MVK_moltenvk) && defined(__APPLE__)
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002125 if (sVkEmulation->instanceSupportsMoltenVK) {
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002126 sVkEmulation->getMTLTextureFunc(infoPtr->image, &infoPtr->mtlTexture);
2127 if (!infoPtr->mtlTexture) {
Doug Hornefb17962021-01-07 16:17:34 -08002128 fprintf(stderr, "%s: Failed to get MTLTexture.\n", __func__);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002129 }
Doug Hornefb17962021-01-07 16:17:34 -08002130
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002131 CFRetain(infoPtr->mtlTexture);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002132 }
Kaiyi Lia9bf3672022-09-08 18:47:43 -07002133#endif
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002134
Jason Macnak5c76bdb2024-01-30 09:07:34 -08002135 sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->image, "ColorBuffer:%d",
2136 colorBufferHandle);
2137 sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->imageView, "ColorBuffer:%d",
2138 colorBufferHandle);
2139 sVkEmulation->debugUtilsHelper.addDebugLabel(infoPtr->memory.memory, "ColorBuffer:%d",
2140 colorBufferHandle);
2141
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002142 infoPtr->initialized = true;
2143
2144 return true;
2145}
2146
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002147static bool createVkColorBufferLocked(uint32_t width, uint32_t height, GLenum internalFormat,
2148 FrameworkFormat frameworkFormat, uint32_t colorBufferHandle,
2149 bool vulkanOnly, uint32_t memoryProperty) {
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002150 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2151 // Already initialized
2152 if (infoPtr) {
2153 return true;
2154 }
2155
2156 VkEmulation::ColorBufferInfo res;
2157
2158 res.handle = colorBufferHandle;
2159 res.width = width;
2160 res.height = height;
2161 res.memoryProperty = memoryProperty;
2162 res.internalFormat = internalFormat;
2163 res.frameworkFormat = frameworkFormat;
2164 res.frameworkStride = 0;
2165
Kaiyi Li2cb8a1f2022-08-30 15:55:15 -07002166 if (vulkanOnly) {
2167 res.vulkanMode = VkEmulation::VulkanMode::VulkanOnly;
2168 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002169
Kaiyi Li5509d442021-10-18 15:13:46 -07002170 sVkEmulation->colorBuffers[colorBufferHandle] = res;
Lingfeng Yang76906892020-10-26 11:10:46 -07002171 return true;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002172}
2173
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002174bool createVkColorBuffer(uint32_t width, uint32_t height, GLenum internalFormat,
2175 FrameworkFormat frameworkFormat, uint32_t colorBufferHandle,
2176 bool vulkanOnly, uint32_t memoryProperty) {
Jason Macnak12c1c392023-03-14 15:15:38 -07002177 if (!sVkEmulation || !sVkEmulation->live) {
2178 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "VkEmulation not available.";
2179 }
2180
2181 AutoLock lock(sVkEmulationLock);
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002182 if (!createVkColorBufferLocked(width, height, internalFormat, frameworkFormat,
2183 colorBufferHandle, vulkanOnly, memoryProperty)) {
2184 return false;
2185 }
2186
2187 const auto& deviceInfo = sVkEmulation->deviceInfo;
2188 if (!deviceInfo.supportsExternalMemoryExport && deviceInfo.supportsExternalMemoryImport) {
2189 /* Returns, deferring initialization of the Vulkan components themselves.
2190 * Platforms that support import but not export of external memory must
2191 * use importExtMemoryHandleToVkColorBuffer(). Otherwise, the colorBuffer
2192 * memory can not be externalized.
2193 */
2194 return true;
2195 }
2196
2197 return initializeVkColorBufferLocked(colorBufferHandle);
Jason Macnak12c1c392023-03-14 15:15:38 -07002198}
2199
Jason Macnak9e9c68e2023-02-23 00:40:01 +00002200std::optional<VkColorBufferMemoryExport> exportColorBufferMemory(uint32_t colorBufferHandle) {
2201 if (!sVkEmulation || !sVkEmulation->live) {
2202 return std::nullopt;
2203 }
2204
2205 AutoLock lock(sVkEmulationLock);
2206
2207 const auto& deviceInfo = sVkEmulation->deviceInfo;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002208 if ((!(deviceInfo.supportsExternalMemoryExport || !deviceInfo.supportsExternalMemoryImport)) ||
2209 (!deviceInfo.glInteropSupported)) {
Jason Macnak9e9c68e2023-02-23 00:40:01 +00002210 return std::nullopt;
2211 }
2212
2213 auto info = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2214 if (!info) {
2215 return std::nullopt;
2216 }
2217
2218 if (info->frameworkFormat != FRAMEWORK_FORMAT_GL_COMPATIBLE) {
2219 return std::nullopt;
2220 }
2221
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002222#if !defined(__QNX__)
2223 ManagedDescriptor descriptor(dupExternalMemory(info->memory.externalHandle));
Jason Macnak9e9c68e2023-02-23 00:40:01 +00002224
2225 info->glExported = true;
2226
2227 return VkColorBufferMemoryExport{
2228 .descriptor = std::move(descriptor),
2229 .size = info->memory.size,
2230 .linearTiling = info->imageCreateInfoShallow.tiling == VK_IMAGE_TILING_LINEAR,
Jason Macnakcc53a202023-02-23 00:40:01 +00002231 .dedicatedAllocation = info->memory.dedicatedAllocation,
Jason Macnak9e9c68e2023-02-23 00:40:01 +00002232 };
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002233#else
2234 return std::nullopt;
2235#endif
Jason Macnak9e9c68e2023-02-23 00:40:01 +00002236}
2237
Jason Macnak12c1c392023-03-14 15:15:38 -07002238bool teardownVkColorBufferLocked(uint32_t colorBufferHandle) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002239 if (!sVkEmulation || !sVkEmulation->live) return false;
2240
2241 auto vk = sVkEmulation->dvk;
2242
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002243 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2244
2245 if (!infoPtr) return false;
2246
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002247 if (infoPtr->initialized) {
2248 auto& info = *infoPtr;
2249 {
2250 android::base::AutoLock lock(*sVkEmulation->queueLock);
2251 VK_CHECK(vk->vkQueueWaitIdle(sVkEmulation->queue));
2252 }
2253 vk->vkDestroyImageView(sVkEmulation->device, info.imageView, nullptr);
2254 vk->vkDestroyImage(sVkEmulation->device, info.image, nullptr);
2255 freeExternalMemoryLocked(vk, &info.memory);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002256
2257#ifdef __APPLE__
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002258 if (info.mtlTexture) {
2259 CFRelease(info.mtlTexture);
2260 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002261#endif
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002262 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002263
2264 sVkEmulation->colorBuffers.erase(colorBufferHandle);
2265
2266 return true;
2267}
2268
Jason Macnak12c1c392023-03-14 15:15:38 -07002269bool teardownVkColorBuffer(uint32_t colorBufferHandle) {
2270 if (!sVkEmulation || !sVkEmulation->live) return false;
2271
2272 AutoLock lock(sVkEmulationLock);
2273 return teardownVkColorBufferLocked(colorBufferHandle);
2274}
2275
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002276bool importExtMemoryHandleToVkColorBuffer(uint32_t colorBufferHandle, uint32_t type,
2277 VK_EXT_MEMORY_HANDLE extMemHandle) {
2278 if (!sVkEmulation || !sVkEmulation->live) {
2279 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "VkEmulation not available.";
2280 }
2281 if (VK_EXT_MEMORY_HANDLE_INVALID == extMemHandle) {
2282 return false;
2283 }
2284
2285 AutoLock lock(sVkEmulationLock);
2286 // Initialize the colorBuffer with the external memory handle
2287 // Note that this will fail if the colorBuffer memory was previously initialized.
2288 return initializeVkColorBufferLocked(colorBufferHandle, extMemHandle);
2289}
2290
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002291VkEmulation::ColorBufferInfo getColorBufferInfo(uint32_t colorBufferHandle) {
2292 VkEmulation::ColorBufferInfo res;
2293
2294 AutoLock lock(sVkEmulationLock);
2295
2296 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2297
2298 if (!infoPtr) return res;
2299
2300 res = *infoPtr;
2301 return res;
2302}
2303
Jason Macnak04363002023-02-23 00:40:01 +00002304bool colorBufferNeedsUpdateBetweenGlAndVk(const VkEmulation::ColorBufferInfo& colorBufferInfo) {
Jason Macnak7b94cd22022-04-19 14:58:35 -07002305 // GL is not used.
2306 if (colorBufferInfo.vulkanMode == VkEmulation::VulkanMode::VulkanOnly) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002307 return false;
2308 }
2309
Jason Macnak7b94cd22022-04-19 14:58:35 -07002310 // YUV formats require extra conversions.
2311 if (colorBufferInfo.frameworkFormat != FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002312 return true;
2313 }
2314
Jason Macnak7b94cd22022-04-19 14:58:35 -07002315 // GL and VK are sharing the same underlying memory.
2316 if (colorBufferInfo.glExported) {
2317 return false;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002318 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002319
2320 return true;
2321}
2322
Jason Macnak04363002023-02-23 00:40:01 +00002323bool colorBufferNeedsUpdateBetweenGlAndVk(uint32_t colorBufferHandle) {
2324 if (!sVkEmulation || !sVkEmulation->live) {
2325 return false;
2326 }
2327
2328 AutoLock lock(sVkEmulationLock);
2329
2330 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2331 if (!colorBufferInfo) {
2332 return false;
2333 }
2334
2335 return colorBufferNeedsUpdateBetweenGlAndVk(*colorBufferInfo);
2336}
2337
2338bool readColorBufferToBytes(uint32_t colorBufferHandle, std::vector<uint8_t>* bytes) {
Jason Macnak7b94cd22022-04-19 14:58:35 -07002339 if (!sVkEmulation || !sVkEmulation->live) {
Yahan Zhou81680452022-07-28 10:46:13 -07002340 VK_COMMON_VERBOSE("VkEmulation not available.");
Jason Macnak7b94cd22022-04-19 14:58:35 -07002341 return false;
2342 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002343
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002344 AutoLock lock(sVkEmulationLock);
2345
Jason Macnak7b94cd22022-04-19 14:58:35 -07002346 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2347 if (!colorBufferInfo) {
Yahan Zhou81680452022-07-28 10:46:13 -07002348 VK_COMMON_VERBOSE("Failed to read from ColorBuffer:%d, not found.", colorBufferHandle);
Jason Macnak04363002023-02-23 00:40:01 +00002349 bytes->clear();
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002350 return false;
2351 }
2352
Jason Macnak7b94cd22022-04-19 14:58:35 -07002353 VkDeviceSize bytesNeeded = 0;
2354 bool result = getFormatTransferInfo(colorBufferInfo->imageCreateInfoShallow.format,
2355 colorBufferInfo->imageCreateInfoShallow.extent.width,
2356 colorBufferInfo->imageCreateInfoShallow.extent.height,
2357 &bytesNeeded, nullptr);
2358 if (!result) {
2359 VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, failed to get read size.",
2360 colorBufferHandle);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002361 return false;
2362 }
2363
Jason Macnak04363002023-02-23 00:40:01 +00002364 bytes->resize(bytesNeeded);
Jason Macnak7b94cd22022-04-19 14:58:35 -07002365
Gurchetan Singhcff99952022-10-14 13:02:03 -07002366 result = readColorBufferToBytesLocked(
Jason Macnak7b94cd22022-04-19 14:58:35 -07002367 colorBufferHandle, 0, 0, colorBufferInfo->imageCreateInfoShallow.extent.width,
Jason Macnak04363002023-02-23 00:40:01 +00002368 colorBufferInfo->imageCreateInfoShallow.extent.height, bytes->data());
Jason Macnak7b94cd22022-04-19 14:58:35 -07002369 if (!result) {
2370 VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, failed to get read size.",
2371 colorBufferHandle);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002372 return false;
2373 }
2374
Jason Macnak04363002023-02-23 00:40:01 +00002375 return true;
Jason Macnak7b94cd22022-04-19 14:58:35 -07002376}
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002377
Jason Macnak7b94cd22022-04-19 14:58:35 -07002378bool readColorBufferToBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
2379 uint32_t h, void* outPixels) {
2380 if (!sVkEmulation || !sVkEmulation->live) {
2381 VK_COMMON_ERROR("VkEmulation not available.");
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002382 return false;
2383 }
2384
Jason Macnak7b94cd22022-04-19 14:58:35 -07002385 AutoLock lock(sVkEmulationLock);
2386 return readColorBufferToBytesLocked(colorBufferHandle, x, y, w, h, outPixels);
2387}
2388
2389bool readColorBufferToBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
2390 uint32_t h, void* outPixels) {
2391 if (!sVkEmulation || !sVkEmulation->live) {
2392 VK_COMMON_ERROR("VkEmulation not available.");
2393 return false;
2394 }
2395
2396 auto vk = sVkEmulation->dvk;
2397
2398 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2399 if (!colorBufferInfo) {
2400 VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, not found.", colorBufferHandle);
2401 return false;
2402 }
2403
2404 if (!colorBufferInfo->image) {
2405 VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, no VkImage.", colorBufferHandle);
2406 return false;
2407 }
2408
2409 if (x != 0 || y != 0 || w != colorBufferInfo->imageCreateInfoShallow.extent.width ||
2410 h != colorBufferInfo->imageCreateInfoShallow.extent.height) {
2411 VK_COMMON_ERROR("Failed to read from ColorBuffer:%d, unhandled subrect.",
2412 colorBufferHandle);
2413 return false;
2414 }
2415
Yahan Zhoud7970e42022-08-05 10:51:24 -07002416 VkDeviceSize bufferCopySize = 0;
Jason Macnak7b94cd22022-04-19 14:58:35 -07002417 std::vector<VkBufferImageCopy> bufferImageCopies;
2418 if (!getFormatTransferInfo(colorBufferInfo->imageCreateInfoShallow.format,
2419 colorBufferInfo->imageCreateInfoShallow.extent.width,
2420 colorBufferInfo->imageCreateInfoShallow.extent.height,
2421 &bufferCopySize, &bufferImageCopies)) {
2422 VK_COMMON_ERROR("Failed to read ColorBuffer:%d, unable to get transfer info.",
2423 colorBufferHandle);
2424 return false;
2425 }
2426
2427 // Avoid transitioning from VK_IMAGE_LAYOUT_UNDEFINED. Unfortunetly, Android does not
2428 // yet have a mechanism for sharing the expected VkImageLayout. However, the Vulkan
2429 // spec's image layout transition sections says "If the old layout is
2430 // VK_IMAGE_LAYOUT_UNDEFINED, the contents of that range may be discarded." Some
2431 // Vulkan drivers have been observed to actually perform the discard which leads to
2432 // ColorBuffer-s being unintentionally cleared. See go/ahb-vkimagelayout for a more
2433 // thorough write up.
2434 if (colorBufferInfo->currentLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
2435 colorBufferInfo->currentLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
2436 }
2437
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002438 // Record our synchronization commands.
Jason Macnak7b94cd22022-04-19 14:58:35 -07002439 const VkCommandBufferBeginInfo beginInfo = {
2440 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2441 .pNext = nullptr,
2442 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002443 };
2444
Jason Macnak7b94cd22022-04-19 14:58:35 -07002445 VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002446
Jason Macnak7b94cd22022-04-19 14:58:35 -07002447 VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002448
Jason Macnak5c76bdb2024-01-30 09:07:34 -08002449 sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
2450 commandBuffer, "readColorBufferToBytes(ColorBuffer:%d)", colorBufferHandle);
2451
Jason Macnak7b94cd22022-04-19 14:58:35 -07002452 const VkImageMemoryBarrier toTransferSrcImageBarrier = {
2453 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2454 .pNext = nullptr,
2455 .srcAccessMask = 0,
2456 .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
2457 .oldLayout = colorBufferInfo->currentLayout,
2458 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2459 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2460 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2461 .image = colorBufferInfo->image,
2462 .subresourceRange =
2463 {
2464 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2465 .baseMipLevel = 0,
2466 .levelCount = 1,
2467 .baseArrayLayer = 0,
2468 .layerCount = 1,
2469 },
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002470 };
2471
Jason Macnak7b94cd22022-04-19 14:58:35 -07002472 vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002473 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
Jason Macnak7b94cd22022-04-19 14:58:35 -07002474 &toTransferSrcImageBarrier);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002475
Jason Macnak7b94cd22022-04-19 14:58:35 -07002476 colorBufferInfo->currentLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
Doug Horn0c2ea5a2021-10-29 17:30:16 -07002477
Jason Macnak7b94cd22022-04-19 14:58:35 -07002478 vk->vkCmdCopyImageToBuffer(commandBuffer, colorBufferInfo->image,
2479 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, sVkEmulation->staging.buffer,
2480 bufferImageCopies.size(), bufferImageCopies.data());
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002481
Jason Macnak5c76bdb2024-01-30 09:07:34 -08002482 sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
2483
Jason Macnak7b94cd22022-04-19 14:58:35 -07002484 VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002485
Jason Macnak7b94cd22022-04-19 14:58:35 -07002486 const VkSubmitInfo submitInfo = {
2487 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
2488 .pNext = nullptr,
2489 .waitSemaphoreCount = 0,
2490 .pWaitSemaphores = nullptr,
2491 .pWaitDstStageMask = nullptr,
2492 .commandBufferCount = 1,
2493 .pCommandBuffers = &commandBuffer,
2494 .signalSemaphoreCount = 0,
2495 .pSignalSemaphores = nullptr,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002496 };
2497
Kaiyi Li263e9f42021-08-20 07:33:05 -07002498 {
2499 android::base::AutoLock lock(*sVkEmulation->queueLock);
Jason Macnak7b94cd22022-04-19 14:58:35 -07002500 VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
2501 sVkEmulation->commandBufferFence));
Kaiyi Li263e9f42021-08-20 07:33:05 -07002502 }
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002503
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002504 static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002505
Jason Macnak7b94cd22022-04-19 14:58:35 -07002506 VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
2507 VK_TRUE, ANB_MAX_WAIT_NS));
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002508
Jason Macnak7b94cd22022-04-19 14:58:35 -07002509 VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
2510
2511 const VkMappedMemoryRange toInvalidate = {
2512 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
2513 .pNext = nullptr,
2514 .memory = sVkEmulation->staging.memory.memory,
2515 .offset = 0,
2516 .size = VK_WHOLE_SIZE,
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002517 };
2518
Jason Macnak7b94cd22022-04-19 14:58:35 -07002519 VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
2520
2521 const auto* stagingBufferPtr = sVkEmulation->staging.memory.mappedPtr;
2522 std::memcpy(outPixels, stagingBufferPtr, bufferCopySize);
2523
2524 return true;
2525}
2526
Jason Macnak04363002023-02-23 00:40:01 +00002527bool updateColorBufferFromBytes(uint32_t colorBufferHandle, const std::vector<uint8_t>& bytes) {
Jason Macnak7b94cd22022-04-19 14:58:35 -07002528 if (!sVkEmulation || !sVkEmulation->live) {
Yahan Zhou81680452022-07-28 10:46:13 -07002529 VK_COMMON_VERBOSE("VkEmulation not available.");
Jason Macnak7b94cd22022-04-19 14:58:35 -07002530 return false;
2531 }
2532
2533 AutoLock lock(sVkEmulationLock);
2534
2535 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2536 if (!colorBufferInfo) {
Yahan Zhou81680452022-07-28 10:46:13 -07002537 VK_COMMON_VERBOSE("Failed to update ColorBuffer:%d, not found.", colorBufferHandle);
Jason Macnak7b94cd22022-04-19 14:58:35 -07002538 return false;
2539 }
2540
Jason Macnak7b94cd22022-04-19 14:58:35 -07002541 return updateColorBufferFromBytesLocked(
2542 colorBufferHandle, 0, 0, colorBufferInfo->imageCreateInfoShallow.extent.width,
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002543 colorBufferInfo->imageCreateInfoShallow.extent.height, bytes.data(), bytes.size());
Jason Macnak7b94cd22022-04-19 14:58:35 -07002544}
2545
2546bool updateColorBufferFromBytes(uint32_t colorBufferHandle, uint32_t x, uint32_t y, uint32_t w,
2547 uint32_t h, const void* pixels) {
2548 if (!sVkEmulation || !sVkEmulation->live) {
2549 VK_COMMON_ERROR("VkEmulation not available.");
2550 return false;
2551 }
2552
Jason Macnak7b94cd22022-04-19 14:58:35 -07002553 AutoLock lock(sVkEmulationLock);
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002554 return updateColorBufferFromBytesLocked(colorBufferHandle, x, y, w, h, pixels, 0);
Jason Macnak7b94cd22022-04-19 14:58:35 -07002555}
2556
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002557static void convertRgbToRgbaPixels(void* dst, const void* src, uint32_t w, uint32_t h) {
2558 const size_t pixelCount = w * h;
2559 const uint8_t* srcBytes = reinterpret_cast<const uint8_t*>(src);
2560 uint32_t* dstPixels = reinterpret_cast<uint32_t*>(dst);
2561 for (size_t i = 0; i < pixelCount; ++i) {
2562 const uint8_t r = *(srcBytes++);
2563 const uint8_t g = *(srcBytes++);
2564 const uint8_t b = *(srcBytes++);
2565 *(dstPixels++) = 0xff000000 | (b << 16) | (g << 8) | r;
2566 }
2567}
2568
2569static bool updateColorBufferFromBytesLocked(uint32_t colorBufferHandle, uint32_t x, uint32_t y,
2570 uint32_t w, uint32_t h, const void* pixels,
2571 size_t inputPixelsSize) {
Jason Macnak7b94cd22022-04-19 14:58:35 -07002572 if (!sVkEmulation || !sVkEmulation->live) {
2573 VK_COMMON_ERROR("VkEmulation not available.");
2574 return false;
2575 }
2576
2577 auto vk = sVkEmulation->dvk;
2578
2579 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
2580 if (!colorBufferInfo) {
2581 VK_COMMON_ERROR("Failed to update ColorBuffer:%d, not found.", colorBufferHandle);
2582 return false;
2583 }
2584
2585 if (!colorBufferInfo->image) {
2586 VK_COMMON_ERROR("Failed to update ColorBuffer:%d, no VkImage.", colorBufferHandle);
2587 return false;
2588 }
2589
2590 if (x != 0 || y != 0 || w != colorBufferInfo->imageCreateInfoShallow.extent.width ||
2591 h != colorBufferInfo->imageCreateInfoShallow.extent.height) {
2592 VK_COMMON_ERROR("Failed to update ColorBuffer:%d, unhandled subrect.", colorBufferHandle);
2593 return false;
2594 }
2595
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002596 VkDeviceSize dstBufferSize = 0;
Jason Macnak7b94cd22022-04-19 14:58:35 -07002597 std::vector<VkBufferImageCopy> bufferImageCopies;
2598 if (!getFormatTransferInfo(colorBufferInfo->imageCreateInfoShallow.format,
2599 colorBufferInfo->imageCreateInfoShallow.extent.width,
2600 colorBufferInfo->imageCreateInfoShallow.extent.height,
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002601 &dstBufferSize, &bufferImageCopies)) {
Jason Macnak7b94cd22022-04-19 14:58:35 -07002602 VK_COMMON_ERROR("Failed to update ColorBuffer:%d, unable to get transfer info.",
2603 colorBufferHandle);
2604 return false;
2605 }
2606
2607 const VkDeviceSize stagingBufferSize = sVkEmulation->staging.size;
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002608 if (dstBufferSize > stagingBufferSize) {
Jason Macnak7b94cd22022-04-19 14:58:35 -07002609 VK_COMMON_ERROR("Failed to update ColorBuffer:%d, transfer size %" PRIu64
2610 " too large for staging buffer size:%" PRIu64 ".",
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002611 colorBufferHandle, dstBufferSize, stagingBufferSize);
2612 return false;
2613 }
2614
2615 bool isThreeByteRgb = (colorBufferInfo->internalFormat == GL_RGB ||
2616 colorBufferInfo->internalFormat == GL_RGB8);
2617 size_t expectedInputSize = (isThreeByteRgb ? dstBufferSize / 4 * 3 : dstBufferSize);
2618
2619 if (inputPixelsSize != 0 && inputPixelsSize != expectedInputSize) {
2620 VK_COMMON_ERROR(
2621 "Unexpected contents size when trying to update ColorBuffer:%d, "
2622 "provided:%zu expected:%zu",
2623 colorBufferHandle, inputPixelsSize, expectedInputSize);
Jason Macnak7b94cd22022-04-19 14:58:35 -07002624 return false;
2625 }
2626
2627 auto* stagingBufferPtr = sVkEmulation->staging.memory.mappedPtr;
Igor Chernysheved39a8d2023-12-21 11:03:24 -08002628
2629 if (isThreeByteRgb) {
2630 // Convert RGB to RGBA, since only for these types glFormat2VkFormat() makes
2631 // an incompatible choice of 4-byte backing VK_FORMAT_R8G8B8A8_UNORM.
2632 // b/281550953
2633 convertRgbToRgbaPixels(stagingBufferPtr, pixels, w, h);
2634 } else {
2635 std::memcpy(stagingBufferPtr, pixels, dstBufferSize);
2636 }
Jason Macnak7b94cd22022-04-19 14:58:35 -07002637
Lars Harrison70989772024-02-03 01:53:24 +00002638 // NOTE: Host vulkan state might not know the correct layout of the
2639 // destination image, as guest grallocs are designed to be used by either
2640 // GL or Vulkan. Consequently, we typically avoid image transitions from
2641 // VK_IMAGE_LAYOUT_UNDEFINED as Vulkan spec allows the contents to be
2642 // discarded (and some drivers have been observed doing it). You can
2643 // check go/ahb-vkimagelayout for more information. But since this
2644 // function does not allow subrects (see above), it will write the
2645 // provided contents onto the entirety of the target buffer, meaning this
2646 // risk of discarding data should not impact anything.
Jason Macnak7b94cd22022-04-19 14:58:35 -07002647
2648 // Record our synchronization commands.
2649 const VkCommandBufferBeginInfo beginInfo = {
2650 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
2651 .pNext = nullptr,
2652 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
2653 };
2654
2655 VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
2656
2657 VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
2658
Jason Macnak5c76bdb2024-01-30 09:07:34 -08002659 sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
2660 commandBuffer, "updateColorBufferFromBytes(ColorBuffer:%d)", colorBufferHandle);
2661
Jason Macnak7b94cd22022-04-19 14:58:35 -07002662 const VkImageMemoryBarrier toTransferDstImageBarrier = {
2663 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2664 .pNext = nullptr,
2665 .srcAccessMask = 0,
2666 .dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
2667 .oldLayout = colorBufferInfo->currentLayout,
2668 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2669 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2670 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
2671 .image = colorBufferInfo->image,
2672 .subresourceRange =
2673 {
2674 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2675 .baseMipLevel = 0,
2676 .levelCount = 1,
2677 .baseArrayLayer = 0,
2678 .layerCount = 1,
2679 },
2680 };
2681
2682 vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
2683 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
2684 &toTransferDstImageBarrier);
2685
2686 colorBufferInfo->currentLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2687
2688 // Copy to staging buffer
2689 vk->vkCmdCopyBufferToImage(commandBuffer, sVkEmulation->staging.buffer, colorBufferInfo->image,
2690 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, bufferImageCopies.size(),
2691 bufferImageCopies.data());
2692
Jason Macnak5c76bdb2024-01-30 09:07:34 -08002693 sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
2694
Jason Macnak7b94cd22022-04-19 14:58:35 -07002695 VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
2696
2697 const VkSubmitInfo submitInfo = {
2698 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
2699 .pNext = nullptr,
2700 .waitSemaphoreCount = 0,
2701 .pWaitSemaphores = nullptr,
2702 .pWaitDstStageMask = nullptr,
2703 .commandBufferCount = 1,
2704 .pCommandBuffers = &commandBuffer,
2705 .signalSemaphoreCount = 0,
2706 .pSignalSemaphores = nullptr,
2707 };
2708
2709 {
2710 android::base::AutoLock lock(*sVkEmulation->queueLock);
2711 VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
2712 sVkEmulation->commandBufferFence));
2713 }
2714
2715 static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
2716
2717 VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
2718 VK_TRUE, ANB_MAX_WAIT_NS));
2719
2720 VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
2721
2722 const VkMappedMemoryRange toInvalidate = {
2723 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
2724 .pNext = nullptr,
2725 .memory = sVkEmulation->staging.memory.memory,
2726 .offset = 0,
2727 .size = VK_WHOLE_SIZE,
2728 };
2729 VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
2730
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002731 return true;
2732}
2733
2734VK_EXT_MEMORY_HANDLE getColorBufferExtMemoryHandle(uint32_t colorBuffer) {
2735 if (!sVkEmulation || !sVkEmulation->live) return VK_EXT_MEMORY_HANDLE_INVALID;
2736
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002737 AutoLock lock(sVkEmulationLock);
2738
2739 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBuffer);
2740
2741 if (!infoPtr) {
2742 // Color buffer not found; this is usually OK.
2743 return VK_EXT_MEMORY_HANDLE_INVALID;
2744 }
2745
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002746 return infoPtr->memory.externalHandle;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002747}
2748
2749bool setColorBufferVulkanMode(uint32_t colorBuffer, uint32_t vulkanMode) {
2750 if (!sVkEmulation || !sVkEmulation->live) return VK_EXT_MEMORY_HANDLE_INVALID;
2751
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002752 AutoLock lock(sVkEmulationLock);
2753
2754 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBuffer);
2755
2756 if (!infoPtr) {
2757 return false;
2758 }
2759
Lingfeng Yang76906892020-10-26 11:10:46 -07002760 infoPtr->vulkanMode = static_cast<VkEmulation::VulkanMode>(vulkanMode);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002761
2762 return true;
2763}
2764
Doug Hornefb17962021-01-07 16:17:34 -08002765MTLTextureRef getColorBufferMTLTexture(uint32_t colorBuffer) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002766 if (!sVkEmulation || !sVkEmulation->live) return nullptr;
2767
2768 AutoLock lock(sVkEmulationLock);
2769
2770 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBuffer);
2771
2772 if (!infoPtr) {
2773 // Color buffer not found; this is usually OK.
2774 return nullptr;
2775 }
2776
2777#ifdef __APPLE__
Doug Hornefb17962021-01-07 16:17:34 -08002778 CFRetain(infoPtr->mtlTexture);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002779#endif
Doug Hornefb17962021-01-07 16:17:34 -08002780 return infoPtr->mtlTexture;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08002781}
2782
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002783int32_t mapGpaToBufferHandle(uint32_t bufferHandle, uint64_t gpa, uint64_t size) {
2784 if (!sVkEmulation || !sVkEmulation->live) return VK_ERROR_DEVICE_LOST;
Lingfeng Yang76906892020-10-26 11:10:46 -07002785
Lingfeng Yang76906892020-10-26 11:10:46 -07002786 AutoLock lock(sVkEmulationLock);
2787
2788 VkEmulation::ExternalMemoryInfo* memoryInfoPtr = nullptr;
2789
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002790 auto colorBufferInfoPtr = android::base::find(sVkEmulation->colorBuffers, bufferHandle);
Lingfeng Yang76906892020-10-26 11:10:46 -07002791 if (colorBufferInfoPtr) {
2792 memoryInfoPtr = &colorBufferInfoPtr->memory;
2793 }
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002794 auto bufferInfoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
Lingfeng Yang76906892020-10-26 11:10:46 -07002795 if (bufferInfoPtr) {
2796 memoryInfoPtr = &bufferInfoPtr->memory;
2797 }
2798
2799 if (!memoryInfoPtr) {
2800 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
2801 }
2802
2803 // memory should be already mapped to host.
2804 if (!memoryInfoPtr->mappedPtr) {
2805 return VK_ERROR_MEMORY_MAP_FAILED;
2806 }
2807
2808 memoryInfoPtr->gpa = gpa;
2809 memoryInfoPtr->pageAlignedHva =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002810 reinterpret_cast<uint8_t*>(memoryInfoPtr->mappedPtr) + memoryInfoPtr->bindOffset;
Lingfeng Yang76906892020-10-26 11:10:46 -07002811
2812 size_t rawSize = memoryInfoPtr->size + memoryInfoPtr->pageOffset;
2813 if (size && size < rawSize) {
2814 rawSize = size;
2815 }
2816
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002817 memoryInfoPtr->sizeToPage = ((rawSize + kPageSize - 1) >> kPageBits) << kPageBits;
Lingfeng Yang76906892020-10-26 11:10:46 -07002818
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002819 // LOG(VERBOSE) << "mapGpaToColorBuffer: hva = " << memoryInfoPtr->mappedPtr
2820 // << ", pageAlignedHva = " << memoryInfoPtr->pageAlignedHva
2821 // << " -> [ " << memoryInfoPtr->gpa << ", "
2822 // << memoryInfoPtr->gpa + memoryInfoPtr->sizeToPage << " ]";
Lingfeng Yang76906892020-10-26 11:10:46 -07002823
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002824 if (sVkEmulation->occupiedGpas.find(gpa) != sVkEmulation->occupiedGpas.end()) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002825 // emugl::emugl_crash_reporter("FATAL: already mapped gpa 0x%lx! ", gpa);
Lingfeng Yang76906892020-10-26 11:10:46 -07002826 return VK_ERROR_MEMORY_MAP_FAILED;
2827 }
2828
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002829 get_emugl_vm_operations().mapUserBackedRam(gpa, memoryInfoPtr->pageAlignedHva,
2830 memoryInfoPtr->sizeToPage);
Lingfeng Yang76906892020-10-26 11:10:46 -07002831
2832 sVkEmulation->occupiedGpas.insert(gpa);
2833
2834 return memoryInfoPtr->pageOffset;
2835}
2836
Jason Macnak5fb22712023-02-23 00:40:01 +00002837bool getBufferAllocationInfo(uint32_t bufferHandle, VkDeviceSize* outSize,
Jason Macnakcc53a202023-02-23 00:40:01 +00002838 uint32_t* outMemoryTypeIndex, bool* outMemoryIsDedicatedAlloc) {
Jason Macnak5fb22712023-02-23 00:40:01 +00002839 if (!sVkEmulation || !sVkEmulation->live) {
2840 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Vulkan emulation not available.";
2841 }
2842
2843 AutoLock lock(sVkEmulationLock);
2844
2845 auto info = android::base::find(sVkEmulation->buffers, bufferHandle);
2846 if (!info) {
2847 return false;
2848 }
2849
2850 if (outSize) {
2851 *outSize = info->memory.size;
2852 }
2853
2854 if (outMemoryTypeIndex) {
2855 *outMemoryTypeIndex = info->memory.typeIndex;
2856 }
2857
Jason Macnakcc53a202023-02-23 00:40:01 +00002858 if (outMemoryIsDedicatedAlloc) {
2859 *outMemoryIsDedicatedAlloc = info->memory.dedicatedAllocation;
2860 }
2861
Jason Macnak5fb22712023-02-23 00:40:01 +00002862 return true;
2863}
2864
Jason Macnak4c45edb2023-02-23 00:40:01 +00002865bool setupVkBuffer(uint64_t size, uint32_t bufferHandle, bool vulkanOnly, uint32_t memoryProperty) {
Lingfeng Yang76906892020-10-26 11:10:46 -07002866 if (vulkanOnly == false) {
Jason Macnak4c45edb2023-02-23 00:40:01 +00002867 VK_COMMON_ERROR("Data buffers should be vulkanOnly. Setup failed.");
Lingfeng Yang76906892020-10-26 11:10:46 -07002868 return false;
2869 }
2870
2871 auto vk = sVkEmulation->dvk;
Lingfeng Yang76906892020-10-26 11:10:46 -07002872
2873 AutoLock lock(sVkEmulationLock);
2874
2875 auto infoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
2876
2877 // Already setup
2878 if (infoPtr) {
Lingfeng Yang76906892020-10-26 11:10:46 -07002879 return true;
2880 }
2881
2882 VkEmulation::BufferInfo res;
2883
2884 res.handle = bufferHandle;
2885
2886 res.size = size;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002887 res.usageFlags = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
2888 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT |
2889 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
Lingfeng Yang76906892020-10-26 11:10:46 -07002890 res.createFlags = 0;
2891
2892 res.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
2893
2894 // Create the image. If external memory is supported, make it external.
2895 VkExternalMemoryBufferCreateInfo extBufferCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002896 VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
2897 0,
2898 VK_EXT_MEMORY_HANDLE_TYPE_BIT,
Lingfeng Yang76906892020-10-26 11:10:46 -07002899 };
2900
2901 VkExternalMemoryBufferCreateInfo* extBufferCiPtr = nullptr;
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05002902 if (sVkEmulation->deviceInfo.supportsExternalMemoryImport ||
2903 sVkEmulation->deviceInfo.supportsExternalMemoryExport) {
Lingfeng Yang76906892020-10-26 11:10:46 -07002904 extBufferCiPtr = &extBufferCi;
2905 }
2906
2907 VkBufferCreateInfo bufferCi = {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002908 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2909 extBufferCiPtr,
2910 res.createFlags,
2911 res.size,
2912 res.usageFlags,
2913 res.sharingMode,
2914 /* queueFamilyIndexCount */ 0,
2915 /* pQueueFamilyIndices */ nullptr,
Lingfeng Yang76906892020-10-26 11:10:46 -07002916 };
2917
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002918 VkResult createRes = vk->vkCreateBuffer(sVkEmulation->device, &bufferCi, nullptr, &res.buffer);
Lingfeng Yang76906892020-10-26 11:10:46 -07002919
2920 if (createRes != VK_SUCCESS) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002921 // LOG(VERBOSE) << "Failed to create Vulkan Buffer for Buffer "
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002922 // << bufferHandle;
Lingfeng Yang76906892020-10-26 11:10:46 -07002923 return false;
2924 }
Jason Macnak04b19042023-02-28 15:47:05 -08002925 bool useDedicated = false;
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002926 if (vk->vkGetBufferMemoryRequirements2KHR) {
2927 VkMemoryDedicatedRequirements dedicated_reqs{
2928 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, nullptr};
2929 VkMemoryRequirements2 reqs{VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicated_reqs};
Lingfeng Yang76906892020-10-26 11:10:46 -07002930
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002931 VkBufferMemoryRequirementsInfo2 info{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
2932 nullptr, res.buffer};
2933 vk->vkGetBufferMemoryRequirements2KHR(sVkEmulation->device, &info, &reqs);
Jason Macnak04b19042023-02-28 15:47:05 -08002934 useDedicated = dedicated_reqs.requiresDedicatedAllocation;
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002935 res.memReqs = reqs.memoryRequirements;
2936 } else {
2937 vk->vkGetBufferMemoryRequirements(sVkEmulation->device, res.buffer, &res.memReqs);
2938 }
Lingfeng Yang76906892020-10-26 11:10:46 -07002939
2940 // Currently we only care about two memory properties: DEVICE_LOCAL
2941 // and HOST_VISIBLE; other memory properties specified in
2942 // rcSetColorBufferVulkanMode2() call will be ignored for now.
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002943 memoryProperty = memoryProperty &
2944 (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
Lingfeng Yang76906892020-10-26 11:10:46 -07002945
2946 res.memory.size = res.memReqs.size;
2947
2948 // Determine memory type.
2949 if (memoryProperty) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002950 res.memory.typeIndex =
2951 lastGoodTypeIndexWithMemoryProperties(res.memReqs.memoryTypeBits, memoryProperty);
Lingfeng Yang76906892020-10-26 11:10:46 -07002952 } else {
2953 res.memory.typeIndex = lastGoodTypeIndex(res.memReqs.memoryTypeBits);
2954 }
2955
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002956 // LOG(VERBOSE) << "Buffer " << bufferHandle
2957 // << "allocation size and type index: " << res.memory.size
2958 // << ", " << res.memory.typeIndex
2959 // << ", allocated memory property: "
2960 // << sVkEmulation->deviceInfo.memProps
2961 // .memoryTypes[res.memory.typeIndex]
2962 // .propertyFlags
2963 // << ", requested memory property: " << memoryProperty;
Lingfeng Yang76906892020-10-26 11:10:46 -07002964
2965 bool isHostVisible = memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
2966 Optional<uint64_t> deviceAlignment =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002967 isHostVisible ? Optional<uint64_t>(res.memReqs.alignment) : kNullopt;
Jason Macnak04b19042023-02-28 15:47:05 -08002968 Optional<VkBuffer> dedicated_buffer = useDedicated ? Optional<VkBuffer>(res.buffer) : kNullopt;
Andrew Woloszynf7135ef2023-02-23 16:20:35 -05002969 bool allocRes = allocExternalMemory(vk, &res.memory, true /* actuallyExternal */,
2970 deviceAlignment, dedicated_buffer);
Lingfeng Yang76906892020-10-26 11:10:46 -07002971
2972 if (!allocRes) {
Lingfeng Yangc02cb032020-10-26 14:21:25 -07002973 // LOG(VERBOSE) << "Failed to allocate ColorBuffer with Vulkan backing.";
Lingfeng Yang76906892020-10-26 11:10:46 -07002974 }
2975
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002976 res.memory.pageOffset = reinterpret_cast<uint64_t>(res.memory.mappedPtr) % kPageSize;
2977 res.memory.bindOffset = res.memory.pageOffset ? kPageSize - res.memory.pageOffset : 0u;
Lingfeng Yang76906892020-10-26 11:10:46 -07002978
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002979 VkResult bindBufferMemoryRes =
2980 vk->vkBindBufferMemory(sVkEmulation->device, res.buffer, res.memory.memory, 0);
Lingfeng Yang76906892020-10-26 11:10:46 -07002981
2982 if (bindBufferMemoryRes != VK_SUCCESS) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002983 fprintf(stderr, "%s: Failed to bind buffer memory. %d\n", __func__, bindBufferMemoryRes);
Lingfeng Yang76906892020-10-26 11:10:46 -07002984 return bindBufferMemoryRes;
2985 }
2986
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002987 bool isHostVisibleMemory = memoryProperty & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
Lingfeng Yang76906892020-10-26 11:10:46 -07002988
2989 if (isHostVisibleMemory) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002990 VkResult mapMemoryRes = vk->vkMapMemory(sVkEmulation->device, res.memory.memory, 0,
2991 res.memory.size, {}, &res.memory.mappedPtr);
Lingfeng Yang76906892020-10-26 11:10:46 -07002992
2993 if (mapMemoryRes != VK_SUCCESS) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07002994 fprintf(stderr, "%s: Failed to map image memory. %d\n", __func__, mapMemoryRes);
Lingfeng Yang76906892020-10-26 11:10:46 -07002995 return false;
2996 }
2997 }
2998
2999 res.glExported = false;
Lingfeng Yang76906892020-10-26 11:10:46 -07003000
3001 sVkEmulation->buffers[bufferHandle] = res;
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003002
3003 sVkEmulation->debugUtilsHelper.addDebugLabel(res.buffer, "Buffer:%d", bufferHandle);
3004 sVkEmulation->debugUtilsHelper.addDebugLabel(res.memory.memory, "Buffer:%d", bufferHandle);
3005
Lingfeng Yang76906892020-10-26 11:10:46 -07003006 return allocRes;
3007}
3008
3009bool teardownVkBuffer(uint32_t bufferHandle) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003010 if (!sVkEmulation || !sVkEmulation->live) return false;
Lingfeng Yang76906892020-10-26 11:10:46 -07003011
3012 auto vk = sVkEmulation->dvk;
3013 AutoLock lock(sVkEmulationLock);
3014
3015 auto infoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003016 if (!infoPtr) return false;
Kaiyi Li263e9f42021-08-20 07:33:05 -07003017 {
3018 android::base::AutoLock lock(*sVkEmulation->queueLock);
3019 VK_CHECK(vk->vkQueueWaitIdle(sVkEmulation->queue));
3020 }
Lingfeng Yang76906892020-10-26 11:10:46 -07003021 auto& info = *infoPtr;
3022
3023 vk->vkDestroyBuffer(sVkEmulation->device, info.buffer, nullptr);
3024 freeExternalMemoryLocked(vk, &info.memory);
3025 sVkEmulation->buffers.erase(bufferHandle);
3026
3027 return true;
3028}
3029
3030VK_EXT_MEMORY_HANDLE getBufferExtMemoryHandle(uint32_t bufferHandle) {
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003031 if (!sVkEmulation || !sVkEmulation->live) return VK_EXT_MEMORY_HANDLE_INVALID;
Lingfeng Yang76906892020-10-26 11:10:46 -07003032
Lingfeng Yang76906892020-10-26 11:10:46 -07003033 AutoLock lock(sVkEmulationLock);
3034
3035 auto infoPtr = android::base::find(sVkEmulation->buffers, bufferHandle);
3036 if (!infoPtr) {
3037 // Color buffer not found; this is usually OK.
3038 return VK_EXT_MEMORY_HANDLE_INVALID;
3039 }
3040
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05003041 return infoPtr->memory.externalHandle;
Lingfeng Yang76906892020-10-26 11:10:46 -07003042}
3043
Jason Macnak6402a1b2022-06-02 15:29:05 -07003044bool readBufferToBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size, void* outBytes) {
3045 if (!sVkEmulation || !sVkEmulation->live) {
3046 VK_COMMON_ERROR("VkEmulation not available.");
3047 return false;
3048 }
3049
3050 auto vk = sVkEmulation->dvk;
3051
3052 AutoLock lock(sVkEmulationLock);
3053
3054 auto bufferInfo = android::base::find(sVkEmulation->buffers, bufferHandle);
3055 if (!bufferInfo) {
3056 VK_COMMON_ERROR("Failed to read from Buffer:%d, not found.", bufferHandle);
3057 return false;
3058 }
3059
3060 const auto& stagingBufferInfo = sVkEmulation->staging;
3061 if (size > stagingBufferInfo.size) {
3062 VK_COMMON_ERROR("Failed to read from Buffer:%d, staging buffer too small.", bufferHandle);
3063 return false;
3064 }
3065
3066 const VkCommandBufferBeginInfo beginInfo = {
3067 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3068 .pNext = nullptr,
3069 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3070 };
3071
3072 VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
3073
3074 VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
3075
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003076 sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(commandBuffer, "readBufferToBytes(Buffer:%d)",
3077 bufferHandle);
3078
Jason Macnak6402a1b2022-06-02 15:29:05 -07003079 const VkBufferCopy bufferCopy = {
3080 .srcOffset = offset,
3081 .dstOffset = 0,
3082 .size = size,
3083 };
3084 vk->vkCmdCopyBuffer(commandBuffer, bufferInfo->buffer, stagingBufferInfo.buffer, 1,
3085 &bufferCopy);
3086
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003087 sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
3088
Jason Macnak6402a1b2022-06-02 15:29:05 -07003089 VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
3090
3091 const VkSubmitInfo submitInfo = {
3092 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3093 .pNext = nullptr,
3094 .waitSemaphoreCount = 0,
3095 .pWaitSemaphores = nullptr,
3096 .pWaitDstStageMask = nullptr,
3097 .commandBufferCount = 1,
3098 .pCommandBuffers = &commandBuffer,
3099 .signalSemaphoreCount = 0,
3100 .pSignalSemaphores = nullptr,
3101 };
3102
3103 {
3104 android::base::AutoLock lock(*sVkEmulation->queueLock);
3105 VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
3106 sVkEmulation->commandBufferFence));
3107 }
3108
3109 static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
3110
3111 VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
3112 VK_TRUE, ANB_MAX_WAIT_NS));
3113
3114 VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
3115
3116 const VkMappedMemoryRange toInvalidate = {
3117 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
3118 .pNext = nullptr,
3119 .memory = stagingBufferInfo.memory.memory,
3120 .offset = 0,
3121 .size = size,
3122 };
3123
3124 VK_CHECK(vk->vkInvalidateMappedMemoryRanges(sVkEmulation->device, 1, &toInvalidate));
3125
3126 const void* srcPtr = reinterpret_cast<const void*>(
3127 reinterpret_cast<const char*>(stagingBufferInfo.memory.mappedPtr));
3128 void* dstPtr = outBytes;
3129 void* dstPtrOffset = reinterpret_cast<void*>(reinterpret_cast<char*>(dstPtr) + offset);
3130 std::memcpy(dstPtrOffset, srcPtr, size);
3131
3132 return true;
3133}
3134
Jason Macnaka296e682022-10-27 16:21:13 -07003135bool updateBufferFromBytes(uint32_t bufferHandle, uint64_t offset, uint64_t size,
3136 const void* bytes) {
Jason Macnak6402a1b2022-06-02 15:29:05 -07003137 if (!sVkEmulation || !sVkEmulation->live) {
3138 VK_COMMON_ERROR("VkEmulation not available.");
3139 return false;
3140 }
3141
3142 auto vk = sVkEmulation->dvk;
3143
3144 AutoLock lock(sVkEmulationLock);
3145
3146 auto bufferInfo = android::base::find(sVkEmulation->buffers, bufferHandle);
3147 if (!bufferInfo) {
3148 VK_COMMON_ERROR("Failed to update Buffer:%d, not found.", bufferHandle);
3149 return false;
3150 }
3151
3152 const auto& stagingBufferInfo = sVkEmulation->staging;
3153 if (size > stagingBufferInfo.size) {
3154 VK_COMMON_ERROR("Failed to update Buffer:%d, staging buffer too small.", bufferHandle);
3155 return false;
3156 }
3157
3158 const void* srcPtr = bytes;
3159 const void* srcPtrOffset =
3160 reinterpret_cast<const void*>(reinterpret_cast<const char*>(srcPtr) + offset);
3161 void* dstPtr = stagingBufferInfo.memory.mappedPtr;
3162 std::memcpy(dstPtr, srcPtrOffset, size);
3163
3164 const VkMappedMemoryRange toFlush = {
3165 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
3166 .pNext = nullptr,
3167 .memory = stagingBufferInfo.memory.memory,
3168 .offset = 0,
3169 .size = size,
3170 };
3171 VK_CHECK(vk->vkFlushMappedMemoryRanges(sVkEmulation->device, 1, &toFlush));
3172
3173 const VkCommandBufferBeginInfo beginInfo = {
3174 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3175 .pNext = nullptr,
3176 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3177 };
3178
3179 VkCommandBuffer commandBuffer = sVkEmulation->commandBuffer;
3180
3181 VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
3182
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003183 sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
3184 commandBuffer, "updateBufferFromBytes(Buffer:%d)", bufferHandle);
3185
Jason Macnak6402a1b2022-06-02 15:29:05 -07003186 const VkBufferCopy bufferCopy = {
3187 .srcOffset = 0,
3188 .dstOffset = offset,
3189 .size = size,
3190 };
3191 vk->vkCmdCopyBuffer(commandBuffer, stagingBufferInfo.buffer, bufferInfo->buffer, 1,
3192 &bufferCopy);
3193
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003194 sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
3195
Jason Macnak6402a1b2022-06-02 15:29:05 -07003196 VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
3197
3198 const VkSubmitInfo submitInfo = {
3199 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3200 .pNext = nullptr,
3201 .waitSemaphoreCount = 0,
3202 .pWaitSemaphores = nullptr,
3203 .pWaitDstStageMask = nullptr,
3204 .commandBufferCount = 1,
3205 .pCommandBuffers = &commandBuffer,
3206 .signalSemaphoreCount = 0,
3207 .pSignalSemaphores = nullptr,
3208 };
3209
3210 {
3211 android::base::AutoLock lock(*sVkEmulation->queueLock);
3212 VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo,
3213 sVkEmulation->commandBufferFence));
3214 }
3215
3216 static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
3217
3218 VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence,
3219 VK_TRUE, ANB_MAX_WAIT_NS));
3220
3221 VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &sVkEmulation->commandBufferFence));
3222
3223 return true;
3224}
3225
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003226VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_tohost(
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003227 VkExternalMemoryHandleTypeFlags bits) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003228 VkExternalMemoryHandleTypeFlags res = bits;
3229
3230 // Transform Android/Fuchsia/Linux bits to host bits.
3231 if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) {
3232 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
3233 }
3234
Lingfeng Yang76906892020-10-26 11:10:46 -07003235#ifdef _WIN32
3236 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
3237 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
3238#endif
3239
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003240 if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) {
3241 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
3242 res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3243 }
3244
Lingfeng Yangcbcfca42022-01-27 12:18:57 -08003245 if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA) {
3246 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003247 res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3248 }
Yilong Lia7a442a2021-03-24 17:17:25 -07003249
3250 if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA) {
3251 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA;
3252 res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3253 }
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05003254
3255#if defined(__QNX__)
3256 // QNX only: Replace DMA_BUF_BIT_EXT with SCREEN_BUFFER_BIT_QNX for host calls
3257 if (bits & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) {
3258 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
3259 res |= VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3260 }
3261#endif
3262
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003263 return res;
3264}
3265
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003266VkExternalMemoryHandleTypeFlags transformExternalMemoryHandleTypeFlags_fromhost(
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003267 VkExternalMemoryHandleTypeFlags hostBits,
3268 VkExternalMemoryHandleTypeFlags wantedGuestHandleType) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003269 VkExternalMemoryHandleTypeFlags res = hostBits;
3270
3271 if (res & VK_EXT_MEMORY_HANDLE_TYPE_BIT) {
3272 res &= ~VK_EXT_MEMORY_HANDLE_TYPE_BIT;
3273 res |= wantedGuestHandleType;
3274 }
3275
Lingfeng Yang76906892020-10-26 11:10:46 -07003276#ifdef _WIN32
3277 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
3278 res &= ~VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
3279#endif
3280
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003281 return res;
3282}
3283
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003284VkExternalMemoryProperties transformExternalMemoryProperties_tohost(
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003285 VkExternalMemoryProperties props) {
3286 VkExternalMemoryProperties res = props;
3287 res.exportFromImportedHandleTypes =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003288 transformExternalMemoryHandleTypeFlags_tohost(props.exportFromImportedHandleTypes);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003289 res.compatibleHandleTypes =
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003290 transformExternalMemoryHandleTypeFlags_tohost(props.compatibleHandleTypes);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003291 return res;
3292}
3293
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003294VkExternalMemoryProperties transformExternalMemoryProperties_fromhost(
3295 VkExternalMemoryProperties props, VkExternalMemoryHandleTypeFlags wantedGuestHandleType) {
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003296 VkExternalMemoryProperties res = props;
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003297 res.exportFromImportedHandleTypes = transformExternalMemoryHandleTypeFlags_fromhost(
3298 props.exportFromImportedHandleTypes, wantedGuestHandleType);
3299 res.compatibleHandleTypes = transformExternalMemoryHandleTypeFlags_fromhost(
3300 props.compatibleHandleTypes, wantedGuestHandleType);
Lingfeng Yangea978ce2019-12-13 13:42:23 -08003301 return res;
3302}
3303
Jason Macnak741afe72022-04-14 08:19:52 -07003304void setColorBufferCurrentLayout(uint32_t colorBufferHandle, VkImageLayout layout) {
3305 AutoLock lock(sVkEmulationLock);
3306
3307 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3308 if (!infoPtr) {
3309 VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
3310 return;
3311 }
3312 infoPtr->currentLayout = layout;
3313}
3314
Kaiyi Li5509d442021-10-18 15:13:46 -07003315// Allocate a ready to use VkCommandBuffer for queue transfer. The caller needs
3316// to signal the returned VkFence when the VkCommandBuffer completes.
3317static std::tuple<VkCommandBuffer, VkFence> allocateQueueTransferCommandBuffer_locked() {
3318 auto vk = sVkEmulation->dvk;
3319 // Check if a command buffer in the pool is ready to use. If the associated
3320 // VkFence is ready, vkGetFenceStatus will return VK_SUCCESS, and the
3321 // associated command buffer should be ready to use, so we return that
3322 // command buffer with the associated VkFence. If the associated VkFence is
3323 // not ready, vkGetFenceStatus will return VK_NOT_READY, we will continue to
3324 // search and test the next command buffer. If the VkFence is in an error
3325 // state, vkGetFenceStatus will return with other VkResult variants, we will
3326 // abort.
3327 for (auto& [commandBuffer, fence] : sVkEmulation->transferQueueCommandBufferPool) {
3328 auto res = vk->vkGetFenceStatus(sVkEmulation->device, fence);
3329 if (res == VK_SUCCESS) {
3330 VK_CHECK(vk->vkResetFences(sVkEmulation->device, 1, &fence));
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003331 VK_CHECK(vk->vkResetCommandBuffer(commandBuffer,
3332 VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT));
Kaiyi Li5509d442021-10-18 15:13:46 -07003333 return std::make_tuple(commandBuffer, fence);
3334 }
3335 if (res == VK_NOT_READY) {
3336 continue;
3337 }
Doug Horne6751122022-03-31 14:19:44 -07003338 // We either have a device lost, or an invalid fence state. For the device lost case,
3339 // VK_CHECK will ensure we capture the relevant streams.
3340 VK_CHECK(res);
Kaiyi Li5509d442021-10-18 15:13:46 -07003341 }
3342 VkCommandBuffer commandBuffer;
3343 VkCommandBufferAllocateInfo allocateInfo = {
3344 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
3345 .pNext = nullptr,
3346 .commandPool = sVkEmulation->commandPool,
3347 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
3348 .commandBufferCount = 1,
3349 };
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003350 VK_CHECK(vk->vkAllocateCommandBuffers(sVkEmulation->device, &allocateInfo, &commandBuffer));
Kaiyi Li5509d442021-10-18 15:13:46 -07003351 VkFence fence;
3352 VkFenceCreateInfo fenceCi = {
3353 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
3354 .pNext = nullptr,
3355 .flags = 0,
3356 };
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003357 VK_CHECK(vk->vkCreateFence(sVkEmulation->device, &fenceCi, nullptr, &fence));
Kaiyi Li5509d442021-10-18 15:13:46 -07003358
3359 sVkEmulation->transferQueueCommandBufferPool.emplace_back(commandBuffer, fence);
3360
3361 VK_COMMON_VERBOSE(
3362 "Create a new command buffer for queue transfer for a total of %d "
3363 "transfer command buffers",
3364 static_cast<int>(sVkEmulation->transferQueueCommandBufferPool.size()));
3365
3366 return std::make_tuple(commandBuffer, fence);
3367}
3368
Jason Macnak741afe72022-04-14 08:19:52 -07003369const VkImageLayout kGuestUseDefaultImageLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
Kaiyi Li5509d442021-10-18 15:13:46 -07003370
Jason Macnak741afe72022-04-14 08:19:52 -07003371void releaseColorBufferForGuestUse(uint32_t colorBufferHandle) {
Kaiyi Li5509d442021-10-18 15:13:46 -07003372 if (!sVkEmulation || !sVkEmulation->live) {
Doug Horn0c2ea5a2021-10-29 17:30:16 -07003373 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Host Vulkan device lost";
Kaiyi Li5509d442021-10-18 15:13:46 -07003374 }
3375
3376 AutoLock lock(sVkEmulationLock);
Kaiyi Li5509d442021-10-18 15:13:46 -07003377
Jason Macnak741afe72022-04-14 08:19:52 -07003378 auto infoPtr = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3379 if (!infoPtr) {
3380 VK_COMMON_ERROR("Failed to find ColorBuffer handle %d.",
3381 static_cast<int>(colorBufferHandle));
3382 return;
3383 }
3384
3385 std::optional<VkImageMemoryBarrier> layoutTransitionBarrier;
3386 if (infoPtr->currentLayout != kGuestUseDefaultImageLayout) {
3387 layoutTransitionBarrier = VkImageMemoryBarrier{
Kaiyi Li5509d442021-10-18 15:13:46 -07003388 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3389 .pNext = nullptr,
3390 .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3391 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3392 .oldLayout = infoPtr->currentLayout,
Jason Macnak741afe72022-04-14 08:19:52 -07003393 .newLayout = kGuestUseDefaultImageLayout,
Kaiyi Li5509d442021-10-18 15:13:46 -07003394 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
3395 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
3396 .image = infoPtr->image,
3397 .subresourceRange =
3398 {
3399 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3400 .baseMipLevel = 0,
3401 .levelCount = 1,
3402 .baseArrayLayer = 0,
3403 .layerCount = 1,
3404 },
3405 };
Jason Macnak741afe72022-04-14 08:19:52 -07003406 infoPtr->currentLayout = kGuestUseDefaultImageLayout;
3407 }
Kaiyi Li5509d442021-10-18 15:13:46 -07003408
Jason Macnak741afe72022-04-14 08:19:52 -07003409 std::optional<VkImageMemoryBarrier> queueTransferBarrier;
3410 if (infoPtr->currentQueueFamilyIndex != VK_QUEUE_FAMILY_EXTERNAL) {
3411 queueTransferBarrier = VkImageMemoryBarrier{
Kaiyi Li5509d442021-10-18 15:13:46 -07003412 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
3413 .pNext = nullptr,
3414 .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3415 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
3416 .oldLayout = infoPtr->currentLayout,
3417 .newLayout = infoPtr->currentLayout,
Jason Macnak741afe72022-04-14 08:19:52 -07003418 .srcQueueFamilyIndex = infoPtr->currentQueueFamilyIndex,
Kaiyi Li5509d442021-10-18 15:13:46 -07003419 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
3420 .image = infoPtr->image,
3421 .subresourceRange =
3422 {
3423 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
3424 .baseMipLevel = 0,
3425 .levelCount = 1,
3426 .baseArrayLayer = 0,
3427 .layerCount = 1,
3428 },
3429 };
Jason Macnak741afe72022-04-14 08:19:52 -07003430 infoPtr->currentQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
Kaiyi Li5509d442021-10-18 15:13:46 -07003431 }
3432
Jason Macnak741afe72022-04-14 08:19:52 -07003433 if (!layoutTransitionBarrier && !queueTransferBarrier) {
3434 return;
3435 }
3436
3437 auto vk = sVkEmulation->dvk;
Kaiyi Li5509d442021-10-18 15:13:46 -07003438 auto [commandBuffer, fence] = allocateQueueTransferCommandBuffer_locked();
3439
3440 VK_CHECK(vk->vkResetCommandBuffer(commandBuffer, 0));
Jason Macnak741afe72022-04-14 08:19:52 -07003441
3442 const VkCommandBufferBeginInfo beginInfo = {
Kaiyi Li5509d442021-10-18 15:13:46 -07003443 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
3444 .pNext = nullptr,
3445 .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
3446 .pInheritanceInfo = nullptr,
3447 };
3448 VK_CHECK(vk->vkBeginCommandBuffer(commandBuffer, &beginInfo));
Jason Macnak741afe72022-04-14 08:19:52 -07003449
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003450 sVkEmulation->debugUtilsHelper.cmdBeginDebugLabel(
3451 commandBuffer, "releaseColorBufferForGuestUse(ColorBuffer:%d)", colorBufferHandle);
3452
Jason Macnak741afe72022-04-14 08:19:52 -07003453 if (layoutTransitionBarrier) {
3454 vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
3455 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
3456 &layoutTransitionBarrier.value());
3457 }
3458 if (queueTransferBarrier) {
3459 vk->vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
3460 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
3461 &queueTransferBarrier.value());
3462 }
3463
Jason Macnak5c76bdb2024-01-30 09:07:34 -08003464 sVkEmulation->debugUtilsHelper.cmdEndDebugLabel(commandBuffer);
3465
Kaiyi Li5509d442021-10-18 15:13:46 -07003466 VK_CHECK(vk->vkEndCommandBuffer(commandBuffer));
Jason Macnak741afe72022-04-14 08:19:52 -07003467
3468 const VkSubmitInfo submitInfo = {
Kaiyi Li5509d442021-10-18 15:13:46 -07003469 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
3470 .pNext = nullptr,
3471 .waitSemaphoreCount = 0,
3472 .pWaitSemaphores = nullptr,
3473 .pWaitDstStageMask = nullptr,
3474 .commandBufferCount = 1,
3475 .pCommandBuffers = &commandBuffer,
3476 .signalSemaphoreCount = 0,
3477 .pSignalSemaphores = nullptr,
3478 };
Kaiyi Li5509d442021-10-18 15:13:46 -07003479 {
Kaiyi Li5509d442021-10-18 15:13:46 -07003480 android::base::AutoLock lock(*sVkEmulation->queueLock);
3481 VK_CHECK(vk->vkQueueSubmit(sVkEmulation->queue, 1, &submitInfo, fence));
3482 }
Kaiyi Li5509d442021-10-18 15:13:46 -07003483
Greg Schlomoffe111d0d2022-05-19 14:40:32 -07003484 static constexpr uint64_t ANB_MAX_WAIT_NS = 5ULL * 1000ULL * 1000ULL * 1000ULL;
3485 VK_CHECK(vk->vkWaitForFences(sVkEmulation->device, 1, &fence, VK_TRUE, ANB_MAX_WAIT_NS));
Kaiyi Li5509d442021-10-18 15:13:46 -07003486}
3487
Jason Macnak741afe72022-04-14 08:19:52 -07003488std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForComposition(uint32_t colorBufferHandle,
3489 bool colorBufferIsTarget) {
Kaiyi Licfd97332021-10-18 16:01:41 -07003490 AutoLock lock(sVkEmulationLock);
3491
Jason Macnak741afe72022-04-14 08:19:52 -07003492 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3493 if (!colorBufferInfo) {
Kaiyi Licfd97332021-10-18 16:01:41 -07003494 VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
Jason Macnak741afe72022-04-14 08:19:52 -07003495 return nullptr;
Kaiyi Licfd97332021-10-18 16:01:41 -07003496 }
Jason Macnak741afe72022-04-14 08:19:52 -07003497
3498 auto compositorInfo = std::make_unique<BorrowedImageInfoVk>();
3499 compositorInfo->id = colorBufferInfo->handle;
3500 compositorInfo->width = colorBufferInfo->imageCreateInfoShallow.extent.width;
3501 compositorInfo->height = colorBufferInfo->imageCreateInfoShallow.extent.height;
3502 compositorInfo->image = colorBufferInfo->image;
3503 compositorInfo->imageView = colorBufferInfo->imageView;
3504 compositorInfo->imageCreateInfo = colorBufferInfo->imageCreateInfoShallow;
3505 compositorInfo->preBorrowLayout = colorBufferInfo->currentLayout;
3506 compositorInfo->preBorrowQueueFamilyIndex = colorBufferInfo->currentQueueFamilyIndex;
3507 if (colorBufferIsTarget && sVkEmulation->displayVk) {
3508 // Instruct the compositor to perform the layout transition after use so
3509 // that it is ready to be blitted to the display.
3510 compositorInfo->postBorrowQueueFamilyIndex = sVkEmulation->queueFamilyIndex;
3511 compositorInfo->postBorrowLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
3512 } else {
3513 // Instruct the compositor to perform the queue transfer release after use
3514 // so that the color buffer can be acquired by the guest.
3515 compositorInfo->postBorrowQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
3516 compositorInfo->postBorrowLayout = colorBufferInfo->currentLayout;
3517
3518 if (compositorInfo->postBorrowLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
3519 compositorInfo->postBorrowLayout = kGuestUseDefaultImageLayout;
3520 }
3521 }
3522
3523 colorBufferInfo->currentLayout = compositorInfo->postBorrowLayout;
3524 colorBufferInfo->currentQueueFamilyIndex = compositorInfo->postBorrowQueueFamilyIndex;
3525
3526 return compositorInfo;
3527}
3528
3529std::unique_ptr<BorrowedImageInfoVk> borrowColorBufferForDisplay(uint32_t colorBufferHandle) {
3530 AutoLock lock(sVkEmulationLock);
3531
3532 auto colorBufferInfo = android::base::find(sVkEmulation->colorBuffers, colorBufferHandle);
3533 if (!colorBufferInfo) {
3534 VK_COMMON_ERROR("Invalid ColorBuffer handle %d.", static_cast<int>(colorBufferHandle));
3535 return nullptr;
3536 }
3537
3538 auto compositorInfo = std::make_unique<BorrowedImageInfoVk>();
3539 compositorInfo->id = colorBufferInfo->handle;
3540 compositorInfo->width = colorBufferInfo->imageCreateInfoShallow.extent.width;
3541 compositorInfo->height = colorBufferInfo->imageCreateInfoShallow.extent.height;
3542 compositorInfo->image = colorBufferInfo->image;
3543 compositorInfo->imageView = colorBufferInfo->imageView;
3544 compositorInfo->imageCreateInfo = colorBufferInfo->imageCreateInfoShallow;
3545 compositorInfo->preBorrowLayout = colorBufferInfo->currentLayout;
3546 compositorInfo->preBorrowQueueFamilyIndex = sVkEmulation->queueFamilyIndex;
3547
3548 // Instruct the display to perform the queue transfer release after use so
3549 // that the color buffer can be acquired by the guest.
3550 compositorInfo->postBorrowQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
3551 compositorInfo->postBorrowLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
3552
3553 colorBufferInfo->currentLayout = compositorInfo->postBorrowLayout;
3554 colorBufferInfo->currentQueueFamilyIndex = compositorInfo->postBorrowQueueFamilyIndex;
3555
3556 return compositorInfo;
Kaiyi Licfd97332021-10-18 16:01:41 -07003557}
3558
Jason Macnak12c1c392023-03-14 15:15:38 -07003559std::optional<uint32_t> findRepresentativeColorBufferMemoryTypeIndexLocked() {
3560 constexpr const uint32_t kArbitraryWidth = 64;
3561 constexpr const uint32_t kArbitraryHeight = 64;
3562 constexpr const uint32_t kArbitraryHandle = std::numeric_limits<uint32_t>::max();
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05003563 if (!createVkColorBufferLocked(kArbitraryWidth, kArbitraryHeight, GL_RGBA8,
3564 FrameworkFormat::FRAMEWORK_FORMAT_GL_COMPATIBLE,
3565 kArbitraryHandle, true, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
Jason Macnak12c1c392023-03-14 15:15:38 -07003566 ERR("Failed to setup memory type index test ColorBuffer.");
3567 return std::nullopt;
3568 }
Aaron Ruby4fc86ed2023-11-17 16:20:22 -05003569 if (!initializeVkColorBufferLocked(kArbitraryHandle)) {
3570 ERR("Failed to initialize memory type index test ColorBuffer.");
3571 return std::nullopt;
3572 }
Jason Macnak12c1c392023-03-14 15:15:38 -07003573
3574 uint32_t memoryTypeIndex = 0;
3575 if (!getColorBufferAllocationInfoLocked(kArbitraryHandle, nullptr, &memoryTypeIndex, nullptr,
3576 nullptr)) {
3577 ERR("Failed to lookup memory type index test ColorBuffer.");
3578 return std::nullopt;
3579 }
3580
3581 if (!teardownVkColorBufferLocked(kArbitraryHandle)) {
3582 ERR("Failed to clean up memory type index test ColorBuffer.");
3583 return std::nullopt;
3584 }
3585
3586 return memoryTypeIndex;
3587}
3588
Jason Macnaked0c9e62023-03-30 15:58:24 -07003589} // namespace vk
3590} // namespace gfxstream