2015-02-17 239 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