blob: 3af85c064e48b8a60cc3f1c336c65001fe481b85 [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
John Bauman1aab9922023-10-24 17:23:47 +0000436 if (protectedContent && !interface.protectedMemoryFeatures->protectedMemory) {
437 BAIL("Protected memory not supported");
438 }
439
Ian Elliott1f0911e2022-09-09 16:31:47 -0600440 float queuePriorities[1] = {0.0f};
441 void* queueNextPtr = nullptr;
442
443 VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo = {
444 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT,
445 nullptr,
446 // If queue priority is supported, RE should always have realtime priority.
Ian Elliottd50658f2023-06-28 11:08:35 -0600447 queuePriority,
Ian Elliott1f0911e2022-09-09 16:31:47 -0600448 };
449
450 if (interface.grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
451 queueNextPtr = &queuePriorityCreateInfo;
Ian Elliott1f0911e2022-09-09 16:31:47 -0600452 }
453
454 VkDeviceQueueCreateFlags deviceQueueCreateFlags =
455 (VkDeviceQueueCreateFlags)(protectedContent ? VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT : 0);
456
457 const VkDeviceQueueCreateInfo queueInfo = {
458 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
459 queueNextPtr,
460 deviceQueueCreateFlags,
461 (uint32_t)graphicsQueueIndex,
462 1,
463 queuePriorities,
464 };
465
466 const VkDeviceCreateInfo deviceInfo = {
467 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
468 interface.physicalDeviceFeatures2,
469 0,
470 1,
471 &queueInfo,
472 0,
473 nullptr,
474 (uint32_t)enabledDeviceExtensionNames.size(),
475 enabledDeviceExtensionNames.data(),
476 nullptr,
477 };
478
479 ALOGD("Trying to create Vk device with protectedContent=%d", protectedContent);
480 VkDevice device;
481 VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &device));
482 ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
483
484 VkQueue graphicsQueue;
Ian Elliott87e3dd82023-02-27 12:07:10 -0700485 VK_GET_DEV_PROC(device, GetDeviceQueue2);
486 const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
487 deviceQueueCreateFlags,
488 (uint32_t)graphicsQueueIndex, 0};
489 vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600490
491 VK_GET_DEV_PROC(device, DeviceWaitIdle);
492 VK_GET_DEV_PROC(device, DestroyDevice);
493 interface.funcs.vkDeviceWaitIdle = vkDeviceWaitIdle;
494 interface.funcs.vkDestroyDevice = vkDestroyDevice;
495
496 VK_GET_DEV_PROC(device, CreateSemaphore);
497 VK_GET_DEV_PROC(device, ImportSemaphoreFdKHR);
498 VK_GET_DEV_PROC(device, GetSemaphoreFdKHR);
499 VK_GET_DEV_PROC(device, DestroySemaphore);
500 interface.funcs.vkCreateSemaphore = vkCreateSemaphore;
501 interface.funcs.vkImportSemaphoreFdKHR = vkImportSemaphoreFdKHR;
502 interface.funcs.vkGetSemaphoreFdKHR = vkGetSemaphoreFdKHR;
503 interface.funcs.vkDestroySemaphore = vkDestroySemaphore;
504
505 // At this point, everything's succeeded and we can continue
506 interface.initialized = true;
507 interface.instance = instance;
508 interface.physicalDevice = physicalDevice;
509 interface.device = device;
510 interface.queue = graphicsQueue;
511 interface.queueIndex = graphicsQueueIndex;
512 interface.apiVersion = physDevProps.properties.apiVersion;
513 // grExtensions already constructed
514 // feature pointers already constructed
515 interface.grGetProc = sGetProc;
516 interface.isProtected = protectedContent;
517 // funcs already initialized
518
519 ALOGD("%s: Success init Vulkan interface", __func__);
520 return interface;
521}
522
523void teardownVulkanInterface(VulkanInterface* interface) {
524 interface->initialized = false;
525
526 if (interface->device != VK_NULL_HANDLE) {
527 interface->funcs.vkDeviceWaitIdle(interface->device);
528 interface->funcs.vkDestroyDevice(interface->device, nullptr);
529 interface->device = VK_NULL_HANDLE;
530 }
531 if (interface->instance != VK_NULL_HANDLE) {
532 interface->funcs.vkDestroyInstance(interface->instance, nullptr);
533 interface->instance = VK_NULL_HANDLE;
534 }
535
536 if (interface->protectedMemoryFeatures) {
537 delete interface->protectedMemoryFeatures;
538 }
539
540 if (interface->samplerYcbcrConversionFeatures) {
541 delete interface->samplerYcbcrConversionFeatures;
542 }
543
544 if (interface->physicalDeviceFeatures2) {
545 delete interface->physicalDeviceFeatures2;
546 }
547
548 interface->samplerYcbcrConversionFeatures = nullptr;
549 interface->physicalDeviceFeatures2 = nullptr;
550 interface->protectedMemoryFeatures = nullptr;
551}
552
553static VulkanInterface sVulkanInterface;
554static VulkanInterface sProtectedContentVulkanInterface;
555
556static void sSetupVulkanInterface() {
557 if (!sVulkanInterface.initialized) {
558 sVulkanInterface = initVulkanInterface(false /* no protected content */);
559 // We will have to abort if non-protected VkDevice creation fails (then nothing works).
560 LOG_ALWAYS_FATAL_IF(!sVulkanInterface.initialized,
561 "Could not initialize Vulkan RenderEngine!");
562 }
563 if (!sProtectedContentVulkanInterface.initialized) {
564 sProtectedContentVulkanInterface = initVulkanInterface(true /* protected content */);
565 if (!sProtectedContentVulkanInterface.initialized) {
566 ALOGE("Could not initialize protected content Vulkan RenderEngine.");
567 }
568 }
569}
570
571namespace skia {
572
573using base::StringAppendF;
574
575bool SkiaVkRenderEngine::canSupportSkiaVkRenderEngine() {
576 VulkanInterface temp = initVulkanInterface(false /* no protected content */);
577 ALOGD("SkiaVkRenderEngine::canSupportSkiaVkRenderEngine(): initialized == %s.",
578 temp.initialized ? "true" : "false");
579 return temp.initialized;
580}
581
582std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
583 const RenderEngineCreationArgs& args) {
584 std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
585 engine->ensureGrContextsCreated();
586
587 if (sVulkanInterface.initialized) {
588 ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__);
589 return engine;
590 } else {
591 ALOGD("SkiaVkRenderEngine::%s: could not create SkiaVkRenderEngine. "
592 "Likely insufficient Vulkan support",
593 __func__);
594 return {};
595 }
596}
597
598SkiaVkRenderEngine::SkiaVkRenderEngine(const RenderEngineCreationArgs& args)
Leon Scroggins III696bf932024-01-24 15:21:05 -0500599 : SkiaRenderEngine(args.threaded, static_cast<PixelFormat>(args.pixelFormat),
Alec Mouri47bcb072023-08-15 02:02:49 +0000600 args.supportsBackgroundBlur) {}
Ian Elliott1f0911e2022-09-09 16:31:47 -0600601
602SkiaVkRenderEngine::~SkiaVkRenderEngine() {
603 finishRenderingAndAbandonContext();
604}
605
606SkiaRenderEngine::Contexts SkiaVkRenderEngine::createDirectContexts(
607 const GrContextOptions& options) {
608 sSetupVulkanInterface();
609
610 SkiaRenderEngine::Contexts contexts;
Kevin Lubick2fc49112023-10-13 13:10:48 +0000611 contexts.first = GrDirectContexts::MakeVulkan(sVulkanInterface.getBackendContext(), options);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600612 if (supportsProtectedContentImpl()) {
613 contexts.second =
Kevin Lubick2fc49112023-10-13 13:10:48 +0000614 GrDirectContexts::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(),
615 options);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600616 }
617
618 return contexts;
619}
620
621bool SkiaVkRenderEngine::supportsProtectedContentImpl() const {
622 return sProtectedContentVulkanInterface.initialized;
623}
624
625bool SkiaVkRenderEngine::useProtectedContextImpl(GrProtected) {
626 return true;
627}
628
Ian Elliott98e87162023-04-14 14:05:19 -0600629static void delete_semaphore(void* semaphore) {
630 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
631 --info->mRefs;
632 if (!info->mRefs) {
633 sVulkanInterface.destroySemaphore(info->mSemaphore);
634 delete info;
635 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600636}
637
Ian Elliott98e87162023-04-14 14:05:19 -0600638static void delete_semaphore_protected(void* semaphore) {
639 DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(semaphore);
640 --info->mRefs;
641 if (!info->mRefs) {
642 sProtectedContentVulkanInterface.destroySemaphore(info->mSemaphore);
643 delete info;
644 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600645}
646
647static VulkanInterface& getVulkanInterface(bool protectedContext) {
648 if (protectedContext) {
649 return sProtectedContentVulkanInterface;
650 }
651 return sVulkanInterface;
652}
653
654void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) {
655 if (fenceFd.get() < 0) return;
656
657 int dupedFd = dup(fenceFd.get());
658 if (dupedFd < 0) {
659 ALOGE("failed to create duplicate fence fd: %d", dupedFd);
660 sync_wait(fenceFd.get(), -1);
661 return;
662 }
663
664 base::unique_fd fenceDup(dupedFd);
665 VkSemaphore waitSemaphore =
666 getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release());
667 GrBackendSemaphore beSemaphore;
668 beSemaphore.initVulkan(waitSemaphore);
669 grContext->wait(1, &beSemaphore, true /* delete after wait */);
670}
671
672base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) {
Ian Elliott98e87162023-04-14 14:05:19 -0600673 VulkanInterface& vi = getVulkanInterface(isProtected());
674 VkSemaphore semaphore = vi.createExportableSemaphore();
675
676 GrBackendSemaphore backendSemaphore;
677 backendSemaphore.initVulkan(semaphore);
678
Ian Elliott1f0911e2022-09-09 16:31:47 -0600679 GrFlushInfo flushInfo;
Ian Elliott98e87162023-04-14 14:05:19 -0600680 DestroySemaphoreInfo* destroySemaphoreInfo = nullptr;
681 if (semaphore != VK_NULL_HANDLE) {
682 destroySemaphoreInfo = new DestroySemaphoreInfo(semaphore);
683 flushInfo.fNumSemaphores = 1;
684 flushInfo.fSignalSemaphores = &backendSemaphore;
685 flushInfo.fFinishedProc = isProtected() ? delete_semaphore_protected : delete_semaphore;
686 flushInfo.fFinishedContext = destroySemaphoreInfo;
687 }
Ian Elliott1f0911e2022-09-09 16:31:47 -0600688 GrSemaphoresSubmitted submitted = grContext->flush(flushInfo);
Kevin Lubicka0efc342023-09-20 13:11:52 +0000689 grContext->submit(GrSyncCpu::kNo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600690 int drawFenceFd = -1;
Ian Elliott98e87162023-04-14 14:05:19 -0600691 if (semaphore != VK_NULL_HANDLE) {
692 if (GrSemaphoresSubmitted::kYes == submitted) {
693 drawFenceFd = vi.exportSemaphoreSyncFd(semaphore);
694 }
695 // Now that drawFenceFd has been created, we can delete our reference to this semaphore
696 flushInfo.fFinishedProc(destroySemaphoreInfo);
Ian Elliott1f0911e2022-09-09 16:31:47 -0600697 }
698 base::unique_fd res(drawFenceFd);
699 return res;
700}
701
702int SkiaVkRenderEngine::getContextPriority() {
703 // EGL_CONTEXT_PRIORITY_REALTIME_NV
704 constexpr int kRealtimePriority = 0x3357;
705 if (getVulkanInterface(isProtected()).isRealtimePriority) {
706 return kRealtimePriority;
707 } else {
708 return 0;
709 }
710}
711
712void SkiaVkRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
713 StringAppendF(&result, "\n ------------RE Vulkan----------\n");
714 StringAppendF(&result, "\n Vulkan device initialized: %d\n", sVulkanInterface.initialized);
715 StringAppendF(&result, "\n Vulkan protected device initialized: %d\n",
716 sProtectedContentVulkanInterface.initialized);
717
718 if (!sVulkanInterface.initialized) {
719 return;
720 }
721
722 StringAppendF(&result, "\n Instance extensions:\n");
723 for (const auto& name : sVulkanInterface.instanceExtensionNames) {
724 StringAppendF(&result, "\n %s\n", name.c_str());
725 }
726
727 StringAppendF(&result, "\n Device extensions:\n");
728 for (const auto& name : sVulkanInterface.deviceExtensionNames) {
729 StringAppendF(&result, "\n %s\n", name.c_str());
730 }
731}
732
733} // namespace skia
734} // namespace renderengine
735} // namespace android