1 /*
2  * Copyright (C) 2016 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 #include "VulkanManager.h"
18 
19 #include <android/sync.h>
20 #include <gui/Surface.h>
21 
22 #include "Properties.h"
23 #include "RenderThread.h"
24 #include "renderstate/RenderState.h"
25 #include "utils/FatVector.h"
26 #include "utils/TraceUtils.h"
27 
28 #include <GrBackendSemaphore.h>
29 #include <GrBackendSurface.h>
30 #include <GrContext.h>
31 #include <GrTypes.h>
32 #include <vk/GrVkExtensions.h>
33 #include <vk/GrVkTypes.h>
34 
35 namespace android {
36 namespace uirenderer {
37 namespace renderthread {
38 
free_features_extensions_structs(const VkPhysicalDeviceFeatures2 & features)39 static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) {
40     // All Vulkan structs that could be part of the features chain will start with the
41     // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
42     // so we can get access to the pNext for the next struct.
43     struct CommonVulkanHeader {
44         VkStructureType sType;
45         void* pNext;
46     };
47 
48     void* pNext = features.pNext;
49     while (pNext) {
50         void* current = pNext;
51         pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
52         free(current);
53     }
54 }
55 
56 #define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F)
57 #define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
58 #define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
59 
destroy()60 void VulkanManager::destroy() {
61     if (VK_NULL_HANDLE != mCommandPool) {
62         mDestroyCommandPool(mDevice, mCommandPool, nullptr);
63         mCommandPool = VK_NULL_HANDLE;
64     }
65 
66     if (mDevice != VK_NULL_HANDLE) {
67         mDeviceWaitIdle(mDevice);
68         mDestroyDevice(mDevice, nullptr);
69     }
70 
71     if (mInstance != VK_NULL_HANDLE) {
72         mDestroyInstance(mInstance, nullptr);
73     }
74 
75     mGraphicsQueue = VK_NULL_HANDLE;
76     mPresentQueue = VK_NULL_HANDLE;
77     mDevice = VK_NULL_HANDLE;
78     mPhysicalDevice = VK_NULL_HANDLE;
79     mInstance = VK_NULL_HANDLE;
80     mInstanceExtensionsOwner.clear();
81     mInstanceExtensions.clear();
82     mDeviceExtensionsOwner.clear();
83     mDeviceExtensions.clear();
84     free_features_extensions_structs(mPhysicalDeviceFeatures2);
85     mPhysicalDeviceFeatures2 = {};
86 }
87 
setupDevice(GrVkExtensions & grExtensions,VkPhysicalDeviceFeatures2 & features)88 void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) {
89     VkResult err;
90 
91     constexpr VkApplicationInfo app_info = {
92             VK_STRUCTURE_TYPE_APPLICATION_INFO,  // sType
93             nullptr,                             // pNext
94             "android framework",                 // pApplicationName
95             0,                                   // applicationVersion
96             "android framework",                 // pEngineName
97             0,                                   // engineVerison
98             mAPIVersion,                         // apiVersion
99     };
100 
101     {
102         GET_PROC(EnumerateInstanceExtensionProperties);
103 
104         uint32_t extensionCount = 0;
105         err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
106         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
107         mInstanceExtensionsOwner.resize(extensionCount);
108         err = mEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
109                                                     mInstanceExtensionsOwner.data());
110         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
111         bool hasKHRSurfaceExtension = false;
112         bool hasKHRAndroidSurfaceExtension = false;
113         for (const VkExtensionProperties& extension : mInstanceExtensionsOwner) {
114             mInstanceExtensions.push_back(extension.extensionName);
115             if (!strcmp(extension.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
116                 hasKHRSurfaceExtension = true;
117             }
118             if (!strcmp(extension.extensionName, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
119                 hasKHRAndroidSurfaceExtension = true;
120             }
121         }
122         LOG_ALWAYS_FATAL_IF(!hasKHRSurfaceExtension || !hasKHRAndroidSurfaceExtension);
123     }
124 
125     const VkInstanceCreateInfo instance_create = {
126             VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,  // sType
127             nullptr,                                 // pNext
128             0,                                       // flags
129             &app_info,                               // pApplicationInfo
130             0,                                       // enabledLayerNameCount
131             nullptr,                                 // ppEnabledLayerNames
132             (uint32_t)mInstanceExtensions.size(),    // enabledExtensionNameCount
133             mInstanceExtensions.data(),              // ppEnabledExtensionNames
134     };
135 
136     GET_PROC(CreateInstance);
137     err = mCreateInstance(&instance_create, nullptr, &mInstance);
138     LOG_ALWAYS_FATAL_IF(err < 0);
139 
140     GET_INST_PROC(DestroyInstance);
141     GET_INST_PROC(EnumeratePhysicalDevices);
142     GET_INST_PROC(GetPhysicalDeviceProperties);
143     GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties);
144     GET_INST_PROC(GetPhysicalDeviceFeatures2);
145     GET_INST_PROC(GetPhysicalDeviceImageFormatProperties2);
146     GET_INST_PROC(CreateDevice);
147     GET_INST_PROC(EnumerateDeviceExtensionProperties);
148     GET_INST_PROC(CreateAndroidSurfaceKHR);
149     GET_INST_PROC(DestroySurfaceKHR);
150     GET_INST_PROC(GetPhysicalDeviceSurfaceSupportKHR);
151     GET_INST_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
152     GET_INST_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
153     GET_INST_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
154 
155     uint32_t gpuCount;
156     LOG_ALWAYS_FATAL_IF(mEnumeratePhysicalDevices(mInstance, &gpuCount, nullptr));
157     LOG_ALWAYS_FATAL_IF(!gpuCount);
158     // Just returning the first physical device instead of getting the whole array. Since there
159     // should only be one device on android.
160     gpuCount = 1;
161     err = mEnumeratePhysicalDevices(mInstance, &gpuCount, &mPhysicalDevice);
162     // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
163     LOG_ALWAYS_FATAL_IF(err && VK_INCOMPLETE != err);
164 
165     VkPhysicalDeviceProperties physDeviceProperties;
166     mGetPhysicalDeviceProperties(mPhysicalDevice, &physDeviceProperties);
167     LOG_ALWAYS_FATAL_IF(physDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0));
168     mDriverVersion = physDeviceProperties.driverVersion;
169 
170     // query to get the initial queue props size
171     uint32_t queueCount;
172     mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
173     LOG_ALWAYS_FATAL_IF(!queueCount);
174 
175     // now get the actual queue props
176     std::unique_ptr<VkQueueFamilyProperties[]> queueProps(new VkQueueFamilyProperties[queueCount]);
177     mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, queueProps.get());
178 
179     // iterate to find the graphics queue
180     mGraphicsQueueIndex = queueCount;
181     for (uint32_t i = 0; i < queueCount; i++) {
182         if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
183             mGraphicsQueueIndex = i;
184             break;
185         }
186     }
187     LOG_ALWAYS_FATAL_IF(mGraphicsQueueIndex == queueCount);
188 
189     // All physical devices and queue families on Android must be capable of
190     // presentation with any native window. So just use the first one.
191     mPresentQueueIndex = 0;
192 
193     {
194         uint32_t extensionCount = 0;
195         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
196                                                   nullptr);
197         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
198         mDeviceExtensionsOwner.resize(extensionCount);
199         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
200                                                   mDeviceExtensionsOwner.data());
201         LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err);
202         bool hasKHRSwapchainExtension = false;
203         for (const VkExtensionProperties& extension : mDeviceExtensionsOwner) {
204             mDeviceExtensions.push_back(extension.extensionName);
205             if (!strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
206                 hasKHRSwapchainExtension = true;
207             }
208         }
209         LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);
210     }
211 
212     auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
213         if (device != VK_NULL_HANDLE) {
214             return vkGetDeviceProcAddr(device, proc_name);
215         }
216         return vkGetInstanceProcAddr(instance, proc_name);
217     };
218 
219     grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
220                       mInstanceExtensions.data(), mDeviceExtensions.size(),
221                       mDeviceExtensions.data());
222 
223     LOG_ALWAYS_FATAL_IF(!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1));
224 
225     memset(&features, 0, sizeof(VkPhysicalDeviceFeatures2));
226     features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
227     features.pNext = nullptr;
228 
229     // Setup all extension feature structs we may want to use.
230     void** tailPNext = &features.pNext;
231 
232     if (grExtensions.hasExtension(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, 2)) {
233         VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT* blend;
234         blend = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)malloc(
235                 sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT));
236         LOG_ALWAYS_FATAL_IF(!blend);
237         blend->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT;
238         blend->pNext = nullptr;
239         *tailPNext = blend;
240         tailPNext = &blend->pNext;
241     }
242 
243     VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
244     ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*)malloc(
245             sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
246     LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
247     ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
248     ycbcrFeature->pNext = nullptr;
249     *tailPNext = ycbcrFeature;
250     tailPNext = &ycbcrFeature->pNext;
251 
252     // query to get the physical device features
253     mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
254     // this looks like it would slow things down,
255     // and we can't depend on it on all platforms
256     features.features.robustBufferAccess = VK_FALSE;
257 
258     float queuePriorities[1] = {0.0};
259 
260     void* queueNextPtr = nullptr;
261 
262     VkDeviceQueueGlobalPriorityCreateInfoEXT queuePriorityCreateInfo;
263 
264     if (Properties::contextPriority != 0 &&
265         grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) {
266         memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT));
267         queuePriorityCreateInfo.sType =
268                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT;
269         queuePriorityCreateInfo.pNext = nullptr;
270         switch (Properties::contextPriority) {
271             case EGL_CONTEXT_PRIORITY_LOW_IMG:
272                 queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT;
273                 break;
274             case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
275                 queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT;
276                 break;
277             case EGL_CONTEXT_PRIORITY_HIGH_IMG:
278                 queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT;
279                 break;
280             default:
281                 LOG_ALWAYS_FATAL("Unsupported context priority");
282         }
283         queueNextPtr = &queuePriorityCreateInfo;
284     }
285 
286     const VkDeviceQueueCreateInfo queueInfo[2] = {
287             {
288                     VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,  // sType
289                     queueNextPtr,                                // pNext
290                     0,                                           // VkDeviceQueueCreateFlags
291                     mGraphicsQueueIndex,                         // queueFamilyIndex
292                     1,                                           // queueCount
293                     queuePriorities,                             // pQueuePriorities
294             },
295             {
296                     VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,  // sType
297                     queueNextPtr,                                // pNext
298                     0,                                           // VkDeviceQueueCreateFlags
299                     mPresentQueueIndex,                          // queueFamilyIndex
300                     1,                                           // queueCount
301                     queuePriorities,                             // pQueuePriorities
302             }};
303     uint32_t queueInfoCount = (mPresentQueueIndex != mGraphicsQueueIndex) ? 2 : 1;
304 
305     const VkDeviceCreateInfo deviceInfo = {
306             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,  // sType
307             &features,                             // pNext
308             0,                                     // VkDeviceCreateFlags
309             queueInfoCount,                        // queueCreateInfoCount
310             queueInfo,                             // pQueueCreateInfos
311             0,                                     // layerCount
312             nullptr,                               // ppEnabledLayerNames
313             (uint32_t)mDeviceExtensions.size(),    // extensionCount
314             mDeviceExtensions.data(),              // ppEnabledExtensionNames
315             nullptr,                               // ppEnabledFeatures
316     };
317 
318     LOG_ALWAYS_FATAL_IF(mCreateDevice(mPhysicalDevice, &deviceInfo, nullptr, &mDevice));
319 
320     GET_DEV_PROC(GetDeviceQueue);
321     GET_DEV_PROC(DeviceWaitIdle);
322     GET_DEV_PROC(DestroyDevice);
323     GET_DEV_PROC(CreateCommandPool);
324     GET_DEV_PROC(DestroyCommandPool);
325     GET_DEV_PROC(AllocateCommandBuffers);
326     GET_DEV_PROC(FreeCommandBuffers);
327     GET_DEV_PROC(ResetCommandBuffer);
328     GET_DEV_PROC(BeginCommandBuffer);
329     GET_DEV_PROC(EndCommandBuffer);
330     GET_DEV_PROC(CmdPipelineBarrier);
331     GET_DEV_PROC(GetDeviceQueue);
332     GET_DEV_PROC(QueueSubmit);
333     GET_DEV_PROC(QueueWaitIdle);
334     GET_DEV_PROC(DeviceWaitIdle);
335     GET_DEV_PROC(CreateSemaphore);
336     GET_DEV_PROC(DestroySemaphore);
337     GET_DEV_PROC(ImportSemaphoreFdKHR);
338     GET_DEV_PROC(GetSemaphoreFdKHR);
339     GET_DEV_PROC(CreateFence);
340     GET_DEV_PROC(DestroyFence);
341     GET_DEV_PROC(WaitForFences);
342     GET_DEV_PROC(ResetFences);
343 }
344 
initialize()345 void VulkanManager::initialize() {
346     if (mDevice != VK_NULL_HANDLE) {
347         return;
348     }
349 
350     GET_PROC(EnumerateInstanceVersion);
351     uint32_t instanceVersion;
352     LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
353     LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
354 
355     this->setupDevice(mExtensions, mPhysicalDeviceFeatures2);
356 
357     mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
358 
359     // create the command pool for the command buffers
360     if (VK_NULL_HANDLE == mCommandPool) {
361         VkCommandPoolCreateInfo commandPoolInfo;
362         memset(&commandPoolInfo, 0, sizeof(VkCommandPoolCreateInfo));
363         commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
364         // this needs to be on the render queue
365         commandPoolInfo.queueFamilyIndex = mGraphicsQueueIndex;
366         commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
367         SkDEBUGCODE(VkResult res =)
368                 mCreateCommandPool(mDevice, &commandPoolInfo, nullptr, &mCommandPool);
369         SkASSERT(VK_SUCCESS == res);
370     }
371     LOG_ALWAYS_FATAL_IF(mCommandPool == VK_NULL_HANDLE);
372 
373     mGetDeviceQueue(mDevice, mPresentQueueIndex, 0, &mPresentQueue);
374 
375     if (Properties::enablePartialUpdates && Properties::useBufferAge) {
376         mSwapBehavior = SwapBehavior::BufferAge;
377     }
378 }
379 
createContext(const GrContextOptions & options)380 sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
381     auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
382         if (device != VK_NULL_HANDLE) {
383             return vkGetDeviceProcAddr(device, proc_name);
384         }
385         return vkGetInstanceProcAddr(instance, proc_name);
386     };
387 
388     GrVkBackendContext backendContext;
389     backendContext.fInstance = mInstance;
390     backendContext.fPhysicalDevice = mPhysicalDevice;
391     backendContext.fDevice = mDevice;
392     backendContext.fQueue = mGraphicsQueue;
393     backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
394     backendContext.fMaxAPIVersion = mAPIVersion;
395     backendContext.fVkExtensions = &mExtensions;
396     backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
397     backendContext.fGetProc = std::move(getProc);
398 
399     return GrContext::MakeVulkan(backendContext, options);
400 }
401 
getVkFunctorInitParams() const402 VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
403     return VkFunctorInitParams{
404             .instance = mInstance,
405             .physical_device = mPhysicalDevice,
406             .device = mDevice,
407             .queue = mGraphicsQueue,
408             .graphics_queue_index = mGraphicsQueueIndex,
409             .api_version = mAPIVersion,
410             .enabled_instance_extension_names = mInstanceExtensions.data(),
411             .enabled_instance_extension_names_length =
412                     static_cast<uint32_t>(mInstanceExtensions.size()),
413             .enabled_device_extension_names = mDeviceExtensions.data(),
414             .enabled_device_extension_names_length =
415                     static_cast<uint32_t>(mDeviceExtensions.size()),
416             .device_features_2 = &mPhysicalDeviceFeatures2,
417     };
418 }
419 
dequeueNextBuffer(VulkanSurface * surface)420 Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) {
421     VulkanSurface::NativeBufferInfo* bufferInfo = surface->dequeueNativeBuffer();
422 
423     if (bufferInfo == nullptr) {
424         ALOGE("VulkanSurface::dequeueNativeBuffer called with an invalid surface!");
425         return Frame(-1, -1, 0);
426     }
427 
428     LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued);
429 
430     if (bufferInfo->dequeue_fence != -1) {
431         struct sync_file_info* finfo = sync_file_info(bufferInfo->dequeue_fence);
432         bool isSignalPending = false;
433         if (finfo != NULL) {
434             isSignalPending = finfo->status != 1;
435             sync_file_info_free(finfo);
436         }
437         if (isSignalPending) {
438             int fence_clone = dup(bufferInfo->dequeue_fence);
439             if (fence_clone == -1) {
440                 ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno),
441                       errno);
442                 sync_wait(bufferInfo->dequeue_fence, -1 /* forever */);
443             } else {
444                 VkSemaphoreCreateInfo semaphoreInfo;
445                 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
446                 semaphoreInfo.pNext = nullptr;
447                 semaphoreInfo.flags = 0;
448                 VkSemaphore semaphore;
449                 VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
450                 LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d",
451                                     err);
452 
453                 VkImportSemaphoreFdInfoKHR importInfo;
454                 importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
455                 importInfo.pNext = nullptr;
456                 importInfo.semaphore = semaphore;
457                 importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
458                 importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
459                 importInfo.fd = fence_clone;
460 
461                 err = mImportSemaphoreFdKHR(mDevice, &importInfo);
462                 LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err);
463 
464                 GrBackendSemaphore backendSemaphore;
465                 backendSemaphore.initVulkan(semaphore);
466                 bufferInfo->skSurface->wait(1, &backendSemaphore);
467                 // The following flush blocks the GPU immediately instead of waiting for other
468                 // drawing ops. It seems dequeue_fence is not respected otherwise.
469                 // TODO: remove the flush after finding why backendSemaphore is not working.
470                 bufferInfo->skSurface->flush();
471             }
472         }
473     }
474 
475     int bufferAge = (mSwapBehavior == SwapBehavior::Discard) ? 0 : surface->getCurrentBuffersAge();
476     return Frame(surface->logicalWidth(), surface->logicalHeight(), bufferAge);
477 }
478 
479 struct DestroySemaphoreInfo {
480     PFN_vkDestroySemaphore mDestroyFunction;
481     VkDevice mDevice;
482     VkSemaphore mSemaphore;
483 
DestroySemaphoreInfoandroid::uirenderer::renderthread::DestroySemaphoreInfo484     DestroySemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device,
485             VkSemaphore semaphore)
486             : mDestroyFunction(destroyFunction), mDevice(device), mSemaphore(semaphore) {}
487 };
488 
destroy_semaphore(void * context)489 static void destroy_semaphore(void* context) {
490     DestroySemaphoreInfo* info = reinterpret_cast<DestroySemaphoreInfo*>(context);
491     info->mDestroyFunction(info->mDevice, info->mSemaphore, nullptr);
492     delete info;
493 }
494 
swapBuffers(VulkanSurface * surface,const SkRect & dirtyRect)495 void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
496     if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
497         ATRACE_NAME("Finishing GPU work");
498         mDeviceWaitIdle(mDevice);
499     }
500 
501     VulkanSurface::NativeBufferInfo* bufferInfo = surface->getCurrentBufferInfo();
502     if (!bufferInfo) {
503         // If VulkanSurface::dequeueNativeBuffer failed earlier, then swapBuffers is a no-op.
504         return;
505     }
506 
507     VkExportSemaphoreCreateInfo exportInfo;
508     exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
509     exportInfo.pNext = nullptr;
510     exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
511 
512     VkSemaphoreCreateInfo semaphoreInfo;
513     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
514     semaphoreInfo.pNext = &exportInfo;
515     semaphoreInfo.flags = 0;
516     VkSemaphore semaphore;
517     VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
518     ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to create semaphore");
519 
520     GrBackendSemaphore backendSemaphore;
521     backendSemaphore.initVulkan(semaphore);
522 
523     int fenceFd = -1;
524     DestroySemaphoreInfo* destroyInfo = new DestroySemaphoreInfo(mDestroySemaphore, mDevice,
525                                                                  semaphore);
526     GrSemaphoresSubmitted submitted =
527             bufferInfo->skSurface->flush(SkSurface::BackendSurfaceAccess::kPresent,
528                                          kNone_GrFlushFlags, 1, &backendSemaphore,
529                                          destroy_semaphore, destroyInfo);
530     if (submitted == GrSemaphoresSubmitted::kYes) {
531         VkSemaphoreGetFdInfoKHR getFdInfo;
532         getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
533         getFdInfo.pNext = nullptr;
534         getFdInfo.semaphore = semaphore;
535         getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
536 
537         err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
538         ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
539     } else {
540         ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
541         mQueueWaitIdle(mGraphicsQueue);
542     }
543 
544     surface->presentCurrentBuffer(dirtyRect, fenceFd);
545 }
546 
destroySurface(VulkanSurface * surface)547 void VulkanManager::destroySurface(VulkanSurface* surface) {
548     // Make sure all submit commands have finished before starting to destroy objects.
549     if (VK_NULL_HANDLE != mPresentQueue) {
550         mQueueWaitIdle(mPresentQueue);
551     }
552     mDeviceWaitIdle(mDevice);
553 
554     delete surface;
555 }
556 
createSurface(ANativeWindow * window,ColorMode colorMode,sk_sp<SkColorSpace> surfaceColorSpace,SkColorType surfaceColorType,GrContext * grContext,uint32_t extraBuffers)557 VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
558                                             sk_sp<SkColorSpace> surfaceColorSpace,
559                                             SkColorType surfaceColorType, GrContext* grContext,
560                                             uint32_t extraBuffers) {
561     LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
562     if (!window) {
563         return nullptr;
564     }
565 
566     return VulkanSurface::Create(window, colorMode, surfaceColorType, surfaceColorSpace, grContext,
567                                  *this, extraBuffers);
568 }
569 
fenceWait(sp<Fence> & fence,GrContext * grContext)570 status_t VulkanManager::fenceWait(sp<Fence>& fence, GrContext* grContext) {
571     if (!hasVkContext()) {
572         ALOGE("VulkanManager::fenceWait: VkDevice not initialized");
573         return INVALID_OPERATION;
574     }
575 
576     // Block GPU on the fence.
577     int fenceFd = fence->dup();
578     if (fenceFd == -1) {
579         ALOGE("VulkanManager::fenceWait: error dup'ing fence fd: %d", errno);
580         return -errno;
581     }
582 
583     VkSemaphoreCreateInfo semaphoreInfo;
584     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
585     semaphoreInfo.pNext = nullptr;
586     semaphoreInfo.flags = 0;
587     VkSemaphore semaphore;
588     VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
589     if (VK_SUCCESS != err) {
590         ALOGE("Failed to create import semaphore, err: %d", err);
591         return UNKNOWN_ERROR;
592     }
593     VkImportSemaphoreFdInfoKHR importInfo;
594     importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
595     importInfo.pNext = nullptr;
596     importInfo.semaphore = semaphore;
597     importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
598     importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
599     importInfo.fd = fenceFd;
600 
601     err = mImportSemaphoreFdKHR(mDevice, &importInfo);
602     if (VK_SUCCESS != err) {
603         mDestroySemaphore(mDevice, semaphore, nullptr);
604         ALOGE("Failed to import semaphore, err: %d", err);
605         return UNKNOWN_ERROR;
606     }
607 
608     GrBackendSemaphore beSemaphore;
609     beSemaphore.initVulkan(semaphore);
610 
611     // Skia takes ownership of the semaphore and will delete it once the wait has finished.
612     grContext->wait(1, &beSemaphore);
613     grContext->flush();
614 
615     return OK;
616 }
617 
createReleaseFence(sp<Fence> & nativeFence,GrContext * grContext)618 status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence, GrContext* grContext) {
619     if (!hasVkContext()) {
620         ALOGE("VulkanManager::createReleaseFence: VkDevice not initialized");
621         return INVALID_OPERATION;
622     }
623 
624     VkExportSemaphoreCreateInfo exportInfo;
625     exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
626     exportInfo.pNext = nullptr;
627     exportInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
628 
629     VkSemaphoreCreateInfo semaphoreInfo;
630     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
631     semaphoreInfo.pNext = &exportInfo;
632     semaphoreInfo.flags = 0;
633     VkSemaphore semaphore;
634     VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
635     if (VK_SUCCESS != err) {
636         ALOGE("VulkanManager::createReleaseFence: Failed to create semaphore");
637         return INVALID_OPERATION;
638     }
639 
640     GrBackendSemaphore backendSemaphore;
641     backendSemaphore.initVulkan(semaphore);
642 
643     DestroySemaphoreInfo* destroyInfo = new DestroySemaphoreInfo(mDestroySemaphore, mDevice,
644                                                                  semaphore);
645     GrSemaphoresSubmitted submitted =
646             grContext->flush(kNone_GrFlushFlags, 1, &backendSemaphore,
647                              destroy_semaphore, destroyInfo);
648 
649     if (submitted == GrSemaphoresSubmitted::kNo) {
650         ALOGE("VulkanManager::createReleaseFence: Failed to submit semaphore");
651         mDestroySemaphore(mDevice, semaphore, nullptr);
652         return INVALID_OPERATION;
653     }
654 
655     VkSemaphoreGetFdInfoKHR getFdInfo;
656     getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
657     getFdInfo.pNext = nullptr;
658     getFdInfo.semaphore = semaphore;
659     getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
660 
661     int fenceFd = 0;
662 
663     err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
664     if (VK_SUCCESS != err) {
665         ALOGE("VulkanManager::createReleaseFence: Failed to get semaphore Fd");
666         return INVALID_OPERATION;
667     }
668     nativeFence = new Fence(fenceFd);
669 
670     return OK;
671 }
672 
673 } /* namespace renderthread */
674 } /* namespace uirenderer */
675 } /* namespace android */
676