2015-11-10 98 views
3

我正在使用glMapBufferRange和GL_MAP_UNSYNCHRONIZED_BIT來映射緩衝區對象。然後,我將返回的指針傳遞給工作線程以異步計算新頂點。對象是雙重緩衝的,所以我可以渲染一個對象而另一個被寫入。使用GL_MAP_UNSYNCHRONIZED_BIT給了我明顯更好的性能(主要是因爲glUnmapBuffer更快地返回),但是我得到了一些視覺工件(儘管有雙重緩衝) - 所以我假設GPU在DMA上傳仍在進行時開始渲染,或者工作線程開始寫入頂點太早。 如果我理解glFenceSync,glWaitSync和glClientWaitSync正確的,那麼我應該解決以下方式將這些問題:OpenGL:單獨線程上的glClientWaitSync

答:避免在GPU渲染緩存對象的DMA過程完成之前:glUnmapBufferRange後直接 ,通話在主線程

GLsync uploadSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 
glFlush(); 
glWaitSync(uploadSync, 0, GL_TIMEOUT_IGNORED); 

B:避免在工作者線程寫入緩衝區中的GPU呈現完畢之前:glDrawElements後 照片直接,調用主線程

GLsync renderSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 

,並在工作線程,右側開始將數據寫入指針與先前已從glMapBufferRange

glClientWaitSync(renderSync,0,100000000); 
...start writing to the mapped pointer 

1返回前:我的辦法來明確同步正確嗎?

2:如何處理第二種情況?我想在工作線程中等待(我不想讓主線程停止工作),但是我無法從工作線程發出glCommands。是否有另一種方法來檢查GLsync是否已被髮送,而非gl呼叫?

+0

您可以爲上傳線程使用單獨的GL上下文,該上下文線程將所有對象與主要上下文共享以進行繪製。在這種情況下,您也可以共享同步對象,並且可以通過這種方式同步這些線程。 – derhass

+0

我理解GLsync對象的方式是它們沒有綁定到上下文,所以我猜這些上下文甚至不需要共享。如果可能的話,我想避免爲工作線程分開上下文。在Android上,似乎可以通過eglDupNativeFenceFDANDROID從GLsync生成本地柵欄 - 如果Windows也有類似的東西,或者與平臺無關,那就太棒了。 – user1282931

+0

同步對象與GL上下文(或多個共享的上下文)相關聯的對象與任何其他GL對象一樣,所以如果沒有共享上下文,您就無法離開。 – derhass

回答

1

你可以做的是在工作者線程中創建一個OpenGL上下文,然後與主線程共享。下一頁:在主線程

運行:

GLsync renderSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush();

那麼工作線程

運行:

glClientWaitSync(renderSync,0,100000000);

主線程上的glFlush非常重要,否則您可能會無限等待。又見OpenGL docs

4.1.2信令

腳註3:等待在另一種情況下的命令流發出的圍籬命令完成時SYNC_FLUSH_COMMANDS_BIT定義的簡單沖洗行爲將不利於。阻擋柵欄同步對象的應用程序必須執行額外的步驟,以確保發出相應柵欄命令的上下文已將該命令刷新到管道圖形處理器。

+0

我想避免爲工作線程設置單獨的上下文,但似乎沒有辦法繞過它 – user1282931