2014-10-10 48 views
0

我在fork中使用各種GL操作時遇到了錯誤(它們在主線程中工作正常)。例如與createProgram我越來越:forkOS似乎無法保留線程的本地存儲

用戶錯誤(未知OpenGL擴展進入glCreateProgram,檢查的OpenGL 3.1)

我打電話是我初始化我的環境(4.3內核之後), 當然。
問題是我在使用forkOS時遇到了這個錯誤,但它仍然失敗(就好像我在不知道GL上下文的TLS中一樣)。

發生了什麼事?

module Main where 
import Graphics.UI.GLUT 
import Control.Concurrent 
import Control.Monad 

main :: IO() 
main = do 
    getArgsAndInitialize 
    initialDisplayMode $= [RGBMode, DoubleBuffered] 
    initialContextVersion $= (4,3) 
    initialContextProfile $= [CoreProfile] 
    initialContextFlags $= [DebugContext, ForwardCompatibleContext] 
    createWindow "GL Window" 

    createProgram -- Works 
    forkOS $ void createProgram -- Fails (user error) 

    displayCallback $= do 
     clearColor $= Color4 0.2 0.2 1 1 
     clear [ColorBuffer] 
     flush >> swapBuffers 

    mainLoop 
+1

似乎GL上下文仍然綁定到您最初創建它的(OS)線程。 – derhass 2014-10-10 18:10:07

+0

@derhass是的,它是必然的。這就是爲什麼我希望'forkOS'能夠成功地進行這些調用,但是它失敗了,正如你所看到的。 – MasterMastic 2014-10-10 19:13:02

+0

你可以發佈一個簡短的示例程序來演示這個問題嗎?很難在沒有看到你在做什麼的情況下進行調試(儘管我懷疑你沒有在一個'forkOS'線程中執行*所有* OpenGL調用)。 – 2014-10-11 08:54:49

回答

2

OpenGL上下文被綁定到一個線程。本質上它們是TLS結構。 forkOS不會自動爲您「攜帶」OpenGL上下文綁定。 forkOS的想法是通過它綁定的Haskell操作保留在操作系統看到的同一線程中。 forkIO可能會通過Haskells自己的調度程序在線程之間混洗操作,這隻會使FFI稱爲庫和API的TLS關聯成爲一場噩夢。

當GLUT createWindow執行時,它會創建一個窗口一個OpenGL上下文並將其綁定到調用線程。

所以你必須選擇:要麼重新綁定到其他線程的OpenGL上下文。或者您創建另一個上下文,安裝一個名稱空間共享第一個,並將其綁定到另一個線程。

+0

我想如果我在同一個線程中,我會擁有相同的TLS(因此可以繼承OpenGL上下文)。爲什麼不是這種情況? – MasterMastic 2014-10-11 09:47:40

+0

'forkOS'創建一個新的線程。因此'createProgram'是在不同於在OpenGL上下文創建(並綁定到)的線程中執行的。如果沒有OpenGL環境,OpenGL調用將會失敗。 http://www.haskell.org/hoogle/?hoogle=forkOS:'就像forkIO一樣,這會引發一個新線程來運行作爲第一個參數傳遞的IO計算,並返回新創建的線程的ThreadId。' – datenwolf 2014-10-11 10:21:03

+0

哦,基本上'forkIO'可能在同一個操作系統線程或新的線程上,並可能隨機播放;相反'forkOS'將始終處於新的單線程中?我理解正確嗎? – MasterMastic 2014-10-11 10:47:32