106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include <string>
1706f6ba60Sopenharmony_ci#include <sstream>
1806f6ba60Sopenharmony_ci#include "include/sp_log.h"
1906f6ba60Sopenharmony_ci#include "include/sp_utils.h"
2006f6ba60Sopenharmony_ci#include "include/GpuCounter.h"
2106f6ba60Sopenharmony_ci#include "include/GpuCounterCallback.h"
2206f6ba60Sopenharmony_ci
2306f6ba60Sopenharmony_cinamespace OHOS {
2406f6ba60Sopenharmony_ci    namespace SmartPerf {
2506f6ba60Sopenharmony_ci        GpuCounterCallbackImpl::GpuCounterCallbackImpl()
2606f6ba60Sopenharmony_ci        {
2706f6ba60Sopenharmony_ci            GpuPerfInfo firstData;
2806f6ba60Sopenharmony_ci            firstData.startTime = SPUtils::GetCurTime();
2906f6ba60Sopenharmony_ci            firstData.duration = 0;
3006f6ba60Sopenharmony_ci            firstData.gpuActive = 0;
3106f6ba60Sopenharmony_ci            firstData.drawCalls = 0;
3206f6ba60Sopenharmony_ci            firstData.primitives = 0;
3306f6ba60Sopenharmony_ci            firstData.vertexCounts = 0;
3406f6ba60Sopenharmony_ci            firstData.totalInstruments = 0;
3506f6ba60Sopenharmony_ci            firstData.gpuLoadPercentage = 0;
3606f6ba60Sopenharmony_ci            firstData.vertexLoadPercentage = 0;
3706f6ba60Sopenharmony_ci            firstData.fragmentLoadPercentage = 0;
3806f6ba60Sopenharmony_ci            firstData.computeLoadPercentage = 0;
3906f6ba60Sopenharmony_ci            firstData.textureLoadPercentage = 0;
4006f6ba60Sopenharmony_ci            firstData.memoryReadBandwidth = 0;
4106f6ba60Sopenharmony_ci            firstData.memoryWriteBandwidth = 0;
4206f6ba60Sopenharmony_ci            firstData.memoryBandwidthPercentage = 0;
4306f6ba60Sopenharmony_ci            firstData.remainTime = maxTime;
4406f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData = firstData;
4506f6ba60Sopenharmony_ci            gpuCounter.push_back(firstData);
4606f6ba60Sopenharmony_ci        }
4706f6ba60Sopenharmony_ci
4806f6ba60Sopenharmony_ci
4906f6ba60Sopenharmony_ci        unsigned long long GpuCounterCallbackImpl::JoinSocketDataPercentFunction(uint32_t itemFirst,
5006f6ba60Sopenharmony_ci            int32_t durationFirst, uint32_t itemSecond, int32_t durationSecond) const
5106f6ba60Sopenharmony_ci        {
5206f6ba60Sopenharmony_ci            return (static_cast<unsigned long long>(itemFirst) * static_cast<unsigned long long>(durationFirst) +
5306f6ba60Sopenharmony_ci                static_cast<unsigned long long>(itemSecond) * static_cast<unsigned long long>(durationSecond)) /
5406f6ba60Sopenharmony_ci                (static_cast<unsigned long long>(durationFirst) + static_cast<unsigned long long>(durationSecond));
5506f6ba60Sopenharmony_ci        }
5606f6ba60Sopenharmony_ci
5706f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::JoinSocketDataValue(GpuPerfInfo *newData)
5806f6ba60Sopenharmony_ci        {
5906f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.gpuActive += newData->gpuActive;
6006f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.drawCalls += newData->drawCalls;
6106f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.primitives += newData->primitives;
6206f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.vertexCounts += newData->vertexCounts;
6306f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.totalInstruments += newData->totalInstruments;
6406f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.memoryReadBandwidth += newData->memoryReadBandwidth;
6506f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.memoryWriteBandwidth += newData->memoryWriteBandwidth;
6606f6ba60Sopenharmony_ci        }
6706f6ba60Sopenharmony_ci
6806f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::JoinSocketDataPercent(GpuPerfInfo *newData)
6906f6ba60Sopenharmony_ci        {
7006f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.gpuLoadPercentage = JoinSocketDataPercentFunction(
7106f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.gpuLoadPercentage, realtimeGpuPerfInfoData.duration,
7206f6ba60Sopenharmony_ci                newData->gpuLoadPercentage, newData->duration);
7306f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.vertexLoadPercentage = JoinSocketDataPercentFunction(
7406f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.vertexLoadPercentage, realtimeGpuPerfInfoData.duration,
7506f6ba60Sopenharmony_ci                newData->vertexLoadPercentage, newData->duration);
7606f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.fragmentLoadPercentage = JoinSocketDataPercentFunction(
7706f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.fragmentLoadPercentage, realtimeGpuPerfInfoData.duration,
7806f6ba60Sopenharmony_ci                newData->fragmentLoadPercentage, newData->duration);
7906f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.computeLoadPercentage = JoinSocketDataPercentFunction(
8006f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.computeLoadPercentage, realtimeGpuPerfInfoData.duration,
8106f6ba60Sopenharmony_ci                newData->computeLoadPercentage, newData->duration);
8206f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.textureLoadPercentage = JoinSocketDataPercentFunction(
8306f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.textureLoadPercentage, realtimeGpuPerfInfoData.duration,
8406f6ba60Sopenharmony_ci                newData->textureLoadPercentage, newData->duration);
8506f6ba60Sopenharmony_ci        }
8606f6ba60Sopenharmony_ci
8706f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::JoinSocketData(GpuPerfInfo *newData)
8806f6ba60Sopenharmony_ci        {
8906f6ba60Sopenharmony_ci            JoinSocketDataValue(newData);
9006f6ba60Sopenharmony_ci            JoinSocketDataPercent(newData);
9106f6ba60Sopenharmony_ci
9206f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.duration += newData->duration;
9306f6ba60Sopenharmony_ci        }
9406f6ba60Sopenharmony_ci
9506f6ba60Sopenharmony_ci        unsigned long long GpuCounterCallbackImpl::SplitSocketDataValueFunction(uint32_t value, int32_t interval,
9606f6ba60Sopenharmony_ci            int32_t duration) const
9706f6ba60Sopenharmony_ci        {
9806f6ba60Sopenharmony_ci            return static_cast<unsigned long long>(value) *
9906f6ba60Sopenharmony_ci                static_cast<unsigned long long>(interval) /
10006f6ba60Sopenharmony_ci                static_cast<unsigned long long>(duration);
10106f6ba60Sopenharmony_ci        }
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::SplitSocketDataValue(int32_t interval)
10406f6ba60Sopenharmony_ci        {
10506f6ba60Sopenharmony_ci            GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
10606f6ba60Sopenharmony_ci
10706f6ba60Sopenharmony_ci            unsigned long long gpuActiveTargetValue = SplitSocketDataValueFunction(
10806f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.gpuActive, interval,
10906f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
11006f6ba60Sopenharmony_ci            unsigned long long drawCallsTargetValue = SplitSocketDataValueFunction(
11106f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.drawCalls, interval,
11206f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
11306f6ba60Sopenharmony_ci            unsigned long long primitivesTargetValue = SplitSocketDataValueFunction(
11406f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.primitives, interval,
11506f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
11606f6ba60Sopenharmony_ci            unsigned long long vertexCountsTargetValue = SplitSocketDataValueFunction(
11706f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.vertexCounts, interval,
11806f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
11906f6ba60Sopenharmony_ci            unsigned long long totalInstrumentsTargetValue = SplitSocketDataValueFunction(
12006f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.totalInstruments, interval,
12106f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
12206f6ba60Sopenharmony_ci            unsigned long long memoryReadBandwidthTargetValue = SplitSocketDataValueFunction(
12306f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.memoryReadBandwidth, interval,
12406f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
12506f6ba60Sopenharmony_ci            unsigned long long memoryWriteBandwidthTargetValue = SplitSocketDataValueFunction(
12606f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.memoryWriteBandwidth, interval,
12706f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.duration);
12806f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
12906f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.gpuActive - gpuActiveTargetValue) + "_");
13006f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
13106f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.drawCalls - drawCallsTargetValue) + "_");
13206f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
13306f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.primitives - primitivesTargetValue) + "_");
13406f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
13506f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.vertexCounts - vertexCountsTargetValue) + "_");
13606f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
13706f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.totalInstruments - totalInstrumentsTargetValue) + "_");
13806f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
13906f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.memoryReadBandwidth - memoryReadBandwidthTargetValue) + "_");
14006f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
14106f6ba60Sopenharmony_ci                realtimeGpuPerfInfoData.memoryWriteBandwidth - memoryWriteBandwidthTargetValue) + "_");
14206f6ba60Sopenharmony_ci
14306f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.gpuActive = gpuActiveTargetValue;
14406f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.drawCalls = drawCallsTargetValue;
14506f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.primitives = primitivesTargetValue;
14606f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.vertexCounts = vertexCountsTargetValue;
14706f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.totalInstruments = totalInstrumentsTargetValue;
14806f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.memoryReadBandwidth = memoryReadBandwidthTargetValue;
14906f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.memoryWriteBandwidth = memoryWriteBandwidthTargetValue;
15006f6ba60Sopenharmony_ci        }
15106f6ba60Sopenharmony_ci
15206f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::SplitSocketDataPercent()
15306f6ba60Sopenharmony_ci        {
15406f6ba60Sopenharmony_ci            GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
15506f6ba60Sopenharmony_ci
15606f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(
15706f6ba60Sopenharmony_ci                std::to_string(realtimeGpuPerfInfoData.gpuLoadPercentage) + "_");
15806f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(
15906f6ba60Sopenharmony_ci                std::to_string(realtimeGpuPerfInfoData.vertexLoadPercentage) + "_");
16006f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(
16106f6ba60Sopenharmony_ci                std::to_string(realtimeGpuPerfInfoData.fragmentLoadPercentage) + "_");
16206f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(
16306f6ba60Sopenharmony_ci                std::to_string(realtimeGpuPerfInfoData.computeLoadPercentage) + "_");
16406f6ba60Sopenharmony_ci            gpuCounterInstance.AddGpuCounterRealtimeData(
16506f6ba60Sopenharmony_ci                std::to_string(realtimeGpuPerfInfoData.textureLoadPercentage) + ";");
16606f6ba60Sopenharmony_ci        }
16706f6ba60Sopenharmony_ci
16806f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::SplitSocketData()
16906f6ba60Sopenharmony_ci        {
17006f6ba60Sopenharmony_ci            int32_t interval = realtimeGpuPerfInfoData.duration - maxDuration;
17106f6ba60Sopenharmony_ci            SplitSocketDataValue(interval);
17206f6ba60Sopenharmony_ci            SplitSocketDataPercent();
17306f6ba60Sopenharmony_ci            realtimeGpuPerfInfoData.duration = interval;
17406f6ba60Sopenharmony_ci        }
17506f6ba60Sopenharmony_ci
17606f6ba60Sopenharmony_ci        void GpuCounterCallbackImpl::GetRealTime(GpuPerfInfo *newData)
17706f6ba60Sopenharmony_ci        {
17806f6ba60Sopenharmony_ci            GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
17906f6ba60Sopenharmony_ci
18006f6ba60Sopenharmony_ci            JoinSocketData(newData);
18106f6ba60Sopenharmony_ci            if ((realtimeGpuPerfInfoData.duration == 0) || (newData->duration == 0)) {
18206f6ba60Sopenharmony_ci                return;
18306f6ba60Sopenharmony_ci            }
18406f6ba60Sopenharmony_ci            gpuCounterInstance.GetRealtimeDataLock().lock();
18506f6ba60Sopenharmony_ci            while (realtimeGpuPerfInfoData.duration >= maxDuration) {
18606f6ba60Sopenharmony_ci                SplitSocketData();
18706f6ba60Sopenharmony_ci            }
18806f6ba60Sopenharmony_ci            gpuCounterInstance.GetRealtimeDataLock().unlock();
18906f6ba60Sopenharmony_ci        }
19006f6ba60Sopenharmony_ci
19106f6ba60Sopenharmony_ci        int GpuCounterCallbackImpl::OnGpuData(std::vector <GpuPerfInfo> &gpuPerfInfos)
19206f6ba60Sopenharmony_ci        {
19306f6ba60Sopenharmony_ci            GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
19406f6ba60Sopenharmony_ci
19506f6ba60Sopenharmony_ci            for (auto gpuPerfInfo : gpuPerfInfos) {
19606f6ba60Sopenharmony_ci                unsigned int gpuCounterBackSize = gpuCounter.size();
19706f6ba60Sopenharmony_ci                gpuCounter.push_back(gpuPerfInfo);
19806f6ba60Sopenharmony_ci                unsigned int gpuCounterSize = gpuCounter.size();
19906f6ba60Sopenharmony_ci                if (gpuCounterSize <= gpuCounterBackSize) {
20006f6ba60Sopenharmony_ci                    LOGE("gpuCounter data len error!");
20106f6ba60Sopenharmony_ci                    return -1;
20206f6ba60Sopenharmony_ci                }
20306f6ba60Sopenharmony_ci                GpuPerfInfo *newData = &gpuCounter[gpuCounterSize - 1];
20406f6ba60Sopenharmony_ci                GpuPerfInfo *backData = &gpuCounter[gpuCounterSize - 2];
20506f6ba60Sopenharmony_ci                long long durationTime = newData->startTime - backData->startTime;
20606f6ba60Sopenharmony_ci
20706f6ba60Sopenharmony_ci                // 如果两次数据间隔过短,则舍弃新数据
20806f6ba60Sopenharmony_ci                if (durationTime < collectInterval) {
20906f6ba60Sopenharmony_ci                    LOGE("Start time(%lld, %lld) make duration time(%lld) too short",
21006f6ba60Sopenharmony_ci                         newData->startTime, backData->startTime, durationTime);
21106f6ba60Sopenharmony_ci                    gpuCounter.pop_back();
21206f6ba60Sopenharmony_ci                    continue;
21306f6ba60Sopenharmony_ci                }
21406f6ba60Sopenharmony_ci
21506f6ba60Sopenharmony_ci                backData->duration = durationTime;
21606f6ba60Sopenharmony_ci
21706f6ba60Sopenharmony_ci                std::ostringstream oss;
21806f6ba60Sopenharmony_ci                oss << backData->startTime << ","
21906f6ba60Sopenharmony_ci                    << backData->duration << ","
22006f6ba60Sopenharmony_ci                    << backData->gpuActive << ","
22106f6ba60Sopenharmony_ci                    << backData->drawCalls << ","
22206f6ba60Sopenharmony_ci                    << backData->primitives << ","
22306f6ba60Sopenharmony_ci                    << backData->vertexCounts << ","
22406f6ba60Sopenharmony_ci                    << backData->totalInstruments << ","
22506f6ba60Sopenharmony_ci                    << backData->gpuLoadPercentage << ","
22606f6ba60Sopenharmony_ci                    << backData->vertexLoadPercentage << ","
22706f6ba60Sopenharmony_ci                    << backData->fragmentLoadPercentage << ","
22806f6ba60Sopenharmony_ci                    << backData->computeLoadPercentage << ","
22906f6ba60Sopenharmony_ci                    << backData->textureLoadPercentage << ","
23006f6ba60Sopenharmony_ci                    << backData->memoryReadBandwidth << ","
23106f6ba60Sopenharmony_ci                    << backData->memoryWriteBandwidth << ","
23206f6ba60Sopenharmony_ci                    << backData->memoryBandwidthPercentage << ",";
23306f6ba60Sopenharmony_ci                gpuCounterInstance.GetGpuCounterData().push_back(oss.str());
23406f6ba60Sopenharmony_ci                gpuCounterInstance.GetGpuCounterSaveReportData().push_back(oss.str());
23506f6ba60Sopenharmony_ci
23606f6ba60Sopenharmony_ci                GetRealTime(backData);
23706f6ba60Sopenharmony_ci            }
23806f6ba60Sopenharmony_ci
23906f6ba60Sopenharmony_ci            if (gpuPerfInfos[0].remainTime <= restartTime) {
24006f6ba60Sopenharmony_ci                LOGI("remain time to restart");
24106f6ba60Sopenharmony_ci                gpuCounterInstance.StartCollect(GpuCounter::GC_RESTART);
24206f6ba60Sopenharmony_ci            }
24306f6ba60Sopenharmony_ci            return 0;
24406f6ba60Sopenharmony_ci        }
24506f6ba60Sopenharmony_ci    }
24606f6ba60Sopenharmony_ci}