• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "frame_filter.h"
16 #include <cstdint>
17 #include <memory>
18 #include <cinttypes>
19 #include "process_filter.h"
20 
21 namespace SysTuning {
22 namespace TraceStreamer {
FrameFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)23 FrameFilter::FrameFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter) : FilterBase(dataCache, filter)
24 {
25 }
26 FrameFilter::~FrameFilter() = default;
27 
BeginVsyncEvent(const BytraceLine & line,uint64_t expectStart,uint64_t expectEnd,uint32_t vsyncId,uint32_t callStackSliceId)28 void FrameFilter::BeginVsyncEvent(const BytraceLine &line,
29                                   uint64_t expectStart,
30                                   uint64_t expectEnd,
31                                   uint32_t vsyncId,
32                                   uint32_t callStackSliceId)
33 {
34     auto frame = std::make_shared<FrameSlice>();
35     frame->nowId_ = expectStart;
36     if (traceType_ == TRACE_FILETYPE_H_TRACE) {
37         if (expectStart != INVALID_UINT64) {
38             expectStart = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, expectStart);
39         }
40         if (expectEnd != INVALID_UINT64) {
41             expectEnd = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, expectEnd);
42         }
43     }
44     frame->startTs_ = line.ts;
45     frame->callStackSliceId_ = callStackSliceId;
46     frame->expectedStartTs_ = expectStart;
47     frame->expectedEndTs_ = expectEnd;
48     frame->expectedDur_ = expectEnd - expectStart;
49     frame->vsyncId_ = vsyncId;
50     auto itid = streamFilters_->processFilter_->GetInternalTid(line.pid);
51     auto ipid = streamFilters_->processFilter_->GetInternalPid(line.tgid);
52     frame->frameSliceRow_ =
53         traceDataCache_->GetFrameSliceData()->AppendFrame(line.ts, ipid, itid, vsyncId, callStackSliceId);
54     FrameSliceRow frameSliceRow = {
55         expectStart, ipid, itid, vsyncId, callStackSliceId, expectEnd, (uint8_t)TraceStdtype::FrameSlice::EXPECT_SLICE};
56     frame->frameExpectedSliceRow_ = traceDataCache_->GetFrameSliceData()->AppendFrame(frameSliceRow);
57     if (vsyncRenderSlice_.count(itid)) {
58         vsyncRenderSlice_[itid].push_back(frame);
59     } else {
60         std::vector<std::shared_ptr<FrameSlice>> frameVec;
61         frameVec.push_back(frame);
62         vsyncRenderSlice_[itid] = frameVec;
63     }
64 }
BeginParallelTraceEvent(const BytraceLine & line,uint32_t callStackSliceId)65 void FrameFilter::BeginParallelTraceEvent(const BytraceLine &line, uint32_t callStackSliceId)
66 {
67     auto frame = std::make_shared<FrameSlice>();
68     frame->startTs_ = line.ts;
69     frame->callStackSliceId_ = callStackSliceId;
70     auto itid = streamFilters_->processFilter_->GetInternalTid(line.pid);
71     auto ipid = streamFilters_->processFilter_->GetInternalPid(line.tgid);
72     auto process = traceDataCache_->GetProcessData(ipid);
73     auto mainThreadId = process->pid_;
74     if (mainThreadId == line.pid) {
75         TS_LOGI("Only deal with the events which are not on main thread.");
76         return;
77     }
78     frame->frameSliceRow_ =
79         traceDataCache_->GetFrameSliceData()->AppendFrame(line.ts, ipid, itid, INVALID_UINT32, callStackSliceId);
80 
81     if (vsyncRenderSlice_.count(itid)) {
82         vsyncRenderSlice_[itid].push_back(frame);
83     } else {
84         std::vector<std::shared_ptr<FrameSlice>> frameVec;
85         frameVec.push_back(frame);
86         vsyncRenderSlice_[itid] = frameVec;
87     }
88 }
89 
UpdateVsyncId(const BytraceLine & line,uint32_t vsyncId,uint64_t timeId)90 bool FrameFilter::UpdateVsyncId(const BytraceLine &line, uint32_t vsyncId, uint64_t timeId)
91 {
92     // only app no main thread needs to update
93     auto itid = streamFilters_->processFilter_->GetInternalTid(line.pid);
94     auto it = vsyncRenderSlice_.find(itid);
95     if (it == vsyncRenderSlice_.end() || it->second.size() == 0) {
96         return false;
97     }
98     // only process not main thread.
99     auto ipid = traceDataCache_->GetThreadData(itid)->internalPid_;
100     auto process = traceDataCache_->GetProcessData(ipid);
101     auto mainThreadId = process->pid_;
102     if (mainThreadId == line.pid) {
103         return false;
104     }
105     auto lastFrame = it->second.back();
106     lastFrame->vsyncId_ = vsyncId;
107     lastFrame->nowId_ = timeId;
108     traceDataCache_->GetFrameSliceData()->SetVsync(lastFrame->frameSliceRow_, vsyncId);
109     auto mainItid = streamFilters_->processFilter_->GetInternalTid(mainThreadId);
110     lastFrame->expectedEndTs_ = traceDataCache_->GetFrameSliceData()->GetExpectEndByItidAndVsyncId(mainItid, vsyncId);
111     return true;
112 }
113 
MarkRSOnDoCompositionEvent(uint32_t itid)114 bool FrameFilter::MarkRSOnDoCompositionEvent(uint32_t itid)
115 {
116     auto frame = vsyncRenderSlice_.find(itid);
117     if (frame == vsyncRenderSlice_.end()) {
118         TS_LOGD("BeginOnDoCompositionEvent find for itid:%u failed", itid);
119         return false;
120     }
121     if (!frame->second.size()) {
122         TS_LOGD("BeginOnDoCompositionEvent find for itid:%u failed", itid);
123         return false;
124     }
125     auto lastFrameSlice = frame->second.back();
126     lastFrameSlice->isRsMainThread_ = true;
127     return true;
128 }
129 // for app
BeginRSTransactionData(uint32_t currentThreadId,uint32_t frameNum,uint32_t mainThreadId,uint64_t timeId)130 bool FrameFilter::BeginRSTransactionData(uint32_t currentThreadId,
131                                          uint32_t frameNum,
132                                          uint32_t mainThreadId,
133                                          uint64_t timeId)
134 {
135     auto frame = vsyncRenderSlice_.find(currentThreadId);
136     if (frame == vsyncRenderSlice_.end()) {
137         TS_LOGD("BeginRSTransactionData find for itid:%u failed", currentThreadId);
138         return false;
139     }
140     if (!frame->second.size()) {
141         TS_LOGD("BeginRSTransactionData find for itid:%u failed", currentThreadId);
142         return false;
143     }
144     std::shared_ptr<FrameSlice> frameSlice = nullptr;
145     if (timeId != INVALID_UINT64) {
146         for (auto it = frame->second.begin(); it != frame->second.end();) {
147             if (it->get()->nowId_ == timeId) {
148                 frameSlice = *it;
149                 frameSlice->frameNum_ = frameNum;
150                 if (frameSlice->isEnd_) {
151                     it = frame->second.erase(it);
152                 }
153                 break;
154             } else {
155                 ++it;
156             }
157         }
158     } else {
159         frameSlice = frame->second.back();
160         if (frameSlice->isEnd_) {
161             return false;
162         }
163         frameSlice->frameNum_ = frameNum;
164     }
165     if (frameSlice == nullptr) {
166         TS_LOGW("No matching frame found,frameNum is:%u", frameNum);
167         return false;
168     }
169     if (!dstRenderSlice_.count(mainThreadId)) {
170         std::unordered_map<uint32_t /* frameNum */, std::shared_ptr<FrameSlice>> frameMap;
171         dstRenderSlice_.emplace(std::make_pair(mainThreadId, std::move(frameMap)));
172     }
173     dstRenderSlice_[mainThreadId][frameNum] = frameSlice;
174     return true;
175 }
176 // for RS
BeginProcessCommandUni(uint32_t itid,const std::vector<FrameMap> & frames,uint32_t sliceIndex)177 bool FrameFilter::BeginProcessCommandUni(uint32_t itid, const std::vector<FrameMap> &frames, uint32_t sliceIndex)
178 {
179     auto frame = vsyncRenderSlice_.find(itid);
180     TS_CHECK_TRUE_RET(frame != vsyncRenderSlice_.end(), false);
181     TS_CHECK_TRUE_RET(!frame->second.empty(), false);
182     auto lastFrameSlice = frame->second.back();
183     TS_CHECK_TRUE_RET(!lastFrameSlice->vsyncEnd_, false);
184     std::vector<uint64_t> fromSlices = {};
185     std::vector<uint64_t> fromExpectedSlices = {};
186     for (auto &it : frames) {
187         auto sourceFrameMap = dstRenderSlice_.find(it.sourceItid);
188         if (sourceFrameMap == dstRenderSlice_.end()) {
189             continue;
190         }
191         auto srcFrame = sourceFrameMap->second.find(it.frameNum);
192         if (srcFrame == sourceFrameMap->second.end()) {
193             continue;
194         }
195         fromSlices.push_back(srcFrame->second->frameSliceRow_);
196         fromExpectedSlices.push_back(srcFrame->second->frameExpectedSliceRow_);
197         srcFrame->second->dstFrameSliceId_ = lastFrameSlice->frameSliceRow_;
198         srcFrame->second->dstExpectedFrameSliceId_ = lastFrameSlice->frameExpectedSliceRow_;
199         TraceStdtype::FrameSlice *frameSlice = traceDataCache_->GetFrameSliceData();
200         (void)traceDataCache_->GetFrameMapsData()->AppendNew(frameSlice, srcFrame->second->frameSliceRow_,
201                                                              srcFrame->second->dstFrameSliceId_);
202         if (srcFrame->second->frameExpectedSliceRow_ != INVALID_UINT64) {
203             (void)traceDataCache_->GetFrameMapsData()->AppendNew(frameSlice, srcFrame->second->frameExpectedSliceRow_,
204                                                                  srcFrame->second->dstExpectedFrameSliceId_);
205         }
206 
207         frameSlice->SetDst(srcFrame->second->frameSliceRow_, srcFrame->second->dstFrameSliceId_);
208         if (srcFrame->second->frameExpectedSliceRow_ != INVALID_UINT64) {
209             frameSlice->SetDst(srcFrame->second->frameExpectedSliceRow_, srcFrame->second->dstExpectedFrameSliceId_);
210         }
211         if (srcFrame->second->endTs_ != INVALID_UINT64) {
212             // erase Source
213             sourceFrameMap->second.erase(it.frameNum);
214         }
215     }
216     TS_CHECK_TRUE_RET(!fromSlices.empty(), false);
217     lastFrameSlice->sourceSlice_ = fromSlices;
218     lastFrameSlice->sourceExpectedSlice_ = fromExpectedSlices;
219     traceDataCache_->GetFrameSliceData()->SetSrcs(lastFrameSlice->frameSliceRow_, fromSlices);
220     traceDataCache_->GetFrameSliceData()->SetSrcs(lastFrameSlice->frameExpectedSliceRow_, fromExpectedSlices);
221     return true;
222 }
EndVsyncEvent(uint64_t ts,uint32_t itid)223 bool FrameFilter::EndVsyncEvent(uint64_t ts, uint32_t itid)
224 {
225     auto frame = vsyncRenderSlice_.find(itid);
226     if (frame == vsyncRenderSlice_.end()) {
227         TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts);
228         return false;
229     }
230     if (!frame->second.size()) {
231         TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts);
232         return false;
233     }
234     auto lastFrameSlice = frame->second.back();
235     lastFrameSlice->vsyncEnd_ = true;
236     if (lastFrameSlice->isRsMainThread_) {
237         if (lastFrameSlice->gpuEnd_) {
238             traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(lastFrameSlice->frameSliceRow_, ts,
239                                                                     lastFrameSlice->expectedEndTs_);
240             lastFrameSlice->endTs_ = ts;
241             // for Render serivce
242             frame->second.pop_back();
243         }
244     } else { // for app
245         if (lastFrameSlice->isEnd_) {
246             return false;
247         }
248         traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(lastFrameSlice->frameSliceRow_, ts,
249                                                                 lastFrameSlice->expectedEndTs_);
250         if (lastFrameSlice->frameNum_ != INVALID_UINT32) {
251             frame->second.pop_back();
252         }
253         lastFrameSlice->isEnd_ = true;
254         lastFrameSlice->endTs_ = ts;
255     }
256     return true;
257 }
258 // only for renderservice
StartFrameQueue(uint64_t ts,uint32_t itid)259 bool FrameFilter::StartFrameQueue(uint64_t ts, uint32_t itid)
260 {
261     auto frame = vsyncRenderSlice_.find(itid);
262     if (frame == vsyncRenderSlice_.end()) {
263         TS_LOGD("StartFrameQueue find for itid:%u failed", itid);
264         return false;
265     }
266     if (!frame->second.size()) {
267         TS_LOGD("StartFrameQueue find for itid:%u failed", itid);
268         return false;
269     }
270     auto firstFrameSlice = frame->second.front();
271     firstFrameSlice->gpuEnd_ = false;
272     firstFrameSlice->frameQueueStartTs_ = ts;
273     return true;
274 }
EndFrameQueue(uint64_t ts,uint32_t itid)275 bool FrameFilter::EndFrameQueue(uint64_t ts, uint32_t itid)
276 {
277     auto frame = vsyncRenderSlice_.find(itid);
278     if (frame == vsyncRenderSlice_.end()) {
279         TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 " failed", itid, ts);
280         return false;
281     }
282     if (!frame->second.size()) {
283         TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 "  failed", itid, ts);
284         return false;
285     }
286     auto firstFrameSlicePos = frame->second.begin();
287     TraceStdtype::FrameSlice *frameSlice = traceDataCache_->GetFrameSliceData();
288     (void)traceDataCache_->GetGPUSliceData()->AppendNew(frameSlice->diskTableSize_ +
289                                                             (*firstFrameSlicePos)->frameSliceRow_,
290                                                         ts - firstFrameSlicePos->get()->frameQueueStartTs_);
291     firstFrameSlicePos->get()->gpuEnd_ = true;
292     if (firstFrameSlicePos->get()->vsyncEnd_) {
293         firstFrameSlicePos->get()->endTs_ = ts;
294         traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(firstFrameSlicePos->get()->frameSliceRow_, ts,
295                                                                 firstFrameSlicePos->get()->expectedEndTs_);
296         // if vsync ended
297         frame->second.erase(firstFrameSlicePos);
298     }
299     return true;
300 }
SetMinFrameSliceRow(uint64_t & minFrameSliceRowToBeUpdated)301 void FrameFilter::SetMinFrameSliceRow(uint64_t &minFrameSliceRowToBeUpdated)
302 {
303     for (const auto &[_, frameSlices] : vsyncRenderSlice_) {
304         for (size_t idx = 0; idx < frameSlices.size(); idx++) {
305             if (minFrameSliceRowToBeUpdated > frameSlices[idx]->frameSliceRow_) {
306                 minFrameSliceRowToBeUpdated = frameSlices[idx]->frameSliceRow_;
307             }
308             if (minFrameSliceRowToBeUpdated > frameSlices[idx]->frameExpectedSliceRow_) {
309                 minFrameSliceRowToBeUpdated = frameSlices[idx]->frameExpectedSliceRow_;
310             }
311         }
312     }
313     for (const auto &pair : dstRenderSlice_) {
314         for (const auto &[_, frameSlice] : pair.second) {
315             if (minFrameSliceRowToBeUpdated > frameSlice->frameSliceRow_) {
316                 minFrameSliceRowToBeUpdated = frameSlice->frameSliceRow_;
317             }
318             if (minFrameSliceRowToBeUpdated > frameSlice->frameExpectedSliceRow_) {
319                 minFrameSliceRowToBeUpdated = frameSlice->frameExpectedSliceRow_;
320             }
321         }
322     }
323 }
UpdateFrameSliceReadySize()324 bool FrameFilter::UpdateFrameSliceReadySize()
325 {
326     traceDataCache_->GetFrameSliceData()->UpdateDepth();
327     auto frameSlice = traceDataCache_->GetFrameSliceData();
328     frameSlice->UpdateReadySize(frameSlice->Size());
329     uint64_t minFrameSliceRowToBeUpdated = INVALID_UINT64;
330     SetMinFrameSliceRow(minFrameSliceRowToBeUpdated);
331     // the ready size isn't all
332     TS_CHECK_TRUE_RET(minFrameSliceRowToBeUpdated != INVALID_UINT64, true);
333     frameSlice->UpdateReadySize(minFrameSliceRowToBeUpdated);
334     TS_LOGI("minFrameSliceRowToBeUpdated=%" PRIu64 ", size=%zu, ready.size=%zu\n", minFrameSliceRowToBeUpdated,
335             frameSlice->Size(), frameSlice->readySize_);
336     for (auto &[_, frameSlices] : vsyncRenderSlice_) {
337         for (size_t idx = 0; idx < frameSlices.size(); idx++) {
338             frameSlices[idx]->frameSliceRow_ -= minFrameSliceRowToBeUpdated;
339             frameSlices[idx]->frameExpectedSliceRow_ -= minFrameSliceRowToBeUpdated;
340         }
341     }
342     for (const auto &pair : dstRenderSlice_) {
343         for (const auto &[_, frameSlice] : pair.second) {
344             frameSlice->frameSliceRow_ -= minFrameSliceRowToBeUpdated;
345             frameSlice->frameExpectedSliceRow_ -= minFrameSliceRowToBeUpdated;
346         }
347     }
348     return true;
349 }
350 
SetTraceType(TraceFileType traceType)351 void FrameFilter::SetTraceType(TraceFileType traceType)
352 {
353     traceType_ = traceType;
354 }
355 
Clear()356 void FrameFilter::Clear()
357 {
358     for (auto &pair : vsyncRenderSlice_) {
359         for (auto &frameSlice : pair.second) {
360             if (frameSlice->isRsMainThread_) {
361                 break;
362             }
363             traceDataCache_->GetFrameSliceData()->Erase(frameSlice->frameSliceRow_);
364             if (frameSlice->frameExpectedSliceRow_ != INVALID_UINT64) {
365                 traceDataCache_->GetFrameSliceData()->Erase(frameSlice->frameExpectedSliceRow_);
366             }
367         }
368     }
369     traceDataCache_->GetFrameSliceData()->UpdateDepth();
370     vsyncRenderSlice_.clear();
371     dstRenderSlice_.clear();
372 }
373 } // namespace TraceStreamer
374 } // namespace SysTuning
375