如何获取Power VR GPU数据

什么是Power VR

PowerVR 是Imagination公司生产的一种GPU系列。早期的苹果A系列芯片优秀的GPU性能大多是基于Power VR GPU实现的。从早期的游戏机实体建模到现在的移动终端设备图形计算中都能够见到它的身影,虽中间有多次动荡,至今依旧在汽车HMI系统中占据着比较大的份额。

如何获取Power VR GPU数据

虽然对于Power VR的GPU,近期已经很难见到了。不过依旧还是有不少性价比手机内部使用的是Power VR,而Imagination也很给力,把对应的API全都开源了,所以相比Adreno和Mali就方便不少。我们可以直接从开源代码中直接学习。

https://github.com/powervr-graphics/Native_SDKicon-default.png?t=M85Bhttps://github.com/powervr-graphics/Native_SDK在这个PowerVR开源的SDK中,包含了多个Demo,这边主要介绍的是如何获取性能数据。

我们以vulkan为例,将该项目clone到本地之后,进入到以下路径“Native_SDK/examples/Vulkan/PVRScopeExample/”

这边我们可以简单地使用Android Studio打开build-android文件夹,就会直接加载对应的库内容。其中可能存在这样一些问题。

Android存在的问题

1. Cmake路径没有指定(cmake没有识别出来)

com.intellij.openapi.externalSystem.model.ExternalSystemException (no error message)

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
com.intellij.openapi.externalSystem.model.ExternalSystemException: 
	at org.jetbrains.plugins.gradle.model.ProjectImportAction.addBuildModels(ProjectImportAction.java:258)
	at org.jetbrains.plugins.gradle.model.ProjectImportAction.execute(ProjectImportAction.java:116)
	at org.jetbrains.plugins.gradle.model.ProjectImportAction.execute(ProjectImportAction.java:41)
	at org.gradle.tooling.internal.consumer.connection.InternalBuildActionAdapter.execute(InternalBuildActionAdapter.java:64)
	at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner$ActionRunningListener.runAction(ClientProvidedPhasedActionRunner.java:120)
	at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner$ActionRunningListener.run(ClientProvidedPhasedActionRunner.java:110)
	at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner$ActionRunningListener.buildFinished(ClientProvidedPhasedActionRunner.java:104)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	

这个问题就是配置问题,可以在local.properties中设置cmake的路径,在里面加上

cmake.dir=D\:\\SDK\\cmake\\3.18.1

具体路径根据用户计算机的cmake路径和版本决定。

主要还是因为Android Studio上默认安装的cmake和配置要求的版本号不匹配。

2. NDK路径问题

同样的,在local.properties中设置ndk的路径,在里面加上

ndk.dir=D\:\\SDK\\ndk\\21.4.7075529

具体的路径依旧是根据用户计算机中的ndk路径配置。

加载完成

正确加载Android Studio后,会在Gradle Scipts下面出现其他几个module的build.gradle文件,这是因为即便是简单的PVRScope Example也是需要依赖于其他Module的。

这时候只需要点击菜单栏 Build->Build Bundle(s)/APK(s)->Build APK(s)即可。

但是这时候感觉会有点懵逼,因为打开主要的Java文件中,我们只会看到一个简单的Java文件,内容也很简单,如下:

package com.powervr.VulkanPVRScopeExample;


import android.app.NativeActivity;
import android.os.Bundle;
import android.widget.Toast;
import android.view.Gravity;

public class VulkanPVRScopeExample extends NativeActivity
{
	public void displayExitMessage(final String text) 
	{
		runOnUiThread(new Runnable() {
		public void run() {
			Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG);
			toast.setGravity(Gravity.CENTER, 0, 0);
			toast.show();
		}
		});
	}
}

那么这个APK的核心究竟在哪里呢?

这时候可以注意到,这个Class继承的是NativeActivity,因此主要的代码应该是外围的C源码。

C++ Android 源码

该源码主要指的是VulkanPVRScopeExample.cpp文件

包括initApplication, initView, releaseView, quitApplication和renderFrame,我们都能很清楚的看懂内部逻辑,但是对于C/C++不太熟悉的就会比较困难了。

这个文件中主要是对于UI框架和显示以及动作的一些描写,如果要关注具体的值获取可以跳过。

C++获取图形数据

该源码主要指的是PVRScopeGraph.h和PVRScopeGraph.cpp文件

在源码中,构建了

class PVRScopeGraph

用于直接获取PVR的图形数据。在里面封装了如下方法,主要也是通过调用如下方法获取所需的图形图像数据。

    uint32_t getActiveGroup() const { return activeGroup; }
	float getMaximumOfData(uint32_t nCounter);
	float getMaximum(uint32_t nCounter);
	void setMaximum(uint32_t nCounter, float fMaximum);
	float getStandardFPS() const;
	int32_t getStandardFPSIndex() const;
	float getStandard2D() const;
	int32_t getStandard2DIndex() const;
	float getStandard3D() const;
	int32_t getStandard3DIndex() const;
	float getStandardTA() const;
	int32_t getStandardTAIndex() const;
	float getStandardCompute() const;
	int32_t getStandardComputeIndex() const;
	float getStandardShaderPixel() const;
	int32_t getStandardShaderPixelIndex() const;
	float getStandardShaderVertex() const;
	int32_t getStandardShaderVertexIndex() const;
	float getStandardShaderCompute() const;
	int32_t getStandardShaderComputeIndex() const;
	uint32_t getCounterNum() const { return numCounter; }
	const char* getCounterName(const uint32_t i) const;
	int getCounterGroup(const uint32_t i) const;

如果要开发对应的C++应用就很方便,但是如果要在Android使用Jni的方法编写对应的app就非常麻烦,需要在setting.gradle中将所有的模块Include进来,这多种依赖又是一个比较大的工程,容易牵一发而动全身,显然不是一个非常方便的做法。

另辟蹊径

我这边的目标主要是通过APK或者app_process的方式获取手机内的Power VR的图形图像信息,最好还是能够通过Java或者kotlin + Jni的方式实现,比起include这么多module,如果能够直接把需要的内容剥离出来就好了。

https://github.com/powervr-graphics/PVRMonitoricon-default.png?t=M85Bhttps://github.com/powervr-graphics/PVRMonitorPowerVR官方还提供了一个apk的项目,里面很简单地将Scope内容剥离出来,倒是可以直接小修小改用上。

该项目使用Jni的方式调用了PVRScopeGraph和CpuMetrics(顺便),不过项目时间比较长,实际使用起来会发现在现在(date up to 2022)的一些设备,甚至是早期的Redmi 9A手机,都不是很支持的样子。这是因为对应的内容需要修改。

修改方式

1. 更换.so文件

在上一节中说到了,最好是将各种Module直接剥离出来,这边就是采取了这样的思路,将各种需要的模块编译出libPVRScopeDeveloper.so,然后直接调用里面的方法,里面的方法在PVRScopeStats.h里面,可以进行参考。

但是存在的问题在于,这个项目的so文件过于老旧,所以需要更换最新的,需要自己编译出新版的libPVRScopeDeveloper.so文件,当然也可以下载官方的PVRTune Developers,然后寻找对应的so文件拷贝出来替换。

2. 添加初始化代码

在PVRScopeHUD.cpp文件中的initialisePVRScope()方法中,本意是用来初始化PVR数据读取的,但是在初始化的过程中获取了一次Counter,而在PVRScopeStats.h中有说明,在获取Counter数据前需要不时地调用PVRScopeReadCounters方法,所以在该方法的

//Initialise the counter data structures.

之前,最好加上一句

readCounters(true); // this method is defined in the class

直接调用了原项目已经封装好的readcounters,再获取一次Counter数据就能够不出问题了。

猜你喜欢

转载自blog.csdn.net/u013379032/article/details/128097520
VR
今日推荐