1 /*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #undef LOG_TAG
18 #define LOG_TAG "RenderEngine"
19
20 #include "VulkanInterface.h"
21
22 #include <include/gpu/GpuTypes.h>
23 #include <include/gpu/vk/VulkanBackendContext.h>
24
25 #include <log/log_main.h>
26 #include <utils/Timers.h>
27
28 #include <cinttypes>
29 #include <sstream>
30
31 namespace android {
32 namespace renderengine {
33 namespace skia {
34
getGaneshBackendContext()35 VulkanBackendContext VulkanInterface::getGaneshBackendContext() {
36 return this->getGraphiteBackendContext();
37 };
38
getGraphiteBackendContext()39 VulkanBackendContext VulkanInterface::getGraphiteBackendContext() {
40 VulkanBackendContext backendContext;
41 backendContext.fInstance = mInstance;
42 backendContext.fPhysicalDevice = mPhysicalDevice;
43 backendContext.fDevice = mDevice;
44 backendContext.fQueue = mQueue;
45 backendContext.fGraphicsQueueIndex = mQueueIndex;
46 backendContext.fMaxAPIVersion = mApiVersion;
47 backendContext.fVkExtensions = &mVulkanExtensions;
48 backendContext.fDeviceFeatures2 = mPhysicalDeviceFeatures2;
49 backendContext.fGetProc = mGrGetProc;
50 backendContext.fProtectedContext = mIsProtected ? Protected::kYes : Protected::kNo;
51 backendContext.fDeviceLostContext = this; // VulkanInterface is long-lived
52 backendContext.fDeviceLostProc = onVkDeviceFault;
53 return backendContext;
54 };
55
createExportableSemaphore()56 VkSemaphore VulkanInterface::createExportableSemaphore() {
57 VkExportSemaphoreCreateInfo exportInfo;
58 exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
59 exportInfo.pNext = nullptr;
60 exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
61
62 VkSemaphoreCreateInfo semaphoreInfo;
63 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
64 semaphoreInfo.pNext = &exportInfo;
65 semaphoreInfo.flags = 0;
66
67 VkSemaphore semaphore;
68 VkResult err = mFuncs.vkCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
69 if (VK_SUCCESS != err) {
70 ALOGE("%s: failed to create semaphore. err %d\n", __func__, err);
71 return VK_NULL_HANDLE;
72 }
73
74 return semaphore;
75 }
76
77 // syncFd cannot be <= 0
importSemaphoreFromSyncFd(int syncFd)78 VkSemaphore VulkanInterface::importSemaphoreFromSyncFd(int syncFd) {
79 VkSemaphoreCreateInfo semaphoreInfo;
80 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
81 semaphoreInfo.pNext = nullptr;
82 semaphoreInfo.flags = 0;
83
84 VkSemaphore semaphore;
85 VkResult err = mFuncs.vkCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
86 if (VK_SUCCESS != err) {
87 ALOGE("%s: failed to create import semaphore", __func__);
88 return VK_NULL_HANDLE;
89 }
90
91 VkImportSemaphoreFdInfoKHR importInfo;
92 importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
93 importInfo.pNext = nullptr;
94 importInfo.semaphore = semaphore;
95 importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
96 importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
97 importInfo.fd = syncFd;
98
99 err = mFuncs.vkImportSemaphoreFdKHR(mDevice, &importInfo);
100 if (VK_SUCCESS != err) {
101 mFuncs.vkDestroySemaphore(mDevice, semaphore, nullptr);
102 ALOGE("%s: failed to import semaphore", __func__);
103 return VK_NULL_HANDLE;
104 }
105
106 return semaphore;
107 }
108
exportSemaphoreSyncFd(VkSemaphore semaphore)109 int VulkanInterface::exportSemaphoreSyncFd(VkSemaphore semaphore) {
110 int res;
111
112 VkSemaphoreGetFdInfoKHR getFdInfo;
113 getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
114 getFdInfo.pNext = nullptr;
115 getFdInfo.semaphore = semaphore;
116 getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
117 VkResult err = mFuncs.vkGetSemaphoreFdKHR(mDevice, &getFdInfo, &res);
118 if (VK_SUCCESS != err) {
119 ALOGE("%s: failed to export semaphore, err: %d", __func__, err);
120 return -1;
121 }
122 return res;
123 }
124
destroySemaphore(VkSemaphore semaphore)125 void VulkanInterface::destroySemaphore(VkSemaphore semaphore) {
126 mFuncs.vkDestroySemaphore(mDevice, semaphore, nullptr);
127 }
128
onVkDeviceFault(void * callbackContext,const std::string & description,const std::vector<VkDeviceFaultAddressInfoEXT> & addressInfos,const std::vector<VkDeviceFaultVendorInfoEXT> & vendorInfos,const std::vector<std::byte> & vendorBinaryData)129 void VulkanInterface::onVkDeviceFault(void* callbackContext, const std::string& description,
130 const std::vector<VkDeviceFaultAddressInfoEXT>& addressInfos,
131 const std::vector<VkDeviceFaultVendorInfoEXT>& vendorInfos,
132 const std::vector<std::byte>& vendorBinaryData) {
133 VulkanInterface* interface = static_cast<VulkanInterface*>(callbackContext);
134 const std::string protectedStr = interface->mIsProtected ? "protected" : "non-protected";
135 // The final crash string should contain as much differentiating info as possible, up to 1024
136 // bytes. As this final message is constructed, the same information is also dumped to the logs
137 // but in a more verbose format. Building the crash string is unsightly, so the clearer logging
138 // statement is always placed first to give context.
139 ALOGE("VK_ERROR_DEVICE_LOST (%s context): %s", protectedStr.c_str(), description.c_str());
140 std::stringstream crashMsg;
141 crashMsg << "VK_ERROR_DEVICE_LOST (" << protectedStr;
142
143 if (!addressInfos.empty()) {
144 ALOGE("%zu VkDeviceFaultAddressInfoEXT:", addressInfos.size());
145 crashMsg << ", " << addressInfos.size() << " address info (";
146 for (VkDeviceFaultAddressInfoEXT addressInfo : addressInfos) {
147 ALOGE(" addressType: %d", (int)addressInfo.addressType);
148 ALOGE(" reportedAddress: %" PRIu64, addressInfo.reportedAddress);
149 ALOGE(" addressPrecision: %" PRIu64, addressInfo.addressPrecision);
150 crashMsg << addressInfo.addressType << ":" << addressInfo.reportedAddress << ":"
151 << addressInfo.addressPrecision << ", ";
152 }
153 crashMsg.seekp(-2, crashMsg.cur); // Move back to overwrite trailing ", "
154 crashMsg << ")";
155 }
156
157 if (!vendorInfos.empty()) {
158 ALOGE("%zu VkDeviceFaultVendorInfoEXT:", vendorInfos.size());
159 crashMsg << ", " << vendorInfos.size() << " vendor info (";
160 for (VkDeviceFaultVendorInfoEXT vendorInfo : vendorInfos) {
161 ALOGE(" description: %s", vendorInfo.description);
162 ALOGE(" vendorFaultCode: %" PRIu64, vendorInfo.vendorFaultCode);
163 ALOGE(" vendorFaultData: %" PRIu64, vendorInfo.vendorFaultData);
164 // Omit descriptions for individual vendor info structs in the crash string, as the
165 // fault code and fault data fields should be enough for clustering, and the verbosity
166 // isn't worth it. Additionally, vendors may just set the general description field of
167 // the overall fault to the description of the first element in this list, and that
168 // overall description will be placed at the end of the crash string.
169 crashMsg << vendorInfo.vendorFaultCode << ":" << vendorInfo.vendorFaultData << ", ";
170 }
171 crashMsg.seekp(-2, crashMsg.cur); // Move back to overwrite trailing ", "
172 crashMsg << ")";
173 }
174
175 if (!vendorBinaryData.empty()) {
176 // TODO: b/322830575 - Log in base64, or dump directly to a file that gets put in bugreports
177 ALOGE("%zu bytes of vendor-specific binary data (please notify Android's Core Graphics"
178 " Stack team if you observe this message).",
179 vendorBinaryData.size());
180 crashMsg << ", " << vendorBinaryData.size() << " bytes binary";
181 }
182
183 crashMsg << "): " << description;
184 LOG_ALWAYS_FATAL("%s", crashMsg.str().c_str());
185 };
186
187 static skgpu::VulkanGetProc sGetProc = [](const char* proc_name,
188 VkInstance instance,
__anonbd5490c30102(const char* proc_name, VkInstance instance, VkDevice device) 189 VkDevice device) {
190 if (device != VK_NULL_HANDLE) {
191 return vkGetDeviceProcAddr(device, proc_name);
192 }
193 return vkGetInstanceProcAddr(instance, proc_name);
194 };
195
196 #define BAIL(fmt, ...) \
197 { \
198 ALOGE("%s: " fmt ", bailing", __func__, ##__VA_ARGS__); \
199 return; \
200 }
201
202 #define CHECK_NONNULL(expr) \
203 if ((expr) == nullptr) { \
204 BAIL("[%s] null", #expr); \
205 }
206
207 #define VK_CHECK(expr) \
208 if ((expr) != VK_SUCCESS) { \
209 BAIL("[%s] failed. err = %d", #expr, expr); \
210 return; \
211 }
212
213 #define VK_GET_PROC(F) \
214 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F); \
215 CHECK_NONNULL(vk##F)
216 #define VK_GET_INST_PROC(instance, F) \
217 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(instance, "vk" #F); \
218 CHECK_NONNULL(vk##F)
219 #define VK_GET_DEV_PROC(device, F) \
220 PFN_vk##F vk##F = (PFN_vk##F)vkGetDeviceProcAddr(device, "vk" #F); \
221 CHECK_NONNULL(vk##F)
222
init(bool protectedContent)223 void VulkanInterface::init(bool protectedContent) {
224 if (isInitialized()) {
225 ALOGW("Called init on already initialized VulkanInterface");
226 return;
227 }
228
229 const nsecs_t timeBefore = systemTime();
230
231 VK_GET_PROC(EnumerateInstanceVersion);
232 uint32_t instanceVersion;
233 VK_CHECK(vkEnumerateInstanceVersion(&instanceVersion));
234
235 if (instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
236 BAIL("Vulkan instance API version %" PRIu32 ".%" PRIu32 ".%" PRIu32 " < 1.1.0",
237 VK_VERSION_MAJOR(instanceVersion), VK_VERSION_MINOR(instanceVersion),
238 VK_VERSION_PATCH(instanceVersion));
239 }
240
241 const VkApplicationInfo appInfo = {
242 VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "surfaceflinger", 0, "android platform", 0,
243 VK_MAKE_VERSION(1, 1, 0),
244 };
245
246 VK_GET_PROC(EnumerateInstanceExtensionProperties);
247
248 uint32_t extensionCount = 0;
249 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr));
250 std::vector<VkExtensionProperties> instanceExtensions(extensionCount);
251 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
252 instanceExtensions.data()));
253 std::vector<const char*> enabledInstanceExtensionNames;
254 enabledInstanceExtensionNames.reserve(instanceExtensions.size());
255 mInstanceExtensionNames.reserve(instanceExtensions.size());
256 for (const auto& instExt : instanceExtensions) {
257 enabledInstanceExtensionNames.push_back(instExt.extensionName);
258 mInstanceExtensionNames.push_back(instExt.extensionName);
259 }
260
261 const VkInstanceCreateInfo instanceCreateInfo = {
262 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
263 nullptr,
264 0,
265 &appInfo,
266 0,
267 nullptr,
268 (uint32_t)enabledInstanceExtensionNames.size(),
269 enabledInstanceExtensionNames.data(),
270 };
271
272 VK_GET_PROC(CreateInstance);
273 VkInstance instance;
274 VK_CHECK(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
275
276 VK_GET_INST_PROC(instance, DestroyInstance);
277 mFuncs.vkDestroyInstance = vkDestroyInstance;
278 VK_GET_INST_PROC(instance, EnumeratePhysicalDevices);
279 VK_GET_INST_PROC(instance, EnumerateDeviceExtensionProperties);
280 VK_GET_INST_PROC(instance, GetPhysicalDeviceProperties2);
281 VK_GET_INST_PROC(instance, GetPhysicalDeviceExternalSemaphoreProperties);
282 VK_GET_INST_PROC(instance, GetPhysicalDeviceQueueFamilyProperties2);
283 VK_GET_INST_PROC(instance, GetPhysicalDeviceFeatures2);
284 VK_GET_INST_PROC(instance, CreateDevice);
285
286 uint32_t physdevCount;
287 VK_CHECK(vkEnumeratePhysicalDevices(instance, &physdevCount, nullptr));
288 if (physdevCount == 0) {
289 BAIL("Could not find any physical devices");
290 }
291
292 physdevCount = 1;
293 VkPhysicalDevice physicalDevice;
294 VkResult enumeratePhysDevsErr =
295 vkEnumeratePhysicalDevices(instance, &physdevCount, &physicalDevice);
296 if (enumeratePhysDevsErr != VK_SUCCESS && VK_INCOMPLETE != enumeratePhysDevsErr) {
297 BAIL("vkEnumeratePhysicalDevices failed with non-VK_INCOMPLETE error: %d",
298 enumeratePhysDevsErr);
299 }
300
301 VkPhysicalDeviceProperties2 physDevProps = {
302 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
303 0,
304 {},
305 };
306 VkPhysicalDeviceProtectedMemoryProperties protMemProps = {
307 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
308 0,
309 {},
310 };
311
312 if (protectedContent) {
313 physDevProps.pNext = &protMemProps;
314 }
315
316 vkGetPhysicalDeviceProperties2(physicalDevice, &physDevProps);
317 const uint32_t physicalDeviceApiVersion = physDevProps.properties.apiVersion;
318 if (physicalDeviceApiVersion < VK_MAKE_VERSION(1, 1, 0)) {
319 BAIL("Vulkan physical device API version %" PRIu32 ".%" PRIu32 ".%" PRIu32 " < 1.1.0",
320 VK_VERSION_MAJOR(physicalDeviceApiVersion), VK_VERSION_MINOR(physicalDeviceApiVersion),
321 VK_VERSION_PATCH(physicalDeviceApiVersion));
322 }
323
324 // Check for syncfd support. Bail if we cannot both import and export them.
325 VkPhysicalDeviceExternalSemaphoreInfo semInfo = {
326 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
327 nullptr,
328 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
329 };
330 VkExternalSemaphoreProperties semProps = {
331 VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, nullptr, 0, 0, 0,
332 };
333 vkGetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &semInfo, &semProps);
334
335 bool sufficientSemaphoreSyncFdSupport = (semProps.exportFromImportedHandleTypes &
336 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
337 (semProps.compatibleHandleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
338 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) &&
339 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
340
341 if (!sufficientSemaphoreSyncFdSupport) {
342 BAIL("Vulkan device does not support sufficient external semaphore sync fd features. "
343 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
344 "compatibleHandleTypes 0x%x (needed 0x%x) "
345 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
346 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
347 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
348 semProps.externalSemaphoreFeatures,
349 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
350 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
351 } else {
352 ALOGD("Vulkan device supports sufficient external semaphore sync fd features. "
353 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
354 "compatibleHandleTypes 0x%x (needed 0x%x) "
355 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
356 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
357 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
358 semProps.externalSemaphoreFeatures,
359 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
360 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
361 }
362
363 uint32_t queueCount;
364 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, nullptr);
365 if (queueCount == 0) {
366 BAIL("Could not find queues for physical device");
367 }
368
369 std::vector<VkQueueFamilyProperties2> queueProps(queueCount);
370 std::vector<VkQueueFamilyGlobalPriorityPropertiesEXT> queuePriorityProps(queueCount);
371 VkQueueGlobalPriorityKHR queuePriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
372 // Even though we don't yet know if the VK_EXT_global_priority extension is available,
373 // we can safely add the request to the pNext chain, and if the extension is not
374 // available, it will be ignored.
375 for (uint32_t i = 0; i < queueCount; ++i) {
376 queuePriorityProps[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT;
377 queuePriorityProps[i].pNext = nullptr;
378 queueProps[i].pNext = &queuePriorityProps[i];
379 }
380 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, queueProps.data());
381
382 int graphicsQueueIndex = -1;
383 for (uint32_t i = 0; i < queueCount; ++i) {
384 // Look at potential answers to the VK_EXT_global_priority query. If answers were
385 // provided, we may adjust the queuePriority.
386 if (queueProps[i].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
387 for (uint32_t j = 0; j < queuePriorityProps[i].priorityCount; j++) {
388 if (queuePriorityProps[i].priorities[j] > queuePriority) {
389 queuePriority = queuePriorityProps[i].priorities[j];
390 }
391 }
392 if (queuePriority == VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR) {
393 mIsRealtimePriority = true;
394 }
395 graphicsQueueIndex = i;
396 break;
397 }
398 }
399
400 if (graphicsQueueIndex == -1) {
401 BAIL("Could not find a graphics queue family");
402 }
403
404 uint32_t deviceExtensionCount;
405 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
406 nullptr));
407 std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
408 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
409 deviceExtensions.data()));
410
411 std::vector<const char*> enabledDeviceExtensionNames;
412 enabledDeviceExtensionNames.reserve(deviceExtensions.size());
413 mDeviceExtensionNames.reserve(deviceExtensions.size());
414 for (const auto& devExt : deviceExtensions) {
415 enabledDeviceExtensionNames.push_back(devExt.extensionName);
416 mDeviceExtensionNames.push_back(devExt.extensionName);
417 }
418
419 mVulkanExtensions.init(sGetProc, instance, physicalDevice, enabledInstanceExtensionNames.size(),
420 enabledInstanceExtensionNames.data(), enabledDeviceExtensionNames.size(),
421 enabledDeviceExtensionNames.data());
422
423 if (!mVulkanExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
424 BAIL("Vulkan driver doesn't support external semaphore fd");
425 }
426
427 mPhysicalDeviceFeatures2 = new VkPhysicalDeviceFeatures2;
428 mPhysicalDeviceFeatures2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
429 mPhysicalDeviceFeatures2->pNext = nullptr;
430
431 mSamplerYcbcrConversionFeatures = new VkPhysicalDeviceSamplerYcbcrConversionFeatures;
432 mSamplerYcbcrConversionFeatures->sType =
433 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
434 mSamplerYcbcrConversionFeatures->pNext = nullptr;
435
436 mPhysicalDeviceFeatures2->pNext = mSamplerYcbcrConversionFeatures;
437 void** tailPnext = &mSamplerYcbcrConversionFeatures->pNext;
438
439 if (protectedContent) {
440 mProtectedMemoryFeatures = new VkPhysicalDeviceProtectedMemoryFeatures;
441 mProtectedMemoryFeatures->sType =
442 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
443 mProtectedMemoryFeatures->pNext = nullptr;
444 *tailPnext = mProtectedMemoryFeatures;
445 tailPnext = &mProtectedMemoryFeatures->pNext;
446 }
447
448 if (mVulkanExtensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) {
449 mDeviceFaultFeatures = new VkPhysicalDeviceFaultFeaturesEXT;
450 mDeviceFaultFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
451 mDeviceFaultFeatures->pNext = nullptr;
452 *tailPnext = mDeviceFaultFeatures;
453 tailPnext = &mDeviceFaultFeatures->pNext;
454 }
455
456 vkGetPhysicalDeviceFeatures2(physicalDevice, mPhysicalDeviceFeatures2);
457 // Looks like this would slow things down and we can't depend on it on all platforms
458 mPhysicalDeviceFeatures2->features.robustBufferAccess = VK_FALSE;
459
460 if (protectedContent && !mProtectedMemoryFeatures->protectedMemory) {
461 BAIL("Protected memory not supported");
462 }
463
464 float queuePriorities[1] = {0.0f};
465 void* queueNextPtr = nullptr;
466
467 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo = {
468 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
469 nullptr,
470 // If queue priority is supported, RE should always have realtime priority.
471 queuePriority,
472 };
473
474 if (mVulkanExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
475 queueNextPtr = &queuePriorityCreateInfo;
476 }
477
478 VkDeviceQueueCreateFlags deviceQueueCreateFlags =
479 (VkDeviceQueueCreateFlags)(protectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0);
480
481 const VkDeviceQueueCreateInfo queueInfo = {
482 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
483 queueNextPtr,
484 deviceQueueCreateFlags,
485 (uint32_t)graphicsQueueIndex,
486 1,
487 queuePriorities,
488 };
489
490 const VkDeviceCreateInfo deviceInfo = {
491 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
492 mPhysicalDeviceFeatures2,
493 0,
494 1,
495 &queueInfo,
496 0,
497 nullptr,
498 (uint32_t)enabledDeviceExtensionNames.size(),
499 enabledDeviceExtensionNames.data(),
500 nullptr,
501 };
502
503 ALOGD("Trying to create Vk device with protectedContent=%d", protectedContent);
504 VkDevice device;
505 VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device));
506 ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
507
508 VkQueue graphicsQueue;
509 VK_GET_DEV_PROC(device, GetDeviceQueue2);
510 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
511 deviceQueueCreateFlags,
512 (uint32_t)graphicsQueueIndex, 0};
513 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
514
515 VK_GET_DEV_PROC(device, DeviceWaitIdle);
516 VK_GET_DEV_PROC(device, DestroyDevice);
517 mFuncs.vkDeviceWaitIdle = vkDeviceWaitIdle;
518 mFuncs.vkDestroyDevice = vkDestroyDevice;
519
520 VK_GET_DEV_PROC(device, CreateSemaphore);
521 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
522 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
523 VK_GET_DEV_PROC(device, DestroySemaphore);
524 mFuncs.vkCreateSemaphore = vkCreateSemaphore;
525 mFuncs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
526 mFuncs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
527 mFuncs.vkDestroySemaphore = vkDestroySemaphore;
528
529 // At this point, everything's succeeded and we can continue
530 mInitialized = true;
531 mInstance = instance;
532 mPhysicalDevice = physicalDevice;
533 mDevice = device;
534 mQueue = graphicsQueue;
535 mQueueIndex = graphicsQueueIndex;
536 mApiVersion = physicalDeviceApiVersion;
537 // grExtensions already constructed
538 // feature pointers already constructed
539 mGrGetProc = sGetProc;
540 mIsProtected = protectedContent;
541 // mIsRealtimePriority already initialized by constructor
542 // funcs already initialized
543
544 const nsecs_t timeAfter = systemTime();
545 const float initTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
546 ALOGD("%s: Success init Vulkan interface in %f ms", __func__, initTimeMs);
547 }
548
takeOwnership()549 bool VulkanInterface::takeOwnership() {
550 if (!isInitialized() || mIsOwned) {
551 return false;
552 }
553 mIsOwned = true;
554 return true;
555 }
556
teardown()557 void VulkanInterface::teardown() {
558 // Core resources that must be destroyed using Vulkan functions.
559 if (mDevice != VK_NULL_HANDLE) {
560 mFuncs.vkDeviceWaitIdle(mDevice);
561 mFuncs.vkDestroyDevice(mDevice, nullptr);
562 mDevice = VK_NULL_HANDLE;
563 }
564 if (mInstance != VK_NULL_HANDLE) {
565 mFuncs.vkDestroyInstance(mInstance, nullptr);
566 mInstance = VK_NULL_HANDLE;
567 }
568
569 // Optional features that can be deleted directly.
570 // TODO: b/293371537 - This section should likely be improved to walk the pNext chain of
571 // mPhysicalDeviceFeatures2 and free everything like HWUI's VulkanManager.
572 if (mProtectedMemoryFeatures) {
573 delete mProtectedMemoryFeatures;
574 mProtectedMemoryFeatures = nullptr;
575 }
576 if (mSamplerYcbcrConversionFeatures) {
577 delete mSamplerYcbcrConversionFeatures;
578 mSamplerYcbcrConversionFeatures = nullptr;
579 }
580 if (mPhysicalDeviceFeatures2) {
581 delete mPhysicalDeviceFeatures2;
582 mPhysicalDeviceFeatures2 = nullptr;
583 }
584 if (mDeviceFaultFeatures) {
585 delete mDeviceFaultFeatures;
586 mDeviceFaultFeatures = nullptr;
587 }
588
589 // Misc. fields that can be trivially reset without special deletion:
590 mInitialized = false;
591 mIsOwned = false;
592 mPhysicalDevice = VK_NULL_HANDLE; // Implicitly destroyed by destroying mInstance.
593 mQueue = VK_NULL_HANDLE; // Implicitly destroyed by destroying mDevice.
594 mQueueIndex = 0;
595 mApiVersion = 0;
596 mVulkanExtensions = skgpu::VulkanExtensions();
597 mGrGetProc = nullptr;
598 mIsProtected = false;
599 mIsRealtimePriority = false;
600
601 mFuncs = VulkanFuncs();
602
603 mInstanceExtensionNames.clear();
604 mDeviceExtensionNames.clear();
605 }
606
607 } // namespace skia
608 } // namespace renderengine
609 } // namespace android
610