• 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 <memory>
17 #include <cinttypes>
18 #include "process_filter.h"
19 
20 namespace SysTuning {
21 namespace TraceStreamer {
FrameFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)22 FrameFilter::FrameFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter) : FilterBase(dataCache, filter)
23 {
24 }
25 FrameFilter::~FrameFilter() = default;
26 
BeginVsyncEvent(const BytraceLine & line,uint64_t expectStart,uint64_t expectEnd,uint32_t vsyncId,uint32_t callStackSliceId)27 void FrameFilter::BeginVsyncEvent(const BytraceLine &line,
28                                   uint64_t expectStart,
29                                   uint64_t expectEnd,
30                                   uint32_t vsyncId,
31                                   uint32_t callStackSliceId)
32 {
33     auto frame = std::make_shared<FrameSlice>();
34     frame->startTs_ = line.ts;
35     frame->callStackSliceId_ = callStackSliceId;
36     frame->expectedStartTs_ = expectStart;
37     frame->expectedEndTs_ = expectEnd;
38     frame->expectedDur_ = expectEnd - expectStart;
39     frame->vsyncId_ = vsyncId;
40     auto itid = streamFilters_->processFilter_->GetInternalTid(line.pid);
41     auto ipid = streamFilters_->processFilter_->GetInternalPid(line.tgid);
42     frame->frameSliceRow_ =
43         traceDataCache_->GetFrameSliceData()->AppendFrame(line.ts, ipid, itid, vsyncId, callStackSliceId);
44     FrameSliceRow frameSliceRow = {
45         expectStart, ipid, itid, vsyncId, callStackSliceId, expectEnd, (uint8_t)TraceStdtype::FrameSlice::EXPECT_SLICE};
46     frame->frameExpectedSliceRow_ = traceDataCache_->GetFrameSliceData()->AppendFrame(frameSliceRow);
47     if (vsyncRenderSlice_.count(itid)) {
48         vsyncRenderSlice_[itid].push_back(frame);
49     } else {
50         std::vector<std::shared_ptr<FrameSlice>> frameVec;
51         frameVec.push_back(frame);
52         vsyncRenderSlice_[itid] = frameVec;
53     }
54 }
BeginUVTraceEvent(const BytraceLine & line,uint32_t callStackSliceId)55 void FrameFilter::BeginUVTraceEvent(const BytraceLine &line, uint32_t callStackSliceId)
56 {
57     auto frame = std::make_shared<FrameSlice>();
58     frame->startTs_ = line.ts;
59     frame->callStackSliceId_ = callStackSliceId;
60     frame->isUVTrace_ = true;
61     auto itid = streamFilters_->processFilter_->GetInternalTid(line.pid);
62     auto ipid = streamFilters_->processFilter_->GetInternalPid(line.tgid);
63     frame->frameSliceRow_ =
64         traceDataCache_->GetFrameSliceData()->AppendFrame(line.ts, ipid, itid, INVALID_UINT32, callStackSliceId);
65 
66     if (vsyncRenderSlice_.count(itid)) {
67         vsyncRenderSlice_[itid].push_back(frame);
68     } else {
69         std::vector<std::shared_ptr<FrameSlice>> frameVec;
70         frameVec.push_back(frame);
71         vsyncRenderSlice_[itid] = frameVec;
72     }
73 }
74 
UpdateVsyncId(const BytraceLine & line,uint32_t vsyncId)75 bool FrameFilter::UpdateVsyncId(const BytraceLine &line, uint32_t vsyncId)
76 {
77     // only app no main thread needs to update
78     auto itid = streamFilters_->processFilter_->GetInternalTid(line.pid);
79     auto it = vsyncRenderSlice_.find(itid);
80     if (it == vsyncRenderSlice_.end() || it->second.size() == 0) {
81         return false;
82     }
83     // only process not main thread.
84     auto ipid = traceDataCache_->GetThreadData(itid)->internalPid_;
85     auto process = traceDataCache_->GetProcessData(ipid);
86     auto mainThreadId = process->pid_;
87     if (mainThreadId == line.pid) {
88         return false;
89     }
90     auto lastFrame = it->second.back();
91     lastFrame->vsyncId_ = vsyncId;
92     traceDataCache_->GetFrameSliceData()->SetVsync(lastFrame->frameSliceRow_, vsyncId);
93     auto mainItid = streamFilters_->processFilter_->GetInternalTid(mainThreadId);
94     lastFrame->expectedEndTs_ = traceDataCache_->GetFrameSliceData()->GetExpectEndByItidAndVsyncId(mainItid, vsyncId);
95     return true;
96 }
97 
MarkRSOnDoCompositionEvent(uint32_t itid)98 bool FrameFilter::MarkRSOnDoCompositionEvent(uint32_t itid)
99 {
100     auto frame = vsyncRenderSlice_.find(itid);
101     if (frame == vsyncRenderSlice_.end()) {
102         TS_LOGD("BeginOnDoCompositionEvent find for itid:%u failed", itid);
103         return false;
104     }
105     if (!frame->second.size()) {
106         TS_LOGD("BeginOnDoCompositionEvent find for itid:%u failed", itid);
107         return false;
108     }
109     auto lastFrameSlice = frame->second.back();
110     lastFrameSlice->isRsMainThread_ = true;
111     return true;
112 }
113 // for app
BeginRSTransactionData(uint32_t currentThreadId,uint32_t frameNum,uint32_t mainThreadId)114 bool FrameFilter::BeginRSTransactionData(uint32_t currentThreadId, uint32_t frameNum, uint32_t mainThreadId)
115 {
116     auto frame = vsyncRenderSlice_.find(currentThreadId);
117     if (frame == vsyncRenderSlice_.end()) {
118         TS_LOGD("BeginRSTransactionData find for itid:%u failed", currentThreadId);
119         return false;
120     }
121     if (!frame->second.size()) {
122         TS_LOGD("BeginRSTransactionData find for itid:%u failed", currentThreadId);
123         return false;
124     }
125     frame->second.begin()->get()->frameNum_ = frameNum;
126     if (!dstRenderSlice_.count(mainThreadId)) {
127         std::unordered_map<uint32_t /* frameNum */, std::shared_ptr<FrameSlice>> frameMap;
128         dstRenderSlice_.emplace(std::make_pair(mainThreadId, std::move(frameMap)));
129     }
130     dstRenderSlice_[mainThreadId][frameNum] = frame->second[0];
131     return true;
132 }
133 // for RS
BeginProcessCommandUni(uint32_t itid,const std::vector<FrameMap> & frames,uint32_t sliceIndex)134 bool FrameFilter::BeginProcessCommandUni(uint32_t itid, const std::vector<FrameMap> &frames, uint32_t sliceIndex)
135 {
136     auto frame = vsyncRenderSlice_.find(itid);
137     TS_CHECK_TRUE_RET(frame != vsyncRenderSlice_.end(), false);
138     TS_CHECK_TRUE_RET(!frame->second.empty(), false);
139     auto lastFrameSlice = frame->second.back();
140     TS_CHECK_TRUE_RET(!lastFrameSlice->vsyncEnd_, false);
141     std::vector<uint64_t> fromSlices = {};
142     std::vector<uint64_t> fromExpectedSlices = {};
143     for (auto &it : frames) {
144         auto sourceFrameMap = dstRenderSlice_.find(it.sourceItid);
145         if (sourceFrameMap == dstRenderSlice_.end()) {
146             continue;
147         }
148         auto srcFrame = sourceFrameMap->second.find(it.frameNum);
149         if (srcFrame == sourceFrameMap->second.end()) {
150             continue;
151         }
152         fromSlices.push_back(srcFrame->second->frameSliceRow_);
153         fromExpectedSlices.push_back(srcFrame->second->frameExpectedSliceRow_);
154         srcFrame->second->dstFrameSliceId_ = lastFrameSlice->frameSliceRow_;
155         srcFrame->second->dstExpectedFrameSliceId_ = lastFrameSlice->frameExpectedSliceRow_;
156         TraceStdtype::FrameSlice *frameSlice = traceDataCache_->GetFrameSliceData();
157         (void)traceDataCache_->GetFrameMapsData()->AppendNew(frameSlice, srcFrame->second->frameSliceRow_,
158                                                              srcFrame->second->dstFrameSliceId_);
159         if (srcFrame->second->frameExpectedSliceRow_ != INVALID_UINT64) {
160             (void)traceDataCache_->GetFrameMapsData()->AppendNew(frameSlice, srcFrame->second->frameExpectedSliceRow_,
161                                                                  srcFrame->second->dstExpectedFrameSliceId_);
162         }
163 
164         frameSlice->SetDst(srcFrame->second->frameSliceRow_, srcFrame->second->dstFrameSliceId_);
165         if (srcFrame->second->frameExpectedSliceRow_ != INVALID_UINT64) {
166             frameSlice->SetDst(srcFrame->second->frameExpectedSliceRow_, srcFrame->second->dstExpectedFrameSliceId_);
167         }
168         if (srcFrame->second->endTs_ != INVALID_UINT64) {
169             // erase Source
170             sourceFrameMap->second.erase(it.frameNum);
171         }
172     }
173     TS_CHECK_TRUE_RET(!fromSlices.empty(), false);
174     lastFrameSlice->sourceSlice_ = fromSlices;
175     lastFrameSlice->sourceExpectedSlice_ = fromExpectedSlices;
176     traceDataCache_->GetFrameSliceData()->SetSrcs(lastFrameSlice->frameSliceRow_, fromSlices);
177     traceDataCache_->GetFrameSliceData()->SetSrcs(lastFrameSlice->frameExpectedSliceRow_, fromExpectedSlices);
178     return true;
179 }
EndVsyncEvent(uint64_t ts,uint32_t itid)180 bool FrameFilter::EndVsyncEvent(uint64_t ts, uint32_t itid)
181 {
182     auto frame = vsyncRenderSlice_.find(itid);
183     if (frame == vsyncRenderSlice_.end()) {
184         TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts);
185         return false;
186     }
187     if (!frame->second.size()) {
188         TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts);
189         return false;
190     }
191     auto lastFrameSlice = frame->second.back();
192     lastFrameSlice->vsyncEnd_ = true;
193     if (lastFrameSlice->isRsMainThread_) {
194         if (lastFrameSlice->gpuEnd_) {
195             traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(lastFrameSlice->frameSliceRow_, ts,
196                                                                     lastFrameSlice->expectedEndTs_);
197             lastFrameSlice->endTs_ = ts;
198             // for Render serivce
199             frame->second.pop_back();
200         }
201     } else { // for app
202         traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(lastFrameSlice->frameSliceRow_, ts,
203                                                                 lastFrameSlice->expectedEndTs_);
204         if (lastFrameSlice->frameNum_ == INVALID_UINT32) {
205             // if app's frame num not received
206             traceDataCache_->GetFrameSliceData()->Erase(lastFrameSlice->frameSliceRow_);
207             if (lastFrameSlice->frameExpectedSliceRow_ != INVALID_UINT64) {
208                 traceDataCache_->GetFrameSliceData()->Erase(lastFrameSlice->frameExpectedSliceRow_);
209             }
210             frame->second.pop_back();
211             return false;
212         }
213         lastFrameSlice->endTs_ = ts;
214         frame->second.pop_back();
215     }
216     return true;
217 }
218 // only for renderservice
StartFrameQueue(uint64_t ts,uint32_t itid)219 bool FrameFilter::StartFrameQueue(uint64_t ts, uint32_t itid)
220 {
221     auto frame = vsyncRenderSlice_.find(itid);
222     if (frame == vsyncRenderSlice_.end()) {
223         TS_LOGD("StartFrameQueue find for itid:%u failed", itid);
224         return false;
225     }
226     if (!frame->second.size()) {
227         TS_LOGD("StartFrameQueue find for itid:%u failed", itid);
228         return false;
229     }
230     auto firstFrameSlice = frame->second.front();
231     firstFrameSlice->gpuEnd_ = false;
232     firstFrameSlice->frameQueueStartTs_ = ts;
233     return true;
234 }
EndFrameQueue(uint64_t ts,uint32_t itid)235 bool FrameFilter::EndFrameQueue(uint64_t ts, uint32_t itid)
236 {
237     auto frame = vsyncRenderSlice_.find(itid);
238     if (frame == vsyncRenderSlice_.end()) {
239         TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 " failed", itid, ts);
240         return false;
241     }
242     if (!frame->second.size()) {
243         TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 "  failed", itid, ts);
244         return false;
245     }
246     auto firstFrameSlicePos = frame->second.begin();
247     TraceStdtype::FrameSlice *frameSlice = traceDataCache_->GetFrameSliceData();
248     (void)traceDataCache_->GetGPUSliceData()->AppendNew(frameSlice->diskTableSize_ +
249                                                             (*firstFrameSlicePos)->frameSliceRow_,
250                                                         ts - firstFrameSlicePos->get()->frameQueueStartTs_);
251     firstFrameSlicePos->get()->gpuEnd_ = true;
252     if (firstFrameSlicePos->get()->vsyncEnd_) {
253         firstFrameSlicePos->get()->endTs_ = ts;
254         traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(firstFrameSlicePos->get()->frameSliceRow_, ts,
255                                                                 firstFrameSlicePos->get()->expectedEndTs_);
256         // if vsync ended
257         frame->second.erase(firstFrameSlicePos);
258     }
259     return true;
260 }
SetMinFrameSliceRow(uint64_t & minFrameSliceRowToBeUpdated)261 void FrameFilter::SetMinFrameSliceRow(uint64_t &minFrameSliceRowToBeUpdated)
262 {
263     for (const auto &[_, frameSlices] : vsyncRenderSlice_) {
264         for (size_t idx = 0; idx < frameSlices.size(); idx++) {
265             if (minFrameSliceRowToBeUpdated > frameSlices[idx]->frameSliceRow_) {
266                 minFrameSliceRowToBeUpdated = frameSlices[idx]->frameSliceRow_;
267             }
268             if (minFrameSliceRowToBeUpdated > frameSlices[idx]->frameExpectedSliceRow_) {
269                 minFrameSliceRowToBeUpdated = frameSlices[idx]->frameExpectedSliceRow_;
270             }
271         }
272     }
273     for (const auto &pair : dstRenderSlice_) {
274         for (const auto &[_, frameSlice] : pair.second) {
275             if (minFrameSliceRowToBeUpdated > frameSlice->frameSliceRow_) {
276                 minFrameSliceRowToBeUpdated = frameSlice->frameSliceRow_;
277             }
278             if (minFrameSliceRowToBeUpdated > frameSlice->frameExpectedSliceRow_) {
279                 minFrameSliceRowToBeUpdated = frameSlice->frameExpectedSliceRow_;
280             }
281         }
282     }
283 }
UpdateFrameSliceReadySize()284 bool FrameFilter::UpdateFrameSliceReadySize()
285 {
286     traceDataCache_->GetFrameSliceData()->UpdateDepth();
287     auto frameSlice = traceDataCache_->GetFrameSliceData();
288     frameSlice->UpdateReadySize(frameSlice->Size());
289     uint64_t minFrameSliceRowToBeUpdated = INVALID_UINT64;
290     SetMinFrameSliceRow(minFrameSliceRowToBeUpdated);
291     // the ready size isn't all
292     TS_CHECK_TRUE_RET(minFrameSliceRowToBeUpdated != INVALID_UINT64, true);
293     frameSlice->UpdateReadySize(minFrameSliceRowToBeUpdated);
294     TS_LOGI("minFrameSliceRowToBeUpdated=%" PRIu64 ", size=%zu, ready.size=%zu\n", minFrameSliceRowToBeUpdated,
295             frameSlice->Size(), frameSlice->readySize_);
296     for (auto &[_, frameSlices] : vsyncRenderSlice_) {
297         for (size_t idx = 0; idx < frameSlices.size(); idx++) {
298             frameSlices[idx]->frameSliceRow_ -= minFrameSliceRowToBeUpdated;
299             frameSlices[idx]->frameExpectedSliceRow_ -= minFrameSliceRowToBeUpdated;
300         }
301     }
302     for (const auto &pair : dstRenderSlice_) {
303         for (const auto &[_, frameSlice] : pair.second) {
304             frameSlice->frameSliceRow_ -= minFrameSliceRowToBeUpdated;
305             frameSlice->frameExpectedSliceRow_ -= minFrameSliceRowToBeUpdated;
306         }
307     }
308     return true;
309 }
Clear()310 void FrameFilter::Clear()
311 {
312     traceDataCache_->GetFrameSliceData()->UpdateDepth();
313     vsyncRenderSlice_.clear();
314     dstRenderSlice_.clear();
315 }
316 } // namespace TraceStreamer
317 } // namespace SysTuning
318