Android 上的 PBO 不会提高 glReadPixels 性能

PBO on Android doesn't improve glReadPixels performance

我想在 OpenGL 中截取当前帧的屏幕截图以进行进一步处理,并且我正在尝试通过使用 PBO 异步读取帧缓冲区来提高 glReadPixels 的性能。

我的印象是 GL_PIXEL_PACK_BUFFER 之后的 glReadPixels 应该立即 return 绑定到缓冲区,但实际上它花费的时间与不使用 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 的延迟减少到大约 100 毫秒,但是当我使用 GLES30.glMapBufferRange 映射缓冲区时,输出帧看起来没有正确呈现。我还在 GLES11Ext 中尝试了 GL_BGRA 格式,但它会在 glReadPixel 中导致 GL_INVALID_OPERATION。

是否有任何其他方法可以立即在 Android return 上创建 glReadPixels 以便 PBO 可以提高性能?

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