【发布时间】:2013-09-06 10:06:03
【问题描述】:
我正在借助 NDK 和 SDL 将 C++ 2D 游戏移植到 Android;我使用 OpenGL 来渲染精灵。表演很令人失望。
经过一番调查,我发现瓶颈在于渲染过程中的 OpenGL 调用。 等一下!在粘贴经典答案之前,告诉不要更改 GL 状态,不要绑定已绑定的纹理等,请阅读以下内容。
实际上,即使我在黑屏中间显示单个 364x353 rgba 纹理,渲染也需要将近 20 毫秒。过程可以总结如下:
编辑 下面的代码用来调用glFlush()。正如 thokra 在 cmets 中指出的那样,这不是必需的。然而,删除它并没有提高性能。
glClear( GL_COLOR_BUFFER_BIT );
glBindTexture( the_texture );
glEnable(GL_BLEND);
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, colors );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, positions );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, texture_positions );
glDrawArrays( GL_TRIANGLE_FAN, 0, vertex_count );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisable(GL_BLEND);
//glFlush();
SDL_GL_SwapWindow( window );
这个函数的最后两行(flush 和 swap)的执行时间很不规律。可能需要 4 到 12 毫秒!
我在网上能找到的最好的提示是this question on StackOverflow 和这个thread on Google Groups。
StackOverflow 上的问题的答案没有任何帮助。根据问题的作者:
使用 glClear 清除与不清除帧对我来说不会影响 fps。启用/禁用混合也不行。
和
[...] 只是想看看使用压缩纹理是否会提高填充率。好像没有[…]
Google Groups 的帖子与我的问题非常相似,但作者放弃后就结束了:
所以基本上,没有办法绘制 480x854 由于纹素读取,屏幕上的图像以 60fps 的 OpenGL 速度显示 瓶颈。
说真的,不行吗?为什么调用glFlush() 和SDL_GL_SwapWindow() 需要这么长时间?为什么它如此不规则?我对此无能为力吗?
我在 SDL2 的源代码和found 中进行了快速搜索,SDL_GL_SwapWindow() 使用 Java 本机接口调用将完成工作的 Java 方法。这可能是不规则的原因吗?我该怎么办?
【问题讨论】:
-
更好的问题是,为什么要冲洗?
-
嗯……我不记得为什么
glFlush()电话会在这里,只是很久以前觉得有必要。必要的,否则我看不到精灵。你觉得我可以扔掉它吗?为什么? -
glFlush 将强制在此之前的命令尽快执行,有效地优先处理您为 GL 提供的任何工作。通常 GL 实现可以很好地确定需要执行什么以及何时执行。调用 glFlush,您告诉 GL 要做什么,从而限制执行顺序最佳的机会。它不像 glFinish 那样糟糕,它会阻塞直到完成,但在大多数应用程序中仍然是不必要的。此外,如果您没有看到精灵,则冲洗不是解决方案。只是某个地方出了点问题。
-
好的,我会尝试删除
glFlush()并尽快测试,看看是否有任何差异。尽管如此,OpenGL documentation onglFlush()告诉“所有程序都应该调用 glFlush,只要他们指望完成所有先前发出的命令。例如,在等待取决于生成图像的用户输入之前调用glFlush”。因此我对实际结果有些怀疑。 -
好吧,这就是 glFlush 被很好地指定的地方:即使之前发出的命令尚未完成,它也可能返回。因此,调用 glFlush 后直接依赖结果是不安全的。依靠glFinish之后的结果是。问题是:你真的依赖已执行的命令吗?我真的不明白你为什么会出现在你的例子中。