blob: b99e3853ee9c817b60a6a9da9ceac9bae7e72fc1 [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);
266 VK_GET_INST_PROC(instance, GetPhysicalDeviceQueueFamilyProperties);
267 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;
345 vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, nullptr);
346 if (queueCount == 0) {
347 BAIL("Could not find queues for physical device");
348 }
349
350 std::vector<VkQueueFamilyProperties> queueProps(queueCount);
351 vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
352
353 int graphicsQueueIndex = -1;
354 for (uint32_t i = 0; i < queueCount; ++i) {
355 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
356 graphicsQueueIndex = i;
357 break;
358 }
359 }
360
361 if (graphicsQueueIndex == -1) {
362 BAIL("Could not find a graphics queue family");
363 }
364
365 uint32_t deviceExtensionCount;
366 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
367 nullptr));
368 std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
369 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
370 deviceExtensions.data()));
371
372 std::vector<const char*> enabledDeviceExtensionNames;
373 enabledDeviceExtensionNames.reserve(deviceExtensions.size());
374 interface.deviceExtensionNames.reserve(deviceExtensions.size());
375 for (const auto& devExt : deviceExtensions) {
376 enabledDeviceExtensionNames.push_back(devExt.extensionName);
377 interface.deviceExtensionNames.push_back(devExt.extensionName);
378 }
379
380 interface.grExtensions.init(sGetProc, instance, physicalDevice,
381 enabledInstanceExtensionNames.size(),
382 enabledInstanceExtensionNames.data(),
383 enabledDeviceExtensionNames.size(),
384 enabledDeviceExtensionNames.data());
385
386 if (!interface.grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
387 BAIL("Vulkan driver doesn't support external semaphore fd");
388 }
389
390 interface.physicalDeviceFeatures2 = new VkPhysicalDeviceFeatures2;
391 interface.physicalDeviceFeatures2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
392 interface.physicalDeviceFeatures2->pNext = nullptr;
393
394 interface.samplerYcbcrConversionFeatures = new VkPhysicalDeviceSamplerYcbcrConversionFeatures;
395 interface.samplerYcbcrConversionFeatures->sType =
396 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
397 interface.samplerYcbcrConversionFeatures->pNext = nullptr;
398
399 interface.physicalDeviceFeatures2->pNext = interface.samplerYcbcrConversionFeatures;
400 void** tailPnext = &interface.samplerYcbcrConversionFeatures->pNext;
401
402 if (protectedContent) {
Ian Elliottae0b8d12023-01-05 19:13:42 -0700403 interface.protectedMemoryFeatures = new VkPhysicalDeviceProtectedMemoryFeatures;
Ian Elliott1f0911e2022-09-09 16:31:47 -0600404 interface.protectedMemoryFeatures->sType =
405 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
406 interface.protectedMemoryFeatures->pNext = nullptr;
407 *tailPnext = interface.protectedMemoryFeatures;
408 tailPnext = &interface.protectedMemoryFeatures->pNext;
409 }
410
411 vkGetPhysicalDeviceFeatures2(physicalDevice, interface.physicalDeviceFeatures2);
412 // Looks like this would slow things down and we can't depend on it on all platforms
413 interface.physicalDeviceFeatures2->features.robustBufferAccess = VK_FALSE;
414
415 float queuePriorities[1] = {0.0f};
416 void* queueNextPtr = nullptr;
417
418 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo = {
419 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
420 nullptr,
421 // If queue priority is supported, RE should always have realtime priority.
422 VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT,
423 };
424
425 if (interface.grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
426 queueNextPtr = &queuePriorityCreateInfo;
427 interface.isRealtimePriority = true;
428 }
429
430 VkDeviceQueueCreateFlags deviceQueueCreateFlags =
431 (VkDeviceQueueCreateFlags)(protectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0);
432
433 const VkDeviceQueueCreateInfo queueInfo = {
434 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
435 queueNextPtr,
436 deviceQueueCreateFlags,
437 (uint32_t)graphicsQueueIndex,
438 1,
439 queuePriorities,
440 };
441
442 const VkDeviceCreateInfo deviceInfo = {
443 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
444 interface.physicalDeviceFeatures2,
445 0,
446 1,
447 &queueInfo,
448 0,
449 nullptr,
450 (uint32_t)enabledDeviceExtensionNames.size(),
451 enabledDeviceExtensionNames.data(),
452 nullptr,
453 };
454
455 ALOGD("Trying to create Vk device with protectedContent=%d", protectedContent);
456 VkDevice device;
457 VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device));
458 ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
459
460 VkQueue graphicsQueue;
Ian Elliott87e3dd82023-02-27 12:07:10 -0700461 VK_GET_DEV_PROC(device, GetDeviceQueue2);
462 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
463 deviceQueueCreateFlags,
464 (uint32_t)graphicsQueueIndex, 0};
465 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600466
467 VK_GET_DEV_PROC(device, DeviceWaitIdle);
468 VK_GET_DEV_PROC(device, DestroyDevice);
469 interface.funcs.vkDeviceWaitIdle = vkDeviceWaitIdle;
470 interface.funcs.vkDestroyDevice = vkDestroyDevice;
471
472 VK_GET_DEV_PROC(device, CreateSemaphore);
473 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
474 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
475 VK_GET_DEV_PROC(device, DestroySemaphore);
476 interface.funcs.vkCreateSemaphore = vkCreateSemaphore;
477 interface.funcs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
478 interface.funcs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
479 interface.funcs.vkDestroySemaphore = vkDestroySemaphore;
480
481 // At this point, everything's succeeded and we can continue
482 interface.initialized = true;
483 interface.instance = instance;
484 interface.physicalDevice = physicalDevice;
485 interface.device = device;
486 interface.queue = graphicsQueue;
487 interface.queueIndex = graphicsQueueIndex;
488 interface.apiVersion = physDevProps.properties.apiVersion;
489 // grExtensions already constructed
490 // feature pointers already constructed
491 interface.grGetProc = sGetProc;
492 interface.isProtected = protectedContent;
493 // funcs already initialized
494
495 ALOGD("%s: Success init Vulkan interface", __func__);
496 return interface;
497}
498
499void teardownVulkanInterface(VulkanInterface* interface) {
500 interface->initialized = false;
501
502 if (interface->device != VK_NULL_HANDLE) {
503 interface->funcs.vkDeviceWaitIdle(interface->device);
504 interface->funcs.vkDestroyDevice(interface->device, nullptr);
505 interface->device = VK_NULL_HANDLE;
506 }
507 if (interface->instance != VK_NULL_HANDLE) {
508 interface->funcs.vkDestroyInstance(interface->instance, nullptr);
509 interface->instance = VK_NULL_HANDLE;
510 }
511
512 if (interface->protectedMemoryFeatures) {
513 delete interface->protectedMemoryFeatures;
514 }
515
516 if (interface->samplerYcbcrConversionFeatures) {
517 delete interface->samplerYcbcrConversionFeatures;
518 }
519
520 if (interface->physicalDeviceFeatures2) {
521 delete interface->physicalDeviceFeatures2;
522 }
523
524 interface->samplerYcbcrConversionFeatures = nullptr;
525 interface->physicalDeviceFeatures2 = nullptr;
526 interface->protectedMemoryFeatures = nullptr;
527}
528
529static VulkanInterface sVulkanInterface;
530static VulkanInterface sProtectedContentVulkanInterface;
531
532static void sSetupVulkanInterface() {
533 if (!sVulkanInterface.initialized) {
534 sVulkanInterface = initVulkanInterface(false /* no protected content */);
535 // We will have to abort if non-protected VkDevice creation fails (then nothing works).
536 LOG_ALWAYS_FATAL_IF(!sVulkanInterface.initialized,
537 "Could not initialize Vulkan RenderEngine!");
538 }
539 if (!sProtectedContentVulkanInterface.initialized) {
540 sProtectedContentVulkanInterface = initVulkanInterface(true /* protected content */);
541 if (!sProtectedContentVulkanInterface.initialized) {
542 ALOGE("Could not initialize protected content Vulkan RenderEngine.");
543 }
544 }
545}
546
547namespace skia {
548
549using base::StringAppendF;
550
551bool SkiaVkRenderEngine::canSupportSkiaVkRenderEngine() {
552 VulkanInterface temp = initVulkanInterface(false /* no protected content */);
553 ALOGD("SkiaVkRenderEngine::canSupportSkiaVkRenderEngine(): initialized == %s.",
554 temp.initialized ? "true" : "false");
555 return temp.initialized;
556}
557
558std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
559 const RenderEngineCreationArgs& args) {
560 std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
561 engine->ensureGrContextsCreated();
562
563 if (sVulkanInterface.initialized) {
564 ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__);
565 return engine;
566 } else {
567 ALOGD("SkiaVkRenderEngine::%s: could not create SkiaVkRenderEngine. "
568 "Likely insufficient Vulkan support",
569 __func__);
570 return {};
571 }
572}
573
574SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
575 : SkiaRenderEngine(args.renderEngineType, static_cast<PixelFormat>(args.pixelFormat),
576 args.useColorManagement, args.supportsBackgroundBlur) {}
577
578SkiaVkRenderEngine::~SkiaVkRenderEngine() {
579 finishRenderingAndAbandonContext();
580}
581
582SkiaRenderEngine::Contexts SkiaVkRenderEngine::createDirectContexts(
583 const GrContextOptions& options) {
584 sSetupVulkanInterface();
585
586 SkiaRenderEngine::Contexts contexts;
587 contexts.first = GrDirectContext::MakeVulkan(sVulkanInterface.getBackendContext(), options);
588 if (supportsProtectedContentImpl()) {
589 contexts.second =
590 GrDirectContext::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
591 options);
592 }
593
594 return contexts;
595}
596
597bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
598 return sProtectedContentVulkanInterface.initialized;
599}
600
601bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
602 return true;
603}
604
Ian Elliott98e87162023-04-14 14:05:19 -0600605static void delete_semaphore(void* semaphore) {
606 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
607 --info->mRefs;
608 if (!info->mRefs) {
609 sVulkanInterface.destroySemaphore(info->mSemaphore);
610 delete info;
611 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600612}
613
Ian Elliott98e87162023-04-14 14:05:19 -0600614static void delete_semaphore_protected(void* semaphore) {
615 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
616 --info->mRefs;
617 if (!info->mRefs) {
618 sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore);
619 delete info;
620 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600621}
622
623static VulkanInterface& getVulkanInterface(bool protectedContext) {
624 if (protectedContext) {
625 return sProtectedContentVulkanInterface;
626 }
627 return sVulkanInterface;
628}
629
630void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) {
631 if (fenceFd.get() < 0) return;
632
633 int dupedFd = dup(fenceFd.get());
634 if (dupedFd < 0) {
635 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
636 sync_wait(fenceFd.get(), -1);
637 return;
638 }
639
640 base::unique_fd fenceDup(dupedFd);
641 VkSemaphore waitSemaphore =
642 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
643 GrBackendSemaphore beSemaphore;
644 beSemaphore.initVulkan(waitSemaphore);
645 grContext->wait(1, &beSemaphore, true /* delete after wait */);
646}
647
648base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
Ian Elliott98e87162023-04-14 14:05:19 -0600649 VulkanInterface& vi = getVulkanInterface(isProtected());
650 VkSemaphore semaphore = vi.createExportableSemaphore();
651
652 GrBackendSemaphore backendSemaphore;
653 backendSemaphore.initVulkan(semaphore);
654
Ian Elliott1f0911e2022-09-09 16:31:47 -0600655 GrFlushInfo flushInfo;
Ian Elliott98e87162023-04-14 14:05:19 -0600656 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
657 if (semaphore != VK_NULL_HANDLE) {
658 destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore);
659 flushInfo.fNumSemaphores = 1;
660 flushInfo.fSignalSemaphores = &backendSemaphore;
661 flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
662 flushInfo.fFinishedContext = destroySemaphoreInfo;
663 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600664 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
665 grContext->submit(false /* no cpu sync */);
666 int drawFenceFd = -1;
Ian Elliott98e87162023-04-14 14:05:19 -0600667 if (semaphore != VK_NULL_HANDLE) {
668 if (GrSemaphoresSubmitted::kYes == submitted) {
669 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
670 }
671 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
672 flushInfo.fFinishedProc(destroySemaphoreInfo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600673 }
674 base::unique_fd res(drawFenceFd);
675 return res;
676}
677
678int SkiaVkRenderEngine::getContextPriority() {
679 // EGL_CONTEXT_PRIORITY_REALTIME_NV
680 constexpr int kRealtimePriority = 0x3357;
681 if (getVulkanInterface(isProtected()).isRealtimePriority) {
682 return kRealtimePriority;
683 } else {
684 return 0;
685 }
686}
687
688void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
689 StringAppendF(&result, "\n ------------RE Vulkan----------\n");
690 StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.initialized);
691 StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
692 sProtectedContentVulkanInterface.initialized);
693
694 if (!sVulkanInterface.initialized) {
695 return;
696 }
697
698 StringAppendF(&result, "\n Instance extensions:\n");
699 for (const auto& name : sVulkanInterface.instanceExtensionNames) {
700 StringAppendF(&result, "\n %s\n", name.c_str());
701 }
702
703 StringAppendF(&result, "\n Device extensions:\n");
704 for (const auto& name : sVulkanInterface.deviceExtensionNames) {
705 StringAppendF(&result, "\n %s\n", name.c_str());
706 }
707}
708
709} // namespace skia
710} // namespace renderengine
711} // namespace android