2016-12-03 642 views
1

我想获取OpenGL中当前帧的屏幕截图作进一步处理,并试图通过使用PBO异步读取帧缓冲区来提高glReadPixels的性能。安卓上的PBO不会改善glReadPixels的性能

我的印象是GL_PIXEL_PACK_BUFFER绑定到缓冲区后glReadPixels应该立即返回,但它实际上需要比不使用PBO类似或甚至更多的时间。

这里是我的代码样品:

// Setup PBO 
GLES30.glGenBuffers(nPbo, pboIndex, 0); 
for(int i=0;i<nPbo; i++){ 
    GLES30.glBindBuffer (GL_PIXEL_PACK_BUFFER, pboIndex[i]); 
    GLES30.glBufferData(GL_PIXEL_PACK_BUFFER, size, null,GL_STREAM_READ); 
} 
GLES30.glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 

...... 

// For each frame, trigger async transfer of framebuffer to PBO. 
// Note that I don't even map the PBO to memory yet 
GLES30.glBindBuffer (GL_PIXEL_PACK_BUFFER, pboIndex[index]); 
// The following is a JNI method to overload glReadPixels in GLES20.glReadPixels, 
// to allow passing int offset to the last param in order to use PBO, 
// and slowdown (around 500ms on my device) happens here 
GLES3PBOReadPixelsFix.glReadPixelsPBO(0, 0, mWidth, mHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, 0); 
GLES30.glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); 

基于this article,减速的原因可能是由于像素传送格式内部格式之间的转换,其可以是GL_BGRA,并且,这是GL_RGBA在我的代码。将传输格式更改为GL_RGB会将glReadPixels的延迟降低到100ms左右,但是当我使用GLES30.glMapBufferRange映射缓冲区时,输出帧看起来看起来不正确。我也尝试了GLES11Ext中的GL_BGRA格式,但它会在glReadPixel中引起GL_INVALID_OPERATION。

是否有任何其他方式使Android上的glReadPixels立即返回,以便PBO可以提高性能?

+0

可能只是特定OpenGL实现的“特征”。您是否尝试过使用各种设备与各种供应商提供的GPU?顺便说一句,针对PBOs的“glReadPixels()”调用最终被添加到API级别24中的Java绑定中。 –

+0

正如您所建议的那样,它变成了一个实现特定的问题。我最初测试的GPU是Adreno 306.当我在Samsung Note 4(Adreno 420)上测试相同的代码时,它按预期工作。感谢您的建议以及新的glReadPixels绑定信息。 –

+0

高通公司在阻止应该异步的呼叫方面声名狼借。 –

回答

0

正如Reto所建议的,事实证明这是一个实现特定的问题。我最初测试的GPU是Adreno 306.当我在Samsung Note 4(Adreno 420)上测试相同的代码时,它按预期工作。因此,在不同设备和GPU上测试这类问题总是值得的。