diff options
Diffstat (limited to 'libs/hwui/renderthread')
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 40 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 6 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/renderthread/VulkanManager.cpp | 68 | ||||
-rw-r--r-- | libs/hwui/renderthread/VulkanManager.h | 4 |
6 files changed, 96 insertions, 32 deletions
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index b760db287bcb..9793300b406d 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -484,7 +484,8 @@ void CanvasContext::draw() { // TODO(b/165985262): measure performance impact const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId); if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) { - const auto inputEventId = mCurrentFrameInfo->get(FrameInfoIndex::NewestInputEvent); + const auto inputEventId = + static_cast<int32_t>(mCurrentFrameInfo->get(FrameInfoIndex::InputEventId)); native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), vsyncId, inputEventId); } @@ -591,7 +592,6 @@ void CanvasContext::draw() { } void CanvasContext::finishFrame(FrameInfo* frameInfo) { - // TODO (b/169858044): Consolidate this into a single call. mJankTracker.finishFrame(*frameInfo); mJankTracker.finishGpuDraw(*frameInfo); @@ -599,10 +599,41 @@ void CanvasContext::finishFrame(FrameInfo* frameInfo) { // TODO (b/169858044): Move this into JankTracker to adjust deadline when queue is // double-stuffed. if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) { - mFrameMetricsReporter->reportFrameMetrics(frameInfo->data()); + mFrameMetricsReporter->reportFrameMetrics(frameInfo->data(), false /*hasPresentTime*/); } } +void CanvasContext::reportMetricsWithPresentTime() { + if (mFrameMetricsReporter == nullptr) { + return; + } + if (mNativeSurface == nullptr) { + return; + } + FrameInfo* forthBehind; + int64_t frameNumber; + { // acquire lock + std::scoped_lock lock(mLast4FrameInfosMutex); + if (mLast4FrameInfos.size() != mLast4FrameInfos.capacity()) { + // Not enough frames yet + return; + } + // Surface object keeps stats for the last 8 frames. + std::tie(forthBehind, frameNumber) = mLast4FrameInfos.front(); + } // release lock + + nsecs_t presentTime = 0; + native_window_get_frame_timestamps( + mNativeSurface->getNativeWindow(), frameNumber, nullptr /*outRequestedPresentTime*/, + nullptr /*outAcquireTime*/, nullptr /*outLatchTime*/, + nullptr /*outFirstRefreshStartTime*/, nullptr /*outLastRefreshStartTime*/, + nullptr /*outGpuCompositionDoneTime*/, &presentTime, nullptr /*outDequeueReadyTime*/, + nullptr /*outReleaseTime*/); + + forthBehind->set(FrameInfoIndex::DisplayPresentTime) = presentTime; + mFrameMetricsReporter->reportFrameMetrics(forthBehind->data(), true /*hasPresentTime*/); +} + void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* control, ASurfaceControlStats* stats) { @@ -624,6 +655,9 @@ void CanvasContext::onSurfaceStatsAvailable(void* context, ASurfaceControl* cont } } } + + instance->reportMetricsWithPresentTime(); + if (frameInfo != nullptr) { if (gpuCompleteTime == -1) { gpuCompleteTime = frameInfo->get(FrameInfoIndex::SwapBuffersCompleted); diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 974c984f3120..626e75e74d31 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -225,6 +225,12 @@ private: SkRect computeDirtyRect(const Frame& frame, SkRect* dirty); void finishFrame(FrameInfo* frameInfo); + /** + * Invoke 'reportFrameMetrics' on the last frame stored in 'mLast4FrameInfos'. + * Populate the 'presentTime' field before calling. + */ + void reportMetricsWithPresentTime(); + // The same type as Frame.mWidth and Frame.mHeight int32_t mLastFrameWidth = 0; int32_t mLastFrameHeight = 0; diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index c9146b2fc2d1..3408ffda3f9d 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -17,7 +17,7 @@ #include "DrawFrameTask.h" #include <utils/Log.h> -#include <utils/Trace.h> +#include <utils/TraceUtils.h> #include "../DeferredLayerUpdater.h" #include "../DisplayList.h" @@ -82,7 +82,8 @@ void DrawFrameTask::postAndWait() { } void DrawFrameTask::run() { - ATRACE_NAME("DrawFrame"); + const int64_t vsyncId = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameTimelineVsyncId)]; + ATRACE_FORMAT("DrawFrames %" PRId64, vsyncId); bool canUnblockUiThread; bool canDrawThisFrame; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index b9568fcf8e66..423cc08189ca 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -230,7 +230,10 @@ void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) { } void RenderProxy::resetProfileInfo() { - mRenderThread.queue().runSync([=]() { mContext->resetFrameStats(); }); + mRenderThread.queue().runSync([=]() { + std::lock_guard lock(mRenderThread.getJankDataMutex()); + mContext->resetFrameStats(); + }); } uint32_t RenderProxy::frameTimePercentile(int percentile) { diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 3e7ce368f55d..e93824dfbd30 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -31,6 +31,7 @@ #include "Properties.h" #include "RenderThread.h" +#include "pipeline/skia/ShaderCache.h" #include "renderstate/RenderState.h" #include "utils/TraceUtils.h" @@ -476,17 +477,10 @@ static void destroy_semaphore(void* context) { } } -void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) { - if (CC_UNLIKELY(Properties::waitForGpuCompletion)) { - ATRACE_NAME("Finishing GPU work"); - mDeviceWaitIdle(mDevice); - } - - VulkanSurface::NativeBufferInfo* bufferInfo = surface->getCurrentBufferInfo(); - if (!bufferInfo) { - // If VulkanSurface::dequeueNativeBuffer failed earlier, then swapBuffers is a no-op. - return; - } +void VulkanManager::finishFrame(SkSurface* surface) { + ATRACE_NAME("Vulkan finish frame"); + ALOGE_IF(mSwapSemaphore != VK_NULL_HANDLE || mDestroySemaphoreContext != nullptr, + "finishFrame already has an outstanding semaphore"); VkExportSemaphoreCreateInfo exportInfo; exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO; @@ -499,32 +493,52 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) semaphoreInfo.flags = 0; VkSemaphore semaphore; VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore); - ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to create semaphore"); + ALOGE_IF(VK_SUCCESS != err, "VulkanManager::makeSwapSemaphore(): Failed to create semaphore"); GrBackendSemaphore backendSemaphore; backendSemaphore.initVulkan(semaphore); - int fenceFd = -1; - DestroySemaphoreInfo* destroyInfo = - new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore); GrFlushInfo flushInfo; - flushInfo.fNumSemaphores = 1; - flushInfo.fSignalSemaphores = &backendSemaphore; - flushInfo.fFinishedProc = destroy_semaphore; - flushInfo.fFinishedContext = destroyInfo; - GrSemaphoresSubmitted submitted = bufferInfo->skSurface->flush( - SkSurface::BackendSurfaceAccess::kPresent, flushInfo); - GrDirectContext* context = GrAsDirectContext(bufferInfo->skSurface->recordingContext()); + if (err == VK_SUCCESS) { + mDestroySemaphoreContext = new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore); + flushInfo.fNumSemaphores = 1; + flushInfo.fSignalSemaphores = &backendSemaphore; + flushInfo.fFinishedProc = destroy_semaphore; + flushInfo.fFinishedContext = mDestroySemaphoreContext; + } else { + semaphore = VK_NULL_HANDLE; + } + GrSemaphoresSubmitted submitted = + surface->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo); + GrDirectContext* context = GrAsDirectContext(surface->recordingContext()); ALOGE_IF(!context, "Surface is not backed by gpu"); context->submit(); - if (submitted == GrSemaphoresSubmitted::kYes) { + if (semaphore != VK_NULL_HANDLE) { + if (submitted == GrSemaphoresSubmitted::kYes) { + mSwapSemaphore = semaphore; + } else { + destroy_semaphore(mDestroySemaphoreContext); + mDestroySemaphoreContext = nullptr; + } + } + skiapipeline::ShaderCache::get().onVkFrameFlushed(context); +} + +void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) { + if (CC_UNLIKELY(Properties::waitForGpuCompletion)) { + ATRACE_NAME("Finishing GPU work"); + mDeviceWaitIdle(mDevice); + } + + int fenceFd = -1; + if (mSwapSemaphore != VK_NULL_HANDLE) { VkSemaphoreGetFdInfoKHR getFdInfo; getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR; getFdInfo.pNext = nullptr; - getFdInfo.semaphore = semaphore; + getFdInfo.semaphore = mSwapSemaphore; getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd); + VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd); ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd"); } else { ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed"); @@ -532,9 +546,11 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) std::lock_guard<std::mutex> lock(mGraphicsQueueMutex); mQueueWaitIdle(mGraphicsQueue); } - destroy_semaphore(destroyInfo); + destroy_semaphore(mDestroySemaphoreContext); surface->presentCurrentBuffer(dirtyRect, fenceFd); + mSwapSemaphore = VK_NULL_HANDLE; + mDestroySemaphoreContext = nullptr; } void VulkanManager::destroySurface(VulkanSurface* surface) { diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 121afc90cfe5..0912369b611d 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -69,6 +69,7 @@ public: void destroySurface(VulkanSurface* surface); Frame dequeueNextBuffer(VulkanSurface* surface); + void finishFrame(SkSurface* surface); void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect); // Inserts a wait on fence command into the Vulkan command buffer. @@ -200,6 +201,9 @@ private: SwapBehavior mSwapBehavior = SwapBehavior::Discard; GrVkExtensions mExtensions; uint32_t mDriverVersion = 0; + + VkSemaphore mSwapSemaphore = VK_NULL_HANDLE; + void* mDestroySemaphoreContext = nullptr; }; } /* namespace renderthread */ |