2015-10-16 60 views
0

我正在編寫一個使用GPU來計算東西的程序,我想從我的客戶端代碼中使用的幀緩衝區中讀取數據。我正在使用的幀緩衝區大約有40個紋理,所有的尺寸都是1024x1024,所有這些紋理都包含需要讀取的數據,但只是非常細膩,就像每個紋理任意x/y座標中的50個像素。使用glReadPixels爲每個紋理,對於每一幀,對我而言都證明過於昂貴,儘管...OpenGL:從許多framebuffer紋理讀取sparce像素數據的有效方法?

我只需要從每個紋理中讀取幾個選定像素,是否有方法可以快速收集數據而無需從GPU下載每一個完整的紋理?

回答

2

這聽起來相當昂貴的,無論你如何切它直接複製像素。想到幾個方法:

  • 我想先嚐試的是glReadPixels(),但使用PBO。綁定足夠大的緩衝區,以將所有像素保存到目標,然後提交glReadPixels()調用,並使用偏移量將結果放在緩衝區的不同部分。然後致電glMapBufferRange()回讀這些值。

  • 另一種方法是將要讀取的所有像素複製到單個紋理中。您可以使用glBlitFramebuffer()glCopyTexSubImage2D()。然後使用一個glReadPixels()glGetTexImage()調用來獲取來自此紋理的所有數據。

這兩種方法都會導致大致相同的工作量和同步開銷。但其中一個或另一個可能更有效率,這取決於驅動程序中的哪個路徑得到了更好的優化。如前面的答案已經提出,我會讓確定你確實需要這個,並且沒有任何方法來保存和處理GPU上的數據。無論何時讀回數據,都會在GPU和CPU之間引入同步,這對性能影響最大。

+0

選項2對我來說似乎是兩者中速度更快的,並且效果相當好! (不幸的是需要提取值是不可避免的) –

0

如果您需要將GPU中的數據複製到CPU內存,則無法使用glReadPixels(AFAIK)。

取決於你使用什麼平臺,和你的程序的具體,你可以嘗試一些優化,使用的FBO:

  • 僅複製紋理的一部分,假設你知道的位置像素。請注意,在大多數情況下,複製整個紋理的速度更快,而不是發出幾個小的讀數

  • 如果不需要32位紋理,則可以渲染到較低的顏色分辨率。具體取決於您的平臺擴展。

  • 也許您不需要複製像素,因爲您打算將它們用作紋理輸入到下一個階段?在這種情況下,你在GPU上使用glCopyTexImage2D

2

您對可以使用的OpenGL版本有任何限制嗎?如果沒有,這聽起來像你應該看看計算着色器。你說你正在計算數據,所以我假設你正在爲應用程序「濫用」渲染管道,特別是片段着色器,並將片段數據存儲在幀緩衝區中,這被解釋爲顏色以外的東西。

如果是這樣的話,那麼你需要的只是一個着色器存儲緩衝區和一個原子計數器。在某一時刻,您正在決定片段(x,y,z [z是紋理索引])的值應該是v。因此,在您的計算着色器中,您將按照在片段着色器中的計算方式進行計算, ,你存儲一個元組(x,y,z,v)。您可以將此元組存儲在着色器存儲緩衝區中原子計數器的索引處,該元素在每個寫入元素後遞增。最後,您將數據緊湊地存儲在緩衝區中,只需要讀回這些元素。確切的數字是原子計數器在終止後保持的值。將glGetBufferSubData緩衝區下載到位置值對的數組中,迭代它並完成CPU的魔力。