From 3e99fa7a272efe3a1c70fd96cb6444f75790811e Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Thu, 21 Mar 2019 11:20:29 -0400 Subject: Block GPU on release fence from dequeueBuffer earlier If dequeueBuffer fence has not fired yet, then submit to the queue and block GPU on VkSemaphore immediatelly. It is not clear why this CL makes a difference, because semaphore was already waited on. Fixes: 128805387 Fixes: 128806388 Fixes: 128807485 Fixes: 128879779 Fixes: 128417453 Bug: 128998567 Test: Ran SelfieCity, Camera360, Settings app Change-Id: I880ba6fa65509ba4c6faca0dc933551efcee423b --- libs/hwui/renderthread/VulkanManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 9916da5d9f10..7f979d6c3e53 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -467,6 +467,10 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) { GrBackendSemaphore backendSemaphore; backendSemaphore.initVulkan(semaphore); bufferInfo->skSurface->wait(1, &backendSemaphore); + // The following flush blocks the GPU immediately instead of waiting for other + // drawing ops. It seems dequeue_fence is not respected otherwise. + //TODO: remove the flush after finding why backendSemaphore is not working. + bufferInfo->skSurface->flush(); } } -- cgit v1.2.3-59-g8ed1b From 197843d031fc1480dbebb2ee1403742834d59fd2 Mon Sep 17 00:00:00 2001 From: Stan Iliev Date: Thu, 21 Mar 2019 11:34:15 -0400 Subject: Block GPU on dequeue fence only if it has not signalled already When Vulkan pipeline dequeues next frame at the beginning of DrawFrame, the dequeue fence has been signalled in most cases. This CL avoids additional work and saves about 0.3ms per frame. There is no need to create VkSemaphore and commit an empty command buffer to the queue if the fence has already signalled. Bug: 128998567 Test: Ran systrace on SelfieCity and observed better performance Change-Id: I3532b785fae90308d922a29f1698f5dbcbd79079 --- libs/hwui/renderthread/VulkanManager.cpp | 73 ++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 7f979d6c3e53..b8ebf3bb0ca9 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -439,38 +439,47 @@ Frame VulkanManager::dequeueNextBuffer(VulkanSurface* surface) { LOG_ALWAYS_FATAL_IF(!bufferInfo->dequeued); if (bufferInfo->dequeue_fence != -1) { - int fence_clone = dup(bufferInfo->dequeue_fence); - if (fence_clone == -1) { - ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno), errno); - sync_wait(bufferInfo->dequeue_fence, -1 /* forever */); - } else { - VkSemaphoreCreateInfo semaphoreInfo; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - semaphoreInfo.pNext = nullptr; - semaphoreInfo.flags = 0; - VkSemaphore semaphore; - VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore); - LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d", - err); - - VkImportSemaphoreFdInfoKHR importInfo; - importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR; - importInfo.pNext = nullptr; - importInfo.semaphore = semaphore; - importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT; - importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - importInfo.fd = fence_clone; - - err = mImportSemaphoreFdKHR(mDevice, &importInfo); - LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err); - - GrBackendSemaphore backendSemaphore; - backendSemaphore.initVulkan(semaphore); - bufferInfo->skSurface->wait(1, &backendSemaphore); - // The following flush blocks the GPU immediately instead of waiting for other - // drawing ops. It seems dequeue_fence is not respected otherwise. - //TODO: remove the flush after finding why backendSemaphore is not working. - bufferInfo->skSurface->flush(); + struct sync_file_info* finfo = sync_file_info(bufferInfo->dequeue_fence); + bool isSignalPending = false; + if (finfo != NULL) { + isSignalPending = finfo->status != 1; + sync_file_info_free(finfo); + } + if (isSignalPending) { + int fence_clone = dup(bufferInfo->dequeue_fence); + if (fence_clone == -1) { + ALOGE("dup(fence) failed, stalling until signalled: %s (%d)", strerror(errno), + errno); + sync_wait(bufferInfo->dequeue_fence, -1 /* forever */); + } else { + VkSemaphoreCreateInfo semaphoreInfo; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphoreInfo.pNext = nullptr; + semaphoreInfo.flags = 0; + VkSemaphore semaphore; + VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore); + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to create import semaphore, err: %d", + err); + + VkImportSemaphoreFdInfoKHR importInfo; + importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR; + importInfo.pNext = nullptr; + importInfo.semaphore = semaphore; + importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT; + importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + importInfo.fd = fence_clone; + + err = mImportSemaphoreFdKHR(mDevice, &importInfo); + LOG_ALWAYS_FATAL_IF(VK_SUCCESS != err, "Failed to import semaphore, err: %d", err); + + GrBackendSemaphore backendSemaphore; + backendSemaphore.initVulkan(semaphore); + bufferInfo->skSurface->wait(1, &backendSemaphore); + // The following flush blocks the GPU immediately instead of waiting for other + // drawing ops. It seems dequeue_fence is not respected otherwise. + //TODO: remove the flush after finding why backendSemaphore is not working. + bufferInfo->skSurface->flush(); + } } } -- cgit v1.2.3-59-g8ed1b