1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
|
{-# LANGUAGE ExistentialQuantification, FlexibleInstances, GeneralizedNewtypeDeriving, ScopedTypeVariables #-}
module LambdaCube.GL.Type where
import Data.IORef
import Data.Int
import Data.IntMap (IntMap)
import Data.Set (Set)
import Data.Map (Map)
import Data.Vector (Vector)
import Data.Word
import Foreign.Ptr
import Foreign.Storable
import Data.ByteString
import Graphics.GL.Core33
import Linear
import IR
type GLUniformName = ByteString
---------------
-- Input API --
---------------
{-
-- Buffer
compileBuffer :: [Array] -> IO Buffer
bufferSize :: Buffer -> Int
arraySize :: Buffer -> Int -> Int
arrayType :: Buffer -> Int -> ArrayType
-- Object
addObject :: Renderer -> ByteString -> Primitive -> Maybe (IndexStream Buffer) -> Trie (Stream Buffer) -> [ByteString] -> IO Object
removeObject :: Renderer -> Object -> IO ()
objectUniformSetter :: Object -> Trie InputSetter
-}
data Buffer -- internal type
= Buffer
{ bufArrays :: Vector ArrayDesc
, bufGLObj :: GLuint
}
deriving (Show,Eq)
data ArrayDesc
= ArrayDesc
{ arrType :: ArrayType
, arrLength :: Int -- item count
, arrOffset :: Int -- byte position in buffer
, arrSize :: Int -- size in bytes
}
deriving (Show,Eq)
{-
handles:
uniforms
textures
buffers
objects
GLStorage can be attached to GLRenderer
-}
{-
pipeline input:
- independent from pipeline
- per object features: enable/disable visibility, set render ordering
-}
data ObjectArraySchema
= ObjectArraySchema
{ primitive :: FetchPrimitive
, attributes :: Map String StreamType
}
deriving Show
data PipelineSchema
= PipelineSchema
{ objectArrays :: Map String ObjectArraySchema
, uniforms :: Map String InputType
}
deriving Show
data GLUniform = forall a. Storable a => GLUniform !InputType !(IORef a)
instance Show GLUniform where
show (GLUniform t _) = "GLUniform " ++ show t
data OrderJob
= Generate
| Reorder
| Ordered
data GLSlot
= GLSlot
{ objectMap :: IntMap Object
, sortedObjects :: Vector (Int,Object)
, orderJob :: OrderJob
}
data GLStorage
= GLStorage
{ schema :: PipelineSchema
, slotMap :: Map String SlotName
, slotVector :: Vector (IORef GLSlot)
, objSeed :: IORef Int
, uniformSetter :: Map GLUniformName InputSetter
, uniformSetup :: Map String GLUniform
, screenSize :: IORef (Word,Word)
, pipelines :: IORef (Vector (Maybe GLRenderer)) -- attached pipelines
}
data Object -- internal type
= Object
{ objSlot :: SlotName
, objPrimitive :: Primitive
, objIndices :: Maybe (IndexStream Buffer)
, objAttributes :: Map String (Stream Buffer)
, objUniSetter :: Map GLUniformName InputSetter
, objUniSetup :: Map String GLUniform
, objOrder :: IORef Int
, objEnabled :: IORef Bool
, objId :: Int
, objCommands :: IORef (Vector (Vector [GLObjectCommand])) -- pipeline id, program name, commands
}
--------------
-- Pipeline --
--------------
data GLProgram
= GLProgram
{ shaderObjects :: [GLuint]
, programObject :: GLuint
, inputUniforms :: Map String GLint
, inputTextures :: Map String GLint -- all input textures (render texture + uniform texture)
, inputTextureUniforms :: Set String
, inputStreams :: Map String (GLuint,String)
}
data GLTexture
= GLTexture
{ glTextureObject :: GLuint
, glTextureTarget :: GLenum
}
data InputConnection
= InputConnection
{ icId :: Int -- identifier (vector index) for attached pipeline
, icInput :: GLStorage
, icSlotMapPipelineToInput :: Vector SlotName -- GLRenderer to GLStorage slot name mapping
, icSlotMapInputToPipeline :: Vector (Maybe SlotName) -- GLStorage to GLRenderer slot name mapping
}
data GLStream
= GLStream
{ glStreamCommands :: IORef [GLObjectCommand]
, glStreamPrimitive :: Primitive
, glStreamAttributes :: Map String (Stream Buffer)
, glStreamProgram :: ProgramName
}
data GLRenderer
= GLRenderer
{ glPrograms :: Vector GLProgram
, glTextures :: Vector GLTexture
, glSamplers :: Vector GLSampler
, glTargets :: Vector GLRenderTarget
, glCommands :: [GLCommand]
, glSlotPrograms :: Vector [ProgramName] -- programs depend on a slot
, glInput :: IORef (Maybe InputConnection)
, glSlotNames :: Vector String
, glVAO :: GLuint
, glTexUnitMapping :: Map String (IORef GLint) -- maps texture uniforms to texture units
, glStreams :: Vector GLStream
}
data GLSampler
= GLSampler
{ samplerObject :: GLuint
}
data GLRenderTarget
= GLRenderTarget
{ framebufferObject :: GLuint
, framebufferDrawbuffers :: Maybe [GLenum]
}
data GLCommand
= GLSetRasterContext !RasterContext
| GLSetAccumulationContext !AccumulationContext
| GLSetRenderTarget !GLuint !(Maybe [GLenum])
| GLSetProgram !GLuint
| GLSetSamplerUniform !GLint !GLint (IORef GLint) -- sampler index, texture unit, IORef stores the actual texture unit mapping
| GLSetTexture !GLenum !GLuint !GLuint
| GLSetSampler !GLuint !GLuint
| GLRenderSlot !SlotName !ProgramName
| GLRenderStream !StreamName !ProgramName
| GLClearRenderTarget [ClearImage]
| GLGenerateMipMap !GLenum !GLenum
| GLSaveImage FrameBufferComponent ImageRef -- from framebuffer component to texture (image)
| GLLoadImage ImageRef FrameBufferComponent -- from texture (image) to framebuffer component
deriving Show
instance Show (IORef GLint) where
show _ = "(IORef GLint)"
data GLObjectCommand
= GLSetUniform !GLint !GLUniform
| GLBindTexture !GLenum !(IORef GLint) !GLUniform -- binds the texture from the gluniform to the specified texture unit and target
| GLSetVertexAttribArray !GLuint !GLuint !GLint !GLenum !(Ptr ()) -- index buffer size type pointer
| GLSetVertexAttribIArray !GLuint !GLuint !GLint !GLenum !(Ptr ()) -- index buffer size type pointer
| GLSetVertexAttrib !GLuint !(Stream Buffer) -- index value
| GLDrawArrays !GLenum !GLint !GLsizei -- mode first count
| GLDrawElements !GLenum !GLsizei !GLenum !GLuint !(Ptr ()) -- mode count type buffer indicesPtr
deriving Show
type SetterFun a = a -> IO ()
-- user will provide scalar input data via this type
data InputSetter
= SBool (SetterFun Bool)
| SV2B (SetterFun V2B)
| SV3B (SetterFun V3B)
| SV4B (SetterFun V4B)
| SWord (SetterFun Word32)
| SV2U (SetterFun V2U)
| SV3U (SetterFun V3U)
| SV4U (SetterFun V4U)
| SInt (SetterFun Int32)
| SV2I (SetterFun V2I)
| SV3I (SetterFun V3I)
| SV4I (SetterFun V4I)
| SFloat (SetterFun Float)
| SV2F (SetterFun V2F)
| SV3F (SetterFun V3F)
| SV4F (SetterFun V4F)
| SM22F (SetterFun M22F)
| SM23F (SetterFun M23F)
| SM24F (SetterFun M24F)
| SM32F (SetterFun M32F)
| SM33F (SetterFun M33F)
| SM34F (SetterFun M34F)
| SM42F (SetterFun M42F)
| SM43F (SetterFun M43F)
| SM44F (SetterFun M44F)
-- shadow textures
| SSTexture1D
| SSTexture2D
| SSTextureCube
| SSTexture1DArray
| SSTexture2DArray
| SSTexture2DRect
-- float textures
| SFTexture1D
| SFTexture2D (SetterFun TextureData)
| SFTexture3D
| SFTextureCube
| SFTexture1DArray
| SFTexture2DArray
| SFTexture2DMS
| SFTexture2DMSArray
| SFTextureBuffer
| SFTexture2DRect
-- int textures
| SITexture1D
| SITexture2D
| SITexture3D
| SITextureCube
| SITexture1DArray
| SITexture2DArray
| SITexture2DMS
| SITexture2DMSArray
| SITextureBuffer
| SITexture2DRect
-- uint textures
| SUTexture1D
| SUTexture2D
| SUTexture3D
| SUTextureCube
| SUTexture1DArray
| SUTexture2DArray
| SUTexture2DMS
| SUTexture2DMSArray
| SUTextureBuffer
| SUTexture2DRect
-- buffer handling
{-
user can fills a buffer (continuous memory region)
each buffer have a data descriptor, what describes the
buffer content. e.g. a buffer can contain more arrays of stream types
-}
-- user will provide stream data using this setup function
type BufferSetter = (Ptr () -> IO ()) -> IO ()
-- specifies array component type (stream type in storage side)
-- this type can be overridden in GPU side, e.g ArrWord8 can be seen as TFloat or TWord also
data ArrayType
= ArrWord8
| ArrWord16
| ArrWord32
| ArrInt8
| ArrInt16
| ArrInt32
| ArrFloat
| ArrHalf -- Hint: half float is not supported in haskell
deriving (Show,Eq,Ord)
sizeOfArrayType :: ArrayType -> Int
sizeOfArrayType ArrWord8 = 1
sizeOfArrayType ArrWord16 = 2
sizeOfArrayType ArrWord32 = 4
sizeOfArrayType ArrInt8 = 1
sizeOfArrayType ArrInt16 = 2
sizeOfArrayType ArrInt32 = 4
sizeOfArrayType ArrFloat = 4
sizeOfArrayType ArrHalf = 2
-- describes an array in a buffer
data Array -- array type, element count (NOT byte size!), setter
= Array ArrayType Int BufferSetter
-- dev hint: this should be InputType
-- we restrict StreamType using type class
-- subset of InputType, describes a stream type (in GPU side)
data StreamType
= Attribute_Word
| Attribute_V2U
| Attribute_V3U
| Attribute_V4U
| Attribute_Int
| Attribute_V2I
| Attribute_V3I
| Attribute_V4I
| Attribute_Float
| Attribute_V2F
| Attribute_V3F
| Attribute_V4F
| Attribute_M22F
| Attribute_M23F
| Attribute_M24F
| Attribute_M32F
| Attribute_M33F
| Attribute_M34F
| Attribute_M42F
| Attribute_M43F
| Attribute_M44F
deriving (Show,Eq,Ord)
toStreamType :: InputType -> Maybe StreamType
toStreamType Word = Just Attribute_Word
toStreamType V2U = Just Attribute_V2U
toStreamType V3U = Just Attribute_V3U
toStreamType V4U = Just Attribute_V4U
toStreamType Int = Just Attribute_Int
toStreamType V2I = Just Attribute_V2I
toStreamType V3I = Just Attribute_V3I
toStreamType V4I = Just Attribute_V4I
toStreamType Float = Just Attribute_Float
toStreamType V2F = Just Attribute_V2F
toStreamType V3F = Just Attribute_V3F
toStreamType V4F = Just Attribute_V4F
toStreamType M22F = Just Attribute_M22F
toStreamType M23F = Just Attribute_M23F
toStreamType M24F = Just Attribute_M24F
toStreamType M32F = Just Attribute_M32F
toStreamType M33F = Just Attribute_M33F
toStreamType M34F = Just Attribute_M34F
toStreamType M42F = Just Attribute_M42F
toStreamType M43F = Just Attribute_M43F
toStreamType M44F = Just Attribute_M44F
toStreamType _ = Nothing
fromStreamType :: StreamType -> InputType
fromStreamType Attribute_Word = Word
fromStreamType Attribute_V2U = V2U
fromStreamType Attribute_V3U = V3U
fromStreamType Attribute_V4U = V4U
fromStreamType Attribute_Int = Int
fromStreamType Attribute_V2I = V2I
fromStreamType Attribute_V3I = V3I
fromStreamType Attribute_V4I = V4I
fromStreamType Attribute_Float = Float
fromStreamType Attribute_V2F = V2F
fromStreamType Attribute_V3F = V3F
fromStreamType Attribute_V4F = V4F
fromStreamType Attribute_M22F = M22F
fromStreamType Attribute_M23F = M23F
fromStreamType Attribute_M24F = M24F
fromStreamType Attribute_M32F = M32F
fromStreamType Attribute_M33F = M33F
fromStreamType Attribute_M34F = M34F
fromStreamType Attribute_M42F = M42F
fromStreamType Attribute_M43F = M43F
fromStreamType Attribute_M44F = M44F
-- user can specify streams using Stream type
-- a stream can be constant (ConstXXX) or can came from a buffer
data Stream b
= ConstWord Word32
| ConstV2U V2U
| ConstV3U V3U
| ConstV4U V4U
| ConstInt Int32
| ConstV2I V2I
| ConstV3I V3I
| ConstV4I V4I
| ConstFloat Float
| ConstV2F V2F
| ConstV3F V3F
| ConstV4F V4F
| ConstM22F M22F
| ConstM23F M23F
| ConstM24F M24F
| ConstM32F M32F
| ConstM33F M33F
| ConstM34F M34F
| ConstM42F M42F
| ConstM43F M43F
| ConstM44F M44F
| Stream
{ streamType :: StreamType
, streamBuffer :: b
, streamArrIdx :: Int
, streamStart :: Int
, streamLength :: Int
}
deriving Show
streamToStreamType :: Stream a -> StreamType
streamToStreamType s = case s of
ConstWord _ -> Attribute_Word
ConstV2U _ -> Attribute_V2U
ConstV3U _ -> Attribute_V3U
ConstV4U _ -> Attribute_V4U
ConstInt _ -> Attribute_Int
ConstV2I _ -> Attribute_V2I
ConstV3I _ -> Attribute_V3I
ConstV4I _ -> Attribute_V4I
ConstFloat _ -> Attribute_Float
ConstV2F _ -> Attribute_V2F
ConstV3F _ -> Attribute_V3F
ConstV4F _ -> Attribute_V4F
ConstM22F _ -> Attribute_M22F
ConstM23F _ -> Attribute_M23F
ConstM24F _ -> Attribute_M24F
ConstM32F _ -> Attribute_M32F
ConstM33F _ -> Attribute_M33F
ConstM34F _ -> Attribute_M34F
ConstM42F _ -> Attribute_M42F
ConstM43F _ -> Attribute_M43F
ConstM44F _ -> Attribute_M44F
Stream t _ _ _ _ -> t
-- stream of index values (for index buffer)
data IndexStream b
= IndexStream
{ indexBuffer :: b
, indexArrIdx :: Int
, indexStart :: Int
, indexLength :: Int
}
newtype TextureData
= TextureData
{ textureObject :: GLuint
}
deriving Storable
data Primitive
= TriangleStrip
| TriangleList
| TriangleFan
| LineStrip
| LineList
| PointList
| TriangleStripAdjacency
| TriangleListAdjacency
| LineStripAdjacency
| LineListAdjacency
deriving (Eq,Ord,Bounded,Enum,Show)
type StreamSetter = Stream Buffer -> IO ()
-- storable instances
instance Storable a => Storable (V2 a) where
sizeOf _ = 2 * sizeOf (undefined :: a)
alignment _ = sizeOf (undefined :: a)
peek q = do
let p = castPtr q :: Ptr a
k = sizeOf (undefined :: a)
x <- peek p
y <- peekByteOff p k
return $! (V2 x y)
poke q (V2 x y) = do
let p = castPtr q :: Ptr a
k = sizeOf (undefined :: a)
poke p x
pokeByteOff p k y
instance Storable a => Storable (V3 a) where
sizeOf _ = 3 * sizeOf (undefined :: a)
alignment _ = sizeOf (undefined :: a)
peek q = do
let p = castPtr q :: Ptr a
k = sizeOf (undefined :: a)
x <- peek p
y <- peekByteOff p k
z <- peekByteOff p (k*2)
return $! (V3 x y z)
poke q (V3 x y z) = do
let p = castPtr q :: Ptr a
k = sizeOf (undefined :: a)
poke p x
pokeByteOff p k y
pokeByteOff p (k*2) z
instance Storable a => Storable (V4 a) where
sizeOf _ = 4 * sizeOf (undefined :: a)
alignment _ = sizeOf (undefined :: a)
peek q = do
let p = castPtr q :: Ptr a
k = sizeOf (undefined :: a)
x <- peek p
y <- peekByteOff p k
z <- peekByteOff p (k*2)
w <- peekByteOff p (k*3)
return $! (V4 x y z w)
poke q (V4 x y z w) = do
let p = castPtr q :: Ptr a
k = sizeOf (undefined :: a)
poke p x
pokeByteOff p k y
pokeByteOff p (k*2) z
pokeByteOff p (k*3) w
|