blob: 8821c0e97dfd692684bde7db583242460ba7e95e [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>
Kevin Lubick2fc49112023-10-13 13:10:48 +000028#include <include/gpu/ganesh/vk/GrVkDirectContext.h>
Ian Elliott1f0911e2022-09-09 16:31:47 -060029
30#include <android-base/stringprintf.h>
31#include <gui/TraceUtils.h>
32#include <sync/sync.h>
33#include <utils/Trace.h>
34
35#include <cstdint>
36#include <memory>
37#include <vector>
38
39#include <vulkan/vulkan.h>
40#include "log/log_main.h"
41
42namespace android {
43namespace renderengine {
44
45struct VulkanFuncs {
46 PFN_vkCreateSemaphore vkCreateSemaphore = nullptr;
47 PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr;
48 PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR = nullptr;
49 PFN_vkDestroySemaphore vkDestroySemaphore = nullptr;
50
51 PFN_vkDeviceWaitIdle vkDeviceWaitIdle = nullptr;
52 PFN_vkDestroyDevice vkDestroyDevice = nullptr;
53 PFN_vkDestroyInstance vkDestroyInstance = nullptr;
54};
55
Ian Elliott98e87162023-04-14 14:05:19 -060056// Ref-Count a semaphore
57struct DestroySemaphoreInfo {
58 VkSemaphore mSemaphore;
59 // We need to make sure we don't delete the VkSemaphore until it is done being used by both Skia
60 // (including by the GPU) and inside SkiaVkRenderEngine. So we always start with two refs, one
61 // owned by Skia and one owned by the SkiaVkRenderEngine. The refs are decremented each time
62 // delete_semaphore* is called with this object. Skia will call destroy_semaphore* once it is
63 // done with the semaphore and the GPU has finished work on the semaphore. SkiaVkRenderEngine
64 // calls delete_semaphore* after sending the semaphore to Skia and exporting it if need be.
65 int mRefs = 2;
66
67 DestroySemaphoreInfo(VkSemaphore semaphore) : mSemaphore(semaphore) {}
68};
69
Ian Elliott1f0911e2022-09-09 16:31:47 -060070struct VulkanInterface {
71 bool initialized = false;
72 VkInstance instance;
73 VkPhysicalDevice physicalDevice;
74 VkDevice device;
75 VkQueue queue;
76 int queueIndex;
77 uint32_t apiVersion;
78 GrVkExtensions grExtensions;
79 VkPhysicalDeviceFeatures2* physicalDeviceFeatures2 = nullptr;
80 VkPhysicalDeviceSamplerYcbcrConversionFeatures* samplerYcbcrConversionFeatures = nullptr;
Ian Elliottae0b8d12023-01-05 19:13:42 -070081 VkPhysicalDeviceProtectedMemoryFeatures* protectedMemoryFeatures = nullptr;
Ian Elliott1f0911e2022-09-09 16:31:47 -060082 GrVkGetProc grGetProc;
83 bool isProtected;
84 bool isRealtimePriority;
85
86 VulkanFuncs funcs;
87
88 std::vector<std::string> instanceExtensionNames;
89 std::vector<std::string> deviceExtensionNames;
90
91 GrVkBackendContext getBackendContext() {
92 GrVkBackendContext backendContext;
93 backendContext.fInstance = instance;
94 backendContext.fPhysicalDevice = physicalDevice;
95 backendContext.fDevice = device;
96 backendContext.fQueue = queue;
97 backendContext.fGraphicsQueueIndex = queueIndex;
98 backendContext.fMaxAPIVersion = apiVersion;
99 backendContext.fVkExtensions = &grExtensions;
100 backendContext.fDeviceFeatures2 = physicalDeviceFeatures2;
101 backendContext.fGetProc = grGetProc;
102 backendContext.fProtectedContext = isProtected ? GrProtected::kYes : GrProtected::kNo;
103 return backendContext;
104 };
105
106 VkSemaphore createExportableSemaphore() {
107 VkExportSemaphoreCreateInfo exportInfo;
108 exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
109 exportInfo.pNext = nullptr;
110 exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
111
112 VkSemaphoreCreateInfo semaphoreInfo;
113 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
114 semaphoreInfo.pNext = &exportInfo;
115 semaphoreInfo.flags = 0;
116
117 VkSemaphore semaphore;
118 VkResult err = funcs.vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore);
119 if (VK_SUCCESS != err) {
120 ALOGE("%s: failed to create semaphore. err %d\n", __func__, err);
121 return VK_NULL_HANDLE;
122 }
123
124 return semaphore;
125 }
126
127 // syncFd cannot be <= 0
128 VkSemaphore importSemaphoreFromSyncFd(int syncFd) {
129 VkSemaphoreCreateInfo semaphoreInfo;
130 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
131 semaphoreInfo.pNext = nullptr;
132 semaphoreInfo.flags = 0;
133
134 VkSemaphore semaphore;
135 VkResult err = funcs.vkCreateSemaphore(device, &semaphoreInfo, nullptr, &semaphore);
136 if (VK_SUCCESS != err) {
137 ALOGE("%s: failed to create import semaphore", __func__);
138 return VK_NULL_HANDLE;
139 }
140
141 VkImportSemaphoreFdInfoKHR importInfo;
142 importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
143 importInfo.pNext = nullptr;
144 importInfo.semaphore = semaphore;
145 importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
146 importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
147 importInfo.fd = syncFd;
148
149 err = funcs.vkImportSemaphoreFdKHR(device, &importInfo);
150 if (VK_SUCCESS != err) {
151 funcs.vkDestroySemaphore(device, semaphore, nullptr);
152 ALOGE("%s: failed to import semaphore", __func__);
153 return VK_NULL_HANDLE;
154 }
155
156 return semaphore;
157 }
158
159 int exportSemaphoreSyncFd(VkSemaphore semaphore) {
160 int res;
161
162 VkSemaphoreGetFdInfoKHR getFdInfo;
163 getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
164 getFdInfo.pNext = nullptr;
165 getFdInfo.semaphore = semaphore;
166 getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
167
168 VkResult err = funcs.vkGetSemaphoreFdKHR(device, &getFdInfo, &res);
169 if (VK_SUCCESS != err) {
170 ALOGE("%s: failed to export semaphore, err: %d", __func__, err);
171 return -1;
172 }
173 return res;
174 }
175
176 void destroySemaphore(VkSemaphore semaphore) {
177 funcs.vkDestroySemaphore(device, semaphore, nullptr);
178 }
179};
180
181static GrVkGetProc sGetProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
182 if (device != VK_NULL_HANDLE) {
183 return vkGetDeviceProcAddr(device, proc_name);
184 }
185 return vkGetInstanceProcAddr(instance, proc_name);
186};
187
188#define BAIL(fmt, ...) \
189 { \
190 ALOGE("%s: " fmt ", bailing", __func__, ##__VA_ARGS__); \
191 return interface; \
192 }
193
194#define CHECK_NONNULL(expr) \
195 if ((expr) == nullptr) { \
196 BAIL("[%s] null", #expr); \
197 }
198
199#define VK_CHECK(expr) \
200 if ((expr) != VK_SUCCESS) { \
201 BAIL("[%s] failed. err = %d", #expr, expr); \
202 return interface; \
203 }
204
205#define VK_GET_PROC(F) \
206 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F); \
207 CHECK_NONNULL(vk##F)
208#define VK_GET_INST_PROC(instance, F) \
209 PFN_vk##F vk##F = (PFN_vk##F)vkGetInstanceProcAddr(instance, "vk" #F); \
210 CHECK_NONNULL(vk##F)
211#define VK_GET_DEV_PROC(device, F) \
212 PFN_vk##F vk##F = (PFN_vk##F)vkGetDeviceProcAddr(device, "vk" #F); \
213 CHECK_NONNULL(vk##F)
214
215VulkanInterface initVulkanInterface(bool protectedContent = false) {
216 VulkanInterface interface;
217
218 VK_GET_PROC(EnumerateInstanceVersion);
219 uint32_t instanceVersion;
220 VK_CHECK(vkEnumerateInstanceVersion(&instanceVersion));
221
222 if (instanceVersion < VK_MAKE_VERSION(1, 1, 0)) {
223 return interface;
224 }
225
226 const VkApplicationInfo appInfo = {
227 VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "surfaceflinger", 0, "android platform", 0,
228 VK_MAKE_VERSION(1, 1, 0),
229 };
230
231 VK_GET_PROC(EnumerateInstanceExtensionProperties);
232
233 uint32_t extensionCount = 0;
234 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr));
235 std::vector<VkExtensionProperties> instanceExtensions(extensionCount);
236 VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
237 instanceExtensions.data()));
238 std::vector<const char*> enabledInstanceExtensionNames;
239 enabledInstanceExtensionNames.reserve(instanceExtensions.size());
240 interface.instanceExtensionNames.reserve(instanceExtensions.size());
241 for (const auto& instExt : instanceExtensions) {
242 enabledInstanceExtensionNames.push_back(instExt.extensionName);
243 interface.instanceExtensionNames.push_back(instExt.extensionName);
244 }
245
246 const VkInstanceCreateInfo instanceCreateInfo = {
247 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
248 nullptr,
249 0,
250 &appInfo,
251 0,
252 nullptr,
253 (uint32_t)enabledInstanceExtensionNames.size(),
254 enabledInstanceExtensionNames.data(),
255 };
256
257 VK_GET_PROC(CreateInstance);
258 VkInstance instance;
259 VK_CHECK(vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
260
261 VK_GET_INST_PROC(instance, DestroyInstance);
262 interface.funcs.vkDestroyInstance = vkDestroyInstance;
263 VK_GET_INST_PROC(instance, EnumeratePhysicalDevices);
264 VK_GET_INST_PROC(instance, EnumerateDeviceExtensionProperties);
265 VK_GET_INST_PROC(instance, GetPhysicalDeviceProperties2);
266 VK_GET_INST_PROC(instance, GetPhysicalDeviceExternalSemaphoreProperties);
Ian Elliottd50658f2023-06-28 11:08:35 -0600267 VK_GET_INST_PROC(instance, GetPhysicalDeviceQueueFamilyProperties2);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600268 VK_GET_INST_PROC(instance, GetPhysicalDeviceFeatures2);
269 VK_GET_INST_PROC(instance, CreateDevice);
270
271 uint32_t physdevCount;
272 VK_CHECK(vkEnumeratePhysicalDevices(instance, &physdevCount, nullptr));
273 if (physdevCount == 0) {
274 BAIL("Could not find any physical devices");
275 }
276
277 physdevCount = 1;
278 VkPhysicalDevice physicalDevice;
279 VkResult enumeratePhysDevsErr =
280 vkEnumeratePhysicalDevices(instance, &physdevCount, &physicalDevice);
281 if (enumeratePhysDevsErr != VK_SUCCESS && VK_INCOMPLETE != enumeratePhysDevsErr) {
282 BAIL("vkEnumeratePhysicalDevices failed with non-VK_INCOMPLETE error: %d",
283 enumeratePhysDevsErr);
284 }
285
286 VkPhysicalDeviceProperties2 physDevProps = {
287 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
288 0,
289 {},
290 };
291 VkPhysicalDeviceProtectedMemoryProperties protMemProps = {
292 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
293 0,
294 {},
295 };
296
297 if (protectedContent) {
298 physDevProps.pNext = &protMemProps;
299 }
300
301 vkGetPhysicalDeviceProperties2(physicalDevice, &physDevProps);
302 if (physDevProps.properties.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
303 BAIL("Could not find a Vulkan 1.1+ physical device");
304 }
305
306 // Check for syncfd support. Bail if we cannot both import and export them.
307 VkPhysicalDeviceExternalSemaphoreInfo semInfo = {
308 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
309 nullptr,
310 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
311 };
312 VkExternalSemaphoreProperties semProps = {
313 VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, nullptr, 0, 0, 0,
314 };
315 vkGetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &semInfo, &semProps);
316
317 bool sufficientSemaphoreSyncFdSupport = (semProps.exportFromImportedHandleTypes &
318 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
319 (semProps.compatibleHandleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) &&
320 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) &&
321 (semProps.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
322
323 if (!sufficientSemaphoreSyncFdSupport) {
324 BAIL("Vulkan device does not support sufficient external semaphore sync fd features. "
325 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
326 "compatibleHandleTypes 0x%x (needed 0x%x) "
327 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
328 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
329 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
330 semProps.externalSemaphoreFeatures,
331 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
332 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
333 } else {
334 ALOGD("Vulkan device supports sufficient external semaphore sync fd features. "
335 "exportFromImportedHandleTypes 0x%x (needed 0x%x) "
336 "compatibleHandleTypes 0x%x (needed 0x%x) "
337 "externalSemaphoreFeatures 0x%x (needed 0x%x) ",
338 semProps.exportFromImportedHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
339 semProps.compatibleHandleTypes, VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
340 semProps.externalSemaphoreFeatures,
341 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
342 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT);
343 }
344
345 uint32_t queueCount;
Ian Elliottd50658f2023-06-28 11:08:35 -0600346 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, nullptr);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600347 if (queueCount == 0) {
348 BAIL("Could not find queues for physical device");
349 }
350
Ian Elliottd50658f2023-06-28 11:08:35 -0600351 std::vector<VkQueueFamilyProperties2> queueProps(queueCount);
352 std::vector<VkQueueFamilyGlobalPriorityPropertiesEXT> queuePriorityProps(queueCount);
353 VkQueueGlobalPriorityKHR queuePriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
354 // Even though we don't yet know if the VK_EXT_global_priority extension is available,
355 // we can safely add the request to the pNext chain, and if the extension is not
356 // available, it will be ignored.
357 for (uint32_t i = 0; i < queueCount; ++i) {
358 queuePriorityProps[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT;
359 queuePriorityProps[i].pNext = nullptr;
360 queueProps[i].pNext = &queuePriorityProps[i];
361 }
362 vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueCount, queueProps.data());
Ian Elliott1f0911e2022-09-09 16:31:47 -0600363
364 int graphicsQueueIndex = -1;
365 for (uint32_t i = 0; i < queueCount; ++i) {
Ian Elliottd50658f2023-06-28 11:08:35 -0600366 // Look at potential answers to the VK_EXT_global_priority query. If answers were
367 // provided, we may adjust the queuePriority.
368 if (queueProps[i].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
369 for (uint32_t j = 0; j < queuePriorityProps[i].priorityCount; j++) {
370 if (queuePriorityProps[i].priorities[j] > queuePriority) {
371 queuePriority = queuePriorityProps[i].priorities[j];
372 }
373 }
374 if (queuePriority == VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR) {
375 interface.isRealtimePriority = true;
376 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600377 graphicsQueueIndex = i;
378 break;
379 }
380 }
381
382 if (graphicsQueueIndex == -1) {
383 BAIL("Could not find a graphics queue family");
384 }
385
386 uint32_t deviceExtensionCount;
387 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
388 nullptr));
389 std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
390 VK_CHECK(vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtensionCount,
391 deviceExtensions.data()));
392
393 std::vector<const char*> enabledDeviceExtensionNames;
394 enabledDeviceExtensionNames.reserve(deviceExtensions.size());
395 interface.deviceExtensionNames.reserve(deviceExtensions.size());
396 for (const auto& devExt : deviceExtensions) {
397 enabledDeviceExtensionNames.push_back(devExt.extensionName);
398 interface.deviceExtensionNames.push_back(devExt.extensionName);
399 }
400
401 interface.grExtensions.init(sGetProc, instance, physicalDevice,
402 enabledInstanceExtensionNames.size(),
403 enabledInstanceExtensionNames.data(),
404 enabledDeviceExtensionNames.size(),
405 enabledDeviceExtensionNames.data());
406
407 if (!interface.grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
408 BAIL("Vulkan driver doesn't support external semaphore fd");
409 }
410
411 interface.physicalDeviceFeatures2 = new VkPhysicalDeviceFeatures2;
412 interface.physicalDeviceFeatures2->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
413 interface.physicalDeviceFeatures2->pNext = nullptr;
414
415 interface.samplerYcbcrConversionFeatures = new VkPhysicalDeviceSamplerYcbcrConversionFeatures;
416 interface.samplerYcbcrConversionFeatures->sType =
417 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
418 interface.samplerYcbcrConversionFeatures->pNext = nullptr;
419
420 interface.physicalDeviceFeatures2->pNext = interface.samplerYcbcrConversionFeatures;
421 void** tailPnext = &interface.samplerYcbcrConversionFeatures->pNext;
422
423 if (protectedContent) {
Ian Elliottae0b8d12023-01-05 19:13:42 -0700424 interface.protectedMemoryFeatures = new VkPhysicalDeviceProtectedMemoryFeatures;
Ian Elliott1f0911e2022-09-09 16:31:47 -0600425 interface.protectedMemoryFeatures->sType =
426 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
427 interface.protectedMemoryFeatures->pNext = nullptr;
428 *tailPnext = interface.protectedMemoryFeatures;
429 tailPnext = &interface.protectedMemoryFeatures->pNext;
430 }
431
432 vkGetPhysicalDeviceFeatures2(physicalDevice, interface.physicalDeviceFeatures2);
433 // Looks like this would slow things down and we can't depend on it on all platforms
434 interface.physicalDeviceFeatures2->features.robustBufferAccess = VK_FALSE;
435
436 float queuePriorities[1] = {0.0f};
437 void* queueNextPtr = nullptr;
438
439 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo = {
440 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
441 nullptr,
442 // If queue priority is supported, RE should always have realtime priority.
Ian Elliottd50658f2023-06-28 11:08:35 -0600443 queuePriority,
Ian Elliott1f0911e2022-09-09 16:31:47 -0600444 };
445
446 if (interface.grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
447 queueNextPtr = &queuePriorityCreateInfo;
Ian Elliott1f0911e2022-09-09 16:31:47 -0600448 }
449
450 VkDeviceQueueCreateFlags deviceQueueCreateFlags =
451 (VkDeviceQueueCreateFlags)(protectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0);
452
453 const VkDeviceQueueCreateInfo queueInfo = {
454 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
455 queueNextPtr,
456 deviceQueueCreateFlags,
457 (uint32_t)graphicsQueueIndex,
458 1,
459 queuePriorities,
460 };
461
462 const VkDeviceCreateInfo deviceInfo = {
463 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
464 interface.physicalDeviceFeatures2,
465 0,
466 1,
467 &queueInfo,
468 0,
469 nullptr,
470 (uint32_t)enabledDeviceExtensionNames.size(),
471 enabledDeviceExtensionNames.data(),
472 nullptr,
473 };
474
475 ALOGD("Trying to create Vk device with protectedContent=%d", protectedContent);
476 VkDevice device;
477 VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device));
478 ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
479
480 VkQueue graphicsQueue;
Ian Elliott87e3dd82023-02-27 12:07:10 -0700481 VK_GET_DEV_PROC(device, GetDeviceQueue2);
482 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
483 deviceQueueCreateFlags,
484 (uint32_t)graphicsQueueIndex, 0};
485 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600486
487 VK_GET_DEV_PROC(device, DeviceWaitIdle);
488 VK_GET_DEV_PROC(device, DestroyDevice);
489 interface.funcs.vkDeviceWaitIdle = vkDeviceWaitIdle;
490 interface.funcs.vkDestroyDevice = vkDestroyDevice;
491
492 VK_GET_DEV_PROC(device, CreateSemaphore);
493 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
494 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
495 VK_GET_DEV_PROC(device, DestroySemaphore);
496 interface.funcs.vkCreateSemaphore = vkCreateSemaphore;
497 interface.funcs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
498 interface.funcs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
499 interface.funcs.vkDestroySemaphore = vkDestroySemaphore;
500
501 // At this point, everything's succeeded and we can continue
502 interface.initialized = true;
503 interface.instance = instance;
504 interface.physicalDevice = physicalDevice;
505 interface.device = device;
506 interface.queue = graphicsQueue;
507 interface.queueIndex = graphicsQueueIndex;
508 interface.apiVersion = physDevProps.properties.apiVersion;
509 // grExtensions already constructed
510 // feature pointers already constructed
511 interface.grGetProc = sGetProc;
512 interface.isProtected = protectedContent;
513 // funcs already initialized
514
515 ALOGD("%s: Success init Vulkan interface", __func__);
516 return interface;
517}
518
519void teardownVulkanInterface(VulkanInterface* interface) {
520 interface->initialized = false;
521
522 if (interface->device != VK_NULL_HANDLE) {
523 interface->funcs.vkDeviceWaitIdle(interface->device);
524 interface->funcs.vkDestroyDevice(interface->device, nullptr);
525 interface->device = VK_NULL_HANDLE;
526 }
527 if (interface->instance != VK_NULL_HANDLE) {
528 interface->funcs.vkDestroyInstance(interface->instance, nullptr);
529 interface->instance = VK_NULL_HANDLE;
530 }
531
532 if (interface->protectedMemoryFeatures) {
533 delete interface->protectedMemoryFeatures;
534 }
535
536 if (interface->samplerYcbcrConversionFeatures) {
537 delete interface->samplerYcbcrConversionFeatures;
538 }
539
540 if (interface->physicalDeviceFeatures2) {
541 delete interface->physicalDeviceFeatures2;
542 }
543
544 interface->samplerYcbcrConversionFeatures = nullptr;
545 interface->physicalDeviceFeatures2 = nullptr;
546 interface->protectedMemoryFeatures = nullptr;
547}
548
549static VulkanInterface sVulkanInterface;
550static VulkanInterface sProtectedContentVulkanInterface;
551
552static void sSetupVulkanInterface() {
553 if (!sVulkanInterface.initialized) {
554 sVulkanInterface = initVulkanInterface(false /* no protected content */);
555 // We will have to abort if non-protected VkDevice creation fails (then nothing works).
556 LOG_ALWAYS_FATAL_IF(!sVulkanInterface.initialized,
557 "Could not initialize Vulkan RenderEngine!");
558 }
559 if (!sProtectedContentVulkanInterface.initialized) {
560 sProtectedContentVulkanInterface = initVulkanInterface(true /* protected content */);
561 if (!sProtectedContentVulkanInterface.initialized) {
562 ALOGE("Could not initialize protected content Vulkan RenderEngine.");
563 }
564 }
565}
566
567namespace skia {
568
569using base::StringAppendF;
570
571bool SkiaVkRenderEngine::canSupportSkiaVkRenderEngine() {
572 VulkanInterface temp = initVulkanInterface(false /* no protected content */);
573 ALOGD("SkiaVkRenderEngine::canSupportSkiaVkRenderEngine(): initialized == %s.",
574 temp.initialized ? "true" : "false");
575 return temp.initialized;
576}
577
578std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
579 const RenderEngineCreationArgs& args) {
580 std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
581 engine->ensureGrContextsCreated();
582
583 if (sVulkanInterface.initialized) {
584 ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__);
585 return engine;
586 } else {
587 ALOGD("SkiaVkRenderEngine::%s: could not create SkiaVkRenderEngine. "
588 "Likely insufficient Vulkan support",
589 __func__);
590 return {};
591 }
592}
593
594SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
595 : SkiaRenderEngine(args.renderEngineType, static_cast<PixelFormat>(args.pixelFormat),
Alec Mouri47bcb072023-08-15 02:02:49 +0000596 args.supportsBackgroundBlur) {}
Ian Elliott1f0911e2022-09-09 16:31:47 -0600597
598SkiaVkRenderEngine::~SkiaVkRenderEngine() {
599 finishRenderingAndAbandonContext();
600}
601
602SkiaRenderEngine::Contexts SkiaVkRenderEngine::createDirectContexts(
603 const GrContextOptions& options) {
604 sSetupVulkanInterface();
605
606 SkiaRenderEngine::Contexts contexts;
Kevin Lubick2fc49112023-10-13 13:10:48 +0000607 contexts.first = GrDirectContexts::MakeVulkan(sVulkanInterface.getBackendContext(), options);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600608 if (supportsProtectedContentImpl()) {
609 contexts.second =
Kevin Lubick2fc49112023-10-13 13:10:48 +0000610 GrDirectContexts::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
611 options);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600612 }
613
614 return contexts;
615}
616
617bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
618 return sProtectedContentVulkanInterface.initialized;
619}
620
621bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
622 return true;
623}
624
Ian Elliott98e87162023-04-14 14:05:19 -0600625static void delete_semaphore(void* semaphore) {
626 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
627 --info->mRefs;
628 if (!info->mRefs) {
629 sVulkanInterface.destroySemaphore(info->mSemaphore);
630 delete info;
631 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600632}
633
Ian Elliott98e87162023-04-14 14:05:19 -0600634static void delete_semaphore_protected(void* semaphore) {
635 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
636 --info->mRefs;
637 if (!info->mRefs) {
638 sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore);
639 delete info;
640 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600641}
642
643static VulkanInterface& getVulkanInterface(bool protectedContext) {
644 if (protectedContext) {
645 return sProtectedContentVulkanInterface;
646 }
647 return sVulkanInterface;
648}
649
650void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) {
651 if (fenceFd.get() < 0) return;
652
653 int dupedFd = dup(fenceFd.get());
654 if (dupedFd < 0) {
655 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
656 sync_wait(fenceFd.get(), -1);
657 return;
658 }
659
660 base::unique_fd fenceDup(dupedFd);
661 VkSemaphore waitSemaphore =
662 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
663 GrBackendSemaphore beSemaphore;
664 beSemaphore.initVulkan(waitSemaphore);
665 grContext->wait(1, &beSemaphore, true /* delete after wait */);
666}
667
668base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
Ian Elliott98e87162023-04-14 14:05:19 -0600669 VulkanInterface& vi = getVulkanInterface(isProtected());
670 VkSemaphore semaphore = vi.createExportableSemaphore();
671
672 GrBackendSemaphore backendSemaphore;
673 backendSemaphore.initVulkan(semaphore);
674
Ian Elliott1f0911e2022-09-09 16:31:47 -0600675 GrFlushInfo flushInfo;
Ian Elliott98e87162023-04-14 14:05:19 -0600676 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
677 if (semaphore != VK_NULL_HANDLE) {
678 destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore);
679 flushInfo.fNumSemaphores = 1;
680 flushInfo.fSignalSemaphores = &backendSemaphore;
681 flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
682 flushInfo.fFinishedContext = destroySemaphoreInfo;
683 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600684 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
Kevin Lubicka0efc342023-09-20 13:11:52 +0000685 grContext->submit(GrSyncCpu::kNo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600686 int drawFenceFd = -1;
Ian Elliott98e87162023-04-14 14:05:19 -0600687 if (semaphore != VK_NULL_HANDLE) {
688 if (GrSemaphoresSubmitted::kYes == submitted) {
689 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
690 }
691 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
692 flushInfo.fFinishedProc(destroySemaphoreInfo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600693 }
694 base::unique_fd res(drawFenceFd);
695 return res;
696}
697
698int SkiaVkRenderEngine::getContextPriority() {
699 // EGL_CONTEXT_PRIORITY_REALTIME_NV
700 constexpr int kRealtimePriority = 0x3357;
701 if (getVulkanInterface(isProtected()).isRealtimePriority) {
702 return kRealtimePriority;
703 } else {
704 return 0;
705 }
706}
707
708void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
709 StringAppendF(&result, "\n ------------RE Vulkan----------\n");
710 StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.initialized);
711 StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
712 sProtectedContentVulkanInterface.initialized);
713
714 if (!sVulkanInterface.initialized) {
715 return;
716 }
717
718 StringAppendF(&result, "\n Instance extensions:\n");
719 for (const auto& name : sVulkanInterface.instanceExtensionNames) {
720 StringAppendF(&result, "\n %s\n", name.c_str());
721 }
722
723 StringAppendF(&result, "\n Device extensions:\n");
724 for (const auto& name : sVulkanInterface.deviceExtensionNames) {
725 StringAppendF(&result, "\n %s\n", name.c_str());
726 }
727}
728
729} // namespace skia
730} // namespace renderengine
731} // namespace android