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 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 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 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 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 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 402 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 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 484 DestroySemaphoreInfo(PFN_vkDestroySemaphore destroyFunction, VkDevice device, 485 VkSemaphore semaphore) 486 : mDestroyFunction(destroyFunction), mDevice(device), mSemaphore(semaphore) {} 487 }; 488 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 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 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 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 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 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