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 }
55
MarkRSOnDoCompositionEvent(uint64_t ts,uint32_t itid)56 bool FrameFilter::MarkRSOnDoCompositionEvent(uint64_t ts, uint32_t itid)
57 {
58 auto frame = vsyncRenderSlice_.find(itid);
59 if (frame == vsyncRenderSlice_.end()) {
60 TS_LOGD("BeginOnDoCompositionEvent find for itid:%u failed, ts:%" PRIu64 "", itid, ts);
61 return false;
62 }
63 if (!frame->second.size()) {
64 TS_LOGD("BeginOnDoCompositionEvent find for itid:%u failed", itid);
65 return false;
66 }
67 auto lastFrameSlice = frame->second.back();
68 lastFrameSlice->isRsMainThread_ = true;
69 return true;
70 }
71 // for app
BeginRSTransactionData(uint64_t ts,uint32_t itid,uint32_t franeNum)72 bool FrameFilter::BeginRSTransactionData(uint64_t ts, uint32_t itid, uint32_t franeNum)
73 {
74 auto frame = vsyncRenderSlice_.find(itid);
75 if (frame == vsyncRenderSlice_.end()) {
76 TS_LOGD("BeginRSTransactionData find for itid:%u failed", itid);
77 return false;
78 }
79 if (!frame->second.size()) {
80 TS_LOGD("BeginRSTransactionData find for itid:%u failed", itid);
81 return false;
82 }
83 frame->second.begin()->get()->frameNum_ = franeNum;
84 if (!dstRenderSlice_.count(itid)) {
85 std::unordered_map<uint32_t /* frameNum */, std::shared_ptr<FrameSlice>> frameMap;
86 dstRenderSlice_.emplace(std::make_pair(itid, std::move(frameMap)));
87 }
88 dstRenderSlice_[itid][franeNum] = frame->second[0];
89 return true;
90 }
91 // for RS
BeginProcessCommandUni(uint64_t ts,uint32_t itid,const std::vector<FrameMap> & frames,uint32_t sliceIndex)92 bool FrameFilter::BeginProcessCommandUni(uint64_t ts,
93 uint32_t itid,
94 const std::vector<FrameMap> &frames,
95 uint32_t sliceIndex)
96 {
97 auto frame = vsyncRenderSlice_.find(itid);
98 TS_CHECK_TRUE_RET(frame != vsyncRenderSlice_.end(), false);
99 TS_CHECK_TRUE_RET(!frame->second.empty(), false);
100 auto lastFrameSlice = frame->second.back();
101 TS_CHECK_TRUE_RET(!lastFrameSlice->vsyncEnd_, false);
102 std::vector<uint64_t> fromSlices = {};
103 std::vector<uint64_t> fromExpectedSlices = {};
104 for (auto &it : frames) {
105 auto sourceFrameMap = dstRenderSlice_.find(it.sourceItid);
106 if (sourceFrameMap == dstRenderSlice_.end()) {
107 continue;
108 }
109 auto srcFrame = sourceFrameMap->second.find(it.frameNum);
110 if (srcFrame == sourceFrameMap->second.end()) {
111 continue;
112 }
113 fromSlices.push_back(srcFrame->second->frameSliceRow_);
114 fromExpectedSlices.push_back(srcFrame->second->frameExpectedSliceRow_);
115 srcFrame->second->dstFrameSliceId_ = lastFrameSlice->frameSliceRow_;
116 srcFrame->second->dstExpectedFrameSliceId_ = lastFrameSlice->frameExpectedSliceRow_;
117 TraceStdtype::FrameSlice *frameSlice = traceDataCache_->GetFrameSliceData();
118 (void)traceDataCache_->GetFrameMapsData()->AppendNew(frameSlice, srcFrame->second->frameSliceRow_,
119 srcFrame->second->dstFrameSliceId_);
120 (void)traceDataCache_->GetFrameMapsData()->AppendNew(frameSlice, srcFrame->second->frameExpectedSliceRow_,
121 srcFrame->second->dstExpectedFrameSliceId_);
122 frameSlice->SetDst(srcFrame->second->frameSliceRow_, srcFrame->second->dstFrameSliceId_);
123 frameSlice->SetDst(srcFrame->second->frameExpectedSliceRow_, srcFrame->second->dstExpectedFrameSliceId_);
124 if (srcFrame->second->endTs_ != INVALID_UINT64) {
125 // erase Source
126 sourceFrameMap->second.erase(it.frameNum);
127 }
128 }
129 TS_CHECK_TRUE_RET(!fromSlices.empty(), false);
130 lastFrameSlice->sourceSlice_ = fromSlices;
131 lastFrameSlice->sourceExpectedSlice_ = fromExpectedSlices;
132 traceDataCache_->GetFrameSliceData()->SetSrcs(lastFrameSlice->frameSliceRow_, fromSlices);
133 traceDataCache_->GetFrameSliceData()->SetSrcs(lastFrameSlice->frameExpectedSliceRow_, fromExpectedSlices);
134 return true;
135 }
EndVsyncEvent(uint64_t ts,uint32_t itid)136 bool FrameFilter::EndVsyncEvent(uint64_t ts, uint32_t itid)
137 {
138 auto frame = vsyncRenderSlice_.find(itid);
139 if (frame == vsyncRenderSlice_.end()) {
140 TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts);
141 return false;
142 }
143 if (!frame->second.size()) {
144 TS_LOGW("EndVsyncEvent find for itid:%u ts:%" PRIu64 " failed", itid, ts);
145 return false;
146 }
147 auto lastFrameSlice = frame->second.back();
148 lastFrameSlice->vsyncEnd_ = true;
149 if (lastFrameSlice->isRsMainThread_) {
150 if (lastFrameSlice->gpuEnd_) {
151 traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(
152 lastFrameSlice->frameSliceRow_, ts, lastFrameSlice->expectedDur_, lastFrameSlice->expectedEndTs_);
153 lastFrameSlice->endTs_ = ts;
154 // for Render serivce
155 frame->second.pop_back();
156 }
157 } else { // for app
158 traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(
159 lastFrameSlice->frameSliceRow_, ts, lastFrameSlice->expectedDur_, lastFrameSlice->expectedEndTs_);
160 if (lastFrameSlice->frameNum_ == INVALID_UINT32) {
161 // if app's frame num not received
162 traceDataCache_->GetFrameSliceData()->Erase(lastFrameSlice->frameSliceRow_);
163 traceDataCache_->GetFrameSliceData()->Erase(lastFrameSlice->frameExpectedSliceRow_);
164 frame->second.pop_back();
165 return false;
166 }
167 lastFrameSlice->endTs_ = ts;
168 frame->second.pop_back();
169 }
170 return true;
171 }
172 // only for renderservice
StartFrameQueue(uint64_t ts,uint32_t itid)173 bool FrameFilter::StartFrameQueue(uint64_t ts, uint32_t itid)
174 {
175 auto frame = vsyncRenderSlice_.find(itid);
176 if (frame == vsyncRenderSlice_.end()) {
177 TS_LOGD("StartFrameQueue find for itid:%u failed", itid);
178 return false;
179 }
180 if (!frame->second.size()) {
181 TS_LOGD("StartFrameQueue find for itid:%u failed", itid);
182 return false;
183 }
184 auto firstFrameSlice = frame->second.front();
185 firstFrameSlice->gpuEnd_ = false;
186 firstFrameSlice->frameQueueStartTs_ = ts;
187 return true;
188 }
EndFrameQueue(uint64_t ts,uint32_t itid)189 bool FrameFilter::EndFrameQueue(uint64_t ts, uint32_t itid)
190 {
191 auto frame = vsyncRenderSlice_.find(itid);
192 if (frame == vsyncRenderSlice_.end()) {
193 TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 " failed", itid, ts);
194 return false;
195 }
196 if (!frame->second.size()) {
197 TS_LOGW("EndFrameQueue find for itid:%u ts:%" PRIu64 " failed", itid, ts);
198 return false;
199 }
200 auto firstFrameSlicePos = frame->second.begin();
201 TraceStdtype::FrameSlice *frameSlice = traceDataCache_->GetFrameSliceData();
202 (void)traceDataCache_->GetGPUSliceData()->AppendNew(frameSlice->diskTableSize_ +
203 (*firstFrameSlicePos)->frameSliceRow_,
204 ts - firstFrameSlicePos->get()->frameQueueStartTs_);
205 firstFrameSlicePos->get()->gpuEnd_ = true;
206 if (firstFrameSlicePos->get()->vsyncEnd_) {
207 firstFrameSlicePos->get()->endTs_ = ts;
208 traceDataCache_->GetFrameSliceData()->SetEndTimeAndFlag(firstFrameSlicePos->get()->frameSliceRow_, ts,
209 firstFrameSlicePos->get()->expectedDur_,
210 firstFrameSlicePos->get()->expectedEndTs_);
211 // if vsync ended
212 frame->second.erase(firstFrameSlicePos);
213 }
214 return true;
215 }
SetMinFrameSliceRow(uint64_t & minFrameSliceRowToBeUpdated)216 void FrameFilter::SetMinFrameSliceRow(uint64_t &minFrameSliceRowToBeUpdated)
217 {
218 for (const auto &[_, frameSlices] : vsyncRenderSlice_) {
219 for (size_t idx = 0; idx < frameSlices.size(); idx++) {
220 if (minFrameSliceRowToBeUpdated > frameSlices[idx]->frameSliceRow_) {
221 minFrameSliceRowToBeUpdated = frameSlices[idx]->frameSliceRow_;
222 }
223 if (minFrameSliceRowToBeUpdated > frameSlices[idx]->frameExpectedSliceRow_) {
224 minFrameSliceRowToBeUpdated = frameSlices[idx]->frameExpectedSliceRow_;
225 }
226 }
227 }
228 for (const auto &pair : dstRenderSlice_) {
229 for (const auto &[_, frameSlice] : pair.second) {
230 if (minFrameSliceRowToBeUpdated > frameSlice->frameSliceRow_) {
231 minFrameSliceRowToBeUpdated = frameSlice->frameSliceRow_;
232 }
233 if (minFrameSliceRowToBeUpdated > frameSlice->frameExpectedSliceRow_) {
234 minFrameSliceRowToBeUpdated = frameSlice->frameExpectedSliceRow_;
235 }
236 }
237 }
238 }
UpdateFrameSliceReadySize()239 bool FrameFilter::UpdateFrameSliceReadySize()
240 {
241 traceDataCache_->GetFrameSliceData()->UpdateDepth();
242 auto frameSlice = traceDataCache_->GetFrameSliceData();
243 frameSlice->UpdateReadySize(frameSlice->Size());
244 uint64_t minFrameSliceRowToBeUpdated = INVALID_UINT64;
245 SetMinFrameSliceRow(minFrameSliceRowToBeUpdated);
246 // the ready size isn't all
247 TS_CHECK_TRUE_RET(minFrameSliceRowToBeUpdated != INVALID_UINT64, true);
248 frameSlice->UpdateReadySize(minFrameSliceRowToBeUpdated);
249 TS_LOGI("minFrameSliceRowToBeUpdated=%" PRIu64 ", size=%zu, ready.size=%zu\n", minFrameSliceRowToBeUpdated,
250 frameSlice->Size(), frameSlice->readySize_);
251 for (auto &[_, frameSlices] : vsyncRenderSlice_) {
252 for (size_t idx = 0; idx < frameSlices.size(); idx++) {
253 frameSlices[idx]->frameSliceRow_ -= minFrameSliceRowToBeUpdated;
254 frameSlices[idx]->frameExpectedSliceRow_ -= minFrameSliceRowToBeUpdated;
255 }
256 }
257 for (const auto &pair : dstRenderSlice_) {
258 for (const auto &[_, frameSlice] : pair.second) {
259 frameSlice->frameSliceRow_ -= minFrameSliceRowToBeUpdated;
260 frameSlice->frameExpectedSliceRow_ -= minFrameSliceRowToBeUpdated;
261 }
262 }
263 return true;
264 }
Clear()265 void FrameFilter::Clear()
266 {
267 traceDataCache_->GetFrameSliceData()->UpdateDepth();
268 vsyncRenderSlice_.clear();
269 dstRenderSlice_.clear();
270 }
271 } // namespace TraceStreamer
272 } // namespace SysTuning
273