blob: bd3cca7b044471d72d177f2a29db44973b49d8ef [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>
Nolan Scobie609e5972024-03-20 14:47:34 -040023#include <include/gpu/vk/VulkanBackendContext.h>
24
Nolan Scobief52ad202024-03-06 18:18:28 -050025#include <log/log_main.h>
26#include <utils/Timers.h>
27
28#include <cinttypes>
29#include <sstream>
30
31namespace android {
32namespace renderengine {
33namespace skia {
34
Nolan Scobiefc125ec2024-03-11 20:08:27 -040035GrVkBackendContext VulkanInterface::getGaneshBackendContext() {
Nolan Scobief52ad202024-03-06 18:18:28 -050036 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
Nolan Scobie609e5972024-03-20 14:47:34 -040052VulkanBackendContext 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
Nolan Scobief52ad202024-03-06 18:18:28 -050069VkSemaphore 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
91VkSemaphore 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
122int 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
138void VulkanInterface::destroySemaphore(VkSemaphore semaphore) {
139 mFuncs.vkDestroySemaphore(mDevice, semaphore, nullptr);
140}
141
142void 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
200static GrVkGetProc sGetProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
201 if (device != VK_NULL_HANDLE) {
202 return vkGetDeviceProcAddr(device, proc_name);
203 }
204 return vkGetInstanceProcAddr(instance, proc_name);
205};
206
207#define BAIL(fmt, ...) \
208 { \
209 ALOGE("%s: " fmt ", bailing", __func__, ##__VA_ARGS__); \
210 return; \
211 }
212
213#define CHECK_NONNULL(expr) \
214 if ((expr) == nullptr) { \
215 BAIL("[%s] null", #expr); \
216 }
217
218#define VK_CHECK(expr) \
219 if ((expr) != VK_SUCCESS) { \
220 BAIL("[%s] failed. err = %d", #expr, expr); \
221 return; \
222 }
223
224#define VK_GET_PROC(F) \
225 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F); \
226 CHECK_NONNULL(vk##F)
227#define VK_GET_INST_PROC(instance, F) \
228 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(instance, "vk" #F); \
229 CHECK_NONNULL(vk##F)
230#define VK_GET_DEV_PROC(device, F) \
231 PFN_vk##F vk##F = (PFN_vk##F)vkGetDeviceProcAddr(device, "vk" #F); \
232 CHECK_NONNULL(vk##F)
233
234void VulkanInterface::init(bool protectedContent) {
235 if (isInitialized()) {
236 ALOGW("Called init on already initialized VulkanInterface");
237 return;
238 }
239
240 const nsecs_t timeBefore = systemTime();
241
242 VK_GET_PROC(EnumerateInstanceVersion);
243 uint32_t instanceVersion;
244 VK_CHECK(vkEnumerateInstanceVersion(&instanceVersion));
245
246 if (instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
247 return;
248 }
249
250 const VkApplicationInfo appInfo = {
251 VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "surfaceflinger", 0, "android platform", 0,
252 VK_MAKE_VERSION(1, 1, 0),
253 };
254
255 VK_GET_PROC(EnumerateInstanceExtensionProperties);
256
257 uint32_t extensionCount = 0;
258 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr));
259 std::vector<VkExtensionProperties> instanceExtensions(extensionCount);
260 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
261 instanceExtensions.data()));
262 std::vector<const char*> enabledInstanceExtensionNames;
263 enabledInstanceExtensionNames.reserve(instanceExtensions.size());
264 mInstanceExtensionNames.reserve(instanceExtensions.size());
265 for (const auto& instExt : instanceExtensions) {
266 enabledInstanceExtensionNames.push_back(instExt.extensionName);
267 mInstanceExtensionNames.push_back(instExt.extensionName);
268 }
269
270 const VkInstanceCreateInfo instanceCreateInfo = {
271 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
272 nullptr,
273 0,
274 &appInfo,
275 0,
276 nullptr,
277 (uint32_t)enabledInstanceExtensionNames.size(),
278 enabledInstanceExtensionNames.data(),
279 };
280
281 VK_GET_PROC(CreateInstance);
282 VkInstance instance;
283 VK_CHECK(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
284
285 VK_GET_INST_PROC(instance, DestroyInstance);
286 mFuncs.vkDestroyInstance = vkDestroyInstance;
287 VK_GET_INST_PROC(instance, EnumeratePhysicalDevices);
288 VK_GET_INST_PROC(instance, EnumerateDeviceExtensionProperties);
289 VK_GET_INST_PROC(instance, GetPhysicalDeviceProperties2);
290 VK_GET_INST_PROC(instance, GetPhysicalDeviceExternalSemaphoreProperties);
291 VK_GET_INST_PROC(instance, GetPhysicalDeviceQueueFamilyProperties2);
292 VK_GET_INST_PROC(instance, GetPhysicalDeviceFeatures2);
293 VK_GET_INST_PROC(instance, CreateDevice);
294
295 uint32_t physdevCount;
296 VK_CHECK(vkEnumeratePhysicalDevices(instance, &physdevCount, nullptr));
297 if (physdevCount == 0) {
298 BAIL("Could not find any physical devices");
299 }
300
301 physdevCount = 1;
302 VkPhysicalDevice physicalDevice;
303 VkResult enumeratePhysDevsErr =
304 vkEnumeratePhysicalDevices(instance, &physdevCount, &physicalDevice);
305 if (enumeratePhysDevsErr != VK_SUCCESS && VK_INCOMPLETE != enumeratePhysDevsErr) {
306 BAIL("vkEnumeratePhysicalDevices failed with non-VK_INCOMPLETE error: %d",
307 enumeratePhysDevsErr);
308 }
309
310 VkPhysicalDeviceProperties2 physDevProps = {
311 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
312 0,
313 {},
314 };
315 VkPhysicalDeviceProtectedMemoryProperties protMemProps = {
316 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
317 0,
318 {},
319 };
320
321 if (protectedContent) {
322 physDevProps.pNext = &protMemProps;
323 }
324
325 vkGetPhysicalDeviceProperties2(physicalDevice, &physDevProps);
326 if (physDevProps.properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
327 BAIL("Could not find a Vulkan 1.1+ physical device");
328 }
329
330 if (physDevProps.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
331 // TODO: b/326633110 - SkiaVK is not working correctly on swiftshader path.
332 BAIL("CPU implementations of Vulkan is not supported");
333 }
334
335 // Check for syncfd support. Bail if we cannot both import and export them.
336 VkPhysicalDeviceExternalSemaphoreInfo semInfo = {
337 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
338 nullptr,
339 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
340 };
341 VkExternalSemaphoreProperties semProps = {
342 VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, nullptr, 0, 0, 0,
343 };
344 vkGetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &semInfo, &semProps);
345
346 bool sufficientSemaphoreSyncFdSupport = (semProps.exportFromImportedHandleTypes &
347 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
348 (semProps.compatibleHandleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
349 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) &&
350 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
351
352 if (!sufficientSemaphoreSyncFdSupport) {
353 BAIL("Vulkan device does not support sufficient external semaphore sync fd features. "
354 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
355 "compatibleHandleTypes 0x%x (needed 0x%x) "
356 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
357 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
358 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
359 semProps.externalSemaphoreFeatures,
360 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
361 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
362 } else {
363 ALOGD("Vulkan device supports sufficient external semaphore sync fd features. "
364 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
365 "compatibleHandleTypes 0x%x (needed 0x%x) "
366 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
367 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
368 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
369 semProps.externalSemaphoreFeatures,
370 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
371 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
372 }
373
374 uint32_t queueCount;
375 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, nullptr);
376 if (queueCount == 0) {
377 BAIL("Could not find queues for physical device");
378 }
379
380 std::vector<VkQueueFamilyProperties2> queueProps(queueCount);
381 std::vector<VkQueueFamilyGlobalPriorityPropertiesEXT> queuePriorityProps(queueCount);
382 VkQueueGlobalPriorityKHR queuePriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
383 // Even though we don't yet know if the VK_EXT_global_priority extension is available,
384 // we can safely add the request to the pNext chain, and if the extension is not
385 // available, it will be ignored.
386 for (uint32_t i = 0; i < queueCount; ++i) {
387 queuePriorityProps[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT;
388 queuePriorityProps[i].pNext = nullptr;
389 queueProps[i].pNext = &queuePriorityProps[i];
390 }
391 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, queueProps.data());
392
393 int graphicsQueueIndex = -1;
394 for (uint32_t i = 0; i < queueCount; ++i) {
395 // Look at potential answers to the VK_EXT_global_priority query. If answers were
396 // provided, we may adjust the queuePriority.
397 if (queueProps[i].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
398 for (uint32_t j = 0; j < queuePriorityProps[i].priorityCount; j++) {
399 if (queuePriorityProps[i].priorities[j] > queuePriority) {
400 queuePriority = queuePriorityProps[i].priorities[j];
401 }
402 }
403 if (queuePriority == VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR) {
404 mIsRealtimePriority = true;
405 }
406 graphicsQueueIndex = i;
407 break;
408 }
409 }
410
411 if (graphicsQueueIndex == -1) {
412 BAIL("Could not find a graphics queue family");
413 }
414
415 uint32_t deviceExtensionCount;
416 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
417 nullptr));
418 std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
419 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
420 deviceExtensions.data()));
421
422 std::vector<const char*> enabledDeviceExtensionNames;
423 enabledDeviceExtensionNames.reserve(deviceExtensions.size());
424 mDeviceExtensionNames.reserve(deviceExtensions.size());
425 for (const auto& devExt : deviceExtensions) {
426 enabledDeviceExtensionNames.push_back(devExt.extensionName);
427 mDeviceExtensionNames.push_back(devExt.extensionName);
428 }
429
430 mGrExtensions.init(sGetProc, instance, physicalDevice, enabledInstanceExtensionNames.size(),
431 enabledInstanceExtensionNames.data(), enabledDeviceExtensionNames.size(),
432 enabledDeviceExtensionNames.data());
433
434 if (!mGrExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
435 BAIL("Vulkan driver doesn't support external semaphore fd");
436 }
437
438 mPhysicalDeviceFeatures2 = new VkPhysicalDeviceFeatures2;
439 mPhysicalDeviceFeatures2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
440 mPhysicalDeviceFeatures2->pNext = nullptr;
441
442 mSamplerYcbcrConversionFeatures = new VkPhysicalDeviceSamplerYcbcrConversionFeatures;
443 mSamplerYcbcrConversionFeatures->sType =
444 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
445 mSamplerYcbcrConversionFeatures->pNext = nullptr;
446
447 mPhysicalDeviceFeatures2->pNext = mSamplerYcbcrConversionFeatures;
448 void** tailPnext = &mSamplerYcbcrConversionFeatures->pNext;
449
450 if (protectedContent) {
451 mProtectedMemoryFeatures = new VkPhysicalDeviceProtectedMemoryFeatures;
452 mProtectedMemoryFeatures->sType =
453 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
454 mProtectedMemoryFeatures->pNext = nullptr;
455 *tailPnext = mProtectedMemoryFeatures;
456 tailPnext = &mProtectedMemoryFeatures->pNext;
457 }
458
459 if (mGrExtensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) {
460 mDeviceFaultFeatures = new VkPhysicalDeviceFaultFeaturesEXT;
461 mDeviceFaultFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
462 mDeviceFaultFeatures->pNext = nullptr;
463 *tailPnext = mDeviceFaultFeatures;
464 tailPnext = &mDeviceFaultFeatures->pNext;
465 }
466
467 vkGetPhysicalDeviceFeatures2(physicalDevice, mPhysicalDeviceFeatures2);
468 // Looks like this would slow things down and we can't depend on it on all platforms
469 mPhysicalDeviceFeatures2->features.robustBufferAccess = VK_FALSE;
470
471 if (protectedContent && !mProtectedMemoryFeatures->protectedMemory) {
472 BAIL("Protected memory not supported");
473 }
474
475 float queuePriorities[1] = {0.0f};
476 void* queueNextPtr = nullptr;
477
478 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo = {
479 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
480 nullptr,
481 // If queue priority is supported, RE should always have realtime priority.
482 queuePriority,
483 };
484
485 if (mGrExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
486 queueNextPtr = &queuePriorityCreateInfo;
487 }
488
489 VkDeviceQueueCreateFlags deviceQueueCreateFlags =
490 (VkDeviceQueueCreateFlags)(protectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0);
491
492 const VkDeviceQueueCreateInfo queueInfo = {
493 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
494 queueNextPtr,
495 deviceQueueCreateFlags,
496 (uint32_t)graphicsQueueIndex,
497 1,
498 queuePriorities,
499 };
500
501 const VkDeviceCreateInfo deviceInfo = {
502 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
503 mPhysicalDeviceFeatures2,
504 0,
505 1,
506 &queueInfo,
507 0,
508 nullptr,
509 (uint32_t)enabledDeviceExtensionNames.size(),
510 enabledDeviceExtensionNames.data(),
511 nullptr,
512 };
513
514 ALOGD("Trying to create Vk device with protectedContent=%d", protectedContent);
515 VkDevice device;
516 VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device));
517 ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
518
519 VkQueue graphicsQueue;
520 VK_GET_DEV_PROC(device, GetDeviceQueue2);
521 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
522 deviceQueueCreateFlags,
523 (uint32_t)graphicsQueueIndex, 0};
524 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
525
526 VK_GET_DEV_PROC(device, DeviceWaitIdle);
527 VK_GET_DEV_PROC(device, DestroyDevice);
528 mFuncs.vkDeviceWaitIdle = vkDeviceWaitIdle;
529 mFuncs.vkDestroyDevice = vkDestroyDevice;
530
531 VK_GET_DEV_PROC(device, CreateSemaphore);
532 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
533 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
534 VK_GET_DEV_PROC(device, DestroySemaphore);
535 mFuncs.vkCreateSemaphore = vkCreateSemaphore;
536 mFuncs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
537 mFuncs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
538 mFuncs.vkDestroySemaphore = vkDestroySemaphore;
539
540 // At this point, everything's succeeded and we can continue
541 mInitialized = true;
542 mInstance = instance;
543 mPhysicalDevice = physicalDevice;
544 mDevice = device;
545 mQueue = graphicsQueue;
546 mQueueIndex = graphicsQueueIndex;
547 mApiVersion = physDevProps.properties.apiVersion;
548 // grExtensions already constructed
549 // feature pointers already constructed
550 mGrGetProc = sGetProc;
551 mIsProtected = protectedContent;
552 // mIsRealtimePriority already initialized by constructor
553 // funcs already initialized
554
555 const nsecs_t timeAfter = systemTime();
556 const float initTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
557 ALOGD("%s: Success init Vulkan interface in %f ms", __func__, initTimeMs);
558}
559
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400560bool VulkanInterface::takeOwnership() {
561 if (!isInitialized() || mIsOwned) {
562 return false;
563 }
564 mIsOwned = true;
565 return true;
566}
Nolan Scobief52ad202024-03-06 18:18:28 -0500567
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400568void VulkanInterface::teardown() {
569 // Core resources that must be destroyed using Vulkan functions.
Nolan Scobief52ad202024-03-06 18:18:28 -0500570 if (mDevice != VK_NULL_HANDLE) {
571 mFuncs.vkDeviceWaitIdle(mDevice);
572 mFuncs.vkDestroyDevice(mDevice, nullptr);
573 mDevice = VK_NULL_HANDLE;
574 }
575 if (mInstance != VK_NULL_HANDLE) {
576 mFuncs.vkDestroyInstance(mInstance, nullptr);
577 mInstance = VK_NULL_HANDLE;
578 }
579
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400580 // Optional features that can be deleted directly.
581 // TODO: b/293371537 - This section should likely be improved to walk the pNext chain of
582 // mPhysicalDeviceFeatures2 and free everything like HWUI's VulkanManager.
Nolan Scobief52ad202024-03-06 18:18:28 -0500583 if (mProtectedMemoryFeatures) {
584 delete mProtectedMemoryFeatures;
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400585 mProtectedMemoryFeatures = nullptr;
Nolan Scobief52ad202024-03-06 18:18:28 -0500586 }
Nolan Scobief52ad202024-03-06 18:18:28 -0500587 if (mSamplerYcbcrConversionFeatures) {
588 delete mSamplerYcbcrConversionFeatures;
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400589 mSamplerYcbcrConversionFeatures = nullptr;
Nolan Scobief52ad202024-03-06 18:18:28 -0500590 }
Nolan Scobief52ad202024-03-06 18:18:28 -0500591 if (mPhysicalDeviceFeatures2) {
592 delete mPhysicalDeviceFeatures2;
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400593 mPhysicalDeviceFeatures2 = nullptr;
Nolan Scobief52ad202024-03-06 18:18:28 -0500594 }
Nolan Scobief52ad202024-03-06 18:18:28 -0500595 if (mDeviceFaultFeatures) {
596 delete mDeviceFaultFeatures;
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400597 mDeviceFaultFeatures = nullptr;
Nolan Scobief52ad202024-03-06 18:18:28 -0500598 }
599
Nolan Scobie2526b2f2024-04-16 15:12:22 -0400600 // Misc. fields that can be trivially reset without special deletion:
601 mInitialized = false;
602 mIsOwned = false;
603 mPhysicalDevice = VK_NULL_HANDLE; // Implicitly destroyed by destroying mInstance.
604 mQueue = VK_NULL_HANDLE; // Implicitly destroyed by destroying mDevice.
605 mQueueIndex = 0;
606 mApiVersion = 0;
607 mGrExtensions = GrVkExtensions();
608 mGrGetProc = nullptr;
609 mIsProtected = false;
610 mIsRealtimePriority = false;
611
612 mFuncs = VulkanFuncs();
613
614 mInstanceExtensionNames.clear();
615 mDeviceExtensionNames.clear();
Nolan Scobief52ad202024-03-06 18:18:28 -0500616}
617
618} // namespace skia
619} // namespace renderengine
620} // namespace android