summaryrefslogtreecommitdiff
path: root/Backend/GL/Input.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Backend/GL/Input.hs')
-rw-r--r--Backend/GL/Input.hs381
1 files changed, 381 insertions, 0 deletions
diff --git a/Backend/GL/Input.hs b/Backend/GL/Input.hs
new file mode 100644
index 0000000..6d4f40f
--- /dev/null
+++ b/Backend/GL/Input.hs
@@ -0,0 +1,381 @@
1module Backend.GL.Input where
2
3import Control.Applicative
4import Control.Exception
5import Control.Monad
6import Data.ByteString.Char8 (ByteString,pack)
7import Data.IORef
8import Data.IntMap (IntMap)
9import Data.Trie (Trie)
10import Data.Trie.Convenience as T
11import Data.Vector (Vector,(//),(!))
12import Data.Word
13import Foreign
14import qualified Data.ByteString.Char8 as SB
15import qualified Data.IntMap as IM
16import qualified Data.Set as S
17import qualified Data.Map as Map
18import qualified Data.Trie as T
19import qualified Data.Vector as V
20import qualified Data.Vector.Algorithms.Intro as I
21
22import Graphics.Rendering.OpenGL.Raw.Core33
23
24import IR as IR
25import Backend.GL.Type as T
26import Backend.GL.Util
27
28import qualified IR as IR
29
30schemaFromPipeline :: IR.Pipeline -> PipelineSchema
31schemaFromPipeline a = PipelineSchema (T.fromList sl) (foldl T.unionL T.empty ul)
32 where
33 (sl,ul) = unzip [((pack n,SlotSchema p (fmap cvt (toTrie s))),toTrie u) | IR.Slot n u s p _ <- V.toList $ IR.slots a]
34 cvt a = case toStreamType a of
35 Just v -> v
36 Nothing -> error "internal error (schemaFromPipeline)"
37
38mkUniform :: [(ByteString,InputType)] -> IO (Trie InputSetter, Trie GLUniform)
39mkUniform l = do
40 unisAndSetters <- forM l $ \(n,t) -> do
41 (uni, setter) <- mkUniformSetter t
42 return ((n,uni),(n,setter))
43 let (unis,setters) = unzip unisAndSetters
44 return (T.fromList setters, T.fromList unis)
45
46mkGLPipelineInput :: PipelineSchema -> IO GLPipelineInput
47mkGLPipelineInput sch = do
48 let sm = T.fromList $ zip (T.keys $ T.slots sch) [0..]
49 len = T.size sm
50 (setters,unis) <- mkUniform $ T.toList $ uniforms sch
51 seed <- newIORef 0
52 slotV <- V.replicateM len $ newIORef (GLSlot IM.empty V.empty Ordered)
53 size <- newIORef (0,0)
54 ppls <- newIORef $ V.singleton Nothing
55 return $ GLPipelineInput
56 { schema = sch
57 , slotMap = sm
58 , slotVector = slotV
59 , objSeed = seed
60 , uniformSetter = setters
61 , uniformSetup = unis
62 , screenSize = size
63 , pipelines = ppls
64 }
65
66-- object
67addObject :: GLPipelineInput -> ByteString -> Primitive -> Maybe (IndexStream Buffer) -> Trie (Stream Buffer) -> [ByteString] -> IO Object
68addObject input slotName prim indices attribs uniformNames = do
69 let sch = schema input
70 forM_ uniformNames $ \n -> case T.lookup n (uniforms sch) of
71 Nothing -> throw $ userError $ "Unknown uniform: " ++ show n
72 _ -> return ()
73 case T.lookup slotName (T.slots sch) of
74 Nothing -> throw $ userError $ "Unknown slot: " ++ show slotName
75 Just (SlotSchema sPrim sAttrs) -> do
76 when (sPrim /= (primitiveToFetchPrimitive prim)) $ throw $ userError $
77 "Primitive mismatch for slot (" ++ show slotName ++ ") expected " ++ show sPrim ++ " but got " ++ show prim
78 let sType = fmap streamToStreamType attribs
79 when (sType /= sAttrs) $ throw $ userError $ unlines $
80 [ "Attribute stream mismatch for slot (" ++ show slotName ++ ") expected "
81 , show sAttrs
82 , " but got "
83 , show sType
84 ]
85
86 let slotIdx = case slotName `T.lookup` slotMap input of
87 Nothing -> error "internal error (slot index)"
88 Just i -> i
89 seed = objSeed input
90 order <- newIORef 0
91 enabled <- newIORef True
92 index <- readIORef seed
93 modifyIORef seed (1+)
94 (setters,unis) <- mkUniform [(n,t) | n <- uniformNames, let Just t = T.lookup n (uniforms sch)]
95 cmdsRef <- newIORef (V.singleton V.empty)
96 let obj = Object
97 { objSlot = slotIdx
98 , objPrimitive = prim
99 , objIndices = indices
100 , objAttributes = attribs
101 , objUniSetter = setters
102 , objUniSetup = unis
103 , objOrder = order
104 , objEnabled = enabled
105 , objId = index
106 , objCommands = cmdsRef
107 }
108
109 modifyIORef (slotVector input ! slotIdx) $ \(GLSlot objs _ _) -> GLSlot (IM.insert index obj objs) V.empty Generate
110
111 -- generate GLObjectCommands for the new object
112 {-
113 foreach pipeline:
114 foreach realted program:
115 generate commands
116 -}
117 ppls <- readIORef $ pipelines input
118 let topUnis = uniformSetup input
119 cmds <- V.forM ppls $ \mp -> case mp of
120 Nothing -> return V.empty
121 Just p -> do
122 Just ic <- readIORef $ glInput p
123 case icSlotMapInputToPipeline ic ! slotIdx of
124 Nothing -> do
125 putStrLn $ " ** slot is not used!"
126 return V.empty -- this slot is not used in that pipeline
127 Just pSlotIdx -> do
128 putStrLn "slot is used!"
129 --where
130 let emptyV = V.replicate (V.length $ glPrograms p) []
131 return $ emptyV // [(prgIdx,createObjectCommands (glTexUnitMapping p) topUnis obj (glPrograms p ! prgIdx))| prgIdx <- glSlotPrograms p ! pSlotIdx]
132 writeIORef cmdsRef cmds
133 return obj
134
135removeObject :: GLPipelineInput -> Object -> IO ()
136removeObject p obj = modifyIORef (slotVector p ! objSlot obj) $ \(GLSlot objs _ _) -> GLSlot (IM.delete (objId obj) objs) V.empty Generate
137
138enableObject :: Object -> Bool -> IO ()
139enableObject obj b = writeIORef (objEnabled obj) b
140
141setObjectOrder :: GLPipelineInput -> Object -> Int -> IO ()
142setObjectOrder p obj i = do
143 writeIORef (objOrder obj) i
144 modifyIORef (slotVector p ! objSlot obj) $ \(GLSlot objs sorted _) -> GLSlot objs sorted Reorder
145
146objectUniformSetter :: Object -> Trie InputSetter
147objectUniformSetter = objUniSetter
148
149setScreenSize :: GLPipelineInput -> Word -> Word -> IO ()
150setScreenSize p w h = writeIORef (screenSize p) (w,h)
151
152sortSlotObjects :: GLPipelineInput -> IO ()
153sortSlotObjects p = V.forM_ (slotVector p) $ \slotRef -> do
154 GLSlot objMap sortedV ord <- readIORef slotRef
155 let cmpFun (a,_) (b,_) = a `compare` b
156 doSort objs = do
157 ordObjsM <- V.thaw objs
158 I.sortBy cmpFun ordObjsM
159 ordObjs <- V.freeze ordObjsM
160 writeIORef slotRef (GLSlot objMap ordObjs Ordered)
161 case ord of
162 Ordered -> return ()
163 Generate -> do
164 objs <- V.forM (V.fromList $ IM.elems objMap) $ \obj -> do
165 ord <- readIORef $ objOrder obj
166 return (ord,obj)
167 doSort objs
168 Reorder -> do
169 objs <- V.forM sortedV $ \(_,obj) -> do
170 ord <- readIORef $ objOrder obj
171 return (ord,obj)
172 doSort objs
173
174createObjectCommands :: Trie (IORef GLint) -> Trie GLUniform -> Object -> GLProgram -> [GLObjectCommand]
175createObjectCommands texUnitMap topUnis obj prg = objUniCmds ++ objStreamCmds ++ [objDrawCmd]
176 where
177 -- object draw command
178 objDrawCmd = case objIndices obj of
179 Nothing -> GLDrawArrays prim 0 (fromIntegral count)
180 Just (IndexStream (Buffer arrs bo) arrIdx start idxCount) -> GLDrawElements prim (fromIntegral idxCount) idxType bo ptr
181 where
182 ArrayDesc arrType arrLen arrOffs arrSize = arrs ! arrIdx
183 idxType = arrayTypeToGLType arrType
184 ptr = intPtrToPtr $! fromIntegral (arrOffs + start * sizeOfArrayType arrType)
185 where
186 objAttrs = objAttributes obj
187 prim = primitiveToGLType $ objPrimitive obj
188 count = head [c | Stream _ _ _ _ c <- T.elems objAttrs]
189
190 -- object uniform commands
191 -- texture slot setup commands
192 objUniCmds = uniCmds ++ texCmds
193 where
194 uniCmds = [GLSetUniform i u | (n,i) <- uniMap, let u = T.lookupWithDefault (topUni n) n objUnis]
195 uniMap = T.toList $ inputUniforms prg
196 topUni n = T.lookupWithDefault (error "internal error (createObjectCommands)!") n topUnis
197 objUnis = objUniSetup obj
198 texUnis = S.toList $ inputTextureUniforms prg
199 texCmds = [ GLBindTexture (inputTypeToTextureTarget $ uniInputType u) texUnit u
200 | n <- texUnis
201 , let u = T.lookupWithDefault (topUni n) n objUnis
202 , let texUnit = T.lookupWithDefault (error "internal error (createObjectCommands - Texture Unit)") n texUnitMap
203 ]
204 uniInputType (GLUniform ty _) = ty
205
206 -- object attribute stream commands
207 objStreamCmds = [attrCmd i s | (i,name) <- T.elems attrMap, let Just s = T.lookup name objAttrs]
208 where
209 attrMap = inputStreams prg
210 objAttrs = objAttributes obj
211 attrCmd i s = case s of
212 Stream ty (Buffer arrs bo) arrIdx start len -> case ty of
213 TWord -> setIntAttrib 1
214 TV2U -> setIntAttrib 2
215 TV3U -> setIntAttrib 3
216 TV4U -> setIntAttrib 4
217 TInt -> setIntAttrib 1
218 TV2I -> setIntAttrib 2
219 TV3I -> setIntAttrib 3
220 TV4I -> setIntAttrib 4
221 TFloat -> setFloatAttrib 1
222 TV2F -> setFloatAttrib 2
223 TV3F -> setFloatAttrib 3
224 TV4F -> setFloatAttrib 4
225 TM22F -> setFloatAttrib 4
226 TM23F -> setFloatAttrib 6
227 TM24F -> setFloatAttrib 8
228 TM32F -> setFloatAttrib 6
229 TM33F -> setFloatAttrib 9
230 TM34F -> setFloatAttrib 12
231 TM42F -> setFloatAttrib 8
232 TM43F -> setFloatAttrib 12
233 TM44F -> setFloatAttrib 16
234 where
235 setFloatAttrib n = GLSetVertexAttribArray i bo n glType (ptr n)
236 setIntAttrib n = GLSetVertexAttribIArray i bo n glType (ptr n)
237 ArrayDesc arrType arrLen arrOffs arrSize = arrs ! arrIdx
238 glType = arrayTypeToGLType arrType
239 ptr compCnt = intPtrToPtr $! fromIntegral (arrOffs + start * fromIntegral compCnt * sizeOfArrayType arrType)
240
241 -- constant generic attribute
242 constAttr -> GLSetVertexAttrib i constAttr
243
244nullSetter :: ByteString -> String -> a -> IO ()
245nullSetter n t _ = return () -- Prelude.putStrLn $ "WARNING: unknown uniform: " ++ SB.unpack n ++ " :: " ++ t
246
247uniformBool :: ByteString -> Trie InputSetter -> SetterFun Bool
248uniformV2B :: ByteString -> Trie InputSetter -> SetterFun V2B
249uniformV3B :: ByteString -> Trie InputSetter -> SetterFun V3B
250uniformV4B :: ByteString -> Trie InputSetter -> SetterFun V4B
251
252uniformWord :: ByteString -> Trie InputSetter -> SetterFun Word32
253uniformV2U :: ByteString -> Trie InputSetter -> SetterFun V2U
254uniformV3U :: ByteString -> Trie InputSetter -> SetterFun V3U
255uniformV4U :: ByteString -> Trie InputSetter -> SetterFun V4U
256
257uniformInt :: ByteString -> Trie InputSetter -> SetterFun Int32
258uniformV2I :: ByteString -> Trie InputSetter -> SetterFun V2I
259uniformV3I :: ByteString -> Trie InputSetter -> SetterFun V3I
260uniformV4I :: ByteString -> Trie InputSetter -> SetterFun V4I
261
262uniformFloat :: ByteString -> Trie InputSetter -> SetterFun Float
263uniformV2F :: ByteString -> Trie InputSetter -> SetterFun V2F
264uniformV3F :: ByteString -> Trie InputSetter -> SetterFun V3F
265uniformV4F :: ByteString -> Trie InputSetter -> SetterFun V4F
266
267uniformM22F :: ByteString -> Trie InputSetter -> SetterFun M22F
268uniformM23F :: ByteString -> Trie InputSetter -> SetterFun M23F
269uniformM24F :: ByteString -> Trie InputSetter -> SetterFun M24F
270uniformM32F :: ByteString -> Trie InputSetter -> SetterFun M32F
271uniformM33F :: ByteString -> Trie InputSetter -> SetterFun M33F
272uniformM34F :: ByteString -> Trie InputSetter -> SetterFun M34F
273uniformM42F :: ByteString -> Trie InputSetter -> SetterFun M42F
274uniformM43F :: ByteString -> Trie InputSetter -> SetterFun M43F
275uniformM44F :: ByteString -> Trie InputSetter -> SetterFun M44F
276
277uniformFTexture2D :: ByteString -> Trie InputSetter -> SetterFun TextureData
278
279uniformBool n is = case T.lookup n is of
280 Just (SBool fun) -> fun
281 _ -> nullSetter n "Bool"
282
283uniformV2B n is = case T.lookup n is of
284 Just (SV2B fun) -> fun
285 _ -> nullSetter n "V2B"
286
287uniformV3B n is = case T.lookup n is of
288 Just (SV3B fun) -> fun
289 _ -> nullSetter n "V3B"
290
291uniformV4B n is = case T.lookup n is of
292 Just (SV4B fun) -> fun
293 _ -> nullSetter n "V4B"
294
295uniformWord n is = case T.lookup n is of
296 Just (SWord fun) -> fun
297 _ -> nullSetter n "Word"
298
299uniformV2U n is = case T.lookup n is of
300 Just (SV2U fun) -> fun
301 _ -> nullSetter n "V2U"
302
303uniformV3U n is = case T.lookup n is of
304 Just (SV3U fun) -> fun
305 _ -> nullSetter n "V3U"
306
307uniformV4U n is = case T.lookup n is of
308 Just (SV4U fun) -> fun
309 _ -> nullSetter n "V4U"
310
311uniformInt n is = case T.lookup n is of
312 Just (SInt fun) -> fun
313 _ -> nullSetter n "Int"
314
315uniformV2I n is = case T.lookup n is of
316 Just (SV2I fun) -> fun
317 _ -> nullSetter n "V2I"
318
319uniformV3I n is = case T.lookup n is of
320 Just (SV3I fun) -> fun
321 _ -> nullSetter n "V3I"
322
323uniformV4I n is = case T.lookup n is of
324 Just (SV4I fun) -> fun
325 _ -> nullSetter n "V4I"
326
327uniformFloat n is = case T.lookup n is of
328 Just (SFloat fun) -> fun
329 _ -> nullSetter n "Float"
330
331uniformV2F n is = case T.lookup n is of
332 Just (SV2F fun) -> fun
333 _ -> nullSetter n "V2F"
334
335uniformV3F n is = case T.lookup n is of
336 Just (SV3F fun) -> fun
337 _ -> nullSetter n "V3F"
338
339uniformV4F n is = case T.lookup n is of
340 Just (SV4F fun) -> fun
341 _ -> nullSetter n "V4F"
342
343uniformM22F n is = case T.lookup n is of
344 Just (SM22F fun) -> fun
345 _ -> nullSetter n "M22F"
346
347uniformM23F n is = case T.lookup n is of
348 Just (SM23F fun) -> fun
349 _ -> nullSetter n "M23F"
350
351uniformM24F n is = case T.lookup n is of
352 Just (SM24F fun) -> fun
353 _ -> nullSetter n "M24F"
354
355uniformM32F n is = case T.lookup n is of
356 Just (SM32F fun) -> fun
357 _ -> nullSetter n "M32F"
358
359uniformM33F n is = case T.lookup n is of
360 Just (SM33F fun) -> fun
361 _ -> nullSetter n "M33F"
362
363uniformM34F n is = case T.lookup n is of
364 Just (SM34F fun) -> fun
365 _ -> nullSetter n "M34F"
366
367uniformM42F n is = case T.lookup n is of
368 Just (SM42F fun) -> fun
369 _ -> nullSetter n "M42F"
370
371uniformM43F n is = case T.lookup n is of
372 Just (SM43F fun) -> fun
373 _ -> nullSetter n "M43F"
374
375uniformM44F n is = case T.lookup n is of
376 Just (SM44F fun) -> fun
377 _ -> nullSetter n "M44F"
378
379uniformFTexture2D n is = case T.lookup n is of
380 Just (SFTexture2D fun) -> fun
381 _ -> nullSetter n "FTexture2D"