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