blob: 936e31679f443477a1925f7ac4a1ee718c9e6ea8 [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;
Ian Elliott87e3dd82023-02-27 12:07:10 -0700447 VK_GET_DEV_PROC(device, GetDeviceQueue2);
448 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
449 deviceQueueCreateFlags,
450 (uint32_t)graphicsQueueIndex, 0};
451 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600452
453 VK_GET_DEV_PROC(device, DeviceWaitIdle);
454 VK_GET_DEV_PROC(device, DestroyDevice);
455 interface.funcs.vkDeviceWaitIdle = vkDeviceWaitIdle;
456 interface.funcs.vkDestroyDevice = vkDestroyDevice;
457
458 VK_GET_DEV_PROC(device, CreateSemaphore);
459 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
460 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
461 VK_GET_DEV_PROC(device, DestroySemaphore);
462 interface.funcs.vkCreateSemaphore = vkCreateSemaphore;
463 interface.funcs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
464 interface.funcs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
465 interface.funcs.vkDestroySemaphore = vkDestroySemaphore;
466
467 // At this point, everything's succeeded and we can continue
468 interface.initialized = true;
469 interface.instance = instance;
470 interface.physicalDevice = physicalDevice;
471 interface.device = device;
472 interface.queue = graphicsQueue;
473 interface.queueIndex = graphicsQueueIndex;
474 interface.apiVersion = physDevProps.properties.apiVersion;
475 // grExtensions already constructed
476 // feature pointers already constructed
477 interface.grGetProc = sGetProc;
478 interface.isProtected = protectedContent;
479 // funcs already initialized
480
481 ALOGD("%s: Success init Vulkan interface", __func__);
482 return interface;
483}
484
485void teardownVulkanInterface(VulkanInterface* interface) {
486 interface->initialized = false;
487
488 if (interface->device != VK_NULL_HANDLE) {
489 interface->funcs.vkDeviceWaitIdle(interface->device);
490 interface->funcs.vkDestroyDevice(interface->device, nullptr);
491 interface->device = VK_NULL_HANDLE;
492 }
493 if (interface->instance != VK_NULL_HANDLE) {
494 interface->funcs.vkDestroyInstance(interface->instance, nullptr);
495 interface->instance = VK_NULL_HANDLE;
496 }
497
498 if (interface->protectedMemoryFeatures) {
499 delete interface->protectedMemoryFeatures;
500 }
501
502 if (interface->samplerYcbcrConversionFeatures) {
503 delete interface->samplerYcbcrConversionFeatures;
504 }
505
506 if (interface->physicalDeviceFeatures2) {
507 delete interface->physicalDeviceFeatures2;
508 }
509
510 interface->samplerYcbcrConversionFeatures = nullptr;
511 interface->physicalDeviceFeatures2 = nullptr;
512 interface->protectedMemoryFeatures = nullptr;
513}
514
515static VulkanInterface sVulkanInterface;
516static VulkanInterface sProtectedContentVulkanInterface;
517
518static void sSetupVulkanInterface() {
519 if (!sVulkanInterface.initialized) {
520 sVulkanInterface = initVulkanInterface(false /* no protected content */);
521 // We will have to abort if non-protected VkDevice creation fails (then nothing works).
522 LOG_ALWAYS_FATAL_IF(!sVulkanInterface.initialized,
523 "Could not initialize Vulkan RenderEngine!");
524 }
525 if (!sProtectedContentVulkanInterface.initialized) {
526 sProtectedContentVulkanInterface = initVulkanInterface(true /* protected content */);
527 if (!sProtectedContentVulkanInterface.initialized) {
528 ALOGE("Could not initialize protected content Vulkan RenderEngine.");
529 }
530 }
531}
532
533namespace skia {
534
535using base::StringAppendF;
536
537bool SkiaVkRenderEngine::canSupportSkiaVkRenderEngine() {
538 VulkanInterface temp = initVulkanInterface(false /* no protected content */);
539 ALOGD("SkiaVkRenderEngine::canSupportSkiaVkRenderEngine(): initialized == %s.",
540 temp.initialized ? "true" : "false");
541 return temp.initialized;
542}
543
544std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
545 const RenderEngineCreationArgs& args) {
546 std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
547 engine->ensureGrContextsCreated();
548
549 if (sVulkanInterface.initialized) {
550 ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__);
551 return engine;
552 } else {
553 ALOGD("SkiaVkRenderEngine::%s: could not create SkiaVkRenderEngine. "
554 "Likely insufficient Vulkan support",
555 __func__);
556 return {};
557 }
558}
559
560SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
561 : SkiaRenderEngine(args.renderEngineType, static_cast<PixelFormat>(args.pixelFormat),
562 args.useColorManagement, args.supportsBackgroundBlur) {}
563
564SkiaVkRenderEngine::~SkiaVkRenderEngine() {
565 finishRenderingAndAbandonContext();
566}
567
568SkiaRenderEngine::Contexts SkiaVkRenderEngine::createDirectContexts(
569 const GrContextOptions& options) {
570 sSetupVulkanInterface();
571
572 SkiaRenderEngine::Contexts contexts;
573 contexts.first = GrDirectContext::MakeVulkan(sVulkanInterface.getBackendContext(), options);
574 if (supportsProtectedContentImpl()) {
575 contexts.second =
576 GrDirectContext::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
577 options);
578 }
579
580 return contexts;
581}
582
583bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
584 return sProtectedContentVulkanInterface.initialized;
585}
586
587bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
588 return true;
589}
590
591static void delete_semaphore(void* _semaphore) {
592 VkSemaphore semaphore = (VkSemaphore)_semaphore;
593 sVulkanInterface.destroySemaphore(semaphore);
594}
595
596static void delete_semaphore_protected(void* _semaphore) {
597 VkSemaphore semaphore = (VkSemaphore)_semaphore;
598 sProtectedContentVulkanInterface.destroySemaphore(semaphore);
599}
600
601static VulkanInterface& getVulkanInterface(bool protectedContext) {
602 if (protectedContext) {
603 return sProtectedContentVulkanInterface;
604 }
605 return sVulkanInterface;
606}
607
608void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) {
609 if (fenceFd.get() < 0) return;
610
611 int dupedFd = dup(fenceFd.get());
612 if (dupedFd < 0) {
613 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
614 sync_wait(fenceFd.get(), -1);
615 return;
616 }
617
618 base::unique_fd fenceDup(dupedFd);
619 VkSemaphore waitSemaphore =
620 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
621 GrBackendSemaphore beSemaphore;
622 beSemaphore.initVulkan(waitSemaphore);
623 grContext->wait(1, &beSemaphore, true /* delete after wait */);
624}
625
626base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
627 VkSemaphore signalSemaphore = getVulkanInterface(isProtected()).createExportableSemaphore();
628 GrBackendSemaphore beSignalSemaphore;
629 beSignalSemaphore.initVulkan(signalSemaphore);
630 GrFlushInfo flushInfo;
631 flushInfo.fNumSemaphores = 1;
632 flushInfo.fSignalSemaphores = &beSignalSemaphore;
633 flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
634 flushInfo.fFinishedContext = (void*)signalSemaphore;
635 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
636 grContext->submit(false /* no cpu sync */);
637 int drawFenceFd = -1;
638 if (GrSemaphoresSubmitted::kYes == submitted) {
639 drawFenceFd = getVulkanInterface(isProtected()).exportSemaphoreSyncFd(signalSemaphore);
640 }
641 base::unique_fd res(drawFenceFd);
642 return res;
643}
644
645int SkiaVkRenderEngine::getContextPriority() {
646 // EGL_CONTEXT_PRIORITY_REALTIME_NV
647 constexpr int kRealtimePriority = 0x3357;
648 if (getVulkanInterface(isProtected()).isRealtimePriority) {
649 return kRealtimePriority;
650 } else {
651 return 0;
652 }
653}
654
655void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
656 StringAppendF(&result, "\n ------------RE Vulkan----------\n");
657 StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.initialized);
658 StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
659 sProtectedContentVulkanInterface.initialized);
660
661 if (!sVulkanInterface.initialized) {
662 return;
663 }
664
665 StringAppendF(&result, "\n Instance extensions:\n");
666 for (const auto& name : sVulkanInterface.instanceExtensionNames) {
667 StringAppendF(&result, "\n %s\n", name.c_str());
668 }
669
670 StringAppendF(&result, "\n Device extensions:\n");
671 for (const auto& name : sVulkanInterface.deviceExtensionNames) {
672 StringAppendF(&result, "\n %s\n", name.c_str());
673 }
674}
675
676} // namespace skia
677} // namespace renderengine
678} // namespace android