enable double buffering

This commit is contained in:
nek0 2023-01-06 16:54:30 +01:00
parent be689da9bf
commit 66455ae0d2
6 changed files with 91 additions and 89 deletions

View file

@ -22,12 +22,15 @@ import qualified Vulkan.Zero as Vk
import Devices import Devices
import Types import Types
createCommandPool frameOverlap :: Int
:: (MonadResource m) frameOverlap = 2
createFrames
:: (MonadResource m, MonadFail m)
=> Vk.PhysicalDevice => Vk.PhysicalDevice
-> Vk.Device -> Vk.Device
-> m (Vk.CommandPool, Vk.Queue) -> m (V.Vector FrameData, Vk.Queue)
createCommandPool physicalDevice logicalDevice = do createFrames physicalDevice logicalDevice = do
queueFamilyIndex <- getQueueFamily physicalDevice Vk.QUEUE_GRAPHICS_BIT queueFamilyIndex <- getQueueFamily physicalDevice Vk.QUEUE_GRAPHICS_BIT
@ -38,31 +41,56 @@ createCommandPool physicalDevice logicalDevice = do
graphicsQueue <- Vk.getDeviceQueue logicalDevice queueFamilyIndex 0 graphicsQueue <- Vk.getDeviceQueue logicalDevice queueFamilyIndex 0
commandPool <- snd <$> allocate frames <- V.mapM
(Vk.createCommandPool logicalDevice poolCreateInfo Nothing) (\_ -> do
(\commandPool -> do
putStrLn "destroying command pool"
Vk.destroyCommandPool logicalDevice commandPool Nothing
)
return (commandPool, graphicsQueue) commandPool <- snd <$> allocate
(Vk.createCommandPool logicalDevice poolCreateInfo Nothing)
(\commandPool -> do
putStrLn "destroying command pool"
Vk.destroyCommandPool logicalDevice commandPool Nothing
)
createCommandBuffer let commandBufferAllocationInfo = Vk.zero
:: (MonadResource m) { Vk.commandPool = commandPool
=> Vk.Device , Vk.level = Vk.COMMAND_BUFFER_LEVEL_PRIMARY
-> Vk.CommandPool , Vk.commandBufferCount = 1
-> Int }
-> m (V.Vector Vk.CommandBuffer)
createCommandBuffer logicalDevice commandPool number = do
let commandBufferAllocationInfo = Vk.zero commandBuffer <- Vk.allocateCommandBuffers logicalDevice commandBufferAllocationInfo
{ Vk.commandPool = commandPool
, Vk.level = Vk.COMMAND_BUFFER_LEVEL_PRIMARY let semaphoreCreateInfo = Vk.zero
, Vk.commandBufferCount = 1 fenceCreateInfo = Vk.zero
{ Vk.flags = Vk.FENCE_CREATE_SIGNALED_BIT
} :: Vk.FenceCreateInfo '[]
[presentSemaphore, renderSemaphore] <- replicateM 2
(snd <$> allocate
(Vk.createSemaphore logicalDevice semaphoreCreateInfo Nothing)
(\semaphore -> do
putStrLn "destroying semaphore"
Vk.destroySemaphore logicalDevice semaphore Nothing
)
)
renderFence <- snd <$> allocate
(Vk.createFence logicalDevice fenceCreateInfo Nothing)
(\fence -> do
putStrLn "destroying fence"
Vk.destroyFence logicalDevice fence Nothing
)
return FrameData
{ framePresentSemaphore = presentSemaphore
, frameRenderSemaphore = renderSemaphore
, frameRenderFence = renderFence
, frameCommandPool = commandPool
, frameMainCommandBuffer = V.head commandBuffer
} }
V.concat <$> )
replicateM number (Vk.allocateCommandBuffers logicalDevice commandBufferAllocationInfo) (V.fromList [1 .. frameOverlap])
return (frames, graphicsQueue)
recordCommandBuffer recordCommandBuffer
:: (MonadResource m, MonadReader ReadState m, MonadIO m) :: (MonadResource m, MonadReader ReadState m, MonadIO m)
@ -170,31 +198,3 @@ recordCommandBuffer
Vk.cmdEndRenderPass commandBuffer Vk.cmdEndRenderPass commandBuffer
Vk.endCommandBuffer commandBuffer Vk.endCommandBuffer commandBuffer
createSyncObjects
:: (MonadResource m, MonadFail m)
=> Vk.Device
-> m (Vk.Semaphore, Vk.Semaphore, Vk.Fence)
createSyncObjects logicalDevice = do
let semaphoreCreateInfo = Vk.zero
fenceCreateInfo = Vk.zero
{ Vk.flags = Vk.FENCE_CREATE_SIGNALED_BIT
} :: Vk.FenceCreateInfo '[]
[imageAvailableSemaphore, renderFinishedSemaphore] <- replicateM 2
(snd <$> allocate
(Vk.createSemaphore logicalDevice semaphoreCreateInfo Nothing)
(\semaphore -> do
putStrLn "destroying semaphore"
Vk.destroySemaphore logicalDevice semaphore Nothing
)
)
inFlightFence <- snd <$> allocate
(Vk.createFence logicalDevice fenceCreateInfo Nothing)
(\fence -> do
putStrLn "destroying fence"
Vk.destroyFence logicalDevice fence Nothing
)
return (imageAvailableSemaphore, renderFinishedSemaphore, inFlightFence)

View file

@ -19,33 +19,30 @@ import qualified Vulkan.Zero as Vk
import CommandBuffer import CommandBuffer
import Types import Types
import Util (getFrame)
drawFrame drawFrame
:: (MonadResource m, MonadFail m, MonadReader ReadState m) :: (MonadResource m, MonadFail m, MonadReader ReadState m)
=> EngineData => EngineData
-> Int
-> m () -> m ()
drawFrame engineData = do drawFrame engineData frameNumber = do
unless (all (V.length (engineCommandBuffers engineData) ==) let frame = getFrame engineData frameNumber
[ V.length (engineCommandBuffers engineData)
, V.length (engineFramebuffers engineData)
]) $
error ("Numbers of elements mismatch: command buffers " <>
show (V.length $ engineCommandBuffers engineData) <>
", frame buffers " <> show (V.length $ engineFramebuffers engineData)
)
let fences = V.singleton $ engineInFlightFence engineData void $ Vk.waitForFences
(engineLogicalDevice engineData)
void $ Vk.waitForFences (engineLogicalDevice engineData) fences True maxBound (V.singleton $ frameRenderFence frame)
Vk.resetFences (engineLogicalDevice engineData) fences True
maxBound
Vk.resetFences (engineLogicalDevice engineData) (V.singleton $ frameRenderFence frame)
(imageResult, index) <- (imageResult, index) <-
Khr.acquireNextImageKHR Khr.acquireNextImageKHR
(engineLogicalDevice engineData) (engineLogicalDevice engineData)
(engineSwapchain engineData) (engineSwapchain engineData)
maxBound maxBound
(engineImageAvailableSemaphore engineData) (frameRenderSemaphore frame)
Vk.NULL_HANDLE Vk.NULL_HANDLE
unless (imageResult == Vk.SUCCESS) $ unless (imageResult == Vk.SUCCESS) $
@ -53,13 +50,13 @@ drawFrame engineData = do
-- liftIO $ putStrLn "resetting command buffer" -- liftIO $ putStrLn "resetting command buffer"
Vk.resetCommandBuffer Vk.resetCommandBuffer
(engineCommandBuffers engineData V.! fromIntegral index) (Vk.CommandBufferResetFlagBits 0) (frameMainCommandBuffer frame) (Vk.CommandBufferResetFlagBits 0)
matLibrary <- (liftIO . STM.atomically. STM.readTMVar) =<< asks materialLibrary matLibrary <- (liftIO . STM.atomically. STM.readTMVar) =<< asks materialLibrary
-- liftIO $ putStrLn "recording command buffer" -- liftIO $ putStrLn "recording command buffer"
recordCommandBuffer recordCommandBuffer
(engineCommandBuffers engineData V.! fromIntegral index) (frameMainCommandBuffer frame)
(engineRenderPass engineData) (engineRenderPass engineData)
(engineFramebuffers engineData V.! fromIntegral index) (engineFramebuffers engineData V.! fromIntegral index)
(engineWindowDimensions engineData) (engineWindowDimensions engineData)
@ -68,23 +65,23 @@ drawFrame engineData = do
let submitInfo = Vk.zero let submitInfo = Vk.zero
{ Vk.waitSemaphores = { Vk.waitSemaphores =
V.singleton $ engineImageAvailableSemaphore engineData V.singleton $ frameRenderSemaphore frame
, Vk.waitDstStageMask = , Vk.waitDstStageMask =
V.singleton Vk.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT V.singleton Vk.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
, Vk.commandBuffers = , Vk.commandBuffers =
V.singleton (Vk.commandBufferHandle $ engineCommandBuffers engineData V.! fromIntegral index) V.singleton (Vk.commandBufferHandle $ frameMainCommandBuffer frame)
, Vk.signalSemaphores = , Vk.signalSemaphores =
V.singleton $ engineRenderFinishedSemaphore engineData V.singleton $ framePresentSemaphore frame
} }
-- liftIO $ putStrLn "submitting to queue" -- liftIO $ putStrLn "submitting to queue"
Vk.queueSubmit Vk.queueSubmit
(engineQueue engineData) (engineQueue engineData)
(V.singleton (Vk.SomeStruct submitInfo)) (V.singleton (Vk.SomeStruct submitInfo))
(engineInFlightFence engineData) (frameRenderFence frame)
let presentInfo = Vk.zero let presentInfo = Vk.zero
{ Khr.waitSemaphores = V.singleton $ engineRenderFinishedSemaphore engineData { Khr.waitSemaphores = V.singleton $ framePresentSemaphore frame
, Khr.swapchains = V.singleton $ engineSwapchain engineData , Khr.swapchains = V.singleton $ engineSwapchain engineData
, Khr.imageIndices = V.singleton index , Khr.imageIndices = V.singleton index
} }

View file

@ -24,10 +24,10 @@ import Instance
import Devices import Devices
import GraphicsPipeline import GraphicsPipeline
import Framebuffers import Framebuffers
import CommandBuffer
import Memory import Memory
import Types import Types
import Mesh import Mesh
import CommandBuffer
initEngine initEngine
:: Render EngineData :: Render EngineData
@ -101,11 +101,7 @@ initVulkan window = do
frameBuffers <- createFramebuffer vulkanLogicalDevice renderPass imageViews depthImageView dimensions frameBuffers <- createFramebuffer vulkanLogicalDevice renderPass imageViews depthImageView dimensions
(commandPool, graphicsQueue) <- createCommandPool vulkanPhysicalDevice vulkanLogicalDevice (frames, queue) <- createFrames vulkanPhysicalDevice vulkanLogicalDevice
commandBuffer <- createCommandBuffer vulkanLogicalDevice commandPool (length frameBuffers)
(imageAvailableSemaphore, renderFinishedSemaphore, inFlightFence) <-
createSyncObjects vulkanLogicalDevice
loadMeshes allocator loadMeshes allocator
@ -118,18 +114,15 @@ initVulkan window = do
vulkanLogicalDevice vulkanLogicalDevice
vulkanInstance vulkanInstance
swapchain swapchain
graphicsQueue queue
commandBuffer
frameBuffers frameBuffers
meshLayout meshLayout
renderPass renderPass
inFlightFence
imageAvailableSemaphore
renderFinishedSemaphore
allocator allocator
depthImageView depthImageView
depthAllocatedImage depthAllocatedImage
Vk.FORMAT_D32_SFLOAT Vk.FORMAT_D32_SFLOAT
frames
initScene :: (MonadReader ReadState m, MonadIO m) => m () initScene :: (MonadReader ReadState m, MonadIO m) => m ()
initScene = do initScene = do

View file

@ -27,6 +27,7 @@ main = do
renderablesContainer <- STM.newTMVarIO (V.empty) renderablesContainer <- STM.newTMVarIO (V.empty)
meshMap <- STM.newTMVarIO (M.empty) meshMap <- STM.newTMVarIO (M.empty)
materialMap <- STM.newTMVarIO (M.empty) materialMap <- STM.newTMVarIO (M.empty)
frameNumber <- STM.newTMVarIO 0
let initState = ReadState let initState = ReadState
{ renderables = renderablesContainer { renderables = renderablesContainer
, meshLibrary = meshMap , meshLibrary = meshMap
@ -45,8 +46,12 @@ main = do
(liftIO $ STM.atomically $ STM.readTMVar quit (liftIO $ STM.atomically $ STM.readTMVar quit
) )
( do ( do
number <- liftIO $ STM.atomically $ do
number <- STM.readTMVar frameNumber
void $ STM.swapTMVar frameNumber (succ number)
return number
-- draw -- draw
drawFrame engineData drawFrame engineData number
-- poll events -- poll events
evs <- liftIO SDL.pollEvents evs <- liftIO SDL.pollEvents
-- flip abort condition on window close -- flip abort condition on window close

View file

@ -31,17 +31,14 @@ data EngineData = EngineData
, engineInstance :: Vk.Instance , engineInstance :: Vk.Instance
, engineSwapchain :: Vk.SwapchainKHR , engineSwapchain :: Vk.SwapchainKHR
, engineQueue :: Vk.Queue , engineQueue :: Vk.Queue
, engineCommandBuffers :: V.Vector Vk.CommandBuffer
, engineFramebuffers :: V.Vector Vk.Framebuffer , engineFramebuffers :: V.Vector Vk.Framebuffer
, meshPipelineLayout :: Vk.PipelineLayout , meshPipelineLayout :: Vk.PipelineLayout
, engineRenderPass :: Vk.RenderPass , engineRenderPass :: Vk.RenderPass
, engineInFlightFence :: Vk.Fence
, engineImageAvailableSemaphore :: Vk.Semaphore
, engineRenderFinishedSemaphore :: Vk.Semaphore
, engineAllocator :: VMA.Allocator , engineAllocator :: VMA.Allocator
, engineDepthImageView :: Vk.ImageView , engineDepthImageView :: Vk.ImageView
, engineDepthImage :: AllocatedImage , engineDepthImage :: AllocatedImage
, engineDepthFormat :: Vk.Format , engineDepthFormat :: Vk.Format
, engineFrames :: V.Vector FrameData
} }
data AllocatedBuffer = AllocatedBuffer data AllocatedBuffer = AllocatedBuffer
@ -180,3 +177,12 @@ type Render a = RenderReader ReadState ResIO a
runRender :: ReadState -> Render a -> IO a runRender :: ReadState -> Render a -> IO a
runRender rd actions = runResourceT $ flip runReaderT rd $ runRenderInner actions runRender rd actions = runResourceT $ flip runReaderT rd $ runRenderInner actions
data FrameData = FrameData
{ framePresentSemaphore :: Vk.Semaphore
, frameRenderSemaphore :: Vk.Semaphore
, frameRenderFence :: Vk.Fence
, frameCommandPool :: Vk.CommandPool
, frameMainCommandBuffer :: Vk.CommandBuffer
}
deriving (Show)

View file

@ -35,6 +35,7 @@ executable vulkan-tutorial
Mesh Mesh
Image Image
Types Types
Util
-- LANGUAGE extensions used by modules in this package. -- LANGUAGE extensions used by modules in this package.
-- other-extensions: -- other-extensions: