Android glReadPixels到EGLImage将纹理速度比glReadPixels到ByteBuffer和glTexSubImage2D慢?

Android glReadPixels到EGLImage将纹理速度比glReadPixels到ByteBuffer和glTexSubImage2D慢?,android,opengl-es,opengl-es-2.0,egl,Android,Opengl Es,Opengl Es 2.0,Egl,我有一个Android OpenGL ES应用程序,具有两个线程。将线程1称为“显示线程”,该线程将其当前纹理与线程2发出的纹理“混合”,也称为“工作线程”。线程2执行屏幕外渲染(渲染到纹理),然后线程1将此纹理与其自身的纹理相结合,以生成显示给用户的帧 我有一个有效的解决方案,但我知道它是低效的,我正在努力改进它。在其OnSurfaceCreated()方法中,线程1创建两个纹理。线程2在其draw方法中,将glReadPixels()转换为ByteBuffer(我们将其称为bb)。然后,线程

我有一个Android OpenGL ES应用程序,具有两个线程。将线程1称为“显示线程”,该线程将其当前纹理与线程2发出的纹理“混合”,也称为“工作线程”。线程2执行屏幕外渲染(渲染到纹理),然后线程1将此纹理与其自身的纹理相结合,以生成显示给用户的帧

我有一个有效的解决方案,但我知道它是低效的,我正在努力改进它。在其OnSurfaceCreated()方法中,线程1创建两个纹理。线程2在其draw方法中,将glReadPixels()转换为ByteBuffer(我们将其称为bb)。然后,线程2向线程1发出新帧准备就绪的信号,此时线程1调用glTexSubImage2D(bb)以使用来自线程2的新数据更新其纹理,并继续进行“混合”以生成新帧

这种架构在一些Android设备上比其他设备工作得更好,而且我已经能够通过使用PBOs获得性能上的轻微改进。但我认为,通过EGL图像扩展()使用所谓的“直接纹理”,我可以通过消除昂贵的glTexSubImage2D()调用获得一些好处。是的,我仍然有glReadPixels()调用,这仍然困扰着我,但至少我应该衡量一些改进。事实上,至少在三星Galaxy Tab S(Mali T628 GPU)上,我的新代码比以前慢了很多!这怎么可能

在新代码中,线程1使用gralloc实例化EGLImage对象,并继续将其绑定到纹理:

//注意gbuffer::create()是gralloc的包装器
buffer=gbuffer::create(宽度、高度、gbuffer::FORMAT_RGBA_8888);
EGLClientBuffer anb=buffer->getNativeBuffer();
EGLImageKHR pEGLImage=_eglCreateImageKHR(eglGetCurrentDisplay(),EGL_NO_上下文,EGL_NATIVE_BUFFER_ANDROID,(EGLClientBuffer)anb,attrs);
glBindTexture(GL_TEXTURE_2D,texid);//来自glGenTextures的texid(…)

_glEGLImageTargetTexture2DOES(GL_纹理,pEGLImage)基于对您试图做的事情的描述,这两种方法听起来都比必要的更复杂、更低效

我一直理解的
EGLImage
,它是在不同的进程和可能不同的API之间共享图像的机制

对于同一过程中的多个OpenGL ES上下文,您只需共享纹理即可。您所需要做的就是使两个上下文成为同一共享组的一部分,并且它们都可以使用相同的纹理。在您的用例中,可以使用FBO将一个线程渲染到纹理,然后在另一个线程中对其进行采样。这样,就没有额外的数据复制,您的代码应该变得更简单

唯一稍微棘手的方面是同步。ES 2.0在API中没有同步机制。您最好在一个线程中调用
glFinish()
(例如,在线程2完成纹理渲染后),然后使用标准IPC机制向另一个线程发送信号。ES 3.0有同步对象,这使得它更加优雅

我前面的回答概述了创建同一共享组中的多个上下文所需的一些步骤:。在同一共享组中创建多个上下文的关键部分是to的第三个参数,其中指定要与之共享对象的上下文