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

Commit af567a88 authored by Ram Indani's avatar Ram Indani Committed by Android (Google) Code Review
Browse files

Merge changes Ie240fc5a,If711f18d into main

* changes:
  [SF] Add a support for N VSyncs in FrameTargeter
  [SF] Add a flag to support N vsyncs in the FrameTargeter
parents 921965fa 513e6507
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
// TODO(b/185536303): Pull to FTL.
#include "../../../TracedOrdinal.h"
#include "../../../Utils/Dumper.h"
#include "../../../Utils/RingBuffer.h"

namespace android::scheduler {

@@ -61,7 +62,7 @@ public:
    // VSYNC of at least one previous frame has not yet passed. In other words, this is NOT the
    // `presentFenceForPreviousFrame` if running N VSYNCs ahead, but the one that should have been
    // signaled by now (unless that frame missed).
    const FenceTimePtr& presentFenceForPastVsync(Period minFramePeriod) const;
    FenceTimePtr presentFenceForPastVsync(Period minFramePeriod) const;

    // Equivalent to `presentFenceForPastVsync` unless running N VSYNCs ahead.
    const FenceTimePtr& presentFenceForPreviousFrame() const {
@@ -84,6 +85,12 @@ protected:
        return mExpectedPresentTime - minFramePeriod;
    }

    void addFence(sp<Fence> presentFence, FenceTimePtr presentFenceTime,
                  TimePoint expectedPresentTime) {
        mFenceWithFenceTimes.next() = {std::move(presentFence), presentFenceTime,
                                       expectedPresentTime};
    }

    VsyncId mVsyncId;
    TimePoint mFrameBeginTime;
    TimePoint mExpectedPresentTime;
@@ -97,8 +104,11 @@ protected:
    struct FenceWithFenceTime {
        sp<Fence> fence = Fence::NO_FENCE;
        FenceTimePtr fenceTime = FenceTime::NO_FENCE;
        TimePoint expectedPresentTime = TimePoint();
    };
    std::array<FenceWithFenceTime, 2> mPresentFences;
    utils::RingBuffer<FenceWithFenceTime, 5> mFenceWithFenceTimes;

    TimePoint mLastSignaledFrameTime;

private:
@@ -109,6 +119,18 @@ private:
        static_assert(N > 1);
        return expectedFrameDuration() > (N - 1) * minFramePeriod;
    }

    const FenceTimePtr pastVsyncTimePtr() const {
        auto pastFenceTimePtr = FenceTime::NO_FENCE;
        for (size_t i = 0; i < mFenceWithFenceTimes.size(); i++) {
            const auto& [_, fenceTimePtr, expectedPresentTime] = mFenceWithFenceTimes[i];
            if (expectedPresentTime > mFrameBeginTime) {
                return pastFenceTimePtr;
            }
            pastFenceTimePtr = fenceTimePtr;
        }
        return pastFenceTimePtr;
    }
};

// Computes a display's per-frame metrics about past/upcoming targeting of present deadlines.
+13 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <gui/TraceUtils.h>

#include <common/FlagManager.h>
#include <scheduler/FrameTargeter.h>
#include <scheduler/IVsyncSource.h>

@@ -33,8 +34,10 @@ TimePoint FrameTarget::pastVsyncTime(Period minFramePeriod) const {
    return mExpectedPresentTime - Period::fromNs(minFramePeriod.ns() << shift);
}

const FenceTimePtr& FrameTarget::presentFenceForPastVsync(Period minFramePeriod) const {
    // TODO(b/267315508): Generalize to N VSYNCs.
FenceTimePtr FrameTarget::presentFenceForPastVsync(Period minFramePeriod) const {
    if (FlagManager::getInstance().allow_n_vsyncs_in_targeter()) {
        return pastVsyncTimePtr();
    }
    const size_t i = static_cast<size_t>(targetsVsyncsAhead<2>(minFramePeriod));
    return mPresentFences[i].fenceTime;
}
@@ -44,7 +47,8 @@ bool FrameTarget::wouldPresentEarly(Period minFramePeriod) const {
    // should use `TimePoint::now()` in case of delays since `mFrameBeginTime`.

    // TODO(b/267315508): Generalize to N VSYNCs.
    if (targetsVsyncsAhead<3>(minFramePeriod)) {
    const bool allowNVsyncs = FlagManager::getInstance().allow_n_vsyncs_in_targeter();
    if (!allowNVsyncs && targetsVsyncsAhead<3>(minFramePeriod)) {
        return true;
    }

@@ -144,8 +148,12 @@ FenceTimePtr FrameTargeter::setPresentFence(sp<Fence> presentFence) {
}

FenceTimePtr FrameTargeter::setPresentFence(sp<Fence> presentFence, FenceTimePtr presentFenceTime) {
    if (FlagManager::getInstance().allow_n_vsyncs_in_targeter()) {
        addFence(std::move(presentFence), presentFenceTime, mExpectedPresentTime);
    } else {
        mPresentFences[1] = mPresentFences[0];
    mPresentFences[0] = {std::move(presentFence), presentFenceTime};
        mPresentFences[0] = {std::move(presentFence), presentFenceTime, mExpectedPresentTime};
    }
    return presentFenceTime;
}

+103 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include <com_android_graphics_surfaceflinger_flags.h>

using namespace com::android::graphics::surfaceflinger;
using namespace std::chrono_literals;

namespace android::scheduler {
@@ -168,6 +169,7 @@ TEST_F(FrameTargeterTest, inflatesExpectedPresentTime) {
}

TEST_F(FrameTargeterTest, recallsPastVsync) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
    VsyncId vsyncId{111};
    TimePoint frameBeginTime(1000ms);
    constexpr Fps kRefreshRate = 60_Hz;
@@ -184,6 +186,7 @@ TEST_F(FrameTargeterTest, recallsPastVsync) {
}

TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAhead) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
    VsyncId vsyncId{222};
    TimePoint frameBeginTime(2000ms);
    constexpr Fps kRefreshRate = 120_Hz;
@@ -203,8 +206,32 @@ TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAhead) {
    }
}

TEST_F(FrameTargeterTest, recallsPastNVsyncTwoVsyncsAhead) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, true);
    VsyncId vsyncId{222};
    TimePoint frameBeginTime(2000ms);
    constexpr Fps kRefreshRate = 120_Hz;
    constexpr Period kPeriod = kRefreshRate.getPeriod();
    constexpr Duration kFrameDuration = 10ms;

    FenceTimePtr previousFence = FenceTime::NO_FENCE;

    for (int n = 5; n-- > 0;) {
        Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate, kRefreshRate);
        const auto fence = frame.end();

        const auto pastVsyncTime = frameBeginTime + kFrameDuration - 2 * kPeriod;
        EXPECT_EQ(target().pastVsyncTime(kPeriod), pastVsyncTime);
        EXPECT_EQ(target().presentFenceForPastVsync(kFrameDuration), previousFence);

        frameBeginTime += kPeriod;
        previousFence = fence;
    }
}

TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAheadVrr) {
    SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::vrr_config, true);
    SET_FLAG_FOR_TEST(flags::vrr_config, true);
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);

    VsyncId vsyncId{222};
    TimePoint frameBeginTime(2000ms);
@@ -227,6 +254,33 @@ TEST_F(FrameTargeterTest, recallsPastVsyncTwoVsyncsAheadVrr) {
    }
}

TEST_F(FrameTargeterTest, recallsPastNVsyncTwoVsyncsAheadVrr) {
    SET_FLAG_FOR_TEST(flags::vrr_config, true);
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, true);

    VsyncId vsyncId{222};
    TimePoint frameBeginTime(2000ms);
    constexpr Fps kRefreshRate = 120_Hz;
    constexpr Fps kPeakRefreshRate = 240_Hz;
    constexpr Period kPeriod = kRefreshRate.getPeriod();
    constexpr Duration kFrameDuration = 10ms;

    FenceTimePtr previousFence = FenceTime::NO_FENCE;

    for (int n = 5; n-- > 0;) {
        Frame frame(this, vsyncId++, frameBeginTime, kFrameDuration, kRefreshRate,
                    kPeakRefreshRate);
        const auto fence = frame.end();

        const auto pastVsyncTime = frameBeginTime + kFrameDuration - 2 * kPeriod;
        EXPECT_EQ(target().pastVsyncTime(kPeriod), pastVsyncTime);
        EXPECT_EQ(target().presentFenceForPastVsync(kFrameDuration), previousFence);

        frameBeginTime += kPeriod;
        previousFence = fence;
    }
}

TEST_F(FrameTargeterTest, doesNotDetectEarlyPresentIfNoFence) {
    constexpr Period kPeriod = (60_Hz).getPeriod();
    EXPECT_EQ(target().presentFenceForPastVsync(kPeriod), FenceTime::NO_FENCE);
@@ -234,6 +288,7 @@ TEST_F(FrameTargeterTest, doesNotDetectEarlyPresentIfNoFence) {
}

TEST_F(FrameTargeterTest, detectsEarlyPresent) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
    VsyncId vsyncId{333};
    TimePoint frameBeginTime(3000ms);
    constexpr Fps kRefreshRate = 60_Hz;
@@ -263,6 +318,7 @@ TEST_F(FrameTargeterTest, detectsEarlyPresent) {
// Same as `detectsEarlyPresent`, above, but verifies that we do not set an earliest present time
// when there is expected present time support.
TEST_F(FrameTargeterWithExpectedPresentSupportTest, detectsEarlyPresent) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
    VsyncId vsyncId{333};
    TimePoint frameBeginTime(3000ms);
    constexpr Fps kRefreshRate = 60_Hz;
@@ -289,6 +345,7 @@ TEST_F(FrameTargeterWithExpectedPresentSupportTest, detectsEarlyPresent) {
}

TEST_F(FrameTargeterTest, detectsEarlyPresentTwoVsyncsAhead) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
    VsyncId vsyncId{444};
    TimePoint frameBeginTime(4000ms);
    constexpr Fps kRefreshRate = 120_Hz;
@@ -320,7 +377,52 @@ TEST_F(FrameTargeterTest, detectsEarlyPresentTwoVsyncsAhead) {
              target().expectedPresentTime() - kPeriod - kHwcMinWorkDuration);
}

TEST_F(FrameTargeterTest, detectsEarlyPresentNVsyncsAhead) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, true);
    VsyncId vsyncId{444};
    TimePoint frameBeginTime(4000ms);
    Fps refreshRate = 120_Hz;
    Period period = refreshRate.getPeriod();

    // The target is not early while past present fences are pending.
    for (int n = 5; n-- > 0;) {
        const Frame frame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate);
        EXPECT_FALSE(wouldPresentEarly(period));
        EXPECT_FALSE(target().earliestPresentTime());
    }

    Frame frame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate);
    auto fence = frame.end();
    frameBeginTime += period;
    fence->signalForTest(frameBeginTime.ns());

    // The target is two VSYNCs ahead, so the past present fence is still pending.
    EXPECT_FALSE(wouldPresentEarly(period));
    EXPECT_FALSE(target().earliestPresentTime());

    { const Frame frame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate); }

    Frame oneEarlyPresentFrame(this, vsyncId++, frameBeginTime, 10ms, refreshRate, refreshRate);
    // The target is early if the past present fence was signaled.
    EXPECT_TRUE(wouldPresentEarly(period));
    ASSERT_NE(std::nullopt, target().earliestPresentTime());
    EXPECT_EQ(*target().earliestPresentTime(),
              target().expectedPresentTime() - period - kHwcMinWorkDuration);

    fence = oneEarlyPresentFrame.end();
    frameBeginTime += period;
    fence->signalForTest(frameBeginTime.ns());

    // Change rate to track frame more than 2 vsyncs ahead
    refreshRate = 144_Hz;
    period = refreshRate.getPeriod();
    Frame onePresentEarlyFrame(this, vsyncId++, frameBeginTime, 16ms, refreshRate, refreshRate);
    // The target is not early as last frame as the past frame is tracked for pending.
    EXPECT_FALSE(wouldPresentEarly(period));
}

TEST_F(FrameTargeterTest, detectsEarlyPresentThreeVsyncsAhead) {
    SET_FLAG_FOR_TEST(flags::allow_n_vsyncs_in_targeter, false);
    TimePoint frameBeginTime(5000ms);
    constexpr Fps kRefreshRate = 144_Hz;
    constexpr Period kPeriod = kRefreshRate.getPeriod();
+2 −0
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@ void FlagManager::dump(std::string& result) const {
    DUMP_READ_ONLY_FLAG(graphite_renderengine);
    DUMP_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed);
    DUMP_READ_ONLY_FLAG(deprecate_vsync_sf);
    DUMP_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter);

#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -234,6 +235,7 @@ FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, "");
FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite")
FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, "");
FLAG_MANAGER_READ_ONLY_FLAG(deprecate_vsync_sf, "");
FLAG_MANAGER_READ_ONLY_FLAG(allow_n_vsyncs_in_targeter, "");

/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
+1 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ public:
    bool graphite_renderengine() const;
    bool latch_unsignaled_with_auto_refresh_changed() const;
    bool deprecate_vsync_sf() const;
    bool allow_n_vsyncs_in_targeter() const;

protected:
    // overridden for unit tests
Loading