summaryrefslogtreecommitdiff
path: root/libs/hwui/renderthread
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/renderthread')
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp40
-rw-r--r--libs/hwui/renderthread/CanvasContext.h6
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp5
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp5
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp68
-rw-r--r--libs/hwui/renderthread/VulkanManager.h4
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 */