2016-12-03 643 views
1

我想獲取OpenGL中當前幀的屏幕截圖作進一步處理,並試圖通過使用PBO異步讀取幀緩衝區來提高glReadPixels的性能。安卓上的PBO不會改善glReadPixels的性能

我的印象是GL_PIXEL_PACK_BUFFER綁定到緩衝區後glReadPixels應該立即返回,但它實際上需要比不使用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的延遲降低到100ms左右,但是當我使用GLES30.glMapBufferRange映射緩衝區時,輸出幀看起來看起來不正確。我也嘗試了GLES11Ext中的GL_BGRA格式,但它會在glReadPixel中引起GL_INVALID_OPERATION。

是否有任何其他方式使Android上的glReadPixels立即返回,以便PBO可以提高性能?

+0

可能只是特定OpenGL實現的「特徵」。您是否嘗試過使用各種設備與各種供應商提供的GPU?順便說一句,針對PBOs的「glReadPixels()」調用最終被添加到API級別24中的Java綁定中。 –

+0

正如您所建議的那樣,它變成了一個實現特定的問題。我最初測試的GPU是Adreno 306.當我在Samsung Note 4(Adreno 420)上測試相同的代碼時,它按預期工作。感謝您的建議以及新的glReadPixels綁定信息。 –

+0

高通公司在阻止應該異步的呼叫方面聲名狼借。 –

回答

0

正如Reto所建議的,事實證明這是一個實現特定的問題。我最初測試的GPU是Adreno 306.當我在Samsung Note 4(Adreno 420)上測試相同的代碼時,它按預期工作。因此,在不同設備和GPU上測試這類問題總是值得的。