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