From 899dcdb63ad9cb81d1987e89be08dc9603aad89b Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Tue, 15 Jun 2021 16:56:21 -0700 Subject: SF: change acquired buffers based on the current refresh rate BLASTBufferQueue set the max acquired buffers based on SF vsync configuration (sf.duration and app.duration). This is calculated based on the max supported refresh rate on the device, and it turn is propogated to apps via min_undequeued_buffers to the app could allocate enough buffers for maintaining the pipeline SF expects. This leads to a higher latency when the device is running in a lower refresh rate as there are more buffers on the buffer queue then required. In this change we are holding on the these "extra buffers" and not releasing them back to the buffer queue so the app would use the number of buffers it needs based on the current refresh rate, and to avoid having unnecessary long latency. Bug: 188553729 Test: Run backpressure based game on 60Hz and 120Hz and collect systraces Change-Id: I9d4e6278f0ddd28008ac437ab0576aa79d05166a --- libs/gui/BLASTBufferQueue.cpp | 52 ++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 15 deletions(-) (limited to 'libs/gui/BLASTBufferQueue.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 8024482531..52d3fa33f0 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -159,9 +159,7 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const spsetDefaultBufferFormat(convertBufferFormat(format)); mBufferItemConsumer->setBlastBufferQueue(this); - int extraBufferCount = 0; - ComposerService::getComposerService()->getExtraBufferCount(&extraBufferCount); - mMaxAcquiredBuffers = 1 + extraBufferCount; + ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers); mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers); mTransformHint = mSurfaceControl->getTransformHint(); @@ -308,18 +306,20 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp context, uint64_t graphicBufferId, - const sp& releaseFence, uint32_t transformHint) { + const sp& releaseFence, uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) { sp blastBufferQueue = context.promote(); ALOGV("releaseBufferCallbackThunk graphicBufferId=%" PRIu64 " blastBufferQueue=%s", graphicBufferId, blastBufferQueue ? "alive" : "dead"); if (blastBufferQueue) { - blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint); + blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint, + currentMaxAcquiredBufferCount); } } void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId, - const sp& releaseFence, - uint32_t transformHint) { + const sp& releaseFence, uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; BQA_LOGV("releaseBufferCallback graphicBufferId=%" PRIu64, graphicBufferId); @@ -330,15 +330,36 @@ void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId, mBufferItemConsumer->setTransformHint(mTransformHint); } - auto it = mSubmitted.find(graphicBufferId); - if (it == mSubmitted.end()) { - BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64, - graphicBufferId); - return; + // Calculate how many buffers we need to hold before we release them back + // to the buffer queue. This will prevent higher latency when we are running + // on a lower refresh rate than the max supported. We only do that for EGL + // clients as others don't care about latency + const bool isEGL = [&] { + const auto it = mSubmitted.find(graphicBufferId); + return it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL; + }(); + + const auto numPendingBuffersToHold = + isEGL ? std::max(0u, mMaxAcquiredBuffers - currentMaxAcquiredBufferCount) : 0; + mPendingRelease.emplace_back(ReleasedBuffer{graphicBufferId, releaseFence}); + + // Release all buffers that are beyond the ones that we need to hold + while (mPendingRelease.size() > numPendingBuffersToHold) { + const auto releaseBuffer = mPendingRelease.front(); + mPendingRelease.pop_front(); + auto it = mSubmitted.find(releaseBuffer.bufferId); + if (it == mSubmitted.end()) { + BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64, + graphicBufferId); + return; + } + + mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); + mSubmitted.erase(it); } - mBufferItemConsumer->releaseBuffer(it->second, releaseFence); - mSubmitted.erase(it); + ATRACE_INT("PendingRelease", mPendingRelease.size()); + mNumAcquired--; processNextBufferLocked(false /* useNextTransaction */); mCallbackCV.notify_all(); @@ -420,7 +441,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4); t->setBuffer(mSurfaceControl, buffer, releaseBufferCallback); t->setDataspace(mSurfaceControl, static_cast(bufferItem.mDataSpace)); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); -- cgit v1.2.3-59-g8ed1b