1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
18*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push
19*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion"
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
22*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "FrameTracer"
23*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
24*38e8c45fSAndroid Build Coastguard Worker
25*38e8c45fSAndroid Build Coastguard Worker #include "FrameTracer.h"
26*38e8c45fSAndroid Build Coastguard Worker
27*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <perfetto/common/builtin_clock.pbzero.h>
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker #include <algorithm>
31*38e8c45fSAndroid Build Coastguard Worker #include <mutex>
32*38e8c45fSAndroid Build Coastguard Worker
33*38e8c45fSAndroid Build Coastguard Worker PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
34*38e8c45fSAndroid Build Coastguard Worker
35*38e8c45fSAndroid Build Coastguard Worker namespace android {
36*38e8c45fSAndroid Build Coastguard Worker
initialize()37*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::initialize() {
38*38e8c45fSAndroid Build Coastguard Worker std::call_once(mInitializationFlag, [this]() {
39*38e8c45fSAndroid Build Coastguard Worker perfetto::TracingInitArgs args;
40*38e8c45fSAndroid Build Coastguard Worker args.backends = perfetto::kSystemBackend;
41*38e8c45fSAndroid Build Coastguard Worker perfetto::Tracing::Initialize(args);
42*38e8c45fSAndroid Build Coastguard Worker registerDataSource();
43*38e8c45fSAndroid Build Coastguard Worker });
44*38e8c45fSAndroid Build Coastguard Worker }
45*38e8c45fSAndroid Build Coastguard Worker
registerDataSource()46*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::registerDataSource() {
47*38e8c45fSAndroid Build Coastguard Worker perfetto::DataSourceDescriptor dsd;
48*38e8c45fSAndroid Build Coastguard Worker dsd.set_name(kFrameTracerDataSource);
49*38e8c45fSAndroid Build Coastguard Worker FrameTracerDataSource::Register(dsd);
50*38e8c45fSAndroid Build Coastguard Worker }
51*38e8c45fSAndroid Build Coastguard Worker
traceNewLayer(int32_t layerId,const std::string & layerName)52*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) {
53*38e8c45fSAndroid Build Coastguard Worker FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) {
54*38e8c45fSAndroid Build Coastguard Worker if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
55*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mTraceMutex);
56*38e8c45fSAndroid Build Coastguard Worker mTraceTracker[layerId].layerName = layerName;
57*38e8c45fSAndroid Build Coastguard Worker }
58*38e8c45fSAndroid Build Coastguard Worker });
59*38e8c45fSAndroid Build Coastguard Worker }
60*38e8c45fSAndroid Build Coastguard Worker
traceTimestamp(int32_t layerId,uint64_t bufferID,uint64_t frameNumber,nsecs_t timestamp,FrameEvent::BufferEventType type,nsecs_t duration)61*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
62*38e8c45fSAndroid Build Coastguard Worker nsecs_t timestamp, FrameEvent::BufferEventType type,
63*38e8c45fSAndroid Build Coastguard Worker nsecs_t duration) {
64*38e8c45fSAndroid Build Coastguard Worker FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type,
65*38e8c45fSAndroid Build Coastguard Worker duration](FrameTracerDataSource::TraceContext ctx) {
66*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mTraceMutex);
67*38e8c45fSAndroid Build Coastguard Worker if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
68*38e8c45fSAndroid Build Coastguard Worker return;
69*38e8c45fSAndroid Build Coastguard Worker }
70*38e8c45fSAndroid Build Coastguard Worker
71*38e8c45fSAndroid Build Coastguard Worker // Handle any pending fences for this buffer.
72*38e8c45fSAndroid Build Coastguard Worker tracePendingFencesLocked(ctx, layerId, bufferID);
73*38e8c45fSAndroid Build Coastguard Worker
74*38e8c45fSAndroid Build Coastguard Worker // Complete current trace.
75*38e8c45fSAndroid Build Coastguard Worker traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
76*38e8c45fSAndroid Build Coastguard Worker });
77*38e8c45fSAndroid Build Coastguard Worker }
78*38e8c45fSAndroid Build Coastguard Worker
traceFence(int32_t layerId,uint64_t bufferID,uint64_t frameNumber,const std::shared_ptr<FenceTime> & fence,FrameEvent::BufferEventType type,nsecs_t startTime)79*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber,
80*38e8c45fSAndroid Build Coastguard Worker const std::shared_ptr<FenceTime>& fence,
81*38e8c45fSAndroid Build Coastguard Worker FrameEvent::BufferEventType type, nsecs_t startTime) {
82*38e8c45fSAndroid Build Coastguard Worker FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type,
83*38e8c45fSAndroid Build Coastguard Worker startTime](FrameTracerDataSource::TraceContext ctx) {
84*38e8c45fSAndroid Build Coastguard Worker const nsecs_t signalTime = fence->getSignalTime();
85*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_INVALID) {
86*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mTraceMutex);
87*38e8c45fSAndroid Build Coastguard Worker if (mTraceTracker.find(layerId) == mTraceTracker.end()) {
88*38e8c45fSAndroid Build Coastguard Worker return;
89*38e8c45fSAndroid Build Coastguard Worker }
90*38e8c45fSAndroid Build Coastguard Worker
91*38e8c45fSAndroid Build Coastguard Worker // Handle any pending fences for this buffer.
92*38e8c45fSAndroid Build Coastguard Worker tracePendingFencesLocked(ctx, layerId, bufferID);
93*38e8c45fSAndroid Build Coastguard Worker
94*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_PENDING) {
95*38e8c45fSAndroid Build Coastguard Worker traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime);
96*38e8c45fSAndroid Build Coastguard Worker } else {
97*38e8c45fSAndroid Build Coastguard Worker mTraceTracker[layerId].pendingFences[bufferID].push_back(
98*38e8c45fSAndroid Build Coastguard Worker {.frameNumber = frameNumber,
99*38e8c45fSAndroid Build Coastguard Worker .type = type,
100*38e8c45fSAndroid Build Coastguard Worker .fence = fence,
101*38e8c45fSAndroid Build Coastguard Worker .startTime = startTime});
102*38e8c45fSAndroid Build Coastguard Worker }
103*38e8c45fSAndroid Build Coastguard Worker }
104*38e8c45fSAndroid Build Coastguard Worker });
105*38e8c45fSAndroid Build Coastguard Worker }
106*38e8c45fSAndroid Build Coastguard Worker
tracePendingFencesLocked(FrameTracerDataSource::TraceContext & ctx,int32_t layerId,uint64_t bufferID)107*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
108*38e8c45fSAndroid Build Coastguard Worker int32_t layerId, uint64_t bufferID) {
109*38e8c45fSAndroid Build Coastguard Worker if (mTraceTracker[layerId].pendingFences.count(bufferID)) {
110*38e8c45fSAndroid Build Coastguard Worker auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID];
111*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < pendingFences.size(); ++i) {
112*38e8c45fSAndroid Build Coastguard Worker auto& pendingFence = pendingFences[i];
113*38e8c45fSAndroid Build Coastguard Worker
114*38e8c45fSAndroid Build Coastguard Worker nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
115*38e8c45fSAndroid Build Coastguard Worker if (pendingFence.fence && pendingFence.fence->isValid()) {
116*38e8c45fSAndroid Build Coastguard Worker signalTime = pendingFence.fence->getSignalTime();
117*38e8c45fSAndroid Build Coastguard Worker if (signalTime == Fence::SIGNAL_TIME_PENDING) {
118*38e8c45fSAndroid Build Coastguard Worker continue;
119*38e8c45fSAndroid Build Coastguard Worker }
120*38e8c45fSAndroid Build Coastguard Worker }
121*38e8c45fSAndroid Build Coastguard Worker
122*38e8c45fSAndroid Build Coastguard Worker if (signalTime != Fence::SIGNAL_TIME_INVALID &&
123*38e8c45fSAndroid Build Coastguard Worker systemTime() - signalTime < kFenceSignallingDeadline) {
124*38e8c45fSAndroid Build Coastguard Worker traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type,
125*38e8c45fSAndroid Build Coastguard Worker pendingFence.startTime, signalTime);
126*38e8c45fSAndroid Build Coastguard Worker }
127*38e8c45fSAndroid Build Coastguard Worker
128*38e8c45fSAndroid Build Coastguard Worker pendingFences.erase(pendingFences.begin() + i);
129*38e8c45fSAndroid Build Coastguard Worker --i;
130*38e8c45fSAndroid Build Coastguard Worker }
131*38e8c45fSAndroid Build Coastguard Worker }
132*38e8c45fSAndroid Build Coastguard Worker }
133*38e8c45fSAndroid Build Coastguard Worker
traceLocked(FrameTracerDataSource::TraceContext & ctx,int32_t layerId,uint64_t bufferID,uint64_t frameNumber,nsecs_t timestamp,FrameEvent::BufferEventType type,nsecs_t duration)134*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
135*38e8c45fSAndroid Build Coastguard Worker uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
136*38e8c45fSAndroid Build Coastguard Worker FrameEvent::BufferEventType type, nsecs_t duration) {
137*38e8c45fSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
138*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
139*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(timestamp);
140*38e8c45fSAndroid Build Coastguard Worker auto* event = packet->set_graphics_frame_event()->set_buffer_event();
141*38e8c45fSAndroid Build Coastguard Worker event->set_buffer_id(static_cast<uint32_t>(bufferID));
142*38e8c45fSAndroid Build Coastguard Worker if (frameNumber != UNSPECIFIED_FRAME_NUMBER) {
143*38e8c45fSAndroid Build Coastguard Worker event->set_frame_number(frameNumber);
144*38e8c45fSAndroid Build Coastguard Worker }
145*38e8c45fSAndroid Build Coastguard Worker event->set_type(type);
146*38e8c45fSAndroid Build Coastguard Worker
147*38e8c45fSAndroid Build Coastguard Worker if (mTraceTracker.find(layerId) != mTraceTracker.end() &&
148*38e8c45fSAndroid Build Coastguard Worker !mTraceTracker[layerId].layerName.empty()) {
149*38e8c45fSAndroid Build Coastguard Worker const std::string& layerName = mTraceTracker[layerId].layerName;
150*38e8c45fSAndroid Build Coastguard Worker event->set_layer_name(layerName.c_str(), layerName.size());
151*38e8c45fSAndroid Build Coastguard Worker }
152*38e8c45fSAndroid Build Coastguard Worker
153*38e8c45fSAndroid Build Coastguard Worker if (duration > 0) {
154*38e8c45fSAndroid Build Coastguard Worker event->set_duration_ns(duration);
155*38e8c45fSAndroid Build Coastguard Worker }
156*38e8c45fSAndroid Build Coastguard Worker }
157*38e8c45fSAndroid Build Coastguard Worker
traceSpanLocked(FrameTracerDataSource::TraceContext & ctx,int32_t layerId,uint64_t bufferID,uint64_t frameNumber,FrameEvent::BufferEventType type,nsecs_t startTime,nsecs_t endTime)158*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId,
159*38e8c45fSAndroid Build Coastguard Worker uint64_t bufferID, uint64_t frameNumber,
160*38e8c45fSAndroid Build Coastguard Worker FrameEvent::BufferEventType type, nsecs_t startTime,
161*38e8c45fSAndroid Build Coastguard Worker nsecs_t endTime) {
162*38e8c45fSAndroid Build Coastguard Worker nsecs_t timestamp = endTime;
163*38e8c45fSAndroid Build Coastguard Worker nsecs_t duration = 0;
164*38e8c45fSAndroid Build Coastguard Worker if (startTime > 0 && startTime < endTime) {
165*38e8c45fSAndroid Build Coastguard Worker timestamp = startTime;
166*38e8c45fSAndroid Build Coastguard Worker duration = endTime - startTime;
167*38e8c45fSAndroid Build Coastguard Worker }
168*38e8c45fSAndroid Build Coastguard Worker traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration);
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker
onDestroy(int32_t layerId)171*38e8c45fSAndroid Build Coastguard Worker void FrameTracer::onDestroy(int32_t layerId) {
172*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> traceLock(mTraceMutex);
173*38e8c45fSAndroid Build Coastguard Worker mTraceTracker.erase(layerId);
174*38e8c45fSAndroid Build Coastguard Worker }
175*38e8c45fSAndroid Build Coastguard Worker
miniDump()176*38e8c45fSAndroid Build Coastguard Worker std::string FrameTracer::miniDump() {
177*38e8c45fSAndroid Build Coastguard Worker std::string result = "FrameTracer miniDump:\n";
178*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(mTraceMutex);
179*38e8c45fSAndroid Build Coastguard Worker android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
180*38e8c45fSAndroid Build Coastguard Worker mTraceTracker.size());
181*38e8c45fSAndroid Build Coastguard Worker return result;
182*38e8c45fSAndroid Build Coastguard Worker }
183*38e8c45fSAndroid Build Coastguard Worker
184*38e8c45fSAndroid Build Coastguard Worker } // namespace android
185*38e8c45fSAndroid Build Coastguard Worker
186*38e8c45fSAndroid Build Coastguard Worker // TODO(b/129481165): remove the #pragma below and fix conversion issues
187*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop // ignored "-Wconversion"
188