{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Pipeline.ShaderStage.Middle.Internal (
	CreateInfo(..), createInfoToCore,
	CreateInfoListToCore, createInfoListToCore ) where

import Foreign.Ptr
import Foreign.Storable.PeekPoke
import Foreign.Storable.HeteroList
import Data.TypeLevel.Maybe qualified as TMaybe
import Data.TypeLevel.Tuple.Uncurry
import qualified Data.HeteroParList as HeteroParList
import Data.HeteroParList (pattern (:**))

import qualified Data.ByteString as BS

import Gpu.Vulkan.Enum
import Gpu.Vulkan.Pipeline.ShaderStage.Enum

import qualified Gpu.Vulkan.ShaderModule.Middle.Internal as ShaderModule
import qualified Gpu.Vulkan.Pipeline.ShaderStage.Core as C
import qualified Gpu.Vulkan.Specialization.Middle.Internal as Specialization

data CreateInfo mn sknd sivs = CreateInfo {
	forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> M mn
createInfoNext :: TMaybe.M mn,
	forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> CreateFlags
createInfoFlags :: CreateFlags,
	forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> ShaderStageFlagBits
createInfoStage :: ShaderStageFlagBits,
	forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> S sknd
createInfoModule :: ShaderModule.S sknd,
	forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> ByteString
createInfoName :: BS.ByteString,
	forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> Maybe (L sivs)
createInfoSpecializationInfo :: Maybe (HeteroParList.L sivs) }

deriving instance (Show (TMaybe.M mn), Show (HeteroParList.L sivs)) =>
	Show (CreateInfo mn sknd sivs)

createInfoToCore ::
	forall mn sknd sivs r . (WithPoked (TMaybe.M mn), PokableList sivs) =>
	CreateInfo mn sknd sivs -> (C.CreateInfo -> IO r) -> IO ()
createInfoToCore :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]) r.
(WithPoked (M mn), PokableList sivs) =>
CreateInfo mn sknd sivs -> (CreateInfo -> IO r) -> IO ()
createInfoToCore CreateInfo {
	createInfoNext :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> M mn
createInfoNext = M mn
mnxt,
	createInfoFlags :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> CreateFlags
createInfoFlags = CreateFlagBits Word32
flgs,
	createInfoStage :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> ShaderStageFlagBits
createInfoStage = ShaderStageFlagBits Word32
stg,
	createInfoModule :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> S sknd
createInfoModule = ShaderModule.S S
mdl,
	createInfoName :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> ByteString
createInfoName = ByteString
nm,
	createInfoSpecializationInfo :: forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]).
CreateInfo mn sknd sivs -> Maybe (L sivs)
createInfoSpecializationInfo = Maybe (L sivs)
mxs } CreateInfo -> IO r
f =
	M mn -> (forall s. PtrS s (M mn) -> IO ()) -> IO ()
forall a b.
WithPoked a =>
a -> (forall s. PtrS s a -> IO b) -> IO b
forall b. M mn -> (forall s. PtrS s (M mn) -> IO b) -> IO b
withPoked' M mn
mnxt \PtrS s (M mn)
pnxt -> PtrS s (M mn) -> (Ptr (M mn) -> IO r) -> IO ()
forall s a b. PtrS s a -> (Ptr a -> IO b) -> IO ()
withPtrS PtrS s (M mn)
pnxt \(Ptr (M mn) -> Ptr ()
forall a b. Ptr a -> Ptr b
castPtr -> Ptr ()
pnxt') ->
	ByteString -> (CString -> IO r) -> IO r
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
nm \CString
cnm ->
	let	 ci :: PtrInfo -> CreateInfo
ci PtrInfo
pcsi = C.CreateInfo {
			createInfoSType :: ()
C.createInfoSType = (),
			createInfoPNext :: Ptr ()
C.createInfoPNext = Ptr ()
pnxt',
			createInfoFlags :: Word32
C.createInfoFlags = Word32
flgs,
			createInfoStage :: Word32
C.createInfoStage = Word32
stg,
			createInfoModule :: S
C.createInfoModule = S
mdl,
			createInfoPName :: CString
C.createInfoPName = CString
cnm,
			createInfoPSpecializationInfo :: PtrInfo
C.createInfoPSpecializationInfo = PtrInfo
pcsi } in
	case Maybe (L sivs)
mxs of
		Maybe (L sivs)
Nothing -> CreateInfo -> IO r
f (CreateInfo -> IO r) -> CreateInfo -> IO r
forall a b. (a -> b) -> a -> b
$ PtrInfo -> CreateInfo
ci PtrInfo
forall a. Ptr a
NullPtr
		Just L sivs
xs -> L sivs -> (Info -> IO r) -> IO r
forall (vs :: [*]) a.
PokableList vs =>
L vs -> (Info -> IO a) -> IO a
Specialization.infoToCore L sivs
xs \Info
csi ->
			Info -> (PtrInfo -> IO r) -> IO r
forall a b. Pokable a => a -> (Ptr a -> IO b) -> IO b
withPoked Info
csi ((PtrInfo -> IO r) -> IO r) -> (PtrInfo -> IO r) -> IO r
forall a b. (a -> b) -> a -> b
$ CreateInfo -> IO r
f (CreateInfo -> IO r) -> (PtrInfo -> CreateInfo) -> PtrInfo -> IO r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PtrInfo -> CreateInfo
ci

class CreateInfoListToCore cias where
	createInfoListToCore ::
		HeteroParList.PL (U3 CreateInfo) cias ->
			([C.CreateInfo] -> IO r) -> IO ()

instance CreateInfoListToCore '[] where
	createInfoListToCore :: forall r. PL (U3 CreateInfo) '[] -> ([CreateInfo] -> IO r) -> IO ()
createInfoListToCore PL (U3 CreateInfo) '[]
HeteroParList.Nil = (() () -> IO r -> IO ()
forall a b. a -> IO b -> IO a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (IO r -> IO ())
-> (([CreateInfo] -> IO r) -> IO r)
-> ([CreateInfo] -> IO r)
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([CreateInfo] -> IO r) -> [CreateInfo] -> IO r
forall a b. (a -> b) -> a -> b
$ [])

instance (WithPoked (TMaybe.M mn), PokableList sivs, CreateInfoListToCore cias) =>
	CreateInfoListToCore ('(mn, sknd, sivs) ': cias) where
	createInfoListToCore :: forall r.
PL (U3 CreateInfo) ('(mn, sknd, sivs) : cias)
-> ([CreateInfo] -> IO r) -> IO ()
createInfoListToCore (U3 CreateInfo s1 s2 s3
ci :** PL (U3 CreateInfo) ss1
cis) [CreateInfo] -> IO r
f =
		CreateInfo s1 s2 s3 -> (CreateInfo -> IO ()) -> IO ()
forall (mn :: Maybe (*)) (sknd :: ShaderKind) (sivs :: [*]) r.
(WithPoked (M mn), PokableList sivs) =>
CreateInfo mn sknd sivs -> (CreateInfo -> IO r) -> IO ()
createInfoToCore CreateInfo s1 s2 s3
ci \CreateInfo
cci ->
		PL (U3 CreateInfo) ss1 -> ([CreateInfo] -> IO r) -> IO ()
forall (cias :: [(Maybe (*), ShaderKind, [*])]) r.
CreateInfoListToCore cias =>
PL (U3 CreateInfo) cias -> ([CreateInfo] -> IO r) -> IO ()
forall r. PL (U3 CreateInfo) ss1 -> ([CreateInfo] -> IO r) -> IO ()
createInfoListToCore PL (U3 CreateInfo) ss1
cis \[CreateInfo]
ccis -> [CreateInfo] -> IO r
f ([CreateInfo] -> IO r) -> [CreateInfo] -> IO r
forall a b. (a -> b) -> a -> b
$ CreateInfo
cci CreateInfo -> [CreateInfo] -> [CreateInfo]
forall a. a -> [a] -> [a]
: [CreateInfo]
ccis