packages feed

gpu-vulkan-0.1.0.137: src/Gpu/Vulkan/Pipeline/Compute.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE TypeApplications, RankNTypes #-}
{-# LANGUAGE MonoLocalBinds, GADTs, TypeFamilies #-}
{-# LANGUAGE DataKinds, PolyKinds #-}
{-# LANGUAGE KindSignatures, TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Pipeline.Compute (

	-- * CREATE

	createCs, C(..), CreateInfo(..),
	CreateInfoListToMiddle, FromMiddleList

	) where

import Foreign.Storable.PeekPoke
import Foreign.Storable.HeteroList
import Control.Exception
import Data.TypeLevel.Maybe qualified as TMaybe
import Data.TypeLevel.ParMaybe qualified as TPMaybe
import Data.TypeLevel.Tuple.Uncurry
import Data.TypeLevel.Tuple.MapIndex qualified as TMapIndex
import qualified Data.HeteroParList as HeteroParList
import Data.HeteroParList (pattern (:**))
import Data.Kind
import Data.Int

import Language.SpirV.ShaderKind

import Gpu.Vulkan.Pipeline.Enum

import qualified Gpu.Vulkan.AllocationCallbacks as AllocationCallbacks
import qualified Gpu.Vulkan.AllocationCallbacks.Type as AllocationCallbacks
import qualified Gpu.Vulkan.Device.Type as Device
import qualified Gpu.Vulkan.Pipeline.ShaderStage.Internal as ShaderStage
import qualified Gpu.Vulkan.DescriptorSetLayout.Type as DescriptorSetLayout
import qualified Gpu.Vulkan.PipelineLayout.Type as Layout
import qualified Gpu.Vulkan.PipelineCache.Type as Cache
import qualified Gpu.Vulkan.Pipeline.Compute.Middle as M


newtype C s (lyta ::
	(Type, [(Type, [DescriptorSetLayout.BindingType])], [Type])) = C M.C
	deriving Show

data CreateInfo mn ssta lyta bpha = CreateInfo {
	createInfoNext :: TMaybe.M mn,
	createInfoFlags :: CreateFlags,
	createInfoStage :: U5 ShaderStage.CreateInfo ssta,
	createInfoLayout :: U3 Layout.P lyta,
	createInfoBasePipelineHandleOrIndex ::
		Maybe (Either (U2 C bpha) Int32) }

createInfoToMiddle ::
	(WithPoked (TMaybe.M n'), AllocationCallbacks.ToMiddle mscc) =>
	Device.D ds ->
	CreateInfo n '(n1, n', 'GlslComputeShader, mscc, vs) lyta bpha ->
	IO (M.CreateInfo n n1 vs)
createInfoToMiddle dvc CreateInfo {
	createInfoNext = mnxt,
	createInfoFlags = flgs,
	createInfoStage = U5 stg,
	createInfoLayout = U3 (Layout.P lyt),
	createInfoBasePipelineHandleOrIndex = mbphi } = do
	stg' <- ShaderStage.createInfoToMiddle dvc stg
	let	(bph, bpi) = case mbphi of
			Nothing -> (Nothing, Nothing)
			Just (Left (U2 (C h))) -> (Just h, Nothing)
			Just (Right i) -> (Nothing, Just i)
	pure M.CreateInfo {
		M.createInfoNext = mnxt,
		M.createInfoFlags = flgs,
		M.createInfoStage = stg',
		M.createInfoLayout = lyt,
		M.createInfoBasePipelineHandle = bph,
		M.createInfoBasePipelineIndex = bpi }

class (	M.CreateInfoListToCore (MiddleArgs as),
	DestroyCreateInfoMiddleList (MiddleArgs as) as ) =>
	CreateInfoListToMiddle as where
	type MiddleArgs as :: [(Maybe Type, Maybe Type, [Type])]
	createInfoListToMiddle ::
		Device.D sd -> HeteroParList.PL (U4 CreateInfo) as ->
		IO (HeteroParList.PL (U3 M.CreateInfo) (MiddleArgs as))

instance CreateInfoListToMiddle '[] where
	type MiddleArgs '[] = '[]
	createInfoListToMiddle _ HeteroParList.Nil = pure HeteroParList.Nil

instance (
	WithPoked (TMaybe.M n'), CreateInfoListToMiddle as,
	AllocationCallbacks.ToMiddle mscc,

	WithPoked (TMaybe.M n), WithPoked (TMaybe.M n1), PokableList vs
	) =>
	CreateInfoListToMiddle (
		'(n, '(n1, n', 'GlslComputeShader, mscc, vs), lyta, bpha
		) ': as) where
	type MiddleArgs (
		'(n, '(n1, n', 'GlslComputeShader, mscc, vs), lyta, bpha) ':
		as ) = '(n, n1, vs) ': MiddleArgs as
	createInfoListToMiddle dvc (U4 ci :** cis) = (:**)
		<$> (U3 <$> createInfoToMiddle dvc ci)
		<*> createInfoListToMiddle dvc cis

destroyCreateInfoMiddle ::
	AllocationCallbacks.ToMiddle mscc =>
	Device.D sd -> M.CreateInfo n n1 vs ->
	CreateInfo n '(n1, n2, 'GlslComputeShader, mscc, vs) lyta bpha -> IO ()
destroyCreateInfoMiddle dvc mci ci = ShaderStage.destroyShaderModule dvc
	(M.createInfoStage mci) ((\(U5 s) -> snd $ ShaderStage.createInfoModule s) $ createInfoStage ci)

class DestroyCreateInfoMiddleList vss vss' where
	destroyCreateInfoMiddleList ::
		Device.D sd ->
		HeteroParList.PL (U3 M.CreateInfo) vss ->
		HeteroParList.PL (U4 CreateInfo) vss' -> IO ()

instance DestroyCreateInfoMiddleList '[] '[] where
	destroyCreateInfoMiddleList _ HeteroParList.Nil HeteroParList.Nil = pure ()

instance (
	DestroyCreateInfoMiddleList vss vss',
	AllocationCallbacks.ToMiddle mscc ) =>
	DestroyCreateInfoMiddleList
		('(n, n1, vs) ': vss)
		('(n, '(n1, n2, 'GlslComputeShader, mscc, vs), lyta, bpha) ': vss') where
	destroyCreateInfoMiddleList dvc
		(U3 mci :** mcis) (U4 ci :** cis) = do
		destroyCreateInfoMiddle dvc mci ci
		destroyCreateInfoMiddleList dvc mcis cis

createCs :: (
	CreateInfoListToMiddle cias, AllocationCallbacks.ToMiddle mac,
	FromMiddleList (TMapIndex.M2_4 cias) ) =>
	Device.D sd -> Maybe (Cache.P spc) -> HeteroParList.PL (U4 CreateInfo) cias ->
	TPMaybe.M (U2 AllocationCallbacks.A) mac ->
	(forall s . HeteroParList.PL (C s) (TMapIndex.M2_4 cias) -> IO a) -> IO a
createCs dvc@(Device.D mdvc) mcch cis
	(AllocationCallbacks.toMiddle -> mac) f = do
	cis' <- createInfoListToMiddle dvc cis
	let	mcch' = (\(Cache.P c) -> c) <$> mcch
	bracket
		(M.createCs mdvc mcch' cis' mac
			<* destroyCreateInfoMiddleList dvc cis' cis)
		(mapM_ \c -> M.destroy mdvc c mac)
		(f . fromMiddleList)

class FromMiddleList ss where
	fromMiddleList :: [M.C] -> HeteroParList.PL (C sc) ss

instance FromMiddleList '[] where fromMiddleList [] = HeteroParList.Nil

instance FromMiddleList ss => FromMiddleList (s ': ss) where
	fromMiddleList (c : cs) = C c :** fromMiddleList cs