diff options
author | 2023-05-03 23:58:43 +0000 | |
---|---|---|
committer | 2023-05-10 03:47:20 +0000 | |
commit | 0e7d8fde28f67650ce663f3f3e43f9377dc90d50 (patch) | |
tree | ac629b033b8c1c9260a5ec2b01a5cf5b2cbbf90e | |
parent | eb7596b865f35d9498e8d1e0f4169018cf423736 (diff) |
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
-rw-r--r-- | libs/gui/Android.bp | 1 | ||||
-rw-r--r-- | libs/gui/FenceMonitor.cpp | 89 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 83 | ||||
-rw-r--r-- | libs/gui/include/gui/FenceMonitor.h | 44 | ||||
-rw-r--r-- | libs/renderengine/skia/SkiaRenderEngine.cpp | 17 |
5 files changed, 150 insertions, 84 deletions
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 <gui/FenceMonitor.h> +#include <gui/TraceUtils.h> +#include <log/log.h> + +#include <thread> + +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>& fence) { + char message[64]; + + std::lock_guard<std::mutex> 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> fence; + uint32_t fenceNum; + { + std::unique_lock<std::mutex> 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<std::mutex> 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 <android/gui/DisplayStatInfo.h> #include <android/native_window.h> +#include <gui/FenceMonitor.h> #include <gui/TraceUtils.h> #include <utils/Log.h> #include <utils/NativeHandle.h> @@ -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>& fence) { - char message[64]; - - std::lock_guard<std::mutex> 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> fence; - uint32_t fenceNum; - { - std::unique_lock<std::mutex> 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<std::mutex> lock(mMutex); - mQueue.pop_front(); - mFencesSignaled++; - ATRACE_INT(mName, int32_t(mQueue.size())); - } - } - - const char* mName; - uint32_t mFencesQueued; - uint32_t mFencesSignaled; - std::deque<sp<Fence>> 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<BatchBuffer>* buffers) { sp<GraphicBuffer>& 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> 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 <cstdint> +#include <deque> +#include <mutex> + +#include <ui/Fence.h> + +namespace android::gui { + +class FenceMonitor { +public: + explicit FenceMonitor(const char* name); + void queueFence(const sp<Fence>& fence); + +private: + void loop(); + void threadLoop(); + + const char* mName; + uint32_t mFencesQueued; + uint32_t mFencesSignaled; + std::deque<sp<Fence>> 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 <SkPath.h> #include <SkPoint.h> #include <SkPoint3.h> +#include <SkRRect.h> #include <SkRect.h> #include <SkRefCnt.h> #include <SkRegion.h> -#include <SkRRect.h> #include <SkRuntimeEffect.h> #include <SkSamplingOptions.h> #include <SkScalar.h> @@ -51,9 +51,11 @@ #include <SkString.h> #include <SkSurface.h> #include <SkTileMode.h> -#include <src/core/SkTraceEventCommon.h> #include <android-base/stringprintf.h> +#include <gui/FenceMonitor.h> #include <gui/TraceUtils.h> +#include <pthread.h> +#include <src/core/SkTraceEventCommon.h> #include <sync/sync.h> #include <ui/BlurRegion.h> #include <ui/DataspaceUtils.h> @@ -63,6 +65,7 @@ #include <cmath> #include <cstdint> +#include <deque> #include <memory> #include <numeric> @@ -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<Fence>::make(std::move(drawFence))); + auto drawFence = sp<Fence>::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 { |