xref: /aosp_15_r20/frameworks/native/libs/renderengine/skia/VulkanInterface.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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