{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments, LambdaCase #-}
{-# LANGUAGE DataKinds, PolyKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGe MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.VertexInput.Internal (
	Rate(..),
	M.AttributeDescription(..),
	BindingDescription(..),

	bindingDescriptionFromRaw,
	bindingDescriptionToMiddle,

	) where

import Data.Word
import Data.TypeLevel.TypeVal qualified as TypeVal

import Gpu.Vulkan.VertexInput.Middle qualified as M
import Gpu.Vulkan.VertexInput.Enum qualified as M

data Rate = RateVertex | RateInstance deriving Int -> Rate -> ShowS
[Rate] -> ShowS
Rate -> String
(Int -> Rate -> ShowS)
-> (Rate -> String) -> ([Rate] -> ShowS) -> Show Rate
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Rate -> ShowS
showsPrec :: Int -> Rate -> ShowS
$cshow :: Rate -> String
show :: Rate -> String
$cshowList :: [Rate] -> ShowS
showList :: [Rate] -> ShowS
Show

instance TypeVal.T 'RateVertex Rate where t :: Rate
t = Rate
RateVertex
instance TypeVal.T 'RateInstance Rate where t :: Rate
t = Rate
RateInstance

data BindingDescription = BindingDescription {
	BindingDescription -> Word32
bindingDescriptionBinding :: Word32,
	BindingDescription -> Word32
bindingDescriptionStride :: Word32,
	BindingDescription -> Rate
bindingDescriptionInputRate :: Rate }
	deriving Int -> BindingDescription -> ShowS
[BindingDescription] -> ShowS
BindingDescription -> String
(Int -> BindingDescription -> ShowS)
-> (BindingDescription -> String)
-> ([BindingDescription] -> ShowS)
-> Show BindingDescription
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BindingDescription -> ShowS
showsPrec :: Int -> BindingDescription -> ShowS
$cshow :: BindingDescription -> String
show :: BindingDescription -> String
$cshowList :: [BindingDescription] -> ShowS
showList :: [BindingDescription] -> ShowS
Show

type SizeAlignment = (Int, Int)

bindingDescriptionFromRaw :: [(SizeAlignment, Rate)] -> [BindingDescription]
bindingDescriptionFromRaw :: [(SizeAlignment, Rate)] -> [BindingDescription]
bindingDescriptionFromRaw [(SizeAlignment, Rate)]
sars = (((Word32, (SizeAlignment, Rate)) -> BindingDescription)
-> [(Word32, (SizeAlignment, Rate))] -> [BindingDescription]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Word32]
-> [(SizeAlignment, Rate)] -> [(Word32, (SizeAlignment, Rate))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Word32
0 ..] [(SizeAlignment, Rate)]
sars)
	\(Word32
b, ((Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral -> Word32
sz, Int
_algn), Rate
r)) -> Word32 -> Word32 -> Rate -> BindingDescription
BindingDescription Word32
b Word32
sz Rate
r

bindingDescriptionToMiddle :: BindingDescription -> M.BindingDescription
bindingDescriptionToMiddle :: BindingDescription -> BindingDescription
bindingDescriptionToMiddle BindingDescription {
	bindingDescriptionBinding :: BindingDescription -> Word32
bindingDescriptionBinding = Word32
bdg,
	bindingDescriptionStride :: BindingDescription -> Word32
bindingDescriptionStride = Word32
strd,
	bindingDescriptionInputRate :: BindingDescription -> Rate
bindingDescriptionInputRate = Rate
rt } = M.BindingDescription {
	bindingDescriptionBinding :: Word32
M.bindingDescriptionBinding = Word32
bdg,
	bindingDescriptionStride :: Word32
M.bindingDescriptionStride = Word32
strd,
	bindingDescriptionInputRate :: Rate
M.bindingDescriptionInputRate = Rate -> Rate
rateToEnum Rate
rt }
	where rateToEnum :: Rate -> Rate
rateToEnum = \case
		Rate
RateVertex -> Rate
M.RateVertex; Rate
RateInstance -> Rate
M.RateInstance