OSDN Git Service

Fix profile gpu bars to use display fps
authorJohn Reck <jreck@google.com>
Fri, 15 Mar 2019 23:36:01 +0000 (16:36 -0700)
committerJohn Reck <jreck@google.com>
Fri, 15 Mar 2019 23:49:25 +0000 (16:49 -0700)
Also adds a 'good' bar at 80% threshold
and a 'bad' bar at 150% threshold (where triple
buffering would start to get iffy)

Fixes: 127371028
Test: eyeball'd it

Change-Id: I109cd293f87f8cb9c8f1e66d49fb8fb2188b0bec

libs/hwui/FrameInfoVisualizer.cpp
libs/hwui/FrameInfoVisualizer.h
libs/hwui/renderthread/CanvasContext.cpp
libs/hwui/renderthread/RenderThread.cpp
libs/hwui/renderthread/RenderThread.h

index b04c774..3a8e559 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "IProfileRenderer.h"
 #include "utils/Color.h"
+#include "utils/TimeUtils.h"
 
 #include <cutils/compiler.h>
 #include <array>
 #define RETURN_IF_DISABLED() \
     if (CC_LIKELY(mType == ProfileType::None && !mShowDirtyRegions)) return
 
-#define PROFILE_DRAW_WIDTH 3
-#define PROFILE_DRAW_THRESHOLD_STROKE_WIDTH 2
-#define PROFILE_DRAW_DP_PER_MS 7
-
 namespace android {
 namespace uirenderer {
 
-// Must be NUM_ELEMENTS in size
-static const SkColor THRESHOLD_COLOR = Color::Green_500;
-static const SkColor BAR_FAST_MASK = 0x8FFFFFFF;
-static const SkColor BAR_JANKY_MASK = 0xDFFFFFFF;
+static constexpr auto PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2;
+static constexpr auto PROFILE_DRAW_DP_PER_MS = 7;
+
+struct Threshold {
+    SkColor color;
+    float percentFrametime;
+};
 
-// We could get this from TimeLord and use the actual frame interval, but
-// this is good enough
-#define FRAME_THRESHOLD 16
-#define FRAME_THRESHOLD_NS 16000000
+static constexpr std::array<Threshold, 3> THRESHOLDS{
+        Threshold{.color = Color::Green_500, .percentFrametime = 0.8f},
+        Threshold{.color = Color::Lime_500, .percentFrametime = 1.0f},
+        Threshold{.color = Color::Red_500, .percentFrametime = 1.5f},
+};
+static constexpr SkColor BAR_FAST_MASK = 0x8FFFFFFF;
+static constexpr SkColor BAR_JANKY_MASK = 0xDFFFFFFF;
 
 struct BarSegment {
     FrameInfoIndex start;
@@ -64,7 +67,8 @@ static int dpToPx(int dp, float density) {
     return (int)(dp * density + 0.5f);
 }
 
-FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
+FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source, nsecs_t frameInterval)
+        : mFrameSource(source), mFrameInterval(frameInterval) {
     setDensity(1);
     consumeProperties();
 }
@@ -76,7 +80,10 @@ FrameInfoVisualizer::~FrameInfoVisualizer() {
 void FrameInfoVisualizer::setDensity(float density) {
     if (CC_UNLIKELY(mDensity != density)) {
         mDensity = density;
-        mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density);
+        // We want the vertical units to scale height relative to a baseline 16ms.
+        // This keeps the threshold lines consistent across varying refresh rates
+        mVerticalUnit = static_cast<int>(dpToPx(PROFILE_DRAW_DP_PER_MS, density) * (float)16_ms /
+                                         (float)mFrameInterval);
         mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density);
     }
 }
@@ -148,7 +155,7 @@ void FrameInfoVisualizer::initializeRects(const int baseline, const int width) {
         float* rect;
         int ri;
         // Rects are LTRB
-        if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) {
+        if (mFrameSource[fi].totalDuration() <= mFrameInterval) {
             rect = mFastRects.get();
             ri = fast_i;
             fast_i += 4;
@@ -181,7 +188,7 @@ void FrameInfoVisualizer::nextBarSegment(FrameInfoIndex start, FrameInfoIndex en
         float* rect;
         int ri;
         // Rects are LTRB
-        if (mFrameSource[fi].totalDuration() <= FRAME_THRESHOLD_NS) {
+        if (mFrameSource[fi].totalDuration() <= mFrameInterval) {
             rect = mFastRects.get();
             ri = fast_i;
             fast_i -= 4;
@@ -211,10 +218,13 @@ void FrameInfoVisualizer::drawGraph(IProfileRenderer& renderer) {
 
 void FrameInfoVisualizer::drawThreshold(IProfileRenderer& renderer) {
     SkPaint paint;
-    paint.setColor(THRESHOLD_COLOR);
-    float yLocation = renderer.getViewportHeight() - (FRAME_THRESHOLD * mVerticalUnit);
-    renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(),
-                      yLocation + mThresholdStroke / 2, paint);
+    for (auto& t : THRESHOLDS) {
+        paint.setColor(t.color);
+        float yLocation = renderer.getViewportHeight() -
+                          (ns2ms(mFrameInterval) * t.percentFrametime * mVerticalUnit);
+        renderer.drawRect(0.0f, yLocation - mThresholdStroke / 2, renderer.getViewportWidth(),
+                          yLocation + mThresholdStroke / 2, paint);
+    }
 }
 
 bool FrameInfoVisualizer::consumeProperties() {
index b98f501..3040a77 100644 (file)
@@ -39,7 +39,7 @@ typedef RingBuffer<FrameInfo, 120> FrameInfoSource;
 
 class FrameInfoVisualizer {
 public:
-    explicit FrameInfoVisualizer(FrameInfoSource& source);
+    explicit FrameInfoVisualizer(FrameInfoSource& source, nsecs_t frameInterval);
     ~FrameInfoVisualizer();
 
     bool consumeProperties();
@@ -71,6 +71,7 @@ private:
 
     FrameInfoSource& mFrameSource;
 
+    nsecs_t mFrameInterval;
     int mVerticalUnit = 0;
     int mThresholdStroke = 0;
 
index 091775d..f5b4d93 100644 (file)
@@ -103,7 +103,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode*
         , mOpaque(!translucent)
         , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
         , mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo())
-        , mProfiler(mJankTracker.frames())
+        , mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
         , mContentDrawBounds(0, 0, 0, 0)
         , mRenderPipeline(std::move(renderPipeline)) {
     rootRenderNode->makeRoot();
index 08edd20..c784d64 100644 (file)
@@ -52,9 +52,6 @@ namespace renderthread {
 // using just a few large reads.
 static const size_t EVENT_BUFFER_SIZE = 100;
 
-// Slight delay to give the UI time to push us a new frame before we replay
-static const nsecs_t DISPATCH_FRAME_CALLBACKS_DELAY = milliseconds_to_nanoseconds(4);
-
 static bool gHasRenderThreadInstance = false;
 
 static JVMAttachHook gOnStartHook = nullptr;
@@ -171,6 +168,7 @@ void RenderThread::initThreadLocals() {
     mDisplayInfo = DeviceInfo::get()->displayInfo();
     nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
     mTimeLord.setFrameInterval(frameIntervalNanos);
+    mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
     initializeDisplayEventReceiver();
     mEglManager = new EglManager();
     mRenderState = new RenderState(*this);
@@ -311,7 +309,7 @@ void RenderThread::drainDisplayEventQueue() {
         if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
             ATRACE_NAME("queue mFrameCallbackTask");
             mFrameCallbackTaskPending = true;
-            nsecs_t runAt = (vsyncEvent + DISPATCH_FRAME_CALLBACKS_DELAY);
+            nsecs_t runAt = (vsyncEvent + mDispatchFrameDelay);
             queue().postAt(runAt, [this]() { dispatchFrameCallbacks(); });
         }
     }
index 329b4b9..9298be6 100644 (file)
@@ -24,6 +24,7 @@
 #include "TimeLord.h"
 #include "thread/ThreadBase.h"
 #include "WebViewFunctorManager.h"
+#include "utils/TimeUtils.h"
 
 #include <GrContext.h>
 #include <SkBitmap.h>
@@ -164,6 +165,7 @@ private:
     bool mFrameCallbackTaskPending;
 
     TimeLord mTimeLord;
+    nsecs_t mDispatchFrameDelay = 4_ms;
     RenderState* mRenderState;
     EglManager* mEglManager;
     WebViewFunctorManager& mFunctorManager;