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