Add ADPF GPU duration reporting for SurfaceFlinger
Gated the new GPU implementation behind the adpf_gpu_sf
flag. Changes below are not gated:
Changed to check if RenderEngine is used instead of
client composition as the latter doesn't always
trigger GPU composition (cache). And we should not set
the flag early in chooseCompositionStrategy, since if
HWC fails, it will get reset and still run on GPU.
Fixed PowerAdvisor::setGpuFenceTime code to truely
respect other displays' delay on start time
Bug: 284324521
Test: atest libcompositionengine_test PowerAdvisorTest
Change-Id: I498401d18d9886cda5c6e82243fe7cdad46e091f
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 6428d08..3d35704 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -252,10 +252,6 @@
auto& hwc = getCompositionEngine().getHwComposer();
const bool requiresClientComposition = anyLayersRequireClientComposition();
- if (isPowerHintSessionEnabled()) {
- mPowerAdvisor->setRequiresClientComposition(mId, requiresClientComposition);
- }
-
const TimePoint hwcValidateStartTime = TimePoint::now();
if (status_t result = hwc.getDeviceCompositionChanges(*halDisplayId, requiresClientComposition,
@@ -416,10 +412,20 @@
return mPowerAdvisor != nullptr && mPowerAdvisor->usePowerHintSession();
}
+// For ADPF GPU v0 this is expected to set start time to when the GPU commands are submitted with
+// fence returned, i.e. when RenderEngine flushes the commands and returns the draw fence.
+void Display::setHintSessionGpuStart(TimePoint startTime) {
+ mPowerAdvisor->setGpuStartTime(mId, startTime);
+}
+
void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) {
mPowerAdvisor->setGpuFenceTime(mId, std::move(gpuFence));
}
+void Display::setHintSessionRequiresRenderEngine(bool requiresRenderEngine) {
+ mPowerAdvisor->setRequiresRenderEngine(mId, requiresRenderEngine);
+}
+
void Display::finishFrame(GpuCompositionResult&& result) {
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 7b5b49d..91f51e9 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -464,6 +464,10 @@
setColorTransform(refreshArgs);
beginFrame();
+ if (isPowerHintSessionEnabled()) {
+ // always reset the flag before the composition prediction
+ setHintSessionRequiresRenderEngine(false);
+ }
GpuCompositionResult result;
const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
if (predictCompositionStrategy) {
@@ -1248,8 +1252,7 @@
if (!optReadyFence) {
return;
}
-
- if (isPowerHintSessionEnabled()) {
+ if (isPowerHintSessionEnabled() && !FlagManager::getInstance().adpf_gpu_sf()) {
// get fence end time to know when gpu is complete in display
setHintSessionGpuFence(
std::make_unique<FenceTime>(sp<Fence>::make(dup(optReadyFence->get()))));
@@ -1393,8 +1396,20 @@
// If rendering was not successful, remove the request from the cache.
mClientCompositionRequestCache->remove(tex->getBuffer()->getId());
}
-
const auto fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
+ if (isPowerHintSessionEnabled()) {
+ if (fence != Fence::NO_FENCE && fence->isValid() &&
+ !outputCompositionState.reusedClientComposition) {
+ setHintSessionRequiresRenderEngine(true);
+ if (FlagManager::getInstance().adpf_gpu_sf()) {
+ // the order of the two calls here matters as we should check if the previously
+ // tracked fence has signaled first and archive the previous start time
+ setHintSessionGpuStart(TimePoint::now());
+ setHintSessionGpuFence(
+ std::make_unique<FenceTime>(sp<Fence>::make(dup(fence->get()))));
+ }
+ }
+ }
if (auto timeStats = getCompositionEngine().getTimeStats()) {
if (fence->isValid()) {
@@ -1577,10 +1592,18 @@
// The base class does nothing with this call.
}
+void Output::setHintSessionGpuStart(TimePoint) {
+ // The base class does nothing with this call.
+}
+
void Output::setHintSessionGpuFence(std::unique_ptr<FenceTime>&&) {
// The base class does nothing with this call.
}
+void Output::setHintSessionRequiresRenderEngine(bool) {
+ // The base class does nothing with this call.
+}
+
bool Output::isPowerHintSessionEnabled() {
return false;
}