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