2015-02-17 220 views
3

我想提高使用PBO glReadPixels()性能glReadPixels()(对于GLES 3个装置)和我遇到了一个问题在这一段代码:的Android的OpenGL ES 3.0 PBO代替

final ByteBuffer pboByteBuffer = ByteBuffer.allocateDirect(4 * mWidth * mHeight); 
pboByteBuffer.order(ByteOrder.nativeOrder()); 

//set framebuffer to read from 
GLES30.glReadBuffer(GLES30.GL_BACK); 

// bind pbo 
GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, mPboHandleContainer[0]); 

// read pixels(should be instant) 
GLES30.glReadPixels(0, 0, mWidth, mHeight, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, pboByteBuffer); 

// map pbo to bb 
ByteBuffer byteBuffer = 
     ((ByteBuffer) GLES30.glMapBufferRange(GLES30.GL_PIXEL_PACK_BUFFER, 0, 4 * mWidth * mHeight, 
               GLES30.GL_MAP_READ_BIT)).order(ByteOrder.nativeOrder()); 

// unmap pbo 
GLES30.glUnmapBuffer(GLES30.GL_PIXEL_PACK_BUFFER); 

// unbind pbo 
GLES30.glBindBuffer(GLES30.GL_PIXEL_PACK_BUFFER, 0); 

目前,它失败glReadPixels()方法。我发现this & this,但我无法发送一个零,因为它需要一个IntBuffer参数。我非常感谢关于此问题的任何建议

更新:似乎不可能只为该任务使用Java API。所以我用ndk添加了一个函数,该函数用正确的最后一个参数调用glReadPixels()(int offset) 现在我的任何GL调用都不会产生错误。

这是我的JNI的C代码:

#include <jni.h> 

#include <GLES3/gl3.h> 

#ifdef __cplusplus 
extern "C" { 
    JNIEXPORT void JNICALL Java_somepackage_GLES3PBOReadPixelsFix_glReadPixelsPBO(JNIEnv * env, jobject obj, jint x, jint y, jint width, jint height, jint format, jint type, jint offsetPBO); 
}; 
#endif 

JNIEXPORT void JNICALL Java_somepackage_GLES3PBOReadPixelsFix_glReadPixelsPBO(JNIEnv * env, jobject obj, jint x, jint y, jint width, jint height, jint format, jint type, jint offsetPBO) 
{ 
    glReadPixels(x, y, width, height, format, type, offsetPBO); 
} 

现在的问题是,glReadPixels()通话时间比没有公益组织这样有没有性能增益还甚至更​​多的时间。我会探索为什么会发生这种情况,并在我找到某些东西时进行更新。

更新2 我忘了前面更新,但实际上的问题是,我用p缓冲器表面,这就是为什么我没有性能增益。我比较了这个选项和不使用pbuffer表面的选项,性能增益巨大。

所以,如果渲染屏幕外使用glReadPixels它使用p缓冲器表面

+1

奇怪。看起来像使用PBO for'glReadPixels()'的Java入口点缺失。如果确实如此,这不是Android中第一次发生这种情况。使用本地代码始终是一个解决方案。也就是说,如果您立即等待结果,那么使用PBO可能对您没有多大帮助。整个想法是'glReadPixels()'调用不会被阻止。如果你之后马上阻止,那不会有太大好处。 – 2015-02-18 06:27:07

+0

@ReetoKoradi感谢您的反馈!在我的情况下,仍然是本机代码。唯一真正重要的是我的代码块与简单的glReadPixels()相比需要多少时间调用 – Sam 2015-02-18 13:35:09

+0

我在Android上遇到过使用PBO没有看到性能增益的相同问题。你能不能解释一下如何在Android上使用pbuffer表面来启用快速异步glReadPixels到PBO?谢谢。 – 2016-11-30 10:17:04

回答

2

映射PBO缓冲glReadPixels总是杀死性能之后的价值。当您请求映射时,GPU仍在工作。因此,glMapBufferRange等待GPU完成读取像素到PBO。如果在glReadPixels之后继续渲染并在一些帧之后执行映射,则会获得性能提升。

更多的信息在这里:http://www.songho.ca/opengl/gl_pbo.html 看“映射PBO”部分。

+0

更新了我的答案。我也看到了那篇文章和其他许多文章 - 不幸的是那时我并没有意识到发生了什么 – Sam 2015-05-26 11:50:57