## gl-block
### Using
Primitive types should have the `Block` instance.
With that in place, you can build structures and get Storable instances derived generically, according to intented usage.
```haskell
import GHC.Generics (Generic)
import Graphics.Gl.Block (Block, Packed(..), Std140(..), Std430(..))
-- | Attribute streams can be packed tightly together
data VertexAttrs = VertexAttrs
{ color :: Vec4
, texCoords :: Vec2
}
deriving stock (Eq, Ord, Show, Generic) -- The regular stuff and Generic
deriving anyclass Block -- The layout class, with Generic defaults
deriving Storable via (Packed VertexAttrs) -- Free goodies!
-- | Uniform data require jumping through padding and alignment flaming hoop.
-- You can use derive-storable-plugin or hs2c instead, but there are gotchas.
data SceneUniform = SceneUniform
{ projection :: Mat4
, viewPosition :: Vec3 -- Here comes the jazz
, viewDirection :: Vec3
}
deriving stock (Eq, Ord, Show, Generic)
deriving anyclass Block
deriving Storable via (Std140 VertexAttrs) -- With comfy padding
-- | Shader buffer objects are less vacuous, but the rules are specific to the domain.
data Material = Material
{ baseColor :: Vec4
, metallicRoughness :: Vec2
, emission :: Vec4
}
deriving stock (Eq, Ord, Show, Generic)
deriving anyclass Block
deriving Storable via (Std430 VertexAttrs) -- Less alignment, less calculations
```
* [Shader Buffer Memory Layout Info](https://gist.github.com/teoxoy/936891c16c2a3d1c3c5e7204ac6cd76c)
### Benchmarks
The benchmark consists of filling a Storable vector.
* Packed layout is on par with manual instances.
* Std140 is slower, but not catastrophically so.
* Std430 seems to regain some performance due to being a tad simpler.
> There's only one "manual" case standing for all the layouts since it would only be different in pointer offsets.
> And no way in hell I'm going to calculate them by hand!
```python
struct
10
manual: OK (2.26s)
60.6 ns ± 5.4 ns
packed: OK (1.21s)
63.7 ns ± 5.8 ns
std140: OK (1.19s)
256 ns ± 26 ns
std430: OK (0.13s)
269 ns ± 24 ns
1000
manual: OK (1.95s)
3.34 μs ± 244 ns
packed: OK (1.96s)
3.34 μs ± 235 ns
std140: OK (1.97s)
6.70 μs ± 425 ns
std430: OK (1.44s)
4.89 μs ± 93 ns
1000000
manual: OK (2.59s)
2.22 ms ± 176 μs
packed: OK (1.50s)
2.47 ms ± 24 μs
std140: OK (2.70s)
4.54 ms ± 431 μs
std430: OK (1.08s)
3.28 ms ± 244 μs
```
> Caveat: nested structures have degraded performance.