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