{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ScopedTypeVariables, RankNTypes, TypeApplications #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures, TypeOperators #-}
{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.CommandBuffer.Internal (

	-- * ALLOCATE

	C, GBinded, CBinded,

	-- ** Type Level List

	allocateCs, AllocateInfo(..),

	-- ** Value Level List

	allocateList, AllocateInfoList(..),

	-- * BEGIN AND RESET

	begin, reset, M.BeginInfo(..), M.InheritanceInfo(..),

	-- * SUBMIT INFO

	SubmitInfo(..), SubmitInfoListToMiddle(..)

	) where

import Foreign.Storable.PeekPoke
import Control.Exception
import Data.TypeLevel.Tuple.Uncurry
import Data.TypeLevel.Tuple.MapIndex qualified as TMapIndex
import Data.TypeLevel.Maybe qualified as TMaybe
import Data.TypeLevel.List qualified as TLength
import Data.HeteroParList (pattern (:**))
import Data.HeteroParList qualified as HPList
import Data.HeteroParList qualified as HeteroParList
import Data.Word

import Gpu.Vulkan.CommandBuffer.Type
import Gpu.Vulkan.CommandBuffer.Enum

import qualified Gpu.Vulkan.Device.Type as Device
import qualified Gpu.Vulkan.CommandPool.Type as CommandPool
import qualified Gpu.Vulkan.CommandBuffer.Middle as M

allocateCs :: (
	WithPoked (TMaybe.M mn), TLength.Length c, HeteroParList.FromList c ) =>
	Device.D sd -> AllocateInfo mn scp c ->
	(forall scb . HeteroParList.LL (C scb) c -> IO a) -> IO a
allocateCs :: forall (mn :: Maybe (*)) (c :: [()]) sd scp a.
(WithPoked (M mn), Length c, FromList c) =>
D sd
-> AllocateInfo mn scp c
-> (forall scb. LL (C scb) c -> IO a)
-> IO a
allocateCs (Device.D D
dvc) AllocateInfo mn scp c
ai forall scb. LL (C scb) c -> IO a
f = IO [C] -> ([C] -> IO ()) -> ([C] -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
	(D -> AllocateInfo mn -> IO [C]
forall (mn :: Maybe (*)).
WithPoked (M mn) =>
D -> AllocateInfo mn -> IO [C]
M.allocateCs D
dvc (AllocateInfo mn -> IO [C]) -> AllocateInfo mn -> IO [C]
forall a b. (a -> b) -> a -> b
$ AllocateInfo mn scp c -> AllocateInfo mn
forall (n :: Maybe (*)) s (c :: [()]).
Length c =>
AllocateInfo n s c -> AllocateInfo n
allocateInfoToMiddle AllocateInfo mn scp c
ai)
	(D -> C -> [C] -> IO ()
M.freeCs D
dvc
		(C -> [C] -> IO ()) -> (C scp -> C) -> C scp -> [C] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\(CommandPool.C C
cp) -> C
cp) (C scp -> [C] -> IO ()) -> C scp -> [C] -> IO ()
forall a b. (a -> b) -> a -> b
$ AllocateInfo mn scp c -> C scp
forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> C scp
allocateInfoCommandPool AllocateInfo mn scp c
ai)
	(LL (C Any) c -> IO a
forall scb. LL (C scb) c -> IO a
f (LL (C Any) c -> IO a) -> ([C] -> LL (C Any) c) -> [C] -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (s :: ()). C -> Dummy (C Any) s) -> [C] -> LL (C Any) c
forall k (ss :: [k]) a (t :: k -> *).
FromList ss =>
(forall (s :: k). a -> t s) -> [a] -> PL t ss
forall a (t :: () -> *).
(forall (s :: ()). a -> t s) -> [a] -> PL t c
HeteroParList.fromList (C Any -> Dummy (C Any) s
forall a (d :: ()). a -> Dummy a d
HeteroParList.Dummy (C Any -> Dummy (C Any) s) -> (C -> C Any) -> C -> Dummy (C Any) s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. C -> C Any
forall s. C -> C s
C))

allocateList :: WithPoked (TMaybe.M mn) =>
	Device.D sd -> AllocateInfoList mn scp ->
	(forall scb . [C scb] -> IO a) -> IO a
allocateList :: forall (mn :: Maybe (*)) sd scp a.
WithPoked (M mn) =>
D sd
-> AllocateInfoList mn scp -> (forall scb. [C scb] -> IO a) -> IO a
allocateList (Device.D D
dvc) AllocateInfoList mn scp
ai forall scb. [C scb] -> IO a
f = IO [C] -> ([C] -> IO ()) -> ([C] -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
	(D -> AllocateInfo mn -> IO [C]
forall (mn :: Maybe (*)).
WithPoked (M mn) =>
D -> AllocateInfo mn -> IO [C]
M.allocateCs D
dvc (AllocateInfo mn -> IO [C]) -> AllocateInfo mn -> IO [C]
forall a b. (a -> b) -> a -> b
$ AllocateInfoList mn scp -> AllocateInfo mn
forall (n :: Maybe (*)) s. AllocateInfoList n s -> AllocateInfo n
allocateInfoToMiddleList AllocateInfoList mn scp
ai)
	(D -> C -> [C] -> IO ()
M.freeCs D
dvc
		(C -> [C] -> IO ()) -> (C scp -> C) -> C scp -> [C] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\(CommandPool.C C
cp) -> C
cp) (C scp -> [C] -> IO ()) -> C scp -> [C] -> IO ()
forall a b. (a -> b) -> a -> b
$ AllocateInfoList mn scp -> C scp
forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> C scp
allocateInfoCommandPoolList AllocateInfoList mn scp
ai)
	([C Any] -> IO a
forall scb. [C scb] -> IO a
f ([C Any] -> IO a) -> ([C] -> [C Any]) -> [C] -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (C -> C Any
forall s. C -> C s
C (C -> C Any) -> [C] -> [C Any]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>))

data AllocateInfo mn scp (c :: [()]) = AllocateInfo {
	forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> M mn
allocateInfoNext :: TMaybe.M mn,
	forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> C scp
allocateInfoCommandPool :: CommandPool.C scp,
	forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> Level
allocateInfoLevel :: Level }

data AllocateInfoList mn scp = AllocateInfoList {
	forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> M mn
allocateInfoNextList :: TMaybe.M mn,
	forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> C scp
allocateInfoCommandPoolList :: CommandPool.C scp,
	forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> Level
allocateInfoLevelList :: Level,
	forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> Word32
allocateInfoCommandBufferCountList :: Word32 }

deriving instance Show (TMaybe.M mn) => Show (AllocateInfo mn s c)

allocateInfoToMiddle :: forall n s c . TLength.Length c =>
	AllocateInfo n s c -> M.AllocateInfo n
allocateInfoToMiddle :: forall (n :: Maybe (*)) s (c :: [()]).
Length c =>
AllocateInfo n s c -> AllocateInfo n
allocateInfoToMiddle AllocateInfo {
	allocateInfoNext :: forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> M mn
allocateInfoNext = M n
mnxt,
	allocateInfoCommandPool :: forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> C scp
allocateInfoCommandPool = CommandPool.C C
cp,
	allocateInfoLevel :: forall (mn :: Maybe (*)) scp (c :: [()]).
AllocateInfo mn scp c -> Level
allocateInfoLevel = Level
lvl } = M.AllocateInfo {
	allocateInfoNext :: M n
M.allocateInfoNext = M n
mnxt,
	allocateInfoCommandPool :: C
M.allocateInfoCommandPool = C
cp,
	allocateInfoLevel :: Level
M.allocateInfoLevel = Level
lvl,
	allocateInfoCommandBufferCount :: Word32
M.allocateInfoCommandBufferCount = forall k (as :: [k]) n. (Length as, Integral n) => n
TLength.length @_ @c }

allocateInfoToMiddleList :: AllocateInfoList n s -> M.AllocateInfo n
allocateInfoToMiddleList :: forall (n :: Maybe (*)) s. AllocateInfoList n s -> AllocateInfo n
allocateInfoToMiddleList AllocateInfoList {
	allocateInfoNextList :: forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> M mn
allocateInfoNextList = M n
mnxt,
	allocateInfoCommandPoolList :: forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> C scp
allocateInfoCommandPoolList = CommandPool.C C
cp,
	allocateInfoLevelList :: forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> Level
allocateInfoLevelList = Level
lvl,
	allocateInfoCommandBufferCountList :: forall (mn :: Maybe (*)) scp. AllocateInfoList mn scp -> Word32
allocateInfoCommandBufferCountList = Word32
c } = M.AllocateInfo {
	allocateInfoNext :: M n
M.allocateInfoNext = M n
mnxt,
	allocateInfoCommandPool :: C
M.allocateInfoCommandPool = C
cp,
	allocateInfoLevel :: Level
M.allocateInfoLevel = Level
lvl,
	allocateInfoCommandBufferCount :: Word32
M.allocateInfoCommandBufferCount = Word32
c }

begin :: (WithPoked (TMaybe.M mn), WithPoked (TMaybe.M ii)) =>
	C s -> M.BeginInfo mn ii -> IO a -> IO a
begin :: forall (mn :: Maybe (*)) (ii :: Maybe (*)) s a.
(WithPoked (M mn), WithPoked (M ii)) =>
C s -> BeginInfo mn ii -> IO a -> IO a
begin (C C
cb) BeginInfo mn ii
bi IO a
act = IO () -> IO () -> IO a -> IO a
forall a b c. IO a -> IO b -> IO c -> IO c
bracket_ (C -> BeginInfo mn ii -> IO ()
forall (mn :: Maybe (*)) (ii :: Maybe (*)).
(WithPoked (M mn), WithPoked (M ii)) =>
C -> BeginInfo mn ii -> IO ()
M.begin C
cb BeginInfo mn ii
bi) (C -> IO ()
M.end C
cb) IO a
act

reset :: C sc -> ResetFlags -> IO ()
reset :: forall sc. C sc -> ResetFlags -> IO ()
reset (C C
cb) ResetFlags
rfs = C -> ResetFlags -> IO ()
M.reset C
cb ResetFlags
rfs

data SubmitInfo mn sc = SubmitInfo {
	forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> M mn
submitInfoNext :: TMaybe.M mn,
	forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> C sc
submitInfoCommandBuffer :: C sc,
	forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> Word32
submitInfoDeviceMask :: Word32 }

class SubmitInfoListToMiddle mnscs where
	submitInfoListToMiddle ::
		HPList.PL (U2 SubmitInfo) mnscs ->
		HPList.PL M.SubmitInfo (TMapIndex.M0_2 mnscs)

instance SubmitInfoListToMiddle '[] where
	submitInfoListToMiddle :: PL (U2 SubmitInfo) '[] -> PL SubmitInfo (M0_2 '[])
submitInfoListToMiddle PL (U2 SubmitInfo) '[]
HPList.Nil = PL SubmitInfo '[]
PL SubmitInfo (M0_2 '[])
forall {k} (t :: k -> *). PL t '[]
HPList.Nil

instance SubmitInfoListToMiddle mnscs =>
	SubmitInfoListToMiddle (mnsc ': mnscs) where
	submitInfoListToMiddle :: PL (U2 SubmitInfo) (mnsc : mnscs)
-> PL SubmitInfo (M0_2 (mnsc : mnscs))
submitInfoListToMiddle (U2 SubmitInfo s1 s2
si :** PL (U2 SubmitInfo) ss1
sis) =
		SubmitInfo s1 s2 -> SubmitInfo s1
forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> SubmitInfo mn
submitInfoToMiddle SubmitInfo s1 s2
si SubmitInfo s1
-> PL SubmitInfo (M0_2 mnscs) -> PL SubmitInfo (s1 : M0_2 mnscs)
forall {k} (t :: k -> *) (s :: k) (ss1 :: [k]).
t s -> PL t ss1 -> PL t (s : ss1)
:** PL (U2 SubmitInfo) ss1 -> PL SubmitInfo (M0_2 ss1)
forall (mnscs :: [(Maybe (*), *)]).
SubmitInfoListToMiddle mnscs =>
PL (U2 SubmitInfo) mnscs -> PL SubmitInfo (M0_2 mnscs)
submitInfoListToMiddle PL (U2 SubmitInfo) ss1
sis

submitInfoToMiddle :: SubmitInfo mn sc -> M.SubmitInfo mn
submitInfoToMiddle :: forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> SubmitInfo mn
submitInfoToMiddle SubmitInfo {
	submitInfoNext :: forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> M mn
submitInfoNext = M mn
mnxt,
	submitInfoCommandBuffer :: forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> C sc
submitInfoCommandBuffer = C C
c,
	submitInfoDeviceMask :: forall (mn :: Maybe (*)) sc. SubmitInfo mn sc -> Word32
submitInfoDeviceMask = Word32
dm } = M.SubmitInfo {
	submitInfoNext :: M mn
M.submitInfoNext = M mn
mnxt,
	submitInfoCommandBuffer :: C
M.submitInfoCommandBuffer = C
c, submitInfoDeviceMask :: Word32
M.submitInfoDeviceMask = Word32
dm }