summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2019-05-30 00:09:21 -0400
committerJoe Crayne <joe@jerkface.net>2019-05-30 00:09:21 -0400
commit315d96fb6f76985ec9269a434039f3afca983d5a (patch)
tree8c681a071207f3d7cc8c08a9464eccf9c95a04f1
parent8e735080a3f45a90f9952f1ff883260b1230fdf1 (diff)
Factored gpu-backend out of RingBuffer, wrote vector-backend.
-rw-r--r--GPURing.hs46
-rw-r--r--MeshSketch.hs9
-rw-r--r--PointPrimitiveRing.hs109
-rw-r--r--RingBuffer.hs70
-rw-r--r--VectorRing.hs17
5 files changed, 138 insertions, 113 deletions
diff --git a/GPURing.hs b/GPURing.hs
new file mode 100644
index 0000000..d5f46af
--- /dev/null
+++ b/GPURing.hs
@@ -0,0 +1,46 @@
1module GPURing where
2
3import Control.Monad.Writer
4import Data.Data
5import Data.Dependent.Sum
6import Data.Function
7import Data.Typeable
8
9import AttributeData
10import RingBuffer
11import MaskableStream
12
13import LambdaCube.GL as LC hiding (updateBuffer)
14import LambdaCube.GL.Data hiding (updateBuffer) -- (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer)
15import LambdaCube.GL.Mesh as LC
16import LambdaCube.GL.Type
17import LambdaCube.IR as LC
18import LambdaCube.GL.Util
19import LambdaCube.GL.Input.Type
20import LambdaCube.GL.Input hiding (createObjectCommands)
21
22
23-- | Typical usage:
24--
25-- > ringBuffer <- newRing capacity (VectorRing.new capacity)
26type Update keys = (keys -> Writer [DSum AttributeKey GLUniformValue] ())
27
28new :: Data keys => GLStorage -> (String -> String) -> Int -> IO (TargetBuffer (Update keys))
29new storage toAttr sz = fix $ \retProxy -> do
30 let paramProxy = paramProxy' retProxy
31 where paramProxy' :: io (targetbuffer (keys -> writer)) -> Proxy keys
32 paramProxy' _ = Proxy
33 let ps = fieldParameters paramProxy toAttr
34 putStrLn $ "Ring params: " ++ show ps
35 gd0 <- uploadDynamicBuffer sz ps
36 let gd = gd0 { dPrimitive = LineStrip }
37 Just keys <- return $ lookupAttrKeys (lookupAttributeKey gd . toAttr)
38 obj <- addToObjectArray storage "Points" [] gd
39 -- readIORef (objCommands obj) >>= mapM_ print
40 return TargetBuffer
41 { syncBuffer = \mask -> do updateCommands storage obj mask
42 return ()
43 , updateBuffer = \i u -> do updateAttributes i $ u keys
44 return ()
45 }
46
diff --git a/MeshSketch.hs b/MeshSketch.hs
index d598bbd..8660119 100644
--- a/MeshSketch.hs
+++ b/MeshSketch.hs
@@ -59,7 +59,8 @@ import LoadMesh
59import InfinitePlane 59import InfinitePlane
60import MtlParser (ObjMaterial(..)) 60import MtlParser (ObjMaterial(..))
61import Matrix 61import Matrix
62import PointPrimitiveRing 62import GPURing as GPU
63import RingBuffer
63import MaskableStream (AttributeKey,(@<-)) 64import MaskableStream (AttributeKey,(@<-))
64import SmallRing 65import SmallRing
65 66
@@ -103,7 +104,7 @@ data State = State
103 , stSkybox :: IORef Int 104 , stSkybox :: IORef Int
104 , stSkyTexture :: IORef TextureCubeData 105 , stSkyTexture :: IORef TextureCubeData
105 , stDragFrom :: IORef (Maybe (Vector Float,Camera)) 106 , stDragFrom :: IORef (Maybe (Vector Float,Camera))
106 , stRingBuffer :: Ring RingPoint 107 , stRingBuffer :: RingBuffer (GPU.Update RingPoint)
107 , stPenDown :: IORef Bool 108 , stPenDown :: IORef Bool
108 , stPlane :: IORef (Maybe Plane) 109 , stPlane :: IORef (Maybe Plane)
109 , stDragPlane :: IORef (Maybe (Vector Float,Plane)) 110 , stDragPlane :: IORef (Maybe (Vector Float,Plane))
@@ -204,7 +205,7 @@ uploadState obj glarea storage = do
204 -- grid plane 205 -- grid plane
205 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" [] 206 uploadMeshToGPU xzplane >>= addMeshToObjectArray storage "plane" []
206 207
207 ring <- newRing storage 100 ringPointAttr 208 ring <- newRing 100 (GPU.new storage ringPointAttr 100)
208 209
209 -- setup FrameClock 210 -- setup FrameClock
210 w <- toWidget glarea 211 w <- toWidget glarea
@@ -298,7 +299,7 @@ setUniforms gl storage st = do
298 "CameraPosition" @= return (pos :: Vector Float) 299 "CameraPosition" @= return (pos :: Vector Float)
299 "ViewProjection" @= return (mvp :: Matrix Float) 300 "ViewProjection" @= return (mvp :: Matrix Float)
300 "PlaneModel" @= return planeModel 301 "PlaneModel" @= return planeModel
301 updateRingUniforms storage (stRingBuffer st) 302 -- updateRingUniforms storage (stRingBuffer st)
302 303
303data MeshSketch = MeshSketch 304data MeshSketch = MeshSketch
304 { mmWidget :: GLArea 305 { mmWidget :: GLArea
diff --git a/PointPrimitiveRing.hs b/PointPrimitiveRing.hs
deleted file mode 100644
index d4fafae..0000000
--- a/PointPrimitiveRing.hs
+++ /dev/null
@@ -1,109 +0,0 @@
1{-# LANGUAGE LambdaCase, RecordWildCards, DataKinds #-}
2module PointPrimitiveRing where
3
4import Control.Monad
5import Control.Monad.Writer
6import Data.Data
7import Data.Dependent.Sum
8import Data.Foldable
9import Data.Function
10import Data.Int
11import Data.IORef
12import Data.Maybe
13import Data.Some
14import Data.Word
15import qualified Data.Map.Strict as Map
16import qualified Data.Vector as V
17 ;import Data.Vector as V ((!),(//))
18import Foreign.C.Types (CPtrdiff)
19import Foreign.Marshal
20import Foreign.Ptr
21import Foreign.Storable
22
23import LambdaCube.GL as LC
24import LambdaCube.GL.Data -- (uploadCubeMapToGPU,uploadTextureBufferToGPU,updateTextureBuffer)
25import LambdaCube.GL.Mesh as LC
26import LambdaCube.GL.Type
27import LambdaCube.IR as LC
28import LambdaCube.GL.Util
29import LambdaCube.GL.Input.Type
30import LambdaCube.GL.Input hiding (createObjectCommands)
31
32import AttributeData
33
34-- import Graphics.GL.Core33
35
36import MaskableStream
37
38data Ring keys = Ring
39 { rBufferObject :: Buffer
40 , rStorage :: GLStorage
41 , rObject :: Object
42 , rSize :: IORef Int -- Current count of vertices in the ring buffer.
43 , rBack :: IORef Int -- Where next vertex will be added.
44 , ringCapacity :: Int -- Maximum number of vertices in buffer.
45 , rKeys :: keys
46 }
47
48newRing :: Data keys => GLStorage -> Int -> (String -> String) -> IO (Ring keys)
49newRing storage sz toAttr = fix $ \retProxy -> do
50 let paramProxy = paramProxy' retProxy
51 where paramProxy' :: io (ring keys) -> Proxy keys
52 paramProxy' _ = Proxy
53 startRef <- newIORef 0
54 sizeRef <- newIORef 0
55 let ps = fieldParameters paramProxy toAttr
56 putStrLn $ "Ring params: " ++ show ps
57 gd0 <- uploadDynamicBuffer sz ps
58 let gd = gd0 { dPrimitive = LineStrip }
59 Just keys <- return $ lookupAttrKeys (lookupAttributeKey gd . toAttr)
60 obj <- addToObjectArray storage "Points" [] gd
61 readIORef (objCommands obj) >>= mapM_ print
62 let r = Ring
63 { rBufferObject = streamBuffer $ head $ Map.elems (dStreams gd)
64 , rStorage = storage
65 , rObject = obj
66 , rSize = sizeRef
67 , rBack = startRef
68 , ringCapacity = sz
69 , rKeys = keys
70 }
71 updateRingCommands r
72 return r
73
74clearRing :: Ring keys -> IO ()
75clearRing r = do
76 writeIORef (rBack r) 0
77 writeIORef (rSize r) 0
78 updateRingCommands r
79
80updateRingCommands :: Ring keys -> IO ()
81updateRingCommands r = do
82 back <- fromIntegral <$> readIORef (rBack r)
83 size <- fromIntegral <$> readIORef (rSize r)
84 let mask 0 = []
85 mask cnt
86 | cnt==size = [(0,cnt)]
87 | otherwise = case cnt + back - size of
88 front | front > cnt -> [(front - cnt,size)]
89 | otherwise -> [(0,back), (front,cnt - front)]
90 updateCommands (rStorage r) (rObject r) mask
91 -- readIORef (objCommands $ rObject r) >>= mapM_ print
92 return ()
93
94pushBack :: Ring keys -> (keys -> Writer [DSum AttributeKey GLUniformValue] a) -> IO ()
95pushBack r attrs = do
96 back <- readIORef $ rBack r
97 writeIORef (rBack r) (mod (back + 1) (ringCapacity r))
98 updateAttributes back $ attrs (rKeys r)
99 sz <- readIORef (rSize r)
100 when (sz < ringCapacity r) $ writeIORef (rSize r) (sz + 1)
101 updateRingCommands r
102
103updateBack :: Ring keys -> (keys -> Writer [DSum AttributeKey GLUniformValue] a) -> IO ()
104updateBack r attrs = do
105 back <- readIORef $ rBack r
106 updateAttributes (mod (back - 1) (ringCapacity r)) $ attrs (rKeys r)
107
108updateRingUniforms :: GLStorage -> Ring keys -> IO ()
109updateRingUniforms _ _ = return ()
diff --git a/RingBuffer.hs b/RingBuffer.hs
new file mode 100644
index 0000000..b2779d7
--- /dev/null
+++ b/RingBuffer.hs
@@ -0,0 +1,70 @@
1module RingBuffer where
2
3import Control.Monad
4import Data.Int
5import Data.IORef
6
7data TargetBuffer u = TargetBuffer
8 { -- | Called whenever the rBack or rSize changes. The purpose is so that
9 -- some other state, such as an OpenGL vertex buffer object, can remain in
10 -- sync.
11 syncBuffer :: (Int32 -> [(Int32,Int32)]) -> IO ()
12 -- | This updates the data associated with a particular index (usually
13 -- rBack). The update specification /u/ may be a value or a set of
14 -- key-value pairs or whatever is most convenient way to instruct the
15 -- target representation to update itself.
16 , updateBuffer :: Int -> u -> IO ()
17 }
18
19data RingBuffer u = RingBuffer
20 { rBack :: IORef Int
21 , rSize :: IORef Int
22 , ringCapacity :: Int
23 , rBuffer :: TargetBuffer u
24 }
25
26newRing :: Int -> IO (TargetBuffer u) -> IO (RingBuffer u)
27newRing sz newBuffer = do
28 backRef <- newIORef 0
29 sizeRef <- newIORef 0
30 b <- newBuffer
31 let r = RingBuffer
32 { rBack = backRef
33 , rSize = sizeRef
34 , ringCapacity = sz
35 , rBuffer = b
36 }
37 syncRing r
38 return r
39
40syncRing :: RingBuffer u -> IO ()
41syncRing r = do
42 size <- fromIntegral <$> readIORef (rSize r)
43 back <- fromIntegral <$> readIORef (rBack r)
44 let mask 0 = []
45 mask cnt
46 | cnt==size = [(0,cnt)]
47 | otherwise = case cnt + back - size of
48 front | front > cnt -> [(front - cnt,size)]
49 | otherwise -> [(0,back), (front,cnt - front)]
50 syncBuffer (rBuffer r) mask
51
52clearRing :: RingBuffer u -> IO ()
53clearRing r = do
54 writeIORef (rBack r) 0
55 writeIORef (rSize r) 0
56 syncRing r
57
58pushBack :: RingBuffer u -> u -> IO ()
59pushBack r upd = do
60 back <- readIORef $ rBack r
61 writeIORef (rBack r) (mod (back + 1) (ringCapacity r))
62 updateBuffer (rBuffer r) back upd
63 sz <- readIORef (rSize r)
64 when (sz < ringCapacity r) $ writeIORef (rSize r) (sz + 1)
65 syncRing r
66
67updateBack :: RingBuffer u -> u -> IO ()
68updateBack r upd = do
69 back <- readIORef $ rBack r
70 updateBuffer (rBuffer r) back upd
diff --git a/VectorRing.hs b/VectorRing.hs
new file mode 100644
index 0000000..2ddac72
--- /dev/null
+++ b/VectorRing.hs
@@ -0,0 +1,17 @@
1module VectorRing where
2
3import Data.Vector.Unboxed.Mutable
4import RingBuffer
5
6-- | Typical usage:
7--
8-- > ringBuffer <- newRing capacity (VectorRing.new capacity)
9new :: Unbox a => Int -> IO (TargetBuffer a)
10new sz = do
11 v <- unsafeNew sz
12 return () :: IO ()
13 return TargetBuffer
14 { syncBuffer = \_ -> return ()
15 , updateBuffer = \i u -> write v i u
16 }
17