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