Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92b519bd authored by Melody Hsu's avatar Melody Hsu
Browse files

Calculate workload target using original frame deadline

The target work duration in HWUI ADPF is sometimes incorrect, and
is more often incorrect during buffer stuffing recovery due to the
exposure of new jank. The issue causes CPU clock frequencies to
decrease too much, and cause potential jank in subequent frames.

The original frame deadline should be used instead in calculating
the workload target deadline when triple buffered because even when
the deadline is pushed later during buffer stuffing, the throughput
requirements remain the same.

Also fixes a misordering in FrameInfoNames that was inconsistent
with FrameInfo and FrameMetrics.

Bug: b/389939827
Test: atest JankTracker
Test: presubmit, perfetto traces w/ and w/o buffer stuffing recovery
Flag: com.android.graphics.hwui.flags.calc_workload_orig_deadline
Change-Id: I2e3da6ee927d20fcbc9299ab5eda5732660d7246
parent a99ccaec
Loading
Loading
Loading
Loading
+13 −12
Original line number Diff line number Diff line
@@ -259,19 +259,20 @@ public final class FrameMetrics {
        int FRAME_DEADLINE = 9;
        int FRAME_START_TIME = 10;
        int FRAME_INTERVAL = 11;
        int SYNC_QUEUED = 12;
        int SYNC_START = 13;
        int ISSUE_DRAW_COMMANDS_START = 14;
        int SWAP_BUFFERS = 15;
        int FRAME_COMPLETED = 16;
        int DEQUEUE_BUFFER_DURATION = 17;
        int QUEUE_BUFFER_DURATION = 18;
        int GPU_COMPLETED = 19;
        int SWAP_BUFFERS_COMPLETED = 20;
        int DISPLAY_PRESENT_TIME = 21;
        int COMMAND_SUBMISSION_COMPLETED = 22;
        int WORKLOAD_TARGET = 12;
        int SYNC_QUEUED = 13;
        int SYNC_START = 14;
        int ISSUE_DRAW_COMMANDS_START = 15;
        int SWAP_BUFFERS = 16;
        int FRAME_COMPLETED = 17;
        int DEQUEUE_BUFFER_DURATION = 18;
        int QUEUE_BUFFER_DURATION = 19;
        int GPU_COMPLETED = 20;
        int SWAP_BUFFERS_COMPLETED = 21;
        int DISPLAY_PRESENT_TIME = 22;
        int COMMAND_SUBMISSION_COMPLETED = 23;

        int FRAME_STATS_COUNT = 23; // must always be last and in sync with
        int FRAME_STATS_COUNT = 24; // must always be last and in sync with
                                    // FrameInfoIndex::NumIndexes in libs/hwui/FrameInfo.h
    }

+2 −1
Original line number Diff line number Diff line
@@ -95,7 +95,8 @@ public final class FrameInfo {

    // Must be the last one
    // This value must be in sync with `UI_THREAD_FRAME_INFO_SIZE` in FrameInfo.h
    private static final int FRAME_INFO_SIZE = FRAME_INTERVAL + 1;
    // In calculating size, + 1 for Flags, and + 1 for WorkloadTarget from FrameInfo.h
    private static final int FRAME_INFO_SIZE = FRAME_INTERVAL + 2;

    /** checkstyle */
    public void setVsync(long intendedVsync, long usedVsync, long frameTimelineVsyncId,
+3 −2
Original line number Diff line number Diff line
@@ -32,8 +32,9 @@ const std::array FrameInfoNames{"Flags",
                                "PerformTraversalsStart",
                                "DrawStart",
                                "FrameDeadline",
                                "FrameInterval",
                                "FrameStartTime",
                                "FrameInterval",
                                "WorkloadTarget",
                                "SyncQueued",
                                "SyncStart",
                                "IssueDrawCommandsStart",
@@ -48,7 +49,7 @@ const std::array FrameInfoNames{"Flags",

};

static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 23,
static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 24,
              "Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");

void FrameInfo::importUiThreadInfo(int64_t* info) {
+8 −1
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@
namespace android {
namespace uirenderer {

static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 12;
// This value must be in sync with `FRAME_INFO_SIZE` in FrameInfo.Java
static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 13;

enum class FrameInfoIndex {
    Flags = 0,
@@ -47,6 +48,11 @@ enum class FrameInfoIndex {
    FrameInterval,
    // End of UI frame info

    // The target workload duration based on the original frame deadline and
    // and intended vsync. Counted in UI_THREAD_FRAME_INFO_SIZE so its value
    // can be set in setVsync().
    WorkloadTarget,

    SyncQueued,

    SyncStart,
@@ -109,6 +115,7 @@ public:
        set(FrameInfoIndex::FrameStartTime) = vsyncTime;
        set(FrameInfoIndex::FrameDeadline) = frameDeadline;
        set(FrameInfoIndex::FrameInterval) = frameInterval;
        set(FrameInfoIndex::WorkloadTarget) = frameDeadline - intendedVsync;
        return *this;
    }

+1 −1
Original line number Diff line number Diff line
@@ -201,7 +201,7 @@ void JankTracker::finishFrame(FrameInfo& frame, std::unique_ptr<FrameMetricsRepo
    // If we are in triple buffering, we have enough buffers in queue to sustain a single frame
    // drop without jank, so adjust the frame interval to the deadline.
    if (isTripleBuffered) {
        int64_t originalDeadlineDuration = deadline - frame[FrameInfoIndex::IntendedVsync];
        int64_t originalDeadlineDuration = frame[FrameInfoIndex::WorkloadTarget];
        deadline = mNextFrameStartUnstuffed + originalDeadlineDuration;
        frame.set(FrameInfoIndex::FrameDeadline) = deadline;
    }
Loading