2014-12-02 111 views
1

OpenGL wiki on Performance,它說:OpenGL:哪些OpenGL實現不流水?

「OpenGL實現幾乎都是流水線 - 也就是說, 的事情,當你告訴OpenGL吸引他們並不一定按 - 和一個OpenGL調用返回的事實並不意味着它完成了 渲染。「

既然它說「差不多」,那就意味着有些實現不是流水線的。

在這裏,我找到一個: OpenGL Pixel Buffer Object (PBO)

「常規glReadPixels()會阻塞管道,並等待,直到所有 像素數據傳輸然後,返回控制到 應用相反,glReadPixels。 ()與PBO可以安排 異步DMA傳輸,並立即返回而不會失速 因此,應用程序(CPU)可以立即執行其他進程, ,同時通過OpenGL(GPU)與DMA傳輸數據。

所以這意味着傳統的glReadPixels()(不與PBO)阻塞管道。 但實際上在glReadPixels的OpenGL引用中,我不能說出這個事實。我想知道: 哪些OpenGL實現不流水線?

glDrawArrays怎麼樣?

+0

不是100%確定,但我認爲所有不返回任何內容的操作都是流水線操作。例如glDrawArrays是流水線,而glGenBuffers不是。 – dari 2014-12-02 22:28:59

回答

2

OpenGL規範本身並未指定術語「管道」,而是「命令流」。命令流執行的運行時行爲是故意保持開放的,從而爲實現者提供最大的靈活性。

的重要術語是 「OpenGL的sychronization點」:https://www.opengl.org/wiki/Synchronization

在這裏,我找到一個:(鏈接到songho文章)

請注意,這不是一個官方的OpenGL規範的資源。 「封鎖OpenGL管道」的措辭有點不幸,因爲它實際上阻止了瓶頸,瓶頸變成了「顛倒」。實際上,它意味着,只有在執行完所有將要讀取圖像的命令後,glReadPixels才能返回。

所以這意味着傳統的glReadPixels()(不與PBO)阻塞管道。但實際上在glReadPixels的OpenGL參考中,我無法說出這個事實。

事實上,它不是被阻塞的OpenGL管道,而是CPU上程序的執行。這意味着,GPU看不到來自CPU的更多命令。所以管道不會「堵塞」,但實際上已經耗盡。當管道流失或需要重新啓動時,有人說管道已經停滯(即管道中的流量停止)。

從GPU的角度來看,所有事情都會發生在最大吞吐量的情況下:渲染東西直到glReadPixels被調用點,進行DMA傳輸,不幸的是在啓動傳輸後沒有其他命令可用。

glDrawArrays怎麼樣?

glDrawArrays在數據排隊並且必要時立即返回。

+0

「所以管道不會」堵塞「,但實際上已經耗盡。」當我在glReadPixels()之後在CPU中設置時鐘時,時鐘記錄是什麼時間? – user1914692 2014-12-02 23:23:37

+0

@ user1914692:這真的取決於OpenGL的實現。假設你做了一些像'draw_something(); glfinish在(); clock_gettime(CLOCK_MONOTONIC,&start); glReadPixels(&cpumem); clock_gettime(CLOCK_MONOTONIC,&end);''你將設置裸轉移和格式轉換時間。但是,如果你做了類似'draw_something(); clock_gettime(CLOCK_MONOTONIC,&start); glReadPixels(&cmpumem); clock_gettime(CLOCK_MONOTONIC,&end);'缺少glFinish),你會得到一個明顯更長的持續時間,原因是glReadPixels意味着一個同步,並且必須等待完成 – datenwolf 2014-12-03 00:43:00

+0

@ user1914692:**但是**如果您將glReadPixels添加到PBO,CPU (); glFinish(); glBindBuffer(GL_PIXEL_PACK_BUFFER,...); clock_gettime(CLOCK_MONOTONIC,&start); glReadPixels(); clock_gettime(CLOCK_MONOTONIC,&end););不需要等待glReadPixels完成。和glFinish:'draw_something(); glBindBuffer(GL_PIXEL_PACK_BUFFER,...); clock_gettime(CLOCK_MONOTONIC,&start); glReadPixels(); clock_gettime(CLOCK_MONOT ONIC,&end);'會相反,因爲沒有什麼需要等待完成。 – datenwolf 2014-12-03 00:45:58

1

實際上它意味着這個特定的操作不能被流水線化,因爲所有的數據都需要在函數返回之前被傳輸,這並不意味着其他東西不能。

這樣的操作據說是檔位的流水線。一個會使管道失速的功能是glFinish

通常,當函數返回一個像獲取緩衝區內容那樣的值時,它會導致失速。

取決於驅動程序的實現創建程序和緩衝區等,可以做到沒有拖延。

+1

'glFlush()'只提交待處理的工作,它不會等待它完成。你可能會想'glFinish()'。 – 2014-12-02 22:38:24

0

然後我想知道:哪些OpenGL實現不流水線?

我可以想象一個純粹的軟件實現可能不是流水線。如果您最終在同一個CPU上執行它,沒有太多理由排隊工作。除非你想利用多線程。

但可以肯定地說,任何使用專用硬件(通常稱爲GPU)的OpenGL實現都將被流水線化。這允許CPU和GPU並行工作,這對於獲得良好的系統性能至關重要。而且,向GPU提交工作會產生一定的開銷,因此排隊工作並將其提交到更大批次是有益的。

但實際上在OpenGL的glReadPixels引用中我不能說出這個事實。

是的。手冊頁不直接指定哪些調用會導致同步。一般來說,任何返回GPU生成的值/數據都會導致同步。想到的例子:

  • glFinish()。顯式地要求完全同步,這實際上是它的唯一目的。
  • glReadPixels(),在非PBO的情況下。 GPU必須先完成渲染,然後才能讀回結果。
  • glGetQueryObjectiv(id, GL_QUERY_RESULT, ...)。阻止,直到GPU達到提交查詢的點。
  • glClientWaitSync()。等待GPU到達提交相應的glFenceSync()的點。

請注意,可能有不同類型的同步不直接綁定到特定的OpenGL調用。例如,在整個工作負載受GPU限制的情況下,除非有一些節流,否則CPU會排隊工作。因此,驅動程序會在多或少的任意點阻塞CPU,讓GPU趕上某個特定點。這可能發生在框架邊界,但它不一定是。如果內存不足,或內部驅動程序資源耗盡,則可能需要進行類似的同步。