packages feed

gpu-vulkan-middle-0.1.0.70: src/Gpu/Vulkan/Cmd/Middle.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ScopedTypeVariables, RankNTypes, TypeApplications #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Gpu.Vulkan.Cmd.Middle (

	-- * BEGIN AND END RENDER PASS

	beginRenderPass, endRenderPass,

	-- * DRAW AND DISPATCH

	-- ** Draw

	bindPipelineGraphics, bindVertexBuffers, bindIndexBuffer, draw, drawIndexed,

	-- ** Dispatch

	bindPipelineCompute, dispatch,

	-- * PUSH CONSTANTS AND BIND DESCRIPTOR SETS

	pushConstants, bindDescriptorSets,

	-- * COPY BUFFERS AND IMAGES

	copyBuffer, copyBufferToImage, copyImageToBuffer, blitImage, blitImage2,

	-- * CLEAR COLOR IMAGE

	clearColorImage,

	-- * MEMORY DEPENDENCY

	pipelineBarrier, pipelineBarrier2,

	-- * QUERY

	resetQueryPool, beginQuery, endQuery, writeTimestamp

	) where

import Foreign.Marshal.Alloc
import Foreign.Marshal.Array
import Foreign.Storable
import Foreign.Storable.PeekPoke (WithPoked)
import Foreign.Storable.HeteroList
import Control.Arrow
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Cont
import Data.TypeLevel.Maybe qualified as TMaybe
import Data.TypeLevel.List qualified as TList
import Data.List qualified as L
import Data.HeteroParList qualified as HPList
import Data.HeteroParList qualified as HeteroParList
import Data.Word
import Data.Int
import Data.IORef

import Gpu.Vulkan.Middle.Internal
import Gpu.Vulkan.Enum

import qualified Gpu.Vulkan.CommandBuffer.Middle.Internal as CommandBuffer.M
import qualified Gpu.Vulkan.Buffer.Middle.Internal as Buffer
import qualified Gpu.Vulkan.Buffer.Core as Buffer.C
import qualified Gpu.Vulkan.Device.Middle.Internal as Device
import qualified Gpu.Vulkan.Cmd.Core as C

import qualified Gpu.Vulkan.RenderPass.Middle.Internal as RenderPass
import qualified Gpu.Vulkan.Subpass.Enum as Subpass
import qualified Gpu.Vulkan.Pipeline.Graphics.Middle.Internal as Pipeline
import qualified Gpu.Vulkan.Pipeline.Compute.Middle.Internal as Pipeline.Compute
import qualified Gpu.Vulkan.Pipeline.Enum as Pipeline
import qualified Gpu.Vulkan.PipelineLayout.Middle.Internal as Pipeline.Layout

import qualified Gpu.Vulkan.DescriptorSet.Middle.Internal as Descriptor.Set

import qualified Gpu.Vulkan.Image.Enum as Image
import qualified Gpu.Vulkan.Image.Middle.Internal as Image
import qualified Gpu.Vulkan.Buffer.Middle.Internal as Buffer.M
import qualified Gpu.Vulkan.Memory.Middle.Internal as Memory.M

import Gpu.Vulkan.Query.Enum qualified as Query
import Gpu.Vulkan.QueryPool.Middle.Internal qualified as QueryPool

beginRenderPass :: (WithPoked (TMaybe.M mn), ClearValueListToCore cts) => CommandBuffer.M.C ->
	RenderPass.BeginInfo mn cts -> Subpass.Contents -> IO ()
beginRenderPass (CommandBuffer.M.C _ cb) rpbi (Subpass.Contents spcnt) =
	RenderPass.beginInfoToCore rpbi \prpbi ->
		C.beginRenderPass cb prpbi spcnt

endRenderPass :: CommandBuffer.M.C -> IO ()
endRenderPass (CommandBuffer.M.C _ cb) = C.endRenderPass cb

bindPipelineGraphics ::
	CommandBuffer.M.C -> Pipeline.BindPoint -> Pipeline.G -> IO ()
bindPipelineGraphics (CommandBuffer.M.C rppl cb) (Pipeline.BindPoint pbp) ppl = do
	ppl0 <- readIORef rppl
	ppl' <- Pipeline.gToCore ppl
	when (ppl' /= ppl0) do
		writeIORef rppl ppl'
		C.bindPipeline cb pbp ppl'

bindPipelineCompute ::
	CommandBuffer.M.C -> Pipeline.BindPoint -> Pipeline.Compute.C -> IO ()
bindPipelineCompute (CommandBuffer.M.C rppl cb) (Pipeline.BindPoint pbp) (Pipeline.Compute.C ppl) = do
	ppl0 <- readIORef rppl
	when (ppl /= ppl0) do
		writeIORef rppl ppl
		C.bindPipeline cb pbp ppl

bindVertexBuffers ::
	CommandBuffer.M.C -> Word32 -> [(Buffer.B, Device.Size)] -> IO ()
bindVertexBuffers (CommandBuffer.M.C _ c)
	fb ((length &&& unzip) -> (bc, (bs, os))) = ($ pure) $ runContT do
	pb <- ContT $ allocaArray bc
	lift . pokeArray pb $ (\(Buffer.B b) -> b) <$> bs
	po <- ContT $ allocaArray bc
	lift . pokeArray po $ (\(Device.Size sz) -> sz) <$> os
	lift $ C.bindVertexBuffers c fb (fromIntegral bc) pb po

bindIndexBuffer ::
	CommandBuffer.M.C -> Buffer.B -> Device.Size -> IndexType -> IO ()
bindIndexBuffer
	(CommandBuffer.M.C _ cb) (Buffer.B ib) (Device.Size sz) (IndexType it) =
	C.bindIndexBuffer cb ib sz it

pushConstants :: forall as . PokableList as =>
	CommandBuffer.M.C -> Pipeline.Layout.P ->
	ShaderStageFlags -> Word32 -> HeteroParList.L as -> IO ()
pushConstants (CommandBuffer.M.C _ cb) (Pipeline.Layout.P lyt)
	(ShaderStageFlagBits ss) ost xs = ($ pure) $ runContT do
	let	sz :: Integral n => n
		sz = fromIntegral $ wholeSize @as
	p <- ContT $ allocaBytes sz
	lift do	pokeList p xs
		C.pushConstants cb lyt ss ost sz p

bindDescriptorSets ::
	CommandBuffer.M.C -> Pipeline.BindPoint -> Pipeline.Layout.P ->
	Word32 -> [Descriptor.Set.D] -> [Word32] -> IO ()
bindDescriptorSets
	(CommandBuffer.M.C _ cb) (Pipeline.BindPoint bp) (Pipeline.Layout.P lyt)
	fs (length &&& id -> (dsc, dss))
	(length &&& id -> (doc, dos)) = ($ pure) $ runContT do
	pdss <- ContT $ allocaArray dsc
	let	cdss = (\(Descriptor.Set.D s) -> s) <$> dss
	lift $ pokeArray pdss cdss
	pdos <- ContT $ allocaArray doc
	lift $ pokeArray pdos dos
	lift $ C.bindDescriptorSets
		cb bp lyt fs (fromIntegral dsc) pdss (fromIntegral doc) pdos

draw :: CommandBuffer.M.C -> Word32 -> Word32 -> Word32 -> Word32 -> IO ()
draw (CommandBuffer.M.C _ cb) vc ic fv fi = C.draw cb vc ic fv fi

drawIndexed :: CommandBuffer.M.C ->
	Word32 -> Word32 -> Word32 -> Int32 -> Word32 -> IO ()
drawIndexed (CommandBuffer.M.C _ cb) idxc istc fidx vo fist =
	C.drawIndexed cb idxc istc fidx vo fist

dispatch :: CommandBuffer.M.C -> Word32 -> Word32 -> Word32 -> IO ()
dispatch (CommandBuffer.M.C _ cb) = C.dispatch cb

copyBuffer ::
	CommandBuffer.M.C -> Buffer.B -> Buffer.B -> [Buffer.C.Copy] -> IO ()
copyBuffer (CommandBuffer.M.C _ c) (Buffer.B s) (Buffer.B d)
	(length &&& id -> (rc, rs)) = ($ pure) $ runContT do
	prs <- ContT $ allocaArray rc
	lift do	pokeArray prs rs
		C.copyBuffer c s d (fromIntegral rc) prs

copyBufferToImage ::
	CommandBuffer.M.C -> Buffer.M.B -> Image.I -> Image.Layout ->
	[Buffer.M.ImageCopy] -> IO ()
copyBufferToImage (CommandBuffer.M.C _ cb)
	(Buffer.M.B sb) (Image.I rdi) (Image.Layout dil)
	(length &&& id -> (rc, rs)) = ($ pure) $ runContT do
	prs <- ContT $ allocaArray rc
	lift . pokeArray prs $ Buffer.M.imageCopyToCore <$> rs
	lift do	(_, di) <- readIORef rdi
		C.copyBufferToImage cb sb di dil (fromIntegral rc) prs

copyImageToBuffer ::
	CommandBuffer.M.C -> Image.I -> Image.Layout -> Buffer.M.B ->
	[Buffer.M.ImageCopy] -> IO ()
copyImageToBuffer (CommandBuffer.M.C _ cb)
	(Image.I rsi) (Image.Layout sil) (Buffer.M.B db)
	(length &&& id -> (rc, rs)) = ($ pure) $ runContT do
	prs <- ContT $ allocaArray rc
	lift . pokeArray prs $ Buffer.M.imageCopyToCore <$> rs
	lift do	(_, si) <- readIORef rsi
		C.copyImageToBuffer cb si sil db (fromIntegral rc) prs

pipelineBarrier :: (
	HeteroParList.ToListWithCCpsM' WithPoked TMaybe.M ns,
	HeteroParList.ToListWithCCpsM' WithPoked TMaybe.M ns',
	HeteroParList.ToListWithCCpsM' WithPoked TMaybe.M ns'' ) =>
	CommandBuffer.M.C -> Pipeline.StageFlags -> Pipeline.StageFlags ->
	DependencyFlags ->
	HeteroParList.PL Memory.M.Barrier ns ->
	HeteroParList.PL Buffer.M.MemoryBarrier ns' ->
	HeteroParList.PL Image.MemoryBarrier ns'' -> IO ()
pipelineBarrier (CommandBuffer.M.C _ cb)
	(Pipeline.StageFlagBits ssm) (Pipeline.StageFlagBits dsm)
	(DependencyFlagBits dfs)
	mbs bbs ibs =
		HeteroParList.withListWithCCpsM' @_ @WithPoked @TMaybe.M mbs Memory.M.barrierToCore \cmbs ->
		let	mbc = length cmbs in
		allocaArray mbc \pmbs ->
		pokeArray pmbs cmbs >>
		HeteroParList.withListWithCCpsM' @_ @WithPoked @TMaybe.M bbs Buffer.M.memoryBarrierToCore' \cbbs ->
		let	bbc = length cbbs in
		allocaArray bbc \pbbs ->
		pokeArray pbbs cbbs >>
		HeteroParList.withListWithCCpsM' @_ @WithPoked @TMaybe.M ibs Image.memoryBarrierToCore \cibs ->
		let	ibc = length cibs in
		allocaArray ibc \pibs ->
		pokeArray pibs cibs >>

		C.pipelineBarrier cb ssm dsm dfs (fromIntegral mbc) pmbs
			(fromIntegral bbc) pbbs (fromIntegral ibc) pibs

pipelineBarrier2 :: (
	WithPoked (TMaybe.M mn),
	HPList.ToListWithCCpsM' WithPoked TMaybe.M mbas, TList.Length mbas,
	HPList.ToListWithCCpsM' WithPoked TMaybe.M bmbas, TList.Length bmbas,
	HPList.ToListWithCCpsM' WithPoked TMaybe.M imbas, TList.Length imbas
	) =>
	CommandBuffer.M.C -> DependencyInfo mn mbas bmbas imbas -> IO ()
pipelineBarrier2 (CommandBuffer.M.C _ cb) di =
	dependencyInfoToCore di \cdi -> alloca \pdi -> do
		poke pdi cdi
		C.pipelineBarrier2 cb pdi

blitImage :: CommandBuffer.M.C ->
	Image.I -> Image.Layout -> Image.I -> Image.Layout ->
	[Image.Blit] -> Filter -> IO ()
blitImage (CommandBuffer.M.C _ cb)
	(Image.I rsrc) (Image.Layout srcLyt) (Image.I rdst) (Image.Layout dstLyt)
	(length &&& id -> (bltc, blts)) (Filter ft) = ($ pure) $ runContT do
	pblts <- ContT $ allocaArray bltc
	lift . pokeArray pblts $ Image.blitToCore <$> blts
	lift do (_, src) <- readIORef rsrc
		(_, dst) <- readIORef rdst
		C.blitImage cb src srcLyt dst dstLyt (fromIntegral bltc) pblts ft

blitImage2 :: (
	WithPoked (TMaybe.M mn),
	TList.Length ras, HPList.ToListWithCCpsM' WithPoked TMaybe.M ras ) =>
	CommandBuffer.M.C -> BlitImageInfo2 mn ras -> IO ()
blitImage2 (CommandBuffer.M.C _ cb) bii =
	blitImageInfo2ToCore bii \pcbii -> C.blitImage2 cb pcbii

resetQueryPool :: CommandBuffer.M.C -> QueryPool.Q -> Word32 -> Word32 -> IO ()
resetQueryPool (CommandBuffer.M.C _ c) (QueryPool.Q q) fq qc =
	C.resetQueryPool c q fq qc

beginQuery :: CommandBuffer.M.C ->
	QueryPool.Q -> Word32 -> Query.ControlFlags -> IO ()
beginQuery (CommandBuffer.M.C _ c) (QueryPool.Q q) i (Query.ControlFlagBits flgs) =
	C.beginQuery c q i flgs

endQuery :: CommandBuffer.M.C -> QueryPool.Q -> Word32 -> IO ()
endQuery (CommandBuffer.M.C _ c) (QueryPool.Q q) = C.endQuery c q

writeTimestamp :: CommandBuffer.M.C -> Pipeline.StageFlagBits ->
	QueryPool.Q -> Word32 -> IO ()
writeTimestamp
	(CommandBuffer.M.C _ c) (Pipeline.StageFlagBits fls) (QueryPool.Q q) i =
	C.writeTimestamp c fls q i

clearColorImage :: ClearColorValueToCore cct =>
	CommandBuffer.M.C -> Image.I -> Image.Layout ->
	ClearValue ('ClearTypeColor cct) -> [Image.SubresourceRange] -> IO ()
clearColorImage
	(CommandBuffer.M.C _ cb) (Image.I rimg) (Image.Layout lyt) cv srrs =
	readIORef rimg >>= \(_, img) ->
	clearColorValueToCore cv \ccv ->
	allocaArray (length srrs) \psrrs ->
	pokeArray psrrs (Image.subresourceRangeToCore <$> srrs) >>
	C.clearColorImage cb img lyt ccv (L.genericLength srrs) psrrs