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