Ian*_*Ian 5 graphics android opengl-es timing
我正在使用OpenGL ES 2开发一个Android应用程序.我遇到的问题是该glClear()功能需要很长时间才能处理,因为帧延迟会导致游戏显得紧张.具有定时探针的程序运行的输出显示,虽然设置来自图集的所有顶点和图像仅需要不到1毫秒,但glClear()需要10到20毫秒.事实上,清算通常占总渲染时间的95%.我的代码基于常见教程,Render功能如下:
private void Render(float[] m, short[] indices) {
Log.d("time", "--START RENDER--");
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "vPosition");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, true,
0, vertexBuffer);
// Get handle to texture coordinates location
int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "a_texCoord" );
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
// Get handle to shape's transformation matrix
int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
// Get handle to textures locations
int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image, "s_texture" );
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i ( mSamplerLoc, 0);
long clearTime = System.nanoTime();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Log.d("time", "Clear time is " + (System.nanoTime() - clearTime));
// Draw the triangles
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
Log.d("time", "--END RENDER--");
}
Run Code Online (Sandbox Code Playgroud)
我试过移动png atlas/drawable-nodpi但它没有效果.
我也尝试过使用glFlush()和glFinish()函数.有趣的是,如果我不打电话,glClear()那么必须自动调用它.这是因为总渲染时间仍然与调用时一样高,并且屏幕上没有前一帧的残余.只有第一次通话glClear()才是耗时的.如果再次调用,则后续调用仅为1或2毫秒.
我也尝试了不同的参数组合(例如GLES20.GL_DEPTH_BUFFER_BIT)和使用glClearColor().晴朗的时间仍然很高.
先感谢您.
你没有衡量你的想法.测量OpenGL API调用的耗用时间大多没有意义.
要理解的关键方面是OpenGL是一种将工作传递给GPU的API.最简单的心理模型(在很大程度上与现实相对应)是,当您进行OpenGL API调用时,您会将稍后提交给GPU的工作排队.例如,如果您glDraw*()拨打电话,请记录构建排队的工作项的呼叫,稍后将提交给GPU执行.
换句话说,API是高度异步的.通过API调用请求的工作在调用返回时尚未完成.在大多数情况下,它甚至没有提交给GPU执行.它只排队等候,稍后会提交,大部分时间都在您的控制之外.
这种一般方法的结果是,您进行glClear()呼叫测量的时间几乎与清除帧缓冲区所需的时间无关.
现在我们已经确定了OpenGL API是如何异步的,下一个要理解的概念是需要一定程度的同步.
让我们看一下整体吞吐量受GPU限制的工作负载(通过GPU性能,或者因为帧速率受显示器刷新限制).如果我们保持整个系统完全异步,并且CPU可以比GPU处理它们更快地生成GPU命令,那么我们将排队逐渐增加的工作量.出于以下几个原因,这是不可取的:
为避免这种情况,驱动程序使用限制机制来防止CPU过远.如何处理这个问题的细节可能相当复杂.但作为一个简单的模型,它可能就像在GPU完成渲染之前超过1-2帧时阻塞CPU.理想情况下,您总是希望排队等待一些工作,以便GPU永远不会为图形有限的应用程序闲置,但您希望尽可能减少排队的工作量,以最大限度地减少内存使用和延迟.
通过解释所有这些背景信息,您的测量结果应该不那么令人惊讶.到目前为止,最可能的情况是您的glClear()呼叫会触发同步,您测量的时间是GPU充分赶上的时间,直到提交更多工作是有意义的.
请注意,这并不意味着所有先前提交的工作都需要完成.让我们看看一个有点假设的序列,但足够现实,以说明可能发生的事情:
glClear()构成渲染帧开始的调用n.n - 3在显示器上,并且GPU正忙于处理帧的渲染命令n - 2.glClear()调用,直到GPU完成帧的渲染命令n - 2.n - 2显示屏上显示帧,这意味着等待下一个光束同步.n - 2在显示器上,之前包含帧的缓冲区n - 3不再使用.它现在可以用于帧n,这意味着现在可以提交glClear()帧命令n.请注意,虽然您的glClear()调用在此场景中进行了各种等待,而您在API调用中花费的时间的一部分,但是没有一次用于实际清除帧的帧缓冲区.您可能只是坐在某种信号量(或类似的同步机制)上,等待GPU完成以前提交的工作.
考虑到您的测量结果毕竟没有直接帮助,您可以从中学到什么?不幸的是不是很多.
如果您确实观察到您的帧速率不符合您的目标,例如因为您观察到口吃,或者甚至更好,因为您在一定时间段内测量帧速率,您唯一确定的是渲染速度太慢.进入性能分析的细节是一个对于这种格式来说太大的话题.只是为了简要介绍一下您可以采取的步骤:
| 归档时间: |
|
| 查看次数: |
1198 次 |
| 最近记录: |