Acts兼容性测评帧率测试无结果问题分析报告
1 关键字 Acts兼容性测评;FPS; 2 问题描述 OpenHarmony版本:3.2 Release 问题描述:使用 Acts-Validator 套件进行帧率测试无结果,测试终端输出卡死 测试步骤: OpenHarmony 兼容性测试网站下载对应的 Acts-Validator 测试套件; 开发板安装 ActsValidatorTest.hap 应用; 推送下载的测试资源到开发板;
1 关键字
Acts兼容性测评;FPS;
2 问题描述
OpenHarmony版本:3.2 Release
问题描述:使用 Acts-Validator 套件进行帧率测试无结果,测试终端输出卡死
测试步骤:
-
OpenHarmony 兼容性测试网站下载对应的 Acts-Validator 测试套件;
-
开发板安装 ActsValidatorTest.hap 应用;
-
推送下载的测试资源到开发板;
-
点击桌面 ActsValidatorTest 应用图标打开应用,Window系统电脑端点击.bat文件启动测试;
-
按照 ActsValidatorTest 应用内提示进行帧率性能测试;
3 问题原因
3.1 正常机制
帧率兼容性测试正常测试,并生成对应结果
3.2 异常机制
按照步骤进行帧率兼容性测试,无法获取FPS值,目录下的 DeskFPS.log 生成如下日志:
fps:0|315504090769
4 解决方案
由于统计不到帧率,需要在 display hid 中增加如下代码:
int32_t HdiDrmComposition::Apply(bool modeSet)
{
......
if(mClientLayer->GetAcceleratorType() != ACCELERATOR_DPU)
{
mClientLayer->SetReleaseFence(dup(crtcOutFence));
}
return DISPLAY_SUCCESS;
}
代码路径:device/soc/产品名/hardware/display/src/display_device/hdi_drm_composition.cpp
5 定位过程
由于使用 ActsValidatorTest.hap 没有获取到测试 FPS 结果,于是使用 GP_daemon_fps 工具命令开始开始定位问题。
在终端输入以下命令:
GP_daemon_fps 10 | grep fps
运行指令后,也无法获取 fps
C:\Users\BF>hdc shell
# GP_daemon_fps 10 | grep fps
fps:0|10822095
fps:0|10822666
fps:0|10823668
fps:0|10824666
fps:0|10825669
fps:0|10826668
fps:0|10827667
fps:0|10828667
fps:0|10829670
fps:0|10830670
查看 GP_daemon_fps 工具源码,GP_daemon_fps 工具获取 fps 是通过 hidumper 指令获取的。
static FpsInfo GetSurfaceFrame(std::string name, FpsConfig &fpsConfig)
{
......
std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
std::string cmdExc = cmd;
FILE *fp = popen(cmdExc.c_str(), "r");
......
}
源码路径:developtools/profiler/host/smartperf/client/client_command_fps/main.cpp
运行 hidumper 命令获取当前 Node 节点,通过 Node 节点获取 fps
运行 hidumper 命令 ,获取到 settings0 Node 节点 (当前开发板的主界面显示 Settings 应用)
# hidumper -s 10 -a surface | grep surface
surface [EntryView] NodeId[3418793967626] LayerId[19]:
surface [settings0] NodeId[3418793967630] LayerId[20]:
surface [SystemUi_StatusBar] NodeId[3418793967620] LayerId[21]:
surface [SystemUi_PrivacyIndicator] NodeId[3418793967622] LayerId[22]:
通过 settings0 节点,执行 hidumper 命令获取当前的帧率时间戳的 buffer。在执行指令后,获取的 buffer 没有更新
# hidumper -s 10 -a "fps settings0"
-------------------------------[ability]-------------------------------
----------------------------------RenderService---------------------------------
-- The recently fps records info of screens:
surface [settings0] Id[3418793967630]:
16806205865518
16806205865518
16806205865518
16806205865518
......
hdi_backend.cpp 文件中的 Repaint 方法调用 fence 相关的接口,获取 fence 刷新的时间戳,Repaint 方法则记录这个时间戳并更新对应的 dump 文件中,执行 hidumper 命令后,解析出对应的时间戳
在 Repaint 方法中获取时间戳后增加日志打印,再次执行 hidumper 命令后,过滤对应的日志,该时间戳没有变化
void HdiBackend::Repaint(std::vector<OutputPtr> &outputs)
{
ScopedBytrace bytrace(__func__);
HLOGD("%{public}s: start", __func__);
......
int32_t ret = DISPLAY_SUCCESS;
for (auto &output : outputs) {
......
int64_t timestamp = lastPresentFence_->SyncFileReadTimestamp();
HLOGI("timestamp %{public}s: ", std::to_string(timestamp).c_str()); // 增加日志打印log
bool startSample = false;
if (timestamp != SyncFence::FENCE_PENDING_TIMESTAMP) {
startSample = sampler_->AddPresentFenceTime(timestamp);
output->RecordCompositionTime(timestamp);
for (auto iter = layersMap.begin(); iter != layersMap.end(); ++iter) {
const LayerPtr &layer = iter->second;
layer->RecordPresentTime(timestamp);
}
}
......
HLOGD("%{public}s: end", __func__);
}
}
文件路径:foundation/graphic/graphic_2d/rosen/modules/composer/hdi_backend/src/hdi_backend.cpp
GetFenceInfo 调用内核 ioctl 方法获取 fence 记录的信息
ns_sec_t SyncFence::SyncFileReadTimestamp()
{
std::vector<SyncPointInfo> ptInfos = GetFenceInfo();
if (ptInfos.empty()) {
return FENCE_PENDING_TIMESTAMP;
}
......
}
std::vector<SyncPointInfo> SyncFence::GetFenceInfo()
{
struct sync_file_info arg;
struct sync_file_info *infoPtr = nullptr;
(void)memset_s(&arg, sizeof(struct sync_file_info), 0, sizeof(struct sync_file_info));
int32_t ret = ioctl(fenceFd_, SYNC_IOC_FILE_INFO, &arg);
......
size_t syncFileInfoMemSize = sizeof(struct sync_file_info) + sizeof(struct sync_fence_info) * arg.num_fences;
infoPtr = (struct sync_file_info *)malloc(syncFileInfoMemSize);
if (infoPtr == nullptr) {
HiLog::Debug(LABEL, "GetFenceInfo malloc failed oom");
return {};
}
(void)memset_s(infoPtr, syncFileInfoMemSize, 0, syncFileInfoMemSize);
infoPtr->num_fences = arg.num_fences;
infoPtr->sync_fence_info = static_cast<uint64_t>(uintptr_t(infoPtr + 1));
......
std::vector<SyncPointInfo> infos;
const auto fenceInfos = (struct sync_fence_info *)(uintptr_t)(infoPtr->sync_fence_info);
for (uint32_t i = 0; i < infoPtr->num_fences; i++) {
infos.push_back(SyncPointInfo { fenceInfos[i].timestamp_ns,
static_cast<FenceStatus>(fenceInfos[i].status) } );
}
free(infoPtr);
return infos;
}
文件路径:foundation/graphic/graphic_2d/utils/sync_gence/src/sync_fence.cpp
底层 hdi_display 会将 signal 信号量传递给 fence。具体查看 hdi_drm_composition.cpp 中的方法
int32_t HdiDrmComposition::Apply(bool modeSet)
{
......
if(mClientLayer->GetAcceleratorType() != ACCELERATOR_DPU)
{
mClientLayer->SetReleaseFence(dup(crtcOutFence));
}
return DISPLAY_SUCCESS;
}
6 知识分享
HiDumper是OpenHarmony中为开发、测试人员,IDE工具提供统一的系统信息获取工具,帮助使用者分析,定位问题。 更多HiDumper信息参考
更多推荐
所有评论(0)