packages feed

gpu-vulkan-middle-0.1.0.54: src/Gpu/Vulkan/Specialization/Middle/Internal.hs

{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Specialization.Middle.Internal (infoToCore) where

import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import Foreign.Storable.HeteroList hiding (alignments)
import qualified Data.HeteroParList as HeteroParList

import qualified Gpu.Vulkan.Specialization.Core as C

type Parameters = (Int, [(Int, Int, Int)], Int, Int)

parameters :: [(Int, Int)] -> Parameters
parameters szals = (
	length szals, zip3 [0 ..] ofs (fst <$> szals), tsz, alignments szals )
	where
	ofs = offsets szals; szs = fst <$> szals; tsz = last ofs + last szs

offsets :: [(Int, Int)] -> [Int]
offsets = tail . (fst <$>) . scanl step (0, 0)

step :: (Int, Int) -> (Int, Int) -> (Int, Int)
step (_st, ed) (sz, al) = (st', st' + sz)
	where st' = ((ed - 1) `div` al + 1) * al

alignments :: [(Int, Int)] -> Int
alignments = foldl lcm 1 . (snd <$>)

mapEntries :: Parameters -> [C.MapEntry]
mapEntries (_, ps, _, _) = (<$> ps) \(i, o, s) -> C.MapEntry {
	C.mapEntryConstantId = fromIntegral i,
	C.mapEntryOffset = fromIntegral o,
	C.mapEntrySize = fromIntegral s }

infoToCore :: forall vs a . PokableList vs =>
	HeteroParList.L vs -> (C.Info -> IO a) -> IO a
infoToCore xs f =
	allocaArray n \pmes ->
	pokeArray pmes (mapEntries ps) >>
	allocaBytesAligned tsz tal \pd ->
	pokeList pd xs >>
	f C.Info {
		C.infoMapEntryCount = fromIntegral n,
		C.infoPMapEntries = pmes,
		C.infoDataSize = fromIntegral tsz,
		C.infoPData = pd }
	where
	szals = sizeAlignments @vs
	ps@(n, _, tsz, tal) = parameters szals