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

Commit 4c459ef8 authored by Matt Buckley's avatar Matt Buckley Committed by Automerger Merge Worker
Browse files

Use true present fence times in PowerHintSession duration calc am: c6b9d38c am: ce78d418

parents 00e982c1 ce78d418
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ public:
    MOCK_METHOD(void, setRequiresClientComposition,
    MOCK_METHOD(void, setRequiresClientComposition,
                (DisplayId displayId, bool requiresClientComposition), (override));
                (DisplayId displayId, bool requiresClientComposition), (override));
    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
    MOCK_METHOD(void, setPresentFenceTime, (nsecs_t presentFenceTime), (override));
    MOCK_METHOD(void, setHwcPresentDelayedTime,
    MOCK_METHOD(void, setHwcPresentDelayedTime,
                (DisplayId displayId,
                (DisplayId displayId,
                 std::chrono::steady_clock::time_point earliestFrameStartTime));
                 std::chrono::steady_clock::time_point earliestFrameStartTime));
+32 −23
Original line number Original line Diff line number Diff line
@@ -315,6 +315,10 @@ void PowerAdvisor::setExpectedPresentTime(nsecs_t expectedPresentTime) {
    mExpectedPresentTimes.append(expectedPresentTime);
    mExpectedPresentTimes.append(expectedPresentTime);
}
}


void PowerAdvisor::setPresentFenceTime(nsecs_t presentFenceTime) {
    mLastPresentFenceTime = presentFenceTime;
}

void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
    mFrameDelayDuration = frameDelayDuration;
    mFrameDelayDuration = frameDelayDuration;
}
}
@@ -384,11 +388,11 @@ std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
    // If we're predicting at the end of the frame, we use the current frame as a reference point
    // If we're predicting at the end of the frame, we use the current frame as a reference point
    nsecs_t referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);
    nsecs_t referenceFrameStartTime = (earlyHint ? mCommitStartTimes[-1] : mCommitStartTimes[0]);


    // We need an idea of when the last present fence fired and how long it made us wait
    // When the prior frame should be presenting to the display
    // If we're predicting at the start of the frame, we want frame n-2's present fence time
    // If we're predicting at the start of the frame, we use last frame's expected present time
    // If we're predicting at the end of the frame we want frame n-1's present time
    // If we're predicting at the end of the frame, the present fence time is already known
    nsecs_t referenceFenceTime =
    nsecs_t lastFramePresentTime = (earlyHint ? mExpectedPresentTimes[-1] : mLastPresentFenceTime);
            (earlyHint ? mExpectedPresentTimes[-2] : mExpectedPresentTimes[-1]);

    // The timing info for the previously calculated display, if there was one
    // The timing info for the previously calculated display, if there was one
    std::optional<DisplayTimeline> previousDisplayReferenceTiming;
    std::optional<DisplayTimeline> previousDisplayReferenceTiming;
    std::vector<DisplayId>&& displayIds =
    std::vector<DisplayId>&& displayIds =
@@ -402,7 +406,11 @@ std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
        }
        }


        auto& displayData = mDisplayTimingData.at(displayId);
        auto& displayData = mDisplayTimingData.at(displayId);
        referenceTiming = displayData.calculateDisplayTimeline(referenceFenceTime);

        // mLastPresentFenceTime should always be the time of the reference frame, since it will be
        // the previous frame's present fence if called at the start, and current frame's if called
        // at the end
        referenceTiming = displayData.calculateDisplayTimeline(mLastPresentFenceTime);


        // If this is the first display, include the duration before hwc present starts
        // If this is the first display, include the duration before hwc present starts
        if (!previousDisplayReferenceTiming.has_value()) {
        if (!previousDisplayReferenceTiming.has_value()) {
@@ -412,14 +420,15 @@ std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
                    previousDisplayReferenceTiming->hwcPresentEndTime;
                    previousDisplayReferenceTiming->hwcPresentEndTime;
        }
        }


        estimatedTiming = referenceTiming.estimateTimelineFromReference(mExpectedPresentTimes[-1],
        estimatedTiming = referenceTiming.estimateTimelineFromReference(lastFramePresentTime,
                                                                        estimatedEndTime);
                                                                        estimatedEndTime);

        // Update predicted present finish time with this display's present time
        // Update predicted present finish time with this display's present time
        estimatedEndTime = estimatedTiming.hwcPresentEndTime;
        estimatedEndTime = estimatedTiming.hwcPresentEndTime;


        // Track how long we spent waiting for the fence, can be excluded from the timing estimate
        // Track how long we spent waiting for the fence, can be excluded from the timing estimate
        idleDuration += estimatedTiming.probablyWaitsForReleaseFence
        idleDuration += estimatedTiming.probablyWaitsForPresentFence
                ? mExpectedPresentTimes[-1] - estimatedTiming.releaseFenceWaitStartTime
                ? lastFramePresentTime - estimatedTiming.presentFenceWaitStartTime
                : 0;
                : 0;


        // Track how long we spent waiting to present, can be excluded from the timing estimate
        // Track how long we spent waiting to present, can be excluded from the timing estimate
@@ -476,15 +485,15 @@ PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFro
    // We don't predict waiting for vsync alignment yet
    // We don't predict waiting for vsync alignment yet
    estimated.hwcPresentDelayDuration = 0;
    estimated.hwcPresentDelayDuration = 0;


    // For now just re-use last frame's post-present duration and assume it will not change much
    // How long we expect to run before we start waiting for the fence
    // How long we expect to run before we start waiting for the fence
    // If it's the early hint we exclude time we spent waiting for a vsync, otherwise don't
    // For now just re-use last frame's post-present duration and assume it will not change much
    estimated.releaseFenceWaitStartTime = estimated.hwcPresentStartTime +
    // Excludes time spent waiting for vsync since that's not going to be consistent
            (releaseFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
    estimated.presentFenceWaitStartTime = estimated.hwcPresentStartTime +
    estimated.probablyWaitsForReleaseFence = fenceTime > estimated.releaseFenceWaitStartTime;
            (presentFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
    estimated.hwcPresentEndTime = postReleaseFenceHwcPresentDuration +
    estimated.probablyWaitsForPresentFence = fenceTime > estimated.presentFenceWaitStartTime;
            (estimated.probablyWaitsForReleaseFence ? fenceTime
    estimated.hwcPresentEndTime = postPresentFenceHwcPresentDuration +
                                                    : estimated.releaseFenceWaitStartTime);
            (estimated.probablyWaitsForPresentFence ? fenceTime
                                                    : estimated.presentFenceWaitStartTime);
    return estimated;
    return estimated;
}
}


@@ -510,16 +519,16 @@ PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayT
    // How long hwc present was delayed waiting for the next appropriate vsync
    // How long hwc present was delayed waiting for the next appropriate vsync
    timeline.hwcPresentDelayDuration =
    timeline.hwcPresentDelayDuration =
            (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0);
            (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0);
    // When we started waiting for the release fence after calling into hwc present
    // When we started waiting for the present fence after calling into hwc present
    timeline.releaseFenceWaitStartTime =
    timeline.presentFenceWaitStartTime =
            timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
            timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
    timeline.probablyWaitsForReleaseFence = fenceTime > timeline.releaseFenceWaitStartTime &&
    timeline.probablyWaitsForPresentFence = fenceTime > timeline.presentFenceWaitStartTime &&
            fenceTime < timeline.hwcPresentEndTime;
            fenceTime < timeline.hwcPresentEndTime;


    // How long we ran after we finished waiting for the fence but before hwc present finished
    // How long we ran after we finished waiting for the fence but before hwc present finished
    timeline.postReleaseFenceHwcPresentDuration = timeline.hwcPresentEndTime -
    timeline.postPresentFenceHwcPresentDuration = timeline.hwcPresentEndTime -
            (timeline.probablyWaitsForReleaseFence ? fenceTime
            (timeline.probablyWaitsForPresentFence ? fenceTime
                                                   : timeline.releaseFenceWaitStartTime);
                                                   : timeline.presentFenceWaitStartTime);
    return timeline;
    return timeline;
}
}


+13 −9
Original line number Original line Diff line number Diff line
@@ -70,7 +70,10 @@ public:
    // Reports the start and end times of a hwc present call this frame for a given display
    // Reports the start and end times of a hwc present call this frame for a given display
    virtual void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
    virtual void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
                                     nsecs_t presentEndTime) = 0;
                                     nsecs_t presentEndTime) = 0;
    // Reports the expected time that the current frame will present to the display
    virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0;
    virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0;
    // Reports the most recent present fence time once it's known at the end of the frame
    virtual void setPresentFenceTime(nsecs_t presentFenceTime) = 0;
    // Reports whether a display used client composition this frame
    // Reports whether a display used client composition this frame
    virtual void setRequiresClientComposition(DisplayId displayId,
    virtual void setRequiresClientComposition(DisplayId displayId,
                                              bool requiresClientComposition) = 0;
                                              bool requiresClientComposition) = 0;
@@ -139,6 +142,7 @@ public:
    void setSkippedValidate(DisplayId displayId, bool skipped) override;
    void setSkippedValidate(DisplayId displayId, bool skipped) override;
    void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
    void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
    void setExpectedPresentTime(nsecs_t expectedPresentTime) override;
    void setExpectedPresentTime(nsecs_t expectedPresentTime) override;
    void setPresentFenceTime(nsecs_t presentFenceTime) override;
    void setHwcPresentDelayedTime(
    void setHwcPresentDelayedTime(
            DisplayId displayId,
            DisplayId displayId,
            std::chrono::steady_clock::time_point earliestFrameStartTime) override;
            std::chrono::steady_clock::time_point earliestFrameStartTime) override;
@@ -172,13 +176,13 @@ private:
        nsecs_t hwcPresentEndTime = -1;
        nsecs_t hwcPresentEndTime = -1;
        // How long the actual hwc present was delayed after hwcPresentStartTime
        // How long the actual hwc present was delayed after hwcPresentStartTime
        nsecs_t hwcPresentDelayDuration = 0;
        nsecs_t hwcPresentDelayDuration = 0;
        // When we think we started waiting for the release fence after calling into hwc present and
        // When we think we started waiting for the present fence after calling into hwc present and
        // after potentially waiting for the earliest present time
        // after potentially waiting for the earliest present time
        nsecs_t releaseFenceWaitStartTime = -1;
        nsecs_t presentFenceWaitStartTime = -1;
        // How long we ran after we finished waiting for the fence but before hwc present finished
        // How long we ran after we finished waiting for the fence but before hwc present finished
        nsecs_t postReleaseFenceHwcPresentDuration = 0;
        nsecs_t postPresentFenceHwcPresentDuration = 0;
        // Are we likely to have waited for the present fence during composition
        // Are we likely to have waited for the present fence during composition
        bool probablyWaitsForReleaseFence = false;
        bool probablyWaitsForPresentFence = false;
        // Estimate one frame's timeline from that of a previous frame
        // Estimate one frame's timeline from that of a previous frame
        DisplayTimeline estimateTimelineFromReference(nsecs_t fenceTime, nsecs_t displayStartTime);
        DisplayTimeline estimateTimelineFromReference(nsecs_t fenceTime, nsecs_t displayStartTime);
    };
    };
@@ -248,7 +252,9 @@ private:
    // Buffer of recent commit start times
    // Buffer of recent commit start times
    RingBuffer<nsecs_t, 2> mCommitStartTimes;
    RingBuffer<nsecs_t, 2> mCommitStartTimes;
    // Buffer of recent expected present times
    // Buffer of recent expected present times
    RingBuffer<nsecs_t, 3> mExpectedPresentTimes;
    RingBuffer<nsecs_t, 2> mExpectedPresentTimes;
    // Most recent present fence time, set at the end of the frame once known
    nsecs_t mLastPresentFenceTime = -1;
    // Target for the entire pipeline including gpu
    // Target for the entire pipeline including gpu
    std::optional<nsecs_t> mTotalFrameTargetDuration;
    std::optional<nsecs_t> mTotalFrameTargetDuration;
    // Updated list of display IDs
    // Updated list of display IDs
@@ -258,10 +264,8 @@ private:
    std::optional<bool> mSupportsPowerHint;
    std::optional<bool> mSupportsPowerHint;
    bool mPowerHintSessionRunning = false;
    bool mPowerHintSessionRunning = false;


    // An adjustable safety margin which moves the "target" earlier to allow flinger to
    // An adjustable safety margin which pads the "actual" value sent to PowerHAL,
    // go a bit over without dropping a frame, especially since we can't measure
    // encouraging more aggressive boosting to give SurfaceFlinger a larger margin for error
    // the exact time hwc finishes composition so "actual" durations are measured
    // from the end of present() instead, which is a bit later.
    static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 1ms;
    static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 1ms;


    // How long we expect hwc to run after the present call until it waits for the fence
    // How long we expect hwc to run after the present call until it waits for the fence
+1 −0
Original line number Original line Diff line number Diff line
@@ -2256,6 +2256,7 @@ void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId)


    // Send a power hint hint after presentation is finished
    // Send a power hint hint after presentation is finished
    if (mPowerHintSessionEnabled) {
    if (mPowerHintSessionEnabled) {
        mPowerAdvisor->setPresentFenceTime(mPreviousPresentFences[0].fenceTime->getSignalTime());
        if (mPowerHintSessionMode.late) {
        if (mPowerHintSessionMode.late) {
            mPowerAdvisor->sendActualWorkDuration();
            mPowerAdvisor->sendActualWorkDuration();
        }
        }
+1 −0
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ public:
    MOCK_METHOD(void, setRequiresClientComposition,
    MOCK_METHOD(void, setRequiresClientComposition,
                (DisplayId displayId, bool requiresClientComposition), (override));
                (DisplayId displayId, bool requiresClientComposition), (override));
    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
    MOCK_METHOD(void, setPresentFenceTime, (nsecs_t presentFenceTime), (override));
    MOCK_METHOD(void, setHwcPresentDelayedTime,
    MOCK_METHOD(void, setHwcPresentDelayedTime,
                (DisplayId displayId,
                (DisplayId displayId,
                 std::chrono::steady_clock::time_point earliestFrameStartTime));
                 std::chrono::steady_clock::time_point earliestFrameStartTime));