packages feed

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

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

module Gpu.Vulkan.Instance.Middle.Internal (

	-- * CREATE AND DESTROY

	create, destroy, I(..), CreateInfo(..),

	-- * ENUMERATE

	enumerateLayerProperties, enumerateExtensionProperties

	) where

import Foreign.Ptr
import Foreign.Marshal
import Foreign.Storable
import Foreign.Storable.PeekPoke (
	WithPoked, withPoked, withPoked', withPtrS, pattern NullPtr )
import Control.Arrow
import Data.TypeLevel.Maybe qualified as TMaybe
import Data.TypeLevel.ParMaybe qualified as TPMaybe
import Data.Default

import Data.Text qualified as T
import Data.Text.Foreign.MiscYj

import Gpu.Vulkan.Middle.Internal
import Gpu.Vulkan.Exception.Middle.Internal
import Gpu.Vulkan.Exception.Enum
import Gpu.Vulkan.Instance.Enum

import qualified Gpu.Vulkan.Instance.Core as C
import Gpu.Vulkan.AllocationCallbacks.Middle.Internal
	qualified as AllocationCallbacks

data CreateInfo mn a = CreateInfo {
	createInfoNext :: TMaybe.M mn,
	createInfoFlags :: CreateFlags,
	createInfoApplicationInfo :: Maybe (ApplicationInfo a),
	createInfoEnabledLayerNames :: [T.Text],
	createInfoEnabledExtensionNames :: [T.Text] }

deriving instance (Show (TMaybe.M mn), Show (TMaybe.M a)) => Show (CreateInfo mn a)

instance Default (CreateInfo 'Nothing a) where
	def = CreateInfo {
		createInfoNext = TMaybe.N,
		createInfoFlags = CreateFlagsZero,
		createInfoApplicationInfo = Nothing,
		createInfoEnabledLayerNames = [],
		createInfoEnabledExtensionNames = [] }

createInfoToCore :: (WithPoked (TMaybe.M mn), WithPoked (TMaybe.M n')) =>
	CreateInfo mn n' -> (Ptr C.CreateInfo -> IO a) -> IO ()
createInfoToCore CreateInfo {
	createInfoNext = mnxt,
	createInfoFlags = (\(CreateFlags f) -> f) -> flgs,
	createInfoApplicationInfo = mai,
	createInfoEnabledLayerNames =
		(fromIntegral . length &&& id) -> (elnc, elns),
	createInfoEnabledExtensionNames =
		(fromIntegral . length &&& id) -> (eenc, eens) } f =
	withPoked' mnxt \pnxt -> withPtrS pnxt \(castPtr -> pnxt') ->
	textListToCStringArray elns \pelna ->
	textListToCStringArray eens \peena ->
	let	ci pai = C.CreateInfo {
			C.createInfoSType = (),
			C.createInfoPNext = pnxt',
			C.createInfoFlags = flgs,
			C.createInfoPApplicationInfo = pai,
			C.createInfoEnabledLayerCount = elnc,
			C.createInfoPpEnabledLayerNames = pelna,
			C.createInfoEnabledExtensionCount = eenc,
			C.createInfoPpEnabledExtensionNames = peena } in
	case mai of
		Nothing -> () <$ withPoked (ci NullPtr) f
		Just ai -> applicationInfoToCore ai \pai ->
			withPoked (ci pai) f

newtype I = I C.I deriving Show

create :: (WithPoked (TMaybe.M mn), WithPoked (TMaybe.M a)) =>
	CreateInfo mn a -> TPMaybe.M AllocationCallbacks.A mc -> IO I
create ci mac = I <$> alloca \pist -> do
	createInfoToCore ci \pcci ->
		AllocationCallbacks.mToCore mac \pac -> do
			r <- C.create pcci pac pist
			throwUnlessSuccess $ Result r
	peek pist

destroy :: I -> TPMaybe.M AllocationCallbacks.A md -> IO ()
destroy (I cist) mac = AllocationCallbacks.mToCore mac $ C.destroy cist

enumerateLayerProperties :: IO [LayerProperties]
enumerateLayerProperties =
	map layerPropertiesFromCore <$> alloca \pLayerCount ->
	C.enumerateLayerProperties pLayerCount NullPtr >>= \r ->
	throwUnlessSuccess (Result r) >>
	peek pLayerCount >>= \(fromIntegral -> layerCount) ->
	allocaArray layerCount \pLayerProps ->
	C.enumerateLayerProperties pLayerCount pLayerProps >>= \r' ->
	throwUnlessSuccess (Result r') >>
	peekArray layerCount pLayerProps

enumerateExtensionProperties :: Maybe T.Text -> IO [ExtensionProperties]
enumerateExtensionProperties mln =
	map extensionPropertiesFromCore <$> case mln of
		Nothing -> go NullPtr
		Just ln -> textToCString ln go
	where go cln = alloca \pExtCount ->
		C.enumerateExtensionProperties cln pExtCount NullPtr >>= \r ->
		throwUnlessSuccess (Result r) >>
		peek pExtCount >>= \(fromIntegral -> extCount) ->
		allocaArray extCount \pExts ->
		C.enumerateExtensionProperties cln pExtCount pExts >>= \r' ->
		throwUnlessSuccess (Result r') >>
		peekArray extCount pExts