Android上OpenGL ES在10秒后CPU使用量大幅增加

Android上OpenGL ES在10秒后CPU使用量大幅增加,android,performance,opengl-es,Android,Performance,Opengl Es,我有一个在Android上运行的非常简单的OpenGL ES应用程序——它只加载一个纹理图集,然后在预定位置绘制一堆瓷砖 它基于本教程: 渲染大约10秒后,CPU急剧增加(如图所示),渲染每个帧所需的时间从1毫秒左右增加到14毫秒左右(在我的Nexus 5上运行) 我在onDrawFrame方法中对所有内容进行计时,这完全是GLES20.glDrawElements 我的整个渲染方法如下所示: GLES20.glUseProgram(ShaderTools.sp_Image); GLES20

我有一个在Android上运行的非常简单的OpenGL ES应用程序——它只加载一个纹理图集,然后在预定位置绘制一堆瓷砖

它基于本教程:

渲染大约10秒后,CPU急剧增加(如图所示),渲染每个帧所需的时间从1毫秒左右增加到14毫秒左右(在我的Nexus 5上运行)

我在
onDrawFrame
方法中对所有内容进行计时,这完全是
GLES20.glDrawElements

我的整个渲染方法如下所示:

GLES20.glUseProgram(ShaderTools.sp_Image);

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

int mPositionHandle = GLES20.glGetAttribLocation(ShaderTools.sp_Image, "vPosition");
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);

int mTexCoordLoc = GLES20.glGetAttribLocation(ShaderTools.sp_Image, "a_texCoord");
GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBuffer);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);

int mtrxhandle = GLES20.glGetUniformLocation(ShaderTools.sp_Image, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mtrxProjectionAndView, 0);

int mSamplerLoc = GLES20.glGetUniformLocation(ShaderTools.sp_Image, "s_texture");

GLES20.glUniform1i(mSamplerLoc, 0);

GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);

如果有人能弄清楚这可能是什么原因,以及如何纠正它,那么我将非常感激:-)

一个可能的解释是移动设备为了节省电池而限制其CPU功率。 该设备可能会发现您使用的CPU非常少,因此它会降低您的CPU电源以节省电池。 我不记得自己曾亲眼目睹过这种现象,但我知道它的存在,不确定这里的情况是否如此


编辑:在这种情况下,或许您可以测量电池使用量是否与CPU使用量呈负相关。

Nexus5基于高通公司的芯片组,具有Adreno 330 GPU

众所周知,如果您的应用程序是图形密集型应用程序/没有fps限制器/以(巨大的)本机分辨率渲染(因此不使用),高通芯片组可以快速调节GPU频率

因此,可能发生的情况是,GPU频率被限制,然后您会看到cpu使用率很高,这表示帧末尾的“cpu等待GPU”

CPU也有可能被节流,但根据我的经验,这种情况往往发生在三星手机上,因为Nexus上的情况不多

好消息是,实际上存在一种工具,用于监控高通设备上的当前CPU和GPU频率,称为,您可以在非根设备上使用它

所以你应该安装这个工具,将它配置为将GPU频率和CPU0频率显示为覆盖,然后启动你的应用程序,你将能够实时看到GPU和/或CPU是如何随着时间而变慢的


另请注意:当手机充电时,节流会更快发生。

很有趣。它看起来不像您正在做的事情,或者至少不在这里的代码中。我的第一个想法是内存泄漏,或者至少是导致频繁垃圾收集的内存使用。这不太可能与您的问题有关,但您确实不应该在draw方法中有所有这些
glGet*
调用。在init期间调用它们一次,并将位置存储在成员变量中。还有一件事:如果你有一个不同的设备,你可以尝试它,那将是一个很好的实验。它为您提供数据,提示问题是否存在于代码中,或者更可能存在于设备软件中。感谢您提供有关
glGet*
调用的提示。似乎你认为这是设备软件中的一个问题是正确的-我在我的旧手机上进行了测试(HTC Sensation XE,大约有3/4年历史,运行Android 4.4,而不是Nexus的5.1),经过进一步测试,CPU从未超过5%,它似乎与传递到
glpaurements
count
参数中的数字有关(
index.length
用于上述代码)-任何大于16382的数字都会导致此问题。不确定这是否有帮助,但我发现这是一个很好的研究。至少从这里显示的情况来看,这可能是OpenGL驱动程序中的一个问题。您可以尝试提交一个错误。测量电池的问题是,设备已插入以允许调试CPU,因此电池正在充电。。。xDI并不是说你看到手机上的电池图标。在xCode上,您可以使用仪器来检查电池的使用情况。希望Android也能做到这一点。即使手机没有充电,手机上的电池图标也明显不够准确。而不是电池,它可能被称为能源消耗或类似的东西。