diff options
author | Joe Crayne <joe@jerkface.net> | 2019-05-14 17:52:40 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-05-14 17:52:40 -0400 |
commit | f5d4a74e9a4b23917b97f48bde529cb21e3ec152 (patch) | |
tree | e46037115608c455b738b864ab2f70cc4162f14c /TextureBufferRing.hs | |
parent | b24d6672ff055208f6c0a85a01c43d17d8de9226 (diff) |
Factor TEXTURE_BUFFER-based ring buffer into module.
Diffstat (limited to 'TextureBufferRing.hs')
-rw-r--r-- | TextureBufferRing.hs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/TextureBufferRing.hs b/TextureBufferRing.hs new file mode 100644 index 0000000..2edf86f --- /dev/null +++ b/TextureBufferRing.hs | |||
@@ -0,0 +1,61 @@ | |||
1 | module TextureBufferRing where | ||
2 | |||
3 | import Control.Monad | ||
4 | import Data.Int | ||
5 | import Data.IORef | ||
6 | import qualified Data.Map.Strict as Map | ||
7 | import qualified Data.Vector as V | ||
8 | import Foreign.Marshal.Array | ||
9 | import Foreign.Storable | ||
10 | |||
11 | import LambdaCube.GL as LC | ||
12 | import LambdaCube.GL.Data (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer) | ||
13 | import LambdaCube.GL.Mesh as LC | ||
14 | import LambdaCube.IR as LC | ||
15 | |||
16 | data Ring = Ring | ||
17 | { ringMax :: Int | ||
18 | , ringTexture :: TextureBufferData | ||
19 | , ringStart :: IO Int | ||
20 | , ringSize :: IO Int | ||
21 | , pushBack :: Float -> Float -> Float -> IO () | ||
22 | , popFront :: IO () | ||
23 | } | ||
24 | |||
25 | newRing :: GLStorage -> Int -> IO Ring | ||
26 | newRing storage cnt = do | ||
27 | let ringCapacity = cnt * 3 | ||
28 | tbo <- uploadTextureBufferToGPU ringCapacity | ||
29 | p <- uploadMeshToGPU Mesh | ||
30 | { mAttributes = Map.singleton "position" $ A_Float $ V.fromList | ||
31 | $ replicate ringCapacity 0.0 | ||
32 | , mPrimitive = P_Points | ||
33 | } | ||
34 | obj <- addMeshToObjectArray storage "Points" [] p | ||
35 | LC.updateUniforms storage $ do | ||
36 | "PointBuffer" @= return tbo | ||
37 | rstart <- newIORef 0 | ||
38 | rsize <- newIORef 0 | ||
39 | return Ring | ||
40 | { ringMax = cnt * 3 | ||
41 | , ringTexture = tbo | ||
42 | , ringStart = readIORef rstart | ||
43 | , ringSize = readIORef rsize | ||
44 | , pushBack = \x y z -> do | ||
45 | start <- readIORef rstart | ||
46 | allocaArray 3 $ \ptr -> do | ||
47 | pokeElemOff ptr 0 x | ||
48 | pokeElemOff ptr 1 y | ||
49 | pokeElemOff ptr 2 z | ||
50 | updateTextureBuffer tbo start 3 ptr | ||
51 | writeIORef rstart (mod (start + 3) ringCapacity) | ||
52 | sz <- readIORef rsize | ||
53 | putStrLn $ "pushBack "++show (sz,start,(x,y,z)) | ||
54 | when (sz < ringCapacity) $ do | ||
55 | writeIORef rsize (sz + 3) | ||
56 | , popFront = modifyIORef' rsize $ \s -> if s > 3 then s - 3 else 0 | ||
57 | } | ||
58 | |||
59 | updateRingUniforms storage ring = LC.updateUniforms storage $ do | ||
60 | "PointsStart" @= fmap (fromIntegral :: Int -> Int32) (ringStart ring) | ||
61 | "PointsMax" @= return (fromIntegral (ringMax ring) :: Int32) | ||