blob: 6ecc6ab3629849c60bc724ed3e64d91338c55ea6 [file] [log] [blame]
Ian Elliott1f0911e2022-09-09 16:31:47 -06001/*
2 * Copyright 2022 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// #define LOG_NDEBUG 0
18#undef LOG_TAG
19#define LOG_TAG "RenderEngine"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21
22#include "SkiaVkRenderEngine.h"
23
24#include <GrBackendSemaphore.h>
25#include <GrContextOptions.h>
26#include <vk/GrVkExtensions.h>
27#include <vk/GrVkTypes.h>
28
29#include <android-base/stringprintf.h>
30#include <gui/TraceUtils.h>
31#include <sync/sync.h>
32#include <utils/Trace.h>
33
34#include <cstdint>
35#include <memory>
36#include <vector>
37
38#include <vulkan/vulkan.h>
39#include "log/log_main.h"
40
41namespace android {
42namespace renderengine {
43
44struct VulkanFuncs {
45 PFN_vkCreateSemaphore vkCreateSemaphore = nullptr;
46 PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr;
47 PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR = nullptr;
48 PFN_vkDestroySemaphore vkDestroySemaphore = nullptr;
49
50 PFN_vkDeviceWaitIdle vkDeviceWaitIdle = nullptr;
51 PFN_vkDestroyDevice vkDestroyDevice = nullptr;
52 PFN_vkDestroyInstance vkDestroyInstance = nullptr;
53};
54
Ian Elliott98e87162023-04-14 14:05:19 -060055// Ref-Count a semaphore
56struct DestroySemaphoreInfo {
57 VkSemaphore mSemaphore;
58 // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia
59 // (including by the GPU) and inside SkiaVkRenderEngine. So we always start with two refs, one
60 // owned by Skia and one owned by the SkiaVkRenderEngine. The refs are decremented each time
61 // delete_semaphore* is called with this object. Skia will call destroy_semaphore* once it is
62 // done with the semaphore and the GPU has finished work on the semaphore. SkiaVkRenderEngine
63 // calls delete_semaphore* after sending the semaphore to Skia and exporting it if need be.
64 int mRefs = 2;
65
66 DestroySemaphoreInfo(VkSemaphore semaphore) : mSemaphore(semaphore) {}
67};
68
Ian Elliott1f0911e2022-09-09 16:31:47 -060069struct VulkanInterface {
70 bool initialized = false;
71 VkInstance instance;
72 VkPhysicalDevice physicalDevice;
73 VkDevice device;
74 VkQueue queue;
75 int queueIndex;
76 uint32_t apiVersion;
77 GrVkExtensions grExtensions;
78 VkPhysicalDeviceFeatures2* physicalDeviceFeatures2 = nullptr;
79 VkPhysicalDeviceSamplerYcbcrConversionFeatures* samplerYcbcrConversionFeatures = nullptr;
Ian Elliottae0b8d12023-01-05 19:13:42 -070080 VkPhysicalDeviceProtectedMemoryFeatures* protectedMemoryFeatures = nullptr;
Ian Elliott1f0911e2022-09-09 16:31:47 -060081 GrVkGetProc grGetProc;
82 bool isProtected;
83 bool isRealtimePriority;
84
85 VulkanFuncs funcs;
86
87 std::vector<std::string> instanceExtensionNames;
88 std::vector<std::string> deviceExtensionNames;
89
90 GrVkBackendContext getBackendContext() {
91 GrVkBackendContext backendContext;
92 backendContext.fInstance = instance;
93 backendContext.fPhysicalDevice = physicalDevice;
94 backendContext.fDevice = device;
95 backendContext.fQueue = queue;
96 backendContext.fGraphicsQueueIndex = queueIndex;
97 backendContext.fMaxAPIVersion = apiVersion;
98 backendContext.fVkExtensions = &grExtensions;
99 backendContext.fDeviceFeatures2 = physicalDeviceFeatures2;
100 backendContext.fGetProc = grGetProc;
101 backendContext.fProtectedContext = isProtected ? GrProtected::kYes : GrProtected::kNo;
102 return backendContext;
103 };
104
105 VkSemaphore createExportableSemaphore() {
106 VkExportSemaphoreCreateInfo exportInfo;
107 exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
108 exportInfo.pNext = nullptr;
109 exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
110
111 VkSemaphoreCreateInfo semaphoreInfo;
112 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
113 semaphoreInfo.pNext = &exportInfo;
114 semaphoreInfo.flags = 0;
115
116 VkSemaphore semaphore;
117 VkResult err = funcs.vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore);
118 if (VK_SUCCESS != err) {
119 ALOGE("%s: failed to create semaphore. err %d\n", __func__, err);
120 return VK_NULL_HANDLE;
121 }
122
123 return semaphore;
124 }
125
126 // syncFd cannot be <= 0
127 VkSemaphore importSemaphoreFromSyncFd(int syncFd) {
128 VkSemaphoreCreateInfo semaphoreInfo;
129 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
130 semaphoreInfo.pNext = nullptr;
131 semaphoreInfo.flags = 0;
132
133 VkSemaphore semaphore;
134 VkResult err = funcs.vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore);
135 if (VK_SUCCESS != err) {
136 ALOGE("%s: failed to create import semaphore", __func__);
137 return VK_NULL_HANDLE;
138 }
139
140 VkImportSemaphoreFdInfoKHR importInfo;
141 importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
142 importInfo.pNext = nullptr;
143 importInfo.semaphore = semaphore;
144 importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
145 importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
146 importInfo.fd = syncFd;
147
148 err = funcs.vkImportSemaphoreFdKHR(device, &importInfo);
149 if (VK_SUCCESS != err) {
150 funcs.vkDestroySemaphore(device, semaphore, nullptr);
151 ALOGE("%s: failed to import semaphore", __func__);
152 return VK_NULL_HANDLE;
153 }
154
155 return semaphore;
156 }
157
158 int exportSemaphoreSyncFd(VkSemaphore semaphore) {
159 int res;
160
161 VkSemaphoreGetFdInfoKHR getFdInfo;
162 getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
163 getFdInfo.pNext = nullptr;
164 getFdInfo.semaphore = semaphore;
165 getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
166
167 VkResult err = funcs.vkGetSemaphoreFdKHR(device, &getFdInfo, &res);
168 if (VK_SUCCESS != err) {
169 ALOGE("%s: failed to export semaphore, err: %d", __func__, err);
170 return -1;
171 }
172 return res;
173 }
174
175 void destroySemaphore(VkSemaphore semaphore) {
176 funcs.vkDestroySemaphore(device, semaphore, nullptr);
177 }
178};
179
180static GrVkGetProc sGetProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
181 if (device != VK_NULL_HANDLE) {
182 return vkGetDeviceProcAddr(device, proc_name);
183 }
184 return vkGetInstanceProcAddr(instance, proc_name);
185};
186
187#define BAIL(fmt, ...) \
188 { \
189 ALOGE("%s: " fmt ", bailing", __func__, ##__VA_ARGS__); \
190 return interface; \
191 }
192
193#define CHECK_NONNULL(expr) \
194 if ((expr) == nullptr) { \
195 BAIL("[%s] null", #expr); \
196 }
197
198#define VK_CHECK(expr) \
199 if ((expr) != VK_SUCCESS) { \
200 BAIL("[%s] failed. err = %d", #expr, expr); \
201 return interface; \
202 }
203
204#define VK_GET_PROC(F) \
205 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F); \
206 CHECK_NONNULL(vk##F)
207#define VK_GET_INST_PROC(instance, F) \
208 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(instance, "vk" #F); \
209 CHECK_NONNULL(vk##F)
210#define VK_GET_DEV_PROC(device, F) \
211 PFN_vk##F vk##F = (PFN_vk##F)vkGetDeviceProcAddr(device, "vk" #F); \
212 CHECK_NONNULL(vk##F)
213
214VulkanInterface initVulkanInterface(bool protectedContent = false) {
215 VulkanInterface interface;
216
217 VK_GET_PROC(EnumerateInstanceVersion);
218 uint32_t instanceVersion;
219 VK_CHECK(vkEnumerateInstanceVersion(&instanceVersion));
220
221 if (instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
222 return interface;
223 }
224
225 const VkApplicationInfo appInfo = {
226 VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "surfaceflinger", 0, "android platform", 0,
227 VK_MAKE_VERSION(1, 1, 0),
228 };
229
230 VK_GET_PROC(EnumerateInstanceExtensionProperties);
231
232 uint32_t extensionCount = 0;
233 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr));
234 std::vector<VkExtensionProperties> instanceExtensions(extensionCount);
235 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
236 instanceExtensions.data()));
237 std::vector<const char*> enabledInstanceExtensionNames;
238 enabledInstanceExtensionNames.reserve(instanceExtensions.size());
239 interface.instanceExtensionNames.reserve(instanceExtensions.size());
240 for (const auto& instExt : instanceExtensions) {
241 enabledInstanceExtensionNames.push_back(instExt.extensionName);
242 interface.instanceExtensionNames.push_back(instExt.extensionName);
243 }
244
245 const VkInstanceCreateInfo instanceCreateInfo = {
246 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
247 nullptr,
248 0,
249 &appInfo,
250 0,
251 nullptr,
252 (uint32_t)enabledInstanceExtensionNames.size(),
253 enabledInstanceExtensionNames.data(),
254 };
255
256 VK_GET_PROC(CreateInstance);
257 VkInstance instance;
258 VK_CHECK(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
259
260 VK_GET_INST_PROC(instance, DestroyInstance);
261 interface.funcs.vkDestroyInstance = vkDestroyInstance;
262 VK_GET_INST_PROC(instance, EnumeratePhysicalDevices);
263 VK_GET_INST_PROC(instance, EnumerateDeviceExtensionProperties);
264 VK_GET_INST_PROC(instance, GetPhysicalDeviceProperties2);
265 VK_GET_INST_PROC(instance, GetPhysicalDeviceExternalSemaphoreProperties);
Ian Elliottd50658f2023-06-28 11:08:35 -0600266 VK_GET_INST_PROC(instance, GetPhysicalDeviceQueueFamilyProperties2);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600267 VK_GET_INST_PROC(instance, GetPhysicalDeviceFeatures2);
268 VK_GET_INST_PROC(instance, CreateDevice);
269
270 uint32_t physdevCount;
271 VK_CHECK(vkEnumeratePhysicalDevices(instance, &physdevCount, nullptr));
272 if (physdevCount == 0) {
273 BAIL("Could not find any physical devices");
274 }
275
276 physdevCount = 1;
277 VkPhysicalDevice physicalDevice;
278 VkResult enumeratePhysDevsErr =
279 vkEnumeratePhysicalDevices(instance, &physdevCount, &physicalDevice);
280 if (enumeratePhysDevsErr != VK_SUCCESS && VK_INCOMPLETE != enumeratePhysDevsErr) {
281 BAIL("vkEnumeratePhysicalDevices failed with non-VK_INCOMPLETE error: %d",
282 enumeratePhysDevsErr);
283 }
284
285 VkPhysicalDeviceProperties2 physDevProps = {
286 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
287 0,
288 {},
289 };
290 VkPhysicalDeviceProtectedMemoryProperties protMemProps = {
291 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
292 0,
293 {},
294 };
295
296 if (protectedContent) {
297 physDevProps.pNext = &protMemProps;
298 }
299
300 vkGetPhysicalDeviceProperties2(physicalDevice, &physDevProps);
301 if (physDevProps.properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
302 BAIL("Could not find a Vulkan 1.1+ physical device");
303 }
304
305 // Check for syncfd support. Bail if we cannot both import and export them.
306 VkPhysicalDeviceExternalSemaphoreInfo semInfo = {
307 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
308 nullptr,
309 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
310 };
311 VkExternalSemaphoreProperties semProps = {
312 VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, nullptr, 0, 0, 0,
313 };
314 vkGetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &semInfo, &semProps);
315
316 bool sufficientSemaphoreSyncFdSupport = (semProps.exportFromImportedHandleTypes &
317 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
318 (semProps.compatibleHandleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
319 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) &&
320 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
321
322 if (!sufficientSemaphoreSyncFdSupport) {
323 BAIL("Vulkan device does not support sufficient external semaphore sync fd features. "
324 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
325 "compatibleHandleTypes 0x%x (needed 0x%x) "
326 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
327 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
328 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
329 semProps.externalSemaphoreFeatures,
330 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
331 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
332 } else {
333 ALOGD("Vulkan device supports sufficient external semaphore sync fd features. "
334 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
335 "compatibleHandleTypes 0x%x (needed 0x%x) "
336 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
337 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
338 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
339 semProps.externalSemaphoreFeatures,
340 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
341 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
342 }
343
344 uint32_t queueCount;
Ian Elliottd50658f2023-06-28 11:08:35 -0600345 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, nullptr);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600346 if (queueCount == 0) {
347 BAIL("Could not find queues for physical device");
348 }
349
Ian Elliottd50658f2023-06-28 11:08:35 -0600350 std::vector<VkQueueFamilyProperties2> queueProps(queueCount);
351 std::vector<VkQueueFamilyGlobalPriorityPropertiesEXT> queuePriorityProps(queueCount);
352 VkQueueGlobalPriorityKHR queuePriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
353 // Even though we don't yet know if the VK_EXT_global_priority extension is available,
354 // we can safely add the request to the pNext chain, and if the extension is not
355 // available, it will be ignored.
356 for (uint32_t i = 0; i < queueCount; ++i) {
357 queuePriorityProps[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT;
358 queuePriorityProps[i].pNext = nullptr;
359 queueProps[i].pNext = &queuePriorityProps[i];
360 }
361 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, queueProps.data());
Ian Elliott1f0911e2022-09-09 16:31:47 -0600362
363 int graphicsQueueIndex = -1;
364 for (uint32_t i = 0; i < queueCount; ++i) {
Ian Elliottd50658f2023-06-28 11:08:35 -0600365 // Look at potential answers to the VK_EXT_global_priority query. If answers were
366 // provided, we may adjust the queuePriority.
367 if (queueProps[i].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
368 for (uint32_t j = 0; j < queuePriorityProps[i].priorityCount; j++) {
369 if (queuePriorityProps[i].priorities[j] > queuePriority) {
370 queuePriority = queuePriorityProps[i].priorities[j];
371 }
372 }
373 if (queuePriority == VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR) {
374 interface.isRealtimePriority = true;
375 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600376 graphicsQueueIndex = i;
377 break;
378 }
379 }
380
381 if (graphicsQueueIndex == -1) {
382 BAIL("Could not find a graphics queue family");
383 }
384
385 uint32_t deviceExtensionCount;
386 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
387 nullptr));
388 std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
389 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
390 deviceExtensions.data()));
391
392 std::vector<const char*> enabledDeviceExtensionNames;
393 enabledDeviceExtensionNames.reserve(deviceExtensions.size());
394 interface.deviceExtensionNames.reserve(deviceExtensions.size());
395 for (const auto& devExt : deviceExtensions) {
396 enabledDeviceExtensionNames.push_back(devExt.extensionName);
397 interface.deviceExtensionNames.push_back(devExt.extensionName);
398 }
399
400 interface.grExtensions.init(sGetProc, instance, physicalDevice,
401 enabledInstanceExtensionNames.size(),
402 enabledInstanceExtensionNames.data(),
403 enabledDeviceExtensionNames.size(),
404 enabledDeviceExtensionNames.data());
405
406 if (!interface.grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
407 BAIL("Vulkan driver doesn't support external semaphore fd");
408 }
409
410 interface.physicalDeviceFeatures2 = new VkPhysicalDeviceFeatures2;
411 interface.physicalDeviceFeatures2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
412 interface.physicalDeviceFeatures2->pNext = nullptr;
413
414 interface.samplerYcbcrConversionFeatures = new VkPhysicalDeviceSamplerYcbcrConversionFeatures;
415 interface.samplerYcbcrConversionFeatures->sType =
416 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
417 interface.samplerYcbcrConversionFeatures->pNext = nullptr;
418
419 interface.physicalDeviceFeatures2->pNext = interface.samplerYcbcrConversionFeatures;
420 void** tailPnext = &interface.samplerYcbcrConversionFeatures->pNext;
421
422 if (protectedContent) {
Ian Elliottae0b8d12023-01-05 19:13:42 -0700423 interface.protectedMemoryFeatures = new VkPhysicalDeviceProtectedMemoryFeatures;
Ian Elliott1f0911e2022-09-09 16:31:47 -0600424 interface.protectedMemoryFeatures->sType =
425 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
426 interface.protectedMemoryFeatures->pNext = nullptr;
427 *tailPnext = interface.protectedMemoryFeatures;
428 tailPnext = &interface.protectedMemoryFeatures->pNext;
429 }
430
431 vkGetPhysicalDeviceFeatures2(physicalDevice, interface.physicalDeviceFeatures2);
432 // Looks like this would slow things down and we can't depend on it on all platforms
433 interface.physicalDeviceFeatures2->features.robustBufferAccess = VK_FALSE;
434
435 float queuePriorities[1] = {0.0f};
436 void* queueNextPtr = nullptr;
437
438 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo = {
439 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
440 nullptr,
441 // If queue priority is supported, RE should always have realtime priority.
Ian Elliottd50658f2023-06-28 11:08:35 -0600442 queuePriority,
Ian Elliott1f0911e2022-09-09 16:31:47 -0600443 };
444
445 if (interface.grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
446 queueNextPtr = &queuePriorityCreateInfo;
Ian Elliott1f0911e2022-09-09 16:31:47 -0600447 }
448
449 VkDeviceQueueCreateFlags deviceQueueCreateFlags =
450 (VkDeviceQueueCreateFlags)(protectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0);
451
452 const VkDeviceQueueCreateInfo queueInfo = {
453 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
454 queueNextPtr,
455 deviceQueueCreateFlags,
456 (uint32_t)graphicsQueueIndex,
457 1,
458 queuePriorities,
459 };
460
461 const VkDeviceCreateInfo deviceInfo = {
462 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
463 interface.physicalDeviceFeatures2,
464 0,
465 1,
466 &queueInfo,
467 0,
468 nullptr,
469 (uint32_t)enabledDeviceExtensionNames.size(),
470 enabledDeviceExtensionNames.data(),
471 nullptr,
472 };
473
474 ALOGD("Trying to create Vk device with protectedContent=%d", protectedContent);
475 VkDevice device;
476 VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device));
477 ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
478
479 VkQueue graphicsQueue;
Ian Elliott87e3dd82023-02-27 12:07:10 -0700480 VK_GET_DEV_PROC(device, GetDeviceQueue2);
481 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
482 deviceQueueCreateFlags,
483 (uint32_t)graphicsQueueIndex, 0};
484 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600485
486 VK_GET_DEV_PROC(device, DeviceWaitIdle);
487 VK_GET_DEV_PROC(device, DestroyDevice);
488 interface.funcs.vkDeviceWaitIdle = vkDeviceWaitIdle;
489 interface.funcs.vkDestroyDevice = vkDestroyDevice;
490
491 VK_GET_DEV_PROC(device, CreateSemaphore);
492 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
493 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
494 VK_GET_DEV_PROC(device, DestroySemaphore);
495 interface.funcs.vkCreateSemaphore = vkCreateSemaphore;
496 interface.funcs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
497 interface.funcs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
498 interface.funcs.vkDestroySemaphore = vkDestroySemaphore;
499
500 // At this point, everything's succeeded and we can continue
501 interface.initialized = true;
502 interface.instance = instance;
503 interface.physicalDevice = physicalDevice;
504 interface.device = device;
505 interface.queue = graphicsQueue;
506 interface.queueIndex = graphicsQueueIndex;
507 interface.apiVersion = physDevProps.properties.apiVersion;
508 // grExtensions already constructed
509 // feature pointers already constructed
510 interface.grGetProc = sGetProc;
511 interface.isProtected = protectedContent;
512 // funcs already initialized
513
514 ALOGD("%s: Success init Vulkan interface", __func__);
515 return interface;
516}
517
518void teardownVulkanInterface(VulkanInterface* interface) {
519 interface->initialized = false;
520
521 if (interface->device != VK_NULL_HANDLE) {
522 interface->funcs.vkDeviceWaitIdle(interface->device);
523 interface->funcs.vkDestroyDevice(interface->device, nullptr);
524 interface->device = VK_NULL_HANDLE;
525 }
526 if (interface->instance != VK_NULL_HANDLE) {
527 interface->funcs.vkDestroyInstance(interface->instance, nullptr);
528 interface->instance = VK_NULL_HANDLE;
529 }
530
531 if (interface->protectedMemoryFeatures) {
532 delete interface->protectedMemoryFeatures;
533 }
534
535 if (interface->samplerYcbcrConversionFeatures) {
536 delete interface->samplerYcbcrConversionFeatures;
537 }
538
539 if (interface->physicalDeviceFeatures2) {
540 delete interface->physicalDeviceFeatures2;
541 }
542
543 interface->samplerYcbcrConversionFeatures = nullptr;
544 interface->physicalDeviceFeatures2 = nullptr;
545 interface->protectedMemoryFeatures = nullptr;
546}
547
548static VulkanInterface sVulkanInterface;
549static VulkanInterface sProtectedContentVulkanInterface;
550
551static void sSetupVulkanInterface() {
552 if (!sVulkanInterface.initialized) {
553 sVulkanInterface = initVulkanInterface(false /* no protected content */);
554 // We will have to abort if non-protected VkDevice creation fails (then nothing works).
555 LOG_ALWAYS_FATAL_IF(!sVulkanInterface.initialized,
556 "Could not initialize Vulkan RenderEngine!");
557 }
558 if (!sProtectedContentVulkanInterface.initialized) {
559 sProtectedContentVulkanInterface = initVulkanInterface(true /* protected content */);
560 if (!sProtectedContentVulkanInterface.initialized) {
561 ALOGE("Could not initialize protected content Vulkan RenderEngine.");
562 }
563 }
564}
565
566namespace skia {
567
568using base::StringAppendF;
569
570bool SkiaVkRenderEngine::canSupportSkiaVkRenderEngine() {
571 VulkanInterface temp = initVulkanInterface(false /* no protected content */);
572 ALOGD("SkiaVkRenderEngine::canSupportSkiaVkRenderEngine(): initialized == %s.",
573 temp.initialized ? "true" : "false");
574 return temp.initialized;
575}
576
577std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
578 const RenderEngineCreationArgs& args) {
579 std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
580 engine->ensureGrContextsCreated();
581
582 if (sVulkanInterface.initialized) {
583 ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__);
584 return engine;
585 } else {
586 ALOGD("SkiaVkRenderEngine::%s: could not create SkiaVkRenderEngine. "
587 "Likely insufficient Vulkan support",
588 __func__);
589 return {};
590 }
591}
592
593SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
594 : SkiaRenderEngine(args.renderEngineType, static_cast<PixelFormat>(args.pixelFormat),
Alec Mouri47bcb072023-08-15 02:02:49 +0000595 args.supportsBackgroundBlur) {}
Ian Elliott1f0911e2022-09-09 16:31:47 -0600596
597SkiaVkRenderEngine::~SkiaVkRenderEngine() {
598 finishRenderingAndAbandonContext();
599}
600
601SkiaRenderEngine::Contexts SkiaVkRenderEngine::createDirectContexts(
602 const GrContextOptions& options) {
603 sSetupVulkanInterface();
604
605 SkiaRenderEngine::Contexts contexts;
606 contexts.first = GrDirectContext::MakeVulkan(sVulkanInterface.getBackendContext(), options);
607 if (supportsProtectedContentImpl()) {
608 contexts.second =
609 GrDirectContext::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
610 options);
611 }
612
613 return contexts;
614}
615
616bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
617 return sProtectedContentVulkanInterface.initialized;
618}
619
620bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
621 return true;
622}
623
Ian Elliott98e87162023-04-14 14:05:19 -0600624static void delete_semaphore(void* semaphore) {
625 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
626 --info->mRefs;
627 if (!info->mRefs) {
628 sVulkanInterface.destroySemaphore(info->mSemaphore);
629 delete info;
630 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600631}
632
Ian Elliott98e87162023-04-14 14:05:19 -0600633static void delete_semaphore_protected(void* semaphore) {
634 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
635 --info->mRefs;
636 if (!info->mRefs) {
637 sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore);
638 delete info;
639 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600640}
641
642static VulkanInterface& getVulkanInterface(bool protectedContext) {
643 if (protectedContext) {
644 return sProtectedContentVulkanInterface;
645 }
646 return sVulkanInterface;
647}
648
649void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) {
650 if (fenceFd.get() < 0) return;
651
652 int dupedFd = dup(fenceFd.get());
653 if (dupedFd < 0) {
654 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
655 sync_wait(fenceFd.get(), -1);
656 return;
657 }
658
659 base::unique_fd fenceDup(dupedFd);
660 VkSemaphore waitSemaphore =
661 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
662 GrBackendSemaphore beSemaphore;
663 beSemaphore.initVulkan(waitSemaphore);
664 grContext->wait(1, &beSemaphore, true /* delete after wait */);
665}
666
667base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
Ian Elliott98e87162023-04-14 14:05:19 -0600668 VulkanInterface& vi = getVulkanInterface(isProtected());
669 VkSemaphore semaphore = vi.createExportableSemaphore();
670
671 GrBackendSemaphore backendSemaphore;
672 backendSemaphore.initVulkan(semaphore);
673
Ian Elliott1f0911e2022-09-09 16:31:47 -0600674 GrFlushInfo flushInfo;
Ian Elliott98e87162023-04-14 14:05:19 -0600675 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
676 if (semaphore != VK_NULL_HANDLE) {
677 destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore);
678 flushInfo.fNumSemaphores = 1;
679 flushInfo.fSignalSemaphores = &backendSemaphore;
680 flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
681 flushInfo.fFinishedContext = destroySemaphoreInfo;
682 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600683 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
684 grContext->submit(false /* no cpu sync */);
685 int drawFenceFd = -1;
Ian Elliott98e87162023-04-14 14:05:19 -0600686 if (semaphore != VK_NULL_HANDLE) {
687 if (GrSemaphoresSubmitted::kYes == submitted) {
688 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
689 }
690 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
691 flushInfo.fFinishedProc(destroySemaphoreInfo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600692 }
693 base::unique_fd res(drawFenceFd);
694 return res;
695}
696
697int SkiaVkRenderEngine::getContextPriority() {
698 // EGL_CONTEXT_PRIORITY_REALTIME_NV
699 constexpr int kRealtimePriority = 0x3357;
700 if (getVulkanInterface(isProtected()).isRealtimePriority) {
701 return kRealtimePriority;
702 } else {
703 return 0;
704 }
705}
706
707void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
708 StringAppendF(&result, "\n ------------RE Vulkan----------\n");
709 StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.initialized);
710 StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
711 sProtectedContentVulkanInterface.initialized);
712
713 if (!sVulkanInterface.initialized) {
714 return;
715 }
716
717 StringAppendF(&result, "\n Instance extensions:\n");
718 for (const auto& name : sVulkanInterface.instanceExtensionNames) {
719 StringAppendF(&result, "\n %s\n", name.c_str());
720 }
721
722 StringAppendF(&result, "\n Device extensions:\n");
723 for (const auto& name : sVulkanInterface.deviceExtensionNames) {
724 StringAppendF(&result, "\n %s\n", name.c_str());
725 }
726}
727
728} // namespace skia
729} // namespace renderengine
730} // namespace android