module Vulkan.Utils.Pipeline.Specialization
( withSpecialization
, allocateSpecialization
, Specialization (..)
, SpecializationConst (..)
) where
import Control.Monad.IO.Class (liftIO)
import Control.Monad.IO.Unlift (MonadUnliftIO, withRunInIO)
import Control.Monad.Trans.Resource (MonadResource, allocate)
import Data.Bool (bool)
import Data.Int (Int32)
import Data.Vector (Vector)
import qualified Data.Vector as Vector
import qualified Data.Vector.Storable as Storable
import Data.Word (Word32)
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Array (mallocArray, pokeArray)
import Foreign.Ptr (castPtr)
import GHC.Float (castFloatToWord32)
import qualified Vulkan.Core10 as Vk
withSpecialization
:: (Specialization spec, MonadUnliftIO m)
=> spec
-> (Maybe Vk.SpecializationInfo -> m a)
-> m a
withSpecialization :: forall spec (m :: * -> *) a.
(Specialization spec, MonadUnliftIO m) =>
spec -> (Maybe SpecializationInfo -> m a) -> m a
withSpecialization spec
spec Maybe SpecializationInfo -> m a
action =
if Vector Word32 -> Bool
forall a. Storable a => Vector a -> Bool
Storable.null Vector Word32
specData
then
Maybe SpecializationInfo -> m a
action Maybe SpecializationInfo
forall a. Maybe a
Nothing
else ((forall a. m a -> IO a) -> IO a) -> m a
forall b. ((forall a. m a -> IO a) -> IO b) -> m b
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO a) -> m a)
-> ((forall a. m a -> IO a) -> IO a) -> m a
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
run ->
Vector Word32 -> (Ptr Word32 -> IO a) -> IO a
forall a b. Storable a => Vector a -> (Ptr a -> IO b) -> IO b
Storable.unsafeWith Vector Word32
specData ((Ptr Word32 -> IO a) -> IO a) -> (Ptr Word32 -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr Word32
specPtr ->
m a -> IO a
forall a. m a -> IO a
run (m a -> IO a)
-> (Maybe SpecializationInfo -> m a)
-> Maybe SpecializationInfo
-> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe SpecializationInfo -> m a
action (Maybe SpecializationInfo -> IO a)
-> Maybe SpecializationInfo -> IO a
forall a b. (a -> b) -> a -> b
$
SpecializationInfo -> Maybe SpecializationInfo
forall a. a -> Maybe a
Just
Vk.SpecializationInfo
{ mapEntries :: Vector SpecializationMapEntry
Vk.mapEntries = Vector SpecializationMapEntry
mapEntries
, dataSize :: Word64
Vk.dataSize = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word64) -> Int -> Word64
forall a b. (a -> b) -> a -> b
$ Vector Word32 -> Int
forall a. Storable a => Vector a -> Int
Storable.length Vector Word32
specData Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
4
, data' :: Ptr ()
Vk.data' = Ptr Word32 -> Ptr ()
forall a b. Ptr a -> Ptr b
castPtr Ptr Word32
specPtr
}
where
specData :: Storable.Vector Word32
specData :: Vector Word32
specData = [Word32] -> Vector Word32
forall a. Storable a => [a] -> Vector a
Storable.fromList (spec -> [Word32]
forall a. Specialization a => a -> [Word32]
specializationData spec
spec)
mapEntries :: Vector Vk.SpecializationMapEntry
mapEntries :: Vector SpecializationMapEntry
mapEntries = Int -> Vector SpecializationMapEntry
specializationMapEntries (Vector Word32 -> Int
forall a. Storable a => Vector a -> Int
Storable.length Vector Word32
specData)
allocateSpecialization
:: (Specialization spec, MonadResource m)
=> spec
-> m (Maybe Vk.SpecializationInfo)
allocateSpecialization :: forall spec (m :: * -> *).
(Specialization spec, MonadResource m) =>
spec -> m (Maybe SpecializationInfo)
allocateSpecialization spec
spec =
case spec -> [Word32]
forall a. Specialization a => a -> [Word32]
specializationData spec
spec of
[] ->
Maybe SpecializationInfo -> m (Maybe SpecializationInfo)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe SpecializationInfo
forall a. Maybe a
Nothing
[Word32]
ws -> do
let n :: Int
n = [Word32] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word32]
ws
(_key, ptr) <- IO (Ptr Word32)
-> (Ptr Word32 -> IO ()) -> m (ReleaseKey, Ptr Word32)
forall (m :: * -> *) a.
MonadResource m =>
IO a -> (a -> IO ()) -> m (ReleaseKey, a)
allocate (Int -> IO (Ptr Word32)
forall a. Storable a => Int -> IO (Ptr a)
mallocArray Int
n) Ptr Word32 -> IO ()
forall a. Ptr a -> IO ()
free
liftIO $ pokeArray ptr ws
pure $
Just
Vk.SpecializationInfo
{ Vk.mapEntries = specializationMapEntries n
, Vk.dataSize = fromIntegral (n * 4)
, Vk.data' = castPtr ptr
}
specializationMapEntries :: Int -> Vector Vk.SpecializationMapEntry
specializationMapEntries :: Int -> Vector SpecializationMapEntry
specializationMapEntries Int
n =
Int
-> (Int -> SpecializationMapEntry) -> Vector SpecializationMapEntry
forall a. Int -> (Int -> a) -> Vector a
Vector.generate Int
n ((Int -> SpecializationMapEntry) -> Vector SpecializationMapEntry)
-> (Int -> SpecializationMapEntry) -> Vector SpecializationMapEntry
forall a b. (a -> b) -> a -> b
$ \Int
ix ->
Vk.SpecializationMapEntry
{ constantID :: Word32
Vk.constantID = Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ix
, offset :: Word32
Vk.offset = Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
4)
, size :: Word64
Vk.size = Word64
4
}
class Specialization a where
specializationData :: a -> [Word32]
instance Specialization () where
specializationData :: () -> [Word32]
specializationData ()
_ = []
instance Specialization [Word32] where
specializationData :: [Word32] -> [Word32]
specializationData = [Word32] -> [Word32]
forall a. a -> a
id
instance Specialization Word32 where
specializationData :: Word32 -> [Word32]
specializationData Word32
x = [Word32 -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData Word32
x]
instance Specialization Int32 where
specializationData :: Int32 -> [Word32]
specializationData Int32
x = [Int32 -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData Int32
x]
instance Specialization Float where
specializationData :: Float -> [Word32]
specializationData Float
x = [Float -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData Float
x]
instance Specialization Bool where
specializationData :: Bool -> [Word32]
specializationData Bool
x = [Bool -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData Bool
x]
class SpecializationConst a where
packConstData :: a -> Word32
instance SpecializationConst Word32 where
packConstData :: Word32 -> Word32
packConstData = Word32 -> Word32
forall a. a -> a
id
instance SpecializationConst Int32 where
packConstData :: Int32 -> Word32
packConstData = Int32 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance SpecializationConst Float where
packConstData :: Float -> Word32
packConstData = Float -> Word32
castFloatToWord32
instance SpecializationConst Bool where
packConstData :: Bool -> Word32
packConstData = Word32 -> Word32 -> Bool -> Word32
forall a. a -> a -> Bool -> a
bool Word32
0 Word32
1
instance
( SpecializationConst a
, SpecializationConst b
)
=> Specialization (a, b)
where
specializationData :: (a, b) -> [Word32]
specializationData (a
a, b
b) =
[ a -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData a
a
, b -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData b
b
]
instance
( SpecializationConst a
, SpecializationConst b
, SpecializationConst c
)
=> Specialization (a, b, c)
where
specializationData :: (a, b, c) -> [Word32]
specializationData (a
a, b
b, c
c) =
[ a -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData a
a
, b -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData b
b
, c -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData c
c
]
instance
( SpecializationConst a
, SpecializationConst b
, SpecializationConst c
, SpecializationConst d
)
=> Specialization (a, b, c, d)
where
specializationData :: (a, b, c, d) -> [Word32]
specializationData (a
a, b
b, c
c, d
d) =
[ a -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData a
a
, b -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData b
b
, c -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData c
c
, d -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData d
d
]
instance
( SpecializationConst a
, SpecializationConst b
, SpecializationConst c
, SpecializationConst d
, SpecializationConst e
)
=> Specialization (a, b, c, d, e)
where
specializationData :: (a, b, c, d, e) -> [Word32]
specializationData (a
a, b
b, c
c, d
d, e
e) =
[ a -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData a
a
, b -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData b
b
, c -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData c
c
, d -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData d
d
, e -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData e
e
]
instance
( SpecializationConst a
, SpecializationConst b
, SpecializationConst c
, SpecializationConst d
, SpecializationConst e
, SpecializationConst f
)
=> Specialization (a, b, c, d, e, f)
where
specializationData :: (a, b, c, d, e, f) -> [Word32]
specializationData (a
a, b
b, c
c, d
d, e
e, f
f) =
[ a -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData a
a
, b -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData b
b
, c -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData c
c
, d -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData d
d
, e -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData e
e
, f -> Word32
forall a. SpecializationConst a => a -> Word32
packConstData f
f
]