我想使用PBO(对于GLES 3设备)提高glReadPixels()
性能,我在这段代码中遇到了问题:
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()
调用比没有PBO需要更多时间,所以还没有性能提升。我将探索为什么会发生这种情况并在找到某些内容时进行更新。
更新2 我忘了早点更新它,但事实上问题是我使用pbuffer表面,这就是为什么我没有性能提升。我比较了不使用pbuffer表面的选项和选项,性能提升很大。
所以如果在屏幕外渲染并使用glReadPixels它值得使用pbuffer surface
答案 0 :(得分:2)
在glReadPixels总是杀死性能之后立即映射PBO缓冲区。您请求映射时GPU仍在工作。因此,glMapBufferRange等待gpu完成读取PBO的像素。如果你继续在glReadPixels之后渲染并在一些帧之后进行映射,那么你将获得性能提升。
此处提供更多信息:http://www.songho.ca/opengl/gl_pbo.html 看看“映射PBO”部分。