我有一个项目,我需要更新纹理的多个区域,并在每一帧将这些区域同步到openGL。我正在使用openGL ES 2.0和xcode5中的项目为iDevices。
为了同步这些纹理变化,我使用glTexSubImage2D,对于绑定纹理的小区域,每帧可能会调用此函数几百次。在运行ios6的iPhone4上进行测试时,这足以满足我的需求。
当我在运行ios7的iPad Mini Retina上进行测试时,它显着停滞。 这些档位出现在mach_msg_trap中,来自glTexSubImage2D下的三个函数。
不幸的是我无法发布配置文件的图像(由于缺少信誉点),但是这三个函数是从agxuBlitRender调用的,占用了86.1%的CPU: agxuCreateRenderTarget(38.2%) SubmitPackets(25.5%) agxuReleaseAllRenderTargets(16.2%)
我很感激mach_msg_trap只是意味着线程在等待时旋转,但我无法从分析器中确定它在等待什么。
我最初想知道它是否可能正在重建mip-maps或ios7强制执行的其他一些过程。我没有打开mipmap,虽然根据gl.h中的选项,我可能没有多少选择(所有TextureMinFilters都是面向mipmap的,即使我将它设置为GL_NEAREST,它可能默认为GL_NEAREST_MIPMAP_NEAREST,如果它认为GL_NEAREST无效)。 iPhone4版本使用完全相同的代码的事实可能不是决定因素,如果它处理引擎盖下的mipmapping。
虽然我已经尝试过每帧复制一次整个纹理,但是当更大的纹理尺寸时,当在openGL的核心深处的函数twiddle32x32_32每帧占用大部分CPU时,这会变得非常慢。
感激不尽的任何帮助。
答案 0 :(得分:1)
glTexSubImage2D()在使用PowerVR GPU的所有设备上都非常慢,因为它们具有延迟渲染的基于图块的设计,并且因为它的笨拙。我更熟悉Android,您可以通过使用EGL图像扩展来获取纹理的虚拟指针并直接访问像素。这通常快4倍。但是,我已经读过iOS中也可以使用类似的功能。例如:
Using OpenGL ES texture caches instead of glReadPixels to get texture data
答案 1 :(得分:0)
调用glTexSubImage2D()“每帧数百次”非常糟糕。你应该退后一步,问问自己为什么需要这样做。它在任何平台上都会很慢,因为GPU不是为支持它而设计的。
你在做什么需要在运行时更新纹理?
如果必须,一个选项是在主存储器中保留纹理的副本(作为BGRA或LUMINENCE像素的数组)。在那里执行更新。然后通过一个呼叫将其上传到GPU。您应该只在帧的开头或结尾上传,以最大限度地减少CPU停滞。 (如果GPU当前正在使用该纹理,CPU将阻塞很长时间。)