{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments, TupleSections #-}
{-# LANGUAGE ScopedTypeVariables, RankNTypes, TypeApplications #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures, TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Memory.Type (

	-- * TYPE

	M(..),

	-- * NEW, READ AND WRITE

	newM, readM, writeMBinded,

	getBinded,

	-- * OBJECT LENGTH

	objectLength,

	-- * RAW OFFSET

	RawOffset, rawOffset, RawOffsetToOffset

	) where

import Data.Kind
import Data.TypeLevel.Tuple.Uncurry
import Data.HeteroParList qualified as HeteroParList
import Data.IORef

import Gpu.Vulkan.Object qualified as VObj
import Gpu.Vulkan.Buffer.Type qualified as B
import Gpu.Vulkan.Image.Type qualified as I

import Gpu.Vulkan.Memory.ImageBuffer
import Gpu.Vulkan.Memory.Middle qualified as M

import Gpu.Vulkan.Device.Internal qualified as Device

-- MEMORY

data M s (ibargs :: [(Type, ImageBufferArg)]) =
	M (IORef (HeteroParList.PL (U2 ImageBuffer) ibargs)) M.M

-- NEW, READ AND WRITE

newM :: HeteroParList.PL (U2 ImageBuffer) ibargs -> M.M -> IO (M s ibargs)
newM :: forall (ibargs :: [(*, ImageBufferArg)]) s.
PL (U2 ImageBuffer) ibargs -> M -> IO (M s ibargs)
newM PL (U2 ImageBuffer) ibargs
ibs M
mm = (IORef (PL (U2 ImageBuffer) ibargs) -> M -> M s ibargs
forall s (ibargs :: [(*, ImageBufferArg)]).
IORef (PL (U2 ImageBuffer) ibargs) -> M -> M s ibargs
`M` M
mm) (IORef (PL (U2 ImageBuffer) ibargs) -> M s ibargs)
-> IO (IORef (PL (U2 ImageBuffer) ibargs)) -> IO (M s ibargs)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PL (U2 ImageBuffer) ibargs
-> IO (IORef (PL (U2 ImageBuffer) ibargs))
forall a. a -> IO (IORef a)
newIORef PL (U2 ImageBuffer) ibargs
ibs

getBinded :: M s ibargs -> IO (HeteroParList.PL (U2 (ImageBufferBinded s)) ibargs)
getBinded :: forall s (ibargs :: [(*, ImageBufferArg)]).
M s ibargs -> IO (PL (U2 (ImageBufferBinded s)) ibargs)
getBinded M s ibargs
m = (forall (s :: (*, ImageBufferArg)).
 U2 ImageBuffer s -> U2 (ImageBufferBinded s) s)
-> PL (U2 ImageBuffer) ibargs
-> PL (U2 (ImageBufferBinded s)) ibargs
forall {k} (t :: k -> *) (t' :: k -> *) (ss :: [k]).
(forall (s :: k). t s -> t' s) -> PL t ss -> PL t' ss
HeteroParList.map U2 ImageBuffer s -> U2 (ImageBufferBinded s) s
forall (s :: (*, ImageBufferArg)).
U2 ImageBuffer s -> U2 (ImageBufferBinded s) s
forall (ibarg :: (*, ImageBufferArg)) sm.
U2 ImageBuffer ibarg -> U2 (ImageBufferBinded sm) ibarg
toBinded (PL (U2 ImageBuffer) ibargs
 -> PL (U2 (ImageBufferBinded s)) ibargs)
-> ((PL (U2 ImageBuffer) ibargs, M) -> PL (U2 ImageBuffer) ibargs)
-> (PL (U2 ImageBuffer) ibargs, M)
-> PL (U2 (ImageBufferBinded s)) ibargs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PL (U2 ImageBuffer) ibargs, M) -> PL (U2 ImageBuffer) ibargs
forall a b. (a, b) -> a
fst ((PL (U2 ImageBuffer) ibargs, M)
 -> PL (U2 (ImageBufferBinded s)) ibargs)
-> IO (PL (U2 ImageBuffer) ibargs, M)
-> IO (PL (U2 (ImageBufferBinded s)) ibargs)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> M s ibargs -> IO (PL (U2 ImageBuffer) ibargs, M)
forall s (ibargs :: [(*, ImageBufferArg)]).
M s ibargs -> IO (PL (U2 ImageBuffer) ibargs, M)
readM M s ibargs
m
	where
	toBinded :: U2 ImageBuffer ibarg -> U2 (ImageBufferBinded sm) ibarg
	toBinded :: forall (ibarg :: (*, ImageBufferArg)) sm.
U2 ImageBuffer ibarg -> U2 (ImageBufferBinded sm) ibarg
toBinded (U2 (Image (I.I I
i))) = ImageBufferBinded sm s1 ('ImageArg nm fmt)
-> U2 (ImageBufferBinded sm) ibarg
ImageBufferBinded sm s1 ('ImageArg nm fmt)
-> U2 (ImageBufferBinded sm) '(s1, 'ImageArg nm fmt)
forall {k} {k1} (t :: k -> k1 -> *) (s1 :: k) (s2 :: k1).
t s1 s2 -> U2 t '(s1, s2)
U2 (ImageBufferBinded sm s1 ('ImageArg nm fmt)
 -> U2 (ImageBufferBinded sm) ibarg)
-> (Binded sm s1 nm fmt
    -> ImageBufferBinded sm s1 ('ImageArg nm fmt))
-> Binded sm s1 nm fmt
-> U2 (ImageBufferBinded sm) ibarg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Binded sm s1 nm fmt -> ImageBufferBinded sm s1 ('ImageArg nm fmt)
forall sm sib (nm :: Symbol) (fmt :: Format).
Binded sm sib nm fmt -> ImageBufferBinded sm sib ('ImageArg nm fmt)
ImageBinded (Binded sm s1 nm fmt -> U2 (ImageBufferBinded sm) ibarg)
-> Binded sm s1 nm fmt -> U2 (ImageBufferBinded sm) ibarg
forall a b. (a -> b) -> a -> b
$ I -> Binded sm s1 nm fmt
forall sm si (nm :: Symbol) (fmt :: Format).
I -> Binded sm si nm fmt
I.Binded I
i
	toBinded (U2 (Buffer (B.B PL Length objs
x B
b))) = ImageBufferBinded sm s1 ('BufferArg nm objs)
-> U2 (ImageBufferBinded sm) ibarg
ImageBufferBinded sm s1 ('BufferArg nm objs)
-> U2 (ImageBufferBinded sm) '(s1, 'BufferArg nm objs)
forall {k} {k1} (t :: k -> k1 -> *) (s1 :: k) (s2 :: k1).
t s1 s2 -> U2 t '(s1, s2)
U2 (ImageBufferBinded sm s1 ('BufferArg nm objs)
 -> U2 (ImageBufferBinded sm) ibarg)
-> (Binded sm s1 nm objs
    -> ImageBufferBinded sm s1 ('BufferArg nm objs))
-> Binded sm s1 nm objs
-> U2 (ImageBufferBinded sm) ibarg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Binded sm s1 nm objs
-> ImageBufferBinded sm s1 ('BufferArg nm objs)
forall sm sib (nm :: Symbol) (objs :: [O]).
Binded sm sib nm objs
-> ImageBufferBinded sm sib ('BufferArg nm objs)
BufferBinded (Binded sm s1 nm objs -> U2 (ImageBufferBinded sm) ibarg)
-> Binded sm s1 nm objs -> U2 (ImageBufferBinded sm) ibarg
forall a b. (a -> b) -> a -> b
$ PL Length objs -> B -> Binded sm s1 nm objs
forall sm sb (nm :: Symbol) (objs :: [O]).
PL Length objs -> B -> Binded sm sb nm objs
B.Binded PL Length objs
x B
b
	toBinded (U2 (Raw Size
algn Size
sz)) = ImageBufferBinded sm s1 'RawArg
-> U2 (ImageBufferBinded sm) '(s1, 'RawArg)
forall {k} {k1} (t :: k -> k1 -> *) (s1 :: k) (s2 :: k1).
t s1 s2 -> U2 t '(s1, s2)
U2 (ImageBufferBinded sm s1 'RawArg
 -> U2 (ImageBufferBinded sm) '(s1, 'RawArg))
-> ImageBufferBinded sm s1 'RawArg
-> U2 (ImageBufferBinded sm) '(s1, 'RawArg)
forall a b. (a -> b) -> a -> b
$ Size -> Size -> ImageBufferBinded sm s1 'RawArg
forall sm sib. Size -> Size -> ImageBufferBinded sm sib 'RawArg
RawBinded Size
algn Size
sz

readM :: M s ibargs -> IO (HeteroParList.PL (U2 ImageBuffer) ibargs, M.M)
readM :: forall s (ibargs :: [(*, ImageBufferArg)]).
M s ibargs -> IO (PL (U2 ImageBuffer) ibargs, M)
readM (M IORef (PL (U2 ImageBuffer) ibargs)
ib M
m) = (, M
m) (PL (U2 ImageBuffer) ibargs -> (PL (U2 ImageBuffer) ibargs, M))
-> IO (PL (U2 ImageBuffer) ibargs)
-> IO (PL (U2 ImageBuffer) ibargs, M)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (PL (U2 ImageBuffer) ibargs)
-> IO (PL (U2 ImageBuffer) ibargs)
forall a. IORef a -> IO a
readIORef IORef (PL (U2 ImageBuffer) ibargs)
ib

writeMBinded :: M s ibargs ->
	HeteroParList.PL (U2 (ImageBufferBinded sm)) ibargs -> IO ()
writeMBinded :: forall s (ibargs :: [(*, ImageBufferArg)]) sm.
M s ibargs -> PL (U2 (ImageBufferBinded sm)) ibargs -> IO ()
writeMBinded (M IORef (PL (U2 ImageBuffer) ibargs)
rib M
_r) PL (U2 (ImageBufferBinded sm)) ibargs
ibs =
	IORef (PL (U2 ImageBuffer) ibargs)
-> PL (U2 ImageBuffer) ibargs -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (PL (U2 ImageBuffer) ibargs)
rib ((forall (s :: (*, ImageBufferArg)).
 U2 (ImageBufferBinded sm) s -> U2 ImageBuffer s)
-> PL (U2 (ImageBufferBinded sm)) ibargs
-> PL (U2 ImageBuffer) ibargs
forall {k} (t :: k -> *) (t' :: k -> *) (ss :: [k]).
(forall (s :: k). t s -> t' s) -> PL t ss -> PL t' ss
HeteroParList.map U2 (ImageBufferBinded sm) s -> U2 ImageBuffer s
forall sm (ibarg :: (*, ImageBufferArg)).
U2 (ImageBufferBinded sm) ibarg -> U2 ImageBuffer ibarg
forall (s :: (*, ImageBufferArg)).
U2 (ImageBufferBinded sm) s -> U2 ImageBuffer s
fromBinded PL (U2 (ImageBufferBinded sm)) ibargs
ibs)
	where
	fromBinded :: U2 (ImageBufferBinded sm) ibarg -> U2 ImageBuffer ibarg
	fromBinded :: forall sm (ibarg :: (*, ImageBufferArg)).
U2 (ImageBufferBinded sm) ibarg -> U2 ImageBuffer ibarg
fromBinded (U2 (ImageBinded (I.Binded I
i))) = ImageBuffer s1 ('ImageArg nm fmt) -> U2 ImageBuffer ibarg
ImageBuffer s1 ('ImageArg nm fmt)
-> U2 ImageBuffer '(s1, 'ImageArg nm fmt)
forall {k} {k1} (t :: k -> k1 -> *) (s1 :: k) (s2 :: k1).
t s1 s2 -> U2 t '(s1, s2)
U2 (ImageBuffer s1 ('ImageArg nm fmt) -> U2 ImageBuffer ibarg)
-> (I s1 nm fmt -> ImageBuffer s1 ('ImageArg nm fmt))
-> I s1 nm fmt
-> U2 ImageBuffer ibarg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. I s1 nm fmt -> ImageBuffer s1 ('ImageArg nm fmt)
forall s (nm :: Symbol) (fmt :: Format).
I s nm fmt -> ImageBuffer s ('ImageArg nm fmt)
Image (I s1 nm fmt -> U2 ImageBuffer ibarg)
-> I s1 nm fmt -> U2 ImageBuffer ibarg
forall a b. (a -> b) -> a -> b
$ I -> I s1 nm fmt
forall s (nm :: Symbol) (fmt :: Format). I -> I s nm fmt
I.I I
i
	fromBinded (U2 (BufferBinded (B.Binded PL Length objs
x B
b))) = ImageBuffer s1 ('BufferArg nm objs) -> U2 ImageBuffer ibarg
ImageBuffer s1 ('BufferArg nm objs)
-> U2 ImageBuffer '(s1, 'BufferArg nm objs)
forall {k} {k1} (t :: k -> k1 -> *) (s1 :: k) (s2 :: k1).
t s1 s2 -> U2 t '(s1, s2)
U2 (ImageBuffer s1 ('BufferArg nm objs) -> U2 ImageBuffer ibarg)
-> (B s1 nm objs -> ImageBuffer s1 ('BufferArg nm objs))
-> B s1 nm objs
-> U2 ImageBuffer ibarg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. B s1 nm objs -> ImageBuffer s1 ('BufferArg nm objs)
forall s (nm :: Symbol) (objs :: [O]).
B s nm objs -> ImageBuffer s ('BufferArg nm objs)
Buffer (B s1 nm objs -> U2 ImageBuffer ibarg)
-> B s1 nm objs -> U2 ImageBuffer ibarg
forall a b. (a -> b) -> a -> b
$ PL Length objs -> B -> B s1 nm objs
forall s (nm :: Symbol) (objs :: [O]).
PL Length objs -> B -> B s nm objs
B.B PL Length objs
x B
b
	fromBinded (U2 (RawBinded Size
algn Size
sz)) = ImageBuffer s1 'RawArg -> U2 ImageBuffer '(s1, 'RawArg)
forall {k} {k1} (t :: k -> k1 -> *) (s1 :: k) (s2 :: k1).
t s1 s2 -> U2 t '(s1, s2)
U2 (ImageBuffer s1 'RawArg -> U2 ImageBuffer '(s1, 'RawArg))
-> ImageBuffer s1 'RawArg -> U2 ImageBuffer '(s1, 'RawArg)
forall a b. (a -> b) -> a -> b
$ Size -> Size -> ImageBuffer s1 'RawArg
forall s. Size -> Size -> ImageBuffer s 'RawArg
Raw Size
algn Size
sz

-- OBJECT LENGTH

objectLength :: forall nm obj ibargs sm . ObjectLength nm obj ibargs =>
	M sm ibargs -> IO (VObj.Length obj)
objectLength :: forall (nm :: Symbol) (obj :: O) (ibargs :: [(*, ImageBufferArg)])
       sm.
ObjectLength nm obj ibargs =>
M sm ibargs -> IO (Length obj)
objectLength M sm ibargs
m = (((PL (U2 ImageBuffer) ibargs, M) -> Length obj)
-> IO (PL (U2 ImageBuffer) ibargs, M) -> IO (Length obj)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> M sm ibargs -> IO (PL (U2 ImageBuffer) ibargs, M)
forall s (ibargs :: [(*, ImageBufferArg)]).
M s ibargs -> IO (PL (U2 ImageBuffer) ibargs, M)
readM M sm ibargs
m) \(PL (U2 ImageBuffer) ibargs
ibs, M
_m) -> forall (nm :: Symbol) (obj :: O) (ibargs :: [(*, ImageBufferArg)]).
ObjectLength nm obj ibargs =>
PL (U2 ImageBuffer) ibargs -> Length obj
objectLength' @nm @obj @ibargs PL (U2 ImageBuffer) ibargs
ibs

-- RAW OFFSET

rawOffset :: RawOffsetToOffset ibargs n =>
	Device.D sd -> M sm ibargs -> RawOffset n -> IO Device.Size
rawOffset :: forall (ibargs :: [(*, ImageBufferArg)]) (n :: Nat) sd sm.
RawOffsetToOffset ibargs n =>
D sd -> M sm ibargs -> RawOffset n -> IO Size
rawOffset D sd
dv (M IORef (PL (U2 ImageBuffer) ibargs)
ribs M
_) RawOffset n
ro = do
	PL (U2 ImageBuffer) ibargs
ibs <- IORef (PL (U2 ImageBuffer) ibargs)
-> IO (PL (U2 ImageBuffer) ibargs)
forall a. IORef a -> IO a
readIORef IORef (PL (U2 ImageBuffer) ibargs)
ribs
	Size
-> D sd -> PL (U2 ImageBuffer) ibargs -> RawOffset n -> IO Size
forall (ibargs :: [(*, ImageBufferArg)]) (n :: Nat) sd.
RawOffsetToOffset ibargs n =>
Size
-> D sd -> PL (U2 ImageBuffer) ibargs -> RawOffset n -> IO Size
forall sd.
Size
-> D sd -> PL (U2 ImageBuffer) ibargs -> RawOffset n -> IO Size
rawOffsetToOffset Size
0 D sd
dv PL (U2 ImageBuffer) ibargs
ibs RawOffset n
ro