{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}

-- |
-- Module      : WGPU.Internal.CommandEncoder
-- Description : Command encoding.
module WGPU.Internal.CommandEncoder
  ( -- * Types
    CommandEncoder (..),

    -- * Functions
    createCommandEncoder,
    commandEncoderFinish,
  )
where

import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Text (Text)
import Foreign (nullPtr)
import WGPU.Internal.CommandBuffer (CommandBuffer (CommandBuffer))
import WGPU.Internal.Device (Device, deviceInst, wgpuDevice)
import WGPU.Internal.Instance (Instance, wgpuHsInstance)
import WGPU.Internal.Memory
  ( ToRaw,
    evalContT,
    raw,
    rawPtr,
    showWithPtr,
    withCZeroingAfter,
  )
import qualified WGPU.Raw.Generated.Fun as RawFun
import WGPU.Raw.Generated.Struct.WGPUCommandBufferDescriptor (WGPUCommandBufferDescriptor)
import qualified WGPU.Raw.Generated.Struct.WGPUCommandBufferDescriptor as WGPUCommandBufferDescriptor
import qualified WGPU.Raw.Generated.Struct.WGPUCommandEncoderDescriptor as WGPUCommandEncoderDescriptor
import WGPU.Raw.Types (WGPUCommandEncoder (WGPUCommandEncoder))

-------------------------------------------------------------------------------

-- | Handle to an encoder for a series of GPU operations.
--
-- A command encoder can record render passes, compute passes, and transfer
-- operations between driver-managed resources like buffers and textures.
data CommandEncoder = CommandEncoder
  { CommandEncoder -> Instance
commandEncoderInst :: !Instance,
    CommandEncoder -> WGPUCommandEncoder
wgpuCommandEncoder :: !WGPUCommandEncoder
  }

instance Show CommandEncoder where
  show :: CommandEncoder -> String
show CommandEncoder
e =
    let CommandEncoder Instance
_ (WGPUCommandEncoder Ptr ()
ptr) = CommandEncoder
e
     in String -> Ptr () -> String
forall a. String -> Ptr a -> String
showWithPtr String
"CommandEncoder" Ptr ()
ptr

instance Eq CommandEncoder where
  == :: CommandEncoder -> CommandEncoder -> Bool
(==) CommandEncoder
e1 CommandEncoder
e2 =
    let CommandEncoder Instance
_ (WGPUCommandEncoder Ptr ()
e1_ptr) = CommandEncoder
e1
        CommandEncoder Instance
_ (WGPUCommandEncoder Ptr ()
e2_ptr) = CommandEncoder
e2
     in Ptr ()
e1_ptr Ptr () -> Ptr () -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr ()
e2_ptr

instance ToRaw CommandEncoder WGPUCommandEncoder where
  raw :: CommandEncoder -> ContT r IO WGPUCommandEncoder
raw = WGPUCommandEncoder -> ContT r IO WGPUCommandEncoder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WGPUCommandEncoder -> ContT r IO WGPUCommandEncoder)
-> (CommandEncoder -> WGPUCommandEncoder)
-> CommandEncoder
-> ContT r IO WGPUCommandEncoder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CommandEncoder -> WGPUCommandEncoder
wgpuCommandEncoder

-------------------------------------------------------------------------------

-- | Create an empty command encoder.
createCommandEncoder ::
  MonadIO m =>
  -- | Device for which to create the command encoder.
  Device ->
  -- | Debug label for the command encoder.
  Text ->
  -- | IO action that returns the command encoder.
  m CommandEncoder
createCommandEncoder :: Device -> Text -> m CommandEncoder
createCommandEncoder Device
device Text
label = IO CommandEncoder -> m CommandEncoder
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO CommandEncoder -> m CommandEncoder)
-> (ContT CommandEncoder IO CommandEncoder -> IO CommandEncoder)
-> ContT CommandEncoder IO CommandEncoder
-> m CommandEncoder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ContT CommandEncoder IO CommandEncoder -> IO CommandEncoder
forall (m :: * -> *) a. Monad m => ContT a m a -> m a
evalContT (ContT CommandEncoder IO CommandEncoder -> m CommandEncoder)
-> ContT CommandEncoder IO CommandEncoder -> m CommandEncoder
forall a b. (a -> b) -> a -> b
$ do
  let inst :: Instance
inst = Device -> Instance
deviceInst Device
device
  Ptr CChar
label_ptr <- Text -> ContT CommandEncoder IO (Ptr CChar)
forall a b r. ToRawPtr a b => a -> ContT r IO (Ptr b)
rawPtr Text
label
  Ptr WGPUCommandEncoderDescriptor
commandEncoderDescriptor_ptr <-
    WGPUCommandEncoderDescriptor
-> ContT CommandEncoder IO (Ptr WGPUCommandEncoderDescriptor)
forall a r. Storable a => a -> ContT r IO (Ptr a)
withCZeroingAfter (WGPUCommandEncoderDescriptor
 -> ContT CommandEncoder IO (Ptr WGPUCommandEncoderDescriptor))
-> WGPUCommandEncoderDescriptor
-> ContT CommandEncoder IO (Ptr WGPUCommandEncoderDescriptor)
forall a b. (a -> b) -> a -> b
$
      WGPUCommandEncoderDescriptor :: Ptr WGPUChainedStruct -> Ptr CChar -> WGPUCommandEncoderDescriptor
WGPUCommandEncoderDescriptor.WGPUCommandEncoderDescriptor
        { nextInChain :: Ptr WGPUChainedStruct
nextInChain = Ptr WGPUChainedStruct
forall a. Ptr a
nullPtr,
          label :: Ptr CChar
label = Ptr CChar
label_ptr
        }
  WGPUCommandEncoder
commandEncoderRaw <-
    WGPUHsInstance
-> WGPUDevice
-> Ptr WGPUCommandEncoderDescriptor
-> ContT CommandEncoder IO WGPUCommandEncoder
forall (m :: * -> *).
MonadIO m =>
WGPUHsInstance
-> WGPUDevice
-> Ptr WGPUCommandEncoderDescriptor
-> m WGPUCommandEncoder
RawFun.wgpuDeviceCreateCommandEncoder
      (Instance -> WGPUHsInstance
wgpuHsInstance Instance
inst)
      (Device -> WGPUDevice
wgpuDevice Device
device)
      Ptr WGPUCommandEncoderDescriptor
commandEncoderDescriptor_ptr
  CommandEncoder -> ContT CommandEncoder IO CommandEncoder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Instance -> WGPUCommandEncoder -> CommandEncoder
CommandEncoder Instance
inst WGPUCommandEncoder
commandEncoderRaw)

-- | Finish encoding commands, returning a command buffer.
commandEncoderFinish ::
  MonadIO m =>
  -- | Command encoder to finish.
  CommandEncoder ->
  -- | Debugging label for the command buffer.
  Text ->
  -- | IO action which returns the command buffer.
  m CommandBuffer
commandEncoderFinish :: CommandEncoder -> Text -> m CommandBuffer
commandEncoderFinish CommandEncoder
commandEncoder Text
label = IO CommandBuffer -> m CommandBuffer
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO CommandBuffer -> m CommandBuffer)
-> (ContT CommandBuffer IO CommandBuffer -> IO CommandBuffer)
-> ContT CommandBuffer IO CommandBuffer
-> m CommandBuffer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ContT CommandBuffer IO CommandBuffer -> IO CommandBuffer
forall (m :: * -> *) a. Monad m => ContT a m a -> m a
evalContT (ContT CommandBuffer IO CommandBuffer -> m CommandBuffer)
-> ContT CommandBuffer IO CommandBuffer -> m CommandBuffer
forall a b. (a -> b) -> a -> b
$ do
  let inst :: Instance
inst = CommandEncoder -> Instance
commandEncoderInst CommandEncoder
commandEncoder
  Ptr WGPUCommandBufferDescriptor
commandBufferDescriptor_ptr <- CommandBufferDescriptor
-> ContT CommandBuffer IO (Ptr WGPUCommandBufferDescriptor)
forall a b r. ToRawPtr a b => a -> ContT r IO (Ptr b)
rawPtr (Text -> CommandBufferDescriptor
CommandBufferDescriptor Text
label)
  WGPUCommandBuffer
commandBufferRaw <-
    WGPUHsInstance
-> WGPUCommandEncoder
-> Ptr WGPUCommandBufferDescriptor
-> ContT CommandBuffer IO WGPUCommandBuffer
forall (m :: * -> *).
MonadIO m =>
WGPUHsInstance
-> WGPUCommandEncoder
-> Ptr WGPUCommandBufferDescriptor
-> m WGPUCommandBuffer
RawFun.wgpuCommandEncoderFinish
      (Instance -> WGPUHsInstance
wgpuHsInstance Instance
inst)
      (CommandEncoder -> WGPUCommandEncoder
wgpuCommandEncoder CommandEncoder
commandEncoder)
      Ptr WGPUCommandBufferDescriptor
commandBufferDescriptor_ptr
  CommandBuffer -> ContT CommandBuffer IO CommandBuffer
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WGPUCommandBuffer -> CommandBuffer
CommandBuffer WGPUCommandBuffer
commandBufferRaw)

-------------------------------------------------------------------------------

newtype CommandBufferDescriptor = CommandBufferDescriptor
  {CommandBufferDescriptor -> Text
commandBufferLabel :: Text}
  deriving (CommandBufferDescriptor -> CommandBufferDescriptor -> Bool
(CommandBufferDescriptor -> CommandBufferDescriptor -> Bool)
-> (CommandBufferDescriptor -> CommandBufferDescriptor -> Bool)
-> Eq CommandBufferDescriptor
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CommandBufferDescriptor -> CommandBufferDescriptor -> Bool
$c/= :: CommandBufferDescriptor -> CommandBufferDescriptor -> Bool
== :: CommandBufferDescriptor -> CommandBufferDescriptor -> Bool
$c== :: CommandBufferDescriptor -> CommandBufferDescriptor -> Bool
Eq, Int -> CommandBufferDescriptor -> ShowS
[CommandBufferDescriptor] -> ShowS
CommandBufferDescriptor -> String
(Int -> CommandBufferDescriptor -> ShowS)
-> (CommandBufferDescriptor -> String)
-> ([CommandBufferDescriptor] -> ShowS)
-> Show CommandBufferDescriptor
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CommandBufferDescriptor] -> ShowS
$cshowList :: [CommandBufferDescriptor] -> ShowS
show :: CommandBufferDescriptor -> String
$cshow :: CommandBufferDescriptor -> String
showsPrec :: Int -> CommandBufferDescriptor -> ShowS
$cshowsPrec :: Int -> CommandBufferDescriptor -> ShowS
Show)

instance ToRaw CommandBufferDescriptor WGPUCommandBufferDescriptor where
  raw :: CommandBufferDescriptor -> ContT r IO WGPUCommandBufferDescriptor
raw CommandBufferDescriptor {Text
commandBufferLabel :: Text
commandBufferLabel :: CommandBufferDescriptor -> Text
..} = do
    Ptr CChar
label_ptr <- Text -> ContT r IO (Ptr CChar)
forall a b r. ToRawPtr a b => a -> ContT r IO (Ptr b)
rawPtr Text
commandBufferLabel
    WGPUCommandBufferDescriptor
-> ContT r IO WGPUCommandBufferDescriptor
forall (f :: * -> *) a. Applicative f => a -> f a
pure
      WGPUCommandBufferDescriptor :: Ptr WGPUChainedStruct -> Ptr CChar -> WGPUCommandBufferDescriptor
WGPUCommandBufferDescriptor.WGPUCommandBufferDescriptor
        { nextInChain :: Ptr WGPUChainedStruct
nextInChain = Ptr WGPUChainedStruct
forall a. Ptr a
nullPtr,
          label :: Ptr CChar
label = Ptr CChar
label_ptr
        }