blob: 441811646bfb012f2441c9f74999f593c2d1550a [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
17#undef LOG_TAG
18#define LOG_TAG "FrameTracer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include "FrameTracer.h"
22
23#include <android-base/stringprintf.h>
Adithya Srinivasan64c4f5c2019-12-03 19:19:20 -080024#include <perfetto/trace/clock_snapshot.pbzero.h>
Mikael Pessa90092f42019-08-26 17:22:04 -070025
26#include <algorithm>
Raymond Chiu27b53722019-09-03 17:55:10 -070027#include <mutex>
Mikael Pessa90092f42019-08-26 17:22:04 -070028
29PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
30
31namespace android {
32
Adithya Srinivasan64c4f5c2019-12-03 19:19:20 -080033using Clock = perfetto::protos::pbzero::ClockSnapshot::Clock;
Mikael Pessa90092f42019-08-26 17:22:04 -070034void FrameTracer::initialize() {
Raymond Chiu27b53722019-09-03 17:55:10 -070035 std::call_once(mInitializationFlag, [this]() {
36 perfetto::TracingInitArgs args;
37 args.backends = perfetto::kSystemBackend;
38 perfetto::Tracing::Initialize(args);
39 registerDataSource();
40 });
Mikael Pessa90092f42019-08-26 17:22:04 -070041}
42
43void FrameTracer::registerDataSource() {
44 perfetto::DataSourceDescriptor dsd;
45 dsd.set_name(kFrameTracerDataSource);
46 FrameTracerDataSource::Register(dsd);
47}
48
Yiwei Zhang1a88c402019-11-18 10:43:58 -080049void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) {
50 FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) {
51 if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
Mikael Pessa90092f42019-08-26 17:22:04 -070052 std::lock_guard<std::mutex> lock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -080053 mTraceTracker[layerId].layerName = layerName;
Mikael Pessa90092f42019-08-26 17:22:04 -070054 }
55 });
56}
57
Yiwei Zhang1a88c402019-11-18 10:43:58 -080058void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
Mikael Pessa90092f42019-08-26 17:22:04 -070059 nsecs_t timestamp, FrameEvent::BufferEventType type,
60 nsecs_t duration) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080061 FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type,
Mikael Pessa90092f42019-08-26 17:22:04 -070062 duration](FrameTracerDataSource::TraceContext ctx) {
63 std::lock_guard<std::mutex> lock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -080064 if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
Mikael Pessa90092f42019-08-26 17:22:04 -070065 return;
66 }
67
68 // Handle any pending fences for this buffer.
Yiwei Zhang1a88c402019-11-18 10:43:58 -080069 tracePendingFencesLocked(ctx, layerId, bufferID);
Mikael Pessa90092f42019-08-26 17:22:04 -070070
71 // Complete current trace.
Yiwei Zhang1a88c402019-11-18 10:43:58 -080072 traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
Mikael Pessa90092f42019-08-26 17:22:04 -070073 });
74}
75
Yiwei Zhang1a88c402019-11-18 10:43:58 -080076void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
Mikael Pessa90092f42019-08-26 17:22:04 -070077 const std::shared_ptr<FenceTime>& fence,
78 FrameEvent::BufferEventType type, nsecs_t startTime) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080079 FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type,
Mikael Pessa90092f42019-08-26 17:22:04 -070080 startTime](FrameTracerDataSource::TraceContext ctx) {
81 const nsecs_t signalTime = fence->getSignalTime();
82 if (signalTime != Fence::SIGNAL_TIME_INVALID) {
83 std::lock_guard<std::mutex> lock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -080084 if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
Mikael Pessa90092f42019-08-26 17:22:04 -070085 return;
86 }
87
88 // Handle any pending fences for this buffer.
Yiwei Zhang1a88c402019-11-18 10:43:58 -080089 tracePendingFencesLocked(ctx, layerId, bufferID);
Mikael Pessa90092f42019-08-26 17:22:04 -070090
91 if (signalTime != Fence::SIGNAL_TIME_PENDING) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080092 traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime);
Mikael Pessa90092f42019-08-26 17:22:04 -070093 } else {
Yiwei Zhang1a88c402019-11-18 10:43:58 -080094 mTraceTracker[layerId].pendingFences[bufferID].push_back(
Mikael Pessa90092f42019-08-26 17:22:04 -070095 {.frameNumber = frameNumber,
96 .type = type,
97 .fence = fence,
98 .startTime = startTime});
99 }
100 }
101 });
102}
103
104void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800105 int32_t layerId, uint64_t bufferID) {
106 if (mTraceTracker[layerId].pendingFences.count(bufferID)) {
107 auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID];
Mikael Pessa90092f42019-08-26 17:22:04 -0700108 for (size_t i = 0; i < pendingFences.size(); ++i) {
109 auto& pendingFence = pendingFences[i];
110
111 nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
112 if (pendingFence.fence && pendingFence.fence->isValid()) {
113 signalTime = pendingFence.fence->getSignalTime();
114 if (signalTime == Fence::SIGNAL_TIME_PENDING) {
115 continue;
116 }
117 }
118
119 if (signalTime != Fence::SIGNAL_TIME_INVALID &&
120 systemTime() - signalTime < kFenceSignallingDeadline) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800121 traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type,
Mikael Pessa90092f42019-08-26 17:22:04 -0700122 pendingFence.startTime, signalTime);
123 }
124
125 pendingFences.erase(pendingFences.begin() + i);
126 --i;
127 }
128 }
129}
130
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800131void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
Mikael Pessa90092f42019-08-26 17:22:04 -0700132 uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
133 FrameEvent::BufferEventType type, nsecs_t duration) {
134 auto packet = ctx.NewTracePacket();
Adithya Srinivasan64c4f5c2019-12-03 19:19:20 -0800135 packet->set_timestamp_clock_id(Clock::MONOTONIC);
Mikael Pessa90092f42019-08-26 17:22:04 -0700136 packet->set_timestamp(timestamp);
137 auto* event = packet->set_graphics_frame_event()->set_buffer_event();
138 event->set_buffer_id(static_cast<uint32_t>(bufferID));
Adithya Srinivasan2e434382019-10-09 11:43:01 -0700139 if (frameNumber != UNSPECIFIED_FRAME_NUMBER) {
140 event->set_frame_number(frameNumber);
141 }
Mikael Pessa90092f42019-08-26 17:22:04 -0700142 event->set_type(type);
143
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800144 if (mTraceTracker.find(layerId) != mTraceTracker.end() &&
145 !mTraceTracker[layerId].layerName.empty()) {
146 const std::string& layerName = mTraceTracker[layerId].layerName;
Mikael Pessa90092f42019-08-26 17:22:04 -0700147 event->set_layer_name(layerName.c_str(), layerName.size());
148 }
149
150 if (duration > 0) {
151 event->set_duration_ns(duration);
152 }
153}
154
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800155void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
Mikael Pessa90092f42019-08-26 17:22:04 -0700156 uint64_t bufferID, uint64_t frameNumber,
157 FrameEvent::BufferEventType type, nsecs_t startTime,
158 nsecs_t endTime) {
159 nsecs_t timestamp = endTime;
160 nsecs_t duration = 0;
161 if (startTime > 0 && startTime < endTime) {
162 timestamp = startTime;
163 duration = endTime - startTime;
164 }
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800165 traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
Mikael Pessa90092f42019-08-26 17:22:04 -0700166}
167
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800168void FrameTracer::onDestroy(int32_t layerId) {
Mikael Pessa90092f42019-08-26 17:22:04 -0700169 std::lock_guard<std::mutex> traceLock(mTraceMutex);
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800170 mTraceTracker.erase(layerId);
Mikael Pessa90092f42019-08-26 17:22:04 -0700171}
172
173std::string FrameTracer::miniDump() {
174 std::string result = "FrameTracer miniDump:\n";
175 std::lock_guard<std::mutex> lock(mTraceMutex);
176 android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
177 mTraceTracker.size());
178 return result;
179}
180
181} // namespace android