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