| Copyright | (c) Jeremy Nuttall 2025 |
|---|---|
| License | BSD-3-Clause |
| Maintainer | jeremy@jeremy-nuttall.com |
| Stability | experimental |
| Safe Haskell | None |
| Language | Haskell2010 |
Foreign.GPU.Storable.Aligned
Description
Derive Storable instances that respect GPU memory layout rules (std140,
std430, scalar). Works with any product type that has a Generic instance.
data Uniforms = Uniforms
{ viewProj :: M44 Float
, cameraPos :: V3 Float
} deriving Generic
instance AlignedStorable Std140 Uniforms
Then use Foreign.GPU.Marshal.Aligned to get properly-padded pointers:
withPacked @Std140 uniforms $ \ptr -> uploadToGPU ptr
NB: vec3 and mat3 types have historically had driver bugs
around alignment. Prefer vec4/mat4 when possible.
Synopsis
- class MemoryLayoutRules layout => AlignedStorable (layout :: MemoryLayout) a where
- packedAlignedSizeOf :: Proxy layout -> Proxy a -> Int
- alignedSizeOf :: Proxy layout -> Proxy a -> Int
- alignedAlignment :: Proxy layout -> Proxy a -> Int
- alignedPeek :: AlignedPtr layout a -> IO a
- alignedPoke :: AlignedPtr layout a -> a -> IO ()
- data MemoryLayout
- data SMemoryLayout (layout :: MemoryLayout) where
- class KnownMemoryLayout (layout :: MemoryLayout) where
- memoryLayoutSing :: SMemoryLayout layout
- memoryLayoutVal :: forall (layout :: MemoryLayout). KnownMemoryLayout layout => Proxy layout -> MemoryLayout
- newtype Strided (layout :: MemoryLayout) a = Strided {
- unStrided :: a
- type StridedVector (layout :: MemoryLayout) a = Vector (Strided layout a)
- newtype Packed (layout :: MemoryLayout) a = Packed {
- unPacked :: a
- newtype AlignedArray (layout :: MemoryLayout) (n :: Nat) a = AlignedArray {
- unAlignedArray :: Vector n (Strided layout a)
- mkAlignedArray :: forall (layout :: MemoryLayout) a (n :: Nat). (AlignedStorable layout a, Storable a) => Vector n a -> AlignedArray layout n a
- withAlignedArray :: forall (layout :: MemoryLayout) (n :: Nat) a. AlignedArray layout n a -> (Vector n (Strided layout a) -> Vector n (Strided layout a)) -> AlignedArray layout n a
- newtype AlignedPtr (layout :: MemoryLayout) a = AlignedPtr {
- unAlignedPtr :: Ptr a
- class MemoryLayoutRules (layout :: MemoryLayout) where
- alignBlock :: Proxy layout -> Int -> Int
- roundStructSize :: Proxy layout -> Int -> Int -> Int
- layoutStride :: Proxy layout -> Int -> Int -> Int
- class GAlignedStorable (layout :: MemoryLayout) (rep :: Type -> Type) where
- galignedSize :: Proxy layout -> Proxy rep -> Int -> (Int, Int)
- galignedPoke :: AlignedPtr layout a -> rep a -> Int -> IO Int
- galignedPeek :: AlignedPtr layout a -> Int -> IO (rep a, Int)
The AlignedStorable class
class MemoryLayoutRules layout => AlignedStorable (layout :: MemoryLayout) a where Source #
A class for types that have calculable layouts according to GPU requirements.
NB: alignedPoke only writes member data. Only poke into zeroed buffers
unless you really enjoy parsing through garbage in RenderDoc.
Minimal complete definition
Nothing
Methods
packedAlignedSizeOf :: Proxy layout -> Proxy a -> Int Source #
The size of the type a after its contents are laid out, but *before*
any final padding is applied to the container struct itself. This is
the offset after the last member.
default packedAlignedSizeOf :: GAlignedStorable layout (Rep a) => Proxy layout -> Proxy a -> Int Source #
alignedSizeOf :: Proxy layout -> Proxy a -> Int Source #
The size of the type a including final padding/rounding according to the
layout rules for a struct. For Std140, this means the size is rounded
up to a multiple of 16.
default alignedSizeOf :: GAlignedStorable layout (Rep a) => Proxy layout -> Proxy a -> Int Source #
alignedAlignment :: Proxy layout -> Proxy a -> Int Source #
The base alignment requirement for the type a.
default alignedAlignment :: GAlignedStorable layout (Rep a) => Proxy layout -> Proxy a -> Int Source #
alignedPeek :: AlignedPtr layout a -> IO a Source #
Read a value from the given pointer, respecting the layout rules.
default alignedPeek :: (Generic a, GAlignedStorable layout (Rep a)) => AlignedPtr layout a -> IO a Source #
alignedPoke :: AlignedPtr layout a -> a -> IO () Source #
Write a value to the given pointer, respecting the layout rules.
default alignedPoke :: (Generic a, GAlignedStorable layout (Rep a)) => AlignedPtr layout a -> a -> IO () Source #
Instances
Memory layout
data MemoryLayout Source #
A type-level tag representing a memory layout standard.
Constructors
| Std140 |
For details, refer to 7.6.2.2 "Standard Uniform Block Layout" of the OpenGL 4.6 Specification. |
| Std430 |
For details, please refer to the section 7.6.2.2 "Standard Uniform Block Layout" of the OpenGL 4.6 Specification. |
| Scalar |
For details, please refer to the extension specification |
Instances
data SMemoryLayout (layout :: MemoryLayout) where Source #
Singled MemoryLayout, primarily useful for authors of higher-level libraries
(e.g., shader eDSLs, descriptor set builders).
Constructors
| SStd140 :: SMemoryLayout 'Std140 | |
| SStd430 :: SMemoryLayout 'Std430 | |
| SScalar :: SMemoryLayout 'Scalar |
class KnownMemoryLayout (layout :: MemoryLayout) where Source #
This class gives the SMemoryLayout associated with a MemoryLayout.
A very rough sketch of this use case:
emitLayoutQualifier :: forall layout. KnownMemoryLayout layout => String emitLayoutQualifier = case memoryLayoutVal (Proxy @layout) of Std140 -> "layout(std140)" Std430 -> "layout(std430)" Scalar -> "layout(scalar)"
Methods
memoryLayoutSing :: SMemoryLayout layout Source #
Instances
| KnownMemoryLayout 'Scalar Source # | |
Defined in Foreign.GPU.Storable.Aligned Methods | |
| KnownMemoryLayout 'Std140 Source # | |
Defined in Foreign.GPU.Storable.Aligned Methods | |
| KnownMemoryLayout 'Std430 Source # | |
Defined in Foreign.GPU.Storable.Aligned Methods | |
memoryLayoutVal :: forall (layout :: MemoryLayout). KnownMemoryLayout layout => Proxy layout -> MemoryLayout Source #
Storable Wrappers
newtype Strided (layout :: MemoryLayout) a Source #
Wrapper whose sizeOf includes stride padding, for use in arrays.
SV.Vector (Strided Std140 MyType) can be copyBytesd to the GPU in one shot.
Instances
| (MemoryLayoutRules layout, AlignedStorable layout a) => Storable (Strided layout a) Source # |
Use zeroed buffers when using this newtype. | ||||
Defined in Foreign.GPU.Storable.Aligned Methods sizeOf :: Strided layout a -> Int # alignment :: Strided layout a -> Int # peekElemOff :: Ptr (Strided layout a) -> Int -> IO (Strided layout a) # pokeElemOff :: Ptr (Strided layout a) -> Int -> Strided layout a -> IO () # peekByteOff :: Ptr b -> Int -> IO (Strided layout a) # pokeByteOff :: Ptr b -> Int -> Strided layout a -> IO () # peek :: Ptr (Strided layout a) -> IO (Strided layout a) # poke :: Ptr (Strided layout a) -> Strided layout a -> IO () # | |||||
| Generic (Strided layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Associated Types
| |||||
| Show a => Show (Strided layout a) Source # | |||||
| Eq a => Eq (Strided layout a) Source # | |||||
| Ord a => Ord (Strided layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods compare :: Strided layout a -> Strided layout a -> Ordering # (<) :: Strided layout a -> Strided layout a -> Bool # (<=) :: Strided layout a -> Strided layout a -> Bool # (>) :: Strided layout a -> Strided layout a -> Bool # (>=) :: Strided layout a -> Strided layout a -> Bool # max :: Strided layout a -> Strided layout a -> Strided layout a # min :: Strided layout a -> Strided layout a -> Strided layout a # | |||||
| type Rep (Strided layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned | |||||
type StridedVector (layout :: MemoryLayout) a = Vector (Strided layout a) Source #
A convenience type for Data.Vector.Storable.Vector (Strided layout a)
newtype Packed (layout :: MemoryLayout) a Source #
Wrapper without stride padding. Use for single values (push constants, lone UBOs).
Instances
| AlignedStorable layout a => Storable (Packed layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods sizeOf :: Packed layout a -> Int # alignment :: Packed layout a -> Int # peekElemOff :: Ptr (Packed layout a) -> Int -> IO (Packed layout a) # pokeElemOff :: Ptr (Packed layout a) -> Int -> Packed layout a -> IO () # peekByteOff :: Ptr b -> Int -> IO (Packed layout a) # pokeByteOff :: Ptr b -> Int -> Packed layout a -> IO () # | |||||
| Generic (Packed layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Associated Types
| |||||
| Show a => Show (Packed layout a) Source # | |||||
| Eq a => Eq (Packed layout a) Source # | |||||
| Ord a => Ord (Packed layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods compare :: Packed layout a -> Packed layout a -> Ordering # (<) :: Packed layout a -> Packed layout a -> Bool # (<=) :: Packed layout a -> Packed layout a -> Bool # (>) :: Packed layout a -> Packed layout a -> Bool # (>=) :: Packed layout a -> Packed layout a -> Bool # max :: Packed layout a -> Packed layout a -> Packed layout a # min :: Packed layout a -> Packed layout a -> Packed layout a # | |||||
| type Rep (Packed layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned | |||||
newtype AlignedArray (layout :: MemoryLayout) (n :: Nat) a Source #
Opt-in copyBytes for fixed-size arrays. Parameterize your struct by layout:
data MyStruct layout = MyStruct { pixels :: AlignedArray layout 64 (V4 Float) }
Constructors
| AlignedArray | |
Fields
| |
Instances
| (KnownNat n, AlignedStorable 'Scalar a) => AlignedStorable 'Scalar (AlignedArray 'Scalar n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods packedAlignedSizeOf :: Proxy 'Scalar -> Proxy (AlignedArray 'Scalar n a) -> Int Source # alignedSizeOf :: Proxy 'Scalar -> Proxy (AlignedArray 'Scalar n a) -> Int Source # alignedAlignment :: Proxy 'Scalar -> Proxy (AlignedArray 'Scalar n a) -> Int Source # alignedPeek :: AlignedPtr 'Scalar (AlignedArray 'Scalar n a) -> IO (AlignedArray 'Scalar n a) Source # alignedPoke :: AlignedPtr 'Scalar (AlignedArray 'Scalar n a) -> AlignedArray 'Scalar n a -> IO () Source # | |||||
| (KnownNat n, AlignedStorable layout a) => AlignedStorable layout (AlignedArray layout n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods packedAlignedSizeOf :: Proxy layout -> Proxy (AlignedArray layout n a) -> Int Source # alignedSizeOf :: Proxy layout -> Proxy (AlignedArray layout n a) -> Int Source # alignedAlignment :: Proxy layout -> Proxy (AlignedArray layout n a) -> Int Source # alignedPeek :: AlignedPtr layout (AlignedArray layout n a) -> IO (AlignedArray layout n a) Source # alignedPoke :: AlignedPtr layout (AlignedArray layout n a) -> AlignedArray layout n a -> IO () Source # | |||||
| Generic (AlignedArray layout n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Associated Types
Methods from :: AlignedArray layout n a -> Rep (AlignedArray layout n a) x # to :: Rep (AlignedArray layout n a) x -> AlignedArray layout n a # | |||||
| (Show a, AlignedStorable layout a) => Show (AlignedArray layout n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods showsPrec :: Int -> AlignedArray layout n a -> ShowS # show :: AlignedArray layout n a -> String # showList :: [AlignedArray layout n a] -> ShowS # | |||||
| (AlignedStorable layout a, Eq a) => Eq (AlignedArray layout n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods (==) :: AlignedArray layout n a -> AlignedArray layout n a -> Bool # (/=) :: AlignedArray layout n a -> AlignedArray layout n a -> Bool # | |||||
| (AlignedStorable layout a, Ord a) => Ord (AlignedArray layout n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods compare :: AlignedArray layout n a -> AlignedArray layout n a -> Ordering # (<) :: AlignedArray layout n a -> AlignedArray layout n a -> Bool # (<=) :: AlignedArray layout n a -> AlignedArray layout n a -> Bool # (>) :: AlignedArray layout n a -> AlignedArray layout n a -> Bool # (>=) :: AlignedArray layout n a -> AlignedArray layout n a -> Bool # max :: AlignedArray layout n a -> AlignedArray layout n a -> AlignedArray layout n a # min :: AlignedArray layout n a -> AlignedArray layout n a -> AlignedArray layout n a # | |||||
| type Rep (AlignedArray layout n a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned type Rep (AlignedArray layout n a) = D1 ('MetaData "AlignedArray" "Foreign.GPU.Storable.Aligned" "heph-aligned-storable-0.1.0.0-6b8LzptWJ8QFQX2EbHBGXb" 'True) (C1 ('MetaCons "AlignedArray" 'PrefixI 'True) (S1 ('MetaSel ('Just "unAlignedArray") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Vector n (Strided layout a))))) | |||||
mkAlignedArray :: forall (layout :: MemoryLayout) a (n :: Nat). (AlignedStorable layout a, Storable a) => Vector n a -> AlignedArray layout n a Source #
Construct an AlignedArray from a sized vector.
withAlignedArray :: forall (layout :: MemoryLayout) (n :: Nat) a. AlignedArray layout n a -> (Vector n (Strided layout a) -> Vector n (Strided layout a)) -> AlignedArray layout n a Source #
Helper function to unwrap an AlignedArray and manipulate its contents.
Don't do unsafe pointer tricks in the closure.
newtype AlignedPtr (layout :: MemoryLayout) a Source #
A Ptr that is tagged with its MemoryLayout.
Constructors
| AlignedPtr | |
Fields
| |
Instances
| Generic (AlignedPtr layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Associated Types
Methods from :: AlignedPtr layout a -> Rep (AlignedPtr layout a) x # to :: Rep (AlignedPtr layout a) x -> AlignedPtr layout a # | |||||
| Show (AlignedPtr layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned Methods showsPrec :: Int -> AlignedPtr layout a -> ShowS # show :: AlignedPtr layout a -> String # showList :: [AlignedPtr layout a] -> ShowS # | |||||
| type Rep (AlignedPtr layout a) Source # | |||||
Defined in Foreign.GPU.Storable.Aligned type Rep (AlignedPtr layout a) = D1 ('MetaData "AlignedPtr" "Foreign.GPU.Storable.Aligned" "heph-aligned-storable-0.1.0.0-6b8LzptWJ8QFQX2EbHBGXb" 'True) (C1 ('MetaCons "AlignedPtr" 'PrefixI 'True) (S1 ('MetaSel ('Just "unAlignedPtr") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Ptr a)))) | |||||
Memory layout rules
class MemoryLayoutRules (layout :: MemoryLayout) where Source #
Defines the precise calculation rules for a given MemoryLayout.
These rules correspond to the memory layout requirements found in the OpenGL and Vulkan specifications.
Methods
alignBlock :: Proxy layout -> Int -> Int Source #
The alignment rule for top-level structs, matrix rows, and array members.
roundStructSize :: Proxy layout -> Int -> Int -> Int Source #
The final size rule for a top-level struct.
layoutStride :: Proxy layout -> Int -> Int -> Int Source #
The stride rule for an element within an array.
Instances
Generics
class GAlignedStorable (layout :: MemoryLayout) (rep :: Type -> Type) where Source #
Generically derive AlignedStorable.
data MyType = MyType { field1 :: Float, field2 :: V3 Float }
deriving (Generic)
instance AlignedStorable Std140 MyTypeMethods
galignedSize :: Proxy layout -> Proxy rep -> Int -> (Int, Int) Source #
galignedPoke :: AlignedPtr layout a -> rep a -> Int -> IO Int Source #
galignedPeek :: AlignedPtr layout a -> Int -> IO (rep a, Int) Source #
Instances
| (TypeError ('Text "Cannot derive AlignedStorable for nullary constructors as there is no shader equivalent.") :: Constraint) => GAlignedStorable layout (U1 :: Type -> Type) Source # | |
Defined in Foreign.GPU.Storable.Aligned | |
| (TypeError ('Text "Cannot derive AlignedStorable for empty data types as there is no shader equivalent.") :: Constraint) => GAlignedStorable layout (V1 :: Type -> Type) Source # | |
Defined in Foreign.GPU.Storable.Aligned | |
| (GAlignedStorable layout a, GAlignedStorable layout b) => GAlignedStorable layout (a :*: b) Source # | |
Defined in Foreign.GPU.Storable.Aligned Methods galignedSize :: Proxy layout -> Proxy (a :*: b) -> Int -> (Int, Int) Source # galignedPoke :: AlignedPtr layout a0 -> (a :*: b) a0 -> Int -> IO Int Source # galignedPeek :: AlignedPtr layout a0 -> Int -> IO ((a :*: b) a0, Int) Source # | |
| (TypeError ('Text "Cannot derive AlignedStorable for sum types as there is no unambiguous shader equivalent.") :: Constraint) => GAlignedStorable layout (a :+: b) Source # | |
Defined in Foreign.GPU.Storable.Aligned Methods galignedSize :: Proxy layout -> Proxy (a :+: b) -> Int -> (Int, Int) Source # galignedPoke :: AlignedPtr layout a0 -> (a :+: b) a0 -> Int -> IO Int Source # galignedPeek :: AlignedPtr layout a0 -> Int -> IO ((a :+: b) a0, Int) Source # | |
| AlignedStorable layout c => GAlignedStorable layout (K1 i c :: Type -> Type) Source # | |
Defined in Foreign.GPU.Storable.Aligned | |
| GAlignedStorable layout f => GAlignedStorable layout (M1 i c f) Source # | |
Defined in Foreign.GPU.Storable.Aligned Methods galignedSize :: Proxy layout -> Proxy (M1 i c f) -> Int -> (Int, Int) Source # galignedPoke :: AlignedPtr layout a -> M1 i c f a -> Int -> IO Int Source # galignedPeek :: AlignedPtr layout a -> Int -> IO (M1 i c f a, Int) Source # | |