我希望通过使用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()
方法。我找到了这个和这个,但是我不能发送零因为它需要一个IntBuffer参数。我非常感谢任何关于这个问题的建议。
更新:似乎不可能仅使用Java API完成此任务。所以我使用ndk添加了一个调用具有正确最后参数(int offset)的glReadPixels()
函数的功能。现在我的所有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()
调用所需时间比不使用PBOs的时间更长,因此目前没有性能提升。我将探究原因,并在找到内容后进行更新。
更新2
我之前忘记更新了,但实际上问题是我正在使用pbuffer表面,这就是为什么我没有获得性能提升的原因。我比较了该选项和不使用pbuffer表面的选项,性能提升非常巨大。因此,在离屏渲染并使用glReadPixels时,值得使用pbuffer表面。
glReadPixels()
的Java入口点丢失了。如果确实是这样,那么这不是Android中第一次发生这种情况。使用本地代码总是一个解决方案。话虽如此,如果您立即等待结果,则使用PBO可能不会对您有太大帮助。整个想法是glReadPixels()
调用不会阻塞。如果您随后立即阻塞,那么这将没有什么好处。 - Reto Koradi