blob: d80c5330f644bb637b59ad304c74fc918cd3ce9b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NondecreasingIndentation #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Main (main) where
import Control.Exception (bracket)
import Data.Bits ((.|.))
import Data.Coerce (coerce)
import Data.Vector (Vector)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Ptr (Ptr)
import Foreign.Storable (peek)
import Unsafe.Coerce (unsafeCoerce)
import Vulkan.CStruct.Extends (SomeStruct(..))
import Vulkan.Zero (zero)
import VkTest.Config (QueriedData(..))
import qualified VkTest.Config as Config
import qualified VkTest.Shaders as Shaders
import qualified VkTest.Util as Util
import qualified Data.ByteString as BS
import qualified Data.Vector as V
import qualified RGFW as RGFW
import qualified Vulkan.Core10 as Vk
import qualified Vulkan.Core13 as Vk
import qualified Vulkan.Extensions.VK_KHR_surface as Vk
import qualified Vulkan.Extensions.VK_KHR_swapchain as Vk
main :: IO ()
main = Util.withRGFW "rgfw instance title" (fromIntegral $ RGFW.unwrapRGFW_initFlags_enum RGFW.RGFW_initVulkan) $ \_ -> do
exts <- alloca $ \extension_count -> do
exts <- RGFW.rGFW_getRequiredInstanceExtensions_Vulkan extension_count
cexts <- peek extension_count
vexts <- Util.processExtensions cexts exts V.empty
return vexts
Vk.withInstance (Config.instance' exts) Nothing bracket $ \i -> do
Util.withWindow "test window" 0 0 Config.width Config.height ((fromIntegral (RGFW.unwrapRGFW_windowFlags_enum RGFW.RGFW_windowCenter)) .|. (fromIntegral (RGFW.unwrapRGFW_windowFlags_enum RGFW.RGFW_windowFloating))) $ \window -> do
surface :: Vk.SurfaceKHR <- alloca $ \surfacePtr -> do
_ <- RGFW.rGFW_window_createSurface_Vulkan window (coerce $ Vk.instanceHandle i) surfacePtr
return . unsafeCoerce =<< peek surfacePtr
(_, pdevs) <- Vk.enumeratePhysicalDevices i
(pdev, q) <- Util.pickPhysicalDevice pdevs surface
let gqueueIndex = fromIntegral $ head $ Util.getGraphicsQueues q
Vk.withDevice pdev (Config.device gqueueIndex) Nothing bracket $ \dev -> do
gqueue <- Vk.getDeviceQueue dev gqueueIndex 0
Vk.withCommandPool dev (Config.commandPool gqueueIndex) Nothing bracket $ \gpool -> do
swapchain <- Vk.createSwapchainKHR dev (Config.swapchain q surface) Nothing
(_, images) <- Vk.getSwapchainImagesKHR dev swapchain
Util.withImageViews dev (Config.imageViews images q) Nothing $ \imageViews -> do
Util.withSemaphores dev (V.fromList (take (fromIntegral Config.consts.framesInFlight) (repeat zero))) Nothing $ \sImageAcquired -> do
Util.withSemaphores dev (V.fromList (take (V.length images) (repeat zero))) Nothing $ \sRenderFinisheds -> do
Util.withFences dev (V.fromList (take (fromIntegral Config.consts.framesInFlight) (repeat ((zero :: Vk.FenceCreateInfo '[]) { Vk.flags = Vk.FENCE_CREATE_SIGNALED_BIT })))) Nothing $ \fences -> do
Vk.withCommandBuffers dev (Config.commandBuffer gpool) bracket $ \cbuffers -> do
rawVert <- BS.readFile Shaders.vertPath
rawFrag <- BS.readFile Shaders.fragPath
Util.withShaderModules dev (V.fromList [ zero { Vk.code = rawVert }, zero { Vk.code = rawFrag } ]) Nothing $ \mods -> do
let vertMod = V.head mods
let fragMod = V.head $ V.tail mods
Vk.withPipelineLayout dev (Config.pipelineLayout) Nothing bracket $ \pipelineLayout -> do
Vk.withGraphicsPipelines dev zero (V.singleton $ SomeStruct (Config.graphicsPipeline q vertMod fragMod pipelineLayout)) Nothing bracket $ \(_, pipelines) -> do
let pipeline = V.head pipelines
gameloop' dev q pipeline swapchain imageViews images cbuffers gqueue sImageAcquired sRenderFinisheds fences 0 window 0
gameloop' :: Vk.Device -> QueriedData -> Vk.Pipeline -> Vk.SwapchainKHR -> Vector Vk.ImageView -> Vector Vk.Image -> Vector Vk.CommandBuffer -> Vk.Queue -> Vector Vk.Semaphore -> Vector Vk.Semaphore -> Vector Vk.Fence -> Int -> Ptr RGFW.RGFW_window -> RGFW.RGFW_bool -> IO ()
gameloop' dev q pipeline swapchain imageViews images cbuffers queue sImageAcquireds sRenderFinisheds fences frameIndex window 0 = do
let cbuffer = (V.!) cbuffers frameIndex
sImageAcquired = (V.!) sImageAcquireds frameIndex
fence = V.singleton $ (V.!) fences frameIndex
_ <- Vk.waitForFences dev fence True 18446744073709551615
Vk.resetFences dev fence
(_, imageIndex) <- Vk.acquireNextImageKHR dev swapchain 18446744073709551615 sImageAcquired zero
let imageView = (V.!) imageViews $ fromIntegral imageIndex
image = (V.!) images $ fromIntegral imageIndex
sRenderFinished = (V.!) sRenderFinisheds $ fromIntegral imageIndex
Vk.resetCommandBuffer cbuffer zero
Vk.useCommandBuffer cbuffer ((zero :: Vk.CommandBufferBeginInfo '[]) { Vk.flags = Vk.COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }) $ do
Vk.cmdPipelineBarrier2 cbuffer $ Config.preRenderPipelineBarrier image
Vk.cmdUseRendering cbuffer (Config.rendering q imageView) $ do
Vk.cmdSetViewport cbuffer 0 $ Config.viewport q
Vk.cmdSetScissor cbuffer 0 $ Config.scissor q
Vk.cmdBindPipeline cbuffer Vk.PIPELINE_BIND_POINT_GRAPHICS pipeline
Vk.cmdDraw cbuffer 3 1 0 0
Vk.cmdPipelineBarrier2 cbuffer $ Config.postRenderPipelineBarrier image
Vk.queueSubmit2 queue (Config.submitQueue cbuffer sImageAcquired sRenderFinished) $ V.head fence
_ <- Vk.queuePresentKHR queue (Config.present swapchain imageIndex sRenderFinished)
RGFW.rGFW_pollEvents
gameloop' dev q pipeline swapchain imageViews images cbuffers queue sImageAcquireds sRenderFinisheds fences (mod (frameIndex + 1) (fromIntegral Config.consts.framesInFlight)) window =<< RGFW.rGFW_window_shouldClose window
gameloop' dev _ _ swapchain _ _ _ _ _ _ _ _ _ _ = do
Vk.deviceWaitIdle dev
Vk.destroySwapchainKHR dev swapchain Nothing
|