From 0e7d8fde28f67650ce663f3f3e43f9377dc90d50 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Wed, 3 May 2023 23:58:43 +0000 Subject: Add tracing thread for RenderEngine's fences RenderEngine doesn't always render to FramebufferSurface, so tracing that is built into BufferQueue is lost. Add a tracing thread so that screenshots and caching can also have GPU work traced. Bug: 280684246 Bug: 269822044 Test: perfetto Change-Id: I067430f6b6b588dd3046d1cf66d0a3fc8465746d --- libs/gui/Android.bp | 1 + libs/gui/FenceMonitor.cpp | 89 +++++++++++++++++++++++++++++ libs/gui/Surface.cpp | 83 ++------------------------- libs/gui/include/gui/FenceMonitor.h | 44 ++++++++++++++ libs/renderengine/skia/SkiaRenderEngine.cpp | 17 ++++-- 5 files changed, 150 insertions(+), 84 deletions(-) create mode 100644 libs/gui/FenceMonitor.cpp create mode 100644 libs/gui/include/gui/FenceMonitor.h diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 80fed98434..bf34987b9e 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -217,6 +217,7 @@ cc_library_shared { "DebugEGLImageTracker.cpp", "DisplayEventDispatcher.cpp", "DisplayEventReceiver.cpp", + "FenceMonitor.cpp", "GLConsumer.cpp", "IConsumerListener.cpp", "IGraphicBufferConsumer.cpp", diff --git a/libs/gui/FenceMonitor.cpp b/libs/gui/FenceMonitor.cpp new file mode 100644 index 0000000000..230c81a0b3 --- /dev/null +++ b/libs/gui/FenceMonitor.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include +#include +#include + +#include + +namespace android::gui { + +FenceMonitor::FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) { + std::thread thread(&FenceMonitor::loop, this); + pthread_setname_np(thread.native_handle(), mName); + thread.detach(); +} + +void FenceMonitor::queueFence(const sp& fence) { + char message[64]; + + std::lock_guard lock(mMutex); + if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) { + snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued); + ATRACE_NAME(message); + // Need an increment on both to make the trace number correct. + mFencesQueued++; + mFencesSignaled++; + return; + } + snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued); + ATRACE_NAME(message); + + mQueue.push_back(fence); + mCondition.notify_one(); + mFencesQueued++; + ATRACE_INT(mName, int32_t(mQueue.size())); +} + +void FenceMonitor::loop() { + while (true) { + threadLoop(); + } +} + +void FenceMonitor::threadLoop() { + sp fence; + uint32_t fenceNum; + { + std::unique_lock lock(mMutex); + while (mQueue.empty()) { + mCondition.wait(lock); + } + fence = mQueue[0]; + fenceNum = mFencesSignaled; + } + { + char message[64]; + snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum); + ATRACE_NAME(message); + + status_t result = fence->waitForever(message); + if (result != OK) { + ALOGE("Error waiting for fence: %d", result); + } + } + { + std::lock_guard lock(mMutex); + mQueue.pop_front(); + mFencesSignaled++; + ATRACE_INT(mName, int32_t(mQueue.size())); + } +} + +} // namespace android::gui \ No newline at end of file diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index a5cf8d6bf0..3a1e600f46 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -545,82 +546,6 @@ int Surface::setSwapInterval(int interval) { return NO_ERROR; } -class FenceMonitor { -public: - explicit FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) { - std::thread thread(&FenceMonitor::loop, this); - pthread_setname_np(thread.native_handle(), mName); - thread.detach(); - } - - void queueFence(const sp& fence) { - char message[64]; - - std::lock_guard lock(mMutex); - if (fence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) { - snprintf(message, sizeof(message), "%s fence %u has signaled", mName, mFencesQueued); - ATRACE_NAME(message); - // Need an increment on both to make the trace number correct. - mFencesQueued++; - mFencesSignaled++; - return; - } - snprintf(message, sizeof(message), "Trace %s fence %u", mName, mFencesQueued); - ATRACE_NAME(message); - - mQueue.push_back(fence); - mCondition.notify_one(); - mFencesQueued++; - ATRACE_INT(mName, int32_t(mQueue.size())); - } - -private: -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wmissing-noreturn" - void loop() { - while (true) { - threadLoop(); - } - } -#pragma clang diagnostic pop - - void threadLoop() { - sp fence; - uint32_t fenceNum; - { - std::unique_lock lock(mMutex); - while (mQueue.empty()) { - mCondition.wait(lock); - } - fence = mQueue[0]; - fenceNum = mFencesSignaled; - } - { - char message[64]; - snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum); - ATRACE_NAME(message); - - status_t result = fence->waitForever(message); - if (result != OK) { - ALOGE("Error waiting for fence: %d", result); - } - } - { - std::lock_guard lock(mMutex); - mQueue.pop_front(); - mFencesSignaled++; - ATRACE_INT(mName, int32_t(mQueue.size())); - } - } - - const char* mName; - uint32_t mFencesQueued; - uint32_t mFencesSignaled; - std::deque> mQueue; - std::condition_variable mCondition; - std::mutex mMutex; -}; - void Surface::getDequeueBufferInputLocked( IGraphicBufferProducer::DequeueBufferInput* dequeueInput) { LOG_ALWAYS_FATAL_IF(dequeueInput == nullptr, "input is null"); @@ -694,7 +619,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) { ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf); if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) { - static FenceMonitor hwcReleaseThread("HWC release"); + static gui::FenceMonitor hwcReleaseThread("HWC release"); hwcReleaseThread.queueFence(fence); } @@ -893,7 +818,7 @@ int Surface::dequeueBuffers(std::vector* buffers) { sp& gbuf(mSlots[slot].buffer); if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) { - static FenceMonitor hwcReleaseThread("HWC release"); + static gui::FenceMonitor hwcReleaseThread("HWC release"); hwcReleaseThread.queueFence(output.fence); } @@ -1163,7 +1088,7 @@ void Surface::onBufferQueuedLocked(int slot, sp fence, mQueueBufferCondition.broadcast(); if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) { - static FenceMonitor gpuCompletionThread("GPU completion"); + static gui::FenceMonitor gpuCompletionThread("GPU completion"); gpuCompletionThread.queueFence(fence); } } diff --git a/libs/gui/include/gui/FenceMonitor.h b/libs/gui/include/gui/FenceMonitor.h new file mode 100644 index 0000000000..62ceddee5f --- /dev/null +++ b/libs/gui/include/gui/FenceMonitor.h @@ -0,0 +1,44 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include + +namespace android::gui { + +class FenceMonitor { +public: + explicit FenceMonitor(const char* name); + void queueFence(const sp& fence); + +private: + void loop(); + void threadLoop(); + + const char* mName; + uint32_t mFencesQueued; + uint32_t mFencesSignaled; + std::deque> mQueue; + std::condition_variable mCondition; + std::mutex mMutex; +}; + +} // namespace android::gui \ No newline at end of file diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index cfea85f98b..5854135afe 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -39,10 +39,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -51,9 +51,11 @@ #include #include #include -#include #include +#include #include +#include +#include #include #include #include @@ -63,6 +65,7 @@ #include #include +#include #include #include @@ -229,7 +232,6 @@ static inline SkM44 getSkM44(const android::mat4& matrix) { static inline SkPoint3 getSkPoint3(const android::vec3& vector) { return SkPoint3::Make(vector.x, vector.y, vector.z); } - } // namespace namespace android { @@ -1134,8 +1136,13 @@ void SkiaRenderEngine::drawLayersInternal( activeSurface->flush(); } - base::unique_fd drawFence = flushAndSubmit(grContext); - resultPromise->set_value(sp::make(std::move(drawFence))); + auto drawFence = sp::make(flushAndSubmit(grContext)); + + if (ATRACE_ENABLED()) { + static gui::FenceMonitor sMonitor("RE Completion"); + sMonitor.queueFence(drawFence); + } + resultPromise->set_value(std::move(drawFence)); } size_t SkiaRenderEngine::getMaxTextureSize() const { -- cgit v1.2.3-59-g8ed1b