module Engine.Stage.Component where

import RIO

import Control.Monad.Trans.Resource (ResourceT)
import Data.Semigroup (Semigroup(..))
import UnliftIO.Resource (ReleaseKey, allocate)
import Vulkan.Core10 qualified as Vk
import Vulkan.NamedType ((:::))

import Engine.Types (Stage(..), StageFrameRIO, StageRIO)
import Engine.Vulkan.Swapchain (SwapchainResources(..))
import Engine.Vulkan.Types qualified as Vulkan
import Resource.Region qualified as Region

assemble
  :: Foldable t
  => Text
  -> Rendering rp p st
  -> Resources rp p st rr
  -> t (Scene rp p st rr)
  -> Stage rp p rr st
assemble :: forall (t :: * -> *) rp p st rr.
Foldable t =>
Text
-> Rendering rp p st
-> Resources rp p st rr
-> t (Scene rp p st rr)
-> Stage rp p rr st
assemble Text
title Rendering{SwapchainResources -> ResourceT (RIO (App GlobalHandles st)) rp
SwapchainResources
-> rp -> ResourceT (RIO (App GlobalHandles st)) p
rAllocateRP :: SwapchainResources -> ResourceT (RIO (App GlobalHandles st)) rp
rAllocateP :: SwapchainResources
-> rp -> ResourceT (RIO (App GlobalHandles st)) p
$sel:rAllocateRP:Rendering :: forall rp p st.
Rendering rp p st
-> SwapchainResources -> ResourceT (StageRIO st) rp
$sel:rAllocateP:Rendering :: forall rp p st.
Rendering rp p st
-> SwapchainResources -> rp -> ResourceT (StageRIO st) p
..} Resources{StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
Queues CommandPool
-> rp -> p -> ResourceT (RIO (App GlobalHandles st)) rr
rInitialRS :: StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
rInitialRR :: Queues CommandPool
-> rp -> p -> ResourceT (RIO (App GlobalHandles st)) rr
$sel:rInitialRS:Resources :: forall rp p st rr.
Resources rp p st rr
-> StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
$sel:rInitialRR:Resources :: forall rp p st rr.
Resources rp p st rr
-> Queues CommandPool -> rp -> p -> ResourceT (StageRIO st) rr
..} (t (Scene rp p st rr) -> Scene rp p st rr
forall m. Monoid m => t m -> m
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold -> Scene{ResourceT (RIO (App GlobalHandles st)) ()
st -> rr -> StageFrameRIO rp p rr st ()
CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scBeforeLoop :: ResourceT (RIO (App GlobalHandles st)) ()
scUpdateBuffers :: st -> rr -> StageFrameRIO rp p rr st ()
scRecordCommands :: CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
$sel:scBeforeLoop:Scene :: forall rp p st rr. Scene rp p st rr -> ResourceT (StageRIO st) ()
$sel:scUpdateBuffers:Scene :: forall rp p st rr.
Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
$sel:scRecordCommands:Scene :: forall rp p st rr.
Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
..}) = Stage
  { $sel:sTitle:Stage :: Text
sTitle = Text
title

  , $sel:sAllocateRP:Stage :: SwapchainResources -> ResourceT (RIO (App GlobalHandles st)) rp
sAllocateRP = SwapchainResources -> ResourceT (RIO (App GlobalHandles st)) rp
rAllocateRP
  , $sel:sAllocateP:Stage :: SwapchainResources
-> rp -> ResourceT (RIO (App GlobalHandles st)) p
sAllocateP  = SwapchainResources
-> rp -> ResourceT (RIO (App GlobalHandles st)) p
rAllocateP

  , $sel:sInitialRS:Stage :: StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
sInitialRS  = StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
rInitialRS
  , $sel:sInitialRR:Stage :: Queues CommandPool
-> rp -> p -> ResourceT (RIO (App GlobalHandles st)) rr
sInitialRR  = Queues CommandPool
-> rp -> p -> ResourceT (RIO (App GlobalHandles st)) rr
rInitialRR

  , $sel:sBeforeLoop:Stage :: StageRIO st ReleaseKey
sBeforeLoop       = ResourceT (RIO (App GlobalHandles st)) () -> StageRIO st ReleaseKey
forall (m :: * -> *) a.
MonadResource m =>
ResourceT m a -> m ReleaseKey
Region.exec ResourceT (RIO (App GlobalHandles st)) ()
scBeforeLoop
  , $sel:sUpdateBuffers:Stage :: st -> rr -> StageFrameRIO rp p rr st ()
sUpdateBuffers    = st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers
  , $sel:sRecordCommands:Stage :: CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
sRecordCommands   = CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scRecordCommands
  , $sel:sAfterLoop:Stage :: ReleaseKey -> StageRIO st ()
sAfterLoop        = ReleaseKey -> StageRIO st ()
forall (m :: * -> *). MonadIO m => ReleaseKey -> m ()
Region.release
  }

data Rendering rp p st = Rendering
  { forall rp p st.
Rendering rp p st
-> SwapchainResources -> ResourceT (StageRIO st) rp
rAllocateRP :: SwapchainResources -> ResourceT (StageRIO st) rp
  , forall rp p st.
Rendering rp p st
-> SwapchainResources -> rp -> ResourceT (StageRIO st) p
rAllocateP  :: SwapchainResources -> rp -> ResourceT (StageRIO st) p
  }

data  NoRenderPass = NoRenderPass

instance Vulkan.RenderPass NoRenderPass where
  updateRenderpass :: forall env swapchain.
(HasLogFunc env, HasSwapchain swapchain, HasVulkan env,
 MonadResource (RIO env)) =>
swapchain -> NoRenderPass -> RIO env NoRenderPass
updateRenderpass swapchain
_context = NoRenderPass -> RIO env NoRenderPass
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  refcountRenderpass :: forall env. MonadResource (RIO env) => NoRenderPass -> RIO env ()
refcountRenderpass NoRenderPass
_rp = () -> RIO env ()
forall a. a -> RIO env a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

data NoPipelines = NoPipelines
type  NoRendering = Rendering NoRenderPass NoPipelines

noRendering :: NoRendering st
noRendering :: forall st. NoRendering st
noRendering = Rendering
  { $sel:rAllocateRP:Rendering :: SwapchainResources -> ResourceT (StageRIO st) NoRenderPass
rAllocateRP = \SwapchainResources
_swapchain ->
      NoRenderPass -> ResourceT (StageRIO st) NoRenderPass
forall a. a -> ResourceT (StageRIO st) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure NoRenderPass
NoRenderPass
  , $sel:rAllocateP:Rendering :: SwapchainResources
-> NoRenderPass -> ResourceT (StageRIO st) NoPipelines
rAllocateP = \SwapchainResources
_swapchain NoRenderPass
NoRenderPass ->
      NoPipelines -> ResourceT (StageRIO st) NoPipelines
forall a. a -> ResourceT (StageRIO st) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure NoPipelines
NoPipelines
  }

data Resources rp p st rr = Resources
  { forall rp p st rr.
Resources rp p st rr
-> StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
rInitialRS :: StageRIO (Maybe SwapchainResources) (ReleaseKey, st)
  , forall rp p st rr.
Resources rp p st rr
-> Queues CommandPool -> rp -> p -> ResourceT (StageRIO st) rr
rInitialRR :: Vulkan.Queues Vk.CommandPool -> rp -> p -> ResourceT (StageRIO st) rr
  }

type NoResources rp p = Resources rp p NoRunState NoFrameResources

data NoRunState = NoRunState
data NoFrameResources = NoFrameResources

noResources :: NoResources rp p
noResources :: forall rp p. NoResources rp p
noResources = Resources
  { $sel:rInitialRS:Resources :: StageRIO (Maybe SwapchainResources) (ReleaseKey, NoRunState)
rInitialRS =
      IO NoRunState
-> (NoRunState -> IO ())
-> StageRIO (Maybe SwapchainResources) (ReleaseKey, NoRunState)
forall (m :: * -> *) a.
MonadResource m =>
IO a -> (a -> IO ()) -> m (ReleaseKey, a)
allocate
        (NoRunState -> IO NoRunState
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure NoRunState
NoRunState)
        (\NoRunState
NoRunState -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
  , $sel:rInitialRR:Resources :: Queues CommandPool
-> rp -> p -> ResourceT (StageRIO NoRunState) NoFrameResources
rInitialRR = \Queues CommandPool
_pool rp
_rp p
_p ->
      NoFrameResources
-> ResourceT (StageRIO NoRunState) NoFrameResources
forall a. a -> ResourceT (StageRIO NoRunState) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure NoFrameResources
NoFrameResources
  }

data Scene rp p st rr = Scene
  { forall rp p st rr. Scene rp p st rr -> ResourceT (StageRIO st) ()
scBeforeLoop       :: ResourceT (StageRIO st) ()
  , forall rp p st rr.
Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers    :: st -> rr -> StageFrameRIO rp p rr st ()
  , forall rp p st rr.
Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
scRecordCommands   :: Vk.CommandBuffer -> rr -> "image index" ::: Word32 -> StageFrameRIO rp p rr st ()
  }

instance Semigroup (Scene rp p st rr) where
  Scene rp p st rr
a <> :: Scene rp p st rr -> Scene rp p st rr -> Scene rp p st rr
<> Scene rp p st rr
b = Scene
    { $sel:scBeforeLoop:Scene :: ResourceT (StageRIO st) ()
scBeforeLoop = do
        Scene rp p st rr -> ResourceT (StageRIO st) ()
forall rp p st rr. Scene rp p st rr -> ResourceT (StageRIO st) ()
scBeforeLoop Scene rp p st rr
a
        Scene rp p st rr -> ResourceT (StageRIO st) ()
forall rp p st rr. Scene rp p st rr -> ResourceT (StageRIO st) ()
scBeforeLoop Scene rp p st rr
b
    , $sel:scUpdateBuffers:Scene :: st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers = \st
st rr
rr -> do
        Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
forall rp p st rr.
Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers Scene rp p st rr
a st
st rr
rr
        Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
forall rp p st rr.
Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers Scene rp p st rr
b st
st rr
rr
    , $sel:scRecordCommands:Scene :: CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scRecordCommands = \CommandBuffer
cb rr
rr "image index" ::: Word32
ii -> do
        Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
forall rp p st rr.
Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
scRecordCommands Scene rp p st rr
a CommandBuffer
cb rr
rr "image index" ::: Word32
ii
        Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
forall rp p st rr.
Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
scRecordCommands Scene rp p st rr
b CommandBuffer
cb rr
rr "image index" ::: Word32
ii
    }

  sconcat :: NonEmpty (Scene rp p st rr) -> Scene rp p st rr
sconcat NonEmpty (Scene rp p st rr)
scenes = Scene
    { $sel:scBeforeLoop:Scene :: ResourceT (StageRIO st) ()
scBeforeLoop = do
        (Scene rp p st rr -> ResourceT (StageRIO st) ())
-> NonEmpty (Scene rp p st rr) -> ResourceT (StageRIO st) ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ Scene rp p st rr -> ResourceT (StageRIO st) ()
forall rp p st rr. Scene rp p st rr -> ResourceT (StageRIO st) ()
scBeforeLoop NonEmpty (Scene rp p st rr)
scenes
    , $sel:scUpdateBuffers:Scene :: st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers = \st
st rr
rr ->
        NonEmpty (Scene rp p st rr)
-> (Scene rp p st rr -> StageFrameRIO rp p rr st ())
-> StageFrameRIO rp p rr st ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ NonEmpty (Scene rp p st rr)
scenes \Scene{st -> rr -> StageFrameRIO rp p rr st ()
$sel:scUpdateBuffers:Scene :: forall rp p st rr.
Scene rp p st rr -> st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers :: st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers} ->
          st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers st
st rr
rr
    , $sel:scRecordCommands:Scene :: CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scRecordCommands = \CommandBuffer
cb rr
rr "image index" ::: Word32
ii ->
        NonEmpty (Scene rp p st rr)
-> (Scene rp p st rr -> StageFrameRIO rp p rr st ())
-> StageFrameRIO rp p rr st ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ NonEmpty (Scene rp p st rr)
scenes \Scene{CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
$sel:scRecordCommands:Scene :: forall rp p st rr.
Scene rp p st rr
-> CommandBuffer
-> rr
-> ("image index" ::: Word32)
-> StageFrameRIO rp p rr st ()
scRecordCommands :: CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scRecordCommands} ->
          CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scRecordCommands CommandBuffer
cb rr
rr "image index" ::: Word32
ii
    }

instance Monoid (Scene rp p st rr) where
  mempty :: Scene rp p st rr
mempty = Scene
    { $sel:scBeforeLoop:Scene :: ResourceT (StageRIO st) ()
scBeforeLoop = () -> ResourceT (StageRIO st) ()
forall a. a -> ResourceT (StageRIO st) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    , $sel:scUpdateBuffers:Scene :: st -> rr -> StageFrameRIO rp p rr st ()
scUpdateBuffers = st -> rr -> StageFrameRIO rp p rr st ()
forall a. Monoid a => a
mempty
    , $sel:scRecordCommands:Scene :: CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
scRecordCommands = CommandBuffer
-> rr -> ("image index" ::: Word32) -> StageFrameRIO rp p rr st ()
forall a. Monoid a => a
mempty
    }