Merge "Skip sending HWUI hints when frame does not draw"

This commit is contained in:
Matt Buckley
2022-10-28 21:38:30 +00:00
committed by Android (Google) Code Review
3 changed files with 28 additions and 15 deletions

View File

@@ -472,11 +472,11 @@ void CanvasContext::notifyFramePending() {
mRenderThread.pushBackFrameCallback(this);
}
nsecs_t CanvasContext::draw() {
std::optional<nsecs_t> CanvasContext::draw() {
if (auto grContext = getGrContext()) {
if (grContext->abandoned()) {
LOG_ALWAYS_FATAL("GrContext is abandoned/device lost at start of CanvasContext::draw");
return 0;
return std::nullopt;
}
}
SkRect dirty;
@@ -498,7 +498,7 @@ nsecs_t CanvasContext::draw() {
std::invoke(func, false /* didProduceBuffer */);
}
mFrameCommitCallbacks.clear();
return 0;
return std::nullopt;
}
ScopedActiveContext activeContext(this);
@@ -543,6 +543,8 @@ nsecs_t CanvasContext::draw() {
}
bool requireSwap = false;
bool didDraw = false;
int error = OK;
bool didSwap = mRenderPipeline->swapBuffers(frame, drawResult.success, windowDirty,
mCurrentFrameInfo, &requireSwap);
@@ -553,7 +555,7 @@ nsecs_t CanvasContext::draw() {
mIsDirty = false;
if (requireSwap) {
bool didDraw = true;
didDraw = true;
// Handle any swapchain errors
error = mNativeSurface->getAndClearError();
if (error == TIMED_OUT) {
@@ -649,7 +651,9 @@ nsecs_t CanvasContext::draw() {
}
mRenderThread.cacheManager().onFrameCompleted();
return mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration);
return didDraw ? std::make_optional(
mCurrentFrameInfo->get(FrameInfoIndex::DequeueBufferDuration))
: std::nullopt;
}
void CanvasContext::reportMetricsWithPresentTime() {

View File

@@ -138,7 +138,7 @@ public:
bool makeCurrent();
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
// Returns the DequeueBufferDuration.
nsecs_t draw();
std::optional<nsecs_t> draw();
void destroy();
// IFrameCallback, Choreographer-driven frame callback entry point

View File

@@ -19,6 +19,7 @@
#include <dlfcn.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
#include <algorithm>
#include "../DeferredLayerUpdater.h"
@@ -28,6 +29,7 @@
#include "CanvasContext.h"
#include "RenderThread.h"
#include "thread/CommonPool.h"
#include "utils/TimeUtils.h"
namespace android {
namespace uirenderer {
@@ -146,6 +148,7 @@ void DrawFrameTask::run() {
bool canUnblockUiThread;
bool canDrawThisFrame;
bool didDraw = false;
{
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
info.forceDrawFrame = mForceDrawFrame;
@@ -188,7 +191,9 @@ void DrawFrameTask::run() {
nsecs_t dequeueBufferDuration = 0;
if (CC_LIKELY(canDrawThisFrame)) {
dequeueBufferDuration = context->draw();
std::optional<nsecs_t> drawResult = context->draw();
didDraw = drawResult.has_value();
dequeueBufferDuration = drawResult.value_or(0);
} else {
// Do a flush in case syncFrameState performed any texture uploads. Since we skipped
// the draw() call, those uploads (or deletes) will end up sitting in the queue.
@@ -209,8 +214,9 @@ void DrawFrameTask::run() {
}
if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
constexpr int64_t kSanityCheckLowerBound = 100_us;
constexpr int64_t kSanityCheckUpperBound = 10_s;
int64_t targetWorkDuration = frameDeadline - intendedVsync;
targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
if (targetWorkDuration > kSanityCheckLowerBound &&
@@ -219,12 +225,15 @@ void DrawFrameTask::run() {
mLastTargetWorkDuration = targetWorkDuration;
mHintSessionWrapper->updateTargetWorkDuration(targetWorkDuration);
}
int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
int64_t actualDuration = frameDuration -
(std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
dequeueBufferDuration;
if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
mHintSessionWrapper->reportActualWorkDuration(actualDuration);
if (didDraw) {
int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
int64_t actualDuration = frameDuration -
(std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
dequeueBufferDuration;
if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
mHintSessionWrapper->reportActualWorkDuration(actualDuration);
}
}
mLastDequeueBufferDuration = dequeueBufferDuration;