尽管平铺,512x512 纹理仍会在 iPhone 上造成巨大的 GPU 压力
-
22-08-2019 - |
题
我正在 iPhone 上测试我的简单 OpenGL ES 实现(一个 2D 游戏), 我注意到渲染利用率很高 使用分析器时。这些是事实:
- 我正在显示 只有一个预加载的大纹理 (512x512 像素)在 60fps 下,渲染利用率约为 40%。
- 我的纹理是使用混合的
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
, 我使用的唯一 GL 函数. - 我尝试过制作纹理 较小且平铺 它,其中 没有什么区别.
- 我使用的是 1024x1024 像素的 PNG 纹理图集
我觉得很奇怪 一个纹理导致 GPU 使用率如此之高。
这是可以预料的吗? 我究竟做错了什么?
编辑: 我的代码:
// OpenGL setup is identical to OpenGL ES template
// initState is called to setup
// timer is initialized, drawView is called by the timer
- (void) initState
{
//usual init declarations have been omitted here
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState (GL_VERTEX_ARRAY);
glVertexPointer (2,GL_FLOAT,sizeof(Vertex),&allVertices[0].x);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer (2,GL_FLOAT,sizeof(Vertex),&allVertices[0].tx);
glEnableClientState (GL_COLOR_ARRAY);
glColorPointer (4,GL_UNSIGNED_BYTE,sizeof(Vertex),&allVertices[0].r);
}
- (void) drawView
{
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat width = backingWidth /2.f;
GLfloat height = backingHeight/2.f;
glOrthof(-width, width, -height, height, -1.f, 1.f);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
[self checkGLError];
}
编辑: 我做了一些改进,但没有一个能够降低渲染利用率。我将纹理划分为 32x32 的部分,将坐标和纹理坐标的类型从 GLfloat 更改为 GLshort,并为退化三角形添加了额外的顶点。
更新内容是:
初始化状态:(顶点和纹理指针现在为 GL_SHORT)
glMatrixMode(GL_TEXTURE);
glScalef(1.f / 1024.f, 1.f / 1024.f, 1.f / 1024.f);
glMatrixMode(GL_MODELVIEW);
glScalef(1.f / 16.f, 1.f/ 16.f, 1.f/ 16.f);
绘制视图:
glDrawArrays(GL_TRIANGLE_STRIP, 0, 1536); //(16*16 parts * 6 vertices)
解决方案
其他提示
我正在编写一个应用程序,它使用 GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA 在 2D 环境中显示五个 512x512 纹理,并且我可以获得大约 14fps。你真的需要 60fps 吗?对于一场比赛,我认为24-30就可以了。另外,如果可能的话,请使用 PVR 纹理压缩。SDK 中包含一个示例。
- 我希望你没有忘记禁用
GL_BLEND
当你已经不需要它的时候。 - 您可以尝试内存带宽优化 - 使用 16 bpp 格式或 PVRTC。恕我直言,您的纹理大小纹理缓存根本没有帮助。
- 不要忘记您的帧缓冲区正被 iPhone UI 用作纹理。如果它被创建为 32 位 RGBA,它将再次进行 alpha 混合。为了获得最佳性能,16 位 565 帧缓冲区是最好的(但图形质量会受到影响)。
我不知道所有细节,例如缓存大小,但是,我想,纹理像素在上传到视频内存时已经被混合,并且三角形被 PVR 平铺引擎分割。因此你自己的分裂显得多余。
最后。这只是一款移动低功耗 GPU,并非专为大屏幕和高填充率而设计。Alpha 混合的成本很高,在 PowerVR 芯片上可能是 3-4 倍的差异。
到底是什么问题呢?
您将获得 60 fps,如丝般流畅。
谁在乎渲染利用率是否为 40%?
该问题可能是由于 iPhone 的纹理缓存大小造成的。它可能简单地归结为每个单独的三角形、四边形或三条带上有多少纹理,具体取决于您设置状态的方式。
尝试这个:细分你的四边形并重复你的测试。因此,如果您是 1 个四边形,请将其改为 4 个。然后16。等等,看看是否有帮助。关键是减少每个基元引用的实际像素数。
当纹理缓存被耗尽时,硬件会将主内存中的纹理查找搅动到为纹理缓冲区预留的任何 vram 中 每个像素. 。这会很快降低性能。
或者 - 我完全错了,因为我真的不了解 iPhone 硬件,而且我也知道 PVR 芯片与我习惯的芯片(PS2、PSP)相比是一个奇怪的野兽。但这仍然是一个简单的测试,我很好奇它是否有帮助。