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

Commit 3afb3972 authored by Alec Mouri's avatar Alec Mouri
Browse files

Make GPU duration metrics more accurate for Vulkan

In the Vulkan pipeline, the GPU start time was measured to be when
swapBuffers starts. But the command queue has already been submitted at
this point, which means that the GPU work would already have begun. This
means that it's possible to measure a negative time since for very light
GPU workloads, the GPU fence can fire prior to CPU making it to
swapBuffers().

To compensate, instead measure from after skia completed submitting GPU
commands, until the GPU fence fires. Since it is theoretically possible
for GPU work to complete if the render thread gets descheduled
immediately after submitting the GPU, we also add some clamping to
ensure that the duration from command submission -> completion of GPU
work is nonnegative.

Bug: 230713131
Test: atest android.view.cts.FrameMetricsListenerTest
Change-Id: Ia30b7732eaab71e4e29766f788d5cd94ec63c38a
parent d7df1b28
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -254,8 +254,9 @@ public final class FrameMetrics {
        int GPU_COMPLETED = 19;
        int SWAP_BUFFERS_COMPLETED = 20;
        int DISPLAY_PRESENT_TIME = 21;
        int COMMAND_SUBMISSION_COMPLETED = 22;

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

@@ -291,7 +292,7 @@ public final class FrameMetrics {
        // RESERVED VSYNC_TIMESTAMP
        0, 0,
        // GPU_DURATION
        Index.SWAP_BUFFERS, Index.GPU_COMPLETED,
        Index.COMMAND_SUBMISSION_COMPLETED, Index.GPU_COMPLETED,
        // DEADLINE
        Index.INTENDED_VSYNC, Index.FRAME_DEADLINE,
    };
+24 −10
Original line number Diff line number Diff line
@@ -20,19 +20,33 @@
namespace android {
namespace uirenderer {

const std::array FrameInfoNames{
        "Flags",               "FrameTimelineVsyncId",   "IntendedVsync",
        "Vsync",               "InputEventId",           "HandleInputStart",
        "AnimationStart",      "PerformTraversalsStart", "DrawStart",
        "FrameDeadline",       "FrameInterval",          "FrameStartTime",
        "SyncQueued",          "SyncStart",              "IssueDrawCommandsStart",
        "SwapBuffers",         "FrameCompleted",         "DequeueBufferDuration",
        "QueueBufferDuration", "GpuCompleted",           "SwapBuffersCompleted",
const std::array FrameInfoNames{"Flags",
                                "FrameTimelineVsyncId",
                                "IntendedVsync",
                                "Vsync",
                                "InputEventId",
                                "HandleInputStart",
                                "AnimationStart",
                                "PerformTraversalsStart",
                                "DrawStart",
                                "FrameDeadline",
                                "FrameInterval",
                                "FrameStartTime",
                                "SyncQueued",
                                "SyncStart",
                                "IssueDrawCommandsStart",
                                "SwapBuffers",
                                "FrameCompleted",
                                "DequeueBufferDuration",
                                "QueueBufferDuration",
                                "GpuCompleted",
                                "SwapBuffersCompleted",
                                "DisplayPresentTime",
                                "CommandSubmissionCompleted"

};

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

void FrameInfo::importUiThreadInfo(int64_t* info) {
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ enum class FrameInfoIndex {
    GpuCompleted,
    SwapBuffersCompleted,
    DisplayPresentTime,
    CommandSubmissionCompleted,

    // Must be the last value!
    // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
+14 −16
Original line number Diff line number Diff line
@@ -16,8 +16,15 @@

#include "SkiaOpenGLPipeline.h"

#include <GrBackendSurface.h>
#include <SkBlendMode.h>
#include <SkImageInfo.h>
#include <cutils/properties.h>
#include <gui/TraceUtils.h>
#include <strings.h>

#include "DeferredLayerUpdater.h"
#include "FrameInfo.h"
#include "LayerDrawable.h"
#include "LightingInfo.h"
#include "SkiaPipeline.h"
@@ -27,17 +34,9 @@
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
#include "renderthread/Frame.h"
#include "renderthread/IRenderPipeline.h"
#include "utils/GLUtils.h"

#include <GLES3/gl3.h>

#include <GrBackendSurface.h>
#include <SkBlendMode.h>
#include <SkImageInfo.h>

#include <cutils/properties.h>
#include <strings.h>

using namespace android::uirenderer::renderthread;

namespace android {
@@ -69,12 +68,11 @@ Frame SkiaOpenGLPipeline::getFrame() {
    return mEglManager.beginFrame(mEglSurface);
}

bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
                              const LightGeometry& lightGeometry,
                              LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
                              bool opaque, const LightInfo& lightInfo,
                              const std::vector<sp<RenderNode>>& renderNodes,
                              FrameInfoVisualizer* profiler) {
IRenderPipeline::DrawResult SkiaOpenGLPipeline::draw(
        const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
        const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
        const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
        const std::vector<sp<RenderNode>>& renderNodes, FrameInfoVisualizer* profiler) {
    if (!isCapturingSkp()) {
        mEglManager.damageFrame(frame, dirty);
    }
@@ -129,7 +127,7 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
        dumpResourceCacheUsage();
    }

    return true;
    return {true, IRenderPipeline::DrawResult::kUnknownTime};
}

bool SkiaOpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
+8 −5
Original line number Diff line number Diff line
@@ -36,9 +36,12 @@ public:

    renderthread::MakeCurrentResult makeCurrent() override;
    renderthread::Frame getFrame() override;
    bool draw(const renderthread::Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
              const LightGeometry& lightGeometry, LayerUpdateQueue* layerUpdateQueue,
              const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
    renderthread::IRenderPipeline::DrawResult draw(const renderthread::Frame& frame,
                                                   const SkRect& screenDirty, const SkRect& dirty,
                                                   const LightGeometry& lightGeometry,
                                                   LayerUpdateQueue* layerUpdateQueue,
                                                   const Rect& contentDrawBounds, bool opaque,
                                                   const LightInfo& lightInfo,
                                                   const std::vector<sp<RenderNode> >& renderNodes,
                                                   FrameInfoVisualizer* profiler) override;
    GrSurfaceOrigin getSurfaceOrigin() override { return kBottomLeft_GrSurfaceOrigin; }
Loading