{-# LANGUAGE OverloadedLists #-}

module Render.Unlit.Line2d.Draw where

import RIO

import Vulkan.Core10 qualified as Vk
import Vulkan.NamedType ((:::))

import Engine.Vulkan.Types (Bound(..))
import Render.Unlit.Line2d.Model qualified as Model
import Resource.Buffer qualified as Buffer

batch
  :: (MonadIO m, Foldable t)
  => Vk.CommandBuffer
  -> Model.Segment
  -> Buffer.Allocated s Model.InstanceAttrs
  -> t ("firstInstance" ::: Word32, "instanceCount" ::: Word32)
  -> Bound dsl vertices instances m ()
batch :: forall (m :: * -> *) (t :: * -> *) (s :: Store) (dsl :: [*])
       vertices instances.
(MonadIO m, Foldable t) =>
CommandBuffer
-> Segment
-> Allocated s InstanceAttrs
-> t ("firstInstance" ::: Word32, "firstInstance" ::: Word32)
-> Bound dsl vertices instances m ()
batch CommandBuffer
cmd Segment
vertices Allocated s InstanceAttrs
points t ("firstInstance" ::: Word32, "firstInstance" ::: Word32)
ranges =
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (s :: Store) a. Allocated s a -> "firstInstance" ::: Word32
Buffer.aUsed Allocated s InstanceAttrs
points forall a. Ord a => a -> a -> Bool
>= "firstInstance" ::: Word32
2) do -- XXX: at least one segment to draw
    forall (io :: * -> *) (s :: Store).
MonadIO io =>
CommandBuffer -> Segment -> Buffer s -> io ()
bind CommandBuffer
cmd Segment
vertices Allocated s InstanceAttrs
points
    -- TODO: check bindings
    forall (dsl :: [*]) vertices instances (m :: * -> *) a.
m a -> Bound dsl vertices instances m a
Bound forall a b. (a -> b) -> a -> b
$
      forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (forall (io :: * -> *) (s :: Store) a.
MonadIO io =>
CommandBuffer
-> Allocated s a
-> ("firstInstance" ::: Word32, "firstInstance" ::: Word32)
-> io ()
segments CommandBuffer
cmd Segment
vertices) t ("firstInstance" ::: Word32, "firstInstance" ::: Word32)
ranges

single
  :: MonadIO m
  => Vk.CommandBuffer
  -> Model.Segment
  -> Buffer.Allocated s Model.InstanceAttrs
  -> Bound dsl vertices instances m ()
single :: forall (m :: * -> *) (s :: Store) (dsl :: [*]) vertices instances.
MonadIO m =>
CommandBuffer
-> Segment
-> Allocated s InstanceAttrs
-> Bound dsl vertices instances m ()
single CommandBuffer
cmd Segment
vertices Allocated s InstanceAttrs
points =
  forall (m :: * -> *) (t :: * -> *) (s :: Store) (dsl :: [*])
       vertices instances.
(MonadIO m, Foldable t) =>
CommandBuffer
-> Segment
-> Allocated s InstanceAttrs
-> t ("firstInstance" ::: Word32, "firstInstance" ::: Word32)
-> Bound dsl vertices instances m ()
batch CommandBuffer
cmd Segment
vertices Allocated s InstanceAttrs
points forall a b. (a -> b) -> a -> b
$
    forall a. a -> Maybe a
Just
      ( "firstInstance" ::: Word32
0
      , forall (s :: Store) a. Allocated s a -> "firstInstance" ::: Word32
Buffer.aUsed Allocated s InstanceAttrs
points
      )

bind
  :: MonadIO io
  => Vk.CommandBuffer
  -> Model.Segment
  -> Model.Buffer s
  -> io ()
bind :: forall (io :: * -> *) (s :: Store).
MonadIO io =>
CommandBuffer -> Segment -> Buffer s -> io ()
bind CommandBuffer
cmd Segment
vertices Buffer s
points = do
  forall (io :: * -> *).
MonadIO io =>
CommandBuffer
-> ("firstInstance" ::: Word32)
-> ("buffers" ::: Vector Buffer)
-> ("offsets" ::: Vector DeviceSize)
-> io ()
Vk.cmdBindVertexBuffers
    CommandBuffer
cmd
    "firstInstance" ::: Word32
0
    "buffers" ::: Vector Buffer
buffers
    "offsets" ::: Vector DeviceSize
offsets
  where
    buffers :: "buffers" ::: Vector Buffer
buffers =
      [ forall (s :: Store) a. Allocated s a -> Buffer
Buffer.aBuffer Segment
vertices
      , forall (s :: Store) a. Allocated s a -> Buffer
Buffer.aBuffer Buffer s
points
      , forall (s :: Store) a. Allocated s a -> Buffer
Buffer.aBuffer Buffer s
points
      ]

    offsets :: "offsets" ::: Vector DeviceSize
offsets =
      [ Item ("offsets" ::: Vector DeviceSize)
0
      , Item ("offsets" ::: Vector DeviceSize)
0
      , Item ("offsets" ::: Vector DeviceSize)
4forall a. Num a => a -> a -> a
*Item ("offsets" ::: Vector DeviceSize)
4 forall a. Num a => a -> a -> a
+ Item ("offsets" ::: Vector DeviceSize)
4forall a. Num a => a -> a -> a
*Item ("offsets" ::: Vector DeviceSize)
4 -- vec4, vec4
      ]

segments
  :: MonadIO io
  => Vk.CommandBuffer
  -> Buffer.Allocated s a
  -> ("firstInstance" ::: Word32, "instanceCount" ::: Word32)
  -> io ()
segments :: forall (io :: * -> *) (s :: Store) a.
MonadIO io =>
CommandBuffer
-> Allocated s a
-> ("firstInstance" ::: Word32, "firstInstance" ::: Word32)
-> io ()
segments CommandBuffer
cmd Allocated s a
vertices ("firstInstance" ::: Word32
offset, "firstInstance" ::: Word32
size) =
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ("firstInstance" ::: Word32
numSegments forall a. Ord a => a -> a -> Bool
> "firstInstance" ::: Word32
0) forall a b. (a -> b) -> a -> b
$
    forall (io :: * -> *).
MonadIO io =>
CommandBuffer
-> ("firstInstance" ::: Word32)
-> ("firstInstance" ::: Word32)
-> ("firstInstance" ::: Word32)
-> ("firstInstance" ::: Word32)
-> io ()
Vk.cmdDraw
      CommandBuffer
cmd
      "firstInstance" ::: Word32
vertexCount
      "firstInstance" ::: Word32
instanceCount
      "firstInstance" ::: Word32
firstVertex
      "firstInstance" ::: Word32
firstInstance
  where
    firstVertex :: "firstInstance" ::: Word32
firstVertex = "firstInstance" ::: Word32
0
    vertexCount :: "firstInstance" ::: Word32
vertexCount = forall (s :: Store) a. Allocated s a -> "firstInstance" ::: Word32
Buffer.aUsed Allocated s a
vertices

    numSegments :: "firstInstance" ::: Word32
numSegments = "firstInstance" ::: Word32
size forall a. Num a => a -> a -> a
- "firstInstance" ::: Word32
1
    firstInstance :: "firstInstance" ::: Word32
firstInstance = "firstInstance" ::: Word32
offset
    instanceCount :: "firstInstance" ::: Word32
instanceCount = "firstInstance" ::: Word32
numSegments