blob: b986f3844a115a1b3a8718cd0ff6aaad97dcef71 [file] [log] [blame]
Mikael Pessa90092f42019-08-26 17:22:04 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Mikael Pessa90092f42019-08-26 17:22:04 -070021#undef LOG_TAG
22#define LOG_TAG "FrameTracer"
23#define ATRACE_TAG ATRACE_TAG_GRAPHICS
24
25#include "FrameTracer.h"
26
27#include <android-base/stringprintf.h>
Adithya Srinivasan64c4f5c2019-12-03 19:19:20 -080028#include <perfetto/trace/clock_snapshot.pbzero.h>
Mikael Pessa90092f42019-08-26 17:22:04 -070029
30#include <algorithm>
Raymond Chiu27b53722019-09-03 17:55:10 -070031#include <mutex>
Mikael Pessa90092f42019-08-26 17:22:04 -070032
33PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
34
35namespace android {
36
Adithya Srinivasan64c4f5c2019-12-03 19:19:20 -080037using Clock = perfetto::protos::pbzero::ClockSnapshot::Clock;
Mikael Pessa90092f42019-08-26 17:22:04 -070038void FrameTracer::initialize() {
Raymond Chiu27b53722019-09-03 17:55:10 -070039 std::call_once(mInitializationFlag, [this]() {
40 perfetto::TracingInitArgs args;
41 args.backends = perfetto::kSystemBackend;
42 perfetto::Tracing::Initialize(args);
43 registerDataSource();
44 });
Mikael Pessa90092f42019-08-26 17:22:04 -070045}
46
47void FrameTracer::registerDataSource() {
48 perfetto::DataSourceDescriptor dsd;
49 dsd.set_name(kFrameTracerDataSource);
50 FrameTracerDataSource::Register(dsd);
51}
52
Yiwei Zhang1a88c402019-11-18 10:43:58 -080053void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) {
54 FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) {
55 if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
Mikael Pessa90092f42019-08-26 17:22:04 -070056 std::lock_guard<std::mutex> lock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -080057 mTraceTracker[layerId].layerName = layerName;
Mikael Pessa90092f42019-08-26 17:22:04 -070058 }
59 });
60}
61
Yiwei Zhang1a88c402019-11-18 10:43:58 -080062void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
Mikael Pessa90092f42019-08-26 17:22:04 -070063 nsecs_t timestamp, FrameEvent::BufferEventType type,
64 nsecs_t duration) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080065 FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type,
Mikael Pessa90092f42019-08-26 17:22:04 -070066 duration](FrameTracerDataSource::TraceContext ctx) {
67 std::lock_guard<std::mutex> lock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -080068 if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
Mikael Pessa90092f42019-08-26 17:22:04 -070069 return;
70 }
71
72 // Handle any pending fences for this buffer.
Yiwei Zhang1a88c402019-11-18 10:43:58 -080073 tracePendingFencesLocked(ctx, layerId, bufferID);
Mikael Pessa90092f42019-08-26 17:22:04 -070074
75 // Complete current trace.
Yiwei Zhang1a88c402019-11-18 10:43:58 -080076 traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
Mikael Pessa90092f42019-08-26 17:22:04 -070077 });
78}
79
Yiwei Zhang1a88c402019-11-18 10:43:58 -080080void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
Mikael Pessa90092f42019-08-26 17:22:04 -070081 const std::shared_ptr<FenceTime>& fence,
82 FrameEvent::BufferEventType type, nsecs_t startTime) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080083 FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type,
Mikael Pessa90092f42019-08-26 17:22:04 -070084 startTime](FrameTracerDataSource::TraceContext ctx) {
85 const nsecs_t signalTime = fence->getSignalTime();
86 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
87 std::lock_guard<std::mutex> lock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -080088 if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
Mikael Pessa90092f42019-08-26 17:22:04 -070089 return;
90 }
91
92 // Handle any pending fences for this buffer.
Yiwei Zhang1a88c402019-11-18 10:43:58 -080093 tracePendingFencesLocked(ctx, layerId, bufferID);
Mikael Pessa90092f42019-08-26 17:22:04 -070094
95 if (signalTime != Fence::SIGNAL_TIME_PENDING) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080096 traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime);
Mikael Pessa90092f42019-08-26 17:22:04 -070097 } else {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080098 mTraceTracker[layerId].pendingFences[bufferID].push_back(
Mikael Pessa90092f42019-08-26 17:22:04 -070099 {.frameNumber = frameNumber,
100 .type = type,
101 .fence = fence,
102 .startTime = startTime});
103 }
104 }
105 });
106}
107
108void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800109 int32_t layerId, uint64_t bufferID) {
110 if (mTraceTracker[layerId].pendingFences.count(bufferID)) {
111 auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID];
Mikael Pessa90092f42019-08-26 17:22:04 -0700112 for (size_t i = 0; i < pendingFences.size(); ++i) {
113 auto& pendingFence = pendingFences[i];
114
115 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
116 if (pendingFence.fence && pendingFence.fence->isValid()) {
117 signalTime = pendingFence.fence->getSignalTime();
118 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
119 continue;
120 }
121 }
122
123 if (signalTime != Fence::SIGNAL_TIME_INVALID &&
124 systemTime() - signalTime < kFenceSignallingDeadline) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800125 traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type,
Mikael Pessa90092f42019-08-26 17:22:04 -0700126 pendingFence.startTime, signalTime);
127 }
128
129 pendingFences.erase(pendingFences.begin() + i);
130 --i;
131 }
132 }
133}
134
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800135void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
Mikael Pessa90092f42019-08-26 17:22:04 -0700136 uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
137 FrameEvent::BufferEventType type, nsecs_t duration) {
138 auto packet = ctx.NewTracePacket();
Adithya Srinivasan64c4f5c2019-12-03 19:19:20 -0800139 packet->set_timestamp_clock_id(Clock::MONOTONIC);
Mikael Pessa90092f42019-08-26 17:22:04 -0700140 packet->set_timestamp(timestamp);
141 auto* event = packet->set_graphics_frame_event()->set_buffer_event();
142 event->set_buffer_id(static_cast<uint32_t>(bufferID));
Adithya Srinivasan2e434382019-10-09 11:43:01 -0700143 if (frameNumber != UNSPECIFIED_FRAME_NUMBER) {
144 event->set_frame_number(frameNumber);
145 }
Mikael Pessa90092f42019-08-26 17:22:04 -0700146 event->set_type(type);
147
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800148 if (mTraceTracker.find(layerId) != mTraceTracker.end() &&
149 !mTraceTracker[layerId].layerName.empty()) {
150 const std::string& layerName = mTraceTracker[layerId].layerName;
Mikael Pessa90092f42019-08-26 17:22:04 -0700151 event->set_layer_name(layerName.c_str(), layerName.size());
152 }
153
154 if (duration > 0) {
155 event->set_duration_ns(duration);
156 }
157}
158
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800159void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
Mikael Pessa90092f42019-08-26 17:22:04 -0700160 uint64_t bufferID, uint64_t frameNumber,
161 FrameEvent::BufferEventType type, nsecs_t startTime,
162 nsecs_t endTime) {
163 nsecs_t timestamp = endTime;
164 nsecs_t duration = 0;
165 if (startTime > 0 && startTime < endTime) {
166 timestamp = startTime;
167 duration = endTime - startTime;
168 }
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800169 traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
Mikael Pessa90092f42019-08-26 17:22:04 -0700170}
171
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800172void FrameTracer::onDestroy(int32_t layerId) {
Mikael Pessa90092f42019-08-26 17:22:04 -0700173 std::lock_guard<std::mutex> traceLock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800174 mTraceTracker.erase(layerId);
Mikael Pessa90092f42019-08-26 17:22:04 -0700175}
176
177std::string FrameTracer::miniDump() {
178 std::string result = "FrameTracer miniDump:\n";
179 std::lock_guard<std::mutex> lock(mTraceMutex);
180 android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
181 mTraceTracker.size());
182 return result;
183}
184
185} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800186
187// TODO(b/129481165): remove the #pragma below and fix conversion issues
188#pragma clang diagnostic pop // ignored "-Wconversion"