diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for try-vulkan-core
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Yoshikuni Jujo (c) 2022
+
+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 Yoshikuni Jujo 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.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# gpu-vulkan-core
+
+See package gpu-vulkan
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/gpu-vulkan-core.cabal b/gpu-vulkan-core.cabal
new file mode 100644
--- /dev/null
+++ b/gpu-vulkan-core.cabal
@@ -0,0 +1,111 @@
+cabal-version: 1.12
+
+-- This file has been generated from package.yaml by hpack version 0.37.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           gpu-vulkan-core
+version:        0.1.0.7
+synopsis:       Thin wrapper for Vulkan API
+description:    Please see the README on GitHub at <https://github.com/YoshikuniJujo/gpu-vulkan-core#readme>
+category:       GPU
+homepage:       https://github.com/githubuser/gpu-vulkan-core#readme
+bug-reports:    https://github.com/githubuser/gpu-vulkan-core/issues
+author:         Yoshikuni Jujo
+maintainer:     example@example.com
+copyright:      2022 Yoshikuni Jujo
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+extra-source-files:
+    README.md
+    ChangeLog.md
+
+source-repository head
+  type: git
+  location: https://github.com/githubuser/gpu-vulkan-core
+
+library
+  exposed-modules:
+      Gpu.Vulkan.AllocationCallbacks.Core
+      Gpu.Vulkan.Attachment.Core
+      Gpu.Vulkan.Buffer.Core
+      Gpu.Vulkan.BufferView.Core
+      Gpu.Vulkan.Cmd.Core
+      Gpu.Vulkan.CommandBuffer.Core
+      Gpu.Vulkan.CommandPool.Core
+      Gpu.Vulkan.Component.Core
+      Gpu.Vulkan.Core
+      Gpu.Vulkan.Descriptor.Core
+      Gpu.Vulkan.DescriptorPool.Core
+      Gpu.Vulkan.DescriptorSet.Core
+      Gpu.Vulkan.DescriptorSetLayout.Core
+      Gpu.Vulkan.DescriptorSetLayout.BindingFlags.Core
+      Gpu.Vulkan.Device.Core
+      Gpu.Vulkan.Fence.Core
+      Gpu.Vulkan.Framebuffer.Core
+      Gpu.Vulkan.Image.Core
+      Gpu.Vulkan.ImageView.Core
+      Gpu.Vulkan.Instance.Core
+      Gpu.Vulkan.Memory.Core
+      Gpu.Vulkan.PhysicalDevice.Core
+      Gpu.Vulkan.PhysicalDevice.Struct.Core
+      Gpu.Vulkan.Pipeline.ColorBlendAttachment.Core
+      Gpu.Vulkan.Pipeline.ColorBlendState.Core
+      Gpu.Vulkan.Pipeline.Compute.Core
+      Gpu.Vulkan.Pipeline.Core
+      Gpu.Vulkan.Pipeline.DepthStencilState.Core
+      Gpu.Vulkan.Pipeline.DynamicState.Core
+      Gpu.Vulkan.Pipeline.Graphics.Core
+      Gpu.Vulkan.Pipeline.InputAssemblyState.Core
+      Gpu.Vulkan.Pipeline.MultisampleState.Core
+      Gpu.Vulkan.Pipeline.RasterizationState.Core
+      Gpu.Vulkan.Pipeline.ShaderStage.Core
+      Gpu.Vulkan.Pipeline.TessellationState.Core
+      Gpu.Vulkan.Pipeline.VertexInputState.Core
+      Gpu.Vulkan.Pipeline.ViewportState.Core
+      Gpu.Vulkan.PipelineCache.Core
+      Gpu.Vulkan.PipelineLayout.Core
+      Gpu.Vulkan.PushConstant.Core
+      Gpu.Vulkan.QueryPool.Core
+      Gpu.Vulkan.Queue.Core
+      Gpu.Vulkan.QueueFamily.Core
+      Gpu.Vulkan.RenderPass.Core
+      Gpu.Vulkan.Sampler.Core
+      Gpu.Vulkan.Semaphore.Core
+      Gpu.Vulkan.ShaderModule.Core
+      Gpu.Vulkan.Specialization.Core
+      Gpu.Vulkan.Subpass.Core
+      Gpu.Vulkan.VertexInput.Core
+      Gpu.Vulkan.TypeSynonyms.Core
+  other-modules:
+      Data.Text.Tools
+      Paths_gpu_vulkan_core
+  hs-source-dirs:
+      src
+  pkgconfig-depends:
+      vulkan
+  build-depends:
+      base >=4.7 && <5
+    , c-enum <1
+    , c-struct <1
+    , nowdoc <1
+    , text <3
+  default-language: Haskell2010
+
+test-suite gpu-vulkan-core-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_gpu_vulkan_core
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , c-enum <1
+    , c-struct <1
+    , gpu-vulkan-core
+    , nowdoc <1
+    , text <3
+  default-language: Haskell2010
diff --git a/src/Data/Text/Tools.hs b/src/Data/Text/Tools.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Text/Tools.hs
@@ -0,0 +1,32 @@
+{-# LANGUAGE BlockArguments, TupleSections #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Data.Text.Tools (pokeText, cstringToText) where
+
+import Foreign.Ptr
+import Foreign.Marshal.Utils
+import Foreign.Storable
+import Foreign.C.Types
+import Foreign.C.String
+
+import qualified Data.Text as Txt
+import qualified Data.Text.Foreign as Txt
+
+pokeText :: Int -> CString -> Txt.Text -> IO ()
+pokeText mx dst t = Txt.withCStringLen t \(src, ln) -> do
+	let	ln' = min ln (mx - 1)
+	copyBytes dst src ln'
+	poke (dst `plusPtr` ln' :: Ptr CChar) 0
+
+cstringToText :: CString -> IO Txt.Text
+cstringToText cs = Txt.peekCStringLen =<< cstringToCStringLen cs
+
+cstringToCStringLen :: CString -> IO CStringLen
+cstringToCStringLen cs = (cs ,) <$> cstringLength cs
+
+cstringLength :: CString -> IO Int
+cstringLength pc = do
+	c <- peek pc
+	case c of
+		0 -> pure 0
+		_ -> (+ 1) <$> cstringLength (pc `plusPtr` 1)
diff --git a/src/Gpu/Vulkan/AllocationCallbacks/Core.hsc b/src/Gpu/Vulkan/AllocationCallbacks/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/AllocationCallbacks/Core.hsc
@@ -0,0 +1,147 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.AllocationCallbacks.Core (
+	-- * TYPE
+	A, pattern A,
+	aPUserData, aPfnAllocation, aPfnReallocation, aPfnFree,
+	aPfnInternalAllocation, aPfnInternalFree,
+
+	-- * FUNCTIONS
+	-- ** ALLOCATION
+	wrapAllocationFunction,
+	FnAllocationFunction, PfnAllocationFunction,
+
+	-- ** REALLOCATION
+	wrapReallocationFunction,
+	FnReallocationFunction, PfnReallocationFunction,
+	
+	-- ** FREE
+	wrapFreeFunction,
+	FnFreeFunction, PfnFreeFunction,
+	
+	-- * INTERNAL NOTIFICATION
+	-- ** ALLOCATION
+	wrapInternalAllocationNotification,
+	FnInternalAllocationNotification, PfnInternalAllocationNotification,
+	
+	-- ** FREE
+	wrapInternalFreeNotification,
+	FnInternalFreeNotification, PfnInternalFreeNotification
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+---------------------------------------------------------------------------
+-- ALLOCATION FUNCTION
+-- REALLOCATION FUNCTION
+-- FREE FUNCTION
+-- INTERNAL ALLOCATION NOTIFICATION
+-- INTERNAL FREE NOTIFICATION
+---------------------------------------------------------------------------
+
+-- * ALLOCATION FUNCTION
+
+type FnAllocationFunction a = Ptr a -> #{type size_t} ->
+	#{type size_t} -> #{type VkSystemAllocationScope} -> IO (Ptr ())
+
+type PfnAllocationFunction = FunPtr (FnAllocationFunction ())
+
+wrapAllocationFunction :: FnAllocationFunction a -> IO PfnAllocationFunction
+wrapAllocationFunction = wrapAllocationFunctionGen . (. castPtr)
+
+foreign import ccall "wrapper" wrapAllocationFunctionGen ::
+	FnAllocationFunction () -> IO PfnAllocationFunction
+
+-- * REALLOCATION FUNCTION
+
+type FnReallocationFunction a = Ptr a -> Ptr () -> #{type size_t} ->
+	#{type size_t} -> #{type VkSystemAllocationScope} -> IO (Ptr ())
+
+type PfnReallocationFunction = FunPtr (FnReallocationFunction ())
+
+wrapReallocationFunction ::
+	FnReallocationFunction a -> IO PfnReallocationFunction
+wrapReallocationFunction = wrapReallocationFunctionGen . (. castPtr)
+
+foreign import ccall "wrapper" wrapReallocationFunctionGen ::
+	FnReallocationFunction () -> IO PfnReallocationFunction
+
+-- * FREE FUNCTION
+
+type FnFreeFunction a = Ptr a -> Ptr () -> IO ()
+
+type PfnFreeFunction = FunPtr (FnFreeFunction ())
+
+wrapFreeFunction :: FnFreeFunction a -> IO PfnFreeFunction
+wrapFreeFunction = wrapFreeFunctionGen . (. castPtr)
+
+foreign import ccall "wrapper" wrapFreeFunctionGen ::
+	FnFreeFunction () -> IO (PfnFreeFunction)
+
+-- * INTERNAL ALLOCATION NOTIFICATION
+
+type FnInternalAllocationNotification a = Ptr a -> #{type size_t} ->
+	#{type VkInternalAllocationType} -> #{type VkSystemAllocationScope} ->
+	IO ()
+
+type PfnInternalAllocationNotification =
+	FunPtr (FnInternalAllocationNotification ())
+
+wrapInternalAllocationNotification ::
+	FnInternalAllocationNotification a ->
+	IO PfnInternalAllocationNotification
+wrapInternalAllocationNotification =
+	wrapInternalAllocationNotificationGen . (. castPtr)
+
+foreign import ccall "wrapper" wrapInternalAllocationNotificationGen ::
+	FnInternalAllocationNotification () ->
+	IO PfnInternalAllocationNotification
+
+-- * INTERNAL FREE NOTIFICATION
+
+type FnInternalFreeNotification a = Ptr a -> #{type size_t} ->
+	#{type VkInternalAllocationType} -> #{type VkSystemAllocationScope} ->
+	IO ()
+
+type PfnInternalFreeNotification = FunPtr (FnInternalFreeNotification ())
+
+wrapInternalFreeNotification ::
+	FnInternalFreeNotification a -> IO PfnInternalFreeNotification
+wrapInternalFreeNotification = wrapInternalFreeNotificationGen . (. castPtr)
+
+foreign import ccall "wrapper" wrapInternalFreeNotificationGen ::
+	FnInternalFreeNotification () -> IO PfnInternalFreeNotification
+
+-- * ALLOCATION CALLBACKS
+
+struct "A" #{size VkAllocationCallbacks}
+		#{alignment VkAllocationCallbacks} [
+	("pUserData", ''PtrVoid,
+		[| #{peek VkAllocationCallbacks, pUserData} |],
+		[| #{poke VkAllocationCallbacks, pUserData} |]),
+	("pfnAllocation", ''PfnAllocationFunction,
+		[| #{peek VkAllocationCallbacks, pfnAllocation} |],
+		[| #{poke VkAllocationCallbacks, pfnAllocation} |]),
+	("pfnReallocation", ''PfnReallocationFunction,
+		[| #{peek VkAllocationCallbacks, pfnReallocation} |],
+		[| #{poke VkAllocationCallbacks, pfnReallocation} |]),
+	("pfnFree", ''PfnFreeFunction,
+		[| #{peek VkAllocationCallbacks, pfnFree} |],
+		[| #{poke VkAllocationCallbacks, pfnFree} |]),
+	("pfnInternalAllocation", ''PfnInternalAllocationNotification,
+		[| #{peek VkAllocationCallbacks, pfnInternalAllocation} |],
+		[| #{poke VkAllocationCallbacks, pfnInternalAllocation} |]),
+	("pfnInternalFree", ''PfnInternalFreeNotification,
+		[| #{peek VkAllocationCallbacks, pfnInternalFree} |],
+		[| #{poke VkAllocationCallbacks, pfnInternalFree} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/Attachment/Core.hsc b/src/Gpu/Vulkan/Attachment/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Attachment/Core.hsc
@@ -0,0 +1,73 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Attachment.Core (
+
+	-- * DESCRIPTION
+
+	Description, PtrDescription, pattern Description,
+	descriptionFlags, descriptionFormat, descriptionSamples,
+	descriptionLoadOp, descriptionStoreOp,
+	descriptionStencilLoadOp, descriptionStencilStoreOp,
+	descriptionInitialLayout, descriptionFinalLayout,
+
+	-- * REFERENCE
+
+	Reference, PtrReference, pattern Reference,
+	referenceAttachment, referenceLayout
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+struct "Description" #{size VkAttachmentDescription}
+		#{alignment VkAttachmentDescription} [
+	("flags", ''#{type VkAttachmentDescriptionFlags},
+		[| #{peek VkAttachmentDescription, flags} |],
+		[| #{poke VkAttachmentDescription, flags} |]),
+	("format", ''#{type VkFormat},
+		[| #{peek VkAttachmentDescription, format} |],
+		[| #{poke VkAttachmentDescription, format} |]),
+	("samples", ''#{type VkSampleCountFlagBits},
+		[| #{peek VkAttachmentDescription, samples} |],
+		[| #{poke VkAttachmentDescription, samples} |]),
+	("loadOp", ''#{type VkAttachmentLoadOp},
+		[| #{peek VkAttachmentDescription, loadOp} |],
+		[| #{poke VkAttachmentDescription, loadOp} |]),
+	("storeOp", ''#{type VkAttachmentStoreOp},
+		[| #{peek VkAttachmentDescription, storeOp} |],
+		[| #{poke VkAttachmentDescription, storeOp} |]),
+	("stencilLoadOp", ''#{type VkAttachmentLoadOp},
+		[| #{peek VkAttachmentDescription, stencilLoadOp} |],
+		[| #{poke VkAttachmentDescription, stencilLoadOp} |]),
+	("stencilStoreOp", ''#{type VkAttachmentStoreOp},
+		[| #{peek VkAttachmentDescription, stencilStoreOp} |],
+		[| #{poke VkAttachmentDescription, stencilStoreOp} |]),
+	("initialLayout", ''#{type VkImageLayout},
+		[| #{peek VkAttachmentDescription, initialLayout} |],
+		[| #{poke VkAttachmentDescription, initialLayout} |]),
+	("finalLayout", ''#{type VkImageLayout},
+		[| #{peek VkAttachmentDescription, finalLayout} |],
+		[| #{poke VkAttachmentDescription, finalLayout} |]) ]
+	[''Show, ''Storable]
+
+type PtrDescription = Ptr Description
+
+struct "Reference" #{size VkAttachmentReference}
+		#{alignment VkAttachmentReference} [
+	("attachment", ''#{type uint32_t},
+		[| #{peek VkAttachmentReference, attachment} |],
+		[| #{poke VkAttachmentReference, attachment} |]),
+	("layout", ''#{type VkImageLayout},
+		[| #{peek VkAttachmentReference, layout} |],
+		[| #{poke VkAttachmentReference, layout} |]) ]
+	[''Show, ''Storable]
+
+type PtrReference = Ptr Reference
diff --git a/src/Gpu/Vulkan/Buffer/Core.hsc b/src/Gpu/Vulkan/Buffer/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Buffer/Core.hsc
@@ -0,0 +1,161 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Buffer.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, getMemoryRequirements, bindMemory, B,
+	CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags, createInfoSize,
+	createInfoUsage, createInfoSharingMode,
+	createInfoQueueFamilyIndexCount, createInfoPQueueFamilyIndices,
+
+	-- * COPY
+
+	Copy, pattern Copy,
+	copySrcOffset, copyDstOffset, copySize,
+
+	ImageCopy, pattern ImageCopy,
+	imageCopyBufferOffset,
+	imageCopyBufferRowLength, imageCopyBufferImageHeight,
+	imageCopyImageSubresource, imageCopyImageOffset, imageCopyImageExtent,
+
+	-- * MEMORY BARRIER
+
+	MemoryBarrier, pattern MemoryBarrier,
+	memoryBarrierSType, memoryBarrierPNext,
+	memoryBarrierSrcAccessMask, memoryBarrierDstAccessMask,
+	memoryBarrierSrcQueueFamilyIndex, memoryBarrierDstQueueFamilyIndex,
+	memoryBarrierBuffer, memoryBarrierOffset, memoryBarrierSize
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.Core
+import Gpu.Vulkan.TypeSynonyms.Core
+import Gpu.Vulkan.AllocationCallbacks.Core qualified as AllocationCallbacks
+import Gpu.Vulkan.Device.Core qualified as Device
+import Gpu.Vulkan.Memory.Core qualified as Memory
+import Gpu.Vulkan.Image.Core qualified as Image
+
+#include <vulkan/vulkan.h>
+
+struct "CreateInfo" #{size VkBufferCreateInfo} #{alignment VkBufferCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkBufferCreateInfo, sType} p
+			(#{const VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO} ::
+				#{type VkStructureType}) |]),
+	("pNext", ''PtrVoid, [| #{peek VkBufferCreateInfo, pNext} |],
+		[| #{poke VkBufferCreateInfo, pNext} |]),
+	("flags", ''#{type VkBufferCreateFlags},
+		[| #{peek VkBufferCreateInfo, flags} |],
+		[| #{poke VkBufferCreateInfo, flags} |]),
+	("size", ''#{type VkDeviceSize},
+		[| #{peek VkBufferCreateInfo, size} |],
+		[| #{poke VkBufferCreateInfo, size} |]),
+	("usage", ''#{type VkBufferUsageFlags},
+		[| #{peek VkBufferCreateInfo, usage} |],
+		[| #{poke VkBufferCreateInfo, usage} |]),
+	("sharingMode", ''#{type VkSharingMode},
+		[| #{peek VkBufferCreateInfo, sharingMode} |],
+		[| #{poke VkBufferCreateInfo, sharingMode} |]),
+	("queueFamilyIndexCount", ''#{type uint32_t},
+		[| #{peek VkBufferCreateInfo, queueFamilyIndexCount} |],
+		[| #{poke VkBufferCreateInfo, queueFamilyIndexCount} |]),
+	("pQueueFamilyIndices", ''PtrUint32T,
+		[| #{peek VkBufferCreateInfo, pQueueFamilyIndices} |],
+		[| #{poke VkBufferCreateInfo, pQueueFamilyIndices} |]) ]
+	[''Show, ''Storable]
+
+data BTag
+type B = Ptr BTag
+
+foreign import ccall "vkCreateBuffer" create ::
+	Device.D -> Ptr CreateInfo ->  Ptr AllocationCallbacks.A -> Ptr B ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyBuffer" destroy ::
+	Device.D -> B -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkGetBufferMemoryRequirements" getMemoryRequirements ::
+	Device.D -> B -> Ptr Memory.Requirements -> IO ()
+
+foreign import ccall "vkBindBufferMemory" bindMemory ::
+	Device.D -> B -> Memory.M -> #{type VkDeviceSize} ->
+	IO #{type VkResult}
+
+struct "Copy" #{size VkBufferCopy} #{alignment VkBufferCopy} [
+	("srcOffset", ''#{type VkDeviceSize},
+		[| #{peek VkBufferCopy, srcOffset} |],
+		[| #{poke VkBufferCopy, srcOffset} |]),
+	("dstOffset", ''#{type VkDeviceSize},
+		[| #{peek VkBufferCopy, dstOffset} |],
+		[| #{poke VkBufferCopy, dstOffset} |]),
+	("size", ''#{type VkDeviceSize},
+		[| #{peek VkBufferCopy, size} |],
+		[| #{poke VkBufferCopy, size} |]) ]
+	[''Show, ''Storable]
+
+mbType :: #{type VkStructureType}
+mbType = #{const VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER}
+
+struct "MemoryBarrier" #{size VkBufferMemoryBarrier}
+		#{alignment VkBufferMemoryBarrier} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkBufferMemoryBarrier, sType} p mbType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkBufferMemoryBarrier, pNext} |],
+		[| #{poke VkBufferMemoryBarrier, pNext} |]),
+	("srcAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkBufferMemoryBarrier, srcAccessMask} |],
+		[| #{poke VkBufferMemoryBarrier, srcAccessMask} |]),
+	("dstAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkBufferMemoryBarrier, dstAccessMask} |],
+		[| #{poke VkBufferMemoryBarrier, dstAccessMask} |]),
+	("srcQueueFamilyIndex", ''#{type uint32_t},
+		[| #{peek VkBufferMemoryBarrier, srcQueueFamilyIndex} |],
+		[| #{poke VkBufferMemoryBarrier, srcQueueFamilyIndex} |]),
+	("dstQueueFamilyIndex", ''#{type uint32_t},
+		[| #{peek VkBufferMemoryBarrier, dstQueueFamilyIndex} |],
+		[| #{poke VkBufferMemoryBarrier, dstQueueFamilyIndex} |]),
+	("buffer", ''B,
+		[| #{peek VkBufferMemoryBarrier, buffer} |],
+		[| #{poke VkBufferMemoryBarrier, buffer} |]),
+	("offset", ''#{type VkDeviceSize},
+		[| #{peek VkBufferMemoryBarrier, offset} |],
+		[| #{poke VkBufferMemoryBarrier, offset} |]),
+	("size", ''#{type VkDeviceSize},
+		[| #{peek VkBufferMemoryBarrier, size} |],
+		[| #{poke VkBufferMemoryBarrier, size} |]) ]
+	[''Show, ''Storable]
+
+struct "ImageCopy" #{size VkBufferImageCopy} #{alignment VkBufferImageCopy} [
+	("bufferOffset", ''#{type VkDeviceSize},
+		[| #{peek VkBufferImageCopy, bufferOffset} |],
+		[| #{poke VkBufferImageCopy, bufferOffset} |]),
+	("bufferRowLength", ''#{type uint32_t},
+		[| #{peek VkBufferImageCopy, bufferRowLength} |],
+		[| #{poke VkBufferImageCopy, bufferRowLength} |]),
+	("bufferImageHeight", ''#{type uint32_t},
+		[| #{peek VkBufferImageCopy, bufferImageHeight} |],
+		[| #{poke VkBufferImageCopy, bufferImageHeight} |]),
+	("imageSubresource", ''Image.SubresourceLayers,
+		[| #{peek VkBufferImageCopy, imageSubresource} |],
+		[| #{poke VkBufferImageCopy, imageSubresource} |]),
+	("imageOffset", ''Offset3d,
+		[| #{peek VkBufferImageCopy, imageOffset} |],
+		[| #{poke VkBufferImageCopy, imageOffset} |]),
+	("imageExtent", ''Extent3d,
+		[| #{peek VkBufferImageCopy, imageExtent} |],
+		[| #{poke VkBufferImageCopy, imageExtent} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/BufferView/Core.hsc b/src/Gpu/Vulkan/BufferView/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/BufferView/Core.hsc
@@ -0,0 +1,67 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.BufferView.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, B, PtrB,
+	CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoBuffer, createInfoFormat, createInfoOffset, createInfoRange
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.Buffer.Core as Buffer
+
+#include <vulkan/vulkan.h>
+
+stype :: #{type VkStructureType}
+stype = #{const VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO}
+
+struct "CreateInfo" #{size VkBufferViewCreateInfo}
+		#{alignment VkBufferViewCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkBufferViewCreateInfo, sType} p stype |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkBufferViewCreateInfo, pNext} |],
+		[| #{poke VkBufferViewCreateInfo, pNext} |]),
+	("flags", ''#{type VkBufferViewCreateFlags},
+		[| #{peek VkBufferViewCreateInfo, flags} |],
+		[| #{poke VkBufferViewCreateInfo, flags} |]),
+	("buffer", ''Buffer.B,
+		[| #{peek VkBufferViewCreateInfo, buffer} |],
+		[| #{poke VkBufferViewCreateInfo, buffer} |]),
+	("format", ''#{type VkFormat},
+		[| #{peek VkBufferViewCreateInfo, format} |],
+		[| #{poke VkBufferViewCreateInfo, format} |]),
+	("offset", ''#{type VkDeviceSize},
+		[| #{peek VkBufferViewCreateInfo, offset} |],
+		[| #{poke VkBufferViewCreateInfo, offset} |]),
+	("range", ''#{type VkDeviceSize},
+		[| #{peek VkBufferViewCreateInfo, range} |],
+		[| #{poke VkBufferViewCreateInfo, range} |]) ]
+	[''Show, ''Storable]
+
+data BTag
+type B = Ptr BTag
+
+type PtrB = Ptr B
+
+foreign import ccall "vkCreateBufferView" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> PtrB ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyBufferView" destroy ::
+	Device.D -> B -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Cmd/Core.hsc b/src/Gpu/Vulkan/Cmd/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Cmd/Core.hsc
@@ -0,0 +1,128 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Cmd.Core (
+
+	-- * BEGIN AND END RENDER PASS
+
+	beginRenderPass, endRenderPass,
+
+	-- * DRAW AND DISPATCH
+
+	draw, drawIndexed, dispatch,
+
+	-- * BIND
+
+	bindPipeline, bindVertexBuffers, bindIndexBuffer,
+	bindDescriptorSets,
+	pushConstants,
+
+	-- * COPY BUFFER AND IMAGE
+
+	copyBuffer, copyBufferToImage, copyImageToBuffer, blitImage,
+
+	-- * PIPELINE BARRIER
+
+	pipelineBarrier,
+
+	-- * QUERY
+
+	beginQuery, endQuery, resetQueryPool,
+	writeTimestamp,
+
+	) where
+
+import Foreign.Ptr
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.RenderPass.Core as RenderPass
+import qualified Gpu.Vulkan.Pipeline.Core as Pipeline
+import qualified Gpu.Vulkan.CommandBuffer.Core as CommandBuffer
+import qualified Gpu.Vulkan.Buffer.Core as Buffer
+import qualified Gpu.Vulkan.PipelineLayout.Core as Pipeline.Layout
+import qualified Gpu.Vulkan.DescriptorSet.Core as DscSet
+import qualified Gpu.Vulkan.Memory.Core as Memory
+import qualified Gpu.Vulkan.Image.Core as Image
+
+import Gpu.Vulkan.QueryPool.Core as QueryPool
+
+#include <vulkan/vulkan.h>
+
+foreign import ccall "vkCmdBeginRenderPass" beginRenderPass ::
+	CommandBuffer.C -> Ptr RenderPass.BeginInfo ->
+	#{type VkSubpassContents} -> IO ()
+
+foreign import ccall "vkCmdBindPipeline" bindPipeline ::
+	CommandBuffer.C -> #{type VkPipelineBindPoint} -> Pipeline.P -> IO ()
+
+foreign import ccall "vkCmdDraw" draw ::
+	CommandBuffer.C -> #{type uint32_t} -> #{type uint32_t} ->
+	#{type uint32_t} -> #{type uint32_t} -> IO ()
+
+foreign import ccall "vkCmdDrawIndexed" drawIndexed ::
+	CommandBuffer.C -> #{type uint32_t} -> #{type uint32_t} ->
+	#{type uint32_t} -> #{type int32_t} -> #{type uint32_t} -> IO ()
+
+foreign import ccall "vkCmdEndRenderPass" endRenderPass ::
+	CommandBuffer.C -> IO ()
+
+foreign import ccall "vkCmdBindVertexBuffers" bindVertexBuffers ::
+	CommandBuffer.C -> #{type uint32_t} -> #{type uint32_t} ->
+	Ptr Buffer.B -> Ptr #{type VkDeviceSize} -> IO ()
+
+foreign import ccall "vkCmdCopyBuffer" copyBuffer ::
+	CommandBuffer.C -> Buffer.B -> Buffer.B -> #{type uint32_t} ->
+	Ptr Buffer.Copy -> IO ()
+
+foreign import ccall "vkCmdBindIndexBuffer" bindIndexBuffer ::
+	CommandBuffer.C -> Buffer.B -> #{type VkDeviceSize} ->
+	#{type VkIndexType} -> IO ()
+
+foreign import ccall "vkCmdBindDescriptorSets" bindDescriptorSets ::
+	CommandBuffer.C -> #{type VkPipelineBindPoint} -> Pipeline.Layout.P ->
+	#{type uint32_t} -> #{type uint32_t} -> Ptr DscSet.D ->
+	#{type uint32_t} -> Ptr #{type uint32_t} -> IO ()
+
+foreign import ccall "vkCmdPipelineBarrier" pipelineBarrier ::
+	CommandBuffer.C ->
+	#{type VkPipelineStageFlags} -> #{type VkPipelineStageFlags} ->
+	#{type VkDependencyFlags} ->
+	#{type uint32_t} -> Ptr Memory.Barrier ->
+	#{type uint32_t} -> Ptr Buffer.MemoryBarrier ->
+	#{type uint32_t} -> Ptr Image.MemoryBarrier -> IO ()
+
+foreign import ccall "vkCmdCopyBufferToImage" copyBufferToImage ::
+	CommandBuffer.C -> Buffer.B -> Image.I -> #{type VkImageLayout} ->
+	#{type uint32_t} -> Ptr Buffer.ImageCopy -> IO ()
+
+foreign import ccall "vkCmdCopyImageToBuffer" copyImageToBuffer ::
+	CommandBuffer.C -> Image.I -> #{type VkImageLayout} -> Buffer.B ->
+	#{type uint32_t} -> Ptr Buffer.ImageCopy -> IO ()
+
+foreign import ccall "vkCmdBlitImage" blitImage ::
+	CommandBuffer.C ->
+	Image.I -> #{type VkImageLayout} -> Image.I -> #{type VkImageLayout} ->
+	#{type uint32_t} -> Ptr Image.Blit -> #{type VkFilter} -> IO ()
+
+foreign import ccall "vkCmdDispatch" dispatch ::
+	CommandBuffer.C ->
+	#{type uint32_t} -> #{type uint32_t} -> #{type uint32_t} -> IO ()
+
+foreign import ccall "vkCmdPushConstants" pushConstants ::
+	CommandBuffer.C -> Pipeline.Layout.P -> #{type VkShaderStageFlags} ->
+	#{type uint32_t} -> #{type uint32_t} -> Ptr () -> IO ()
+
+foreign import ccall "vkCmdResetQueryPool" resetQueryPool ::
+	CommandBuffer.C -> QueryPool.Q ->
+	#{type uint32_t} -> #{type uint32_t} -> IO ()
+
+foreign import ccall "vkCmdBeginQuery" beginQuery ::
+	CommandBuffer.C -> QueryPool.Q -> #{type uint32_t} ->
+	#{type VkQueryControlFlags} -> IO ()
+
+foreign import ccall "vkCmdEndQuery" endQuery ::
+	CommandBuffer.C -> QueryPool.Q -> #{type uint32_t} -> IO ()
+
+foreign import ccall "vkCmdWriteTimestamp" writeTimestamp ::
+	CommandBuffer.C -> #{type VkPipelineStageFlagBits} -> QueryPool.Q ->
+	#{type uint32_t} -> IO ()
diff --git a/src/Gpu/Vulkan/CommandBuffer/Core.hs-boot b/src/Gpu/Vulkan/CommandBuffer/Core.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/CommandBuffer/Core.hs-boot
@@ -0,0 +1,9 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.CommandBuffer.Core (C, PtrC) where
+
+import Foreign.Ptr
+
+data CTag
+type C = Ptr CTag
+type PtrC = Ptr C
diff --git a/src/Gpu/Vulkan/CommandBuffer/Core.hsc b/src/Gpu/Vulkan/CommandBuffer/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/CommandBuffer/Core.hsc
@@ -0,0 +1,137 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.CommandBuffer.Core (
+
+	-- * ALLOCATE AND FREE
+
+	allocateCs, freeCs, C, PtrC,
+	AllocateInfo, pattern AllocateInfo,
+	allocateInfoSType, allocateInfoPNext, allocateInfoCommandPool,
+	allocateInfoLevel, levelPrimary, allocateInfoCommandBufferCount,
+
+	-- * BEGIN, END AND RESET
+	begin, end, reset,
+	BeginInfo, pattern BeginInfo,
+	beginInfoSType, beginInfoPNext, beginInfoFlags,
+	beginInfoPInheritanceInfo,
+
+	-- ** INHERITANCE INFO
+	InheritanceInfo, pattern InheritanceInfo,
+	inheritanceInfoSType, inheritanceInfoPNext,
+	inheritanceInfoRenderPass, inheritanceInfoSubpass,
+	inheritanceInfoFramebuffer, inheritanceInfoOcclusionQueryEnable,
+	inheritanceInfoQueryFlags, inheritanceInfoPipelineStatistics
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.RenderPass.Core as RenderPass
+import qualified Gpu.Vulkan.Framebuffer.Core as Framebuffer
+import qualified Gpu.Vulkan.CommandPool.Core as CommandPool
+
+#include <vulkan/vulkan.h>
+
+sTypeA, sTypeB, sTypeI :: #{type VkStructureType}
+sTypeA = #{const VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO}
+sTypeB = #{const VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}
+sTypeI = #{const VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO}
+
+struct "AllocateInfo" #{size VkCommandBufferAllocateInfo}
+		#{alignment VkCommandBufferAllocateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkCommandBufferAllocateInfo, sType}
+			p sTypeA |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkCommandBufferAllocateInfo, pNext} |],
+		[| #{poke VkCommandBufferAllocateInfo, pNext} |]),
+	("commandPool", ''CommandPool.C,
+		[| #{peek VkCommandBufferAllocateInfo, commandPool} |],
+		[| #{poke VkCommandBufferAllocateInfo, commandPool} |]),
+	("level", ''#{type VkCommandBufferLevel},
+		[| #{peek VkCommandBufferAllocateInfo, level} |],
+		[| #{poke VkCommandBufferAllocateInfo, level} |]),
+	("commandBufferCount", ''#{type uint32_t},
+		[| #{peek VkCommandBufferAllocateInfo, commandBufferCount} |],
+		[| #{poke VkCommandBufferAllocateInfo, commandBufferCount} |]) ]
+	[''Show, ''Storable]
+
+levelPrimary :: #{type VkCommandBufferLevel}
+levelPrimary = #{const VK_COMMAND_BUFFER_LEVEL_PRIMARY}
+
+data CTag
+type C = Ptr CTag
+type PtrC = Ptr C
+
+foreign import ccall "vkAllocateCommandBuffers" allocateCs ::
+	Device.D -> Ptr AllocateInfo -> Ptr C -> IO #{type VkResult}
+
+struct "InheritanceInfo" #{size VkCommandBufferInheritanceInfo}
+		#{alignment VkCommandBufferInheritanceInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkCommandBufferInheritanceInfo, sType}
+			p sTypeI |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkCommandBufferInheritanceInfo, pNext} |],
+		[| #{poke VkCommandBufferInheritanceInfo, pNext} |]),
+	("renderPass", ''RenderPass.R,
+		[| #{peek VkCommandBufferInheritanceInfo, renderPass} |],
+		[| #{poke VkCommandBufferInheritanceInfo, renderPass} |]),
+	("subpass", ''#{type uint32_t},
+		[| #{peek VkCommandBufferInheritanceInfo, subpass} |],
+		[| #{poke VkCommandBufferInheritanceInfo, subpass} |]),
+	("framebuffer", ''Framebuffer.F,
+		[| #{peek VkCommandBufferInheritanceInfo, framebuffer} |],
+		[| #{poke VkCommandBufferInheritanceInfo, framebuffer} |]),
+	("occlusionQueryEnable", ''#{type VkBool32},
+		[| #{peek VkCommandBufferInheritanceInfo,
+			occlusionQueryEnable} |],
+		[| #{poke VkCommandBufferInheritanceInfo,
+			occlusionQueryEnable} |]),
+	("queryFlags", ''#{type VkQueryControlFlags},
+		[| #{peek VkCommandBufferInheritanceInfo, queryFlags} |],
+		[| #{poke VkCommandBufferInheritanceInfo, queryFlags} |]),
+	("pipelineStatistics", ''#{type VkQueryPipelineStatisticFlags},
+		[| #{peek VkCommandBufferInheritanceInfo,
+			pipelineStatistics} |],
+		[| #{poke VkCommandBufferInheritanceInfo,
+			pipelineStatistics} |]) ]
+	[''Show, ''Storable]
+
+type PtrInheritanceInfo = Ptr InheritanceInfo
+
+struct "BeginInfo" #{size VkCommandBufferBeginInfo}
+		#{alignment VkCommandBufferBeginInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkCommandBufferBeginInfo, sType}
+			p sTypeB |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkCommandBufferBeginInfo, pNext} |],
+		[| #{poke VkCommandBufferBeginInfo, pNext} |]),
+	("flags", ''#{type VkCommandBufferUsageFlags},
+		[| #{peek VkCommandBufferBeginInfo, flags} |],
+		[| #{poke VkCommandBufferBeginInfo, flags} |]),
+	("pInheritanceInfo", ''PtrInheritanceInfo,
+		[| #{peek VkCommandBufferBeginInfo, pInheritanceInfo} |],
+		[| #{poke VkCommandBufferBeginInfo, pInheritanceInfo} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkBeginCommandBuffer" begin ::
+	C -> Ptr BeginInfo -> IO #{type VkResult}
+
+foreign import ccall "vkEndCommandBuffer" end :: C -> IO #{type VkResult}
+
+foreign import ccall "vkResetCommandBuffer" reset ::
+	C -> #{type VkCommandBufferResetFlags} -> IO #{type VkResult}
+
+foreign import ccall "vkFreeCommandBuffers" freeCs ::
+	Device.D -> CommandPool.C -> #{type uint32_t} -> Ptr C -> IO ()
diff --git a/src/Gpu/Vulkan/CommandPool/Core.hsc b/src/Gpu/Vulkan/CommandPool/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/CommandPool/Core.hsc
@@ -0,0 +1,58 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.CommandPool.Core (
+
+	-- * CREATE, DESTROY AND RESET
+
+	create, destroy, reset, C,
+	CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext,
+	createInfoFlags, createInfoQueueFamilyIndex
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO}
+
+struct "CreateInfo" #{size VkCommandPoolCreateInfo}
+		#{alignment VkCommandPoolCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkCommandPoolCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkCommandPoolCreateInfo, pNext} |],
+		[| #{poke VkCommandPoolCreateInfo, pNext} |]),
+	("flags", ''#{type VkCommandPoolCreateFlags},
+		[| #{peek VkCommandPoolCreateInfo, flags} |],
+		[| #{poke VkCommandPoolCreateInfo, flags} |]),
+	("queueFamilyIndex", ''#{type uint32_t},
+		[| #{peek VkCommandPoolCreateInfo, queueFamilyIndex} |],
+		[| #{poke VkCommandPoolCreateInfo, queueFamilyIndex} |]) ]
+	[''Show, ''Storable]
+
+data CTag
+type C = Ptr CTag
+
+foreign import ccall "vkCreateCommandPool" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr C ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyCommandPool" destroy ::
+	Device.D -> C -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkResetCommandPool" reset ::
+	Device.D -> C -> #{type VkCommandPoolResetFlags} -> IO ()
diff --git a/src/Gpu/Vulkan/Component/Core.hsc b/src/Gpu/Vulkan/Component/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Component/Core.hsc
@@ -0,0 +1,33 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Component.Core (
+	Mapping, pattern Mapping, mappingR, mappingG, mappingB, mappingA,
+	swizzleIdentity ) where
+
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+struct "Mapping" #{size VkComponentMapping}
+		#{alignment VkComponentMapping} [
+	("r", ''#{type VkComponentSwizzle},
+		[| #{peek VkComponentMapping, r} |],
+		[| #{poke VkComponentMapping, r} |]),
+	("g", ''#{type VkComponentSwizzle},
+		[| #{peek VkComponentMapping, g} |],
+		[| #{poke VkComponentMapping, g} |]),
+	("b", ''#{type VkComponentSwizzle},
+		[| #{peek VkComponentMapping, b} |],
+		[| #{poke VkComponentMapping, b} |]),
+	("a", ''#{type VkComponentSwizzle},
+		[| #{peek VkComponentMapping, a} |],
+		[| #{poke VkComponentMapping, a} |]) ]
+	[''Show, ''Storable]
+
+swizzleIdentity :: #{type VkComponentSwizzle}
+swizzleIdentity = #{const VK_COMPONENT_SWIZZLE_IDENTITY}
diff --git a/src/Gpu/Vulkan/Core.hsc b/src/Gpu/Vulkan/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Core.hsc
@@ -0,0 +1,382 @@
+{-# LANGUAGE CApiFFI #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE BlockArguments, TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Core (
+
+	-- * INFO
+
+	-- ** ApplicationInfo
+
+	ApplicationInfo, PtrApplicationInfo, pattern ApplicationInfo,
+	applicationInfoSType, applicationInfoPNext,
+	applicationInfoPApplicationName, applicationInfoApplicationVersion,
+	applicationInfoPEngineName, applicationInfoEngineVersion,
+	applicationInfoApiVersion,
+
+	-- *** ApiVersion
+
+	ApiVersion, makeApiVersion, apiVersion_1_0, apiVersion_1_1,
+
+	-- ** SubmitInfo
+
+	SubmitInfo, pattern SubmitInfo,
+	submitInfoSType, submitInfoPNext,
+	submitInfoWaitSemaphoreCount, submitInfoPWaitSemaphores,
+	submitInfoPWaitDstStageMask, PtrPipelineStageFlags,
+	submitInfoCommandBufferCount, submitInfoPCommandBuffers,
+	submitInfoSignalSemaphoreCount, submitInfoPSignalSemaphores,
+
+	-- * PROPERTIES
+
+	-- ** ExtensionProperties
+
+	ExtensionProperties, pattern ExtensionProperties,
+	extensionPropertiesExtensionName, extensionPropertiesSpecVersion,
+
+	-- ** LayerProperties
+
+	LayerProperties, pattern LayerProperties,
+	layerPropertiesLayerName, layerPropertiesSpecVersion,
+	layerPropertiesImplementationVersion, layerPropertiesDescription,
+
+	-- ** FormatProperties
+
+	FormatProperties, pattern FormatProperties,
+	formatPropertiesLinearTilingFeatures,
+	formatPropertiesOptimalTilingFeatures, formatPropertiesBufferFeatures,
+
+	-- * PIPELINE VALUES
+
+	-- ** Viewport
+
+	Viewport, PtrViewport, pattern Viewport,
+	viewportX, viewportY, viewportWidth, viewportHeight,
+	viewportMinDepth, viewportMaxDepth,
+
+	-- ** StencilOpState
+
+	StencilOpState, pattern StencilOpState,
+	stencilOpStateFailOp, stencilOpStatePassOp, stencilOpStateDepthFailOp,
+	stencilOpStateCompareOp, stencilOpStateCompareMask,
+	stencilOpStateWriteMask, stencilOpStateReference,
+
+	-- ** ClearValue
+
+	ClearValue, PtrClearValue,
+	clearValueFromClearColorValue, clearValueFromClearDepthStencilValue,
+
+	-- *** ClearColorValue
+
+	ClearColorValue,
+	clearColorValueFromUints, clearColorValueFromInts,
+	clearColorValueFromFloats,
+
+	-- *** ClearDepthStencilValue
+	
+	ClearDepthStencilValue, pattern ClearDepthStencilValue,
+	clearDepthStencilValueDepth, clearDepthStencilValueStencil,
+
+	-- * STRUCT COMMON
+
+	StructCommon, pattern StructCommon,
+	structCommonSType, structCommonPNext,
+
+	-- * RECT, OFFSET AND EXTENT
+
+	-- ** Rect
+
+	Rect2d, PtrRect2d, pattern Rect2d,
+	rect2dExtent, rect2dOffset,
+
+	-- ** Offset
+
+	Offset2d, pattern Offset2d,
+	offset2dX, offset2dY,
+
+	Offset3d, ListOffset3d, pattern Offset3d,
+	offset3dX, offset3dY, offset3dZ,
+
+	-- ** Extent
+
+	Extent2d, pattern Extent2d,
+	extent2dWidth, extent2dHeight,
+
+	Extent3d, pattern Extent3d,
+	extent3dWidth, extent3dHeight, extent3dDepth,
+
+	) where
+
+import Foreign.Ptr
+import Foreign.ForeignPtr
+import Foreign.Marshal.Utils
+import Foreign.Storable
+import Foreign.C.Types
+import Foreign.C.String
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Data.Text as Txt
+import qualified Data.Text.Foreign as Txt
+
+import {-# SOURCE #-} qualified Gpu.Vulkan.CommandBuffer.Core as CommandBuffer
+import {-# SOURCE #-} qualified Gpu.Vulkan.Semaphore.Core as Semaphore
+
+#include <vulkan/vulkan.h>
+
+struct "StructCommon" #{size VkApplicationInfo}
+		#{alignment VkApplicationInfo} [
+	("sType", ''#{type VkStructureType},
+		[| #{peek VkApplicationInfo, sType} |],
+		[| #{poke VkApplicationInfo, sType} |] ),
+	("pNext", ''PtrVoid,
+		[| #{peek VkApplicationInfo, pNext} |],
+		[| #{poke VkApplicationInfo, pNext} |]) ]
+	[''Show, ''Storable]
+
+type ApiVersion = #{type uint32_t}
+
+struct "ApplicationInfo" #{size VkApplicationInfo}
+		#{alignment VkApplicationInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkApplicationInfo, sType} p
+			(#{const VK_STRUCTURE_TYPE_APPLICATION_INFO} ::
+				#{type VkStructureType}) |]),
+	("pNext", ''PtrVoid, [| #{peek VkApplicationInfo, pNext} |],
+		[| #{poke VkApplicationInfo, pNext} |]),
+	("pApplicationName", ''CString,
+		[| #{peek VkApplicationInfo, pApplicationName} |],
+		[| #{poke VkApplicationInfo, pApplicationName} |]),
+	("applicationVersion", ''ApiVersion,
+		[| #{peek VkApplicationInfo, applicationVersion} |],
+		[| #{poke VkApplicationInfo, applicationVersion} |]),
+	("pEngineName", ''CString,
+		[| #{peek VkApplicationInfo, pEngineName} |],
+		[| #{poke VkApplicationInfo, pEngineName} |]),
+	("engineVersion", ''ApiVersion,
+		[| #{peek VkApplicationInfo, engineVersion} |],
+		[| #{poke VkApplicationInfo, engineVersion} |]),
+	("apiVersion", ''ApiVersion,
+		[| #{peek VkApplicationInfo, apiVersion} |],
+		[| #{poke VkApplicationInfo, apiVersion} |]) ]
+	[''Show, ''Storable]
+
+foreign import capi "vulkan/vulkan.h VK_MAKE_API_VERSION" makeApiVersion ::
+	Word8 -> Word8 -> Word16 -> Word16 -> ApiVersion
+
+foreign import capi "vulkan/vulkan.h value VK_API_VERSION_1_0" apiVersion_1_0 ::
+	ApiVersion
+
+foreign import capi "vulkan/vulkan.h value VK_API_VERSION_1_1" apiVersion_1_1 ::
+	ApiVersion
+
+type PtrApplicationInfo = Ptr ApplicationInfo
+
+struct "Extent2d" #{size VkExtent2D} #{alignment VkExtent2D} [
+	("width", ''#{type uint32_t}, [| #{peek VkExtent2D, width} |],
+		[| #{poke VkExtent2D, width} |]),
+	("height", ''#{type uint32_t}, [| #{peek VkExtent2D, height} |],
+		[| #{poke VkExtent2D, height} |]) ]
+	[''Show, ''Storable]
+
+struct "Extent3d" #{size VkExtent3D} #{alignment VkExtent3D} [
+	("width", ''#{type uint32_t}, [| #{peek VkExtent3D, width} |],
+		[| #{poke VkExtent3D, width} |]),
+	("height", ''#{type uint32_t}, [| #{peek VkExtent3D, height} |],
+		[| #{poke VkExtent3D, height} |]),
+	("depth", ''#{type uint32_t}, [| #{peek VkExtent3D, depth} |],
+		[| #{poke VkExtent3D, depth} |]) ]
+	[''Show, ''Storable]
+
+struct "Viewport" #{size VkViewport} #{alignment VkViewport} [
+	("x", ''#{type float}, [| #{peek VkViewport, x} |],
+		[| #{poke VkViewport, x} |]),
+	("y", ''#{type float}, [| #{peek VkViewport, y} |],
+		[| #{poke VkViewport, y} |]),
+	("width", ''#{type float}, [| #{peek VkViewport, width} |],
+		[| #{poke VkViewport, width} |]),
+	("height", ''#{type float}, [| #{peek VkViewport, height} |],
+		[| #{poke VkViewport, height} |]),
+	("minDepth", ''#{type float}, [| #{peek VkViewport, minDepth} |],
+		[| #{poke VkViewport, minDepth} |]),
+	("maxDepth", ''#{type float}, [| #{peek VkViewport, maxDepth} |],
+		[| #{poke VkViewport, maxDepth} |]) ]
+	[''Show, ''Storable]
+
+type PtrViewport = Ptr Viewport
+
+struct "Offset2d" #{size VkOffset2D} #{alignment VkOffset2D} [
+	("x", ''#{type int32_t}, [| #{peek VkOffset2D, x} |],
+		[| #{poke VkOffset2D, x} |]),
+	("y", ''#{type int32_t}, [| #{peek VkOffset2D, y} |],
+		[| #{poke VkOffset2D, y} |]) ]
+	[''Show, ''Storable]
+
+struct "Offset3d" #{size VkOffset3D} #{alignment VkOffset3D} [
+	("x", ''#{type int32_t}, [| #{peek VkOffset3D, x} |],
+		[| #{poke VkOffset3D, x} |]),
+	("y", ''#{type int32_t}, [| #{peek VkOffset3D, y} |],
+		[| #{poke VkOffset3D, y} |]),
+	("z", ''#{type int32_t}, [| #{peek VkOffset3D, z} |],
+		[| #{poke VkOffset3D, z} |]) ]
+	[''Show, ''Storable]
+
+type ListOffset3d = [Offset3d]
+
+struct "Rect2d" #{size VkRect2D} #{alignment VkRect2D} [
+	("offset", ''Offset2d, [| #{peek VkRect2D, offset} |],
+		[| #{poke VkRect2D, offset} |]),
+	("extent", ''Extent2d, [| #{peek VkRect2D, extent} |],
+		[| #{poke VkRect2D, extent} |]) ]
+	[''Show, ''Storable]
+
+type PtrRect2d = Ptr Rect2d
+
+type PtrPipelineStageFlags = Ptr #{type VkPipelineStageFlags}
+
+sTypeS :: #{type VkStructureType}
+sTypeS = #{const VK_STRUCTURE_TYPE_SUBMIT_INFO}
+
+struct "SubmitInfo" #{size VkSubmitInfo} #{alignment VkSubmitInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkSubmitInfo, sType} p sTypeS |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkSubmitInfo, pNext} |],
+		[| #{poke VkSubmitInfo, pNext} |]),
+	("waitSemaphoreCount", ''#{type uint32_t},
+		[| #{peek VkSubmitInfo, waitSemaphoreCount} |],
+		[| #{poke VkSubmitInfo, waitSemaphoreCount} |]),
+	("pWaitSemaphores", ''Semaphore.PtrS,
+		[| #{peek VkSubmitInfo, pWaitSemaphores} |],
+		[| #{poke VkSubmitInfo, pWaitSemaphores} |]),
+	("pWaitDstStageMask", ''PtrPipelineStageFlags,
+		[| #{peek VkSubmitInfo, pWaitDstStageMask} |],
+		[| #{poke VkSubmitInfo, pWaitDstStageMask} |]),
+	("commandBufferCount", ''#{type uint32_t},
+		[| #{peek VkSubmitInfo, commandBufferCount} |],
+		[| #{poke VkSubmitInfo, commandBufferCount} |]),
+	("pCommandBuffers", ''CommandBuffer.PtrC,
+		[| #{peek VkSubmitInfo, pCommandBuffers} |],
+		[| #{poke VkSubmitInfo, pCommandBuffers} |]),
+	("signalSemaphoreCount", ''#{type int32_t},
+		[| #{peek VkSubmitInfo, signalSemaphoreCount} |],
+		[| #{poke VkSubmitInfo, signalSemaphoreCount} |]),
+	("pSignalSemaphores", ''Semaphore.PtrS,
+		[| #{peek VkSubmitInfo, pSignalSemaphores} |],
+		[| #{poke VkSubmitInfo, pSignalSemaphores} |]) ]
+	[''Show, ''Storable]
+
+struct "ExtensionProperties" #{size VkExtensionProperties}
+		#{alignment VkExtensionProperties} [
+	("extensionName", ''Txt.Text,
+		[| \p -> Txt.takeWhile (/= '\NUL') <$> Txt.peekCStringLen
+			(#{ptr VkExtensionProperties, extensionName} p,
+				#{const VK_MAX_EXTENSION_NAME_SIZE}) |],
+		[| \p bs -> Txt.withCStringLen bs \(cs, ln) -> do
+			copyBytes (#{ptr VkExtensionProperties, extensionName} p) cs ln
+			poke (#{ptr VkExtensionProperties, extensionName} p `plusPtr` ln :: Ptr CChar) 0
+			|]
+		),
+	("specVersion", ''#{type uint32_t},
+		[| #{peek VkExtensionProperties, specVersion} |],
+		[| #{poke VkExtensionProperties, specVersion} |]) ]
+	[''Show, ''Storable]
+
+struct "LayerProperties" #{size VkLayerProperties}
+		#{alignment VkLayerProperties} [
+	("layerName", ''Txt.Text,
+		[| \p -> Txt.takeWhile (/= '\NUL') <$> Txt.peekCStringLen
+			(#{ptr VkLayerProperties, layerName} p,
+				#{const VK_MAX_EXTENSION_NAME_SIZE}) |],
+		[| \p bs -> Txt.withCStringLen bs \(cs, ln) -> do
+			copyBytes (#{ptr VkLayerProperties, layerName} p) cs ln
+			poke (#{ptr VkLayerProperties, layerName} p `plusPtr` ln :: Ptr CChar) 0
+			|]),
+	("specVersion", ''#{type uint32_t},
+		[| #{peek VkLayerProperties, specVersion} |],
+		[| #{poke VkLayerProperties, specVersion} |]),
+	("implementationVersion", ''#{type uint32_t},
+		[| #{peek VkLayerProperties, implementationVersion} |],
+		[| #{poke VkLayerProperties, implementationVersion} |]),
+	("description", ''Txt.Text,
+		[| \p -> Txt.takeWhile (/= '\NUL') <$> Txt.peekCStringLen
+			(#{ptr VkLayerProperties, description} p,
+				#{const VK_MAX_DESCRIPTION_SIZE}) |],
+		[| \p bs -> Txt.withCStringLen bs \(cs, ln) -> do
+			copyBytes (#{ptr VkLayerProperties, description} p) cs ln
+			poke (#{ptr VkLayerProperties, description} p `plusPtr` ln :: Ptr CChar) 0
+			|]) ]
+	[''Show, ''Storable]
+
+struct "StencilOpState" #{size VkStencilOpState} #{alignment VkStencilOpState} [
+	("failOp", ''#{type VkStencilOp},
+		[| #{peek VkStencilOpState, failOp} |],
+		[| #{poke VkStencilOpState, failOp} |]),
+	("passOp", ''#{type VkStencilOp},
+		[| #{peek VkStencilOpState, passOp} |],
+		[| #{poke VkStencilOpState, passOp} |]),
+	("depthFailOp", ''#{type VkStencilOp},
+		[| #{peek VkStencilOpState, depthFailOp} |],
+		[| #{poke VkStencilOpState, depthFailOp} |]),
+	("compareOp", ''#{type VkCompareOp},
+		[| #{peek VkStencilOpState, compareOp} |],
+		[| #{poke VkStencilOpState, compareOp} |]),
+	("compareMask", ''#{type uint32_t},
+		[| #{peek VkStencilOpState, compareMask} |],
+		[| #{poke VkStencilOpState, compareMask} |]),
+	("writeMask", ''#{type uint32_t},
+		[| #{peek VkStencilOpState, writeMask} |],
+		[| #{poke VkStencilOpState, writeMask} |]),
+	("reference", ''#{type uint32_t},
+		[| #{peek VkStencilOpState, reference} |],
+		[| #{poke VkStencilOpState, reference} |]) ]
+	[''Show, ''Storable]
+
+data ClearValue
+type PtrClearValue = Ptr ClearValue
+data ClearColorValue
+
+clearColorValueFromFloats :: Ptr #{type float} -> Ptr ClearColorValue
+clearColorValueFromFloats = castPtr
+
+clearColorValueFromInts :: Ptr #{type int32_t} -> Ptr ClearColorValue
+clearColorValueFromInts = castPtr
+
+clearColorValueFromUints :: Ptr #{type uint32_t} -> Ptr ClearColorValue
+clearColorValueFromUints = castPtr
+
+struct "ClearDepthStencilValue" #{size VkClearDepthStencilValue}
+		#{alignment VkClearDepthStencilValue} [
+	("depth", ''#{type float},
+		[| #{peek VkClearDepthStencilValue, depth} |],
+		[| #{poke VkClearDepthStencilValue, depth} |]),
+	("stencil", ''#{type uint32_t},
+		[| #{peek VkClearDepthStencilValue, stencil} |],
+		[| #{poke VkClearDepthStencilValue, stencil} |]) ]
+	[''Show, ''Storable]
+
+clearValueFromClearColorValue :: Ptr ClearColorValue -> Ptr ClearValue
+clearValueFromClearColorValue = castPtr
+
+clearValueFromClearDepthStencilValue ::
+	ClearDepthStencilValue -> (Ptr ClearValue -> IO a) -> IO a
+clearValueFromClearDepthStencilValue (ClearDepthStencilValue_ fp) f =
+	withForeignPtr fp $ f . castPtr
+
+struct "FormatProperties" #{size VkFormatProperties}
+		#{alignment VkFormatProperties} [
+	("linearTilingFeatures", ''#{type VkFormatFeatureFlags},
+		[| #{peek VkFormatProperties, linearTilingFeatures} |],
+		[| #{poke VkFormatProperties, linearTilingFeatures} |]),
+	("optimalTilingFeatures", ''#{type VkFormatFeatureFlags},
+		[| #{peek VkFormatProperties, optimalTilingFeatures} |],
+		[| #{poke VkFormatProperties, optimalTilingFeatures} |]),
+	("bufferFeatures", ''#{type VkFormatFeatureFlags},
+		[| #{peek VkFormatProperties, bufferFeatures} |],
+		[| #{poke VkFormatProperties, bufferFeatures} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/Descriptor/Core.hsc b/src/Gpu/Vulkan/Descriptor/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Descriptor/Core.hsc
@@ -0,0 +1,61 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Descriptor.Core (
+
+	-- * BUFFER INFO
+
+	BufferInfo, PtrBufferInfo,
+	pattern BufferInfo,
+	bufferInfoBuffer, bufferInfoOffset, bufferInfoRange,
+
+	-- * IMAGE INFO
+
+	ImageInfo, PtrImageInfo,
+	pattern ImageInfo,
+	imageInfoSampler, imageInfoImageView, imageInfoImageLayout
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+import qualified Gpu.Vulkan.Buffer.Core as Buffer
+import qualified Gpu.Vulkan.ImageView.Core as ImageView
+import qualified Gpu.Vulkan.Sampler.Core as Sampler
+
+#include <vulkan/vulkan.h>
+
+struct "BufferInfo" #{size VkDescriptorBufferInfo}
+		#{alignment VkDescriptorBufferInfo} [
+	("buffer", ''Buffer.B,
+		[| #{peek VkDescriptorBufferInfo, buffer} |],
+		[| #{poke VkDescriptorBufferInfo, buffer} |]),
+	("offset", ''#{type VkDeviceSize},
+		[| #{peek VkDescriptorBufferInfo, offset} |],
+		[| #{poke VkDescriptorBufferInfo, offset} |]),
+	("range", ''#{type VkDeviceSize},
+		[| #{peek VkDescriptorBufferInfo, range} |],
+		[| #{poke VkDescriptorBufferInfo, range} |]) ]
+	[''Show, ''Storable]
+
+type PtrBufferInfo = Ptr BufferInfo
+
+struct "ImageInfo" #{size VkDescriptorImageInfo}
+		#{alignment VkDescriptorImageInfo} [
+	("sampler", ''Sampler.S,
+		[| #{peek VkDescriptorImageInfo, sampler} |],
+		[| #{poke VkDescriptorImageInfo, sampler} |]),
+	("imageView", ''ImageView.I,
+		[| #{peek VkDescriptorImageInfo, imageView} |],
+		[| #{poke VkDescriptorImageInfo, imageView} |]),
+	("imageLayout", ''#{type VkImageLayout},
+		[| #{peek VkDescriptorImageInfo, imageLayout} |],
+		[| #{poke VkDescriptorImageInfo, imageLayout} |]) ]
+	[''Show, ''Storable]
+
+type PtrImageInfo = Ptr ImageInfo
diff --git a/src/Gpu/Vulkan/DescriptorPool/Core.hsc b/src/Gpu/Vulkan/DescriptorPool/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/DescriptorPool/Core.hsc
@@ -0,0 +1,77 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.DescriptorPool.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, D, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoMaxSets, createInfoPoolSizeCount, createInfoPPoolSizes,
+
+	-- ** Size
+
+	Size, PtrSize, pattern Size, sizeType, sizeDescriptorCount
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+struct "Size" #{size VkDescriptorPoolSize} #{alignment VkDescriptorPoolSize} [
+	("type", ''#{type VkDescriptorType},
+		[| #{peek VkDescriptorPoolSize, type} |],
+		[| #{poke VkDescriptorPoolSize, type} |]),
+	("descriptorCount", ''#{type uint32_t},
+		[| #{peek VkDescriptorPoolSize, descriptorCount} |],
+		[| #{poke VkDescriptorPoolSize, descriptorCount} |])
+	]
+	[''Show, ''Storable]
+
+type PtrSize = Ptr Size
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO}
+
+struct "CreateInfo" #{size VkDescriptorPoolCreateInfo}
+		#{alignment VkDescriptorPoolCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ ->
+			#{poke VkDescriptorPoolCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkDescriptorPoolCreateInfo, pNext} |],
+		[| #{poke VkDescriptorPoolCreateInfo, pNext} |]),
+	("flags", ''#{type VkDescriptorPoolCreateFlags},
+		[| #{peek VkDescriptorPoolCreateInfo, flags} |],
+		[| #{poke VkDescriptorPoolCreateInfo, flags} |]),
+	("maxSets", ''#{type uint32_t},
+		[| #{peek VkDescriptorPoolCreateInfo, maxSets} |],
+		[| #{poke VkDescriptorPoolCreateInfo, maxSets} |]),
+	("poolSizeCount", ''#{type uint32_t},
+		[| #{peek VkDescriptorPoolCreateInfo, poolSizeCount} |],
+		[| #{poke VkDescriptorPoolCreateInfo, poolSizeCount} |]),
+	("pPoolSizes", ''PtrSize,
+		[| #{peek VkDescriptorPoolCreateInfo, pPoolSizes} |],
+		[| #{poke VkDescriptorPoolCreateInfo, pPoolSizes} |]) ]
+	[''Show, ''Storable]
+
+data DTag
+type D = Ptr DTag
+
+foreign import ccall "vkCreateDescriptorPool" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A ->
+	Ptr D -> IO #{type VkResult}
+
+foreign import ccall "vkDestroyDescriptorPool" destroy ::
+	Device.D -> D -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/DescriptorSet/Core.hsc b/src/Gpu/Vulkan/DescriptorSet/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/DescriptorSet/Core.hsc
@@ -0,0 +1,151 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.DescriptorSet.Core (
+
+	-- * ALLOCATE AND FREE
+
+	allocateDs, freeDs, D, AllocateInfo, pattern AllocateInfo,
+	allocateInfoSType, allocateInfoPNext,
+	allocateInfoDescriptorPool, allocateInfoDescriptorSetCount,
+	allocateInfoPSetLayouts,
+
+	-- * UPDATE
+
+	updateDs,
+
+	-- ** Write
+
+	Write, pattern Write,
+	writeSType, writePNext,
+	writeDstSet, writeDstBinding, writeDstArrayElement,
+	writeDescriptorCount, writeDescriptorType,
+	writePImageInfo, writePBufferInfo, writePTexelBufferView,
+
+	-- ** Copy
+
+	Copy, pattern Copy,
+	copySType, copyPNext,
+	copySrcSet, copySrcBinding, copySrcArrayElement,
+	copyDstSet, copyDstBinding, copyDstArrayElement,
+	copyDescriptorCount
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.BufferView.Core as Buffer.View
+import qualified Gpu.Vulkan.Descriptor.Core as Dsc
+import qualified Gpu.Vulkan.DescriptorPool.Core as Pool
+import qualified Gpu.Vulkan.DescriptorSetLayout.Core as Layout
+
+#include <vulkan/vulkan.h>
+
+aType :: #{type VkStructureType}
+aType = #{const VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO}
+
+struct "AllocateInfo" #{size VkDescriptorSetAllocateInfo}
+		#{alignment VkDescriptorSetAllocateInfo} [
+	("sType", ''(), [| const $ pure () |], [| \p _ ->
+		#{poke VkDescriptorSetAllocateInfo, sType} p aType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkDescriptorSetAllocateInfo, pNext} |],
+		[| #{poke VkDescriptorSetAllocateInfo, pNext} |]),
+	("descriptorPool", ''Pool.D,
+		[| #{peek VkDescriptorSetAllocateInfo, descriptorPool} |],
+		[| #{poke VkDescriptorSetAllocateInfo, descriptorPool} |]),
+	("descriptorSetCount", ''#{type uint32_t},
+		[| #{peek VkDescriptorSetAllocateInfo, descriptorSetCount} |],
+		[| #{poke VkDescriptorSetAllocateInfo, descriptorSetCount} |]),
+	("pSetLayouts", ''Layout.PtrD,
+		[| #{peek VkDescriptorSetAllocateInfo, pSetLayouts} |],
+		[| #{poke VkDescriptorSetAllocateInfo, pSetLayouts} |]) ]
+	[''Show, ''Storable]
+
+data DTag
+type D = Ptr DTag
+
+foreign import ccall "vkAllocateDescriptorSets" allocateDs ::
+	Device.D -> Ptr AllocateInfo -> Ptr D -> IO #{type VkResult}
+
+foreign import ccall "vkFreeDescriptorSets" freeDs ::
+	Device.D -> Pool.D -> #{type uint32_t} -> Ptr D -> IO #{type VkResult}
+
+wType :: #{type VkStructureType}
+wType = #{const VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET}
+
+struct "Write" #{size VkWriteDescriptorSet} #{alignment VkWriteDescriptorSet} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkWriteDescriptorSet, sType} p wType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkWriteDescriptorSet, pNext} |],
+		[| #{poke VkWriteDescriptorSet, pNext} |]),
+	("dstSet", ''D,
+		[| #{peek VkWriteDescriptorSet, dstSet} |],
+		[| #{poke VkWriteDescriptorSet, dstSet} |]),
+	("dstBinding", ''#{type uint32_t},
+		[| #{peek VkWriteDescriptorSet, dstBinding} |],
+		[| #{poke VkWriteDescriptorSet, dstBinding} |]),
+	("dstArrayElement", ''#{type uint32_t},
+		[| #{peek VkWriteDescriptorSet, dstArrayElement} |],
+		[| #{poke VkWriteDescriptorSet, dstArrayElement} |]),
+	("descriptorCount", ''#{type uint32_t},
+		[| #{peek VkWriteDescriptorSet, descriptorCount} |],
+		[| #{poke VkWriteDescriptorSet, descriptorCount} |]),
+	("descriptorType", ''#{type VkDescriptorType},
+		[| #{peek VkWriteDescriptorSet, descriptorType} |],
+		[| #{poke VkWriteDescriptorSet, descriptorType} |]),
+	("pImageInfo", ''Dsc.PtrImageInfo,
+		[| #{peek VkWriteDescriptorSet, pImageInfo} |],
+		[| #{poke VkWriteDescriptorSet, pImageInfo} |]),
+	("pBufferInfo", ''Dsc.PtrBufferInfo,
+		[| #{peek VkWriteDescriptorSet, pBufferInfo} |],
+		[| #{poke VkWriteDescriptorSet, pBufferInfo} |]),
+	("pTexelBufferView", ''Buffer.View.PtrB,
+		[| #{peek VkWriteDescriptorSet, pTexelBufferView} |],
+		[| #{poke VkWriteDescriptorSet, pTexelBufferView} |]) ]
+	[''Show, ''Storable]
+
+cType :: #{type VkStructureType}
+cType = #{const VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET}
+
+struct "Copy" #{size VkCopyDescriptorSet} #{alignment VkCopyDescriptorSet} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkCopyDescriptorSet, sType} p cType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkCopyDescriptorSet, pNext} |],
+		[| #{poke VkCopyDescriptorSet, pNext} |]),
+	("srcSet", ''D,
+		[| #{peek VkCopyDescriptorSet, srcSet} |],
+		[| #{poke VkCopyDescriptorSet, srcSet} |]),
+	("srcBinding", ''#{type uint32_t},
+		[| #{peek VkCopyDescriptorSet, srcBinding} |],
+		[| #{poke VkCopyDescriptorSet, srcBinding} |]),
+	("srcArrayElement", ''#{type uint32_t},
+		[| #{peek VkCopyDescriptorSet, srcArrayElement} |],
+		[| #{poke VkCopyDescriptorSet, srcArrayElement} |]),
+	("dstSet", ''D,
+		[| #{peek VkCopyDescriptorSet, dstSet} |],
+		[| #{poke VkCopyDescriptorSet, dstSet} |]),
+	("dstBinding", ''#{type uint32_t},
+		[| #{peek VkCopyDescriptorSet, dstBinding} |],
+		[| #{poke VkCopyDescriptorSet, dstBinding} |]),
+	("dstArrayElement", ''#{type uint32_t},
+		[| #{peek VkCopyDescriptorSet, dstArrayElement} |],
+		[| #{poke VkCopyDescriptorSet, dstArrayElement} |]),
+	("descriptorCount", ''#{type uint32_t},
+		[| #{peek VkCopyDescriptorSet, descriptorCount} |],
+		[| #{poke VkCopyDescriptorSet, descriptorCount} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkUpdateDescriptorSets" updateDs ::
+	Device.D ->
+	#{type uint32_t} -> Ptr Write -> #{type uint32_t} -> Ptr Copy -> IO ()
diff --git a/src/Gpu/Vulkan/DescriptorSetLayout/BindingFlags/Core.hsc b/src/Gpu/Vulkan/DescriptorSetLayout/BindingFlags/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/DescriptorSetLayout/BindingFlags/Core.hsc
@@ -0,0 +1,47 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.DescriptorSetLayout.BindingFlags.Core (
+	CreateInfo, pattern CreateInfo, BPtr,
+	createInfoSType, createInfoPNext,
+	createInfoBindingCount, createInfoPBindingFlags ) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const
+	VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO}
+
+type BPtr = Ptr #{type VkDescriptorBindingFlags}
+
+struct "CreateInfo" #{size VkDescriptorSetLayoutBindingFlagsCreateInfo}
+		#{alignment VkDescriptorSetLayoutBindingFlagsCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ ->
+			#{poke VkDescriptorSetLayoutBindingFlagsCreateInfo,
+				sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkDescriptorSetLayoutBindingFlagsCreateInfo,
+			pNext} |],
+		[| #{poke VkDescriptorSetLayoutBindingFlagsCreateInfo,
+			pNext} |]),
+	("bindingCount", ''#{type uint32_t},
+		[| #{peek VkDescriptorSetLayoutBindingFlagsCreateInfo,
+			bindingCount} |],
+		[| #{poke VkDescriptorSetLayoutBindingFlagsCreateInfo,
+			bindingCount} |]),
+	("pBindingFlags", ''BPtr,
+		[| #{peek VkDescriptorSetLayoutBindingFlagsCreateInfo,
+			pBindingFlags} |],
+		[| #{poke VkDescriptorSetLayoutBindingFlagsCreateInfo,
+			pBindingFlags} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/DescriptorSetLayout/Core.hsc b/src/Gpu/Vulkan/DescriptorSetLayout/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/DescriptorSetLayout/Core.hsc
@@ -0,0 +1,87 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.DescriptorSetLayout.Core (
+	-- * CREATE AND DESTROY
+
+	create, destroy, D, PtrD, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoBindingCount, createInfoPBindings,
+
+	-- ** Binding
+	Binding, PtrBinding, pattern Binding,
+	bindingBinding, bindingDescriptorType, bindingDescriptorCount,
+	bindingStageFlags, bindingPImmutableSamplers
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.Sampler.Core as Sampler
+
+#include <vulkan/vulkan.h>
+
+data DTag
+type D = Ptr DTag
+
+type PtrD = Ptr D
+
+struct "Binding" #{size VkDescriptorSetLayoutBinding}
+		#{alignment VkDescriptorSetLayoutBinding} [
+	("binding", ''#{type uint32_t},
+		[| #{peek VkDescriptorSetLayoutBinding, binding} |],
+		[| #{poke VkDescriptorSetLayoutBinding, binding} |]),
+	("descriptorType", ''#{type VkDescriptorType},
+		[| #{peek VkDescriptorSetLayoutBinding, descriptorType} |],
+		[| #{poke VkDescriptorSetLayoutBinding, descriptorType} |]),
+	("descriptorCount", ''#{type uint32_t},
+		[| #{peek VkDescriptorSetLayoutBinding, descriptorCount} |],
+		[| #{poke VkDescriptorSetLayoutBinding, descriptorCount} |]),
+	("stageFlags", ''#{type VkShaderStageFlags},
+		[| #{peek VkDescriptorSetLayoutBinding, stageFlags} |],
+		[| #{poke VkDescriptorSetLayoutBinding, stageFlags} |]),
+	("pImmutableSamplers", ''Sampler.PtrS,
+		[| #{peek VkDescriptorSetLayoutBinding, pImmutableSamplers} |],
+		[| #{poke VkDescriptorSetLayoutBinding, pImmutableSamplers} |])
+	]
+	[''Show, ''Storable]
+
+type PtrBinding = Ptr Binding
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO}
+
+struct "CreateInfo" #{size VkDescriptorSetLayoutCreateInfo}
+		#{alignment VkDescriptorSetLayoutCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkDescriptorSetLayoutCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkDescriptorSetLayoutCreateInfo, pNext} |],
+		[| #{poke VkDescriptorSetLayoutCreateInfo, pNext} |]),
+	("flags", ''#{type VkDescriptorSetLayoutCreateFlags},
+		[| #{peek VkDescriptorSetLayoutCreateInfo, flags} |],
+		[| #{poke VkDescriptorSetLayoutCreateInfo, flags} |]),
+	("bindingCount", ''#{type uint32_t},
+		[| #{peek VkDescriptorSetLayoutCreateInfo, bindingCount} |],
+		[| #{poke VkDescriptorSetLayoutCreateInfo, bindingCount} |]),
+	("pBindings", ''PtrBinding,
+		[| #{peek VkDescriptorSetLayoutCreateInfo, pBindings} |],
+		[| #{poke VkDescriptorSetLayoutCreateInfo, pBindings} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkCreateDescriptorSetLayout" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr D ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyDescriptorSetLayout" destroy ::
+	Device.D -> D -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Device/Core.hs-boot b/src/Gpu/Vulkan/Device/Core.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Device/Core.hs-boot
@@ -0,0 +1,8 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Device.Core (D) where
+
+import Foreign.Ptr
+
+data DTag
+type D = Ptr DTag
diff --git a/src/Gpu/Vulkan/Device/Core.hsc b/src/Gpu/Vulkan/Device/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Device/Core.hsc
@@ -0,0 +1,120 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Device.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, D, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoQueueCreateInfoCount, createInfoPQueueCreateInfos,
+	createInfoEnabledLayerCount, createInfoPpEnabledLayerNames,
+	createInfoEnabledExtensionCount, createInfoPpEnabledExtensionNames,
+	createInfoPEnabledFeatures,
+
+	-- ** QueueCreateInfo
+
+	QueueCreateInfo, PtrQueueCreateInfo, pattern QueueCreateInfo,
+	queueCreateInfoSType, queueCreateInfoPNext, queueCreateInfoFlags,
+	queueCreateInfoQueueFamilyIndex,
+	queueCreateInfoQueueCount, queueCreateInfoPQueuePriorities,
+
+	-- * GET AND WAIT IDLE
+
+	getQueue, waitIdle
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.PhysicalDevice.Core as PhysicalDevice
+import qualified Gpu.Vulkan.PhysicalDevice.Struct.Core as PhysicalDevice
+import qualified Gpu.Vulkan.Queue.Core as Queue
+
+#include <vulkan/vulkan.h>
+
+queueStructureType :: #{type VkStructureType}
+queueStructureType = #{const VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}
+
+struct "QueueCreateInfo" #{size VkDeviceQueueCreateInfo} 
+		#{alignment VkDeviceQueueCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkDeviceQueueCreateInfo, sType}
+			p queueStructureType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkDeviceQueueCreateInfo, pNext} |],
+		[| #{poke VkDeviceQueueCreateInfo, pNext} |]),
+	("flags", ''#{type VkDeviceQueueCreateFlags},
+		[| #{peek VkDeviceQueueCreateInfo, flags} |],
+		[| #{poke VkDeviceQueueCreateInfo, flags} |]),
+	("queueFamilyIndex", ''#{type uint32_t},
+		[| #{peek VkDeviceQueueCreateInfo, queueFamilyIndex} |],
+		[| #{poke VkDeviceQueueCreateInfo, queueFamilyIndex} |]),
+	("queueCount", ''#{type uint32_t},
+		[| #{peek VkDeviceQueueCreateInfo, queueCount} |],
+		[| #{poke VkDeviceQueueCreateInfo, queueCount} |]),
+	("pQueuePriorities", ''PtrFloat,
+		[| #{peek VkDeviceQueueCreateInfo, pQueuePriorities} |],
+		[| #{poke VkDeviceQueueCreateInfo, pQueuePriorities} |]) ]
+	[''Show, ''Storable]
+
+type PtrQueueCreateInfo = Ptr QueueCreateInfo
+
+struct "CreateInfo" #{size VkDeviceCreateInfo}
+		#{alignment VkDeviceCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkDeviceCreateInfo, sType} p
+			(#{const VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO} ::
+				#{type VkStructureType}) |]),
+	("pNext", ''PtrVoid, [| #{peek VkDeviceCreateInfo, pNext} |],
+		[| #{poke VkDeviceCreateInfo, pNext} |]),
+	("flags", ''#{type VkDeviceCreateFlags},
+		[| #{peek VkDeviceCreateInfo, flags} |],
+		[| #{poke VkDeviceCreateInfo, flags} |]),
+	("queueCreateInfoCount", ''#{type uint32_t},
+		[| #{peek VkDeviceCreateInfo, queueCreateInfoCount} |],
+		[| #{poke VkDeviceCreateInfo, queueCreateInfoCount} |]),
+	("pQueueCreateInfos", ''PtrQueueCreateInfo,
+		[| #{peek VkDeviceCreateInfo, pQueueCreateInfos} |],
+		[| #{poke VkDeviceCreateInfo, pQueueCreateInfos} |]),
+	("enabledLayerCount", ''#{type uint32_t},
+		[| #{peek VkDeviceCreateInfo, enabledLayerCount} |],
+		[| #{poke VkDeviceCreateInfo, enabledLayerCount} |]),
+	("ppEnabledLayerNames", ''PtrCString,
+		[| #{peek VkDeviceCreateInfo, ppEnabledLayerNames} |],
+		[| #{poke VkDeviceCreateInfo, ppEnabledLayerNames} |]),
+	("enabledExtensionCount", ''#{type uint32_t},
+		[| #{peek VkDeviceCreateInfo, enabledExtensionCount} |],
+		[| #{poke VkDeviceCreateInfo, enabledExtensionCount} |]),
+	("ppEnabledExtensionNames", ''PtrCString,
+		[| #{peek VkDeviceCreateInfo, ppEnabledExtensionNames} |],
+		[| #{poke VkDeviceCreateInfo, ppEnabledExtensionNames} |]),
+	("pEnabledFeatures", ''PhysicalDevice.PtrFeatures,
+		[| #{peek VkDeviceCreateInfo, pEnabledFeatures} |],
+		[| #{poke VkDeviceCreateInfo, pEnabledFeatures} |])
+	]
+	[''Show, ''Storable]
+
+data DTag
+type D = Ptr DTag
+
+foreign import ccall "vkCreateDevice" create ::
+	PhysicalDevice.P -> Ptr CreateInfo -> Ptr AllocationCallbacks.A ->
+	Ptr D -> IO #{type VkResult}
+
+foreign import ccall "vkDestroyDevice"
+	destroy :: D -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkGetDeviceQueue" getQueue ::
+	D -> #{type uint32_t} -> #{type uint32_t} -> Ptr Queue.Q -> IO ()
+
+foreign import ccall "vkDeviceWaitIdle" waitIdle ::
+	D -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/Fence/Core.hs-boot b/src/Gpu/Vulkan/Fence/Core.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Fence/Core.hs-boot
@@ -0,0 +1,8 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Fence.Core (F) where
+
+import Foreign.Ptr
+
+data FTag
+type F = Ptr FTag
diff --git a/src/Gpu/Vulkan/Fence/Core.hsc b/src/Gpu/Vulkan/Fence/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Fence/Core.hsc
@@ -0,0 +1,60 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Fence.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, F, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+
+	-- * WAIT AND RESET
+
+	waitForFs, resetFs
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_FENCE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkFenceCreateInfo} #{alignment VkFenceCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkFenceCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkFenceCreateInfo, pNext} |],
+		[| #{poke VkFenceCreateInfo, pNext} |]),
+	("flags", ''#{type VkFenceCreateFlags},
+		[| #{peek VkFenceCreateInfo, flags} |],
+		[| #{poke VkFenceCreateInfo, flags} |]) ]
+	[''Show, ''Storable]
+
+data FTag
+type F = Ptr FTag
+
+foreign import ccall "vkCreateFence" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr F ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyFence" destroy ::
+	Device.D -> F -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkWaitForFences" waitForFs ::
+	Device.D -> #{type uint32_t} -> Ptr F -> #{type VkBool32} ->
+	#{type uint64_t} -> IO #{type VkResult}
+
+foreign import ccall "vkResetFences" resetFs ::
+	Device.D -> #{type uint32_t} -> Ptr F -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/Framebuffer/Core.hsc b/src/Gpu/Vulkan/Framebuffer/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Framebuffer/Core.hsc
@@ -0,0 +1,72 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Framebuffer.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, F, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags, createInfoRenderPass,
+	createInfoAttachmentCount, createInfoPAttachments,
+	createInfoWidth, createInfoHeight, createInfoLayers
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import {-# SOURCE #-} qualified Gpu.Vulkan.RenderPass.Core as RenderPass
+import qualified Gpu.Vulkan.ImageView.Core as ImageView
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO}
+
+struct "CreateInfo" #{size VkFramebufferCreateInfo}
+		#{alignment VkFramebufferCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkFramebufferCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkFramebufferCreateInfo, pNext} |],
+		[| #{poke VkFramebufferCreateInfo, pNext} |]),
+	("flags", ''#{type VkFramebufferCreateFlags},
+		[| #{peek VkFramebufferCreateInfo, flags} |],
+		[| #{poke VkFramebufferCreateInfo, flags} |]),
+	("renderPass", ''RenderPass.R,
+		[| #{peek VkFramebufferCreateInfo, renderPass} |],
+		[| #{poke VkFramebufferCreateInfo, renderPass} |]),
+	("attachmentCount", ''#{type uint32_t},
+		[| #{peek VkFramebufferCreateInfo, attachmentCount} |],
+		[| #{poke VkFramebufferCreateInfo, attachmentCount} |]),
+	("pAttachments", ''ImageView.PtrI,
+		[| #{peek VkFramebufferCreateInfo, pAttachments} |],
+		[| #{poke VkFramebufferCreateInfo, pAttachments} |]),
+	("width", ''#{type uint32_t},
+		[| #{peek VkFramebufferCreateInfo, width} |],
+		[| #{poke VkFramebufferCreateInfo, width} |]),
+	("height", ''#{type uint32_t},
+		[| #{peek VkFramebufferCreateInfo, height} |],
+		[| #{poke VkFramebufferCreateInfo, height} |]),
+	("layers", ''#{type uint32_t},
+		[| #{peek VkFramebufferCreateInfo, layers} |],
+		[| #{poke VkFramebufferCreateInfo, layers} |]) ]
+	[''Show, ''Storable]
+
+data FTag
+type F = Ptr FTag
+
+foreign import ccall "vkCreateFramebuffer" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr F ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyFramebuffer" destroy ::
+	Device.D -> F -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Image/Core.hsc b/src/Gpu/Vulkan/Image/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Image/Core.hsc
@@ -0,0 +1,220 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Image.Core (
+
+	-- * CREATE AND DESTROY
+	create, destroy, I, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoImageType, createInfoFormat, createInfoExtent,
+	createInfoMipLevels, createInfoArrayLayers, createInfoSamples,
+	createInfoTiling, createInfoUsage, createInfoSharingMode,
+	createInfoQueueFamilyIndexCount, createInfoPQueueFamilyIndices,
+	createInfoInitialLayout,
+
+	-- * MEMORY: REQUIREMENTS AND BINDING
+
+	getMemoryRequirements, bindMemory,
+
+	-- * MEMORY BARRIER
+
+	MemoryBarrier, pattern MemoryBarrier,
+	memoryBarrierSType, memoryBarrierPNext,
+	memoryBarrierSrcAccessMask, memoryBarrierDstAccessMask,
+	memoryBarrierOldLayout, memoryBarrierNewLayout,
+	memoryBarrierSrcQueueFamilyIndex, memoryBarrierDstQueueFamilyIndex,
+	memoryBarrierImage, memoryBarrierSubresourceRange,
+
+	-- ** SubresourceRange
+
+	SubresourceRange, pattern SubresourceRange,
+	subresourceRangeAspectMask, subresourceRangeBaseMipLevel,
+	subresourceRangeLevelCount, subresourceRangeBaseArrayLayer,
+	subresourceRangeLayerCount,
+
+	-- * BLIT
+	
+	Blit, pattern Blit,
+	blitSrcSubresource, blitSrcOffsets, blitDstSubresource, blitDstOffsets,
+
+	-- ** SubresourceLayers
+
+	SubresourceLayers, pattern SubresourceLayers,
+	subresourceLayersAspectMask, subresourceLayersMipLevel,
+	subresourceLayersBaseArrayLayer, subresourceLayersLayerCount,
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Marshal.Array
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.Core
+import Gpu.Vulkan.TypeSynonyms.Core
+import Gpu.Vulkan.AllocationCallbacks.Core qualified as AllocationCallbacks
+import Gpu.Vulkan.Device.Core qualified as Device
+import Gpu.Vulkan.Memory.Core qualified as Memory
+
+#include <vulkan/vulkan.h>
+
+struct "SubresourceRange" #{size VkImageSubresourceRange}
+		#{alignment VkImageSubresourceRange} [
+	("aspectMask", ''#{type VkImageAspectFlags},
+		[| #{peek VkImageSubresourceRange, aspectMask} |],
+		[| #{poke VkImageSubresourceRange, aspectMask} |]),
+	("baseMipLevel", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceRange, baseMipLevel} |],
+		[| #{poke VkImageSubresourceRange, baseMipLevel} |]),
+	("levelCount", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceRange, levelCount} |],
+		[| #{poke VkImageSubresourceRange, levelCount} |]),
+	("baseArrayLayer", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceRange, baseArrayLayer} |],
+		[| #{poke VkImageSubresourceRange, baseArrayLayer} |]),
+	("layerCount", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceRange, layerCount} |],
+		[| #{poke VkImageSubresourceRange, layerCount} |]) ]
+	[''Show, ''Storable]
+
+data ITag
+type I = Ptr ITag
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkImageCreateInfo} #{alignment VkImageCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkImageCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkImageCreateInfo, pNext} |],
+		[| #{poke VkImageCreateInfo, pNext} |]),
+	("flags", ''#{type VkImageCreateFlags},
+		[| #{peek VkImageCreateInfo, flags} |],
+		[| #{poke VkImageCreateInfo, flags} |]),
+	("imageType", ''#{type VkImageType},
+		[| #{peek VkImageCreateInfo, imageType} |],
+		[| #{poke VkImageCreateInfo, imageType} |]),
+	("format", ''#{type VkFormat},
+		[| #{peek VkImageCreateInfo, format} |],
+		[| #{poke VkImageCreateInfo, format} |]),
+	("extent", ''Extent3d,
+		[| #{peek VkImageCreateInfo, extent} |],
+		[| #{poke VkImageCreateInfo, extent} |]),
+	("mipLevels", ''#{type uint32_t},
+		[| #{peek VkImageCreateInfo, mipLevels} |],
+		[| #{poke VkImageCreateInfo, mipLevels} |]),
+	("arrayLayers", ''#{type uint32_t},
+		[| #{peek VkImageCreateInfo, arrayLayers} |],
+		[| #{poke VkImageCreateInfo, arrayLayers} |]),
+	("samples", ''#{type VkSampleCountFlagBits},
+		[| #{peek VkImageCreateInfo, samples} |],
+		[| #{poke VkImageCreateInfo, samples} |]),
+	("tiling", ''#{type VkImageTiling},
+		[| #{peek VkImageCreateInfo, tiling} |],
+		[| #{poke VkImageCreateInfo, tiling} |]),
+	("usage", ''#{type VkImageUsageFlags},
+		[| #{peek VkImageCreateInfo, usage} |],
+		[| #{poke VkImageCreateInfo, usage} |]),
+	("sharingMode", ''#{type VkSharingMode},
+		[| #{peek VkImageCreateInfo, sharingMode} |],
+		[| #{poke VkImageCreateInfo, sharingMode} |]),
+	("queueFamilyIndexCount", ''#{type uint32_t},
+		[| #{peek VkImageCreateInfo, queueFamilyIndexCount} |],
+		[| #{poke VkImageCreateInfo, queueFamilyIndexCount} |]),
+	("pQueueFamilyIndices", ''PtrUint32T,
+		[| #{peek VkImageCreateInfo, pQueueFamilyIndices} |],
+		[| #{poke VkImageCreateInfo, pQueueFamilyIndices} |]),
+	("initialLayout", ''#{type VkImageLayout},
+		[| #{peek VkImageCreateInfo, initialLayout} |],
+		[| #{poke VkImageCreateInfo, initialLayout} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkCreateImage" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr I ->
+	IO #{type VkResult}
+
+foreign import ccall "vkGetImageMemoryRequirements" getMemoryRequirements ::
+	Device.D -> I -> Ptr Memory.Requirements -> IO ()
+
+foreign import ccall "vkBindImageMemory" bindMemory ::
+	Device.D -> I -> Memory.M -> #{type VkDeviceSize} ->
+	IO #{type VkResult}
+
+mbType :: #{type VkStructureType}
+mbType = #{const VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}
+
+struct "MemoryBarrier" #{size VkImageMemoryBarrier}
+		#{alignment VkImageMemoryBarrier} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkImageMemoryBarrier, sType} p mbType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkImageMemoryBarrier, pNext} |],
+		[| #{poke VkImageMemoryBarrier, pNext} |]),
+	("srcAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkImageMemoryBarrier, srcAccessMask} |],
+		[| #{poke VkImageMemoryBarrier, srcAccessMask} |]),
+	("dstAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkImageMemoryBarrier, dstAccessMask} |],
+		[| #{poke VkImageMemoryBarrier, dstAccessMask} |]),
+	("oldLayout", ''#{type VkImageLayout},
+		[| #{peek VkImageMemoryBarrier, oldLayout} |],
+		[| #{poke VkImageMemoryBarrier, oldLayout} |]),
+	("newLayout", ''#{type VkImageLayout},
+		[| #{peek VkImageMemoryBarrier, newLayout} |],
+		[| #{poke VkImageMemoryBarrier, newLayout} |]),
+	("srcQueueFamilyIndex", ''#{type uint32_t},
+		[| #{peek VkImageMemoryBarrier, srcQueueFamilyIndex} |],
+		[| #{poke VkImageMemoryBarrier, srcQueueFamilyIndex} |]),
+	("dstQueueFamilyIndex", ''#{type uint32_t},
+		[| #{peek VkImageMemoryBarrier, dstQueueFamilyIndex} |],
+		[| #{poke VkImageMemoryBarrier, dstQueueFamilyIndex} |]),
+	("image", ''I,
+		[| #{peek VkImageMemoryBarrier, image} |],
+		[| #{poke VkImageMemoryBarrier, image} |]),
+	("subresourceRange", ''SubresourceRange,
+		[| #{peek VkImageMemoryBarrier, subresourceRange} |],
+		[| #{poke VkImageMemoryBarrier, subresourceRange} |]) ]
+	[''Show, ''Storable]
+
+struct "SubresourceLayers" #{size VkImageSubresourceLayers}
+		#{alignment VkImageSubresourceLayers} [
+	("aspectMask", ''#{type VkImageAspectFlags},
+		[| #{peek VkImageSubresourceLayers, aspectMask} |],
+		[| #{poke VkImageSubresourceLayers, aspectMask} |]),
+	("mipLevel", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceLayers, mipLevel} |],
+		[| #{poke VkImageSubresourceLayers, mipLevel} |]),
+	("baseArrayLayer", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceLayers, baseArrayLayer} |],
+		[| #{poke VkImageSubresourceLayers, baseArrayLayer} |]),
+	("layerCount", ''#{type uint32_t},
+		[| #{peek VkImageSubresourceLayers, layerCount} |],
+		[| #{poke VkImageSubresourceLayers, layerCount} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkDestroyImage" destroy ::
+	Device.D -> I -> Ptr AllocationCallbacks.A -> IO ()
+
+struct "Blit" #{size VkImageBlit} #{alignment VkImageBlit} [
+	("srcSubresource", ''SubresourceLayers,
+		[| #{peek VkImageBlit, srcSubresource} |],
+		[| #{poke VkImageBlit, srcSubresource} |]),
+	("srcOffsets", ''ListOffset3d,
+		[| \p -> peekArray 2 (#{ptr VkImageBlit, srcOffsets} p) |],
+		[| \p os -> pokeArray
+			(#{ptr VkImageBlit, srcOffsets} p) $ take 2 os |]),
+	("dstSubresource", ''SubresourceLayers,
+		[| #{peek VkImageBlit, dstSubresource} |],
+		[| #{poke VkImageBlit, dstSubresource} |]),
+	("dstOffsets", ''ListOffset3d,
+		[| \p -> peekArray 2 (#{ptr VkImageBlit, dstOffsets} p) |],
+		[| \p os -> pokeArray
+			(#{ptr VkImageBlit, dstOffsets} p) $ take 2 os |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/ImageView/Core.hsc b/src/Gpu/Vulkan/ImageView/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/ImageView/Core.hsc
@@ -0,0 +1,70 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.ImageView.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, I, PtrI, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoImage, createInfoViewType, createInfoFormat,
+	createInfoComponents, createInfoSubresourceRange,
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.Image.Core as Image
+import qualified Gpu.Vulkan.Component.Core as Component
+
+#include <vulkan/vulkan.h>
+
+data ITag
+type I = Ptr ITag
+type PtrI = Ptr I
+
+strType :: #{type VkStructureType}
+strType = #{const VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}
+
+struct "CreateInfo" #{size VkImageViewCreateInfo}
+		#{alignment VkImageViewCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkImageViewCreateInfo, sType} p strType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkImageViewCreateInfo, pNext} |],
+		[| #{poke VkImageViewCreateInfo, pNext} |]),
+	("flags", ''#{type VkImageViewCreateFlags},
+		[| #{peek VkImageViewCreateInfo, flags} |],
+		[| #{poke VkImageViewCreateInfo, flags} |]),
+	("image", ''Image.I,
+		[| #{peek VkImageViewCreateInfo, image} |],
+		[| #{poke VkImageViewCreateInfo, image} |]),
+	("viewType", ''#{type VkImageViewType},
+		[| #{peek VkImageViewCreateInfo, viewType} |],
+		[| #{poke VkImageViewCreateInfo, viewType} |]),
+	("format", ''#{type VkFormat},
+		[| #{peek VkImageViewCreateInfo, format} |],
+		[| #{poke VkImageViewCreateInfo, format} |]),
+	("components", ''Component.Mapping,
+		[| #{peek VkImageViewCreateInfo, components} |],
+		[| #{poke VkImageViewCreateInfo, components} |]),
+	("subresourceRange", ''Image.SubresourceRange,
+		[| #{peek VkImageViewCreateInfo, subresourceRange} |],
+		[| #{poke VkImageViewCreateInfo, subresourceRange} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkCreateImageView" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr I ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyImageView" destroy ::
+	Device.D -> I -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Instance/Core.hsc b/src/Gpu/Vulkan/Instance/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Instance/Core.hsc
@@ -0,0 +1,80 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Instance.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, I, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoPApplicationInfo,
+	createInfoEnabledLayerCount, createInfoPpEnabledLayerNames,
+	createInfoEnabledExtensionCount, createInfoPpEnabledExtensionNames,
+
+	-- * ENUMERATE
+
+	enumerateLayerProperties, enumerateExtensionProperties
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.String
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.Core
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+
+#include <vulkan/vulkan.h>
+
+struct "CreateInfo" #{size VkInstanceCreateInfo}
+		#{alignment VkInstanceCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkInstanceCreateInfo, sType} p
+			(#{const VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO} ::
+				#{type VkStructureType}) |]),
+	("pNext", ''PtrVoid, [| #{peek VkInstanceCreateInfo, pNext} |],
+		[| #{poke VkInstanceCreateInfo, pNext} |]),
+	("flags", ''#{type VkInstanceCreateFlags},
+		[| #{peek VkInstanceCreateInfo, flags} |],
+		[| #{poke VkInstanceCreateInfo, flags} |]),
+	("pApplicationInfo", ''PtrApplicationInfo,
+		[| #{peek VkInstanceCreateInfo, pApplicationInfo} |],
+		[| #{poke VkInstanceCreateInfo, pApplicationInfo} |]),
+	("enabledLayerCount", ''#{type uint32_t},
+		[| #{peek VkInstanceCreateInfo, enabledLayerCount} |],
+		[| #{poke VkInstanceCreateInfo, enabledLayerCount} |]),
+	("ppEnabledLayerNames", ''PtrCString,
+		[| #{peek VkInstanceCreateInfo, ppEnabledLayerNames} |],
+		[| #{poke VkInstanceCreateInfo, ppEnabledLayerNames} |]),
+	("enabledExtensionCount", ''#{type uint32_t},
+		[| #{peek VkInstanceCreateInfo, enabledExtensionCount} |],
+		[| #{poke VkInstanceCreateInfo, enabledExtensionCount} |]),
+	("ppEnabledExtensionNames", ''PtrCString,
+		[| #{peek VkInstanceCreateInfo, ppEnabledExtensionNames} |],
+		[| #{poke VkInstanceCreateInfo, ppEnabledExtensionNames} |]) ]
+	[''Show, ''Storable]
+
+data ITag
+type I = Ptr ITag
+
+foreign import ccall "vkCreateInstance" create ::
+	Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr I -> IO #{type VkResult}
+
+foreign import ccall "vkDestroyInstance" destroy ::
+	I -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkEnumerateInstanceExtensionProperties"
+	enumerateExtensionProperties ::
+	CString -> Ptr #{type uint32_t} -> Ptr ExtensionProperties ->
+	IO #{type VkResult}
+
+foreign import ccall "vkEnumerateInstanceLayerProperties"
+	enumerateLayerProperties ::
+	Ptr #{type uint32_t} -> Ptr LayerProperties -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/Memory/Core.hsc b/src/Gpu/Vulkan/Memory/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Memory/Core.hsc
@@ -0,0 +1,141 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Memory.Core (
+
+	-- * ALLOCATE AND FREE
+
+	allocate, free, M, AllocateInfo, pattern AllocateInfo,
+	allocateInfoSType, allocateInfoPNext, allocateInfoAllocationSize,
+	allocateInfoMemoryTypeIndex,
+
+	-- * MAP AND UNMAP
+
+	map, unmap,
+
+	-- * REQUIREMENTS
+
+	Requirements, pattern Requirements,
+	requirementsSize, requirementsAlignment, requirementsMemoryTypeBits,
+
+	-- * TYPE
+
+	MType, ListMType, pattern MType, mTypePropertyFlags, mTypeHeapIndex, maxTypes,
+
+	-- * HEAP
+
+	Heap, ListHeap, pattern Heap, heapSize, heapFlags, maxHeaps,
+
+	-- * BARRIER
+
+	Barrier, pattern Barrier,
+	barrierSType, barrierPNext, barrierSrcAccessMask, barrierDstAccessMask
+
+	) where
+
+import Prelude hiding (map)
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+
+import {-# SOURCE #-} qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+data MTag
+type M = Ptr MTag
+
+struct "Requirements" #{size VkMemoryRequirements}
+		#{alignment VkMemoryRequirements} [
+	("size", ''#{type VkDeviceSize},
+		[| #{peek VkMemoryRequirements, size} |],
+		[| #{poke VkMemoryRequirements, size} |]),
+	("alignment", ''#{type VkDeviceSize},
+		[| #{peek VkMemoryRequirements, alignment} |],
+		[| #{poke VkMemoryRequirements, alignment} |]),
+	("memoryTypeBits", ''#{type uint32_t},
+		[| #{peek VkMemoryRequirements, memoryTypeBits} |],
+		[| #{poke VkMemoryRequirements, memoryTypeBits} |]) ]
+	[''Show, ''Storable]
+
+struct "MType" #{size VkMemoryType} #{alignment VkMemoryType} [
+	("propertyFlags", ''#{type VkMemoryPropertyFlags},
+		[| #{peek VkMemoryType, propertyFlags} |],
+		[| #{poke VkMemoryType, propertyFlags} |]),
+	("heapIndex", ''#{type uint32_t},
+		[| #{peek VkMemoryType, heapIndex} |],
+		[| #{poke VkMemoryType, heapIndex} |]) ]
+	[''Show, ''Storable]
+
+type ListMType = [MType]
+
+struct "Heap" #{size VkMemoryHeap} #{alignment VkMemoryHeap} [
+	("size", ''#{type VkDeviceSize},
+		[| #{peek VkMemoryHeap, size} |],
+		[| #{poke VkMemoryHeap, size} |]),
+	("flags", ''#{type VkMemoryHeapFlags},
+		[| #{peek VkMemoryHeap, flags} |],
+		[| #{poke VkMemoryHeap, flags} |]) ]
+	[''Show, ''Storable]
+
+type ListHeap = [Heap]
+
+maxTypes, maxHeaps :: Integral n => n
+maxTypes = #{const VK_MAX_MEMORY_TYPES}
+maxHeaps = #{const VK_MAX_MEMORY_HEAPS}
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}
+
+struct "AllocateInfo" #{size VkMemoryAllocateInfo}
+		#{alignment VkMemoryAllocateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkMemoryAllocateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkMemoryAllocateInfo, pNext} |],
+		[| #{poke VkMemoryAllocateInfo, pNext} |]),
+	("allocationSize", ''#{type VkDeviceSize},
+		[| #{peek VkMemoryAllocateInfo, allocationSize} |],
+		[| #{poke VkMemoryAllocateInfo, allocationSize} |]),
+	("memoryTypeIndex", ''#{type uint32_t},
+		[| #{peek VkMemoryAllocateInfo, memoryTypeIndex} |],
+		[| #{poke VkMemoryAllocateInfo, memoryTypeIndex} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkAllocateMemory" allocate ::
+	Device.D -> Ptr AllocateInfo -> Ptr AllocationCallbacks.A ->
+	Ptr M -> IO #{type VkResult}
+
+foreign import ccall "vkFreeMemory" free ::
+	Device.D -> M -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkMapMemory" map ::
+	Device.D -> M -> #{type VkDeviceSize} -> #{type VkDeviceSize} ->
+	#{type VkMemoryMapFlags} -> Ptr (Ptr a) -> IO #{type VkResult}
+
+foreign import ccall "vkUnmapMemory" unmap :: Device.D -> M -> IO ()
+
+bType :: #{type VkStructureType}
+bType = #{const VK_STRUCTURE_TYPE_MEMORY_BARRIER}
+
+struct "Barrier" #{size VkMemoryBarrier} #{alignment VkMemoryBarrier} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkMemoryBarrier, sType} p bType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkMemoryBarrier, pNext} |],
+		[| #{poke VkMemoryBarrier, pNext} |]),
+	("srcAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkMemoryBarrier, srcAccessMask} |],
+		[| #{poke VkMemoryBarrier, srcAccessMask} |]),
+	("dstAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkMemoryBarrier, dstAccessMask} |],
+		[| #{poke VkMemoryBarrier, dstAccessMask} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/PhysicalDevice/Core.hsc b/src/Gpu/Vulkan/PhysicalDevice/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/PhysicalDevice/Core.hsc
@@ -0,0 +1,263 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.PhysicalDevice.Core (
+
+	-- * ENUMERATE
+
+	enumerate, P,
+
+	-- * PROPERTIES
+
+	getProperties, Properties, pattern Properties,
+	propertiesApiVersion, propertiesDriverVersion,
+	propertiesVendorId, propertiesDeviceId,
+	propertiesDeviceType, propertiesDeviceName,
+	propertiesPipelineCacheUuid, propertiesLimits,
+	propertiesSparseProperties,
+
+	-- ** SparseProperties
+
+	SparseProperties, pattern SparseProperties,
+	sparsePropertiesResidencyStandard2DBlockShape,
+	sparsePropertiesResidencyStandard2DMultisampleBlockShape,
+	sparsePropertiesResidencyStandard3DBlockShape,
+	sparsePropertiesResidencyAlignedMipSize,
+	sparsePropertiesResidencyNonResidentStrict,
+
+	-- ** ExtensionProperties
+
+	enumerateExtensionProperties,
+
+	-- ** QqueueFamilyProperties
+
+	getQueueFamilyProperties,
+
+	-- ** MemoryProperties
+
+	getMemoryProperties, MemoryProperties, pattern MemoryProperties,
+	memoryPropertiesMemoryTypeCount, memoryPropertiesMemoryTypes,
+	memoryPropertiesMemoryHeapCount, memoryPropertiesMemoryHeaps,
+
+	-- ** FormatProperties
+
+	getFormatProperties,
+
+	-- * FEATURES
+
+	-- ** Get Features
+
+	getFeatures, Features, pattern Features, getClearedFeatures,
+
+	-- ** Get Features 2
+
+	getFeatures2, Features2,
+	pattern Features2, features2SType, features2PNext, features2Features,
+
+	-- ** ShaderDrawParametersFeatures
+
+	ShaderDrawParametersFeatures, pattern ShaderDrawParametersFeatures,
+	shaderDrawParametersFeaturesSType, shaderDrawParametersFeaturesPNext,
+	shaderDrawParametersFeaturesShaderDrawParameters
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Concurrent
+import Foreign.Marshal
+import Foreign.Storable
+import Foreign.C.String
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+import Data.Text.Tools
+
+import qualified Data.Text as T
+
+-- import Gpu.Vulkan.Base
+
+import Gpu.Vulkan.Core (ExtensionProperties, FormatProperties)
+import Gpu.Vulkan.TypeSynonyms.Core
+import Gpu.Vulkan.PhysicalDevice.Struct.Core
+
+import qualified Gpu.Vulkan.Instance.Core as Instance
+import qualified Gpu.Vulkan.QueueFamily.Core as QueueFamily
+import qualified Gpu.Vulkan.Memory.Core as Memory
+
+#include <vulkan/vulkan.h>
+
+data PTag
+type P = Ptr PTag
+
+foreign import ccall "vkEnumeratePhysicalDevices" enumerate ::
+	Instance.I -> Ptr #{type uint32_t} -> Ptr P ->
+	IO #{type VkResult}
+
+struct "SparseProperties" #{size VkPhysicalDeviceSparseProperties}
+		#{alignment VkPhysicalDeviceSparseProperties} [
+	("residencyStandard2DBlockShape", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceSparseProperties,
+			residencyStandard2DBlockShape} |],
+		[| #{poke VkPhysicalDeviceSparseProperties,
+			residencyStandard2DBlockShape} |]),
+	("residencyStandard2DMultisampleBlockShape", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceSparseProperties,
+			residencyStandard2DMultisampleBlockShape} |],
+		[| #{poke VkPhysicalDeviceSparseProperties,
+			residencyStandard2DMultisampleBlockShape} |]),
+	("residencyStandard3DBlockShape", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceSparseProperties,
+			residencyStandard3DBlockShape} |],
+		[| #{poke VkPhysicalDeviceSparseProperties,
+			residencyStandard3DBlockShape} |]),
+	("residencyAlignedMipSize", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceSparseProperties,
+			residencyAlignedMipSize} |],
+		[| #{poke VkPhysicalDeviceSparseProperties,
+			residencyAlignedMipSize} |]),
+	("residencyNonResidentStrict", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceSparseProperties,
+			residencyNonResidentStrict} |],
+		[| #{poke VkPhysicalDeviceSparseProperties,
+			residencyNonResidentStrict} |]) ]
+	[''Show, ''Storable]
+
+struct "Properties" #{size VkPhysicalDeviceProperties}
+		#{alignment VkPhysicalDeviceProperties} [
+	("apiVersion", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceProperties, apiVersion} |],
+		[| #{poke VkPhysicalDeviceProperties, apiVersion} |]),
+	("driverVersion", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceProperties, driverVersion} |],
+		[| #{poke VkPhysicalDeviceProperties, driverVersion} |]),
+	("vendorId", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceProperties, vendorID} |],
+		[| #{poke VkPhysicalDeviceProperties, vendorID} |]),
+	("deviceId", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceProperties, deviceID} |],
+		[| #{poke VkPhysicalDeviceProperties, deviceID} |]),
+	("deviceType", ''#{type VkPhysicalDeviceType},
+		[| #{peek VkPhysicalDeviceProperties, deviceType} |],
+		[| #{poke VkPhysicalDeviceProperties, deviceType} |]),
+	("deviceName", ''T.Text,
+		[| cstringToText
+			. #{ptr VkPhysicalDeviceProperties, deviceName} |],
+		[| \p -> pokeText maxNameSize
+			(#{ptr VkPhysicalDeviceProperties, deviceName} p) |]),
+	("pipelineCacheUuid", ''ListUint8T,
+		[| peekArray #{const VK_UUID_SIZE}
+			. #{ptr VkPhysicalDeviceProperties, pipelineCacheUUID}
+			|],
+		[| \p -> pokeArray
+			(#{ptr VkPhysicalDeviceProperties, pipelineCacheUUID} p)
+				. take #{const VK_UUID_SIZE} |]),
+	("limits", ''Limits,
+		[| #{peek VkPhysicalDeviceProperties, limits} |],
+		[| #{poke VkPhysicalDeviceProperties, limits} |]),
+	("sparseProperties", ''SparseProperties,
+		[| #{peek VkPhysicalDeviceProperties, sparseProperties} |],
+		[| #{poke VkPhysicalDeviceProperties, sparseProperties} |]) ]
+	[''Show, ''Storable]
+
+maxNameSize :: Integral n => n
+maxNameSize = #{const VK_MAX_PHYSICAL_DEVICE_NAME_SIZE}
+
+foreign import ccall "vkGetPhysicalDeviceProperties" getProperties ::
+	P -> Ptr Properties -> IO ()
+
+getClearedFeatures :: IO Features
+getClearedFeatures = do
+	pf <- calloc
+	Features_ <$> newForeignPtr pf (free pf)
+
+foreign import ccall "vkGetPhysicalDeviceFeatures" getFeatures ::
+	P -> Ptr Features -> IO ()
+
+sTypeFeatures2 :: #{type VkStructureType}
+sTypeFeatures2 = #{const VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}
+
+struct "Features2"
+	#{size VkPhysicalDeviceFeatures2}
+	#{alignment VkPhysicalDeviceFeatures2} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPhysicalDeviceFeatures2, sType}
+			p sTypeFeatures2 |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPhysicalDeviceFeatures2, pNext} |],
+		[| #{poke VkPhysicalDeviceFeatures2, pNext} |]),
+	("features", ''Features,
+		[| peek . #{ptr VkPhysicalDeviceFeatures2, features} |],
+		[| poke . #{ptr VkPhysicalDeviceFeatures2, features} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkGetPhysicalDeviceFeatures2" getFeatures2 ::
+	P -> Ptr Features2 -> IO ()
+
+foreign import ccall "vkGetPhysicalDeviceQueueFamilyProperties"
+	getQueueFamilyProperties ::
+	P -> Ptr #{type uint32_t} -> Ptr QueueFamily.Properties ->
+	IO ()
+
+foreign import ccall "vkEnumerateDeviceExtensionProperties"
+	enumerateExtensionProperties ::
+	P -> CString -> Ptr #{type uint32_t} ->
+	Ptr ExtensionProperties -> IO #{type VkResult}
+
+struct "MemoryProperties" #{size VkPhysicalDeviceMemoryProperties}
+		#{alignment VkPhysicalDeviceMemoryProperties} [
+	("memoryTypeCount", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceMemoryProperties, memoryTypeCount} |],
+		[| #{poke
+			VkPhysicalDeviceMemoryProperties, memoryTypeCount} |]),
+	("memoryTypes", ''Memory.ListMType,
+		[| \p -> peekArray Memory.maxTypes
+			$ #{ptr VkPhysicalDeviceMemoryProperties, memoryTypes} p
+			|],
+		[| \p -> pokeArray
+				(#{ptr VkPhysicalDeviceMemoryProperties,
+					memoryTypes} p)
+			. take Memory.maxTypes |]),
+	("memoryHeapCount", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceMemoryProperties, memoryHeapCount} |],
+		[| #{poke
+			VkPhysicalDeviceMemoryProperties, memoryHeapCount} |]),
+	("memoryHeaps", ''Memory.ListHeap,
+		[| \p -> peekArray Memory.maxHeaps
+			$ #{ptr VkPhysicalDeviceMemoryProperties, memoryHeaps} p
+			|],
+		[| \p -> pokeArray
+				(#{ptr VkPhysicalDeviceMemoryProperties,
+					memoryHeaps} p) .
+			take Memory.maxHeaps |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkGetPhysicalDeviceMemoryProperties"
+	getMemoryProperties :: P -> Ptr MemoryProperties -> IO ()
+
+foreign import ccall "vkGetPhysicalDeviceFormatProperties"
+	getFormatProperties ::
+	P -> #{type VkFormat} -> Ptr FormatProperties -> IO ()
+
+shaderDrawParametersFeaturesType :: #{type VkStructureType}
+shaderDrawParametersFeaturesType =
+	#{const VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES}
+
+struct "ShaderDrawParametersFeatures"
+	#{size VkPhysicalDeviceShaderDrawParametersFeatures}
+	#{alignment VkPhysicalDeviceShaderDrawParametersFeatures} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ ->
+			#{poke VkPhysicalDeviceShaderDrawParametersFeatures,
+				sType} p shaderDrawParametersFeaturesType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPhysicalDeviceShaderDrawParametersFeatures, pNext} |],
+		[| #{poke VkPhysicalDeviceShaderDrawParametersFeatures, pNext} |]),
+	("shaderDrawParameters", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceShaderDrawParametersFeatures,
+			shaderDrawParameters} |],
+		[| #{poke VkPhysicalDeviceShaderDrawParametersFeatures,
+			shaderDrawParameters} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/PhysicalDevice/Struct/Core.hsc b/src/Gpu/Vulkan/PhysicalDevice/Struct/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/PhysicalDevice/Struct/Core.hsc
@@ -0,0 +1,586 @@
+
+-- This file is automatically generated by the tools/makeStruct.hs
+--	% stack runghc --cwd tools/ makeStruct
+
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.PhysicalDevice.Struct.Core where
+
+import Foreign.Ptr
+import Foreign.Marshal.Array
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.TypeSynonyms.Core
+
+#include <vulkan/vulkan.h>
+
+struct "Limits" #{size VkPhysicalDeviceLimits}
+		#{alignment VkPhysicalDeviceLimits} [
+	("maxImageDimension1D", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxImageDimension1D} |],
+		[| #{poke VkPhysicalDeviceLimits, maxImageDimension1D} |]),
+	("maxImageDimension2D", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxImageDimension2D} |],
+		[| #{poke VkPhysicalDeviceLimits, maxImageDimension2D} |]),
+	("maxImageDimension3D", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxImageDimension3D} |],
+		[| #{poke VkPhysicalDeviceLimits, maxImageDimension3D} |]),
+	("maxImageDimensionCube", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxImageDimensionCube} |],
+		[| #{poke VkPhysicalDeviceLimits, maxImageDimensionCube} |]),
+	("maxImageArrayLayers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxImageArrayLayers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxImageArrayLayers} |]),
+	("maxTexelBufferElements", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTexelBufferElements} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTexelBufferElements} |]),
+	("maxUniformBufferRange", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxUniformBufferRange} |],
+		[| #{poke VkPhysicalDeviceLimits, maxUniformBufferRange} |]),
+	("maxStorageBufferRange", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxStorageBufferRange} |],
+		[| #{poke VkPhysicalDeviceLimits, maxStorageBufferRange} |]),
+	("maxPushConstantsSize", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPushConstantsSize} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPushConstantsSize} |]),
+	("maxMemoryAllocationCount", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxMemoryAllocationCount} |],
+		[| #{poke VkPhysicalDeviceLimits, maxMemoryAllocationCount} |]),
+	("maxSamplerAllocationCount", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxSamplerAllocationCount} |],
+		[| #{poke VkPhysicalDeviceLimits, maxSamplerAllocationCount} |]),
+	("bufferImageGranularity", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, bufferImageGranularity} |],
+		[| #{poke VkPhysicalDeviceLimits, bufferImageGranularity} |]),
+	("sparseAddressSpaceSize", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, sparseAddressSpaceSize} |],
+		[| #{poke VkPhysicalDeviceLimits, sparseAddressSpaceSize} |]),
+	("maxBoundDescriptorSets", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxBoundDescriptorSets} |],
+		[| #{poke VkPhysicalDeviceLimits, maxBoundDescriptorSets} |]),
+	("maxPerStageDescriptorSamplers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageDescriptorSamplers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageDescriptorSamplers} |]),
+	("maxPerStageDescriptorUniformBuffers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageDescriptorUniformBuffers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageDescriptorUniformBuffers} |]),
+	("maxPerStageDescriptorStorageBuffers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageDescriptorStorageBuffers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageDescriptorStorageBuffers} |]),
+	("maxPerStageDescriptorSampledImages", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageDescriptorSampledImages} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageDescriptorSampledImages} |]),
+	("maxPerStageDescriptorStorageImages", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageDescriptorStorageImages} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageDescriptorStorageImages} |]),
+	("maxPerStageDescriptorInputAttachments", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageDescriptorInputAttachments} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageDescriptorInputAttachments} |]),
+	("maxPerStageResources", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxPerStageResources} |],
+		[| #{poke VkPhysicalDeviceLimits, maxPerStageResources} |]),
+	("maxDescriptorSetSamplers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetSamplers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetSamplers} |]),
+	("maxDescriptorSetUniformBuffers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetUniformBuffers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetUniformBuffers} |]),
+	("maxDescriptorSetUniformBuffersDynamic", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetUniformBuffersDynamic} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetUniformBuffersDynamic} |]),
+	("maxDescriptorSetStorageBuffers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetStorageBuffers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetStorageBuffers} |]),
+	("maxDescriptorSetStorageBuffersDynamic", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetStorageBuffersDynamic} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetStorageBuffersDynamic} |]),
+	("maxDescriptorSetSampledImages", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetSampledImages} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetSampledImages} |]),
+	("maxDescriptorSetStorageImages", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetStorageImages} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetStorageImages} |]),
+	("maxDescriptorSetInputAttachments", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDescriptorSetInputAttachments} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDescriptorSetInputAttachments} |]),
+	("maxVertexInputAttributes", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxVertexInputAttributes} |],
+		[| #{poke VkPhysicalDeviceLimits, maxVertexInputAttributes} |]),
+	("maxVertexInputBindings", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxVertexInputBindings} |],
+		[| #{poke VkPhysicalDeviceLimits, maxVertexInputBindings} |]),
+	("maxVertexInputAttributeOffset", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxVertexInputAttributeOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, maxVertexInputAttributeOffset} |]),
+	("maxVertexInputBindingStride", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxVertexInputBindingStride} |],
+		[| #{poke VkPhysicalDeviceLimits, maxVertexInputBindingStride} |]),
+	("maxVertexOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxVertexOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxVertexOutputComponents} |]),
+	("maxTessellationGenerationLevel", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationGenerationLevel} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationGenerationLevel} |]),
+	("maxTessellationPatchSize", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationPatchSize} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationPatchSize} |]),
+	("maxTessellationControlPerVertexInputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationControlPerVertexInputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationControlPerVertexInputComponents} |]),
+	("maxTessellationControlPerVertexOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationControlPerVertexOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationControlPerVertexOutputComponents} |]),
+	("maxTessellationControlPerPatchOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationControlPerPatchOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationControlPerPatchOutputComponents} |]),
+	("maxTessellationControlTotalOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationControlTotalOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationControlTotalOutputComponents} |]),
+	("maxTessellationEvaluationInputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationEvaluationInputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationEvaluationInputComponents} |]),
+	("maxTessellationEvaluationOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTessellationEvaluationOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTessellationEvaluationOutputComponents} |]),
+	("maxGeometryShaderInvocations", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxGeometryShaderInvocations} |],
+		[| #{poke VkPhysicalDeviceLimits, maxGeometryShaderInvocations} |]),
+	("maxGeometryInputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxGeometryInputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxGeometryInputComponents} |]),
+	("maxGeometryOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxGeometryOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxGeometryOutputComponents} |]),
+	("maxGeometryOutputVertices", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxGeometryOutputVertices} |],
+		[| #{poke VkPhysicalDeviceLimits, maxGeometryOutputVertices} |]),
+	("maxGeometryTotalOutputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxGeometryTotalOutputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxGeometryTotalOutputComponents} |]),
+	("maxFragmentInputComponents", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFragmentInputComponents} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFragmentInputComponents} |]),
+	("maxFragmentOutputAttachments", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFragmentOutputAttachments} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFragmentOutputAttachments} |]),
+	("maxFragmentDualSrcAttachments", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFragmentDualSrcAttachments} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFragmentDualSrcAttachments} |]),
+	("maxFragmentCombinedOutputResources", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFragmentCombinedOutputResources} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFragmentCombinedOutputResources} |]),
+	("maxComputeSharedMemorySize", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxComputeSharedMemorySize} |],
+		[| #{poke VkPhysicalDeviceLimits, maxComputeSharedMemorySize} |]),
+	("maxComputeWorkGroupCount", ''ListUint32T,
+		[| peekArray 3 . #{ptr VkPhysicalDeviceLimits, maxComputeWorkGroupCount}|],
+		[| pokeArray . #{ptr VkPhysicalDeviceLimits, maxComputeWorkGroupCount} |]),
+	("maxComputeWorkGroupInvocations", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxComputeWorkGroupInvocations} |],
+		[| #{poke VkPhysicalDeviceLimits, maxComputeWorkGroupInvocations} |]),
+	("maxComputeWorkGroupSize", ''ListUint32T,
+		[| peekArray 3 . #{ptr VkPhysicalDeviceLimits, maxComputeWorkGroupSize}|],
+		[| pokeArray . #{ptr VkPhysicalDeviceLimits, maxComputeWorkGroupSize} |]),
+	("subPixelPrecisionBits", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, subPixelPrecisionBits} |],
+		[| #{poke VkPhysicalDeviceLimits, subPixelPrecisionBits} |]),
+	("subTexelPrecisionBits", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, subTexelPrecisionBits} |],
+		[| #{poke VkPhysicalDeviceLimits, subTexelPrecisionBits} |]),
+	("mipmapPrecisionBits", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, mipmapPrecisionBits} |],
+		[| #{poke VkPhysicalDeviceLimits, mipmapPrecisionBits} |]),
+	("maxDrawIndexedIndexValue", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDrawIndexedIndexValue} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDrawIndexedIndexValue} |]),
+	("maxDrawIndirectCount", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxDrawIndirectCount} |],
+		[| #{poke VkPhysicalDeviceLimits, maxDrawIndirectCount} |]),
+	("maxSamplerLodBias", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, maxSamplerLodBias} |],
+		[| #{poke VkPhysicalDeviceLimits, maxSamplerLodBias} |]),
+	("maxSamplerAnisotropy", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, maxSamplerAnisotropy} |],
+		[| #{poke VkPhysicalDeviceLimits, maxSamplerAnisotropy} |]),
+	("maxViewports", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxViewports} |],
+		[| #{poke VkPhysicalDeviceLimits, maxViewports} |]),
+	("maxViewportDimensions", ''ListUint32T,
+		[| peekArray 2 . #{ptr VkPhysicalDeviceLimits, maxViewportDimensions}|],
+		[| pokeArray . #{ptr VkPhysicalDeviceLimits, maxViewportDimensions} |]),
+	("viewportBoundsRange", ''ListFloat,
+		[| peekArray 2 . #{ptr VkPhysicalDeviceLimits, viewportBoundsRange}|],
+		[| pokeArray . #{ptr VkPhysicalDeviceLimits, viewportBoundsRange} |]),
+	("viewportSubPixelBits", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, viewportSubPixelBits} |],
+		[| #{poke VkPhysicalDeviceLimits, viewportSubPixelBits} |]),
+	("minMemoryMapAlignment", ''#{type size_t},
+		[| #{peek VkPhysicalDeviceLimits, minMemoryMapAlignment} |],
+		[| #{poke VkPhysicalDeviceLimits, minMemoryMapAlignment} |]),
+	("minTexelBufferOffsetAlignment", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, minTexelBufferOffsetAlignment} |],
+		[| #{poke VkPhysicalDeviceLimits, minTexelBufferOffsetAlignment} |]),
+	("minUniformBufferOffsetAlignment", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, minUniformBufferOffsetAlignment} |],
+		[| #{poke VkPhysicalDeviceLimits, minUniformBufferOffsetAlignment} |]),
+	("minStorageBufferOffsetAlignment", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, minStorageBufferOffsetAlignment} |],
+		[| #{poke VkPhysicalDeviceLimits, minStorageBufferOffsetAlignment} |]),
+	("minTexelOffset", ''#{type int32_t},
+		[| #{peek VkPhysicalDeviceLimits, minTexelOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, minTexelOffset} |]),
+	("maxTexelOffset", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTexelOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTexelOffset} |]),
+	("minTexelGatherOffset", ''#{type int32_t},
+		[| #{peek VkPhysicalDeviceLimits, minTexelGatherOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, minTexelGatherOffset} |]),
+	("maxTexelGatherOffset", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxTexelGatherOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, maxTexelGatherOffset} |]),
+	("minInterpolationOffset", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, minInterpolationOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, minInterpolationOffset} |]),
+	("maxInterpolationOffset", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, maxInterpolationOffset} |],
+		[| #{poke VkPhysicalDeviceLimits, maxInterpolationOffset} |]),
+	("subPixelInterpolationOffsetBits", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, subPixelInterpolationOffsetBits} |],
+		[| #{poke VkPhysicalDeviceLimits, subPixelInterpolationOffsetBits} |]),
+	("maxFramebufferWidth", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFramebufferWidth} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFramebufferWidth} |]),
+	("maxFramebufferHeight", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFramebufferHeight} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFramebufferHeight} |]),
+	("maxFramebufferLayers", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxFramebufferLayers} |],
+		[| #{poke VkPhysicalDeviceLimits, maxFramebufferLayers} |]),
+	("framebufferColorSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, framebufferColorSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, framebufferColorSampleCounts} |]),
+	("framebufferDepthSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, framebufferDepthSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, framebufferDepthSampleCounts} |]),
+	("framebufferStencilSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, framebufferStencilSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, framebufferStencilSampleCounts} |]),
+	("framebufferNoAttachmentsSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, framebufferNoAttachmentsSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, framebufferNoAttachmentsSampleCounts} |]),
+	("maxColorAttachments", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxColorAttachments} |],
+		[| #{poke VkPhysicalDeviceLimits, maxColorAttachments} |]),
+	("sampledImageColorSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, sampledImageColorSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, sampledImageColorSampleCounts} |]),
+	("sampledImageIntegerSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, sampledImageIntegerSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, sampledImageIntegerSampleCounts} |]),
+	("sampledImageDepthSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, sampledImageDepthSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, sampledImageDepthSampleCounts} |]),
+	("sampledImageStencilSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, sampledImageStencilSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, sampledImageStencilSampleCounts} |]),
+	("storageImageSampleCounts", ''#{type VkSampleCountFlags},
+		[| #{peek VkPhysicalDeviceLimits, storageImageSampleCounts} |],
+		[| #{poke VkPhysicalDeviceLimits, storageImageSampleCounts} |]),
+	("maxSampleMaskWords", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxSampleMaskWords} |],
+		[| #{poke VkPhysicalDeviceLimits, maxSampleMaskWords} |]),
+	("timestampComputeAndGraphics", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceLimits, timestampComputeAndGraphics} |],
+		[| #{poke VkPhysicalDeviceLimits, timestampComputeAndGraphics} |]),
+	("timestampPeriod", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, timestampPeriod} |],
+		[| #{poke VkPhysicalDeviceLimits, timestampPeriod} |]),
+	("maxClipDistances", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxClipDistances} |],
+		[| #{poke VkPhysicalDeviceLimits, maxClipDistances} |]),
+	("maxCullDistances", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxCullDistances} |],
+		[| #{poke VkPhysicalDeviceLimits, maxCullDistances} |]),
+	("maxCombinedClipAndCullDistances", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, maxCombinedClipAndCullDistances} |],
+		[| #{poke VkPhysicalDeviceLimits, maxCombinedClipAndCullDistances} |]),
+	("discreteQueuePriorities", ''#{type uint32_t},
+		[| #{peek VkPhysicalDeviceLimits, discreteQueuePriorities} |],
+		[| #{poke VkPhysicalDeviceLimits, discreteQueuePriorities} |]),
+	("pointSizeRange", ''ListFloat,
+		[| peekArray 2 . #{ptr VkPhysicalDeviceLimits, pointSizeRange}|],
+		[| pokeArray . #{ptr VkPhysicalDeviceLimits, pointSizeRange} |]),
+	("lineWidthRange", ''ListFloat,
+		[| peekArray 2 . #{ptr VkPhysicalDeviceLimits, lineWidthRange}|],
+		[| pokeArray . #{ptr VkPhysicalDeviceLimits, lineWidthRange} |]),
+	("pointSizeGranularity", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, pointSizeGranularity} |],
+		[| #{poke VkPhysicalDeviceLimits, pointSizeGranularity} |]),
+	("lineWidthGranularity", ''#{type float},
+		[| #{peek VkPhysicalDeviceLimits, lineWidthGranularity} |],
+		[| #{poke VkPhysicalDeviceLimits, lineWidthGranularity} |]),
+	("strictLines", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceLimits, strictLines} |],
+		[| #{poke VkPhysicalDeviceLimits, strictLines} |]),
+	("standardSampleLocations", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceLimits, standardSampleLocations} |],
+		[| #{poke VkPhysicalDeviceLimits, standardSampleLocations} |]),
+	("optimalBufferCopyOffsetAlignment", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, optimalBufferCopyOffsetAlignment} |],
+		[| #{poke VkPhysicalDeviceLimits, optimalBufferCopyOffsetAlignment} |]),
+	("optimalBufferCopyRowPitchAlignment", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, optimalBufferCopyRowPitchAlignment} |],
+		[| #{poke VkPhysicalDeviceLimits, optimalBufferCopyRowPitchAlignment} |]),
+	("nonCoherentAtomSize", ''#{type VkDeviceSize},
+		[| #{peek VkPhysicalDeviceLimits, nonCoherentAtomSize} |],
+		[| #{poke VkPhysicalDeviceLimits, nonCoherentAtomSize} |]) ]
+	[''Show, ''Storable]
+
+struct "Features" #{size VkPhysicalDeviceFeatures}
+		#{alignment VkPhysicalDeviceFeatures} [
+	("robustBufferAccess", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, robustBufferAccess} |],
+		[| #{poke VkPhysicalDeviceFeatures, robustBufferAccess} |]),
+	("fullDrawIndexUint32", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, fullDrawIndexUint32} |],
+		[| #{poke VkPhysicalDeviceFeatures, fullDrawIndexUint32} |]),
+	("imageCubeArray", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, imageCubeArray} |],
+		[| #{poke VkPhysicalDeviceFeatures, imageCubeArray} |]),
+	("independentBlend", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, independentBlend} |],
+		[| #{poke VkPhysicalDeviceFeatures, independentBlend} |]),
+	("geometryShader", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, geometryShader} |],
+		[| #{poke VkPhysicalDeviceFeatures, geometryShader} |]),
+	("tessellationShader", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, tessellationShader} |],
+		[| #{poke VkPhysicalDeviceFeatures, tessellationShader} |]),
+	("sampleRateShading", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sampleRateShading} |],
+		[| #{poke VkPhysicalDeviceFeatures, sampleRateShading} |]),
+	("dualSrcBlend", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, dualSrcBlend} |],
+		[| #{poke VkPhysicalDeviceFeatures, dualSrcBlend} |]),
+	("logicOp", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, logicOp} |],
+		[| #{poke VkPhysicalDeviceFeatures, logicOp} |]),
+	("multiDrawIndirect", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, multiDrawIndirect} |],
+		[| #{poke VkPhysicalDeviceFeatures, multiDrawIndirect} |]),
+	("drawIndirectFirstInstance", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, drawIndirectFirstInstance} |],
+		[| #{poke VkPhysicalDeviceFeatures, drawIndirectFirstInstance} |]),
+	("depthClamp", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, depthClamp} |],
+		[| #{poke VkPhysicalDeviceFeatures, depthClamp} |]),
+	("depthBiasClamp", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, depthBiasClamp} |],
+		[| #{poke VkPhysicalDeviceFeatures, depthBiasClamp} |]),
+	("fillModeNonSolid", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, fillModeNonSolid} |],
+		[| #{poke VkPhysicalDeviceFeatures, fillModeNonSolid} |]),
+	("depthBounds", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, depthBounds} |],
+		[| #{poke VkPhysicalDeviceFeatures, depthBounds} |]),
+	("wideLines", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, wideLines} |],
+		[| #{poke VkPhysicalDeviceFeatures, wideLines} |]),
+	("largePoints", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, largePoints} |],
+		[| #{poke VkPhysicalDeviceFeatures, largePoints} |]),
+	("alphaToOne", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, alphaToOne} |],
+		[| #{poke VkPhysicalDeviceFeatures, alphaToOne} |]),
+	("multiViewport", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, multiViewport} |],
+		[| #{poke VkPhysicalDeviceFeatures, multiViewport} |]),
+	("samplerAnisotropy", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, samplerAnisotropy} |],
+		[| #{poke VkPhysicalDeviceFeatures, samplerAnisotropy} |]),
+	("textureCompressionETC2", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, textureCompressionETC2} |],
+		[| #{poke VkPhysicalDeviceFeatures, textureCompressionETC2} |]),
+	("textureCompressionASTC_LDR", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, textureCompressionASTC_LDR} |],
+		[| #{poke VkPhysicalDeviceFeatures, textureCompressionASTC_LDR} |]),
+	("textureCompressionBC", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, textureCompressionBC} |],
+		[| #{poke VkPhysicalDeviceFeatures, textureCompressionBC} |]),
+	("occlusionQueryPrecise", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, occlusionQueryPrecise} |],
+		[| #{poke VkPhysicalDeviceFeatures, occlusionQueryPrecise} |]),
+	("pipelineStatisticsQuery", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, pipelineStatisticsQuery} |],
+		[| #{poke VkPhysicalDeviceFeatures, pipelineStatisticsQuery} |]),
+	("vertexPipelineStoresAndAtomics", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, vertexPipelineStoresAndAtomics} |],
+		[| #{poke VkPhysicalDeviceFeatures, vertexPipelineStoresAndAtomics} |]),
+	("fragmentStoresAndAtomics", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, fragmentStoresAndAtomics} |],
+		[| #{poke VkPhysicalDeviceFeatures, fragmentStoresAndAtomics} |]),
+	("shaderTessellationAndGeometryPointSize", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderTessellationAndGeometryPointSize} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderTessellationAndGeometryPointSize} |]),
+	("shaderImageGatherExtended", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderImageGatherExtended} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderImageGatherExtended} |]),
+	("shaderStorageImageExtendedFormats", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderStorageImageExtendedFormats} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderStorageImageExtendedFormats} |]),
+	("shaderStorageImageMultisample", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderStorageImageMultisample} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderStorageImageMultisample} |]),
+	("shaderStorageImageReadWithoutFormat", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderStorageImageReadWithoutFormat} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderStorageImageReadWithoutFormat} |]),
+	("shaderStorageImageWriteWithoutFormat", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderStorageImageWriteWithoutFormat} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderStorageImageWriteWithoutFormat} |]),
+	("shaderUniformBufferArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderUniformBufferArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderUniformBufferArrayDynamicIndexing} |]),
+	("shaderSampledImageArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderSampledImageArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderSampledImageArrayDynamicIndexing} |]),
+	("shaderStorageBufferArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderStorageBufferArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderStorageBufferArrayDynamicIndexing} |]),
+	("shaderStorageImageArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderStorageImageArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderStorageImageArrayDynamicIndexing} |]),
+	("shaderClipDistance", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderClipDistance} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderClipDistance} |]),
+	("shaderCullDistance", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderCullDistance} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderCullDistance} |]),
+	("shaderFloat64", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderFloat64} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderFloat64} |]),
+	("shaderInt64", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderInt64} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderInt64} |]),
+	("shaderInt16", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderInt16} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderInt16} |]),
+	("shaderResourceResidency", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderResourceResidency} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderResourceResidency} |]),
+	("shaderResourceMinLod", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, shaderResourceMinLod} |],
+		[| #{poke VkPhysicalDeviceFeatures, shaderResourceMinLod} |]),
+	("sparseBinding", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseBinding} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseBinding} |]),
+	("sparseResidencyBuffer", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidencyBuffer} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidencyBuffer} |]),
+	("sparseResidencyImage2D", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidencyImage2D} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidencyImage2D} |]),
+	("sparseResidencyImage3D", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidencyImage3D} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidencyImage3D} |]),
+	("sparseResidency2Samples", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidency2Samples} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidency2Samples} |]),
+	("sparseResidency4Samples", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidency4Samples} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidency4Samples} |]),
+	("sparseResidency8Samples", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidency8Samples} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidency8Samples} |]),
+	("sparseResidency16Samples", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidency16Samples} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidency16Samples} |]),
+	("sparseResidencyAliased", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, sparseResidencyAliased} |],
+		[| #{poke VkPhysicalDeviceFeatures, sparseResidencyAliased} |]),
+	("variableMultisampleRate", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, variableMultisampleRate} |],
+		[| #{poke VkPhysicalDeviceFeatures, variableMultisampleRate} |]),
+	("inheritedQueries", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceFeatures, inheritedQueries} |],
+		[| #{poke VkPhysicalDeviceFeatures, inheritedQueries} |]) ]
+	[''Show, ''Storable]
+
+struct "DescriptorIndexingFeatures" #{size VkPhysicalDeviceDescriptorIndexingFeatures}
+		#{alignment VkPhysicalDeviceDescriptorIndexingFeatures} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPhysicalDeviceDescriptorIndexingFeatures, sType} p
+			(#{const VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES} ::
+				#{type VkStructureType}) |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, pNext} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, pNext} |]),
+	("shaderInputAttachmentArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderInputAttachmentArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderInputAttachmentArrayDynamicIndexing} |]),
+	("shaderUniformTexelBufferArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderUniformTexelBufferArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderUniformTexelBufferArrayDynamicIndexing} |]),
+	("shaderStorageTexelBufferArrayDynamicIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageTexelBufferArrayDynamicIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageTexelBufferArrayDynamicIndexing} |]),
+	("shaderUniformBufferArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderUniformBufferArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderUniformBufferArrayNonUniformIndexing} |]),
+	("shaderSampledImageArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderSampledImageArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderSampledImageArrayNonUniformIndexing} |]),
+	("shaderStorageBufferArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageBufferArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageBufferArrayNonUniformIndexing} |]),
+	("shaderStorageImageArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageImageArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageImageArrayNonUniformIndexing} |]),
+	("shaderInputAttachmentArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderInputAttachmentArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderInputAttachmentArrayNonUniformIndexing} |]),
+	("shaderUniformTexelBufferArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderUniformTexelBufferArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderUniformTexelBufferArrayNonUniformIndexing} |]),
+	("shaderStorageTexelBufferArrayNonUniformIndexing", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageTexelBufferArrayNonUniformIndexing} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, shaderStorageTexelBufferArrayNonUniformIndexing} |]),
+	("descriptorBindingUniformBufferUpdateAfterBind", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingUniformBufferUpdateAfterBind} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingUniformBufferUpdateAfterBind} |]),
+	("descriptorBindingSampledImageUpdateAfterBind", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingSampledImageUpdateAfterBind} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingSampledImageUpdateAfterBind} |]),
+	("descriptorBindingStorageImageUpdateAfterBind", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingStorageImageUpdateAfterBind} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingStorageImageUpdateAfterBind} |]),
+	("descriptorBindingStorageBufferUpdateAfterBind", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingStorageBufferUpdateAfterBind} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingStorageBufferUpdateAfterBind} |]),
+	("descriptorBindingUniformTexelBufferUpdateAfterBind", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingUniformTexelBufferUpdateAfterBind} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingUniformTexelBufferUpdateAfterBind} |]),
+	("descriptorBindingStorageTexelBufferUpdateAfterBind", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingStorageTexelBufferUpdateAfterBind} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingStorageTexelBufferUpdateAfterBind} |]),
+	("descriptorBindingUpdateUnusedWhilePending", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingUpdateUnusedWhilePending} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingUpdateUnusedWhilePending} |]),
+	("descriptorBindingPartiallyBound", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingPartiallyBound} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingPartiallyBound} |]),
+	("descriptorBindingVariableDescriptorCount", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingVariableDescriptorCount} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, descriptorBindingVariableDescriptorCount} |]),
+	("runtimeDescriptorArray", ''#{type VkBool32},
+		[| #{peek VkPhysicalDeviceDescriptorIndexingFeatures, runtimeDescriptorArray} |],
+		[| #{poke VkPhysicalDeviceDescriptorIndexingFeatures, runtimeDescriptorArray} |]) ]
+	[''Show, ''Storable]
+
+type PtrFeatures = Ptr Features
diff --git a/src/Gpu/Vulkan/Pipeline/ColorBlendAttachment/Core.hsc b/src/Gpu/Vulkan/Pipeline/ColorBlendAttachment/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/ColorBlendAttachment/Core.hsc
@@ -0,0 +1,65 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.ColorBlendAttachment.Core (
+
+	-- * STATE
+
+	State, PtrState, pattern State,
+	stateBlendEnable,
+	stateSrcColorBlendFactor, stateDstColorBlendFactor, stateColorBlendOp,
+	stateSrcAlphaBlendFactor, stateDstAlphaBlendFactor, stateAlphaBlendOp,
+	stateColorWriteMask
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+struct "State" #{size VkPipelineColorBlendAttachmentState}
+		#{alignment VkPipelineColorBlendAttachmentState} [
+	("blendEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineColorBlendAttachmentState, blendEnable} |],
+		[| #{poke VkPipelineColorBlendAttachmentState, blendEnable} |]),
+	("srcColorBlendFactor", ''#{type VkBlendFactor},
+		[| #{peek VkPipelineColorBlendAttachmentState,
+			srcColorBlendFactor} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			srcColorBlendFactor} |]),
+	("dstColorBlendFactor", ''#{type VkBlendFactor},
+		[| #{peek VkPipelineColorBlendAttachmentState,
+			dstColorBlendFactor} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			dstColorBlendFactor} |]),
+	("colorBlendOp", ''#{type VkBlendOp},
+		[| #{peek VkPipelineColorBlendAttachmentState, colorBlendOp} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			colorBlendOp} |]),
+	("srcAlphaBlendFactor", ''#{type VkBlendFactor},
+		[| #{peek VkPipelineColorBlendAttachmentState,
+			srcAlphaBlendFactor} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			srcAlphaBlendFactor} |]),
+	("dstAlphaBlendFactor", ''#{type VkBlendFactor},
+		[| #{peek VkPipelineColorBlendAttachmentState,
+			dstAlphaBlendFactor} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			dstAlphaBlendFactor} |]),
+	("alphaBlendOp", ''#{type VkBlendOp},
+		[| #{peek VkPipelineColorBlendAttachmentState, alphaBlendOp} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			alphaBlendOp} |]),
+	("colorWriteMask", ''#{type VkColorComponentFlags},
+		[| #{peek VkPipelineColorBlendAttachmentState,
+			colorWriteMask} |],
+		[| #{poke VkPipelineColorBlendAttachmentState,
+			colorWriteMask} |]) ]
+	[''Show, ''Storable]
+
+type PtrState = Ptr State
diff --git a/src/Gpu/Vulkan/Pipeline/ColorBlendState/Core.hsc b/src/Gpu/Vulkan/Pipeline/ColorBlendState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/ColorBlendState/Core.hsc
@@ -0,0 +1,66 @@
+{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.ColorBlendState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoLogicOpEnable, createInfoLogicOp,
+	createInfoAttachmentCount, createInfoPAttachments,
+	createInfoBlendConstants
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Marshal.Array
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+import qualified Gpu.Vulkan.Pipeline.ColorBlendAttachment.Core as ColorBlendAttachment
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineColorBlendStateCreateInfo}
+		#{alignment VkPipelineColorBlendStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineColorBlendStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineColorBlendStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineColorBlendStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineColorBlendStateCreateFlags},
+		[| #{peek VkPipelineColorBlendStateCreateInfo, flags} |],
+		[| #{poke VkPipelineColorBlendStateCreateInfo, flags} |]),
+	("logicOpEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineColorBlendStateCreateInfo,
+			logicOpEnable} |],
+		[| #{poke VkPipelineColorBlendStateCreateInfo,
+			logicOpEnable} |]),
+	("logicOp", ''#{type VkLogicOp},
+		[| #{peek VkPipelineColorBlendStateCreateInfo, logicOp} |],
+		[| #{poke VkPipelineColorBlendStateCreateInfo, logicOp} |]),
+	("attachmentCount", ''#{type uint32_t},
+		[| #{peek VkPipelineColorBlendStateCreateInfo,
+			attachmentCount} |],
+		[| #{poke VkPipelineColorBlendStateCreateInfo,
+			attachmentCount} |]),
+	("pAttachments", ''ColorBlendAttachment.PtrState,
+		[| #{peek VkPipelineColorBlendStateCreateInfo, pAttachments} |],
+		[| #{poke VkPipelineColorBlendStateCreateInfo,
+			pAttachments} |]),
+	("blendConstants", ''ListFloat,
+		[| \p -> peekArray 4 (#{ptr VkPipelineColorBlendStateCreateInfo,
+			blendConstants} p) |],
+		[| \p bcs -> pokeArray (#{ptr VkPipelineColorBlendStateCreateInfo,
+			blendConstants} p) $ take 4 bcs |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/Compute/Core.hsc b/src/Gpu/Vulkan/Pipeline/Compute/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/Compute/Core.hsc
@@ -0,0 +1,63 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.Compute.Core (
+
+	-- * CREATE
+
+	createCs, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoStage, createInfoLayout,
+	createInfoBasePipelineHandle, createInfoBasePipelineIndex
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.Pipeline.Core as Pipeline
+import qualified Gpu.Vulkan.Pipeline.ShaderStage.Core as Pipeline.ShaderStage
+import qualified Gpu.Vulkan.PipelineLayout.Core as Pipeline.Layout
+import qualified Gpu.Vulkan.PipelineCache.Core as Cache
+
+#include <vulkan/vulkan.h>
+
+stype :: #{type VkStructureType}
+stype = #{const VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkComputePipelineCreateInfo}
+		#{alignment VkComputePipelineCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkComputePipelineCreateInfo, sType}
+			p stype |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkComputePipelineCreateInfo, pNext} |],
+		[| #{poke VkComputePipelineCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineCreateFlags},
+		[| #{peek VkComputePipelineCreateInfo, flags} |],
+		[| #{poke VkComputePipelineCreateInfo, flags} |]),
+	("stage", ''Pipeline.ShaderStage.CreateInfo,
+		[| #{peek VkComputePipelineCreateInfo, stage} |],
+		[| #{poke VkComputePipelineCreateInfo, stage} |]),
+	("layout", ''Pipeline.Layout.P,
+		[| #{peek VkComputePipelineCreateInfo, layout} |],
+		[| #{poke VkComputePipelineCreateInfo, layout} |]),
+	("basePipelineHandle", ''Pipeline.P,
+		[| #{peek VkComputePipelineCreateInfo, basePipelineHandle} |],
+		[| #{poke VkComputePipelineCreateInfo, basePipelineHandle} |]),
+	("basePipelineIndex", ''#{type int32_t},
+		[| #{peek VkComputePipelineCreateInfo, basePipelineIndex} |],
+		[| #{poke VkComputePipelineCreateInfo, basePipelineIndex} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkCreateComputePipelines" createCs ::
+	Device.D -> Cache.P -> #{type uint32_t} -> Ptr CreateInfo ->
+	Ptr AllocationCallbacks.A -> Ptr Pipeline.P -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/Pipeline/Core.hsc b/src/Gpu/Vulkan/Pipeline/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/Core.hsc
@@ -0,0 +1,20 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.Core (
+
+	-- * DESTROY
+
+	destroy, P
+
+	) where
+
+import Foreign.Ptr
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+data PTag
+type P = Ptr PTag
+
+foreign import ccall "vkDestroyPipeline" destroy ::
+	Device.D -> P -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Pipeline/DepthStencilState/Core.hsc b/src/Gpu/Vulkan/Pipeline/DepthStencilState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/DepthStencilState/Core.hsc
@@ -0,0 +1,86 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.DepthStencilState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoDepthTestEnable, createInfoDepthWriteEnable,
+	createInfoDepthCompareOp, createInfoDepthBoundsTestEnable,
+	createInfoStencilTestEnable, createInfoFront, createInfoBack,
+	createInfoMinDepthBounds, createInfoMaxDepthBounds
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+import Gpu.Vulkan.Core
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineDepthStencilStateCreateInfo}
+		#{alignment VkPipelineDepthStencilStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineDepthStencilStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineDepthStencilStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineDepthStencilStateCreateFlags},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo, flags} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo, flags} |]),
+	("depthTestEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			depthTestEnable} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			depthTestEnable} |]),
+	("depthWriteEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			depthWriteEnable} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			depthWriteEnable} |]),
+	("depthCompareOp", ''#{type VkCompareOp},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			depthCompareOp} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			depthCompareOp} |]),
+	("depthBoundsTestEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			depthBoundsTestEnable} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			depthBoundsTestEnable} |]),
+	("stencilTestEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			stencilTestEnable} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			stencilTestEnable} |]),
+	("front", ''StencilOpState,
+		[| #{peek VkPipelineDepthStencilStateCreateInfo, front} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo, front} |]),
+	("back", ''StencilOpState,
+		[| #{peek VkPipelineDepthStencilStateCreateInfo, back} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo, back} |]),
+	("minDepthBounds", ''#{type float},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			minDepthBounds} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			minDepthBounds} |]),
+	("maxDepthBounds", ''#{type float},
+		[| #{peek VkPipelineDepthStencilStateCreateInfo,
+			maxDepthBounds} |],
+		[| #{poke VkPipelineDepthStencilStateCreateInfo,
+			maxDepthBounds} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/DynamicState/Core.hsc b/src/Gpu/Vulkan/Pipeline/DynamicState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/DynamicState/Core.hsc
@@ -0,0 +1,51 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.DynamicState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoDynamicStateCount, createInfoPDynamicStates
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO}
+
+type PtrVkDynamicState = Ptr #{type VkDynamicState}
+
+struct "CreateInfo" #{size VkPipelineDynamicStateCreateInfo}
+		#{alignment VkPipelineDynamicStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineDynamicStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineDynamicStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineDynamicStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineDynamicStateCreateFlags},
+		[| #{peek VkPipelineDynamicStateCreateInfo, flags} |],
+		[| #{poke VkPipelineDynamicStateCreateInfo, flags} |]),
+	("dynamicStateCount", ''#{type uint32_t},
+		[| #{peek VkPipelineDynamicStateCreateInfo,
+			dynamicStateCount} |],
+		[| #{poke VkPipelineDynamicStateCreateInfo,
+			dynamicStateCount} |]),
+	("pDynamicStates", ''PtrVkDynamicState,
+		[| #{peek VkPipelineDynamicStateCreateInfo, pDynamicStates} |],
+		[| #{poke VkPipelineDynamicStateCreateInfo, pDynamicStates} |])
+	]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/Graphics/Core.hsc b/src/Gpu/Vulkan/Pipeline/Graphics/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/Graphics/Core.hsc
@@ -0,0 +1,118 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.Graphics.Core (
+
+	-- * CREATE
+
+	create, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoStageCount, createInfoPStages,
+	createInfoPVertexInputState, createInfoPInputAssemblyState,
+	createInfoPTessellationState, createInfoPViewportState,
+	createInfoPRasterizationState, createInfoPMultisampleState,
+	createInfoPDepthStencilState, createInfoPColorBlendState,
+	createInfoPDynamicState,
+	createInfoLayout, createInfoRenderPass, createInfoSubpass,
+	createInfoBasePipelineHandle, createInfoBasePipelineIndex
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.Pipeline.Core as Pipeline
+import qualified Gpu.Vulkan.Pipeline.ShaderStage.Core as ShaderStage
+import qualified Gpu.Vulkan.Pipeline.VertexInputState.Core as VertexInputState
+import qualified Gpu.Vulkan.Pipeline.InputAssemblyState.Core as InputAssemblyState
+import qualified Gpu.Vulkan.Pipeline.TessellationState.Core as TessellationState
+import qualified Gpu.Vulkan.Pipeline.ViewportState.Core as ViewportState
+import qualified Gpu.Vulkan.Pipeline.RasterizationState.Core as RasterizationState
+import qualified Gpu.Vulkan.Pipeline.MultisampleState.Core as MultisampleState
+import qualified Gpu.Vulkan.Pipeline.DepthStencilState.Core as DepthStencilState
+import qualified Gpu.Vulkan.Pipeline.ColorBlendState.Core as ColorBlendState
+import qualified Gpu.Vulkan.Pipeline.DynamicState.Core as DynamicState
+import qualified Gpu.Vulkan.PipelineLayout.Core as Layout
+import qualified Gpu.Vulkan.RenderPass.Core as RenderPass
+
+import qualified Gpu.Vulkan.PipelineCache.Core as Cache
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkGraphicsPipelineCreateInfo}
+		#{alignment VkGraphicsPipelineCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkGraphicsPipelineCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkGraphicsPipelineCreateInfo, pNext} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineCreateFlags},
+		[| #{peek VkGraphicsPipelineCreateInfo, flags} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, flags} |]),
+	("stageCount", ''#{type uint32_t},
+		[| #{peek VkGraphicsPipelineCreateInfo, stageCount} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, stageCount} |]),
+	("pStages", ''ShaderStage.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pStages} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pStages} |]),
+	("pVertexInputState", ''VertexInputState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pVertexInputState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pVertexInputState} |]),
+	("pInputAssemblyState", ''InputAssemblyState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pInputAssemblyState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo,
+			pInputAssemblyState} |]),
+	("pTessellationState", ''TessellationState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pTessellationState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pTessellationState} |]),
+	("pViewportState", ''ViewportState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pViewportState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pViewportState} |]),
+	("pRasterizationState", ''RasterizationState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pRasterizationState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo,
+			pRasterizationState} |]),
+	("pMultisampleState", ''MultisampleState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pMultisampleState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pMultisampleState} |]),
+	("pDepthStencilState", ''DepthStencilState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pDepthStencilState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pDepthStencilState} |]),
+	("pColorBlendState", ''ColorBlendState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pColorBlendState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pColorBlendState} |]),
+	("pDynamicState", ''DynamicState.PtrCreateInfo,
+		[| #{peek VkGraphicsPipelineCreateInfo, pDynamicState} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, pDynamicState} |]),
+	("layout", ''Layout.P,
+		[| #{peek VkGraphicsPipelineCreateInfo, layout} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, layout} |]),
+	("renderPass", ''RenderPass.R,
+		[| #{peek VkGraphicsPipelineCreateInfo, renderPass} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, renderPass} |]),
+	("subpass", ''#{type uint32_t},
+		[| #{peek VkGraphicsPipelineCreateInfo, subpass} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, subpass} |]),
+	("basePipelineHandle", ''Pipeline.P,
+		[| #{peek VkGraphicsPipelineCreateInfo, basePipelineHandle} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, basePipelineHandle} |]),
+	("basePipelineIndex", ''#{type int32_t},
+		[| #{peek VkGraphicsPipelineCreateInfo, basePipelineIndex} |],
+		[| #{poke VkGraphicsPipelineCreateInfo, basePipelineIndex} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkCreateGraphicsPipelines" create ::
+	Device.D -> Cache.P -> #{type uint32_t} -> Ptr CreateInfo ->
+	Ptr AllocationCallbacks.A -> Ptr Pipeline.P -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/Pipeline/InputAssemblyState/Core.hsc b/src/Gpu/Vulkan/Pipeline/InputAssemblyState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/InputAssemblyState/Core.hsc
@@ -0,0 +1,48 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.InputAssemblyState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoTopology, createInfoPrimitiveRestartEnable
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineInputAssemblyStateCreateInfo}
+		#{alignment VkPipelineInputAssemblyStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineInputAssemblyStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineInputAssemblyStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineInputAssemblyStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineInputAssemblyStateCreateFlags},
+		[| #{peek VkPipelineInputAssemblyStateCreateInfo, flags} |],
+		[| #{poke VkPipelineInputAssemblyStateCreateInfo, flags} |]),
+	("topology", ''#{type VkPrimitiveTopology},
+		[| #{peek VkPipelineInputAssemblyStateCreateInfo, topology} |],
+		[| #{poke VkPipelineInputAssemblyStateCreateInfo, topology} |]),
+	("primitiveRestartEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineInputAssemblyStateCreateInfo,
+			primitiveRestartEnable} |],
+		[| #{poke VkPipelineInputAssemblyStateCreateInfo,
+			primitiveRestartEnable} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/MultisampleState/Core.hsc b/src/Gpu/Vulkan/Pipeline/MultisampleState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/MultisampleState/Core.hsc
@@ -0,0 +1,73 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.MultisampleState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoRasterizationSamples, createInfoSampleShadingEnable,
+	createInfoMinSampleShading, createInfoPSampleMask,
+	createInfoAlphaToCoverageEnable, createInfoAlphaToOneEnable
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO}
+
+type PtrSampleMask = Ptr #{type VkSampleMask}
+
+struct "CreateInfo" #{size VkPipelineMultisampleStateCreateInfo}
+		#{alignment VkPipelineMultisampleStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineMultisampleStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineMultisampleStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineMultisampleStateCreateFlags},
+		[| #{peek VkPipelineMultisampleStateCreateInfo, flags} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo, flags} |]),
+	("rasterizationSamples", ''#{type VkSampleCountFlagBits},
+		[| #{peek VkPipelineMultisampleStateCreateInfo,
+			rasterizationSamples} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo,
+			rasterizationSamples} |]),
+	("sampleShadingEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineMultisampleStateCreateInfo,
+			sampleShadingEnable} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo,
+			sampleShadingEnable} |]),
+	("minSampleShading", ''#{type float},
+		[| #{peek VkPipelineMultisampleStateCreateInfo,
+			minSampleShading} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo,
+			minSampleShading} |]),
+	("pSampleMask", ''PtrSampleMask,
+		[| #{peek VkPipelineMultisampleStateCreateInfo, pSampleMask} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo,
+			pSampleMask} |]),
+	("alphaToCoverageEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineMultisampleStateCreateInfo,
+			alphaToCoverageEnable} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo,
+			alphaToCoverageEnable} |]),
+	("alphaToOneEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineMultisampleStateCreateInfo,
+			alphaToOneEnable} |],
+		[| #{poke VkPipelineMultisampleStateCreateInfo,
+			alphaToOneEnable} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/RasterizationState/Core.hsc b/src/Gpu/Vulkan/Pipeline/RasterizationState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/RasterizationState/Core.hsc
@@ -0,0 +1,90 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.RasterizationState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoDepthClampEnable, createInfoRasterizerDiscardEnable,
+	createInfoPolygonMode, createInfoCullMode, createInfoFrontFace,
+	createInfoDepthBiasEnable, createInfoDepthBiasConstantFactor,
+	createInfoDepthBiasClamp, createInfoDepthBiasSlopeFactor,
+	createInfoLineWidth
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineRasterizationStateCreateInfo}
+		#{alignment VkPipelineRasterizationStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineRasterizationStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineRasterizationStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineRasterizationStateCreateFlags},
+		[| #{peek VkPipelineRasterizationStateCreateInfo, flags} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo, flags} |]),
+	("depthClampEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			depthClampEnable} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			depthClampEnable} |]),
+	("rasterizerDiscardEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			rasterizerDiscardEnable} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			rasterizerDiscardEnable} |]),
+	("polygonMode", ''#{type VkPolygonMode},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			polygonMode} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			polygonMode} |]),
+	("cullMode", ''#{type VkCullModeFlags},
+		[| #{peek VkPipelineRasterizationStateCreateInfo, cullMode} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo, cullMode} |]),
+	("frontFace", ''#{type VkFrontFace},
+		[| #{peek VkPipelineRasterizationStateCreateInfo, frontFace} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			frontFace} |]),
+	("depthBiasEnable", ''#{type VkBool32},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			depthBiasEnable} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			depthBiasEnable} |]),
+	("depthBiasConstantFactor", ''#{type float},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			depthBiasConstantFactor} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			depthBiasConstantFactor} |]),
+	("depthBiasClamp", ''#{type float},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			depthBiasClamp } |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			depthBiasClamp } |]),
+	("depthBiasSlopeFactor", ''#{type float},
+		[| #{peek VkPipelineRasterizationStateCreateInfo,
+			depthBiasSlopeFactor} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo,
+			depthBiasSlopeFactor} |]),
+	("lineWidth", ''#{type float},
+		[| #{peek VkPipelineRasterizationStateCreateInfo, lineWidth} |],
+		[| #{poke VkPipelineRasterizationStateCreateInfo, lineWidth} |])
+	]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/ShaderStage/Core.hsc b/src/Gpu/Vulkan/Pipeline/ShaderStage/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/ShaderStage/Core.hsc
@@ -0,0 +1,59 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.ShaderStage.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoStage, createInfoModule, createInfoPName,
+	createInfoPSpecializationInfo
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.String
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+import qualified Gpu.Vulkan.ShaderModule.Core as Shader.Module
+import qualified Gpu.Vulkan.Specialization.Core as Specialization
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineShaderStageCreateInfo}
+		#{alignment VkPipelineShaderStageCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineShaderStageCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineShaderStageCreateInfo, pNext} |],
+		[| #{poke VkPipelineShaderStageCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineShaderStageCreateFlags},
+		[| #{peek VkPipelineShaderStageCreateInfo, flags} |],
+		[| #{poke VkPipelineShaderStageCreateInfo, flags} |]),
+	("stage", ''#{type VkShaderStageFlagBits},
+		[| #{peek VkPipelineShaderStageCreateInfo, stage} |],
+		[| #{poke VkPipelineShaderStageCreateInfo, stage} |]),
+	("module", ''Shader.Module.S,
+		[| #{peek VkPipelineShaderStageCreateInfo, module} |],
+		[| #{poke VkPipelineShaderStageCreateInfo, module} |]),
+	("pName", ''CString,
+		[| #{peek VkPipelineShaderStageCreateInfo, pName} |],
+		[| #{poke VkPipelineShaderStageCreateInfo, pName} |]),
+	("pSpecializationInfo", ''Specialization.PtrInfo,
+		[| #{peek VkPipelineShaderStageCreateInfo,
+			pSpecializationInfo} |],
+		[| #{poke VkPipelineShaderStageCreateInfo,
+			pSpecializationInfo} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/TessellationState/Core.hsc b/src/Gpu/Vulkan/Pipeline/TessellationState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/TessellationState/Core.hsc
@@ -0,0 +1,46 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE MonoLocalBinds #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.TessellationState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoPatchControlPoints
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineTessellationStateCreateInfo}
+		#{alignment VkPipelineTessellationStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineTessellationStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineTessellationStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineTessellationStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineTessellationStateCreateFlags},
+		[| #{peek VkPipelineTessellationStateCreateInfo, flags} |],
+		[| #{poke VkPipelineTessellationStateCreateInfo, flags} |]),
+	("patchControlPoints", ''#{type uint32_t},
+		[| #{peek VkPipelineTessellationStateCreateInfo,
+			patchControlPoints} |],
+		[| #{poke VkPipelineTessellationStateCreateInfo,
+			patchControlPoints} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/VertexInputState/Core.hsc b/src/Gpu/Vulkan/Pipeline/VertexInputState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/VertexInputState/Core.hsc
@@ -0,0 +1,65 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.VertexInputState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoVertexBindingDescriptionCount,
+	createInfoPVertexBindingDescriptions,
+	createInfoVertexAttributeDescriptionCount,
+	createInfoPVertexAttributeDescriptions
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct	
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+import qualified Gpu.Vulkan.VertexInput.Core as VertexInput
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineVertexInputStateCreateInfo}
+		#{alignment VkPipelineVertexInputStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineVertexInputStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineVertexInputStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineVertexInputStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineVertexInputStateCreateFlags},
+		[| #{peek VkPipelineVertexInputStateCreateInfo, flags} |],
+		[| #{poke VkPipelineVertexInputStateCreateInfo, flags} |]),
+	("vertexBindingDescriptionCount", ''#{type uint32_t},
+		[| #{peek VkPipelineVertexInputStateCreateInfo,
+			vertexBindingDescriptionCount} |],
+		[| #{poke VkPipelineVertexInputStateCreateInfo,
+			vertexBindingDescriptionCount} |]),
+	("pVertexBindingDescriptions", ''VertexInput.PtrBindingDescription,
+		[| #{peek VkPipelineVertexInputStateCreateInfo,
+			pVertexBindingDescriptions} |],
+		[| #{poke VkPipelineVertexInputStateCreateInfo,
+			pVertexBindingDescriptions} |]),
+	("vertexAttributeDescriptionCount", ''#{type uint32_t},
+		[| #{peek VkPipelineVertexInputStateCreateInfo,
+			vertexAttributeDescriptionCount} |],
+		[| #{poke VkPipelineVertexInputStateCreateInfo,
+			vertexAttributeDescriptionCount} |]),
+	("pVertexAttributeDescriptions", ''VertexInput.PtrAttributeDescription,
+		[| #{peek VkPipelineVertexInputStateCreateInfo,
+			pVertexAttributeDescriptions} |],
+		[| #{poke VkPipelineVertexInputStateCreateInfo,
+			pVertexAttributeDescriptions} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/Pipeline/ViewportState/Core.hsc b/src/Gpu/Vulkan/Pipeline/ViewportState/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Pipeline/ViewportState/Core.hsc
@@ -0,0 +1,55 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Pipeline.ViewportState.Core (
+
+	-- * CREATE INFO
+
+	CreateInfo, PtrCreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoViewportCount, createInfoPViewports,
+	createInfoScissorCount, createInfoPScissors
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+import Gpu.Vulkan.Core
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineViewportStateCreateInfo}
+		#{alignment VkPipelineViewportStateCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineViewportStateCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineViewportStateCreateInfo, pNext} |],
+		[| #{poke VkPipelineViewportStateCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineViewportStateCreateFlags},
+		[| #{peek VkPipelineViewportStateCreateInfo, flags} |],
+		[| #{poke VkPipelineViewportStateCreateInfo, flags} |]),
+	("viewportCount", ''#{type uint32_t},
+		[| #{peek VkPipelineViewportStateCreateInfo, viewportCount} |],
+		[| #{poke VkPipelineViewportStateCreateInfo, viewportCount} |]),
+	("pViewports", ''PtrViewport,
+		[| #{peek VkPipelineViewportStateCreateInfo, pViewports} |],
+		[| #{poke VkPipelineViewportStateCreateInfo, pViewports} |]),
+	("scissorCount", ''#{type uint32_t},
+		[| #{peek VkPipelineViewportStateCreateInfo, scissorCount} |],
+		[| #{poke VkPipelineViewportStateCreateInfo, scissorCount} |]),
+	("pScissors", ''PtrRect2d,
+		[| #{peek VkPipelineViewportStateCreateInfo, pScissors} |],
+		[| #{poke VkPipelineViewportStateCreateInfo, pScissors} |]) ]
+	[''Show, ''Storable]
+
+type PtrCreateInfo = Ptr CreateInfo
diff --git a/src/Gpu/Vulkan/PipelineCache/Core.hsc b/src/Gpu/Vulkan/PipelineCache/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/PipelineCache/Core.hsc
@@ -0,0 +1,64 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.PipelineCache.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, P, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoInitialDataSize, createInfoPInitialData,
+
+	-- * GET DATA
+
+	getData
+	
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineCacheCreateInfo}
+		#{alignment VkPipelineCacheCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineCacheCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineCacheCreateInfo, pNext} |],
+		[| #{poke VkPipelineCacheCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineCacheCreateFlags},
+		[| #{peek VkPipelineCacheCreateInfo, flags} |],
+		[| #{poke VkPipelineCacheCreateInfo, flags} |]),
+	("initialDataSize", ''#{type size_t},
+		[| #{peek VkPipelineCacheCreateInfo, initialDataSize} |],
+		[| #{poke VkPipelineCacheCreateInfo, initialDataSize} |]),
+	("pInitialData", ''PtrVoid,
+		[| #{peek VkPipelineCacheCreateInfo, pInitialData} |],
+		[| #{poke VkPipelineCacheCreateInfo, pInitialData} |]) ]
+	[''Show, ''Storable]
+
+data PTag
+type P = Ptr PTag
+
+foreign import ccall "vkCreatePipelineCache" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr P ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyPipelineCache" destroy ::
+	Device.D -> P -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkGetPipelineCacheData" getData ::
+	Device.D -> P -> Ptr #{type size_t} -> Ptr () -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/PipelineLayout/Core.hsc b/src/Gpu/Vulkan/PipelineLayout/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/PipelineLayout/Core.hsc
@@ -0,0 +1,68 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.PipelineLayout.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, P, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoSetLayoutCount, createInfoPSetLayouts,
+	createInfoPushConstantRangeCount, createInfoPPushConstantRanges
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.DescriptorSetLayout.Core as DescriptorSet.Layout
+import qualified Gpu.Vulkan.PushConstant.Core as PushConstant
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}
+
+struct "CreateInfo" #{size VkPipelineLayoutCreateInfo}
+		#{alignment VkPipelineLayoutCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkPipelineLayoutCreateInfo, sType}
+			p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkPipelineLayoutCreateInfo, pNext} |],
+		[| #{poke VkPipelineLayoutCreateInfo, pNext} |]),
+	("flags", ''#{type VkPipelineLayoutCreateFlags},
+		[| #{peek VkPipelineLayoutCreateInfo, flags} |],
+		[| #{poke VkPipelineLayoutCreateInfo, flags} |]),
+	("setLayoutCount", ''#{type uint32_t},
+		[| #{peek VkPipelineLayoutCreateInfo, setLayoutCount} |],
+		[| #{poke VkPipelineLayoutCreateInfo, setLayoutCount} |]),
+	("pSetLayouts", ''DescriptorSet.Layout.PtrD,
+		[| #{peek VkPipelineLayoutCreateInfo, pSetLayouts} |],
+		[| #{poke VkPipelineLayoutCreateInfo, pSetLayouts} |]),
+	("pushConstantRangeCount", ''#{type uint32_t},
+		[| #{peek VkPipelineLayoutCreateInfo,
+			pushConstantRangeCount} |],
+		[| #{poke VkPipelineLayoutCreateInfo,
+			pushConstantRangeCount} |]),
+	("pPushConstantRanges", ''PushConstant.PtrRange,
+		[| #{peek VkPipelineLayoutCreateInfo, pPushConstantRanges} |],
+		[| #{poke VkPipelineLayoutCreateInfo, pPushConstantRanges} |]) ]
+	[''Show, ''Storable]
+
+data PTag
+type P = Ptr PTag
+
+foreign import ccall "vkCreatePipelineLayout" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr P -> IO #{type VkResult}
+
+foreign import ccall "vkDestroyPipelineLayout" destroy ::
+	Device.D -> P -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/PushConstant/Core.hsc b/src/Gpu/Vulkan/PushConstant/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/PushConstant/Core.hsc
@@ -0,0 +1,33 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.PushConstant.Core (
+
+	-- * RANGE
+
+	Range, PtrRange, pattern Range, rangeStageFlags, rangeOffset, rangeSize
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+struct "Range" #{size VkPushConstantRange} #{alignment VkPushConstantRange} [
+	("stageFlags", ''#{type VkShaderStageFlags},
+		[| #{peek VkPushConstantRange, stageFlags} |],
+		[| #{poke VkPushConstantRange, stageFlags} |]),
+	("offset", ''#{type uint32_t},
+		[| #{peek VkPushConstantRange, offset} |],
+		[| #{poke VkPushConstantRange, offset} |]),
+	("size", ''#{type uint32_t},
+		[| #{peek VkPushConstantRange, size} |],
+		[| #{poke VkPushConstantRange, size} |]) ]
+	[''Show, ''Storable]
+
+type PtrRange = Ptr Range
diff --git a/src/Gpu/Vulkan/QueryPool/Core.hsc b/src/Gpu/Vulkan/QueryPool/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/QueryPool/Core.hsc
@@ -0,0 +1,73 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.QueryPool.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, Q, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoQueryType, createInfoQueryCount, createInfoPipelineStatistics,
+
+	-- * RESET AND GET RESULTS
+
+	reset, getResults
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.AllocationCallbacks.Core qualified as AllocationCallbacks
+import Gpu.Vulkan.Device.Core qualified as Device
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO}
+
+struct "CreateInfo" #{size VkQueryPoolCreateInfo}
+	#{alignment VkQueryPoolCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkQueryPoolCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkQueryPoolCreateInfo, pNext} |],
+		[| #{poke VkQueryPoolCreateInfo, pNext} |]),
+	("flags", ''#{type VkQueryPoolCreateFlags},
+		[| #{peek VkQueryPoolCreateInfo, flags} |],
+		[| #{poke VkQueryPoolCreateInfo, flags} |]),
+	("queryType", ''#{type VkQueryType},
+		[| #{peek VkQueryPoolCreateInfo, queryType} |],
+		[| #{poke VkQueryPoolCreateInfo, queryType} |]),
+	("queryCount", ''#{type uint32_t},
+		[| #{peek VkQueryPoolCreateInfo, queryCount} |],
+		[| #{poke VkQueryPoolCreateInfo, queryCount} |]),
+	("pipelineStatistics", ''#{type VkQueryPipelineStatisticFlags},
+		[| #{peek VkQueryPoolCreateInfo, pipelineStatistics} |],
+		[| #{poke VkQueryPoolCreateInfo, pipelineStatistics} |]) ]
+	[''Show, ''Storable]
+
+data QTag
+type Q = Ptr QTag
+
+foreign import ccall "vkCreateQueryPool" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr Q ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyQueryPool" destroy ::
+	Device.D -> Q -> Ptr AllocationCallbacks.A -> IO ()
+
+foreign import ccall "vkResetQueryPool" reset ::
+	Device.D -> Q -> #{type uint32_t} -> #{type uint32_t} -> IO ()
+
+foreign import ccall "vkGetQueryPoolResults" getResults ::
+	Device.D -> Q -> #{type uint32_t} -> #{type uint32_t} ->
+	#{type size_t} -> Ptr () -> #{type VkDeviceSize} ->
+	#{type VkQueryResultFlags} -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/Queue/Core.hsc b/src/Gpu/Vulkan/Queue/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Queue/Core.hsc
@@ -0,0 +1,28 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Queue.Core (
+
+	-- SUBMIT AND WAIT IDLE
+
+	Q, submit, waitIdle
+
+	) where
+
+import Foreign.Ptr
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.Core
+
+import {-# SOURCE #-} qualified Gpu.Vulkan.Fence.Core as Fence
+
+#include <vulkan/vulkan.h>
+
+data QTag
+type Q = Ptr QTag
+
+foreign import ccall "vkQueueSubmit" submit ::
+	Q -> #{type uint32_t} -> Ptr SubmitInfo -> Fence.F ->
+	IO #{type VkResult}
+
+foreign import ccall "vkQueueWaitIdle" waitIdle :: Q -> IO #{type VkResult}
diff --git a/src/Gpu/Vulkan/QueueFamily/Core.hsc b/src/Gpu/Vulkan/QueueFamily/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/QueueFamily/Core.hsc
@@ -0,0 +1,40 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.QueueFamily.Core (
+
+	-- * PROPERTIES
+
+	Properties, pattern Properties,
+	propertiesQueueFlags, propertiesQueueCount,
+	propertiesTimestampValidBits, propertiesMinImageTransferGranularity
+
+	) where
+
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+import Gpu.Vulkan.Core
+
+struct "Properties" #{size VkQueueFamilyProperties}
+		#{alignment VkQueueFamilyProperties} [
+	("queueFlags", ''#{type VkQueueFlags},
+		[| #{peek VkQueueFamilyProperties, queueFlags} |],
+		[| #{poke VkQueueFamilyProperties, queueFlags} |]),
+	("queueCount", ''#{type uint32_t},
+		[| #{peek VkQueueFamilyProperties, queueCount} |],
+		[| #{poke VkQueueFamilyProperties, queueCount} |]),
+	("timestampValidBits", ''#{type uint32_t},
+		[| #{peek VkQueueFamilyProperties, timestampValidBits} |],
+		[| #{poke VkQueueFamilyProperties, timestampValidBits} |]),
+	("minImageTransferGranularity", ''Extent3d,
+		[| #{peek VkQueueFamilyProperties,
+			minImageTransferGranularity} |],
+		[| #{poke VkQueueFamilyProperties,
+			minImageTransferGranularity} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/RenderPass/Core.hs-boot b/src/Gpu/Vulkan/RenderPass/Core.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/RenderPass/Core.hs-boot
@@ -0,0 +1,6 @@
+module Gpu.Vulkan.RenderPass.Core (R) where
+
+import Foreign.Ptr
+
+data RTag
+type R = Ptr RTag
diff --git a/src/Gpu/Vulkan/RenderPass/Core.hsc b/src/Gpu/Vulkan/RenderPass/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/RenderPass/Core.hsc
@@ -0,0 +1,108 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.RenderPass.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, R, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoAttachmentCount, createInfoPAttachments,
+	createInfoSubpassCount, createInfoPSubpasses,
+	createInfoDependencyCount, createInfoPDependencies,
+
+	-- * BEGIN INFO
+
+	BeginInfo, pattern BeginInfo,
+	beginInfoSType, beginInfoPNext,
+	beginInfoRenderPass, beginInfoFramebuffer, beginInfoRenderArea,
+	beginInfoClearValueCount, beginInfoPClearValues
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.Core
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+import qualified Gpu.Vulkan.Attachment.Core as Attachment
+import qualified Gpu.Vulkan.Subpass.Core as Subpass
+import qualified Gpu.Vulkan.Framebuffer.Core as Framebuffer
+
+#include <vulkan/vulkan.h>
+
+sTypeC, sTypeB :: #{type VkStructureType}
+sTypeC = #{const VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO}
+sTypeB = #{const VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO}
+
+struct "CreateInfo" #{size VkRenderPassCreateInfo}
+		#{alignment VkRenderPassCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkRenderPassCreateInfo, sType} p sTypeC |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkRenderPassCreateInfo, pNext} |],
+		[| #{poke VkRenderPassCreateInfo, pNext} |]),
+	("flags", ''#{type VkRenderPassCreateFlags},
+		[| #{peek VkRenderPassCreateInfo, flags} |],
+		[| #{poke VkRenderPassCreateInfo, flags} |]),
+	("attachmentCount", ''#{type uint32_t},
+		[| #{peek VkRenderPassCreateInfo, attachmentCount} |],
+		[| #{poke VkRenderPassCreateInfo, attachmentCount} |]),
+	("pAttachments", ''Attachment.PtrDescription,
+		[| #{peek VkRenderPassCreateInfo, pAttachments} |],
+		[| #{poke VkRenderPassCreateInfo, pAttachments} |]),
+	("subpassCount", ''#{type uint32_t},
+		[| #{peek VkRenderPassCreateInfo, subpassCount} |],
+		[| #{poke VkRenderPassCreateInfo, subpassCount} |]),
+	("pSubpasses", ''Subpass.PtrDescription,
+		[| #{peek VkRenderPassCreateInfo, pSubpasses} |],
+		[| #{poke VkRenderPassCreateInfo, pSubpasses} |]),
+	("dependencyCount", ''#{type uint32_t},
+		[| #{peek VkRenderPassCreateInfo, dependencyCount} |],
+		[| #{poke VkRenderPassCreateInfo, dependencyCount} |]),
+	("pDependencies", ''Subpass.PtrDependency,
+		[| #{peek VkRenderPassCreateInfo, pDependencies} |],
+		[| #{poke VkRenderPassCreateInfo, pDependencies} |]) ]
+	[''Show, ''Storable]
+
+data RTag
+type R = Ptr RTag
+
+foreign import ccall "vkCreateRenderPass" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr R ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroyRenderPass" destroy ::
+	Device.D -> R -> Ptr AllocationCallbacks.A -> IO ()
+
+struct "BeginInfo" #{size VkRenderPassBeginInfo}
+		#{alignment VkRenderPassBeginInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkRenderPassBeginInfo, sType} p sTypeB |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkRenderPassBeginInfo, pNext} |],
+		[| #{poke VkRenderPassBeginInfo, pNext} |]),
+	("renderPass", ''R,
+		[| #{peek VkRenderPassBeginInfo, renderPass } |],
+		[| #{poke VkRenderPassBeginInfo, renderPass } |]),
+	("framebuffer", ''Framebuffer.F,
+		[| #{peek VkRenderPassBeginInfo, framebuffer} |],
+		[| #{poke VkRenderPassBeginInfo, framebuffer} |]),
+	("renderArea", ''Rect2d,
+		[| #{peek VkRenderPassBeginInfo, renderArea} |],
+		[| #{poke VkRenderPassBeginInfo, renderArea} |]),
+	("clearValueCount", ''#{type uint32_t},
+		[| #{peek VkRenderPassBeginInfo, clearValueCount} |],
+		[| #{poke VkRenderPassBeginInfo, clearValueCount} |]),
+	("pClearValues", ''PtrClearValue,
+		[| #{peek VkRenderPassBeginInfo, pClearValues} |],
+		[| #{poke VkRenderPassBeginInfo, pClearValues} |]) ]
+	[''Show, ''Storable]
diff --git a/src/Gpu/Vulkan/Sampler/Core.hsc b/src/Gpu/Vulkan/Sampler/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Sampler/Core.hsc
@@ -0,0 +1,104 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Sampler.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, S, PtrS, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoMagFilter, createInfoMinFilter, createInfoMipmapMode,
+	createInfoAddressModeU, createInfoAddressModeV, createInfoAddressModeW,
+	createInfoMipLodBias,
+	createInfoAnisotropyEnable, createInfoMaxAnisotropy,
+	createInfoCompareEnable, createInfoCompareOp,
+	createInfoMinLod, createInfoMaxLod,
+	createInfoBorderColor, createInfoUnnormalizedCoordinates
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+data STag
+type S = Ptr STag
+
+type PtrS = Ptr S
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}
+
+struct "CreateInfo" #{size VkSamplerCreateInfo}
+		#{alignment VkSamplerCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkSamplerCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkSamplerCreateInfo, pNext} |],
+		[| #{poke VkSamplerCreateInfo, pNext} |]),
+	("flags", ''#{type VkSamplerCreateFlags},
+		[| #{peek VkSamplerCreateInfo, flags} |],
+		[| #{poke VkSamplerCreateInfo, flags} |]),
+	("magFilter", ''#{type VkFilter},
+		[| #{peek VkSamplerCreateInfo, magFilter} |],
+		[| #{poke VkSamplerCreateInfo, magFilter} |]),
+	("minFilter", ''#{type VkFilter},
+		[| #{peek VkSamplerCreateInfo, minFilter} |],
+		[| #{poke VkSamplerCreateInfo, minFilter} |]),
+	("mipmapMode", ''#{type VkSamplerMipmapMode},
+		[| #{peek VkSamplerCreateInfo, mipmapMode} |],
+		[| #{poke VkSamplerCreateInfo, mipmapMode} |]),
+	("addressModeU", ''#{type VkSamplerAddressMode},
+		[| #{peek VkSamplerCreateInfo, addressModeU} |],
+		[| #{poke VkSamplerCreateInfo, addressModeU} |]),
+	("addressModeV", ''#{type VkSamplerAddressMode},
+		[| #{peek VkSamplerCreateInfo, addressModeV} |],
+		[| #{poke VkSamplerCreateInfo, addressModeV} |]),
+	("addressModeW", ''#{type VkSamplerAddressMode},
+		[| #{peek VkSamplerCreateInfo, addressModeW} |],
+		[| #{poke VkSamplerCreateInfo, addressModeW} |]),
+	("mipLodBias", ''#{type float},
+		[| #{peek VkSamplerCreateInfo, mipLodBias} |],
+		[| #{poke VkSamplerCreateInfo, mipLodBias} |]),
+	("anisotropyEnable", ''#{type VkBool32},
+		[| #{peek VkSamplerCreateInfo, anisotropyEnable} |],
+		[| #{poke VkSamplerCreateInfo, anisotropyEnable} |]),
+	("maxAnisotropy", ''#{type float},
+		[| #{peek VkSamplerCreateInfo, maxAnisotropy} |],
+		[| #{poke VkSamplerCreateInfo, maxAnisotropy} |]),
+	("compareEnable", ''#{type VkBool32},
+		[| #{peek VkSamplerCreateInfo, compareEnable} |],
+		[| #{poke VkSamplerCreateInfo, compareEnable} |]),
+	("compareOp", ''#{type VkCompareOp},
+		[| #{peek VkSamplerCreateInfo, compareOp} |],
+		[| #{poke VkSamplerCreateInfo, compareOp} |]),
+	("minLod", ''#{type float},
+		[| #{peek VkSamplerCreateInfo, minLod} |],
+		[| #{poke VkSamplerCreateInfo, minLod} |]),
+	("maxLod", ''#{type float},
+		[| #{peek VkSamplerCreateInfo, maxLod} |],
+		[| #{poke VkSamplerCreateInfo, maxLod} |]),
+	("borderColor", ''#{type VkBorderColor},
+		[| #{peek VkSamplerCreateInfo, borderColor} |],
+		[| #{poke VkSamplerCreateInfo, borderColor} |]),
+	("unnormalizedCoordinates", ''#{type VkBool32},
+		[| #{peek VkSamplerCreateInfo, unnormalizedCoordinates} |],
+		[| #{poke VkSamplerCreateInfo, unnormalizedCoordinates} |]) ]
+	[''Show, ''Storable]
+
+foreign import ccall "vkCreateSampler" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr S ->
+	IO #{type VkResult}
+
+foreign import ccall "vkDestroySampler" destroy ::
+	Device.D -> S -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Semaphore/Core.hs-boot b/src/Gpu/Vulkan/Semaphore/Core.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Semaphore/Core.hs-boot
@@ -0,0 +1,9 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Semaphore.Core (S, PtrS) where
+
+import Foreign.Ptr
+
+data STag
+type S = Ptr STag
+type PtrS = Ptr S
diff --git a/src/Gpu/Vulkan/Semaphore/Core.hsc b/src/Gpu/Vulkan/Semaphore/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Semaphore/Core.hsc
@@ -0,0 +1,51 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Semaphore.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, S, PtrS, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import qualified Gpu.Vulkan.AllocationCallbacks.Core as AllocationCallbacks
+import qualified Gpu.Vulkan.Device.Core as Device
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkSemaphoreCreateInfo}
+		#{alignment VkSemaphoreCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkSemaphoreCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid,
+		[| #{peek VkSemaphoreCreateInfo, pNext} |],
+		[| #{poke VkSemaphoreCreateInfo, pNext} |]),
+	("flags", ''#{type VkSemaphoreCreateFlags},
+		[| #{peek VkSemaphoreCreateInfo, flags} |],
+		[| #{poke VkSemaphoreCreateInfo, flags} |]) ]
+	[''Show, ''Storable]
+
+data STag
+type S = Ptr STag
+type PtrS = Ptr S
+
+foreign import ccall "vkCreateSemaphore" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A ->
+	Ptr S -> IO #{type VkResult}
+
+foreign import ccall "vkDestroySemaphore" destroy ::
+	Device.D -> S -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/ShaderModule/Core.hsc b/src/Gpu/Vulkan/ShaderModule/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/ShaderModule/Core.hsc
@@ -0,0 +1,57 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.ShaderModule.Core (
+
+	-- * CREATE AND DESTROY
+
+	create, destroy, S, CreateInfo, pattern CreateInfo,
+	createInfoSType, createInfoPNext, createInfoFlags,
+	createInfoCodeSize, createInfoPCode
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+import Data.Int
+
+import Gpu.Vulkan.TypeSynonyms.Core
+import Gpu.Vulkan.AllocationCallbacks.Core qualified as AllocationCallbacks
+import Gpu.Vulkan.Device.Core qualified as Device
+
+#include <vulkan/vulkan.h>
+
+sType :: #{type VkStructureType}
+sType = #{const VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}
+
+struct "CreateInfo" #{size VkShaderModuleCreateInfo}
+		#{alignment VkShaderModuleCreateInfo} [
+	("sType", ''(), [| const $ pure () |],
+		[| \p _ -> #{poke VkShaderModuleCreateInfo, sType} p sType |]),
+	("pNext", ''PtrVoid, [| #{peek VkShaderModuleCreateInfo, pNext} |],
+		[| #{poke VkShaderModuleCreateInfo, pNext} |]),
+	("flags", ''#{type VkShaderModuleCreateFlags},
+		[| #{peek VkShaderModuleCreateInfo, flags} |],
+		[| #{poke VkShaderModuleCreateInfo, flags} |]),
+	("codeSize", ''#{type size_t},
+		[| #{peek VkShaderModuleCreateInfo, codeSize} |],
+		[| #{poke VkShaderModuleCreateInfo, codeSize} |]),
+	("pCode", ''PtrUint32T,
+		[| #{peek VkShaderModuleCreateInfo, pCode} |],
+		[| #{poke VkShaderModuleCreateInfo, pCode} |]) ]
+	[''Show, ''Storable]
+
+data STag
+type S = Ptr STag
+
+foreign import ccall "vkCreateShaderModule" create ::
+	Device.D -> Ptr CreateInfo -> Ptr AllocationCallbacks.A -> Ptr S -> IO #{type VkResult}
+
+foreign import ccall "vkDestroyShaderModule" destroy ::
+	Device.D -> S -> Ptr AllocationCallbacks.A -> IO ()
diff --git a/src/Gpu/Vulkan/Specialization/Core.hsc b/src/Gpu/Vulkan/Specialization/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Specialization/Core.hsc
@@ -0,0 +1,58 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Specialization.Core (
+
+	-- * INFO
+
+	Info, PtrInfo, pattern Info,
+	infoMapEntryCount, infoPMapEntries, infoDataSize, infoPData,
+
+	-- ** MapEntry
+
+	MapEntry, pattern MapEntry,
+	mapEntryConstantId, mapEntryOffset, mapEntrySize,
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Foreign.C.Struct.TypeSynonyms
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+struct "MapEntry" #{size VkSpecializationMapEntry}
+		#{alignment VkSpecializationMapEntry} [
+	("constantId", ''#{type uint32_t},
+		[| #{peek VkSpecializationMapEntry, constantID} |],
+		[| #{poke VkSpecializationMapEntry, constantID} |]),
+	("offset", ''#{type uint32_t},
+		[| #{peek VkSpecializationMapEntry, offset} |],
+		[| #{poke VkSpecializationMapEntry, offset} |]),
+	("size", ''#{type size_t},
+		[| #{peek VkSpecializationMapEntry, size} |],
+		[| #{poke VkSpecializationMapEntry, size} |]) ]
+	[''Show, ''Storable]
+
+type PtrMapEntry = Ptr MapEntry
+
+struct "Info" #{size VkSpecializationInfo} #{alignment VkSpecializationInfo} [
+	("mapEntryCount", ''#{type uint32_t},
+		[| #{peek VkSpecializationInfo, mapEntryCount} |],
+		[| #{poke VkSpecializationInfo, mapEntryCount} |]),
+	("pMapEntries", ''PtrMapEntry,
+		[| #{peek VkSpecializationInfo, pMapEntries} |],
+		[| #{poke VkSpecializationInfo, pMapEntries} |]),
+	("dataSize", ''#{type size_t},
+		[| #{peek VkSpecializationInfo, dataSize} |],
+		[| #{poke VkSpecializationInfo, dataSize} |]),
+	("pData", ''PtrVoid,
+		[| #{peek VkSpecializationInfo, pData} |],
+		[| #{poke VkSpecializationInfo, pData} |]) ]
+	[''Show, ''Storable]
+
+type PtrInfo = Ptr Info
diff --git a/src/Gpu/Vulkan/Subpass/Core.hsc b/src/Gpu/Vulkan/Subpass/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/Subpass/Core.hsc
@@ -0,0 +1,99 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.Subpass.Core (
+
+	-- * DESCRIPTION
+
+	Description, PtrDescription, pattern Description,
+	descriptionFlags, descriptionPipelineBindPoint,
+	descriptionInputAttachmentCount, descriptionPInputAttachments,
+	descriptionColorAttachmentCount, descriptionPColorAttachments,
+	descriptionPResolveAttachments, descriptionPDepthStencilAttachment,
+	descriptionPreserveAttachmentCount, descriptionPPreserveAttachments,
+
+	-- * DEPENDENCY
+
+	Dependency, PtrDependency, pattern Dependency,
+	dependencySrcSubpass, dependencyDstSubpass,
+	dependencySrcStageMask, dependencyDstStageMask,
+	dependencySrcAccessMask, dependencyDstAccessMask,
+	dependencyDependencyFlags
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+import Gpu.Vulkan.TypeSynonyms.Core
+import Gpu.Vulkan.Attachment.Core qualified as Attachment
+
+#include <vulkan/vulkan.h>
+
+struct "Description" #{size VkSubpassDescription}
+		#{alignment VkSubpassDescription} [
+	("flags", ''#{type VkSubpassDescriptionFlags},
+		[| #{peek VkSubpassDescription, flags} |],
+		[| #{poke VkSubpassDescription, flags} |]),
+	("pipelineBindPoint", ''#{type VkPipelineBindPoint},
+		[| #{peek VkSubpassDescription, pipelineBindPoint} |],
+		[| #{poke VkSubpassDescription, pipelineBindPoint} |]),
+	("inputAttachmentCount", ''#{type uint32_t},
+		[| #{peek VkSubpassDescription, inputAttachmentCount} |],
+		[| #{poke VkSubpassDescription, inputAttachmentCount} |]),
+	("pInputAttachments", ''Attachment.PtrReference,
+		[| #{peek VkSubpassDescription, pInputAttachments} |],
+		[| #{poke VkSubpassDescription, pInputAttachments} |]),
+	("colorAttachmentCount", ''#{type uint32_t},
+		[| #{peek VkSubpassDescription, colorAttachmentCount} |],
+		[| #{poke VkSubpassDescription, colorAttachmentCount} |]),
+	("pColorAttachments", ''Attachment.PtrReference,
+		[| #{peek VkSubpassDescription, pColorAttachments} |],
+		[| #{poke VkSubpassDescription, pColorAttachments} |]),
+	("pResolveAttachments", ''Attachment.PtrReference,
+		[| #{peek VkSubpassDescription, pResolveAttachments} |],
+		[| #{poke VkSubpassDescription, pResolveAttachments} |]),
+	("pDepthStencilAttachment", ''Attachment.PtrReference,
+		[| #{peek VkSubpassDescription, pDepthStencilAttachment} |],
+		[| #{poke VkSubpassDescription, pDepthStencilAttachment} |]),
+	("preserveAttachmentCount", ''#{type uint32_t},
+		[| #{peek VkSubpassDescription, preserveAttachmentCount} |],
+		[| #{poke VkSubpassDescription, preserveAttachmentCount} |]),
+	("pPreserveAttachments", ''PtrUint32T,
+		[| #{peek VkSubpassDescription, pPreserveAttachments} |],
+		[| #{poke VkSubpassDescription, pPreserveAttachments} |]) ]
+	[''Show, ''Storable]
+
+type PtrDescription = Ptr Description
+
+struct "Dependency" #{size VkSubpassDependency}
+		#{alignment VkSubpassDependency} [
+	("srcSubpass", ''#{type uint32_t},
+		[| #{peek VkSubpassDependency, srcSubpass} |],
+		[| #{poke VkSubpassDependency, srcSubpass} |]),
+	("dstSubpass", ''#{type uint32_t},
+		[| #{peek VkSubpassDependency, dstSubpass} |],
+		[| #{poke VkSubpassDependency, dstSubpass} |]),
+	("srcStageMask", ''#{type VkPipelineStageFlags},
+		[| #{peek VkSubpassDependency, srcStageMask} |],
+		[| #{poke VkSubpassDependency, srcStageMask} |]),
+	("dstStageMask", ''#{type VkPipelineStageFlags},
+		[| #{peek VkSubpassDependency, dstStageMask} |],
+		[| #{poke VkSubpassDependency, dstStageMask} |]),
+	("srcAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkSubpassDependency, srcAccessMask} |],
+		[| #{poke VkSubpassDependency, srcAccessMask} |]),
+	("dstAccessMask", ''#{type VkAccessFlags},
+		[| #{peek VkSubpassDependency, dstAccessMask} |],
+		[| #{poke VkSubpassDependency, dstAccessMask} |]),
+	("dependencyFlags", ''#{type VkDependencyFlags},
+		[| #{peek VkSubpassDependency, dependencyFlags} |],
+		[| #{poke VkSubpassDependency, dependencyFlags} |]) ]
+	[''Show, ''Storable]
+
+type PtrDependency = Ptr Dependency
diff --git a/src/Gpu/Vulkan/TypeSynonyms/Core.hsc b/src/Gpu/Vulkan/TypeSynonyms/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/TypeSynonyms/Core.hsc
@@ -0,0 +1,25 @@
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.TypeSynonyms.Core (
+
+	-- * PTR
+
+	PtrResult, PtrUint32T,
+
+	-- * LIST
+
+	ListUint8T, ListUint32T
+
+	) where
+
+import Foreign.Ptr
+import Data.Word
+import Data.Int
+
+#include <vulkan/vulkan.h>
+
+type PtrUint32T = Ptr #{type uint32_t}
+type PtrResult = Ptr #{type VkResult}
+
+type ListUint8T = [#{type uint8_t}]
+type ListUint32T = [#{type uint32_t}]
diff --git a/src/Gpu/Vulkan/VertexInput/Core.hsc b/src/Gpu/Vulkan/VertexInput/Core.hsc
new file mode 100644
--- /dev/null
+++ b/src/Gpu/Vulkan/VertexInput/Core.hsc
@@ -0,0 +1,61 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
+
+module Gpu.Vulkan.VertexInput.Core (
+
+	-- * BINDING DESCRIPTION
+
+	BindingDescription, PtrBindingDescription, pattern BindingDescription,
+	bindingDescriptionBinding, bindingDescriptionStride,
+	bindingDescriptionInputRate,
+
+	-- * ATTRIBUTE DESCRIPTION
+
+	AttributeDescription, PtrAttributeDescription,
+	pattern AttributeDescription,
+	attributeDescriptionLocation, attributeDescriptionBinding,
+	attributeDescriptionFormat, attributeDescriptionOffset
+
+	) where
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.C.Struct
+import Data.Word
+
+#include <vulkan/vulkan.h>
+
+struct "BindingDescription" #{size VkVertexInputBindingDescription}
+		#{alignment VkVertexInputBindingDescription} [
+	("binding", ''#{type uint32_t},
+		[| #{peek VkVertexInputBindingDescription, binding} |],
+		[| #{poke VkVertexInputBindingDescription, binding} |]),
+	("stride", ''#{type uint32_t},
+		[| #{peek VkVertexInputBindingDescription, stride} |],
+		[| #{poke VkVertexInputBindingDescription, stride} |]),
+	("inputRate", ''#{type VkVertexInputRate},
+		[| #{peek VkVertexInputBindingDescription, inputRate} |],
+		[| #{poke VkVertexInputBindingDescription, inputRate} |]) ]
+	[''Show, ''Storable]
+
+type PtrBindingDescription = Ptr BindingDescription
+
+struct "AttributeDescription" #{size VkVertexInputAttributeDescription}
+		#{alignment VkVertexInputAttributeDescription} [
+	("location", ''#{type uint32_t},
+		[| #{peek VkVertexInputAttributeDescription, location} |],
+		[| #{poke VkVertexInputAttributeDescription, location} |]),
+	("binding", ''#{type uint32_t},
+		[| #{peek VkVertexInputAttributeDescription, binding} |],
+		[| #{poke VkVertexInputAttributeDescription, binding} |]),
+	("format", ''#{type VkFormat},
+		[| #{peek VkVertexInputAttributeDescription, format} |],
+		[| #{poke VkVertexInputAttributeDescription, format} |]),
+	("offset", ''#{type uint32_t},
+		[| #{peek VkVertexInputAttributeDescription, offset} |],
+		[| #{poke VkVertexInputAttributeDescription, offset} |]) ]
+	[''Show, ''Storable]
+
+type PtrAttributeDescription = Ptr AttributeDescription
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
