vulkan-init-sdl2 (empty) → 0.1.0.0
raw patch · 8 files changed
+320/−0 lines, 8 filesdep +basedep +bytestringdep +resourcetsetup-changed
Dependencies added: base, bytestring, resourcet, sdl2, text, vector, vulkan, vulkan-utils
Files
- LICENSE +30/−0
- Setup.hs +3/−0
- changelog.md +4/−0
- package.yaml +38/−0
- readme.md +5/−0
- src/Vulkan/Utils/Init/SDL2.hs +83/−0
- src/Vulkan/Utils/Init/SDL2/Window.hs +101/−0
- vulkan-init-sdl2.cabal +56/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright IC Rainbow (c) 2026++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of IC Rainbow nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple++main = defaultMain
+ changelog.md view
@@ -0,0 +1,4 @@+# Change Log++## [0.1.0.0]+- Initial release.
+ package.yaml view
@@ -0,0 +1,38 @@+name: vulkan-init-sdl2+version: "0.1.0.0"+synopsis: Vulkan initialization helpers for SDL2+category: Graphics+maintainer: IC Rainbow <aenor.realm@gmail.com>+license: BSD-3-Clause+license-file: LICENSE+github: haskell-game/vulkan+extra-source-files:+- readme.md+- changelog.md+- package.yaml++library:+ source-dirs: src+ dependencies:+ - base <5+ - bytestring+ - resourcet >= 1.2.4+ - sdl2 >= 2.5 && < 2.6+ - text+ - vector+ - vulkan >= 3.6.14 && < 3.28+ - vulkan-utils++ghc-options:+- -Wall++default-extensions:+- DerivingStrategies+- FlexibleContexts+- LambdaCase+- NamedFieldPuns+- OverloadedStrings+- PatternSynonyms+- RankNTypes+- RecordWildCards+- ScopedTypeVariables
+ readme.md view
@@ -0,0 +1,5 @@+# vulkan-init-sdl2++Vulkan initialization helpers for SDL2 windows. Provides the SDL-specific+glue around `vulkan-utils` so apps can build a Vulkan `Instance` and a+`SurfaceKHR` from an `SDL.Window` with a couple of calls.
+ src/Vulkan/Utils/Init/SDL2.hs view
@@ -0,0 +1,83 @@+{-| Vulkan initialization glue for SDL2 windows. Compose with+'Vulkan.Utils.Initialization.allocateVulkanInstance' (or just call+'allocateInstance' here) and the rest of @vulkan-utils@ to get a+ready-to-render setup.+-}+module Vulkan.Utils.Init.SDL2+ ( -- * Required extensions+ getRequiredInstanceExtensions+ , getRequiredDeviceExtensions++ -- * Surface+ , createSurface+ , destroySurface+ , allocateSurface++ -- * Instance+ , allocateInstance+ ) where++import Control.Monad.IO.Class (MonadIO, liftIO)+import Control.Monad.Trans.Resource (MonadResource, allocate)+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.Vector (Vector)+import qualified Data.Vector as V+import Foreign.Ptr (castPtr)+import qualified SDL+import qualified SDL.Video.Vulkan as SDL+import Vulkan.Core10+ ( ApplicationInfo+ , Instance+ , instanceHandle+ )+import Vulkan.Extensions.VK_KHR_surface+ ( SurfaceKHR (..)+ , destroySurfaceKHR+ )+import Vulkan.Extensions.VK_KHR_swapchain+ ( pattern KHR_SWAPCHAIN_EXTENSION_NAME+ )+import Vulkan.Requirement (InstanceRequirement)+import Vulkan.Utils.Initialization (allocateVulkanInstance)++-- | Vulkan instance extensions the SDL2 window requires for presentation.+getRequiredInstanceExtensions :: (MonadIO m) => SDL.Window -> m (Vector ByteString)+getRequiredInstanceExtensions w =+ liftIO $+ V.fromList <$> (traverse BS.packCString =<< SDL.vkGetInstanceExtensions w)++{- | Device extensions an SDL2-presenting application needs. Currently just+@VK_KHR_swapchain@.+-}+getRequiredDeviceExtensions :: [ByteString]+getRequiredDeviceExtensions = [KHR_SWAPCHAIN_EXTENSION_NAME]++-- | Create a 'SurfaceKHR' for the given SDL window.+createSurface :: Instance -> SDL.Window -> IO SurfaceKHR+createSurface inst w =+ SurfaceKHR <$> SDL.vkCreateSurface w (castPtr (instanceHandle inst))++-- | Destroy a 'SurfaceKHR' previously created with 'createSurface'.+destroySurface :: Instance -> SurfaceKHR -> IO ()+destroySurface inst s = destroySurfaceKHR inst s Nothing++-- | Allocate a surface in 'MonadResource', released with the resource scope.+allocateSurface :: (MonadResource m) => Instance -> SDL.Window -> m SurfaceKHR+allocateSurface inst w =+ snd <$> allocate (createSurface inst w) (destroySurface inst)++{- | Build a Vulkan 'Instance' wired up with the SDL window's required+extensions. Composes 'getRequiredInstanceExtensions' and+'Vulkan.Utils.Initialization.allocateVulkanInstance'.+-}+allocateInstance+ :: (MonadResource m)+ => SDL.Window+ -> Maybe ApplicationInfo+ -> [InstanceRequirement]+ -> [InstanceRequirement]+ -> m Instance+allocateInstance w appInfo reqs optReqs = do+ exts <- getRequiredInstanceExtensions w+ allocateVulkanInstance exts appInfo reqs optReqs
+ src/Vulkan/Utils/Init/SDL2/Window.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE TypeApplications #-}++{-| Convenience helpers for opening an SDL2 window suitable for Vulkan+rendering, polling for quit events, and querying the current drawable+size for swapchain recreation.++These wrap a small set of opinionated defaults — Vulkan graphics+context, resizable, high-DPI, hidden until the caller has the swapchain+ready — sufficient for examples and prototypes. Applications with+different needs should call SDL directly.+-}+module Vulkan.Utils.Init.SDL2.Window+ ( withSDL+ , createWindow+ , drawableSize+ , showWindow+ , shouldQuit+ , sdl2Adapter+ ) where++import Control.Monad (void)+import Control.Monad.IO.Class+import Control.Monad.Trans.Resource+import Data.Text (Text)+import qualified SDL+import qualified SDL.Video.Vulkan as SDL+import Vulkan.Core10 (Extent2D (..))+import qualified Vulkan.Utils.Init.SDL2 as Init+import Vulkan.Utils.WindowAdapter (WindowAdapter (..))++-- | Bring SDL up for the duration of the resource scope.+withSDL :: (MonadResource m) => m ()+withSDL = void $ allocate_ (SDL.initialize @[] [SDL.InitEvents]) SDL.quit++-- | Create an SDL2 window configured for Vulkan rendering.+createWindow+ :: (MonadResource m)+ => Text+ -- ^ Title+ -> Int+ -- ^ Width+ -> Int+ -- ^ Height+ -> m SDL.Window+createWindow title width height = do+ SDL.initialize @[] [SDL.InitVideo]+ _ <- allocate_ (SDL.vkLoadLibrary Nothing) SDL.vkUnloadLibrary+ (_, window) <-+ allocate+ ( SDL.createWindow+ title+ ( SDL.defaultWindow+ { SDL.windowInitialSize =+ SDL.V2+ (fromIntegral width)+ (fromIntegral height)+ , SDL.windowGraphicsContext = SDL.VulkanContext+ , SDL.windowResizable = True+ , SDL.windowHighDPI = True+ , SDL.windowVisible = False+ }+ )+ )+ SDL.destroyWindow+ pure window++-- | Current drawable size, suitable as the swapchain extent fallback.+drawableSize :: (MonadIO m) => SDL.Window -> m Extent2D+drawableSize win = do+ SDL.V2 w h <- SDL.vkGetDrawableSize win+ pure $ Extent2D (fromIntegral w) (fromIntegral h)++{- | Make the window visible. The window is created hidden so the swapchain+can be brought up first.+-}+showWindow :: (MonadIO m) => SDL.Window -> m ()+showWindow = SDL.showWindow++-- | The window's 'WindowAdapter', for backend-agnostic boot helpers.+sdl2Adapter :: (MonadResource m) => SDL.Window -> WindowAdapter m+sdl2Adapter w =+ WindowAdapter+ { waAllocateInstance = Init.allocateInstance w+ , waAllocateSurface = \i -> Init.allocateSurface i w+ , waDrawableSize = drawableSize w+ }++{- | Poll the event queue and report whether the user requested to quit+(window close, Q, or Escape). The window argument is unused — SDL's event+queue is global — but kept for symmetry with the GLFW backend.+-}+shouldQuit :: (MonadIO m) => SDL.Window -> m Bool+shouldQuit _ = any isQuitEvent <$> SDL.pollEvents+ where+ isQuitEvent :: SDL.Event -> Bool+ isQuitEvent = \case+ (SDL.Event _ SDL.QuitEvent) -> True+ SDL.Event _ (SDL.KeyboardEvent (SDL.KeyboardEventData _ SDL.Released False (SDL.Keysym _ code _)))+ | code == SDL.KeycodeQ || code == SDL.KeycodeEscape ->+ True+ _ -> False
+ vulkan-init-sdl2.cabal view
@@ -0,0 +1,56 @@+cabal-version: 2.2++-- This file has been generated from package.yaml by hpack version 0.39.6.+--+-- see: https://github.com/sol/hpack++name: vulkan-init-sdl2+version: 0.1.0.0+synopsis: Vulkan initialization helpers for SDL2+category: Graphics+homepage: https://github.com/haskell-game/vulkan#readme+bug-reports: https://github.com/haskell-game/vulkan/issues+maintainer: IC Rainbow <aenor.realm@gmail.com>+license: BSD-3-Clause+license-file: LICENSE+build-type: Simple+extra-source-files:+ readme.md+ changelog.md+ package.yaml++source-repository head+ type: git+ location: https://github.com/haskell-game/vulkan++library+ exposed-modules:+ Vulkan.Utils.Init.SDL2+ Vulkan.Utils.Init.SDL2.Window+ other-modules:+ Paths_vulkan_init_sdl2+ autogen-modules:+ Paths_vulkan_init_sdl2+ hs-source-dirs:+ src+ default-extensions:+ DerivingStrategies+ FlexibleContexts+ LambdaCase+ NamedFieldPuns+ OverloadedStrings+ PatternSynonyms+ RankNTypes+ RecordWildCards+ ScopedTypeVariables+ ghc-options: -Wall+ build-depends:+ base <5+ , bytestring+ , resourcet >=1.2.4+ , sdl2 ==2.5.*+ , text+ , vector+ , vulkan >=3.6.14 && <3.28+ , vulkan-utils+ default-language: Haskell2010