{-# language CPP #-}
module Graphics.Vulkan.Core10.Shader ( createShaderModule
, withShaderModule
, destroyShaderModule
, ShaderModuleCreateInfo(..)
) where
import Control.Exception.Base (bracket)
import Control.Monad (unless)
import Control.Monad.IO.Class (liftIO)
import Data.Bits ((.&.))
import Data.Typeable (eqT)
import Foreign.Marshal.Alloc (allocaBytesAligned)
import Foreign.Marshal.Alloc (callocBytes)
import Foreign.Marshal.Alloc (free)
import Foreign.Marshal.Utils (copyBytes)
import Foreign.Ptr (ptrToWordPtr)
import GHC.Base (when)
import GHC.IO (throwIO)
import GHC.Ptr (castPtr)
import Foreign.Ptr (nullPtr)
import Foreign.Ptr (plusPtr)
import qualified Data.ByteString (length)
import Data.ByteString (packCStringLen)
import Data.ByteString.Unsafe (unsafeUseAsCString)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Cont (evalContT)
import Control.Monad.IO.Class (MonadIO)
import Data.Type.Equality ((:~:)(Refl))
import Data.Typeable (Typeable)
import Foreign.C.Types (CChar)
import Foreign.C.Types (CSize)
import Foreign.C.Types (CSize(CSize))
import Foreign.Storable (Storable(peek))
import Foreign.Storable (Storable(poke))
import GHC.IO.Exception (IOErrorType(..))
import GHC.IO.Exception (IOException(..))
import Foreign.Ptr (FunPtr)
import Foreign.Ptr (Ptr)
import Data.Word (Word32)
import Data.ByteString (ByteString)
import Data.Kind (Type)
import Control.Monad.Trans.Cont (ContT(..))
import Graphics.Vulkan.NamedType ((:::))
import Graphics.Vulkan.Core10.AllocationCallbacks (AllocationCallbacks)
import Graphics.Vulkan.CStruct.Extends (Chain)
import Graphics.Vulkan.Core10.Handles (Device)
import Graphics.Vulkan.Core10.Handles (Device(..))
import Graphics.Vulkan.Dynamic (DeviceCmds(pVkCreateShaderModule))
import Graphics.Vulkan.Dynamic (DeviceCmds(pVkDestroyShaderModule))
import Graphics.Vulkan.Core10.Handles (Device_T)
import Graphics.Vulkan.CStruct.Extends (Extends)
import Graphics.Vulkan.CStruct.Extends (Extensible(..))
import Graphics.Vulkan.CStruct (FromCStruct)
import Graphics.Vulkan.CStruct (FromCStruct(..))
import Graphics.Vulkan.CStruct.Extends (PeekChain)
import Graphics.Vulkan.CStruct.Extends (PeekChain(..))
import Graphics.Vulkan.CStruct.Extends (PokeChain)
import Graphics.Vulkan.CStruct.Extends (PokeChain(..))
import Graphics.Vulkan.Core10.Enums.Result (Result)
import Graphics.Vulkan.Core10.Enums.Result (Result(..))
import Graphics.Vulkan.Core10.Handles (ShaderModule)
import Graphics.Vulkan.Core10.Handles (ShaderModule(..))
import Graphics.Vulkan.Core10.Enums.ShaderModuleCreateFlagBits (ShaderModuleCreateFlags)
import {-# SOURCE #-} Graphics.Vulkan.Extensions.VK_EXT_validation_cache (ShaderModuleValidationCacheCreateInfoEXT)
import Graphics.Vulkan.Core10.Enums.StructureType (StructureType)
import Graphics.Vulkan.CStruct (ToCStruct)
import Graphics.Vulkan.CStruct (ToCStruct(..))
import Graphics.Vulkan.Exception (VulkanException(..))
import Graphics.Vulkan.Zero (Zero(..))
import Graphics.Vulkan.Core10.Enums.StructureType (StructureType(STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO))
import Graphics.Vulkan.Core10.Enums.Result (Result(SUCCESS))
foreign import ccall
#if !defined(SAFE_FOREIGN_CALLS)
unsafe
#endif
"dynamic" mkVkCreateShaderModule
:: FunPtr (Ptr Device_T -> Ptr (ShaderModuleCreateInfo a) -> Ptr AllocationCallbacks -> Ptr ShaderModule -> IO Result) -> Ptr Device_T -> Ptr (ShaderModuleCreateInfo a) -> Ptr AllocationCallbacks -> Ptr ShaderModule -> IO Result
createShaderModule :: forall a io . (PokeChain a, MonadIO io) => Device -> ShaderModuleCreateInfo a -> ("allocator" ::: Maybe AllocationCallbacks) -> io (ShaderModule)
createShaderModule device createInfo allocator = liftIO . evalContT $ do
let vkCreateShaderModule' = mkVkCreateShaderModule (pVkCreateShaderModule (deviceCmds (device :: Device)))
pCreateInfo <- ContT $ withCStruct (createInfo)
pAllocator <- case (allocator) of
Nothing -> pure nullPtr
Just j -> ContT $ withCStruct (j)
pPShaderModule <- ContT $ bracket (callocBytes @ShaderModule 8) free
r <- lift $ vkCreateShaderModule' (deviceHandle (device)) pCreateInfo pAllocator (pPShaderModule)
lift $ when (r < SUCCESS) (throwIO (VulkanException r))
pShaderModule <- lift $ peek @ShaderModule pPShaderModule
pure $ (pShaderModule)
withShaderModule :: forall a io r . (PokeChain a, MonadIO io) => (io (ShaderModule) -> ((ShaderModule) -> io ()) -> r) -> Device -> ShaderModuleCreateInfo a -> Maybe AllocationCallbacks -> r
withShaderModule b device pCreateInfo pAllocator =
b (createShaderModule device pCreateInfo pAllocator)
(\(o0) -> destroyShaderModule device o0 pAllocator)
foreign import ccall
#if !defined(SAFE_FOREIGN_CALLS)
unsafe
#endif
"dynamic" mkVkDestroyShaderModule
:: FunPtr (Ptr Device_T -> ShaderModule -> Ptr AllocationCallbacks -> IO ()) -> Ptr Device_T -> ShaderModule -> Ptr AllocationCallbacks -> IO ()
destroyShaderModule :: forall io . MonadIO io => Device -> ShaderModule -> ("allocator" ::: Maybe AllocationCallbacks) -> io ()
destroyShaderModule device shaderModule allocator = liftIO . evalContT $ do
let vkDestroyShaderModule' = mkVkDestroyShaderModule (pVkDestroyShaderModule (deviceCmds (device :: Device)))
pAllocator <- case (allocator) of
Nothing -> pure nullPtr
Just j -> ContT $ withCStruct (j)
lift $ vkDestroyShaderModule' (deviceHandle (device)) (shaderModule) pAllocator
pure $ ()
data ShaderModuleCreateInfo (es :: [Type]) = ShaderModuleCreateInfo
{
next :: Chain es
,
flags :: ShaderModuleCreateFlags
,
code :: ByteString
}
deriving (Typeable)
deriving instance Show (Chain es) => Show (ShaderModuleCreateInfo es)
instance Extensible ShaderModuleCreateInfo where
extensibleType = STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
setNext x next = x{next = next}
getNext ShaderModuleCreateInfo{..} = next
extends :: forall e b proxy. Typeable e => proxy e -> (Extends ShaderModuleCreateInfo e => b) -> Maybe b
extends _ f
| Just Refl <- eqT @e @ShaderModuleValidationCacheCreateInfoEXT = Just f
| otherwise = Nothing
instance PokeChain es => ToCStruct (ShaderModuleCreateInfo es) where
withCStruct x f = allocaBytesAligned 40 8 $ \p -> pokeCStruct p x (f p)
pokeCStruct p ShaderModuleCreateInfo{..} f = evalContT $ do
lift $ poke ((p `plusPtr` 0 :: Ptr StructureType)) (STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO)
pNext'' <- fmap castPtr . ContT $ withChain (next)
lift $ poke ((p `plusPtr` 8 :: Ptr (Ptr ()))) pNext''
lift $ poke ((p `plusPtr` 16 :: Ptr ShaderModuleCreateFlags)) (flags)
lift $ poke ((p `plusPtr` 24 :: Ptr CSize)) (fromIntegral $ Data.ByteString.length (code))
lift $ unless (Data.ByteString.length (code) .&. 3 == 0) $
throwIO $ IOError Nothing InvalidArgument "" "code size must be a multiple of 4" Nothing Nothing
unalignedCode <- ContT $ unsafeUseAsCString (code)
pCode'' <- if ptrToWordPtr unalignedCode .&. 3 == 0
then pure $ castPtr @CChar @Word32 unalignedCode
else do
let len = Data.ByteString.length (code)
mem <- ContT $ allocaBytesAligned @Word32 len 4
lift $ copyBytes mem (castPtr @CChar @Word32 unalignedCode) len
pure mem
lift $ poke ((p `plusPtr` 32 :: Ptr (Ptr Word32))) pCode''
lift $ f
cStructSize = 40
cStructAlignment = 8
pokeZeroCStruct p f = evalContT $ do
lift $ poke ((p `plusPtr` 0 :: Ptr StructureType)) (STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO)
pNext' <- fmap castPtr . ContT $ withZeroChain @es
lift $ poke ((p `plusPtr` 8 :: Ptr (Ptr ()))) pNext'
lift $ f
instance PeekChain es => FromCStruct (ShaderModuleCreateInfo es) where
peekCStruct p = do
pNext <- peek @(Ptr ()) ((p `plusPtr` 8 :: Ptr (Ptr ())))
next <- peekChain (castPtr pNext)
flags <- peek @ShaderModuleCreateFlags ((p `plusPtr` 16 :: Ptr ShaderModuleCreateFlags))
codeSize <- peek @CSize ((p `plusPtr` 24 :: Ptr CSize))
pCode <- peek @(Ptr Word32) ((p `plusPtr` 32 :: Ptr (Ptr Word32)))
code <- packCStringLen (castPtr @Word32 @CChar pCode, fromIntegral $ ((\(CSize a) -> a) codeSize) * 4)
pure $ ShaderModuleCreateInfo
next flags code
instance es ~ '[] => Zero (ShaderModuleCreateInfo es) where
zero = ShaderModuleCreateInfo
()
zero
mempty