From 5706876e21210812301e30140db10cabd50f5e59 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 16:43:18 +0800 Subject: [PATCH 01/70] Add missing module to cabal --- generate-new/generate-new.cabal | 2 -- 1 file changed, 2 deletions(-) diff --git a/generate-new/generate-new.cabal b/generate-new/generate-new.cabal index ac3bce9a2..d867a3ee2 100644 --- a/generate-new/generate-new.cabal +++ b/generate-new/generate-new.cabal @@ -3,8 +3,6 @@ cabal-version: 1.12 -- This file has been generated from package.yaml by hpack version 0.34.2. -- -- see: https://github.com/sol/hpack --- --- hash: f003049e4e28f45438397824d96b59f210dce0b5135c67e24548bd9019a968f5 name: generate-new version: 0.0.0 From 1361a0cc3f1cb5756eedd0e8f29454121c481a62 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 17:06:07 +0800 Subject: [PATCH 02/70] Parse and write SPIR-V information Closes https://github.com/expipiplus1/vulkan/issues/214 --- generate-new/generate-new.cabal | 1 + generate-new/src/Spec/Parse.hs | 126 ++++++++++++++++++++++------ generate-new/src/Spec/Types.hs | 26 ++++++ generate-new/vk/VK/Render.hs | 25 +++--- generate-new/vk/VK/SPIRVElements.hs | 115 +++++++++++++++++++++++++ 5 files changed, 256 insertions(+), 37 deletions(-) create mode 100644 generate-new/vk/VK/SPIRVElements.hs diff --git a/generate-new/generate-new.cabal b/generate-new/generate-new.cabal index d867a3ee2..731e7bfd6 100644 --- a/generate-new/generate-new.cabal +++ b/generate-new/generate-new.cabal @@ -140,6 +140,7 @@ executable vk VK.AssignModules VK.Bracket VK.Render + VK.SPIRVElements Paths_generate_new hs-source-dirs: vk diff --git a/generate-new/src/Spec/Parse.hs b/generate-new/src/Spec/Parse.hs index 8e78f3346..3296e66dc 100644 --- a/generate-new/src/Spec/Parse.hs +++ b/generate-new/src/Spec/Parse.hs @@ -1,8 +1,7 @@ module Spec.Parse ( module Spec.Types , parseSpec - ) -where + ) where import Control.Monad.Extra ( mapMaybeM ) import Data.Bits @@ -102,6 +101,10 @@ parseSpec bs = do parseExtensions OnlyDisabled . contents =<< oneChild "extensions" n specAPIConstants <- parseAPIConstants (contents n) specExtensionConstants <- parseExtensionConstants (contents n) + specSPIRVExtensions <- + parseSPIRVExtensions . contents =<< oneChild "spirvextensions" n + specSPIRVCapabilities <- + parseSPIRVCapabilities . contents =<< oneChild "spirvcapabilities" n let sizeMap :: Map.Map CName (Int, Int) sizeMap = @@ -342,7 +345,11 @@ data ParseDisabled = OnlyDisabled | NotDisabled parseExtensions :: ParseDisabled -> [Content] -> P (Vector Extension) parseExtensions parseDisabled es = V.fromList <$> sequenceV - [ parseExtension e | Element e <- es, "extension" == name e, disabled parseDisabled e ] + [ parseExtension e + | Element e <- es + , "extension" == name e + , disabled parseDisabled e + ] where parseExtension :: Node -> P Extension parseExtension n = do @@ -391,7 +398,7 @@ parseExtensionConstants :: [Content] -> P (Vector Constant) parseExtensionConstants es = V.fromList <$> sequenceV [ do n' <- decode n - context n' $ (Constant (CName n') <$> parseConstant v) + context n' (Constant (CName n') <$> parseConstant v) | Element e <- es , "extensions" == name e , Element ex <- contents e @@ -419,18 +426,18 @@ someConstants r = parseTypeAliases :: [ByteString] -> [Content] -> P (Vector Alias) parseTypeAliases categories es = fmap fromList - . sequenceV + . sequenceV $ [ do - aName <- nameAttr "struct alias" n - aTarget <- decodeName alias - let aType = TypeAlias - pure Alias { .. } - | Element n <- es - , "type" == name n - , Just alias <- pure $ getAttr "alias" n - , Just c <- pure $ getAttr "category" n - , c `elem` categories - ] + aName <- nameAttr "struct alias" n + aTarget <- decodeName alias + let aType = TypeAlias + pure Alias { .. } + | Element n <- es + , "type" == name n + , Just alias <- pure $ getAttr "alias" n + , Just c <- pure $ getAttr "category" n + , c `elem` categories + ] parseEnumAliases :: Vector Node -> P (Vector Alias) parseEnumAliases rs = @@ -447,8 +454,7 @@ parseEnumAliases rs = , Just alias <- pure $ getAttr "alias" ee ] -parseCommandAliases - :: [Content] -> P (Vector Alias) +parseCommandAliases :: [Content] -> P (Vector Alias) parseCommandAliases es = fmap V.fromList . sequenceV @@ -476,7 +482,7 @@ parseConstantAliases es = , Element ee <- contents e , "enum" == name ee , Just alias <- pure $ getAttr "alias" ee - , aType <- [TypeAlias, PatternAlias] + , aType <- [TypeAlias, PatternAlias] ] ---------------------------------------------------------------- @@ -611,7 +617,8 @@ parseEnums types es = do Nothing -> (0x1 `shiftL`) <$> readAttr "bitpos" v pure EnumValue { .. } -parseEnumExtensions :: Vector (Node, Maybe Int) -> P (Vector (CName, EnumValue)) +parseEnumExtensions + :: Vector (Node, Maybe Int) -> P (Vector (CName, EnumValue)) parseEnumExtensions rs = fmap V.fromList . sequenceV @@ -673,7 +680,8 @@ parseEnumExtensions rs = in fromIntegral (sign n) -appendEnumExtensions :: Vector (CName, EnumValue) -> Vector Enum' -> Vector Enum' +appendEnumExtensions + :: Vector (CName, EnumValue) -> Vector Enum' -> Vector Enum' appendEnumExtensions extensions = let extensionMap :: Map.Map CName (Vector EnumValue) @@ -693,7 +701,8 @@ parseStructs :: [Content] -> P (Vector (StructOrUnion AStruct WithoutSize WithoutChildren)) parseStructs = onTypes "struct" parseStruct -parseUnions :: [Content] -> P (Vector (StructOrUnion AUnion WithoutSize WithoutChildren)) +parseUnions + :: [Content] -> P (Vector (StructOrUnion AUnion WithoutSize WithoutChildren)) parseUnions = onTypes "union" parseStruct parseStruct :: Node -> P (StructOrUnion a WithoutSize WithoutChildren) @@ -765,6 +774,60 @@ parseCommands es = pLengths <- lenListAttr listAttrName m pure Parameter { .. } +---------------------------------------------------------------- +-- SPIR-V +---------------------------------------------------------------- + +parseSPIRVExtensions :: [Content] -> P (Vector SPIRVExtension) +parseSPIRVExtensions = parseSPIRVThings "spirvextension" SPIRVExtension + +parseSPIRVCapabilities :: [Content] -> P (Vector SPIRVCapability) +parseSPIRVCapabilities = parseSPIRVThings "spirvcapability" SPIRVCapability + +parseSPIRVThings + :: ByteString + -> (Text -> Vector SPIRVRequirement -> a) + -> [Content] + -> P (Vector a) +parseSPIRVThings thingType mkThing es = V.fromList + <$> sequenceV [ parseExtension e | Element e <- es, thingType == name e ] + where + parseExtension n = do + name <- decode =<< note ("spirv " <> show thingType <> " has no name") + (getAttr "name" n) + reqs <- V.fromList + <$> traverse parseSPIRVReq [ r | Element r <- contents n ] + pure $ mkThing name reqs + +parseSPIRVReq :: Node -> P SPIRVRequirement +parseSPIRVReq r + | Just v <- getAttr "version" r + = case parseAPIVersion v of + Nothing -> throw $ "Unable to parse API version: " <> show v + Just v -> pure $ SPIRVReqVersion v + | Just e <- getAttr "extension" r + = do + e' <- decode e + pure $ SPIRVReqExtension e' + | Just s <- getAttr "struct" r + , Just f <- getAttr "feature" r + = do + exts' <- listAttr decode "requires" r + s' <- CName <$> decode s + f' <- CName <$> decode f + pure $ SPIRVReqFeature s' f' exts' + | Just p <- getAttr "property" r + , Just m <- getAttr "member" r + , Just v <- getAttr "value" r + = do + exts' <- listAttr decode "requires" r + p' <- CName <$> decode p + m' <- CName <$> decode m + v' <- CName <$> decode v + pure $ SPIRVReqProperty p' m' v' exts' + | otherwise + = throw $ "Couldn't parse SPIRV requirement element: " <> show r + ---------------------------------------------------------------- -- Getting all the type names ---------------------------------------------------------------- @@ -890,6 +953,17 @@ disabled p e = OnlyDisabled -> (==) in Just "disabled" `comp` getAttr "supported" e +-- >>> parseAPIVersion "VK_API_VERSION_1_2" +-- Just (Version {versionBranch = [1,2], versionTags = []}) +parseAPIVersion :: ByteString -> Maybe Version +parseAPIVersion b = do + let p = "VK_API_VERSION_" + v <- if p `BS.isPrefixOf` b then pure $ BS.drop (BS.length p) b else empty + let cs = BS.split '_' v + is <- traverse (readMaybe . BS.unpack) cs + pure $ makeVersion is + + ---------------------------------------------------------------- -- XML ---------------------------------------------------------------- @@ -932,11 +1006,11 @@ allTextOn p = elemText :: ByteString -> Node -> Maybe ByteString elemText elemName node = let r = - [ m - | Element a <- contents node - , name a == elemName - , [Text m] <- pure (contents a) - ] + [ m + | Element a <- contents node + , name a == elemName + , [Text m] <- pure (contents a) + ] in case r of [x] -> Just x _ -> Nothing diff --git a/generate-new/src/Spec/Types.hs b/generate-new/src/Spec/Types.hs index 547c53622..878cefff4 100644 --- a/generate-new/src/Spec/Types.hs +++ b/generate-new/src/Spec/Types.hs @@ -28,6 +28,8 @@ data Spec = Spec , specDisabledExtensions :: Vector Extension , specAPIConstants :: Vector Constant , specExtensionConstants :: Vector Constant + , specSPIRVExtensions :: Vector SPIRVExtension + , specSPIRVCapabilities :: Vector SPIRVCapability } deriving Show @@ -227,3 +229,27 @@ data EnumType -- ^ Stores the name of the "Flags" type deriving (Show, Eq) +-- +-- SPIR-V stuff +-- + +data SPIRVExtension = SPIRVExtension + { spirvExtensionName :: Text + , spirvExtensionReqs :: Vector SPIRVRequirement + } + deriving (Show, Eq) + +data SPIRVCapability = SPIRVCapability + { spirvCapabilityName :: Text + , spirvCapabilityReqs :: Vector SPIRVRequirement + } + deriving (Show, Eq) + +data SPIRVRequirement + = SPIRVReqVersion Version + | SPIRVReqExtension Text + | SPIRVReqFeature CName CName (Vector Text) + -- ^ Struct, feature, requires + | SPIRVReqProperty CName CName CName (Vector Text) + -- ^ Property, member, value, requires + deriving (Show, Eq) diff --git a/generate-new/vk/VK/Render.hs b/generate-new/vk/VK/Render.hs index 7bc73f92d..3b7141885 100644 --- a/generate-new/vk/VK/Render.hs +++ b/generate-new/vk/VK/Render.hs @@ -1,6 +1,5 @@ {-# language DeriveFunctor, DeriveFoldable, DeriveTraversable #-} -module VK.Render - where +module VK.Render where import qualified Data.HashMap.Strict as Map import Data.Vector ( Vector ) @@ -39,6 +38,7 @@ import Spec.Parse import Render.State ( HasRenderState ) import VK.Bracket +import VK.SPIRVElements data RenderedSpec a = RenderedSpec { rsHandles :: Vector a @@ -121,15 +121,18 @@ renderSpec spec@Spec {..} getDoc ss us cs = do , rsAPIConstants = renderConstant <$> filterConstants specAPIConstants , rsExtensionConstants = renderConstant <$> filterConstants specExtensionConstants - , rsOthers = bespokeElements - <> V.singleton (renderDynamicLoader cs) - <> cStructDocs - <> V.singleton marshalUtils - <> V.singleton zeroClass - <> V.singleton hasObjectTypeClass - <> V.singleton (vkExceptionRenderElement getDoc vkResult) - <> specVersions spec - <> V.singleton (structExtends spec) + , rsOthers = + bespokeElements + <> V.singleton (renderDynamicLoader cs) + <> cStructDocs + <> V.singleton marshalUtils + <> V.singleton zeroClass + <> V.singleton hasObjectTypeClass + <> V.singleton (vkExceptionRenderElement getDoc vkResult) + <> specVersions spec + <> V.singleton (structExtends spec) + <> V.singleton + (renderSPIRVElements specSPIRVExtensions specSPIRVCapabilities) } -- | Render a command along with any associated bracketing function diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs new file mode 100644 index 000000000..084ffdc82 --- /dev/null +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -0,0 +1,115 @@ +{-# LANGUAGE QuasiQuotes #-} + +module VK.SPIRVElements + ( renderSPIRVElements + ) where + +import qualified Data.Text as T +import Data.Text.Prettyprint.Doc +import Data.Vector ( Vector ) +import qualified Data.Vector as V +import Data.Version ( Version(versionBranch) + , makeVersion + ) +import Error +import Polysemy.Input +import Relude +import Render.Element +import Spec.Types +import Text.InterpolatedString.Perl6.Unindented +import VkModulePrefix + +renderSPIRVElements + :: (HasErr r, HasRenderParams r) + => Vector SPIRVExtension + -> Vector SPIRVCapability + -> Sem r RenderElement +renderSPIRVElements exts caps = do + genRe "SPIR-V stuff" $ do + tellExplicitModule (vulkanModule ["SPIRVInfo"]) + tellCanFormat + bespokeStuff + renderExts exts + renderCaps caps + +renderExts + :: (HasRenderElem r, HasRenderParams r) => Vector SPIRVExtension -> Sem r () +renderExts = renderSPIRVThing "spirvExtensionRequirements" + spirvExtensionName + spirvExtensionReqs + +renderCaps + :: (HasRenderElem r, HasRenderParams r) => Vector SPIRVCapability -> Sem r () +renderCaps = renderSPIRVThing "spirvCapabilityRequirements" + spirvCapabilityName + spirvCapabilityReqs + +renderSPIRVThing + :: (HasRenderElem r, HasRenderParams r) + => Text + -> (a -> Text) + -> (a -> Vector SPIRVRequirement) + -> Vector a + -> Sem r () +renderSPIRVThing funName name reqs xs = do + let case' x = do + reqs' <- traverse renderReq (V.toList (reqs x)) + pure $ viaShow (name x) <+> "->" <+> list reqs' + cases <- (<> ["_ -> []"]) <$> traverse case' (V.toList xs) + tellImport ''ByteString + tellDoc $ vsep + [ (pretty funName <+> ":: ByteString -> [SPIRVRequirement]") + , (pretty funName <+> "= \\case" <> line <> indent 2 (vsep cases)) + ] + +renderReq + :: (HasRenderParams r, HasRenderElem r) => SPIRVRequirement -> Sem r (Doc ()) +renderReq = \case + SPIRVReqVersion v -> do + tellImport 'makeVersion + pure $ "Version $ makeVersion" <+> viaShow (versionBranch v) + SPIRVReqExtension p -> do + p' <- extensionNamePattern p + pure $ "Extension" <+> p' + SPIRVReqFeature s f rs -> do + rs' <- traverse extensionNamePattern (V.toList rs) + tellLanguageExtension (LanguageExtension "OverloadedLists") + pure $ "Feature" <+> viaShow s <+> viaShow f <+> list rs' + SPIRVReqProperty p m v rs -> do + rs' <- traverse extensionNamePattern (V.toList rs) + tellLanguageExtension (LanguageExtension "OverloadedLists") + pure $ "Property" <+> viaShow p <+> viaShow m <+> viaShow v <+> list rs' + +extensionNamePattern + :: (HasRenderElem r, HasRenderParams r) + => Text + -> Sem r (Doc ()) +extensionNamePattern p = do + RenderParams {..} <- input + if "VK_VERSION_" `T.isPrefixOf` p + then pure $ viaShow p + else do + let nameName = case p of + -- TODO: Handle these properly + "VK_INTEL_shader_integer_functions2" -> + CName "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME" + _ -> CName $ T.toUpper p <> "_EXTENSION_NAME" + let p' = mkPatternName nameName + tellImport p' + pure $ pretty p' + +bespokeStuff :: (HasRenderParams r, HasRenderElem r) => Sem r () +bespokeStuff = do + tellImport ''ByteString + tellImport ''Vector + tellImport ''Version + tellDoc [qqi| + data SPIRVRequirement + = Version Version + | Extension ByteString + | Feature ByteString ByteString (Vector ByteString) + -- ^ Struct, feature, requires + | Property ByteString ByteString ByteString (Vector ByteString) + -- ^ Property, member, value, requires + deriving(Show) + |] From 5a2c4dce012a672deb7b62a2fa2a83dee5ded0da Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 17:06:34 +0800 Subject: [PATCH 03/70] wobblie hie --- generate-new/hie.yaml | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/generate-new/hie.yaml b/generate-new/hie.yaml index debf9f6e9..83193e878 100644 --- a/generate-new/hie.yaml +++ b/generate-new/hie.yaml @@ -1,8 +1,20 @@ cradle: - cabal: - - path: ./src/ - component: lib:generate-new - - path: ./vk/ - component: exe:vk - - path: ./vma/ - component: exe:vma + multi: + - path: ./out + config: + cradle: + none: + - path: ./out-vma + config: + cradle: + none: + - path: ./ + config: + cradle: + cabal: + - path: ./src/ + component: lib:generate-new + - path: ./vk/ + component: exe:vk + - path: ./vma/ + component: exe:vma From ef45e2898711f7c1de70f9562e55163ab2bd2c57 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 17:07:05 +0800 Subject: [PATCH 04/70] regenerate with SPIR-V info --- src/Vulkan.hs | 2 + src/Vulkan/SPIRVInfo.hs | 563 ++++++++++++++++++++++++++++++++++++++++ vulkan.cabal | 1 + 3 files changed, 566 insertions(+) create mode 100644 src/Vulkan/SPIRVInfo.hs diff --git a/src/Vulkan.hs b/src/Vulkan.hs index 6eaebdb3d..b7a700e9e 100644 --- a/src/Vulkan.hs +++ b/src/Vulkan.hs @@ -6,6 +6,7 @@ module Vulkan ( module Vulkan.CStruct , module Vulkan.Core12 , module Vulkan.Extensions , module Vulkan.NamedType + , module Vulkan.SPIRVInfo , module Vulkan.Version , module Vulkan.Zero ) where @@ -15,6 +16,7 @@ import Vulkan.Core11 import Vulkan.Core12 import Vulkan.Extensions import Vulkan.NamedType +import Vulkan.SPIRVInfo import Vulkan.Version import Vulkan.Zero diff --git a/src/Vulkan/SPIRVInfo.hs b/src/Vulkan/SPIRVInfo.hs new file mode 100644 index 000000000..fe02c2be8 --- /dev/null +++ b/src/Vulkan/SPIRVInfo.hs @@ -0,0 +1,563 @@ +{-# language CPP #-} +{-# language OverloadedLists #-} +module Vulkan.SPIRVInfo () where + +import Data.Version (makeVersion) +import Data.Version (Version) +import Data.ByteString (ByteString) +import Data.Vector (Vector) +import Vulkan.Extensions.VK_AMD_gcn_shader (pattern AMD_GCN_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gpu_shader_half_float (pattern AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gpu_shader_int16 (pattern AMD_GPU_SHADER_INT16_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_ballot (pattern AMD_SHADER_BALLOT_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_explicit_vertex_parameter (pattern AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_fragment_mask (pattern AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_image_load_store_lod (pattern AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_trinary_minmax (pattern AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_texture_gather_bias_lod (pattern AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_buffer_device_address (pattern EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_descriptor_indexing (pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_density_map (pattern EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (pattern EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_post_depth_coverage (pattern EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_atomic_float (pattern EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (pattern EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (pattern EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_stencil_export (pattern EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_subgroup_ballot (pattern EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_subgroup_vote (pattern EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_viewport_index_layer (pattern EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_transform_feedback (pattern EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_decorate_string (pattern GOOGLE_DECORATE_STRING_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_hlsl_functionality1 (pattern GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_user_type (pattern GOOGLE_USER_TYPE_EXTENSION_NAME) +import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (pattern INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_device_group (pattern KHR_DEVICE_GROUP_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_fragment_shading_rate (pattern KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_draw_parameters (pattern KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float16_int8 (pattern KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float_controls (pattern KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_vulkan_memory_model (pattern KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME) +import Vulkan.Extensions.VK_NVX_multiview_per_view_attributes (pattern NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_compute_shader_derivatives (pattern NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_cooperative_matrix (pattern NV_COOPERATIVE_MATRIX_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (pattern NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_geometry_shader_passthrough (pattern NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_mesh_shader (pattern NV_MESH_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_ray_tracing (pattern NV_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_sample_mask_override_coverage (pattern NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_image_footprint (pattern NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_sm_builtins (pattern NV_SHADER_SM_BUILTINS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_subgroup_partitioned (pattern NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shading_rate_image (pattern NV_SHADING_RATE_IMAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_viewport_array2 (pattern NV_VIEWPORT_ARRAY2_EXTENSION_NAME) +data SPIRVRequirement + = Version Version + | Extension ByteString + | Feature ByteString ByteString (Vector ByteString) + -- ^ Struct, feature, requires + | Property ByteString ByteString ByteString (Vector ByteString) + -- ^ Property, member, value, requires + deriving(Show) + +spirvExtensionRequirements :: ByteString -> [SPIRVRequirement] +spirvExtensionRequirements = \case + "SPV_KHR_variable_pointers" -> [Version $ makeVersion [1, 1], Extension KHR_VARIABLE_POINTERS_EXTENSION_NAME] + "SPV_AMD_shader_explicit_vertex_parameter" -> [Extension AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME] + "SPV_AMD_gcn_shader" -> [Extension AMD_GCN_SHADER_EXTENSION_NAME] + "SPV_AMD_gpu_shader_half_float" -> [Extension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME] + "SPV_AMD_gpu_shader_int16" -> [Extension AMD_GPU_SHADER_INT16_EXTENSION_NAME] + "SPV_AMD_shader_ballot" -> [Extension AMD_SHADER_BALLOT_EXTENSION_NAME] + "SPV_AMD_shader_fragment_mask" -> [Extension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] + "SPV_AMD_shader_image_load_store_lod" -> [Extension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] + "SPV_AMD_shader_trinary_minmax" -> [Extension AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME] + "SPV_AMD_texture_gather_bias_lod" -> [Extension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] + "SPV_KHR_shader_draw_parameters" -> + [Version $ makeVersion [1, 1], Extension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME] + "SPV_KHR_8bit_storage" -> [Version $ makeVersion [1, 2], Extension KHR_8BIT_STORAGE_EXTENSION_NAME] + "SPV_KHR_16bit_storage" -> [Version $ makeVersion [1, 1], Extension KHR_16BIT_STORAGE_EXTENSION_NAME] + "SPV_KHR_shader_clock" -> [Extension KHR_SHADER_CLOCK_EXTENSION_NAME] + "SPV_KHR_float_controls" -> [Version $ makeVersion [1, 2], Extension KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + "SPV_KHR_storage_buffer_storage_class" -> + [Version $ makeVersion [1, 1], Extension KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] + "SPV_KHR_post_depth_coverage" -> [Extension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] + "SPV_EXT_shader_stencil_export" -> [Extension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] + "SPV_KHR_shader_ballot" -> [Extension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] + "SPV_KHR_subgroup_vote" -> [Extension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] + "SPV_NV_sample_mask_override_coverage" -> [Extension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] + "SPV_NV_geometry_shader_passthrough" -> [Extension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] + "SPV_NV_mesh_shader" -> [Extension NV_MESH_SHADER_EXTENSION_NAME] + "SPV_NV_viewport_array2" -> [Extension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] + "SPV_NV_shader_subgroup_partitioned" -> [Extension NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] + "SPV_EXT_shader_viewport_index_layer" -> + [Version $ makeVersion [1, 2], Extension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] + "SPV_NVX_multiview_per_view_attributes" -> [Extension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] + "SPV_EXT_descriptor_indexing" -> [Version $ makeVersion [1, 2], Extension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + "SPV_KHR_vulkan_memory_model" -> [Version $ makeVersion [1, 2], Extension KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + "SPV_NV_compute_shader_derivatives" -> [Extension NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] + "SPV_NV_fragment_shader_barycentric" -> [Extension NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] + "SPV_NV_shader_image_footprint" -> [Extension NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] + "SPV_NV_shading_rate" -> [Extension NV_SHADING_RATE_IMAGE_EXTENSION_NAME] + "SPV_NV_ray_tracing" -> [Extension NV_RAY_TRACING_EXTENSION_NAME] + "SPV_KHR_ray_tracing" -> [Extension KHR_RAY_TRACING_EXTENSION_NAME] + "SPV_KHR_ray_query" -> [Extension KHR_RAY_TRACING_EXTENSION_NAME] + "SPV_GOOGLE_hlsl_functionality1" -> [Extension GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME] + "SPV_GOOGLE_user_type" -> [Extension GOOGLE_USER_TYPE_EXTENSION_NAME] + "SPV_GOOGLE_decorate_string" -> [Extension GOOGLE_DECORATE_STRING_EXTENSION_NAME] + "SPV_EXT_fragment_invocation_density" -> [Extension EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] + "SPV_KHR_physical_storage_buffer" -> + [Version $ makeVersion [1, 2], Extension KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + "SPV_EXT_physical_storage_buffer" -> [Extension EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + "SPV_NV_cooperative_matrix" -> [Extension NV_COOPERATIVE_MATRIX_EXTENSION_NAME] + "SPV_NV_shader_sm_builtins" -> [Extension NV_SHADER_SM_BUILTINS_EXTENSION_NAME] + "SPV_EXT_fragment_shader_interlock" -> [Extension EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + "SPV_EXT_demote_to_helper_invocation" -> [Extension EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] + "SPV_KHR_fragment_shading_rate" -> [Extension KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + "SPV_KHR_non_semantic_info" -> [Extension KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME] + "SPV_EXT_shader_image_int64" -> [Extension EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] + "SPV_KHR_terminate_invocation" -> [Extension KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME] + _ -> [] + +spirvCapabilityRequirements :: ByteString -> [SPIRVRequirement] +spirvCapabilityRequirements = \case + "Matrix" -> [Version $ makeVersion [1, 0]] + "Shader" -> [Version $ makeVersion [1, 0]] + "InputAttachment" -> [Version $ makeVersion [1, 0]] + "Sampled1D" -> [Version $ makeVersion [1, 0]] + "Image1D" -> [Version $ makeVersion [1, 0]] + "SampledBuffer" -> [Version $ makeVersion [1, 0]] + "ImageBuffer" -> [Version $ makeVersion [1, 0]] + "ImageQuery" -> [Version $ makeVersion [1, 0]] + "DerivativeControl" -> [Version $ makeVersion [1, 0]] + "Geometry" -> [Feature "VkPhysicalDeviceFeatures" "geometryShader" []] + "Tessellation" -> [Feature "VkPhysicalDeviceFeatures" "tessellationShader" []] + "Float64" -> [Feature "VkPhysicalDeviceFeatures" "shaderFloat64" []] + "Int64" -> [Feature "VkPhysicalDeviceFeatures" "shaderInt64" []] + "Int64Atomics" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderBufferInt64Atomics" + ["VK_VERSION_1_2", KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] + , Feature "VkPhysicalDeviceVulkan12Features" + "shaderSharedInt64Atomics" + ["VK_VERSION_1_2", KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] + ] + "AtomicFloat32AddEXT" -> + [ Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" + "shaderBufferFloat32AtomicAdd" + [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" + "shaderSharedFloat32AtomicAdd" + [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" + "shaderImageFloat32AtomicAdd" + [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" + "sparseImageFloat32AtomicAdd" + [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + ] + "AtomicFloat64AddEXT" -> + [ Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" + "shaderBufferFloat64AtomicAdd" + [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" + "shaderSharedFloat64AtomicAdd" + [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + ] + "Int64ImageEXT" -> + [ Feature "VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT" + "shaderImageInt64Atomics" + [EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] + ] + "Int16" -> [Feature "VkPhysicalDeviceFeatures" "shaderInt16" []] + "TessellationPointSize" -> [Feature "VkPhysicalDeviceFeatures" "shaderTessellationAndGeometryPointSize" []] + "GeometryPointSize" -> [Feature "VkPhysicalDeviceFeatures" "shaderTessellationAndGeometryPointSize" []] + "ImageGatherExtended" -> [Feature "VkPhysicalDeviceFeatures" "shaderImageGatherExtended" []] + "StorageImageMultisample" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageMultisample" []] + "UniformBufferArrayDynamicIndexing" -> + [Feature "VkPhysicalDeviceFeatures" "shaderUniformBufferArrayDynamicIndexing" []] + "SampledImageArrayDynamicIndexing" -> + [Feature "VkPhysicalDeviceFeatures" "shaderSampledImageArrayDynamicIndexing" []] + "StorageBufferArrayDynamicIndexing" -> + [Feature "VkPhysicalDeviceFeatures" "shaderStorageBufferArrayDynamicIndexing" []] + "StorageImageArrayDynamicIndexing" -> + [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageArrayDynamicIndexing" []] + "ClipDistance" -> [Feature "VkPhysicalDeviceFeatures" "shaderClipDistance" []] + "CullDistance" -> [Feature "VkPhysicalDeviceFeatures" "shaderCullDistance" []] + "ImageCubeArray" -> [Feature "VkPhysicalDeviceFeatures" "imageCubeArray" []] + "SampleRateShading" -> [Feature "VkPhysicalDeviceFeatures" "sampleRateShading" []] + "SparseResidency" -> [Feature "VkPhysicalDeviceFeatures" "shaderResourceResidency" []] + "MinLod" -> [Feature "VkPhysicalDeviceFeatures" "shaderResourceMinLod" []] + "SampledCubeArray" -> [Feature "VkPhysicalDeviceFeatures" "imageCubeArray" []] + "ImageMSArray" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageMultisample" []] + "StorageImageExtendedFormats" -> [Version $ makeVersion [1, 0]] + "InterpolationFunction" -> [Feature "VkPhysicalDeviceFeatures" "sampleRateShading" []] + "StorageImageReadWithoutFormat" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageReadWithoutFormat" []] + "StorageImageWriteWithoutFormat" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageWriteWithoutFormat" []] + "MultiViewport" -> [Feature "VkPhysicalDeviceFeatures" "multiViewport" []] + "DrawParameters" -> + [ Feature "VkPhysicalDeviceVulkan11Features" "shaderDrawParameters" ["VK_VERSION_1_1"] + , Extension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME + ] + "MultiView" -> + [Feature "VkPhysicalDeviceVulkan11Features" "multiview" ["VK_VERSION_1_1", KHR_MULTIVIEW_EXTENSION_NAME]] + "DeviceGroup" -> [Version $ makeVersion [1, 1], Extension KHR_DEVICE_GROUP_EXTENSION_NAME] + "VariablePointersStorageBuffer" -> + [ Feature "VkPhysicalDeviceVulkan11Features" + "variablePointersStorageBuffer" + ["VK_VERSION_1_1", KHR_VARIABLE_POINTERS_EXTENSION_NAME] + ] + "VariablePointers" -> + [ Feature "VkPhysicalDeviceVulkan11Features" + "variablePointers" + ["VK_VERSION_1_1", KHR_VARIABLE_POINTERS_EXTENSION_NAME] + ] + "ShaderClockKHR" -> [Extension KHR_SHADER_CLOCK_EXTENSION_NAME] + "StencilExportEXT" -> [Extension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] + "SubgroupBallotKHR" -> [Extension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] + "SubgroupVoteKHR" -> [Extension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] + "ImageReadWriteLodAMD" -> [Extension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] + "ImageGatherBiasLodAMD" -> [Extension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] + "FragmentMaskAMD" -> [Extension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] + "SampleMaskOverrideCoverageNV" -> [Extension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] + "GeometryShaderPassthroughNV" -> [Extension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] + "ShaderViewportIndex" -> [Feature "VkPhysicalDeviceVulkan12Features" "shaderOutputViewportIndex" ["VK_VERSION_1_2"]] + "ShaderLayer" -> [Feature "VkPhysicalDeviceVulkan12Features" "shaderOutputLayer" ["VK_VERSION_1_2"]] + "ShaderViewportIndexLayerEXT" -> [Extension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] + "ShaderViewportIndexLayerNV" -> [Extension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] + "ShaderViewportMaskNV" -> [Extension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] + "PerViewAttributesNV" -> [Extension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] + "StorageBuffer16BitAccess" -> + [ Feature "VkPhysicalDeviceVulkan11Features" + "storageBuffer16BitAccess" + ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] + ] + "UniformAndStorageBuffer16BitAccess" -> + [ Feature "VkPhysicalDeviceVulkan11Features" + "uniformAndStorageBuffer16BitAccess" + ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] + ] + "StoragePushConstant16" -> + [ Feature "VkPhysicalDeviceVulkan11Features" + "storagePushConstant16" + ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] + ] + "StorageInputOutput16" -> + [ Feature "VkPhysicalDeviceVulkan11Features" + "storageInputOutput16" + ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] + ] + "GroupNonUniform" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_BASIC_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformVote" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_VOTE_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformArithmetic" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_ARITHMETIC_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformBallot" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_BALLOT_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformShuffle" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_SHUFFLE_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformShuffleRelative" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformClustered" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_CLUSTERED_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformQuad" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_QUAD_BIT" + ["VK_VERSION_1_1"] + ] + "GroupNonUniformPartitionedNV" -> + [ Property "VkPhysicalDeviceVulkan11Properties" + "subgroupSupportedOperations" + "VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV" + [NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] + ] + "SampleMaskPostDepthCoverage" -> [Extension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] + "ShaderNonUniform" -> [Version $ makeVersion [1, 2], Extension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + "RuntimeDescriptorArray" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "runtimeDescriptorArray" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "InputAttachmentArrayDynamicIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderInputAttachmentArrayDynamicIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "UniformTexelBufferArrayDynamicIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderUniformTexelBufferArrayDynamicIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "StorageTexelBufferArrayDynamicIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderStorageTexelBufferArrayDynamicIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "UniformBufferArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderUniformBufferArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "SampledImageArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderSampledImageArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "StorageBufferArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderStorageBufferArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "StorageImageArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderStorageImageArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "InputAttachmentArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderInputAttachmentArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "UniformTexelBufferArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderUniformTexelBufferArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "StorageTexelBufferArrayNonUniformIndexing" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderStorageTexelBufferArrayNonUniformIndexing" + ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + ] + "Float16" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "shaderFloat16" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME] + , Extension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME + ] + "Int8" -> + [Feature "VkPhysicalDeviceVulkan12Features" "shaderInt8" ["VK_VERSION_1_2", KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME]] + "StorageBuffer8BitAccess" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "storageBuffer8BitAccess" + ["VK_VERSION_1_2", KHR_8BIT_STORAGE_EXTENSION_NAME] + ] + "UniformAndStorageBuffer8BitAccess" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "uniformAndStorageBuffer8BitAccess" + ["VK_VERSION_1_2", KHR_8BIT_STORAGE_EXTENSION_NAME] + ] + "StoragePushConstant8" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "storagePushConstant8" + ["VK_VERSION_1_2", KHR_8BIT_STORAGE_EXTENSION_NAME] + ] + "VulkanMemoryModel" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "vulkanMemoryModel" + ["VK_VERSION_1_2", KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + ] + "VulkanMemoryModelDeviceScope" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "vulkanMemoryModelDeviceScope" + ["VK_VERSION_1_2", KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + ] + "DenormPreserve" -> + [ Property "VkPhysicalDeviceVulkan12Properties" + "shaderDenormPreserveFloat16" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderDenormPreserveFloat32" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderDenormPreserveFloat64" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + ] + "DenormFlushToZero" -> + [ Property "VkPhysicalDeviceVulkan12Properties" + "shaderDenormFlushToZeroFloat16" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderDenormFlushToZeroFloat32" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderDenormFlushToZeroFloat64" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + ] + "SignedZeroInfNanPreserve" -> + [ Property "VkPhysicalDeviceVulkan12Properties" + "shaderSignedZeroInfNanPreserveFloat16" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderSignedZeroInfNanPreserveFloat32" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderSignedZeroInfNanPreserveFloat64" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + ] + "RoundingModeRTE" -> + [ Property "VkPhysicalDeviceVulkan12Properties" + "shaderRoundingModeRTEFloat16" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderRoundingModeRTEFloat32" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderRoundingModeRTEFloat64" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + ] + "RoundingModeRTZ" -> + [ Property "VkPhysicalDeviceVulkan12Properties" + "shaderRoundingModeRTZFloat16" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderRoundingModeRTZFloat32" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + , Property "VkPhysicalDeviceVulkan12Properties" + "shaderRoundingModeRTZFloat64" + "VK_TRUE" + ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + ] + "ComputeDerivativeGroupQuadsNV" -> + [ Feature "VkPhysicalDeviceComputeShaderDerivativesFeaturesNV" + "computeDerivativeGroupQuads" + [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] + ] + "ComputeDerivativeGroupLinearNV" -> + [ Feature "VkPhysicalDeviceComputeShaderDerivativesFeaturesNV" + "computeDerivativeGroupLinear" + [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] + ] + "FragmentBarycentricNV" -> + [ Feature "VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV" + "fragmentShaderBarycentric" + [NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] + ] + "ImageFootprintNV" -> + [ Feature "VkPhysicalDeviceShaderImageFootprintFeaturesNV" + "imageFootprint" + [NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] + ] + "ShadingRateNV" -> + [Feature "VkPhysicalDeviceShadingRateImageFeaturesNV" "shadingRateImage" [NV_SHADING_RATE_IMAGE_EXTENSION_NAME]] + "MeshShadingNV" -> [Extension NV_MESH_SHADER_EXTENSION_NAME] + "RayTracingProvisionalKHR" -> + [Feature "VkPhysicalDeviceRayTracingFeaturesKHR" "rayTracing" [KHR_RAY_TRACING_EXTENSION_NAME]] + "RayQueryProvisionalKHR" -> + [Feature "VkPhysicalDeviceRayTracingFeaturesKHR" "rayQuery" [KHR_RAY_TRACING_EXTENSION_NAME]] + "RayTraversalPrimitiveCullingProvisionalKHR" -> + [Feature "VkPhysicalDeviceRayTracingFeaturesKHR" "rayTracingPrimitiveCulling" [KHR_RAY_TRACING_EXTENSION_NAME]] + "RayTracingNV" -> [Extension NV_RAY_TRACING_EXTENSION_NAME] + "TransformFeedback" -> + [Feature "VkPhysicalDeviceTransformFeedbackFeaturesEXT" "transformFeedback" [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME]] + "GeometryStreams" -> + [Feature "VkPhysicalDeviceTransformFeedbackFeaturesEXT" "geometryStreams" [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME]] + "FragmentDensityEXT" -> + [ Feature "VkPhysicalDeviceFragmentDensityMapFeaturesEXT" + "fragmentDensityMap" + [EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] + ] + "PhysicalStorageBufferAddresses" -> + [ Feature "VkPhysicalDeviceVulkan12Features" + "bufferDeviceAddress" + ["VK_VERSION_1_2", KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + , Feature "VkPhysicalDeviceBufferDeviceAddressFeaturesEXT" + "bufferDeviceAddress" + [EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + ] + "CooperativeMatrixNV" -> + [Feature "VkPhysicalDeviceCooperativeMatrixFeaturesNV" "cooperativeMatrix" [NV_COOPERATIVE_MATRIX_EXTENSION_NAME]] + "IntegerFunctions2INTEL" -> + [ Feature "VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL" + "shaderIntegerFunctions2" + [INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME] + ] + "ShaderSMBuiltinsNV" -> + [Feature "VkPhysicalDeviceShaderSMBuiltinsFeaturesNV" "shaderSMBuiltins" [NV_SHADER_SM_BUILTINS_EXTENSION_NAME]] + "FragmentShaderSampleInterlockEXT" -> + [ Feature "VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT" + "fragmentShaderSampleInterlock" + [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + ] + "FragmentShaderPixelInterlockEXT" -> + [ Feature "VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT" + "fragmentShaderPixelInterlock" + [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + ] + "FragmentShaderShadingRateInterlockEXT" -> + [ Feature "VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT" + "fragmentShaderShadingRateInterlock" + [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + , Feature "VkPhysicalDeviceShadingRateImageFeaturesNV" "shadingRateImage" [NV_SHADING_RATE_IMAGE_EXTENSION_NAME] + ] + "DemoteToHelperInvocationEXT" -> + [ Feature "VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT" + "shaderDemoteToHelperInvocation" + [EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] + ] + "FragmentShadingRateKHR" -> + [ Feature "VkPhysicalDeviceFragmentShadingRateFeaturesKHR" + "pipelineFragmentShadingRate" + [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + , Feature "VkPhysicalDeviceFragmentShadingRateFeaturesKHR" + "primitiveFragmentShadingRate" + [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + , Feature "VkPhysicalDeviceFragmentShadingRateFeaturesKHR" + "attachmentFragmentShadingRate" + [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + ] + _ -> [] + diff --git a/vulkan.cabal b/vulkan.cabal index 1a5e2cb7a..a33d3e156 100644 --- a/vulkan.cabal +++ b/vulkan.cabal @@ -471,6 +471,7 @@ library Vulkan.Extensions.VK_QCOM_render_pass_transform Vulkan.Extensions.VK_QCOM_rotated_copy_commands Vulkan.NamedType + Vulkan.SPIRVInfo Vulkan.Version Vulkan.Zero Vulkan.Internal.Utils From 1660b6b9d8aff829a0fe433f208f75c2105c5def Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 17:08:00 +0800 Subject: [PATCH 05/70] bump changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 55e4dd8ed..a12a963a6 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,8 @@ ## WIP +- Expose SPIR-V Extensions and Capabilities in `Vulkan.SPIRVInfo` + ## [3.7] - 2020-11-24 - Bump API version to v1.2.162 - This is a breaking change to anyone using VK_KHR_ray_tracing (which no From fea5f0bfe00db26393a15f0a09c4069b83ed87ba Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 15:26:56 +0800 Subject: [PATCH 06/70] Use new Requirements type for SPIRV requirements Also move SPIRVInfo to SPIRVRequirements --- changelog.md | 2 +- generate-new/vk/VK/SPIRVElements.hs | 190 ++++++++++++++++++++++------ 2 files changed, 152 insertions(+), 40 deletions(-) diff --git a/changelog.md b/changelog.md index a12a963a6..544280f54 100644 --- a/changelog.md +++ b/changelog.md @@ -2,7 +2,7 @@ ## WIP -- Expose SPIR-V Extensions and Capabilities in `Vulkan.SPIRVInfo` +- Expose SPIR-V Extensions and Capabilities in `Vulkan.SPIRVRequirements` ## [3.7] - 2020-11-24 - Bump API version to v1.2.162 diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs index 084ffdc82..38aaf9a4f 100644 --- a/generate-new/vk/VK/SPIRVElements.hs +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -4,6 +4,9 @@ module VK.SPIRVElements ( renderSPIRVElements ) where +import CType ( CType(TypeName) ) +import Data.Bits +import Data.Foldable import qualified Data.Text as T import Data.Text.Prettyprint.Doc import Data.Vector ( Vector ) @@ -12,40 +15,54 @@ import Data.Version ( Version(versionBranch) , makeVersion ) import Error +import Haskell ( HName(..) + , allTypeNames + , renderType + , (~>) + ) +import Language.Haskell.TH ( Type(ConT) + , mkName + ) import Polysemy.Input import Relude import Render.Element +import Render.SpecInfo ( HasSpecInfo ) +import Render.Type ( cToHsType ) +import Render.Type.Preserve ( Preserve(DoNotPreserve) ) import Spec.Types import Text.InterpolatedString.Perl6.Unindented import VkModulePrefix renderSPIRVElements - :: (HasErr r, HasRenderParams r) + :: (HasErr r, HasRenderParams r, HasSpecInfo r) => Vector SPIRVExtension -> Vector SPIRVCapability -> Sem r RenderElement -renderSPIRVElements exts caps = do - genRe "SPIR-V stuff" $ do - tellExplicitModule (vulkanModule ["SPIRVInfo"]) - tellCanFormat - bespokeStuff - renderExts exts - renderCaps caps +renderSPIRVElements exts caps = genRe "SPIR-V stuff" $ do + tellExplicitModule (vulkanModule ["SPIRVRequirements"]) + tellCanFormat + bespokeStuff + renderExts exts + renderCaps caps renderExts - :: (HasRenderElem r, HasRenderParams r) => Vector SPIRVExtension -> Sem r () + :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) + => Vector SPIRVExtension + -> Sem r () renderExts = renderSPIRVThing "spirvExtensionRequirements" spirvExtensionName spirvExtensionReqs renderCaps - :: (HasRenderElem r, HasRenderParams r) => Vector SPIRVCapability -> Sem r () + :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) + => Vector SPIRVCapability + -> Sem r () renderCaps = renderSPIRVThing "spirvCapabilityRequirements" spirvCapabilityName spirvCapabilityReqs renderSPIRVThing - :: (HasRenderElem r, HasRenderParams r) + :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) => Text -> (a -> Text) -> (a -> Vector SPIRVRequirement) @@ -57,38 +74,111 @@ renderSPIRVThing funName name reqs xs = do pure $ viaShow (name x) <+> "->" <+> list reqs' cases <- (<> ["_ -> []"]) <$> traverse case' (V.toList xs) tellImport ''ByteString + tellImport (mkName "Vulkan.Requirements.Requirement") + tellExport (ETerm (TermName funName)) tellDoc $ vsep - [ (pretty funName <+> ":: ByteString -> [SPIRVRequirement]") - , (pretty funName <+> "= \\case" <> line <> indent 2 (vsep cases)) + [ pretty funName <+> ":: ByteString -> [Requirement]" + , pretty funName <+> "= \\case" <> line <> indent 2 (vsep cases) ] renderReq - :: (HasRenderParams r, HasRenderElem r) => SPIRVRequirement -> Sem r (Doc ()) + :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) + => SPIRVRequirement + -> Sem r (Doc ()) renderReq = \case - SPIRVReqVersion v -> do - tellImport 'makeVersion - pure $ "Version $ makeVersion" <+> viaShow (versionBranch v) + SPIRVReqVersion v -> versionReq v SPIRVReqExtension p -> do - p' <- extensionNamePattern p - pure $ "Extension" <+> p' + extensionNamePattern p >>= \case + Left v -> versionReq v + Right p' -> do + tellImportWithAll (mkName "Vulkan.Requirements.Requirement") + pure $ "RequireExtension" <+> p' SPIRVReqFeature s f rs -> do - rs' <- traverse extensionNamePattern (V.toList rs) + RenderParams {..} <- input + tellImportWithAll (mkName "Vulkan.Requirements.Requirement") tellLanguageExtension (LanguageExtension "OverloadedLists") - pure $ "Feature" <+> viaShow s <+> viaShow f <+> list rs' + sTy <- cToHsType DoNotPreserve (TypeName s) + -- TODO: this is pretty lazy, import the accessors properly + traverse_ tellImportWithAll (allTypeNames sTy) + checkTDoc <- renderType (sTy ~> ConT ''Bool) + sTyDoc <- renderType sTy + otherSetters <- minVersionAndExtensionsSetters rs + let featureMemberName = mkMemberName f + let xs = + [ "featureName =" <+> viaShow f + , "checkFeature =" <+> pretty featureMemberName <+> "::" <+> checkTDoc + , "enableFeature =" + <+> "\\f ->" + <+> "f" + <> braces (pretty featureMemberName <+> "= True") + <+> "::" + <+> sTyDoc + ] + <> otherSetters + pure $ "RequireFeature" <> encloseSep "{" "}" ", " xs SPIRVReqProperty p m v rs -> do - rs' <- traverse extensionNamePattern (V.toList rs) + RenderParams {..} <- input + tellImportWithAll (mkName "Vulkan.Requirements.Requirement") tellLanguageExtension (LanguageExtension "OverloadedLists") - pure $ "Property" <+> viaShow p <+> viaShow m <+> viaShow v <+> list rs' + -- TODO: this is pretty lazy, import the accessors properly + sTy <- cToHsType DoNotPreserve (TypeName p) + traverse_ tellImportWithAll (allTypeNames sTy) + sTyDoc <- renderType sTy + let propertyMemberName = mkMemberName m + propertyValueName = mkPatternName v + otherSetters <- minVersionAndExtensionsSetters rs + -- TODO, do this properly + checker <- if + | v == "VK_TRUE" + -> pure $ "\\p ->" <+> pretty propertyMemberName <+> parens + ("p ::" <+> sTyDoc) + | "_BIT" `T.isInfixOf` unCName v + -> do + tellImport propertyValueName + pure + $ "\\p ->" + <+> pretty propertyValueName + <+> ".&&." + <+> pretty propertyMemberName + <+> parens ("p ::" <+> sTyDoc) + | otherwise + -> do + tellImport propertyValueName + pure + $ "\\p ->" + <+> pretty propertyValueName + <+> "==" + <+> pretty propertyMemberName + <+> parens ("p ::" <+> sTyDoc) + let xs = + ["propertyName =" <+> viaShow p, "checkProperty =" <+> checker] + <> otherSetters + pure $ "RequireProperty" <> encloseSep "{" "}" ", " xs + +minVersionAndExtensionsSetters + :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) + => Vector Text + -> Sem r [Doc ()] +minVersionAndExtensionsSetters rs = do + (minVersions, extensionNames) <- + partitionEithers . V.toList <$> traverse extensionNamePattern rs + minVersionDoc <- case minVersions of + [] -> pure "Nothing" + vs -> ("Just $" <+>) <$> versionDoc (maximum vs) + pure + [ "requireMinVersion =" <+> minVersionDoc + , "requireExtensions =" <+> viaShow extensionNames + ] extensionNamePattern :: (HasRenderElem r, HasRenderParams r) => Text - -> Sem r (Doc ()) + -> Sem r (Either Version (Doc ())) extensionNamePattern p = do RenderParams {..} <- input - if "VK_VERSION_" `T.isPrefixOf` p - then pure $ viaShow p - else do + case parseVersion p of + Just v -> pure . Left $ v + Nothing -> do let nameName = case p of -- TODO: Handle these properly "VK_INTEL_shader_integer_functions2" -> @@ -96,20 +186,42 @@ extensionNamePattern p = do _ -> CName $ T.toUpper p <> "_EXTENSION_NAME" let p' = mkPatternName nameName tellImport p' - pure $ pretty p' + pure . Right $ pretty p' + +versionReq + :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) +versionReq v = do + tellImportWithAll (mkName "Vulkan.Requirements.Requirement") + vDoc <- versionDoc v + pure $ "RequireVersion $" <+> vDoc + +versionDoc + :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) +versionDoc v = do + tellImport (ConName "MAKE_VERSION") + (ma, mi, pa) <- case versionBranch v of + [ma] -> pure (ma, 0, 0) + [ma, mi] -> pure (ma, mi, 0) + [ma, mi, pa] -> pure (ma, mi, pa) + [] -> throw "Version branch has no components" + _ -> throw "Version branch has more than three components" + pure $ "MAKE_VERSION" <+> hsep (viaShow <$> [ma, mi, pa]) + +parseVersion :: Text -> Maybe Version +parseVersion t = do + let p = "VK_VERSION_" + v <- if p `T.isPrefixOf` t then pure $ T.drop (T.length p) t else empty + let cs = T.split (== '_') v + is <- traverse (readMaybe . T.unpack) cs + pure $ makeVersion is bespokeStuff :: (HasRenderParams r, HasRenderElem r) => Sem r () bespokeStuff = do - tellImport ''ByteString - tellImport ''Vector - tellImport ''Version + tellImport ''Bits + tellImport '(.&.) + tellImport 'zeroBits tellDoc [qqi| - data SPIRVRequirement - = Version Version - | Extension ByteString - | Feature ByteString ByteString (Vector ByteString) - -- ^ Struct, feature, requires - | Property ByteString ByteString ByteString (Vector ByteString) - -- ^ Property, member, value, requires - deriving(Show) + -- | Check if the intersection of bits is non-zero + (.&&.) :: Bits a => a -> a -> Bool + x .&&. y = (x .&. y) /= zeroBits |] From f41fdb8bd0d2ff144669c5d46b9c8a0147c13a22 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 15:27:25 +0800 Subject: [PATCH 07/70] Add Requirements structure from https://github.com/expipiplus1/vulkan/pull/216 --- nix/haskell-packages.nix | 4 +- src-manual/Vulkan/Requirements.hs | 243 ++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 src-manual/Vulkan/Requirements.hs diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 46526e7b5..93406d56d 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -11,8 +11,8 @@ let "package.yaml" "changelog.md" "readme.md" - ]) || pkgs.lib.hasInfix "/src" path || pkgs.lib.hasInfix "/vk" path - || pkgs.lib.hasInfix "/vma" path); + ]) || pkgs.lib.hasInfix "/src" path || pkgs.lib.hasInfix "/src-manual" path + || pkgs.lib.hasInfix "/vk" path || pkgs.lib.hasInfix "/vma" path); mod = if buildProfiling then drv: doHaddock (enableLibraryProfiling drv) diff --git a/src-manual/Vulkan/Requirements.hs b/src-manual/Vulkan/Requirements.hs new file mode 100644 index 000000000..07ada48f9 --- /dev/null +++ b/src-manual/Vulkan/Requirements.hs @@ -0,0 +1,243 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE Strict #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} + +module Vulkan.Requirements where + +-- base +import Control.Arrow + ( Arrow(first,second,(***)) ) +import Data.Foldable + ( for_, foldr' ) +import Data.Kind + ( Type ) +import Data.Type.Equality + ( (:~:)(Refl) ) +import Data.Typeable + ( Typeable, eqT ) +import Data.Word + ( Word32 ) +import GHC.Exts + ( Proxy#, proxy# ) + +-- bytestring +import Data.ByteString + ( ByteString ) + +-- vulkan +import Vulkan.Core10.DeviceInitialization + ( PhysicalDeviceFeatures, PhysicalDeviceProperties ) +import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 + ( PhysicalDeviceFeatures2(..) ) +import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 + ( PhysicalDeviceProperties2(..) ) +import Vulkan.CStruct + ( FromCStruct, ToCStruct ) +import Vulkan.CStruct.Extends + ( Chain, PeekChain, PokeChain, Extends, Extendss ) +import Vulkan.Version + ( pattern MAKE_VERSION ) +import Vulkan.Zero + ( Zero(zero) ) + +---------------------------------------------------------------------------- + +-- | A Vulkan requirement. +data Requirement where + -- | Require a minimum Vulkan API version. + RequireVersion + :: { version :: Word32 } + -> Requirement + -- | Require a Vulkan extension. + RequireExtension + :: { extension :: ByteString } + -> Requirement + -- | Require a Vulkan device feature. + RequireFeature + :: forall struct + . KnownFeature struct + => { featureName :: ByteString + , checkFeature :: struct -> Bool + , enableFeature :: struct -> struct + , requireMinVersion :: Maybe Word32 + , requireExtensions :: [ByteString] + } + -> Requirement + -- | Require a Vulkan device property. + RequireProperty + :: forall struct + . KnownProperty struct + => { propertyName :: ByteString + , checkProperty :: struct -> Bool + , requireMinVersion :: Maybe Word32 + , requireExtensions :: [ByteString] + } + -> Requirement + +data SFeature feat where + BasicFeature + :: SFeature PhysicalDeviceFeatures + ExtendedFeature + :: ( Typeable feat, Extends PhysicalDeviceFeatures2 feat, Zero feat, FromCStruct feat, ToCStruct feat ) + => SFeature feat +class KnownFeature feat where + sFeature :: SFeature feat +instance KnownFeature PhysicalDeviceFeatures where + sFeature = BasicFeature +instance {-# OVERLAPPABLE #-} + ( Typeable feat, Extends PhysicalDeviceFeatures2 feat, Zero feat, FromCStruct feat, ToCStruct feat ) + => KnownFeature feat where + sFeature = ExtendedFeature + +data SProperty prop where + BasicProperty + :: SProperty PhysicalDeviceProperties + ExtendedProperty + :: ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) + => SProperty prop +class KnownProperty prop where + sProperty :: SProperty prop +instance KnownProperty PhysicalDeviceProperties where + sProperty = BasicProperty +instance {-# OVERLAPPABLE #-} + ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) + => KnownProperty prop where + sProperty = ExtendedProperty + + +-- | Enough information to focus on any structure within a Vulkan structure chain. +class (PeekChain xs, PokeChain xs) => KnownChain (xs :: [Type]) where + -- | If the given structure can be found within a chain, return a lens to it. + -- Otherwise, return 'Nothing'. + has :: forall a. Typeable a => Proxy# a -> Maybe (Chain xs -> a, (a -> a) -> (Chain xs -> Chain xs)) +instance KnownChain '[] where + has _ = Nothing +instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain (x ': xs) where + has (px :: Proxy# a) + | Just Refl <- eqT @a @x + = Just (fst,first) + | otherwise + = ((. snd) *** (second .)) <$> has px + + +-- | A collection of Vulkan requirements. +-- +-- Parameterised over the structure chains used by 'PhysicalDeviceFeatures2' and 'PhysicalDeviceProperties2'. +data Requirements where + Requirements + :: forall feats props + . ( KnownChain feats, Extendss PhysicalDeviceFeatures2 feats + , KnownChain props, Extendss PhysicalDeviceProperties2 props + ) + => { version :: Word32 -- ^ Minimum Vulkan API version required. + , extensions :: [ ByteString ] -- ^ Required Vulkan device extension names. + , missingFeatures :: PhysicalDeviceFeatures2 feats -> [ByteString] -- ^ Returns all the required features that were not enabled in 'PhysicalDeviceFeatures2'. + , neededFeatures :: PhysicalDeviceFeatures2 feats -- ^ All required features, to be used in 'DeviceCreateInfo'. + , missingProperties :: PhysicalDeviceProperties2 props -> [ByteString] -- ^ Returns all the required properties that were not satisfied in 'PhysicalDeviceProperties2' + } + -> Requirements + +-- | Collect up requirements. +requirements :: Foldable f => f Requirement -> Requirements +requirements = foldr' addRequirement noRequire + where + noRequire :: Requirements + noRequire = Requirements @'[] @'[] (MAKE_VERSION 1 0 0) [] (const []) zero (const []) + addRequirement :: Requirement -> Requirements -> Requirements + addRequirement (RequireVersion {version}) = requireVersion version + addRequirement (RequireExtension {extension}) = requireExtension extension + addRequirement (RequireFeature {..}) = do + for_ requireMinVersion requireVersion + for_ requireExtensions requireExtension + requireFeature featureName checkFeature enableFeature + addRequirement (RequireProperty {..}) = do + for_ requireMinVersion requireVersion + for_ requireExtensions requireExtension + requireProperty propertyName checkProperty + + +requireVersion :: Word32 -> Requirements -> Requirements +requireVersion ver1 req@(Requirements{version = ver2}) = req {version = max ver1 ver2} + +requireExtension :: ByteString -> Requirements -> Requirements +requireExtension ext req@(Requirements{extensions = exts}) = req {extensions = ext:exts} + +requireFeature :: forall struct + . ( KnownFeature struct ) + => ByteString -> (struct -> Bool) -> (struct -> struct) -> Requirements -> Requirements +requireFeature featName checkFeat enableFeat + ( Requirements ver exts + (missingFeats :: PhysicalDeviceFeatures2 feats -> [ByteString]) + enabledFeats@(PhysicalDeviceFeatures2{next=nextEnabledFeats,features=prevEnabledFeats}) + missingProps + ) + = case sFeature @struct of + BasicFeature -> + let + missingFeats' :: PhysicalDeviceFeatures2 feats -> [ByteString] + missingFeats' feats2@(PhysicalDeviceFeatures2{features}) = + (if checkFeat features then id else (featName:)) + (missingFeats feats2) + enabledFeats' :: PhysicalDeviceFeatures2 feats + enabledFeats' = enabledFeats { features = enableFeat prevEnabledFeats } + in Requirements ver exts missingFeats' enabledFeats' missingProps + ExtendedFeature + | Just (getFeatureStruct, modifyFeatureStruct) <- has @feats @struct proxy# + , let + missingFeats' :: PhysicalDeviceFeatures2 feats -> [ByteString] + missingFeats' feats2@(PhysicalDeviceFeatures2{next}) = + (if checkFeat (getFeatureStruct next) then id else (featName:)) + (missingFeats feats2) + enabledFeats' :: PhysicalDeviceFeatures2 feats + enabledFeats' = enabledFeats { next = modifyFeatureStruct enableFeat nextEnabledFeats } + -> Requirements ver exts missingFeats' enabledFeats' missingProps + | let + missingFeats' :: PhysicalDeviceFeatures2 (struct ': feats) -> [ByteString] + missingFeats' feats2@(PhysicalDeviceFeatures2{next=(struct,feats)}) = + (if checkFeat struct then id else (featName:)) + (missingFeats (feats2{next=feats})) + enabledFeats' :: PhysicalDeviceFeatures2 (struct ': feats) + enabledFeats' = enabledFeats { next = (enableFeat zero, nextEnabledFeats) } + -> Requirements ver exts missingFeats' enabledFeats' missingProps + +requireProperty :: forall struct + . ( KnownProperty struct ) + => ByteString -> (struct -> Bool) -> Requirements -> Requirements +requireProperty propName checkProp + ( Requirements ver exts missingFeats enabledFeats + (missingProps :: PhysicalDeviceProperties2 props -> [ByteString]) + ) + = case sProperty @struct of + BasicProperty -> + let + missingProps' :: PhysicalDeviceProperties2 props -> [ByteString] + missingProps' props2@(PhysicalDeviceProperties2{properties}) = + (if checkProp properties then id else (propName:)) + (missingProps props2) + in Requirements ver exts missingFeats enabledFeats missingProps' + + ExtendedProperty + | Just (getPropertyStruct,_) <- has @props @struct proxy# + , let + missingProps' :: PhysicalDeviceProperties2 props -> [ByteString] + missingProps' props2@(PhysicalDeviceProperties2{next}) = + (if checkProp (getPropertyStruct next) then id else (propName:)) + (missingProps props2) + -> Requirements ver exts missingFeats enabledFeats missingProps' + | let + missingProps' :: PhysicalDeviceProperties2 (struct ': props) -> [ByteString] + missingProps' props2@(PhysicalDeviceProperties2{next=(struct,props)}) = + (if checkProp struct then id else (propName:)) + (missingProps (props2{next=props})) + -> Requirements ver exts missingFeats enabledFeats missingProps' From cc6e843277453387d105c7632329d46aca69c0db Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 15:30:13 +0800 Subject: [PATCH 08/70] regenerate --- src/Vulkan.hs | 4 +- src/Vulkan/SPIRVInfo.hs | 563 ---------------- src/Vulkan/SPIRVRequirements.hs | 1125 +++++++++++++++++++++++++++++++ vulkan.cabal | 3 +- 4 files changed, 1129 insertions(+), 566 deletions(-) delete mode 100644 src/Vulkan/SPIRVInfo.hs create mode 100644 src/Vulkan/SPIRVRequirements.hs diff --git a/src/Vulkan.hs b/src/Vulkan.hs index b7a700e9e..6bfb73143 100644 --- a/src/Vulkan.hs +++ b/src/Vulkan.hs @@ -6,7 +6,7 @@ module Vulkan ( module Vulkan.CStruct , module Vulkan.Core12 , module Vulkan.Extensions , module Vulkan.NamedType - , module Vulkan.SPIRVInfo + , module Vulkan.SPIRVRequirements , module Vulkan.Version , module Vulkan.Zero ) where @@ -16,7 +16,7 @@ import Vulkan.Core11 import Vulkan.Core12 import Vulkan.Extensions import Vulkan.NamedType -import Vulkan.SPIRVInfo +import Vulkan.SPIRVRequirements import Vulkan.Version import Vulkan.Zero diff --git a/src/Vulkan/SPIRVInfo.hs b/src/Vulkan/SPIRVInfo.hs deleted file mode 100644 index fe02c2be8..000000000 --- a/src/Vulkan/SPIRVInfo.hs +++ /dev/null @@ -1,563 +0,0 @@ -{-# language CPP #-} -{-# language OverloadedLists #-} -module Vulkan.SPIRVInfo () where - -import Data.Version (makeVersion) -import Data.Version (Version) -import Data.ByteString (ByteString) -import Data.Vector (Vector) -import Vulkan.Extensions.VK_AMD_gcn_shader (pattern AMD_GCN_SHADER_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_gpu_shader_half_float (pattern AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_gpu_shader_int16 (pattern AMD_GPU_SHADER_INT16_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_shader_ballot (pattern AMD_SHADER_BALLOT_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_shader_explicit_vertex_parameter (pattern AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_shader_fragment_mask (pattern AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_shader_image_load_store_lod (pattern AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_shader_trinary_minmax (pattern AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME) -import Vulkan.Extensions.VK_AMD_texture_gather_bias_lod (pattern AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_buffer_device_address (pattern EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_descriptor_indexing (pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_fragment_density_map (pattern EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (pattern EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_post_depth_coverage (pattern EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_atomic_float (pattern EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (pattern EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (pattern EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_stencil_export (pattern EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_subgroup_ballot (pattern EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_subgroup_vote (pattern EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_shader_viewport_index_layer (pattern EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME) -import Vulkan.Extensions.VK_EXT_transform_feedback (pattern EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME) -import Vulkan.Extensions.VK_GOOGLE_decorate_string (pattern GOOGLE_DECORATE_STRING_EXTENSION_NAME) -import Vulkan.Extensions.VK_GOOGLE_hlsl_functionality1 (pattern GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME) -import Vulkan.Extensions.VK_GOOGLE_user_type (pattern GOOGLE_USER_TYPE_EXTENSION_NAME) -import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (pattern INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_device_group (pattern KHR_DEVICE_GROUP_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_fragment_shading_rate (pattern KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_draw_parameters (pattern KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_float16_int8 (pattern KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_float_controls (pattern KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_vulkan_memory_model (pattern KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME) -import Vulkan.Extensions.VK_NVX_multiview_per_view_attributes (pattern NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_compute_shader_derivatives (pattern NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_cooperative_matrix (pattern NV_COOPERATIVE_MATRIX_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (pattern NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_geometry_shader_passthrough (pattern NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_mesh_shader (pattern NV_MESH_SHADER_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_ray_tracing (pattern NV_RAY_TRACING_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_sample_mask_override_coverage (pattern NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_shader_image_footprint (pattern NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_shader_sm_builtins (pattern NV_SHADER_SM_BUILTINS_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_shader_subgroup_partitioned (pattern NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_shading_rate_image (pattern NV_SHADING_RATE_IMAGE_EXTENSION_NAME) -import Vulkan.Extensions.VK_NV_viewport_array2 (pattern NV_VIEWPORT_ARRAY2_EXTENSION_NAME) -data SPIRVRequirement - = Version Version - | Extension ByteString - | Feature ByteString ByteString (Vector ByteString) - -- ^ Struct, feature, requires - | Property ByteString ByteString ByteString (Vector ByteString) - -- ^ Property, member, value, requires - deriving(Show) - -spirvExtensionRequirements :: ByteString -> [SPIRVRequirement] -spirvExtensionRequirements = \case - "SPV_KHR_variable_pointers" -> [Version $ makeVersion [1, 1], Extension KHR_VARIABLE_POINTERS_EXTENSION_NAME] - "SPV_AMD_shader_explicit_vertex_parameter" -> [Extension AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME] - "SPV_AMD_gcn_shader" -> [Extension AMD_GCN_SHADER_EXTENSION_NAME] - "SPV_AMD_gpu_shader_half_float" -> [Extension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME] - "SPV_AMD_gpu_shader_int16" -> [Extension AMD_GPU_SHADER_INT16_EXTENSION_NAME] - "SPV_AMD_shader_ballot" -> [Extension AMD_SHADER_BALLOT_EXTENSION_NAME] - "SPV_AMD_shader_fragment_mask" -> [Extension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] - "SPV_AMD_shader_image_load_store_lod" -> [Extension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] - "SPV_AMD_shader_trinary_minmax" -> [Extension AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME] - "SPV_AMD_texture_gather_bias_lod" -> [Extension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] - "SPV_KHR_shader_draw_parameters" -> - [Version $ makeVersion [1, 1], Extension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME] - "SPV_KHR_8bit_storage" -> [Version $ makeVersion [1, 2], Extension KHR_8BIT_STORAGE_EXTENSION_NAME] - "SPV_KHR_16bit_storage" -> [Version $ makeVersion [1, 1], Extension KHR_16BIT_STORAGE_EXTENSION_NAME] - "SPV_KHR_shader_clock" -> [Extension KHR_SHADER_CLOCK_EXTENSION_NAME] - "SPV_KHR_float_controls" -> [Version $ makeVersion [1, 2], Extension KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - "SPV_KHR_storage_buffer_storage_class" -> - [Version $ makeVersion [1, 1], Extension KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] - "SPV_KHR_post_depth_coverage" -> [Extension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] - "SPV_EXT_shader_stencil_export" -> [Extension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] - "SPV_KHR_shader_ballot" -> [Extension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] - "SPV_KHR_subgroup_vote" -> [Extension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] - "SPV_NV_sample_mask_override_coverage" -> [Extension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] - "SPV_NV_geometry_shader_passthrough" -> [Extension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] - "SPV_NV_mesh_shader" -> [Extension NV_MESH_SHADER_EXTENSION_NAME] - "SPV_NV_viewport_array2" -> [Extension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] - "SPV_NV_shader_subgroup_partitioned" -> [Extension NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] - "SPV_EXT_shader_viewport_index_layer" -> - [Version $ makeVersion [1, 2], Extension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] - "SPV_NVX_multiview_per_view_attributes" -> [Extension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] - "SPV_EXT_descriptor_indexing" -> [Version $ makeVersion [1, 2], Extension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - "SPV_KHR_vulkan_memory_model" -> [Version $ makeVersion [1, 2], Extension KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] - "SPV_NV_compute_shader_derivatives" -> [Extension NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] - "SPV_NV_fragment_shader_barycentric" -> [Extension NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] - "SPV_NV_shader_image_footprint" -> [Extension NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] - "SPV_NV_shading_rate" -> [Extension NV_SHADING_RATE_IMAGE_EXTENSION_NAME] - "SPV_NV_ray_tracing" -> [Extension NV_RAY_TRACING_EXTENSION_NAME] - "SPV_KHR_ray_tracing" -> [Extension KHR_RAY_TRACING_EXTENSION_NAME] - "SPV_KHR_ray_query" -> [Extension KHR_RAY_TRACING_EXTENSION_NAME] - "SPV_GOOGLE_hlsl_functionality1" -> [Extension GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME] - "SPV_GOOGLE_user_type" -> [Extension GOOGLE_USER_TYPE_EXTENSION_NAME] - "SPV_GOOGLE_decorate_string" -> [Extension GOOGLE_DECORATE_STRING_EXTENSION_NAME] - "SPV_EXT_fragment_invocation_density" -> [Extension EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] - "SPV_KHR_physical_storage_buffer" -> - [Version $ makeVersion [1, 2], Extension KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - "SPV_EXT_physical_storage_buffer" -> [Extension EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - "SPV_NV_cooperative_matrix" -> [Extension NV_COOPERATIVE_MATRIX_EXTENSION_NAME] - "SPV_NV_shader_sm_builtins" -> [Extension NV_SHADER_SM_BUILTINS_EXTENSION_NAME] - "SPV_EXT_fragment_shader_interlock" -> [Extension EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - "SPV_EXT_demote_to_helper_invocation" -> [Extension EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] - "SPV_KHR_fragment_shading_rate" -> [Extension KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - "SPV_KHR_non_semantic_info" -> [Extension KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME] - "SPV_EXT_shader_image_int64" -> [Extension EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] - "SPV_KHR_terminate_invocation" -> [Extension KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME] - _ -> [] - -spirvCapabilityRequirements :: ByteString -> [SPIRVRequirement] -spirvCapabilityRequirements = \case - "Matrix" -> [Version $ makeVersion [1, 0]] - "Shader" -> [Version $ makeVersion [1, 0]] - "InputAttachment" -> [Version $ makeVersion [1, 0]] - "Sampled1D" -> [Version $ makeVersion [1, 0]] - "Image1D" -> [Version $ makeVersion [1, 0]] - "SampledBuffer" -> [Version $ makeVersion [1, 0]] - "ImageBuffer" -> [Version $ makeVersion [1, 0]] - "ImageQuery" -> [Version $ makeVersion [1, 0]] - "DerivativeControl" -> [Version $ makeVersion [1, 0]] - "Geometry" -> [Feature "VkPhysicalDeviceFeatures" "geometryShader" []] - "Tessellation" -> [Feature "VkPhysicalDeviceFeatures" "tessellationShader" []] - "Float64" -> [Feature "VkPhysicalDeviceFeatures" "shaderFloat64" []] - "Int64" -> [Feature "VkPhysicalDeviceFeatures" "shaderInt64" []] - "Int64Atomics" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderBufferInt64Atomics" - ["VK_VERSION_1_2", KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] - , Feature "VkPhysicalDeviceVulkan12Features" - "shaderSharedInt64Atomics" - ["VK_VERSION_1_2", KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] - ] - "AtomicFloat32AddEXT" -> - [ Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" - "shaderBufferFloat32AtomicAdd" - [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" - "shaderSharedFloat32AtomicAdd" - [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" - "shaderImageFloat32AtomicAdd" - [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" - "sparseImageFloat32AtomicAdd" - [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - ] - "AtomicFloat64AddEXT" -> - [ Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" - "shaderBufferFloat64AtomicAdd" - [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - , Feature "VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" - "shaderSharedFloat64AtomicAdd" - [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - ] - "Int64ImageEXT" -> - [ Feature "VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT" - "shaderImageInt64Atomics" - [EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] - ] - "Int16" -> [Feature "VkPhysicalDeviceFeatures" "shaderInt16" []] - "TessellationPointSize" -> [Feature "VkPhysicalDeviceFeatures" "shaderTessellationAndGeometryPointSize" []] - "GeometryPointSize" -> [Feature "VkPhysicalDeviceFeatures" "shaderTessellationAndGeometryPointSize" []] - "ImageGatherExtended" -> [Feature "VkPhysicalDeviceFeatures" "shaderImageGatherExtended" []] - "StorageImageMultisample" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageMultisample" []] - "UniformBufferArrayDynamicIndexing" -> - [Feature "VkPhysicalDeviceFeatures" "shaderUniformBufferArrayDynamicIndexing" []] - "SampledImageArrayDynamicIndexing" -> - [Feature "VkPhysicalDeviceFeatures" "shaderSampledImageArrayDynamicIndexing" []] - "StorageBufferArrayDynamicIndexing" -> - [Feature "VkPhysicalDeviceFeatures" "shaderStorageBufferArrayDynamicIndexing" []] - "StorageImageArrayDynamicIndexing" -> - [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageArrayDynamicIndexing" []] - "ClipDistance" -> [Feature "VkPhysicalDeviceFeatures" "shaderClipDistance" []] - "CullDistance" -> [Feature "VkPhysicalDeviceFeatures" "shaderCullDistance" []] - "ImageCubeArray" -> [Feature "VkPhysicalDeviceFeatures" "imageCubeArray" []] - "SampleRateShading" -> [Feature "VkPhysicalDeviceFeatures" "sampleRateShading" []] - "SparseResidency" -> [Feature "VkPhysicalDeviceFeatures" "shaderResourceResidency" []] - "MinLod" -> [Feature "VkPhysicalDeviceFeatures" "shaderResourceMinLod" []] - "SampledCubeArray" -> [Feature "VkPhysicalDeviceFeatures" "imageCubeArray" []] - "ImageMSArray" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageMultisample" []] - "StorageImageExtendedFormats" -> [Version $ makeVersion [1, 0]] - "InterpolationFunction" -> [Feature "VkPhysicalDeviceFeatures" "sampleRateShading" []] - "StorageImageReadWithoutFormat" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageReadWithoutFormat" []] - "StorageImageWriteWithoutFormat" -> [Feature "VkPhysicalDeviceFeatures" "shaderStorageImageWriteWithoutFormat" []] - "MultiViewport" -> [Feature "VkPhysicalDeviceFeatures" "multiViewport" []] - "DrawParameters" -> - [ Feature "VkPhysicalDeviceVulkan11Features" "shaderDrawParameters" ["VK_VERSION_1_1"] - , Extension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME - ] - "MultiView" -> - [Feature "VkPhysicalDeviceVulkan11Features" "multiview" ["VK_VERSION_1_1", KHR_MULTIVIEW_EXTENSION_NAME]] - "DeviceGroup" -> [Version $ makeVersion [1, 1], Extension KHR_DEVICE_GROUP_EXTENSION_NAME] - "VariablePointersStorageBuffer" -> - [ Feature "VkPhysicalDeviceVulkan11Features" - "variablePointersStorageBuffer" - ["VK_VERSION_1_1", KHR_VARIABLE_POINTERS_EXTENSION_NAME] - ] - "VariablePointers" -> - [ Feature "VkPhysicalDeviceVulkan11Features" - "variablePointers" - ["VK_VERSION_1_1", KHR_VARIABLE_POINTERS_EXTENSION_NAME] - ] - "ShaderClockKHR" -> [Extension KHR_SHADER_CLOCK_EXTENSION_NAME] - "StencilExportEXT" -> [Extension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] - "SubgroupBallotKHR" -> [Extension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] - "SubgroupVoteKHR" -> [Extension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] - "ImageReadWriteLodAMD" -> [Extension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] - "ImageGatherBiasLodAMD" -> [Extension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] - "FragmentMaskAMD" -> [Extension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] - "SampleMaskOverrideCoverageNV" -> [Extension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] - "GeometryShaderPassthroughNV" -> [Extension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] - "ShaderViewportIndex" -> [Feature "VkPhysicalDeviceVulkan12Features" "shaderOutputViewportIndex" ["VK_VERSION_1_2"]] - "ShaderLayer" -> [Feature "VkPhysicalDeviceVulkan12Features" "shaderOutputLayer" ["VK_VERSION_1_2"]] - "ShaderViewportIndexLayerEXT" -> [Extension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] - "ShaderViewportIndexLayerNV" -> [Extension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] - "ShaderViewportMaskNV" -> [Extension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] - "PerViewAttributesNV" -> [Extension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] - "StorageBuffer16BitAccess" -> - [ Feature "VkPhysicalDeviceVulkan11Features" - "storageBuffer16BitAccess" - ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] - ] - "UniformAndStorageBuffer16BitAccess" -> - [ Feature "VkPhysicalDeviceVulkan11Features" - "uniformAndStorageBuffer16BitAccess" - ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] - ] - "StoragePushConstant16" -> - [ Feature "VkPhysicalDeviceVulkan11Features" - "storagePushConstant16" - ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] - ] - "StorageInputOutput16" -> - [ Feature "VkPhysicalDeviceVulkan11Features" - "storageInputOutput16" - ["VK_VERSION_1_1", KHR_16BIT_STORAGE_EXTENSION_NAME] - ] - "GroupNonUniform" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_BASIC_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformVote" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_VOTE_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformArithmetic" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_ARITHMETIC_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformBallot" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_BALLOT_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformShuffle" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_SHUFFLE_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformShuffleRelative" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformClustered" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_CLUSTERED_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformQuad" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_QUAD_BIT" - ["VK_VERSION_1_1"] - ] - "GroupNonUniformPartitionedNV" -> - [ Property "VkPhysicalDeviceVulkan11Properties" - "subgroupSupportedOperations" - "VK_SUBGROUP_FEATURE_PARTITIONED_BIT_NV" - [NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] - ] - "SampleMaskPostDepthCoverage" -> [Extension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] - "ShaderNonUniform" -> [Version $ makeVersion [1, 2], Extension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - "RuntimeDescriptorArray" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "runtimeDescriptorArray" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "InputAttachmentArrayDynamicIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderInputAttachmentArrayDynamicIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "UniformTexelBufferArrayDynamicIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderUniformTexelBufferArrayDynamicIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "StorageTexelBufferArrayDynamicIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderStorageTexelBufferArrayDynamicIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "UniformBufferArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderUniformBufferArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "SampledImageArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderSampledImageArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "StorageBufferArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderStorageBufferArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "StorageImageArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderStorageImageArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "InputAttachmentArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderInputAttachmentArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "UniformTexelBufferArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderUniformTexelBufferArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "StorageTexelBufferArrayNonUniformIndexing" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderStorageTexelBufferArrayNonUniformIndexing" - ["VK_VERSION_1_2", EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - ] - "Float16" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "shaderFloat16" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME] - , Extension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME - ] - "Int8" -> - [Feature "VkPhysicalDeviceVulkan12Features" "shaderInt8" ["VK_VERSION_1_2", KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME]] - "StorageBuffer8BitAccess" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "storageBuffer8BitAccess" - ["VK_VERSION_1_2", KHR_8BIT_STORAGE_EXTENSION_NAME] - ] - "UniformAndStorageBuffer8BitAccess" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "uniformAndStorageBuffer8BitAccess" - ["VK_VERSION_1_2", KHR_8BIT_STORAGE_EXTENSION_NAME] - ] - "StoragePushConstant8" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "storagePushConstant8" - ["VK_VERSION_1_2", KHR_8BIT_STORAGE_EXTENSION_NAME] - ] - "VulkanMemoryModel" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "vulkanMemoryModel" - ["VK_VERSION_1_2", KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] - ] - "VulkanMemoryModelDeviceScope" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "vulkanMemoryModelDeviceScope" - ["VK_VERSION_1_2", KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] - ] - "DenormPreserve" -> - [ Property "VkPhysicalDeviceVulkan12Properties" - "shaderDenormPreserveFloat16" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderDenormPreserveFloat32" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderDenormPreserveFloat64" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - ] - "DenormFlushToZero" -> - [ Property "VkPhysicalDeviceVulkan12Properties" - "shaderDenormFlushToZeroFloat16" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderDenormFlushToZeroFloat32" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderDenormFlushToZeroFloat64" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - ] - "SignedZeroInfNanPreserve" -> - [ Property "VkPhysicalDeviceVulkan12Properties" - "shaderSignedZeroInfNanPreserveFloat16" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderSignedZeroInfNanPreserveFloat32" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderSignedZeroInfNanPreserveFloat64" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - ] - "RoundingModeRTE" -> - [ Property "VkPhysicalDeviceVulkan12Properties" - "shaderRoundingModeRTEFloat16" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderRoundingModeRTEFloat32" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderRoundingModeRTEFloat64" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - ] - "RoundingModeRTZ" -> - [ Property "VkPhysicalDeviceVulkan12Properties" - "shaderRoundingModeRTZFloat16" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderRoundingModeRTZFloat32" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - , Property "VkPhysicalDeviceVulkan12Properties" - "shaderRoundingModeRTZFloat64" - "VK_TRUE" - ["VK_VERSION_1_2", KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - ] - "ComputeDerivativeGroupQuadsNV" -> - [ Feature "VkPhysicalDeviceComputeShaderDerivativesFeaturesNV" - "computeDerivativeGroupQuads" - [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] - ] - "ComputeDerivativeGroupLinearNV" -> - [ Feature "VkPhysicalDeviceComputeShaderDerivativesFeaturesNV" - "computeDerivativeGroupLinear" - [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] - ] - "FragmentBarycentricNV" -> - [ Feature "VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV" - "fragmentShaderBarycentric" - [NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] - ] - "ImageFootprintNV" -> - [ Feature "VkPhysicalDeviceShaderImageFootprintFeaturesNV" - "imageFootprint" - [NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] - ] - "ShadingRateNV" -> - [Feature "VkPhysicalDeviceShadingRateImageFeaturesNV" "shadingRateImage" [NV_SHADING_RATE_IMAGE_EXTENSION_NAME]] - "MeshShadingNV" -> [Extension NV_MESH_SHADER_EXTENSION_NAME] - "RayTracingProvisionalKHR" -> - [Feature "VkPhysicalDeviceRayTracingFeaturesKHR" "rayTracing" [KHR_RAY_TRACING_EXTENSION_NAME]] - "RayQueryProvisionalKHR" -> - [Feature "VkPhysicalDeviceRayTracingFeaturesKHR" "rayQuery" [KHR_RAY_TRACING_EXTENSION_NAME]] - "RayTraversalPrimitiveCullingProvisionalKHR" -> - [Feature "VkPhysicalDeviceRayTracingFeaturesKHR" "rayTracingPrimitiveCulling" [KHR_RAY_TRACING_EXTENSION_NAME]] - "RayTracingNV" -> [Extension NV_RAY_TRACING_EXTENSION_NAME] - "TransformFeedback" -> - [Feature "VkPhysicalDeviceTransformFeedbackFeaturesEXT" "transformFeedback" [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME]] - "GeometryStreams" -> - [Feature "VkPhysicalDeviceTransformFeedbackFeaturesEXT" "geometryStreams" [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME]] - "FragmentDensityEXT" -> - [ Feature "VkPhysicalDeviceFragmentDensityMapFeaturesEXT" - "fragmentDensityMap" - [EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] - ] - "PhysicalStorageBufferAddresses" -> - [ Feature "VkPhysicalDeviceVulkan12Features" - "bufferDeviceAddress" - ["VK_VERSION_1_2", KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - , Feature "VkPhysicalDeviceBufferDeviceAddressFeaturesEXT" - "bufferDeviceAddress" - [EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - ] - "CooperativeMatrixNV" -> - [Feature "VkPhysicalDeviceCooperativeMatrixFeaturesNV" "cooperativeMatrix" [NV_COOPERATIVE_MATRIX_EXTENSION_NAME]] - "IntegerFunctions2INTEL" -> - [ Feature "VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL" - "shaderIntegerFunctions2" - [INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME] - ] - "ShaderSMBuiltinsNV" -> - [Feature "VkPhysicalDeviceShaderSMBuiltinsFeaturesNV" "shaderSMBuiltins" [NV_SHADER_SM_BUILTINS_EXTENSION_NAME]] - "FragmentShaderSampleInterlockEXT" -> - [ Feature "VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT" - "fragmentShaderSampleInterlock" - [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - ] - "FragmentShaderPixelInterlockEXT" -> - [ Feature "VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT" - "fragmentShaderPixelInterlock" - [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - ] - "FragmentShaderShadingRateInterlockEXT" -> - [ Feature "VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT" - "fragmentShaderShadingRateInterlock" - [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - , Feature "VkPhysicalDeviceShadingRateImageFeaturesNV" "shadingRateImage" [NV_SHADING_RATE_IMAGE_EXTENSION_NAME] - ] - "DemoteToHelperInvocationEXT" -> - [ Feature "VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT" - "shaderDemoteToHelperInvocation" - [EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] - ] - "FragmentShadingRateKHR" -> - [ Feature "VkPhysicalDeviceFragmentShadingRateFeaturesKHR" - "pipelineFragmentShadingRate" - [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - , Feature "VkPhysicalDeviceFragmentShadingRateFeaturesKHR" - "primitiveFragmentShadingRate" - [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - , Feature "VkPhysicalDeviceFragmentShadingRateFeaturesKHR" - "attachmentFragmentShadingRate" - [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - ] - _ -> [] - diff --git a/src/Vulkan/SPIRVRequirements.hs b/src/Vulkan/SPIRVRequirements.hs new file mode 100644 index 000000000..279ddf004 --- /dev/null +++ b/src/Vulkan/SPIRVRequirements.hs @@ -0,0 +1,1125 @@ +{-# language CPP #-} +{-# language OverloadedLists #-} +module Vulkan.SPIRVRequirements ( spirvExtensionRequirements + , spirvCapabilityRequirements + ) where + +import Vulkan.Requirements (Requirement) +import Vulkan.Requirements (Requirement(..)) +import Data.Bits ((.&.)) +import Data.Bits (zeroBits) +import Data.Bits (Bits) +import Data.ByteString (ByteString) +import Vulkan.Extensions.VK_EXT_buffer_device_address (PhysicalDeviceBufferDeviceAddressFeaturesEXT) +import Vulkan.Extensions.VK_EXT_buffer_device_address (PhysicalDeviceBufferDeviceAddressFeaturesEXT(..)) +import Vulkan.Extensions.VK_NV_compute_shader_derivatives (PhysicalDeviceComputeShaderDerivativesFeaturesNV) +import Vulkan.Extensions.VK_NV_compute_shader_derivatives (PhysicalDeviceComputeShaderDerivativesFeaturesNV(..)) +import Vulkan.Extensions.VK_NV_cooperative_matrix (PhysicalDeviceCooperativeMatrixFeaturesNV) +import Vulkan.Extensions.VK_NV_cooperative_matrix (PhysicalDeviceCooperativeMatrixFeaturesNV(..)) +import Vulkan.Core10.DeviceInitialization (PhysicalDeviceFeatures) +import Vulkan.Core10.DeviceInitialization (PhysicalDeviceFeatures(..)) +import Vulkan.Extensions.VK_EXT_fragment_density_map (PhysicalDeviceFragmentDensityMapFeaturesEXT) +import Vulkan.Extensions.VK_EXT_fragment_density_map (PhysicalDeviceFragmentDensityMapFeaturesEXT(..)) +import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (PhysicalDeviceFragmentShaderBarycentricFeaturesNV) +import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (PhysicalDeviceFragmentShaderBarycentricFeaturesNV(..)) +import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (PhysicalDeviceFragmentShaderInterlockFeaturesEXT) +import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (PhysicalDeviceFragmentShaderInterlockFeaturesEXT(..)) +import Vulkan.Extensions.VK_KHR_fragment_shading_rate (PhysicalDeviceFragmentShadingRateFeaturesKHR) +import Vulkan.Extensions.VK_KHR_fragment_shading_rate (PhysicalDeviceFragmentShadingRateFeaturesKHR(..)) +import Vulkan.Extensions.VK_KHR_ray_tracing (PhysicalDeviceRayTracingFeaturesKHR) +import Vulkan.Extensions.VK_KHR_ray_tracing (PhysicalDeviceRayTracingFeaturesKHR(..)) +import Vulkan.Extensions.VK_EXT_shader_atomic_float (PhysicalDeviceShaderAtomicFloatFeaturesEXT) +import Vulkan.Extensions.VK_EXT_shader_atomic_float (PhysicalDeviceShaderAtomicFloatFeaturesEXT(..)) +import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT) +import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT(..)) +import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (PhysicalDeviceShaderImageAtomicInt64FeaturesEXT) +import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (PhysicalDeviceShaderImageAtomicInt64FeaturesEXT(..)) +import Vulkan.Extensions.VK_NV_shader_image_footprint (PhysicalDeviceShaderImageFootprintFeaturesNV) +import Vulkan.Extensions.VK_NV_shader_image_footprint (PhysicalDeviceShaderImageFootprintFeaturesNV(..)) +import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL) +import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL(..)) +import Vulkan.Extensions.VK_NV_shader_sm_builtins (PhysicalDeviceShaderSMBuiltinsFeaturesNV) +import Vulkan.Extensions.VK_NV_shader_sm_builtins (PhysicalDeviceShaderSMBuiltinsFeaturesNV(..)) +import Vulkan.Extensions.VK_NV_shading_rate_image (PhysicalDeviceShadingRateImageFeaturesNV) +import Vulkan.Extensions.VK_NV_shading_rate_image (PhysicalDeviceShadingRateImageFeaturesNV(..)) +import Vulkan.Extensions.VK_EXT_transform_feedback (PhysicalDeviceTransformFeedbackFeaturesEXT) +import Vulkan.Extensions.VK_EXT_transform_feedback (PhysicalDeviceTransformFeedbackFeaturesEXT(..)) +import Vulkan.Core12 (PhysicalDeviceVulkan11Features) +import Vulkan.Core12 (PhysicalDeviceVulkan11Features(..)) +import Vulkan.Core12 (PhysicalDeviceVulkan11Properties) +import Vulkan.Core12 (PhysicalDeviceVulkan11Properties(..)) +import Vulkan.Core12 (PhysicalDeviceVulkan12Features) +import Vulkan.Core12 (PhysicalDeviceVulkan12Features(..)) +import Vulkan.Core12 (PhysicalDeviceVulkan12Properties) +import Vulkan.Core12 (PhysicalDeviceVulkan12Properties(..)) +import Vulkan.Extensions.VK_AMD_gcn_shader (pattern AMD_GCN_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gpu_shader_half_float (pattern AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gpu_shader_int16 (pattern AMD_GPU_SHADER_INT16_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_ballot (pattern AMD_SHADER_BALLOT_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_explicit_vertex_parameter (pattern AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_fragment_mask (pattern AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_image_load_store_lod (pattern AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_trinary_minmax (pattern AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_texture_gather_bias_lod (pattern AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_buffer_device_address (pattern EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_descriptor_indexing (pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_density_map (pattern EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (pattern EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_post_depth_coverage (pattern EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_atomic_float (pattern EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (pattern EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (pattern EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_stencil_export (pattern EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_subgroup_ballot (pattern EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_subgroup_vote (pattern EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_viewport_index_layer (pattern EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_transform_feedback (pattern EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_decorate_string (pattern GOOGLE_DECORATE_STRING_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_hlsl_functionality1 (pattern GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_user_type (pattern GOOGLE_USER_TYPE_EXTENSION_NAME) +import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (pattern INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_device_group (pattern KHR_DEVICE_GROUP_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_fragment_shading_rate (pattern KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_draw_parameters (pattern KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float16_int8 (pattern KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float_controls (pattern KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_vulkan_memory_model (pattern KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME) +import Vulkan.Version (pattern MAKE_VERSION) +import Vulkan.Extensions.VK_NVX_multiview_per_view_attributes (pattern NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_compute_shader_derivatives (pattern NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_cooperative_matrix (pattern NV_COOPERATIVE_MATRIX_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (pattern NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_geometry_shader_passthrough (pattern NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_mesh_shader (pattern NV_MESH_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_ray_tracing (pattern NV_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_sample_mask_override_coverage (pattern NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_image_footprint (pattern NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_sm_builtins (pattern NV_SHADER_SM_BUILTINS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_subgroup_partitioned (pattern NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shading_rate_image (pattern NV_SHADING_RATE_IMAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_viewport_array2 (pattern NV_VIEWPORT_ARRAY2_EXTENSION_NAME) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_ARITHMETIC_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_BALLOT_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_BASIC_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_CLUSTERED_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_PARTITIONED_BIT_NV)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_QUAD_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_SHUFFLE_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT)) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) +import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_VOTE_BIT)) +-- | Check if the intersection of bits is non-zero +(.&&.) :: Bits a => a -> a -> Bool +x .&&. y = (x .&. y) /= zeroBits + +spirvExtensionRequirements :: ByteString -> [Requirement] +spirvExtensionRequirements = \case + "SPV_KHR_variable_pointers" -> + [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_VARIABLE_POINTERS_EXTENSION_NAME] + "SPV_AMD_shader_explicit_vertex_parameter" -> [RequireExtension AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME] + "SPV_AMD_gcn_shader" -> [RequireExtension AMD_GCN_SHADER_EXTENSION_NAME] + "SPV_AMD_gpu_shader_half_float" -> [RequireExtension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME] + "SPV_AMD_gpu_shader_int16" -> [RequireExtension AMD_GPU_SHADER_INT16_EXTENSION_NAME] + "SPV_AMD_shader_ballot" -> [RequireExtension AMD_SHADER_BALLOT_EXTENSION_NAME] + "SPV_AMD_shader_fragment_mask" -> [RequireExtension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] + "SPV_AMD_shader_image_load_store_lod" -> [RequireExtension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] + "SPV_AMD_shader_trinary_minmax" -> [RequireExtension AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME] + "SPV_AMD_texture_gather_bias_lod" -> [RequireExtension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] + "SPV_KHR_shader_draw_parameters" -> + [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME] + "SPV_KHR_8bit_storage" -> [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_8BIT_STORAGE_EXTENSION_NAME] + "SPV_KHR_16bit_storage" -> [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_16BIT_STORAGE_EXTENSION_NAME] + "SPV_KHR_shader_clock" -> [RequireExtension KHR_SHADER_CLOCK_EXTENSION_NAME] + "SPV_KHR_float_controls" -> + [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + "SPV_KHR_storage_buffer_storage_class" -> + [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] + "SPV_KHR_post_depth_coverage" -> [RequireExtension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] + "SPV_EXT_shader_stencil_export" -> [RequireExtension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] + "SPV_KHR_shader_ballot" -> [RequireExtension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] + "SPV_KHR_subgroup_vote" -> [RequireExtension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] + "SPV_NV_sample_mask_override_coverage" -> [RequireExtension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] + "SPV_NV_geometry_shader_passthrough" -> [RequireExtension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] + "SPV_NV_mesh_shader" -> [RequireExtension NV_MESH_SHADER_EXTENSION_NAME] + "SPV_NV_viewport_array2" -> [RequireExtension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] + "SPV_NV_shader_subgroup_partitioned" -> [RequireExtension NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] + "SPV_EXT_shader_viewport_index_layer" -> + [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] + "SPV_NVX_multiview_per_view_attributes" -> [RequireExtension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] + "SPV_EXT_descriptor_indexing" -> + [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + "SPV_KHR_vulkan_memory_model" -> + [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + "SPV_NV_compute_shader_derivatives" -> [RequireExtension NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] + "SPV_NV_fragment_shader_barycentric" -> [RequireExtension NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] + "SPV_NV_shader_image_footprint" -> [RequireExtension NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] + "SPV_NV_shading_rate" -> [RequireExtension NV_SHADING_RATE_IMAGE_EXTENSION_NAME] + "SPV_NV_ray_tracing" -> [RequireExtension NV_RAY_TRACING_EXTENSION_NAME] + "SPV_KHR_ray_tracing" -> [RequireExtension KHR_RAY_TRACING_EXTENSION_NAME] + "SPV_KHR_ray_query" -> [RequireExtension KHR_RAY_TRACING_EXTENSION_NAME] + "SPV_GOOGLE_hlsl_functionality1" -> [RequireExtension GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME] + "SPV_GOOGLE_user_type" -> [RequireExtension GOOGLE_USER_TYPE_EXTENSION_NAME] + "SPV_GOOGLE_decorate_string" -> [RequireExtension GOOGLE_DECORATE_STRING_EXTENSION_NAME] + "SPV_EXT_fragment_invocation_density" -> [RequireExtension EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] + "SPV_KHR_physical_storage_buffer" -> + [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + "SPV_EXT_physical_storage_buffer" -> [RequireExtension EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + "SPV_NV_cooperative_matrix" -> [RequireExtension NV_COOPERATIVE_MATRIX_EXTENSION_NAME] + "SPV_NV_shader_sm_builtins" -> [RequireExtension NV_SHADER_SM_BUILTINS_EXTENSION_NAME] + "SPV_EXT_fragment_shader_interlock" -> [RequireExtension EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + "SPV_EXT_demote_to_helper_invocation" -> [RequireExtension EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] + "SPV_KHR_fragment_shading_rate" -> [RequireExtension KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + "SPV_KHR_non_semantic_info" -> [RequireExtension KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME] + "SPV_EXT_shader_image_int64" -> [RequireExtension EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] + "SPV_KHR_terminate_invocation" -> [RequireExtension KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME] + _ -> [] + +spirvCapabilityRequirements :: ByteString -> [Requirement] +spirvCapabilityRequirements = \case + "Matrix" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "Shader" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "InputAttachment" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "Sampled1D" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "Image1D" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "SampledBuffer" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "ImageBuffer" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "ImageQuery" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "DerivativeControl" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "Geometry" -> + [ RequireFeature { featureName = "geometryShader" + , checkFeature = geometryShader :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { geometryShader = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "Tessellation" -> + [ RequireFeature { featureName = "tessellationShader" + , checkFeature = tessellationShader :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { tessellationShader = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "Float64" -> + [ RequireFeature { featureName = "shaderFloat64" + , checkFeature = shaderFloat64 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderFloat64 = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "Int64" -> + [ RequireFeature { featureName = "shaderInt64" + , checkFeature = shaderInt64 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderInt64 = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "Int64Atomics" -> + [ RequireFeature { featureName = "shaderBufferInt64Atomics" + , checkFeature = shaderBufferInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderBufferInt64Atomics = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] + } + , RequireFeature { featureName = "shaderSharedInt64Atomics" + , checkFeature = shaderSharedInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderSharedInt64Atomics = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] + } + ] + "AtomicFloat32AddEXT" -> + [ RequireFeature + { featureName = "shaderBufferFloat32AtomicAdd" + , checkFeature = shaderBufferFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + , enableFeature = \f -> f { shaderBufferFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + } + , RequireFeature + { featureName = "shaderSharedFloat32AtomicAdd" + , checkFeature = shaderSharedFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + , enableFeature = \f -> f { shaderSharedFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + } + , RequireFeature + { featureName = "shaderImageFloat32AtomicAdd" + , checkFeature = shaderImageFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + , enableFeature = \f -> f { shaderImageFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + } + , RequireFeature + { featureName = "sparseImageFloat32AtomicAdd" + , checkFeature = sparseImageFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + , enableFeature = \f -> f { sparseImageFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + } + ] + "AtomicFloat64AddEXT" -> + [ RequireFeature + { featureName = "shaderBufferFloat64AtomicAdd" + , checkFeature = shaderBufferFloat64AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + , enableFeature = \f -> f { shaderBufferFloat64AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + } + , RequireFeature + { featureName = "shaderSharedFloat64AtomicAdd" + , checkFeature = shaderSharedFloat64AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + , enableFeature = \f -> f { shaderSharedFloat64AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] + } + ] + "Int64ImageEXT" -> + [ RequireFeature + { featureName = "shaderImageInt64Atomics" + , checkFeature = shaderImageInt64Atomics :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT -> Bool + , enableFeature = \f -> f { shaderImageInt64Atomics = True } :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] + } + ] + "Int16" -> + [ RequireFeature { featureName = "shaderInt16" + , checkFeature = shaderInt16 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderInt16 = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "TessellationPointSize" -> + [ RequireFeature + { featureName = "shaderTessellationAndGeometryPointSize" + , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "GeometryPointSize" -> + [ RequireFeature + { featureName = "shaderTessellationAndGeometryPointSize" + , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "ImageGatherExtended" -> + [ RequireFeature { featureName = "shaderImageGatherExtended" + , checkFeature = shaderImageGatherExtended :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderImageGatherExtended = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "StorageImageMultisample" -> + [ RequireFeature { featureName = "shaderStorageImageMultisample" + , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "UniformBufferArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderUniformBufferArrayDynamicIndexing" + , checkFeature = shaderUniformBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderUniformBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "SampledImageArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderSampledImageArrayDynamicIndexing" + , checkFeature = shaderSampledImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderSampledImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "StorageBufferArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderStorageBufferArrayDynamicIndexing" + , checkFeature = shaderStorageBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "StorageImageArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderStorageImageArrayDynamicIndexing" + , checkFeature = shaderStorageImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "ClipDistance" -> + [ RequireFeature { featureName = "shaderClipDistance" + , checkFeature = shaderClipDistance :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderClipDistance = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "CullDistance" -> + [ RequireFeature { featureName = "shaderCullDistance" + , checkFeature = shaderCullDistance :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderCullDistance = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "ImageCubeArray" -> + [ RequireFeature { featureName = "imageCubeArray" + , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "SampleRateShading" -> + [ RequireFeature { featureName = "sampleRateShading" + , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "SparseResidency" -> + [ RequireFeature { featureName = "shaderResourceResidency" + , checkFeature = shaderResourceResidency :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderResourceResidency = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "MinLod" -> + [ RequireFeature { featureName = "shaderResourceMinLod" + , checkFeature = shaderResourceMinLod :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderResourceMinLod = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "SampledCubeArray" -> + [ RequireFeature { featureName = "imageCubeArray" + , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "ImageMSArray" -> + [ RequireFeature { featureName = "shaderStorageImageMultisample" + , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "StorageImageExtendedFormats" -> [RequireVersion $ MAKE_VERSION 1 0 0] + "InterpolationFunction" -> + [ RequireFeature { featureName = "sampleRateShading" + , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "StorageImageReadWithoutFormat" -> + [ RequireFeature { featureName = "shaderStorageImageReadWithoutFormat" + , checkFeature = shaderStorageImageReadWithoutFormat :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageReadWithoutFormat = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "StorageImageWriteWithoutFormat" -> + [ RequireFeature { featureName = "shaderStorageImageWriteWithoutFormat" + , checkFeature = shaderStorageImageWriteWithoutFormat :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageWriteWithoutFormat = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "MultiViewport" -> + [ RequireFeature { featureName = "multiViewport" + , checkFeature = multiViewport :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { multiViewport = True } :: PhysicalDeviceFeatures + , requireMinVersion = Nothing + , requireExtensions = [] + } + ] + "DrawParameters" -> + [ RequireFeature { featureName = "shaderDrawParameters" + , checkFeature = shaderDrawParameters :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { shaderDrawParameters = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + , RequireExtension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME + ] + "MultiView" -> + [ RequireFeature { featureName = "multiview" + , checkFeature = multiview :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { multiview = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_MULTIVIEW_EXTENSION_NAME] + } + ] + "DeviceGroup" -> [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_DEVICE_GROUP_EXTENSION_NAME] + "VariablePointersStorageBuffer" -> + [ RequireFeature + { featureName = "variablePointersStorageBuffer" + , checkFeature = variablePointersStorageBuffer :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { variablePointersStorageBuffer = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_VARIABLE_POINTERS_EXTENSION_NAME] + } + ] + "VariablePointers" -> + [ RequireFeature { featureName = "variablePointers" + , checkFeature = variablePointers :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { variablePointers = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_VARIABLE_POINTERS_EXTENSION_NAME] + } + ] + "ShaderClockKHR" -> [RequireExtension KHR_SHADER_CLOCK_EXTENSION_NAME] + "StencilExportEXT" -> [RequireExtension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] + "SubgroupBallotKHR" -> [RequireExtension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] + "SubgroupVoteKHR" -> [RequireExtension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] + "ImageReadWriteLodAMD" -> [RequireExtension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] + "ImageGatherBiasLodAMD" -> [RequireExtension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] + "FragmentMaskAMD" -> [RequireExtension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] + "SampleMaskOverrideCoverageNV" -> [RequireExtension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] + "GeometryShaderPassthroughNV" -> [RequireExtension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] + "ShaderViewportIndex" -> + [ RequireFeature { featureName = "shaderOutputViewportIndex" + , checkFeature = shaderOutputViewportIndex :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderOutputViewportIndex = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [] + } + ] + "ShaderLayer" -> + [ RequireFeature { featureName = "shaderOutputLayer" + , checkFeature = shaderOutputLayer :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderOutputLayer = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [] + } + ] + "ShaderViewportIndexLayerEXT" -> [RequireExtension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] + "ShaderViewportIndexLayerNV" -> [RequireExtension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] + "ShaderViewportMaskNV" -> [RequireExtension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] + "PerViewAttributesNV" -> [RequireExtension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] + "StorageBuffer16BitAccess" -> + [ RequireFeature { featureName = "storageBuffer16BitAccess" + , checkFeature = storageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + } + ] + "UniformAndStorageBuffer16BitAccess" -> + [ RequireFeature + { featureName = "uniformAndStorageBuffer16BitAccess" + , checkFeature = uniformAndStorageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { uniformAndStorageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + } + ] + "StoragePushConstant16" -> + [ RequireFeature { featureName = "storagePushConstant16" + , checkFeature = storagePushConstant16 :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storagePushConstant16 = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + } + ] + "StorageInputOutput16" -> + [ RequireFeature { featureName = "storageInputOutput16" + , checkFeature = storageInputOutput16 :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storageInputOutput16 = True } :: PhysicalDeviceVulkan11Features + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + } + ] + "GroupNonUniform" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_BASIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformVote" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_VOTE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformArithmetic" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_ARITHMETIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformBallot" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_BALLOT_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformShuffle" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_SHUFFLE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformShuffleRelative" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformClustered" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_CLUSTERED_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformQuad" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_QUAD_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 1 0 + , requireExtensions = [] + } + ] + "GroupNonUniformPartitionedNV" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_PARTITIONED_BIT_NV .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + , requireMinVersion = Nothing + , requireExtensions = [NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] + } + ] + "SampleMaskPostDepthCoverage" -> [RequireExtension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] + "ShaderNonUniform" -> [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + "RuntimeDescriptorArray" -> + [ RequireFeature { featureName = "runtimeDescriptorArray" + , checkFeature = runtimeDescriptorArray :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { runtimeDescriptorArray = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "InputAttachmentArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderInputAttachmentArrayDynamicIndexing" + , checkFeature = shaderInputAttachmentArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderInputAttachmentArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "UniformTexelBufferArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderUniformTexelBufferArrayDynamicIndexing" + , checkFeature = shaderUniformTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderUniformTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "StorageTexelBufferArrayDynamicIndexing" -> + [ RequireFeature + { featureName = "shaderStorageTexelBufferArrayDynamicIndexing" + , checkFeature = shaderStorageTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderStorageTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "UniformBufferArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderUniformBufferArrayNonUniformIndexing" + , checkFeature = shaderUniformBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderUniformBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "SampledImageArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderSampledImageArrayNonUniformIndexing" + , checkFeature = shaderSampledImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderSampledImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "StorageBufferArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderStorageBufferArrayNonUniformIndexing" + , checkFeature = shaderStorageBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderStorageBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "StorageImageArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderStorageImageArrayNonUniformIndexing" + , checkFeature = shaderStorageImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderStorageImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "InputAttachmentArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderInputAttachmentArrayNonUniformIndexing" + , checkFeature = shaderInputAttachmentArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderInputAttachmentArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "UniformTexelBufferArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderUniformTexelBufferArrayNonUniformIndexing" + , checkFeature = shaderUniformTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderUniformTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "StorageTexelBufferArrayNonUniformIndexing" -> + [ RequireFeature + { featureName = "shaderStorageTexelBufferArrayNonUniformIndexing" + , checkFeature = shaderStorageTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderStorageTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + } + ] + "Float16" -> + [ RequireFeature { featureName = "shaderFloat16" + , checkFeature = shaderFloat16 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderFloat16 = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME] + } + , RequireExtension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME + ] + "Int8" -> + [ RequireFeature { featureName = "shaderInt8" + , checkFeature = shaderInt8 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderInt8 = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME] + } + ] + "StorageBuffer8BitAccess" -> + [ RequireFeature { featureName = "storageBuffer8BitAccess" + , checkFeature = storageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { storageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_8BIT_STORAGE_EXTENSION_NAME] + } + ] + "UniformAndStorageBuffer8BitAccess" -> + [ RequireFeature + { featureName = "uniformAndStorageBuffer8BitAccess" + , checkFeature = uniformAndStorageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { uniformAndStorageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_8BIT_STORAGE_EXTENSION_NAME] + } + ] + "StoragePushConstant8" -> + [ RequireFeature { featureName = "storagePushConstant8" + , checkFeature = storagePushConstant8 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { storagePushConstant8 = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_8BIT_STORAGE_EXTENSION_NAME] + } + ] + "VulkanMemoryModel" -> + [ RequireFeature { featureName = "vulkanMemoryModel" + , checkFeature = vulkanMemoryModel :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { vulkanMemoryModel = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + } + ] + "VulkanMemoryModelDeviceScope" -> + [ RequireFeature { featureName = "vulkanMemoryModelDeviceScope" + , checkFeature = vulkanMemoryModelDeviceScope :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { vulkanMemoryModelDeviceScope = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + } + ] + "DenormPreserve" -> + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormPreserveFloat32 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormPreserveFloat64 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + ] + "DenormFlushToZero" -> + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormFlushToZeroFloat16 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormFlushToZeroFloat32 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormFlushToZeroFloat64 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + ] + "SignedZeroInfNanPreserve" -> + [ RequireProperty + { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty + { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat32 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty + { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat64 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + ] + "RoundingModeRTE" -> + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTEFloat16 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTEFloat32 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTEFloat64 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + ] + "RoundingModeRTZ" -> + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTZFloat16 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTZFloat32 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTZFloat64 (p :: PhysicalDeviceVulkan12Properties) + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + } + ] + "ComputeDerivativeGroupQuadsNV" -> + [ RequireFeature + { featureName = "computeDerivativeGroupQuads" + , checkFeature = computeDerivativeGroupQuads :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool + , enableFeature = \f -> + f { computeDerivativeGroupQuads = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] + } + ] + "ComputeDerivativeGroupLinearNV" -> + [ RequireFeature + { featureName = "computeDerivativeGroupLinear" + , checkFeature = computeDerivativeGroupLinear :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool + , enableFeature = \f -> + f { computeDerivativeGroupLinear = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] + } + ] + "FragmentBarycentricNV" -> + [ RequireFeature + { featureName = "fragmentShaderBarycentric" + , checkFeature = fragmentShaderBarycentric :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV -> Bool + , enableFeature = \f -> + f { fragmentShaderBarycentric = True } :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] + } + ] + "ImageFootprintNV" -> + [ RequireFeature { featureName = "imageFootprint" + , checkFeature = imageFootprint :: PhysicalDeviceShaderImageFootprintFeaturesNV -> Bool + , enableFeature = \f -> f { imageFootprint = True } :: PhysicalDeviceShaderImageFootprintFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] + } + ] + "ShadingRateNV" -> + [ RequireFeature { featureName = "shadingRateImage" + , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool + , enableFeature = \f -> f { shadingRateImage = True } :: PhysicalDeviceShadingRateImageFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_SHADING_RATE_IMAGE_EXTENSION_NAME] + } + ] + "MeshShadingNV" -> [RequireExtension NV_MESH_SHADER_EXTENSION_NAME] + "RayTracingProvisionalKHR" -> + [ RequireFeature { featureName = "rayTracing" + , checkFeature = rayTracing :: PhysicalDeviceRayTracingFeaturesKHR -> Bool + , enableFeature = \f -> f { rayTracing = True } :: PhysicalDeviceRayTracingFeaturesKHR + , requireMinVersion = Nothing + , requireExtensions = [KHR_RAY_TRACING_EXTENSION_NAME] + } + ] + "RayQueryProvisionalKHR" -> + [ RequireFeature { featureName = "rayQuery" + , checkFeature = rayQuery :: PhysicalDeviceRayTracingFeaturesKHR -> Bool + , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayTracingFeaturesKHR + , requireMinVersion = Nothing + , requireExtensions = [KHR_RAY_TRACING_EXTENSION_NAME] + } + ] + "RayTraversalPrimitiveCullingProvisionalKHR" -> + [ RequireFeature + { featureName = "rayTracingPrimitiveCulling" + , checkFeature = rayTracingPrimitiveCulling :: PhysicalDeviceRayTracingFeaturesKHR -> Bool + , enableFeature = \f -> f { rayTracingPrimitiveCulling = True } :: PhysicalDeviceRayTracingFeaturesKHR + , requireMinVersion = Nothing + , requireExtensions = [KHR_RAY_TRACING_EXTENSION_NAME] + } + ] + "RayTracingNV" -> [RequireExtension NV_RAY_TRACING_EXTENSION_NAME] + "TransformFeedback" -> + [ RequireFeature + { featureName = "transformFeedback" + , checkFeature = transformFeedback :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool + , enableFeature = \f -> f { transformFeedback = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME] + } + ] + "GeometryStreams" -> + [ RequireFeature { featureName = "geometryStreams" + , checkFeature = geometryStreams :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool + , enableFeature = \f -> f { geometryStreams = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME] + } + ] + "FragmentDensityEXT" -> + [ RequireFeature + { featureName = "fragmentDensityMap" + , checkFeature = fragmentDensityMap :: PhysicalDeviceFragmentDensityMapFeaturesEXT -> Bool + , enableFeature = \f -> f { fragmentDensityMap = True } :: PhysicalDeviceFragmentDensityMapFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] + } + ] + "PhysicalStorageBufferAddresses" -> + [ RequireFeature { featureName = "bufferDeviceAddress" + , checkFeature = bufferDeviceAddress :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceVulkan12Features + , requireMinVersion = Just $ MAKE_VERSION 1 2 0 + , requireExtensions = [KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + } + , RequireFeature + { featureName = "bufferDeviceAddress" + , checkFeature = bufferDeviceAddress :: PhysicalDeviceBufferDeviceAddressFeaturesEXT -> Bool + , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceBufferDeviceAddressFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + } + ] + "CooperativeMatrixNV" -> + [ RequireFeature { featureName = "cooperativeMatrix" + , checkFeature = cooperativeMatrix :: PhysicalDeviceCooperativeMatrixFeaturesNV -> Bool + , enableFeature = \f -> f { cooperativeMatrix = True } :: PhysicalDeviceCooperativeMatrixFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_COOPERATIVE_MATRIX_EXTENSION_NAME] + } + ] + "IntegerFunctions2INTEL" -> + [ RequireFeature + { featureName = "shaderIntegerFunctions2" + , checkFeature = shaderIntegerFunctions2 :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL -> Bool + , enableFeature = \f -> + f { shaderIntegerFunctions2 = True } :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL + , requireMinVersion = Nothing + , requireExtensions = [INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME] + } + ] + "ShaderSMBuiltinsNV" -> + [ RequireFeature { featureName = "shaderSMBuiltins" + , checkFeature = shaderSMBuiltins :: PhysicalDeviceShaderSMBuiltinsFeaturesNV -> Bool + , enableFeature = \f -> f { shaderSMBuiltins = True } :: PhysicalDeviceShaderSMBuiltinsFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_SHADER_SM_BUILTINS_EXTENSION_NAME] + } + ] + "FragmentShaderSampleInterlockEXT" -> + [ RequireFeature + { featureName = "fragmentShaderSampleInterlock" + , checkFeature = fragmentShaderSampleInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool + , enableFeature = \f -> + f { fragmentShaderSampleInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + } + ] + "FragmentShaderPixelInterlockEXT" -> + [ RequireFeature + { featureName = "fragmentShaderPixelInterlock" + , checkFeature = fragmentShaderPixelInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool + , enableFeature = \f -> + f { fragmentShaderPixelInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + } + ] + "FragmentShaderShadingRateInterlockEXT" -> + [ RequireFeature + { featureName = "fragmentShaderShadingRateInterlock" + , checkFeature = fragmentShaderShadingRateInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool + , enableFeature = \f -> + f { fragmentShaderShadingRateInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] + } + , RequireFeature { featureName = "shadingRateImage" + , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool + , enableFeature = \f -> f { shadingRateImage = True } :: PhysicalDeviceShadingRateImageFeaturesNV + , requireMinVersion = Nothing + , requireExtensions = [NV_SHADING_RATE_IMAGE_EXTENSION_NAME] + } + ] + "DemoteToHelperInvocationEXT" -> + [ RequireFeature + { featureName = "shaderDemoteToHelperInvocation" + , checkFeature = shaderDemoteToHelperInvocation :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT + -> Bool + , enableFeature = \f -> + f { shaderDemoteToHelperInvocation = True } :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT + , requireMinVersion = Nothing + , requireExtensions = [EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] + } + ] + "FragmentShadingRateKHR" -> + [ RequireFeature + { featureName = "pipelineFragmentShadingRate" + , checkFeature = pipelineFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool + , enableFeature = \f -> f { pipelineFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR + , requireMinVersion = Nothing + , requireExtensions = [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + } + , RequireFeature + { featureName = "primitiveFragmentShadingRate" + , checkFeature = primitiveFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool + , enableFeature = \f -> f { primitiveFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR + , requireMinVersion = Nothing + , requireExtensions = [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + } + , RequireFeature + { featureName = "attachmentFragmentShadingRate" + , checkFeature = attachmentFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool + , enableFeature = \f -> f { attachmentFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR + , requireMinVersion = Nothing + , requireExtensions = [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] + } + ] + _ -> [] + diff --git a/vulkan.cabal b/vulkan.cabal index a33d3e156..85f1ad2fc 100644 --- a/vulkan.cabal +++ b/vulkan.cabal @@ -471,10 +471,11 @@ library Vulkan.Extensions.VK_QCOM_render_pass_transform Vulkan.Extensions.VK_QCOM_rotated_copy_commands Vulkan.NamedType - Vulkan.SPIRVInfo + Vulkan.SPIRVRequirements Vulkan.Version Vulkan.Zero Vulkan.Internal.Utils + Vulkan.Requirements hs-source-dirs: src src-manual From 2ac6a17d5c7a0a075a6debd569913163bb60e41e Mon Sep 17 00:00:00 2001 From: sheaf Date: Tue, 24 Nov 2020 09:11:13 +0100 Subject: [PATCH 09/70] Handle layers and instance extensions, track min version numbers --- src-manual/Vulkan/Requirements.hs | 304 ++++++++++++++++++++---------- 1 file changed, 203 insertions(+), 101 deletions(-) diff --git a/src-manual/Vulkan/Requirements.hs b/src-manual/Vulkan/Requirements.hs index 07ada48f9..aa52379a7 100644 --- a/src-manual/Vulkan/Requirements.hs +++ b/src-manual/Vulkan/Requirements.hs @@ -1,17 +1,18 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE DuplicateRecordFields #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE PatternSynonyms #-} -{-# LANGUAGE PolyKinds #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE Strict #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE Strict #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE UndecidableSuperClasses #-} module Vulkan.Requirements where @@ -19,7 +20,7 @@ module Vulkan.Requirements where import Control.Arrow ( Arrow(first,second,(***)) ) import Data.Foldable - ( for_, foldr' ) + ( foldr' ) import Data.Kind ( Type ) import Data.Type.Equality @@ -35,9 +36,19 @@ import GHC.Exts import Data.ByteString ( ByteString ) +-- unordered-containers +import Data.HashMap.Strict + ( HashMap ) +import qualified Data.HashMap.Strict as HashMap + ( empty, insertWith, singleton, unionWith ) +import Data.HashSet + ( HashSet ) +import qualified Data.HashSet as HashSet + ( empty, insert ) + -- vulkan import Vulkan.Core10.DeviceInitialization - ( PhysicalDeviceFeatures, PhysicalDeviceProperties ) + ( InstanceCreateInfo, PhysicalDeviceFeatures, PhysicalDeviceProperties ) import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 ( PhysicalDeviceFeatures2(..) ) import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 @@ -59,61 +70,93 @@ data Requirement where RequireVersion :: { version :: Word32 } -> Requirement - -- | Require a Vulkan extension. - RequireExtension - :: { extension :: ByteString } + -- | Require a Vulkan layer. + RequireInstanceLayer + :: { instanceLayerName :: ByteString + , instanceLayerMinVersion :: Word32 + } + -> Requirement + -- | Require a Vulkan instance extension. + RequireInstanceExtension + :: { instanceExtensionLayerName :: Maybe ByteString + , instanceExtensionName :: ByteString + , instanceExtensionMinVersion :: Word32 + } + -> Requirement + -- | Require a Vulkan device extension. + RequireDeviceExtension + :: { deviceExtensionLayerName :: Maybe ByteString + , deviceExtensionName :: ByteString + , deviceExtensionMinVersion :: Word32 + } + -> Requirement + -- | Require a Vulkan instance setting (e.g. enable or disable a validation feature). + RequireInstanceSetting + :: forall struct + . KnownInstanceSettingStruct struct + => { setInstanceSetting :: struct -> struct } -> Requirement -- | Require a Vulkan device feature. RequireFeature :: forall struct - . KnownFeature struct - => { featureName :: ByteString - , checkFeature :: struct -> Bool - , enableFeature :: struct -> struct - , requireMinVersion :: Maybe Word32 - , requireExtensions :: [ByteString] + . KnownFeatureStruct struct + => { featureName :: ByteString + , checkFeature :: struct -> Bool + , enableFeature :: struct -> struct } -> Requirement -- | Require a Vulkan device property. RequireProperty :: forall struct - . KnownProperty struct - => { propertyName :: ByteString - , checkProperty :: struct -> Bool - , requireMinVersion :: Maybe Word32 - , requireExtensions :: [ByteString] + . KnownPropertyStruct struct + => { propertyName :: ByteString + , checkProperty :: struct -> Bool } -> Requirement -data SFeature feat where - BasicFeature - :: SFeature PhysicalDeviceFeatures - ExtendedFeature +-- | A Vulkan structure that can appear in 'InstanceCreateInfo'. +class ( Typeable sett, Extends InstanceCreateInfo sett, Zero sett, FromCStruct sett, ToCStruct sett ) + => KnownInstanceSettingStruct sett where +instance ( Typeable sett, Extends InstanceCreateInfo sett, Zero sett, FromCStruct sett, ToCStruct sett ) + => KnownInstanceSettingStruct sett where + +-- | Singleton for a Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. +-- +-- It is either 'PhysicalDeviceFeatures', or it 'Extends' 'PhysicalDeviceFeatures2'. +data SFeatureStruct feat where + BasicFeatureStruct + :: SFeatureStruct PhysicalDeviceFeatures + ExtendedFeatureStruct :: ( Typeable feat, Extends PhysicalDeviceFeatures2 feat, Zero feat, FromCStruct feat, ToCStruct feat ) - => SFeature feat -class KnownFeature feat where - sFeature :: SFeature feat -instance KnownFeature PhysicalDeviceFeatures where - sFeature = BasicFeature + => SFeatureStruct feat +-- | A Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. +class KnownFeatureStruct feat where + sFeatureStruct :: SFeatureStruct feat +instance KnownFeatureStruct PhysicalDeviceFeatures where + sFeatureStruct = BasicFeatureStruct instance {-# OVERLAPPABLE #-} ( Typeable feat, Extends PhysicalDeviceFeatures2 feat, Zero feat, FromCStruct feat, ToCStruct feat ) - => KnownFeature feat where - sFeature = ExtendedFeature + => KnownFeatureStruct feat where + sFeatureStruct = ExtendedFeatureStruct -data SProperty prop where - BasicProperty - :: SProperty PhysicalDeviceProperties - ExtendedProperty +-- | Singleton for a Vulkan structure that can appear in 'PhysicalDeviceProperties2'. +-- +-- It is either 'PhysicalDeviceProperties', or it 'Extends' 'PhysicalDeviceProperties2'. +data SPropertyStruct prop where + BasicPropertyStruct + :: SPropertyStruct PhysicalDeviceProperties + ExtendedPropertyStruct :: ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) - => SProperty prop -class KnownProperty prop where - sProperty :: SProperty prop -instance KnownProperty PhysicalDeviceProperties where - sProperty = BasicProperty + => SPropertyStruct prop +-- | A Vulkan structure that can appear in 'PhysicalDeviceProperties2'. +class KnownPropertyStruct prop where + sPropertyStruct :: SPropertyStruct prop +instance KnownPropertyStruct PhysicalDeviceProperties where + sPropertyStruct = BasicPropertyStruct instance {-# OVERLAPPABLE #-} ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) - => KnownProperty prop where - sProperty = ExtendedProperty + => KnownPropertyStruct prop where + sPropertyStruct = ExtendedPropertyStruct -- | Enough information to focus on any structure within a Vulkan structure chain. @@ -130,21 +173,39 @@ instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain ( | otherwise = ((. snd) *** (second .)) <$> has px +data LayerName + = BaseLayer + | LayerName ByteString -- | A collection of Vulkan requirements. -- -- Parameterised over the structure chains used by 'PhysicalDeviceFeatures2' and 'PhysicalDeviceProperties2'. data Requirements where Requirements - :: forall feats props - . ( KnownChain feats, Extendss PhysicalDeviceFeatures2 feats + :: forall setts feats props + . ( KnownChain setts, Extendss InstanceCreateInfo setts + , KnownChain feats, Extendss PhysicalDeviceFeatures2 feats , KnownChain props, Extendss PhysicalDeviceProperties2 props ) - => { version :: Word32 -- ^ Minimum Vulkan API version required. - , extensions :: [ ByteString ] -- ^ Required Vulkan device extension names. - , missingFeatures :: PhysicalDeviceFeatures2 feats -> [ByteString] -- ^ Returns all the required features that were not enabled in 'PhysicalDeviceFeatures2'. - , neededFeatures :: PhysicalDeviceFeatures2 feats -- ^ All required features, to be used in 'DeviceCreateInfo'. - , missingProperties :: PhysicalDeviceProperties2 props -> [ByteString] -- ^ Returns all the required properties that were not satisfied in 'PhysicalDeviceProperties2' + => { + -- | Minimum Vulkan API version required. + version :: Word32 + -- | Required Vulkan layer names and their minimum versions. + , instanceLayers :: HashMap ByteString Word32 + -- | Required Vulkan instance extension names and their minimum versions, + -- collected by the Vulkan layer name they come from. + , instanceExtensions :: HashMap (Maybe ByteString) (HashMap ByteString Word32) + -- | Required Vulkan device extension names and their minimum versions, + -- collected by the Vulkan layer name they come from. + , deviceExtensions :: HashMap (Maybe ByteString) (HashMap ByteString Word32) + -- | Required Vulkan instance settings ('InstanceCreateInfo' structure extension chain). + , neededSettings :: Chain setts + -- | Returns all the required features that were not enabled in 'PhysicalDeviceFeatures2'. + , missingFeatures :: PhysicalDeviceFeatures2 feats -> HashSet ByteString + -- | All required features, to be used in 'DeviceCreateInfo'. + , neededFeatures :: PhysicalDeviceFeatures2 feats + -- | Returns all the required properties that were not satisfied in 'PhysicalDeviceProperties2' + , missingProperties :: PhysicalDeviceProperties2 props -> HashSet ByteString } -> Requirements @@ -153,91 +214,132 @@ requirements :: Foldable f => f Requirement -> Requirements requirements = foldr' addRequirement noRequire where noRequire :: Requirements - noRequire = Requirements @'[] @'[] (MAKE_VERSION 1 0 0) [] (const []) zero (const []) + noRequire = + Requirements @'[] @'[] @'[] + (MAKE_VERSION 1 0 0) + HashMap.empty HashMap.empty HashMap.empty + () + (const HashSet.empty) zero (const HashSet.empty) addRequirement :: Requirement -> Requirements -> Requirements - addRequirement (RequireVersion {version}) = requireVersion version - addRequirement (RequireExtension {extension}) = requireExtension extension - addRequirement (RequireFeature {..}) = do - for_ requireMinVersion requireVersion - for_ requireExtensions requireExtension + addRequirement (RequireVersion {..}) = + requireVersion version + addRequirement (RequireInstanceLayer {..}) = + requireInstanceLayer instanceLayerName instanceLayerMinVersion + addRequirement (RequireInstanceExtension {..}) = + requireInstanceExtension instanceExtensionLayerName instanceExtensionName instanceExtensionMinVersion + addRequirement (RequireDeviceExtension {..}) = + requireDeviceExtension deviceExtensionLayerName deviceExtensionName deviceExtensionMinVersion + addRequirement (RequireInstanceSetting {..}) = + requireInstanceSetting setInstanceSetting + addRequirement (RequireFeature {..}) = requireFeature featureName checkFeature enableFeature - addRequirement (RequireProperty {..}) = do - for_ requireMinVersion requireVersion - for_ requireExtensions requireExtension + addRequirement (RequireProperty {..}) = requireProperty propertyName checkProperty requireVersion :: Word32 -> Requirements -> Requirements -requireVersion ver1 req@(Requirements{version = ver2}) = req {version = max ver1 ver2} +requireVersion ver1 req@(Requirements{version = ver2}) = + req {version = max ver1 ver2} + +requireInstanceLayer :: ByteString -> Word32-> Requirements -> Requirements +requireInstanceLayer layName layVer req@(Requirements{instanceLayers = lays}) = + req {instanceLayers = HashMap.insertWith max layName layVer lays} + +requireInstanceExtension :: Maybe ByteString -> ByteString -> Word32 -> Requirements -> Requirements +requireInstanceExtension mbLayName extName extVer req@(Requirements{instanceExtensions = exts}) = + (case mbLayName of { Just layName -> requireInstanceLayer layName 0; Nothing -> id }) $ + req {instanceExtensions = HashMap.insertWith (HashMap.unionWith max) mbLayName (HashMap.singleton extName extVer) exts} -requireExtension :: ByteString -> Requirements -> Requirements -requireExtension ext req@(Requirements{extensions = exts}) = req {extensions = ext:exts} +requireDeviceExtension :: Maybe ByteString -> ByteString -> Word32 -> Requirements -> Requirements +requireDeviceExtension mbLayName extName extVer req@(Requirements{deviceExtensions = exts}) = + (case mbLayName of { Just layName -> requireInstanceLayer layName 0; Nothing -> id }) $ + req {deviceExtensions = HashMap.insertWith (HashMap.unionWith max) mbLayName (HashMap.singleton extName extVer) exts} + +requireInstanceSetting :: forall struct + . ( KnownInstanceSettingStruct struct ) + => (struct -> struct) -> Requirements -> Requirements +requireInstanceSetting setSetting + ( Requirements ver lays instExts devExts + (setts :: Chain setts) + missingFeats enabledFeats missingProps + ) + = case has @setts @struct proxy# of + Just (_, modifySettingStruct) + | let + setts' :: Chain setts + setts' = modifySettingStruct setSetting setts + -> Requirements ver lays instExts devExts setts' missingFeats enabledFeats missingProps + Nothing + | let + setts' :: Chain (struct ': setts) + setts' = (setSetting zero, setts) + -> Requirements ver lays instExts devExts setts' missingFeats enabledFeats missingProps requireFeature :: forall struct - . ( KnownFeature struct ) + . ( KnownFeatureStruct struct ) => ByteString -> (struct -> Bool) -> (struct -> struct) -> Requirements -> Requirements requireFeature featName checkFeat enableFeat - ( Requirements ver exts - (missingFeats :: PhysicalDeviceFeatures2 feats -> [ByteString]) + ( Requirements ver lays instExts devExts setts + (missingFeats :: PhysicalDeviceFeatures2 feats -> HashSet ByteString) enabledFeats@(PhysicalDeviceFeatures2{next=nextEnabledFeats,features=prevEnabledFeats}) missingProps ) - = case sFeature @struct of - BasicFeature -> + = case sFeatureStruct @struct of + BasicFeatureStruct -> let - missingFeats' :: PhysicalDeviceFeatures2 feats -> [ByteString] + missingFeats' :: PhysicalDeviceFeatures2 feats -> HashSet ByteString missingFeats' feats2@(PhysicalDeviceFeatures2{features}) = - (if checkFeat features then id else (featName:)) + (if checkFeat features then id else HashSet.insert featName) (missingFeats feats2) enabledFeats' :: PhysicalDeviceFeatures2 feats enabledFeats' = enabledFeats { features = enableFeat prevEnabledFeats } - in Requirements ver exts missingFeats' enabledFeats' missingProps - ExtendedFeature + in Requirements ver lays instExts devExts setts missingFeats' enabledFeats' missingProps + ExtendedFeatureStruct | Just (getFeatureStruct, modifyFeatureStruct) <- has @feats @struct proxy# , let - missingFeats' :: PhysicalDeviceFeatures2 feats -> [ByteString] + missingFeats' :: PhysicalDeviceFeatures2 feats -> HashSet ByteString missingFeats' feats2@(PhysicalDeviceFeatures2{next}) = - (if checkFeat (getFeatureStruct next) then id else (featName:)) + (if checkFeat (getFeatureStruct next) then id else HashSet.insert featName) (missingFeats feats2) enabledFeats' :: PhysicalDeviceFeatures2 feats enabledFeats' = enabledFeats { next = modifyFeatureStruct enableFeat nextEnabledFeats } - -> Requirements ver exts missingFeats' enabledFeats' missingProps + -> Requirements ver lays instExts devExts setts missingFeats' enabledFeats' missingProps | let - missingFeats' :: PhysicalDeviceFeatures2 (struct ': feats) -> [ByteString] + missingFeats' :: PhysicalDeviceFeatures2 (struct ': feats) -> HashSet ByteString missingFeats' feats2@(PhysicalDeviceFeatures2{next=(struct,feats)}) = - (if checkFeat struct then id else (featName:)) + (if checkFeat struct then id else HashSet.insert featName) (missingFeats (feats2{next=feats})) enabledFeats' :: PhysicalDeviceFeatures2 (struct ': feats) enabledFeats' = enabledFeats { next = (enableFeat zero, nextEnabledFeats) } - -> Requirements ver exts missingFeats' enabledFeats' missingProps + -> Requirements ver lays instExts devExts setts missingFeats' enabledFeats' missingProps requireProperty :: forall struct - . ( KnownProperty struct ) + . ( KnownPropertyStruct struct ) => ByteString -> (struct -> Bool) -> Requirements -> Requirements requireProperty propName checkProp - ( Requirements ver exts missingFeats enabledFeats - (missingProps :: PhysicalDeviceProperties2 props -> [ByteString]) + ( Requirements ver lays instExts devExts setts missingFeats enabledFeats + (missingProps :: PhysicalDeviceProperties2 props -> HashSet ByteString) ) - = case sProperty @struct of - BasicProperty -> + = case sPropertyStruct @struct of + BasicPropertyStruct -> let - missingProps' :: PhysicalDeviceProperties2 props -> [ByteString] + missingProps' :: PhysicalDeviceProperties2 props -> HashSet ByteString missingProps' props2@(PhysicalDeviceProperties2{properties}) = - (if checkProp properties then id else (propName:)) + (if checkProp properties then id else HashSet.insert propName) (missingProps props2) - in Requirements ver exts missingFeats enabledFeats missingProps' + in Requirements ver lays instExts devExts setts missingFeats enabledFeats missingProps' - ExtendedProperty + ExtendedPropertyStruct | Just (getPropertyStruct,_) <- has @props @struct proxy# , let - missingProps' :: PhysicalDeviceProperties2 props -> [ByteString] + missingProps' :: PhysicalDeviceProperties2 props -> HashSet ByteString missingProps' props2@(PhysicalDeviceProperties2{next}) = - (if checkProp (getPropertyStruct next) then id else (propName:)) + (if checkProp (getPropertyStruct next) then id else HashSet.insert propName) (missingProps props2) - -> Requirements ver exts missingFeats enabledFeats missingProps' + -> Requirements ver lays instExts devExts setts missingFeats enabledFeats missingProps' | let - missingProps' :: PhysicalDeviceProperties2 (struct ': props) -> [ByteString] + missingProps' :: PhysicalDeviceProperties2 (struct ': props) -> HashSet ByteString missingProps' props2@(PhysicalDeviceProperties2{next=(struct,props)}) = - (if checkProp struct then id else (propName:)) + (if checkProp struct then id else HashSet.insert propName) (missingProps (props2{next=props})) - -> Requirements ver exts missingFeats enabledFeats missingProps' + -> Requirements ver lays instExts devExts setts missingFeats enabledFeats missingProps' From 88f09be8db376d7bb38c5ddac2aba3c8e6f82198 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 17:17:03 +0800 Subject: [PATCH 10/70] Generate SPIR-V reqs compatible with letest Requirements.hs --- generate-new/src/Render/SpecInfo.hs | 28 ++++- generate-new/src/Spec/Parse.hs | 15 ++- generate-new/src/Spec/Types.hs | 15 ++- generate-new/vk/VK/SPIRVElements.hs | 155 +++++++++++++++++++--------- 4 files changed, 150 insertions(+), 63 deletions(-) diff --git a/generate-new/src/Render/SpecInfo.hs b/generate-new/src/Render/SpecInfo.hs index 20dbe6d67..d25fe6e7b 100644 --- a/generate-new/src/Render/SpecInfo.hs +++ b/generate-new/src/Render/SpecInfo.hs @@ -1,5 +1,4 @@ -module Render.SpecInfo - where +module Render.SpecInfo where import Algebra.Graph.Relation import Algebra.Graph.ToGraph @@ -11,6 +10,7 @@ import Polysemy import Polysemy.Input import Relude hiding ( Handle ) +import qualified Data.Vector as V import Render.Element import Spec.Types @@ -31,6 +31,8 @@ data SpecInfo = SpecInfo , siAppearsInPositivePosition :: CName -> Bool , siAppearsInNegativePosition :: CName -> Bool , siGetAliases :: CName -> [CName] + , siExtensionType :: Text -> Maybe ExtensionType + , siExtensionDeps :: Text -> [Text] } instance Semigroup SpecInfo where @@ -48,6 +50,8 @@ instance Semigroup SpecInfo where , siAppearsInNegativePosition = applyBoth siAppearsInNegativePosition (liftA2 (||)) , siGetAliases = applyBoth siGetAliases (liftA2 (<>)) + , siExtensionType = first siExtensionType + , siExtensionDeps = applyBoth siExtensionDeps (liftA2 (<>)) } where first :: (SpecInfo -> (a -> Maybe b)) -> a -> Maybe b @@ -67,6 +71,8 @@ instance Monoid SpecInfo where (const False) (const False) (const []) + (const Nothing) + (const []) specSpecInfo :: Spec -> (CType -> Maybe (Int, Int)) -> SpecInfo specSpecInfo Spec {..} siTypeSize = @@ -135,6 +141,22 @@ specSpecInfo Spec {..} siTypeSize = a <- Map.lookupDefault [] n reverseAliasMap a : go a in go + siExtensionType = + let exMap = Map.fromList + [ (exName, exType) | Extension {..} <- toList specExtensions ] + in (`Map.lookup` exMap) + siExtensionDeps = + let + depMap = Map.fromList + [ (exName, V.toList exDependencies) + | Extension {..} <- toList specExtensions + ] + get n = fromMaybe mempty (Map.lookup n depMap) + close n = + let immediateDeps = get n + in concat (immediateDeps : (close <$> immediateDeps)) + in + close in SpecInfo { .. } @@ -167,7 +189,7 @@ getDisabledCommand t = ($ t) <$> inputs siIsDisabledCommand getTypeSize :: (HasErr r, HasSpecInfo r) => CType -> Sem r (Int, Int) getTypeSize t = - note ("Unable to get size for " <> show t) =<< ($ t) <$> inputs siTypeSize + note ("Unable to get size for " <> show t) . ($ t) =<< inputs siTypeSize appearsInPositivePosition :: HasSpecInfo r => CName -> Sem r Bool appearsInPositivePosition s = ($ s) <$> inputs siAppearsInPositivePosition diff --git a/generate-new/src/Spec/Parse.hs b/generate-new/src/Spec/Parse.hs index 3296e66dc..a42c51566 100644 --- a/generate-new/src/Spec/Parse.hs +++ b/generate-new/src/Spec/Parse.hs @@ -353,10 +353,17 @@ parseExtensions parseDisabled es = V.fromList <$> sequenceV where parseExtension :: Node -> P Extension parseExtension n = do - exName <- decode =<< note "extension has no name" (getAttr "name" n) - exNumber <- readAttr "number" n - exRequires <- parseRequires n - exSupported <- decode + exName <- decode =<< note "extension has no name" (getAttr "name" n) + exNumber <- readAttr "number" n + exType <- case getAttr "type" n of + Just "device" -> pure DeviceExtension + Just "instance" -> pure InstanceExtension + Just t -> + throw $ "Unhandled extension type: " <> show exName <> " " <> show t + Nothing -> pure UnknownExtensionType + exDependencies <- listAttr decode "requires" n + exRequires <- parseRequires n + exSupported <- decode =<< note "extension has no supported attr" (getAttr "supported" n) pure Extension { .. } diff --git a/generate-new/src/Spec/Types.hs b/generate-new/src/Spec/Types.hs index 878cefff4..a523e8b84 100644 --- a/generate-new/src/Spec/Types.hs +++ b/generate-new/src/Spec/Types.hs @@ -45,12 +45,17 @@ data Feature = Feature deriving (Show) data Extension = Extension - { exName :: Text - , exNumber :: Int - , exRequires :: Vector Require - , exSupported :: Text + { exName :: Text + , exNumber :: Int + , exRequires :: Vector Require + , exSupported :: Text + , exType :: ExtensionType + , exDependencies :: Vector Text } - deriving (Show) + deriving Show + +data ExtensionType = DeviceExtension | InstanceExtension | UnknownExtensionType + deriving Show data Require = Require { rComment :: Maybe Text diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs index 38aaf9a4f..695b06e1c 100644 --- a/generate-new/vk/VK/SPIRVElements.hs +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -7,6 +7,7 @@ module VK.SPIRVElements import CType ( CType(TypeName) ) import Data.Bits import Data.Foldable +import Data.List.Extra ( nubOrd ) import qualified Data.Text as T import Data.Text.Prettyprint.Doc import Data.Vector ( Vector ) @@ -26,12 +27,15 @@ import Language.Haskell.TH ( Type(ConT) import Polysemy.Input import Relude import Render.Element -import Render.SpecInfo ( HasSpecInfo ) +import Render.SpecInfo ( HasSpecInfo + , SpecInfo(..) + ) import Render.Type ( cToHsType ) import Render.Type.Preserve ( Preserve(DoNotPreserve) ) import Spec.Types import Text.InterpolatedString.Perl6.Unindented import VkModulePrefix +import qualified Prelude renderSPIRVElements :: (HasErr r, HasRenderParams r, HasSpecInfo r) @@ -70,7 +74,9 @@ renderSPIRVThing -> Sem r () renderSPIRVThing funName name reqs xs = do let case' x = do - reqs' <- traverse renderReq (V.toList (reqs x)) + let mergeReqs = Prelude.head -- TODO: this is probably wrong! discarding the + -- other reqs + reqs' <- mergeReqs <$> traverse renderReq (V.toList (reqs x)) pure $ viaShow (name x) <+> "->" <+> list reqs' cases <- (<> ["_ -> []"]) <$> traverse case' (V.toList xs) tellImport ''ByteString @@ -84,15 +90,12 @@ renderSPIRVThing funName name reqs xs = do renderReq :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) => SPIRVRequirement - -> Sem r (Doc ()) + -> Sem r [Doc ()] renderReq = \case - SPIRVReqVersion v -> versionReq v - SPIRVReqExtension p -> do - extensionNamePattern p >>= \case - Left v -> versionReq v - Right p' -> do - tellImportWithAll (mkName "Vulkan.Requirements.Requirement") - pure $ "RequireExtension" <+> p' + SPIRVReqVersion v -> pure <$> versionReq v + + SPIRVReqExtension p -> minVersionAndExtensionsReqs (V.singleton p) + SPIRVReqFeature s f rs -> do RenderParams {..} <- input tellImportWithAll (mkName "Vulkan.Requirements.Requirement") @@ -100,22 +103,23 @@ renderReq = \case sTy <- cToHsType DoNotPreserve (TypeName s) -- TODO: this is pretty lazy, import the accessors properly traverse_ tellImportWithAll (allTypeNames sTy) - checkTDoc <- renderType (sTy ~> ConT ''Bool) - sTyDoc <- renderType sTy - otherSetters <- minVersionAndExtensionsSetters rs + checkTDoc <- renderType (sTy ~> ConT ''Bool) + sTyDoc <- renderType sTy + otherReqs <- minVersionAndExtensionsReqs rs let featureMemberName = mkMemberName f let xs = - [ "featureName =" <+> viaShow f - , "checkFeature =" <+> pretty featureMemberName <+> "::" <+> checkTDoc - , "enableFeature =" - <+> "\\f ->" - <+> "f" - <> braces (pretty featureMemberName <+> "= True") - <+> "::" - <+> sTyDoc - ] - <> otherSetters - pure $ "RequireFeature" <> encloseSep "{" "}" ", " xs + [ ("featureName" , viaShow f) + , ("checkFeature", pretty featureMemberName <+> "::" <+> checkTDoc) + , ( "enableFeature" + , "\\f ->" + <+> "f" + <> braces (pretty featureMemberName <+> "= True") + <+> "::" + <+> sTyDoc + ) + ] + pure $ "RequireFeature" <> braceAssignmentList xs : otherReqs + SPIRVReqProperty p m v rs -> do RenderParams {..} <- input tellImportWithAll (mkName "Vulkan.Requirements.Requirement") @@ -126,9 +130,9 @@ renderReq = \case sTyDoc <- renderType sTy let propertyMemberName = mkMemberName m propertyValueName = mkPatternName v - otherSetters <- minVersionAndExtensionsSetters rs + otherReqs <- minVersionAndExtensionsReqs rs -- TODO, do this properly - checker <- if + checker <- if | v == "VK_TRUE" -> pure $ "\\p ->" <+> pretty propertyMemberName <+> parens ("p ::" <+> sTyDoc) @@ -150,43 +154,84 @@ renderReq = \case <+> "==" <+> pretty propertyMemberName <+> parens ("p ::" <+> sTyDoc) - let xs = - ["propertyName =" <+> viaShow p, "checkProperty =" <+> checker] - <> otherSetters - pure $ "RequireProperty" <> encloseSep "{" "}" ", " xs + let xs = [("propertyName", viaShow p), ("checkProperty", checker)] + pure $ "RequireProperty" <> braceAssignmentList xs : otherReqs -minVersionAndExtensionsSetters +minVersionAndExtensionsReqs :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) => Vector Text -> Sem r [Doc ()] -minVersionAndExtensionsSetters rs = do - (minVersions, extensionNames) <- - partitionEithers . V.toList <$> traverse extensionNamePattern rs - minVersionDoc <- case minVersions of - [] -> pure "Nothing" - vs -> ("Just $" <+>) <$> versionDoc (maximum vs) +minVersionAndExtensionsReqs rs = do + SpecInfo {..} <- input + let dependencies = nubOrd $ toList rs <> concatMap siExtensionDeps rs + (minVersions, instanceExtensions, deviceExtensions) <- + foldMap + (\case + RequireVersion v -> ([v], [], []) + RequireInstanceExtension e v -> ([], [(e, v)], []) + RequireDeviceExtension e v -> ([], [], [(e, v)]) + ) + <$> traverse extensionNamePattern dependencies + + v <- case minVersions of + [] -> pure Nothing + xs -> Just <$> versionReq (maximum xs) + pure - [ "requireMinVersion =" <+> minVersionDoc - , "requireExtensions =" <+> viaShow extensionNames - ] + $ maybeToList v + <> [ "RequireInstanceExtension" <> braceAssignmentList + [ ("instanceExtensionLayerName" , "Nothing") + , ("instanceExtensionName" , e) + , ("instanceExtensionMinVersion", v) + ] + | (e, v) <- instanceExtensions + ] + <> [ "RequireDeviceExtension" <> braceAssignmentList + [ ("deviceExtensionLayerName" , "Nothing") + , ("deviceExtensionName" , e) + , ("deviceExtensionMinVersion", v) + ] + | (e, v) <- deviceExtensions + ] extensionNamePattern - :: (HasRenderElem r, HasRenderParams r) + :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) => Text - -> Sem r (Either Version (Doc ())) + -> Sem r RequireType extensionNamePattern p = do RenderParams {..} <- input + SpecInfo {..} <- input case parseVersion p of - Just v -> pure . Left $ v + Just v -> pure . RequireVersion $ v Nothing -> do - let nameName = case p of - -- TODO: Handle these properly - "VK_INTEL_shader_integer_functions2" -> - CName "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME" - _ -> CName $ T.toUpper p <> "_EXTENSION_NAME" - let p' = mkPatternName nameName - tellImport p' - pure . Right $ pretty p' + -- TODO: do this properly lol + let patternPrefix = if + | p == "VK_KHR_maintenance2" -> "VK_KHR_MAINTENANCE2" + | p == "VK_NV_viewport_array2" -> "VK_NV_VIEWPORT_ARRAY2" + | "2" `T.isSuffixOf` p -> T.toUpper (T.init p) <> "_2" + | otherwise -> T.toUpper p + nameName = CName $ patternPrefix <> "_EXTENSION_NAME" + versionName = CName $ patternPrefix <> "_SPEC_VERSION" + let namePattern = mkPatternName nameName + versionPattern = mkPatternName versionName + tellImport namePattern + tellImport versionPattern + case siExtensionType p of + Just DeviceExtension -> pure $ RequireDeviceExtension + (pretty namePattern) + (pretty versionPattern) + Just InstanceExtension -> pure $ RequireInstanceExtension + (pretty namePattern) + (pretty versionPattern) + Just UnknownExtensionType -> + throw $ "Dependency on extension of unknown type: " <> show p + Nothing -> throw $ "Dependency on unknown extension" <> show p + +data RequireType + = RequireVersion Version + | RequireInstanceExtension (Doc ()) (Doc ()) + | RequireDeviceExtension (Doc ()) (Doc ()) + -- ^ _EXTENSION_NAME and _SPEC_VERSION versionReq :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) @@ -225,3 +270,11 @@ bespokeStuff = do (.&&.) :: Bits a => a -> a -> Bool x .&&. y = (x .&. y) /= zeroBits |] + + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +braceAssignmentList :: [(Doc ann, Doc ann)] -> Doc ann +braceAssignmentList = encloseSep "{" "}" ", " . fmap (\(l, r) -> l <+> "=" <+> r) From 16645663caa90e0927ac117b13af2b2d92f7e157 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 17:17:22 +0800 Subject: [PATCH 11/70] regenerate --- package.yaml | 1 + src/Vulkan/SPIRVRequirements.hs | 2206 +++++++++++++++++++++---------- vulkan.cabal | 1 + 3 files changed, 1528 insertions(+), 680 deletions(-) diff --git a/package.yaml b/package.yaml index 91fc0035d..f6aae3830 100644 --- a/package.yaml +++ b/package.yaml @@ -20,6 +20,7 @@ library: - base <5 - bytestring - transformers + - unordered-containers - vector when: - condition: os(windows) diff --git a/src/Vulkan/SPIRVRequirements.hs b/src/Vulkan/SPIRVRequirements.hs index 279ddf004..14f648d60 100644 --- a/src/Vulkan/SPIRVRequirements.hs +++ b/src/Vulkan/SPIRVRequirements.hs @@ -53,62 +53,134 @@ import Vulkan.Core12 (PhysicalDeviceVulkan12Features(..)) import Vulkan.Core12 (PhysicalDeviceVulkan12Properties) import Vulkan.Core12 (PhysicalDeviceVulkan12Properties(..)) import Vulkan.Extensions.VK_AMD_gcn_shader (pattern AMD_GCN_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gcn_shader (pattern AMD_GCN_SHADER_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_gpu_shader_half_float (pattern AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gpu_shader_half_float (pattern AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_gpu_shader_int16 (pattern AMD_GPU_SHADER_INT16_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_gpu_shader_int16 (pattern AMD_GPU_SHADER_INT16_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_shader_ballot (pattern AMD_SHADER_BALLOT_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_ballot (pattern AMD_SHADER_BALLOT_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_shader_explicit_vertex_parameter (pattern AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_explicit_vertex_parameter (pattern AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_shader_fragment_mask (pattern AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_fragment_mask (pattern AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_shader_image_load_store_lod (pattern AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_image_load_store_lod (pattern AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_shader_trinary_minmax (pattern AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_trinary_minmax (pattern AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION) import Vulkan.Extensions.VK_AMD_texture_gather_bias_lod (pattern AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_texture_gather_bias_lod (pattern AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_buffer_device_address (pattern EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_buffer_device_address (pattern EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_descriptor_indexing (pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_descriptor_indexing (pattern EXT_DESCRIPTOR_INDEXING_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_fragment_density_map (pattern EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_density_map (pattern EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (pattern EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (pattern EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_post_depth_coverage (pattern EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_post_depth_coverage (pattern EXT_POST_DEPTH_COVERAGE_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_atomic_float (pattern EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_atomic_float (pattern EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (pattern EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (pattern EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (pattern EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (pattern EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_stencil_export (pattern EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_stencil_export (pattern EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_subgroup_ballot (pattern EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_subgroup_ballot (pattern EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_subgroup_vote (pattern EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_subgroup_vote (pattern EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_shader_viewport_index_layer (pattern EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_viewport_index_layer (pattern EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION) import Vulkan.Extensions.VK_EXT_transform_feedback (pattern EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_transform_feedback (pattern EXT_TRANSFORM_FEEDBACK_SPEC_VERSION) import Vulkan.Extensions.VK_GOOGLE_decorate_string (pattern GOOGLE_DECORATE_STRING_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_decorate_string (pattern GOOGLE_DECORATE_STRING_SPEC_VERSION) import Vulkan.Extensions.VK_GOOGLE_hlsl_functionality1 (pattern GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_hlsl_functionality1 (pattern GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION) import Vulkan.Extensions.VK_GOOGLE_user_type (pattern GOOGLE_USER_TYPE_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_user_type (pattern GOOGLE_USER_TYPE_SPEC_VERSION) import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (pattern INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (pattern INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_create_renderpass2 (pattern KHR_CREATE_RENDERPASS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_create_renderpass2 (pattern KHR_CREATE_RENDERPASS_2_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_deferred_host_operations (pattern KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_deferred_host_operations (pattern KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_device_group_creation (pattern KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_device_group_creation (pattern KHR_DEVICE_GROUP_CREATION_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_device_group (pattern KHR_DEVICE_GROUP_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_device_group (pattern KHR_DEVICE_GROUP_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_fragment_shading_rate (pattern KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_fragment_shading_rate (pattern KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_get_memory_requirements2 (pattern KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_get_memory_requirements2 (pattern KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 (pattern KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 (pattern KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_maintenance2 (pattern KHR_MAINTENANCE2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_maintenance2 (pattern KHR_MAINTENANCE2_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_maintenance3 (pattern KHR_MAINTENANCE3_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_maintenance3 (pattern KHR_MAINTENANCE3_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_pipeline_library (pattern KHR_PIPELINE_LIBRARY_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_pipeline_library (pattern KHR_PIPELINE_LIBRARY_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_draw_parameters (pattern KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_draw_parameters (pattern KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_float16_int8 (pattern KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float16_int8 (pattern KHR_SHADER_FLOAT16_INT8_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_float_controls (pattern KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float_controls (pattern KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_vulkan_memory_model (pattern KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_vulkan_memory_model (pattern KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION) import Vulkan.Version (pattern MAKE_VERSION) import Vulkan.Extensions.VK_NVX_multiview_per_view_attributes (pattern NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NVX_multiview_per_view_attributes (pattern NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION) import Vulkan.Extensions.VK_NV_compute_shader_derivatives (pattern NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_compute_shader_derivatives (pattern NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION) import Vulkan.Extensions.VK_NV_cooperative_matrix (pattern NV_COOPERATIVE_MATRIX_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_cooperative_matrix (pattern NV_COOPERATIVE_MATRIX_SPEC_VERSION) import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (pattern NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (pattern NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION) import Vulkan.Extensions.VK_NV_geometry_shader_passthrough (pattern NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_geometry_shader_passthrough (pattern NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION) import Vulkan.Extensions.VK_NV_mesh_shader (pattern NV_MESH_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_mesh_shader (pattern NV_MESH_SHADER_SPEC_VERSION) import Vulkan.Extensions.VK_NV_ray_tracing (pattern NV_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_ray_tracing (pattern NV_RAY_TRACING_SPEC_VERSION) import Vulkan.Extensions.VK_NV_sample_mask_override_coverage (pattern NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_sample_mask_override_coverage (pattern NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION) import Vulkan.Extensions.VK_NV_shader_image_footprint (pattern NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_image_footprint (pattern NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION) import Vulkan.Extensions.VK_NV_shader_sm_builtins (pattern NV_SHADER_SM_BUILTINS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_sm_builtins (pattern NV_SHADER_SM_BUILTINS_SPEC_VERSION) import Vulkan.Extensions.VK_NV_shader_subgroup_partitioned (pattern NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_subgroup_partitioned (pattern NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION) import Vulkan.Extensions.VK_NV_shading_rate_image (pattern NV_SHADING_RATE_IMAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shading_rate_image (pattern NV_SHADING_RATE_IMAGE_SPEC_VERSION) import Vulkan.Extensions.VK_NV_viewport_array2 (pattern NV_VIEWPORT_ARRAY2_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_viewport_array2 (pattern NV_VIEWPORT_ARRAY2_SPEC_VERSION) import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBGROUP_FEATURE_ARITHMETIC_BIT)) import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlags) @@ -133,65 +205,401 @@ x .&&. y = (x .&. y) /= zeroBits spirvExtensionRequirements :: ByteString -> [Requirement] spirvExtensionRequirements = \case - "SPV_KHR_variable_pointers" -> - [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_VARIABLE_POINTERS_EXTENSION_NAME] - "SPV_AMD_shader_explicit_vertex_parameter" -> [RequireExtension AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME] - "SPV_AMD_gcn_shader" -> [RequireExtension AMD_GCN_SHADER_EXTENSION_NAME] - "SPV_AMD_gpu_shader_half_float" -> [RequireExtension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME] - "SPV_AMD_gpu_shader_int16" -> [RequireExtension AMD_GPU_SHADER_INT16_EXTENSION_NAME] - "SPV_AMD_shader_ballot" -> [RequireExtension AMD_SHADER_BALLOT_EXTENSION_NAME] - "SPV_AMD_shader_fragment_mask" -> [RequireExtension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] - "SPV_AMD_shader_image_load_store_lod" -> [RequireExtension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] - "SPV_AMD_shader_trinary_minmax" -> [RequireExtension AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME] - "SPV_AMD_texture_gather_bias_lod" -> [RequireExtension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] - "SPV_KHR_shader_draw_parameters" -> - [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME] - "SPV_KHR_8bit_storage" -> [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_8BIT_STORAGE_EXTENSION_NAME] - "SPV_KHR_16bit_storage" -> [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_16BIT_STORAGE_EXTENSION_NAME] - "SPV_KHR_shader_clock" -> [RequireExtension KHR_SHADER_CLOCK_EXTENSION_NAME] - "SPV_KHR_float_controls" -> - [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - "SPV_KHR_storage_buffer_storage_class" -> - [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] - "SPV_KHR_post_depth_coverage" -> [RequireExtension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] - "SPV_EXT_shader_stencil_export" -> [RequireExtension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] - "SPV_KHR_shader_ballot" -> [RequireExtension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] - "SPV_KHR_subgroup_vote" -> [RequireExtension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] - "SPV_NV_sample_mask_override_coverage" -> [RequireExtension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] - "SPV_NV_geometry_shader_passthrough" -> [RequireExtension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] - "SPV_NV_mesh_shader" -> [RequireExtension NV_MESH_SHADER_EXTENSION_NAME] - "SPV_NV_viewport_array2" -> [RequireExtension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] - "SPV_NV_shader_subgroup_partitioned" -> [RequireExtension NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] - "SPV_EXT_shader_viewport_index_layer" -> - [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] - "SPV_NVX_multiview_per_view_attributes" -> [RequireExtension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] - "SPV_EXT_descriptor_indexing" -> - [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - "SPV_KHR_vulkan_memory_model" -> - [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] - "SPV_NV_compute_shader_derivatives" -> [RequireExtension NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] - "SPV_NV_fragment_shader_barycentric" -> [RequireExtension NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] - "SPV_NV_shader_image_footprint" -> [RequireExtension NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] - "SPV_NV_shading_rate" -> [RequireExtension NV_SHADING_RATE_IMAGE_EXTENSION_NAME] - "SPV_NV_ray_tracing" -> [RequireExtension NV_RAY_TRACING_EXTENSION_NAME] - "SPV_KHR_ray_tracing" -> [RequireExtension KHR_RAY_TRACING_EXTENSION_NAME] - "SPV_KHR_ray_query" -> [RequireExtension KHR_RAY_TRACING_EXTENSION_NAME] - "SPV_GOOGLE_hlsl_functionality1" -> [RequireExtension GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME] - "SPV_GOOGLE_user_type" -> [RequireExtension GOOGLE_USER_TYPE_EXTENSION_NAME] - "SPV_GOOGLE_decorate_string" -> [RequireExtension GOOGLE_DECORATE_STRING_EXTENSION_NAME] - "SPV_EXT_fragment_invocation_density" -> [RequireExtension EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] - "SPV_KHR_physical_storage_buffer" -> - [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - "SPV_EXT_physical_storage_buffer" -> [RequireExtension EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - "SPV_NV_cooperative_matrix" -> [RequireExtension NV_COOPERATIVE_MATRIX_EXTENSION_NAME] - "SPV_NV_shader_sm_builtins" -> [RequireExtension NV_SHADER_SM_BUILTINS_EXTENSION_NAME] - "SPV_EXT_fragment_shader_interlock" -> [RequireExtension EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - "SPV_EXT_demote_to_helper_invocation" -> [RequireExtension EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] - "SPV_KHR_fragment_shading_rate" -> [RequireExtension KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - "SPV_KHR_non_semantic_info" -> [RequireExtension KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME] - "SPV_EXT_shader_image_int64" -> [RequireExtension EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] - "SPV_KHR_terminate_invocation" -> [RequireExtension KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME] - _ -> [] + "SPV_KHR_variable_pointers" -> [RequireVersion $ MAKE_VERSION 1 1 0] + "SPV_AMD_shader_explicit_vertex_parameter" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION + } + ] + "SPV_AMD_gcn_shader" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_GCN_SHADER_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_GCN_SHADER_SPEC_VERSION + } + ] + "SPV_AMD_gpu_shader_half_float" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION + } + ] + "SPV_AMD_gpu_shader_int16" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_GPU_SHADER_INT16_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_GPU_SHADER_INT16_SPEC_VERSION + } + ] + "SPV_AMD_shader_ballot" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_BALLOT_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_BALLOT_SPEC_VERSION + } + ] + "SPV_AMD_shader_fragment_mask" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION + } + ] + "SPV_AMD_shader_image_load_store_lod" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION + } + ] + "SPV_AMD_shader_trinary_minmax" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION + } + ] + "SPV_AMD_texture_gather_bias_lod" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION + } + ] + "SPV_KHR_shader_draw_parameters" -> [RequireVersion $ MAKE_VERSION 1 1 0] + "SPV_KHR_8bit_storage" -> [RequireVersion $ MAKE_VERSION 1 2 0] + "SPV_KHR_16bit_storage" -> [RequireVersion $ MAKE_VERSION 1 1 0] + "SPV_KHR_shader_clock" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_CLOCK_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_CLOCK_SPEC_VERSION + } + ] + "SPV_KHR_float_controls" -> [RequireVersion $ MAKE_VERSION 1 2 0] + "SPV_KHR_storage_buffer_storage_class" -> [RequireVersion $ MAKE_VERSION 1 1 0] + "SPV_KHR_post_depth_coverage" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_POST_DEPTH_COVERAGE_SPEC_VERSION + } + ] + "SPV_EXT_shader_stencil_export" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION + } + ] + "SPV_KHR_shader_ballot" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION + } + ] + "SPV_KHR_subgroup_vote" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION + } + ] + "SPV_NV_sample_mask_override_coverage" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION + } + ] + "SPV_NV_geometry_shader_passthrough" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME + , deviceExtensionMinVersion = NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION + } + ] + "SPV_NV_mesh_shader" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_MESH_SHADER_EXTENSION_NAME + , deviceExtensionMinVersion = NV_MESH_SHADER_SPEC_VERSION + } + ] + "SPV_NV_viewport_array2" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_VIEWPORT_ARRAY2_EXTENSION_NAME + , deviceExtensionMinVersion = NV_VIEWPORT_ARRAY2_SPEC_VERSION + } + ] + "SPV_NV_shader_subgroup_partitioned" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION + } + ] + "SPV_EXT_shader_viewport_index_layer" -> [RequireVersion $ MAKE_VERSION 1 2 0] + "SPV_NVX_multiview_per_view_attributes" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME + , deviceExtensionMinVersion = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MULTIVIEW_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION + } + ] + "SPV_EXT_descriptor_indexing" -> [RequireVersion $ MAKE_VERSION 1 2 0] + "SPV_KHR_vulkan_memory_model" -> [RequireVersion $ MAKE_VERSION 1 2 0] + "SPV_NV_compute_shader_derivatives" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME + , deviceExtensionMinVersion = NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION + } + ] + "SPV_NV_fragment_shader_barycentric" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME + , deviceExtensionMinVersion = NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION + } + ] + "SPV_NV_shader_image_footprint" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION + } + ] + "SPV_NV_shading_rate" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADING_RATE_IMAGE_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADING_RATE_IMAGE_SPEC_VERSION + } + ] + "SPV_NV_ray_tracing" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = NV_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } + ] + "SPV_KHR_ray_tracing" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } + ] + "SPV_KHR_ray_query" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } + ] + "SPV_GOOGLE_hlsl_functionality1" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME + , deviceExtensionMinVersion = GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION + } + ] + "SPV_GOOGLE_user_type" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = GOOGLE_USER_TYPE_EXTENSION_NAME + , deviceExtensionMinVersion = GOOGLE_USER_TYPE_SPEC_VERSION + } + ] + "SPV_GOOGLE_decorate_string" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = GOOGLE_DECORATE_STRING_EXTENSION_NAME + , deviceExtensionMinVersion = GOOGLE_DECORATE_STRING_SPEC_VERSION + } + ] + "SPV_EXT_fragment_invocation_density" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION + } + ] + "SPV_KHR_physical_storage_buffer" -> [RequireVersion $ MAKE_VERSION 1 2 0] + "SPV_EXT_physical_storage_buffer" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } + ] + "SPV_NV_cooperative_matrix" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_COOPERATIVE_MATRIX_EXTENSION_NAME + , deviceExtensionMinVersion = NV_COOPERATIVE_MATRIX_SPEC_VERSION + } + ] + "SPV_NV_shader_sm_builtins" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADER_SM_BUILTINS_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADER_SM_BUILTINS_SPEC_VERSION + } + ] + "SPV_EXT_fragment_shader_interlock" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION + } + ] + "SPV_EXT_demote_to_helper_invocation" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION + } + ] + "SPV_KHR_fragment_shading_rate" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_CREATE_RENDERPASS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_CREATE_RENDERPASS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MULTIVIEW_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE2_SPEC_VERSION + } + ] + "SPV_KHR_non_semantic_info" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION + } + ] + "SPV_EXT_shader_image_int64" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION + } + ] + "SPV_KHR_terminate_invocation" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION + } + ] + _ -> [] spirvCapabilityRequirements :: ByteString -> [Requirement] spirvCapabilityRequirements = \case @@ -205,921 +613,1359 @@ spirvCapabilityRequirements = \case "ImageQuery" -> [RequireVersion $ MAKE_VERSION 1 0 0] "DerivativeControl" -> [RequireVersion $ MAKE_VERSION 1 0 0] "Geometry" -> - [ RequireFeature { featureName = "geometryShader" - , checkFeature = geometryShader :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { geometryShader = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "geometryShader" + , checkFeature = geometryShader :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { geometryShader = True } :: PhysicalDeviceFeatures } ] "Tessellation" -> - [ RequireFeature { featureName = "tessellationShader" - , checkFeature = tessellationShader :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { tessellationShader = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "tessellationShader" + , checkFeature = tessellationShader :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { tessellationShader = True } :: PhysicalDeviceFeatures } ] "Float64" -> - [ RequireFeature { featureName = "shaderFloat64" - , checkFeature = shaderFloat64 :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderFloat64 = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderFloat64" + , checkFeature = shaderFloat64 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderFloat64 = True } :: PhysicalDeviceFeatures } ] "Int64" -> - [ RequireFeature { featureName = "shaderInt64" - , checkFeature = shaderInt64 :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderInt64 = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderInt64" + , checkFeature = shaderInt64 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderInt64 = True } :: PhysicalDeviceFeatures } ] "Int64Atomics" -> - [ RequireFeature { featureName = "shaderBufferInt64Atomics" - , checkFeature = shaderBufferInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderBufferInt64Atomics = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] - } - , RequireFeature { featureName = "shaderSharedInt64Atomics" - , checkFeature = shaderSharedInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderSharedInt64Atomics = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME] + [ RequireFeature { featureName = "shaderBufferInt64Atomics" + , checkFeature = shaderBufferInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderBufferInt64Atomics = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_ATOMIC_INT64_SPEC_VERSION + } ] "AtomicFloat32AddEXT" -> [ RequireFeature - { featureName = "shaderBufferFloat32AtomicAdd" - , checkFeature = shaderBufferFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + { featureName = "shaderBufferFloat32AtomicAdd" + , checkFeature = shaderBufferFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool , enableFeature = \f -> f { shaderBufferFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - } - , RequireFeature - { featureName = "shaderSharedFloat32AtomicAdd" - , checkFeature = shaderSharedFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool - , enableFeature = \f -> f { shaderSharedFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - } - , RequireFeature - { featureName = "shaderImageFloat32AtomicAdd" - , checkFeature = shaderImageFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool - , enableFeature = \f -> f { shaderImageFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - } - , RequireFeature - { featureName = "sparseImageFloat32AtomicAdd" - , checkFeature = sparseImageFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool - , enableFeature = \f -> f { sparseImageFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION + } ] "AtomicFloat64AddEXT" -> [ RequireFeature - { featureName = "shaderBufferFloat64AtomicAdd" - , checkFeature = shaderBufferFloat64AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool + { featureName = "shaderBufferFloat64AtomicAdd" + , checkFeature = shaderBufferFloat64AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool , enableFeature = \f -> f { shaderBufferFloat64AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] - } - , RequireFeature - { featureName = "shaderSharedFloat64AtomicAdd" - , checkFeature = shaderSharedFloat64AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool - , enableFeature = \f -> f { shaderSharedFloat64AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION + } ] "Int64ImageEXT" -> [ RequireFeature - { featureName = "shaderImageInt64Atomics" - , checkFeature = shaderImageInt64Atomics :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT -> Bool - , enableFeature = \f -> f { shaderImageInt64Atomics = True } :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME] - } + { featureName = "shaderImageInt64Atomics" + , checkFeature = shaderImageInt64Atomics :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT -> Bool + , enableFeature = \f -> f { shaderImageInt64Atomics = True } :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION + } ] "Int16" -> - [ RequireFeature { featureName = "shaderInt16" - , checkFeature = shaderInt16 :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderInt16 = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderInt16" + , checkFeature = shaderInt16 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderInt16 = True } :: PhysicalDeviceFeatures } ] "TessellationPointSize" -> [ RequireFeature - { featureName = "shaderTessellationAndGeometryPointSize" - , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + { featureName = "shaderTessellationAndGeometryPointSize" + , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures } ] "GeometryPointSize" -> [ RequireFeature - { featureName = "shaderTessellationAndGeometryPointSize" - , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + { featureName = "shaderTessellationAndGeometryPointSize" + , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures } ] "ImageGatherExtended" -> - [ RequireFeature { featureName = "shaderImageGatherExtended" - , checkFeature = shaderImageGatherExtended :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderImageGatherExtended = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderImageGatherExtended" + , checkFeature = shaderImageGatherExtended :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderImageGatherExtended = True } :: PhysicalDeviceFeatures } ] "StorageImageMultisample" -> - [ RequireFeature { featureName = "shaderStorageImageMultisample" - , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderStorageImageMultisample" + , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures } ] "UniformBufferArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderUniformBufferArrayDynamicIndexing" - , checkFeature = shaderUniformBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderUniformBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + { featureName = "shaderUniformBufferArrayDynamicIndexing" + , checkFeature = shaderUniformBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderUniformBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] "SampledImageArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderSampledImageArrayDynamicIndexing" - , checkFeature = shaderSampledImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderSampledImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + { featureName = "shaderSampledImageArrayDynamicIndexing" + , checkFeature = shaderSampledImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderSampledImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] "StorageBufferArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderStorageBufferArrayDynamicIndexing" - , checkFeature = shaderStorageBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + { featureName = "shaderStorageBufferArrayDynamicIndexing" + , checkFeature = shaderStorageBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] "StorageImageArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderStorageImageArrayDynamicIndexing" - , checkFeature = shaderStorageImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + { featureName = "shaderStorageImageArrayDynamicIndexing" + , checkFeature = shaderStorageImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] "ClipDistance" -> - [ RequireFeature { featureName = "shaderClipDistance" - , checkFeature = shaderClipDistance :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderClipDistance = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderClipDistance" + , checkFeature = shaderClipDistance :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderClipDistance = True } :: PhysicalDeviceFeatures } ] "CullDistance" -> - [ RequireFeature { featureName = "shaderCullDistance" - , checkFeature = shaderCullDistance :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderCullDistance = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderCullDistance" + , checkFeature = shaderCullDistance :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderCullDistance = True } :: PhysicalDeviceFeatures } ] "ImageCubeArray" -> - [ RequireFeature { featureName = "imageCubeArray" - , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "imageCubeArray" + , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures } ] "SampleRateShading" -> - [ RequireFeature { featureName = "sampleRateShading" - , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "sampleRateShading" + , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures } ] "SparseResidency" -> - [ RequireFeature { featureName = "shaderResourceResidency" - , checkFeature = shaderResourceResidency :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderResourceResidency = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderResourceResidency" + , checkFeature = shaderResourceResidency :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderResourceResidency = True } :: PhysicalDeviceFeatures } ] "MinLod" -> - [ RequireFeature { featureName = "shaderResourceMinLod" - , checkFeature = shaderResourceMinLod :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderResourceMinLod = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderResourceMinLod" + , checkFeature = shaderResourceMinLod :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderResourceMinLod = True } :: PhysicalDeviceFeatures } ] "SampledCubeArray" -> - [ RequireFeature { featureName = "imageCubeArray" - , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "imageCubeArray" + , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures } ] "ImageMSArray" -> - [ RequireFeature { featureName = "shaderStorageImageMultisample" - , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "shaderStorageImageMultisample" + , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures } ] "StorageImageExtendedFormats" -> [RequireVersion $ MAKE_VERSION 1 0 0] "InterpolationFunction" -> - [ RequireFeature { featureName = "sampleRateShading" - , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "sampleRateShading" + , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures } ] "StorageImageReadWithoutFormat" -> - [ RequireFeature { featureName = "shaderStorageImageReadWithoutFormat" - , checkFeature = shaderStorageImageReadWithoutFormat :: PhysicalDeviceFeatures -> Bool + [ RequireFeature { featureName = "shaderStorageImageReadWithoutFormat" + , checkFeature = shaderStorageImageReadWithoutFormat :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderStorageImageReadWithoutFormat = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] } ] "StorageImageWriteWithoutFormat" -> - [ RequireFeature { featureName = "shaderStorageImageWriteWithoutFormat" - , checkFeature = shaderStorageImageWriteWithoutFormat :: PhysicalDeviceFeatures -> Bool + [ RequireFeature { featureName = "shaderStorageImageWriteWithoutFormat" + , checkFeature = shaderStorageImageWriteWithoutFormat :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderStorageImageWriteWithoutFormat = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] } ] "MultiViewport" -> - [ RequireFeature { featureName = "multiViewport" - , checkFeature = multiViewport :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { multiViewport = True } :: PhysicalDeviceFeatures - , requireMinVersion = Nothing - , requireExtensions = [] + [ RequireFeature { featureName = "multiViewport" + , checkFeature = multiViewport :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { multiViewport = True } :: PhysicalDeviceFeatures } ] "DrawParameters" -> - [ RequireFeature { featureName = "shaderDrawParameters" - , checkFeature = shaderDrawParameters :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { shaderDrawParameters = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] + [ RequireFeature { featureName = "shaderDrawParameters" + , checkFeature = shaderDrawParameters :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { shaderDrawParameters = True } :: PhysicalDeviceVulkan11Features } - , RequireExtension KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME + , RequireVersion $ MAKE_VERSION 1 1 0 ] "MultiView" -> - [ RequireFeature { featureName = "multiview" - , checkFeature = multiview :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { multiview = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_MULTIVIEW_EXTENSION_NAME] + [ RequireFeature { featureName = "multiview" + , checkFeature = multiview :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { multiview = True } :: PhysicalDeviceVulkan11Features } - ] - "DeviceGroup" -> [RequireVersion $ MAKE_VERSION 1 1 0, RequireExtension KHR_DEVICE_GROUP_EXTENSION_NAME] + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MULTIVIEW_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION + } + ] + "DeviceGroup" -> [RequireVersion $ MAKE_VERSION 1 1 0] "VariablePointersStorageBuffer" -> [ RequireFeature - { featureName = "variablePointersStorageBuffer" - , checkFeature = variablePointersStorageBuffer :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { variablePointersStorageBuffer = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_VARIABLE_POINTERS_EXTENSION_NAME] - } + { featureName = "variablePointersStorageBuffer" + , checkFeature = variablePointersStorageBuffer :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { variablePointersStorageBuffer = True } :: PhysicalDeviceVulkan11Features + } + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_VARIABLE_POINTERS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_VARIABLE_POINTERS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "VariablePointers" -> - [ RequireFeature { featureName = "variablePointers" - , checkFeature = variablePointers :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { variablePointers = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_VARIABLE_POINTERS_EXTENSION_NAME] + [ RequireFeature { featureName = "variablePointers" + , checkFeature = variablePointers :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { variablePointers = True } :: PhysicalDeviceVulkan11Features } + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_VARIABLE_POINTERS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_VARIABLE_POINTERS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } + ] + "ShaderClockKHR" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_CLOCK_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_CLOCK_SPEC_VERSION + } + ] + "StencilExportEXT" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION + } + ] + "SubgroupBallotKHR" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION + } + ] + "SubgroupVoteKHR" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION + } + ] + "ImageReadWriteLodAMD" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION + } + ] + "ImageGatherBiasLodAMD" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION + } + ] + "FragmentMaskAMD" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME + , deviceExtensionMinVersion = AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION + } + ] + "SampleMaskOverrideCoverageNV" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION + } + ] + "GeometryShaderPassthroughNV" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME + , deviceExtensionMinVersion = NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION + } ] - "ShaderClockKHR" -> [RequireExtension KHR_SHADER_CLOCK_EXTENSION_NAME] - "StencilExportEXT" -> [RequireExtension EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME] - "SubgroupBallotKHR" -> [RequireExtension EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME] - "SubgroupVoteKHR" -> [RequireExtension EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME] - "ImageReadWriteLodAMD" -> [RequireExtension AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME] - "ImageGatherBiasLodAMD" -> [RequireExtension AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME] - "FragmentMaskAMD" -> [RequireExtension AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME] - "SampleMaskOverrideCoverageNV" -> [RequireExtension NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME] - "GeometryShaderPassthroughNV" -> [RequireExtension NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME] "ShaderViewportIndex" -> - [ RequireFeature { featureName = "shaderOutputViewportIndex" - , checkFeature = shaderOutputViewportIndex :: PhysicalDeviceVulkan12Features -> Bool + [ RequireFeature { featureName = "shaderOutputViewportIndex" + , checkFeature = shaderOutputViewportIndex :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { shaderOutputViewportIndex = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [] } + , RequireVersion $ MAKE_VERSION 1 2 0 ] "ShaderLayer" -> - [ RequireFeature { featureName = "shaderOutputLayer" - , checkFeature = shaderOutputLayer :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderOutputLayer = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [] + [ RequireFeature { featureName = "shaderOutputLayer" + , checkFeature = shaderOutputLayer :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderOutputLayer = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + ] + "ShaderViewportIndexLayerEXT" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION + } + ] + "ShaderViewportIndexLayerNV" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_VIEWPORT_ARRAY2_EXTENSION_NAME + , deviceExtensionMinVersion = NV_VIEWPORT_ARRAY2_SPEC_VERSION + } + ] + "ShaderViewportMaskNV" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_VIEWPORT_ARRAY2_EXTENSION_NAME + , deviceExtensionMinVersion = NV_VIEWPORT_ARRAY2_SPEC_VERSION + } + ] + "PerViewAttributesNV" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME + , deviceExtensionMinVersion = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MULTIVIEW_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION + } ] - "ShaderViewportIndexLayerEXT" -> [RequireExtension EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME] - "ShaderViewportIndexLayerNV" -> [RequireExtension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] - "ShaderViewportMaskNV" -> [RequireExtension NV_VIEWPORT_ARRAY2_EXTENSION_NAME] - "PerViewAttributesNV" -> [RequireExtension NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME] "StorageBuffer16BitAccess" -> - [ RequireFeature { featureName = "storageBuffer16BitAccess" - , checkFeature = storageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { storageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + [ RequireFeature { featureName = "storageBuffer16BitAccess" + , checkFeature = storageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features } + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "UniformAndStorageBuffer16BitAccess" -> [ RequireFeature - { featureName = "uniformAndStorageBuffer16BitAccess" - , checkFeature = uniformAndStorageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { uniformAndStorageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] - } + { featureName = "uniformAndStorageBuffer16BitAccess" + , checkFeature = uniformAndStorageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { uniformAndStorageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features + } + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "StoragePushConstant16" -> - [ RequireFeature { featureName = "storagePushConstant16" - , checkFeature = storagePushConstant16 :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { storagePushConstant16 = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + [ RequireFeature { featureName = "storagePushConstant16" + , checkFeature = storagePushConstant16 :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storagePushConstant16 = True } :: PhysicalDeviceVulkan11Features } + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "StorageInputOutput16" -> - [ RequireFeature { featureName = "storageInputOutput16" - , checkFeature = storageInputOutput16 :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { storageInputOutput16 = True } :: PhysicalDeviceVulkan11Features - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [KHR_16BIT_STORAGE_EXTENSION_NAME] + [ RequireFeature { featureName = "storageInputOutput16" + , checkFeature = storageInputOutput16 :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storageInputOutput16 = True } :: PhysicalDeviceVulkan11Features } + , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "GroupNonUniform" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_BASIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_BASIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformVote" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_VOTE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_VOTE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformArithmetic" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_ARITHMETIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_ARITHMETIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformBallot" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_BALLOT_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_BALLOT_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformShuffle" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_SHUFFLE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_SHUFFLE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformShuffleRelative" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformClustered" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_CLUSTERED_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_CLUSTERED_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformQuad" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_QUAD_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 1 0 - , requireExtensions = [] - } + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_QUAD_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireVersion $ MAKE_VERSION 1 1 0 ] "GroupNonUniformPartitionedNV" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan11Properties" - , checkProperty = \p -> - SUBGROUP_FEATURE_PARTITIONED_BIT_NV .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) - , requireMinVersion = Nothing - , requireExtensions = [NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME] - } - ] - "SampleMaskPostDepthCoverage" -> [RequireExtension EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME] - "ShaderNonUniform" -> [RequireVersion $ MAKE_VERSION 1 2 0, RequireExtension EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + { propertyName = "VkPhysicalDeviceVulkan11Properties" + , checkProperty = \p -> + SUBGROUP_FEATURE_PARTITIONED_BIT_NV .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION + } + ] + "SampleMaskPostDepthCoverage" -> + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_POST_DEPTH_COVERAGE_SPEC_VERSION + } + ] + "ShaderNonUniform" -> [RequireVersion $ MAKE_VERSION 1 2 0] "RuntimeDescriptorArray" -> - [ RequireFeature { featureName = "runtimeDescriptorArray" - , checkFeature = runtimeDescriptorArray :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { runtimeDescriptorArray = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] + [ RequireFeature { featureName = "runtimeDescriptorArray" + , checkFeature = runtimeDescriptorArray :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { runtimeDescriptorArray = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "InputAttachmentArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderInputAttachmentArrayDynamicIndexing" - , checkFeature = shaderInputAttachmentArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderInputAttachmentArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderInputAttachmentArrayDynamicIndexing" + , checkFeature = shaderInputAttachmentArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderInputAttachmentArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "UniformTexelBufferArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderUniformTexelBufferArrayDynamicIndexing" - , checkFeature = shaderUniformTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderUniformTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderUniformTexelBufferArrayDynamicIndexing" + , checkFeature = shaderUniformTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderUniformTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "StorageTexelBufferArrayDynamicIndexing" -> [ RequireFeature - { featureName = "shaderStorageTexelBufferArrayDynamicIndexing" - , checkFeature = shaderStorageTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderStorageTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderStorageTexelBufferArrayDynamicIndexing" + , checkFeature = shaderStorageTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderStorageTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "UniformBufferArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderUniformBufferArrayNonUniformIndexing" - , checkFeature = shaderUniformBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderUniformBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderUniformBufferArrayNonUniformIndexing" + , checkFeature = shaderUniformBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderUniformBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "SampledImageArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderSampledImageArrayNonUniformIndexing" - , checkFeature = shaderSampledImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderSampledImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderSampledImageArrayNonUniformIndexing" + , checkFeature = shaderSampledImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderSampledImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "StorageBufferArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderStorageBufferArrayNonUniformIndexing" - , checkFeature = shaderStorageBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderStorageBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderStorageBufferArrayNonUniformIndexing" + , checkFeature = shaderStorageBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderStorageBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "StorageImageArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderStorageImageArrayNonUniformIndexing" - , checkFeature = shaderStorageImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderStorageImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderStorageImageArrayNonUniformIndexing" + , checkFeature = shaderStorageImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderStorageImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "InputAttachmentArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderInputAttachmentArrayNonUniformIndexing" - , checkFeature = shaderInputAttachmentArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderInputAttachmentArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderInputAttachmentArrayNonUniformIndexing" + , checkFeature = shaderInputAttachmentArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderInputAttachmentArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "UniformTexelBufferArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderUniformTexelBufferArrayNonUniformIndexing" - , checkFeature = shaderUniformTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderUniformTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderUniformTexelBufferArrayNonUniformIndexing" + , checkFeature = shaderUniformTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderUniformTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "StorageTexelBufferArrayNonUniformIndexing" -> [ RequireFeature - { featureName = "shaderStorageTexelBufferArrayNonUniformIndexing" - , checkFeature = shaderStorageTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> - f { shaderStorageTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME] - } + { featureName = "shaderStorageTexelBufferArrayNonUniformIndexing" + , checkFeature = shaderStorageTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> + f { shaderStorageTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "Float16" -> - [ RequireFeature { featureName = "shaderFloat16" - , checkFeature = shaderFloat16 :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderFloat16 = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME] + [ RequireFeature { featureName = "shaderFloat16" + , checkFeature = shaderFloat16 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderFloat16 = True } :: PhysicalDeviceVulkan12Features } - , RequireExtension AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT16_INT8_SPEC_VERSION + } ] "Int8" -> - [ RequireFeature { featureName = "shaderInt8" - , checkFeature = shaderInt8 :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderInt8 = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME] + [ RequireFeature { featureName = "shaderInt8" + , checkFeature = shaderInt8 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderInt8 = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT16_INT8_SPEC_VERSION + } ] "StorageBuffer8BitAccess" -> - [ RequireFeature { featureName = "storageBuffer8BitAccess" - , checkFeature = storageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { storageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_8BIT_STORAGE_EXTENSION_NAME] + [ RequireFeature { featureName = "storageBuffer8BitAccess" + , checkFeature = storageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { storageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_8BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_8BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "UniformAndStorageBuffer8BitAccess" -> [ RequireFeature - { featureName = "uniformAndStorageBuffer8BitAccess" - , checkFeature = uniformAndStorageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { uniformAndStorageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_8BIT_STORAGE_EXTENSION_NAME] - } + { featureName = "uniformAndStorageBuffer8BitAccess" + , checkFeature = uniformAndStorageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { uniformAndStorageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features + } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_8BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_8BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "StoragePushConstant8" -> - [ RequireFeature { featureName = "storagePushConstant8" - , checkFeature = storagePushConstant8 :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { storagePushConstant8 = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_8BIT_STORAGE_EXTENSION_NAME] + [ RequireFeature { featureName = "storagePushConstant8" + , checkFeature = storagePushConstant8 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { storagePushConstant8 = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_8BIT_STORAGE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_8BIT_STORAGE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION + } ] "VulkanMemoryModel" -> - [ RequireFeature { featureName = "vulkanMemoryModel" - , checkFeature = vulkanMemoryModel :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { vulkanMemoryModel = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] + [ RequireFeature { featureName = "vulkanMemoryModel" + , checkFeature = vulkanMemoryModel :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { vulkanMemoryModel = True } :: PhysicalDeviceVulkan12Features } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION + } ] "VulkanMemoryModelDeviceScope" -> - [ RequireFeature { featureName = "vulkanMemoryModelDeviceScope" - , checkFeature = vulkanMemoryModelDeviceScope :: PhysicalDeviceVulkan12Features -> Bool + [ RequireFeature { featureName = "vulkanMemoryModelDeviceScope" + , checkFeature = vulkanMemoryModelDeviceScope :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { vulkanMemoryModelDeviceScope = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME] } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION + } ] "DenormPreserve" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormPreserveFloat32 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormPreserveFloat64 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION + } ] "DenormFlushToZero" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormFlushToZeroFloat16 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormFlushToZeroFloat32 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormFlushToZeroFloat64 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormFlushToZeroFloat16 (p :: PhysicalDeviceVulkan12Properties) } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION + } ] "SignedZeroInfNanPreserve" -> [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty - { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat32 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty - { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat64 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION + } ] "RoundingModeRTE" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTEFloat16 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTEFloat32 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTEFloat64 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTEFloat16 (p :: PhysicalDeviceVulkan12Properties) } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION + } ] "RoundingModeRTZ" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTZFloat16 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTZFloat32 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] - } - , RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTZFloat64 (p :: PhysicalDeviceVulkan12Properties) - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME] + [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTZFloat16 (p :: PhysicalDeviceVulkan12Properties) } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION + } ] "ComputeDerivativeGroupQuadsNV" -> [ RequireFeature - { featureName = "computeDerivativeGroupQuads" - , checkFeature = computeDerivativeGroupQuads :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool - , enableFeature = \f -> - f { computeDerivativeGroupQuads = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] - } + { featureName = "computeDerivativeGroupQuads" + , checkFeature = computeDerivativeGroupQuads :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool + , enableFeature = \f -> + f { computeDerivativeGroupQuads = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME + , deviceExtensionMinVersion = NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION + } ] "ComputeDerivativeGroupLinearNV" -> [ RequireFeature - { featureName = "computeDerivativeGroupLinear" - , checkFeature = computeDerivativeGroupLinear :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool - , enableFeature = \f -> - f { computeDerivativeGroupLinear = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME] - } + { featureName = "computeDerivativeGroupLinear" + , checkFeature = computeDerivativeGroupLinear :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool + , enableFeature = \f -> + f { computeDerivativeGroupLinear = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME + , deviceExtensionMinVersion = NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION + } ] "FragmentBarycentricNV" -> [ RequireFeature - { featureName = "fragmentShaderBarycentric" - , checkFeature = fragmentShaderBarycentric :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV -> Bool - , enableFeature = \f -> - f { fragmentShaderBarycentric = True } :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME] - } + { featureName = "fragmentShaderBarycentric" + , checkFeature = fragmentShaderBarycentric :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV -> Bool + , enableFeature = \f -> + f { fragmentShaderBarycentric = True } :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME + , deviceExtensionMinVersion = NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION + } ] "ImageFootprintNV" -> - [ RequireFeature { featureName = "imageFootprint" - , checkFeature = imageFootprint :: PhysicalDeviceShaderImageFootprintFeaturesNV -> Bool + [ RequireFeature { featureName = "imageFootprint" + , checkFeature = imageFootprint :: PhysicalDeviceShaderImageFootprintFeaturesNV -> Bool , enableFeature = \f -> f { imageFootprint = True } :: PhysicalDeviceShaderImageFootprintFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION + } ] "ShadingRateNV" -> - [ RequireFeature { featureName = "shadingRateImage" - , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool + [ RequireFeature { featureName = "shadingRateImage" + , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool , enableFeature = \f -> f { shadingRateImage = True } :: PhysicalDeviceShadingRateImageFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_SHADING_RATE_IMAGE_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADING_RATE_IMAGE_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADING_RATE_IMAGE_SPEC_VERSION + } + ] + "MeshShadingNV" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_MESH_SHADER_EXTENSION_NAME + , deviceExtensionMinVersion = NV_MESH_SHADER_SPEC_VERSION + } ] - "MeshShadingNV" -> [RequireExtension NV_MESH_SHADER_EXTENSION_NAME] "RayTracingProvisionalKHR" -> - [ RequireFeature { featureName = "rayTracing" - , checkFeature = rayTracing :: PhysicalDeviceRayTracingFeaturesKHR -> Bool - , enableFeature = \f -> f { rayTracing = True } :: PhysicalDeviceRayTracingFeaturesKHR - , requireMinVersion = Nothing - , requireExtensions = [KHR_RAY_TRACING_EXTENSION_NAME] + [ RequireFeature { featureName = "rayTracing" + , checkFeature = rayTracing :: PhysicalDeviceRayTracingFeaturesKHR -> Bool + , enableFeature = \f -> f { rayTracing = True } :: PhysicalDeviceRayTracingFeaturesKHR } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "RayQueryProvisionalKHR" -> - [ RequireFeature { featureName = "rayQuery" - , checkFeature = rayQuery :: PhysicalDeviceRayTracingFeaturesKHR -> Bool - , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayTracingFeaturesKHR - , requireMinVersion = Nothing - , requireExtensions = [KHR_RAY_TRACING_EXTENSION_NAME] + [ RequireFeature { featureName = "rayQuery" + , checkFeature = rayQuery :: PhysicalDeviceRayTracingFeaturesKHR -> Bool + , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayTracingFeaturesKHR } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } ] "RayTraversalPrimitiveCullingProvisionalKHR" -> [ RequireFeature - { featureName = "rayTracingPrimitiveCulling" - , checkFeature = rayTracingPrimitiveCulling :: PhysicalDeviceRayTracingFeaturesKHR -> Bool - , enableFeature = \f -> f { rayTracingPrimitiveCulling = True } :: PhysicalDeviceRayTracingFeaturesKHR - , requireMinVersion = Nothing - , requireExtensions = [KHR_RAY_TRACING_EXTENSION_NAME] - } + { featureName = "rayTracingPrimitiveCulling" + , checkFeature = rayTracingPrimitiveCulling :: PhysicalDeviceRayTracingFeaturesKHR -> Bool + , enableFeature = \f -> f { rayTracingPrimitiveCulling = True } :: PhysicalDeviceRayTracingFeaturesKHR + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION + } + ] + "RayTracingNV" -> + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_RAY_TRACING_EXTENSION_NAME + , deviceExtensionMinVersion = NV_RAY_TRACING_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + } ] - "RayTracingNV" -> [RequireExtension NV_RAY_TRACING_EXTENSION_NAME] "TransformFeedback" -> [ RequireFeature - { featureName = "transformFeedback" - , checkFeature = transformFeedback :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool - , enableFeature = \f -> f { transformFeedback = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME] - } + { featureName = "transformFeedback" + , checkFeature = transformFeedback :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool + , enableFeature = \f -> f { transformFeedback = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_TRANSFORM_FEEDBACK_SPEC_VERSION + } ] "GeometryStreams" -> - [ RequireFeature { featureName = "geometryStreams" - , checkFeature = geometryStreams :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool + [ RequireFeature { featureName = "geometryStreams" + , checkFeature = geometryStreams :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool , enableFeature = \f -> f { geometryStreams = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_TRANSFORM_FEEDBACK_SPEC_VERSION + } ] "FragmentDensityEXT" -> [ RequireFeature - { featureName = "fragmentDensityMap" - , checkFeature = fragmentDensityMap :: PhysicalDeviceFragmentDensityMapFeaturesEXT -> Bool - , enableFeature = \f -> f { fragmentDensityMap = True } :: PhysicalDeviceFragmentDensityMapFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME] - } + { featureName = "fragmentDensityMap" + , checkFeature = fragmentDensityMap :: PhysicalDeviceFragmentDensityMapFeaturesEXT -> Bool + , enableFeature = \f -> f { fragmentDensityMap = True } :: PhysicalDeviceFragmentDensityMapFeaturesEXT + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION + } ] "PhysicalStorageBufferAddresses" -> - [ RequireFeature { featureName = "bufferDeviceAddress" - , checkFeature = bufferDeviceAddress :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceVulkan12Features - , requireMinVersion = Just $ MAKE_VERSION 1 2 0 - , requireExtensions = [KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] + [ RequireFeature { featureName = "bufferDeviceAddress" + , checkFeature = bufferDeviceAddress :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceVulkan12Features } - , RequireFeature - { featureName = "bufferDeviceAddress" - , checkFeature = bufferDeviceAddress :: PhysicalDeviceBufferDeviceAddressFeaturesEXT -> Bool - , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceBufferDeviceAddressFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME] - } + , RequireVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION + } ] "CooperativeMatrixNV" -> - [ RequireFeature { featureName = "cooperativeMatrix" - , checkFeature = cooperativeMatrix :: PhysicalDeviceCooperativeMatrixFeaturesNV -> Bool + [ RequireFeature { featureName = "cooperativeMatrix" + , checkFeature = cooperativeMatrix :: PhysicalDeviceCooperativeMatrixFeaturesNV -> Bool , enableFeature = \f -> f { cooperativeMatrix = True } :: PhysicalDeviceCooperativeMatrixFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_COOPERATIVE_MATRIX_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_COOPERATIVE_MATRIX_EXTENSION_NAME + , deviceExtensionMinVersion = NV_COOPERATIVE_MATRIX_SPEC_VERSION + } ] "IntegerFunctions2INTEL" -> [ RequireFeature - { featureName = "shaderIntegerFunctions2" - , checkFeature = shaderIntegerFunctions2 :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL -> Bool - , enableFeature = \f -> - f { shaderIntegerFunctions2 = True } :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL - , requireMinVersion = Nothing - , requireExtensions = [INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME] - } + { featureName = "shaderIntegerFunctions2" + , checkFeature = shaderIntegerFunctions2 :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL -> Bool + , enableFeature = \f -> f { shaderIntegerFunctions2 = True } :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME + , deviceExtensionMinVersion = INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION + } ] "ShaderSMBuiltinsNV" -> - [ RequireFeature { featureName = "shaderSMBuiltins" - , checkFeature = shaderSMBuiltins :: PhysicalDeviceShaderSMBuiltinsFeaturesNV -> Bool + [ RequireFeature { featureName = "shaderSMBuiltins" + , checkFeature = shaderSMBuiltins :: PhysicalDeviceShaderSMBuiltinsFeaturesNV -> Bool , enableFeature = \f -> f { shaderSMBuiltins = True } :: PhysicalDeviceShaderSMBuiltinsFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_SHADER_SM_BUILTINS_EXTENSION_NAME] } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = NV_SHADER_SM_BUILTINS_EXTENSION_NAME + , deviceExtensionMinVersion = NV_SHADER_SM_BUILTINS_SPEC_VERSION + } ] "FragmentShaderSampleInterlockEXT" -> [ RequireFeature - { featureName = "fragmentShaderSampleInterlock" - , checkFeature = fragmentShaderSampleInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool - , enableFeature = \f -> - f { fragmentShaderSampleInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - } + { featureName = "fragmentShaderSampleInterlock" + , checkFeature = fragmentShaderSampleInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool + , enableFeature = \f -> + f { fragmentShaderSampleInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION + } ] "FragmentShaderPixelInterlockEXT" -> [ RequireFeature - { featureName = "fragmentShaderPixelInterlock" - , checkFeature = fragmentShaderPixelInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool - , enableFeature = \f -> - f { fragmentShaderPixelInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] - } + { featureName = "fragmentShaderPixelInterlock" + , checkFeature = fragmentShaderPixelInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool + , enableFeature = \f -> + f { fragmentShaderPixelInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION + } ] "FragmentShaderShadingRateInterlockEXT" -> [ RequireFeature - { featureName = "fragmentShaderShadingRateInterlock" - , checkFeature = fragmentShaderShadingRateInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool - , enableFeature = \f -> + { featureName = "fragmentShaderShadingRateInterlock" + , checkFeature = fragmentShaderShadingRateInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool + , enableFeature = \f -> f { fragmentShaderShadingRateInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME] } - , RequireFeature { featureName = "shadingRateImage" - , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool - , enableFeature = \f -> f { shadingRateImage = True } :: PhysicalDeviceShadingRateImageFeaturesNV - , requireMinVersion = Nothing - , requireExtensions = [NV_SHADING_RATE_IMAGE_EXTENSION_NAME] - } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION + } ] "DemoteToHelperInvocationEXT" -> [ RequireFeature - { featureName = "shaderDemoteToHelperInvocation" - , checkFeature = shaderDemoteToHelperInvocation :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT - -> Bool - , enableFeature = \f -> - f { shaderDemoteToHelperInvocation = True } :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT - , requireMinVersion = Nothing - , requireExtensions = [EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME] - } + { featureName = "shaderDemoteToHelperInvocation" + , checkFeature = shaderDemoteToHelperInvocation :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT -> Bool + , enableFeature = \f -> + f { shaderDemoteToHelperInvocation = True } :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT + } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME + , deviceExtensionMinVersion = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION + } ] "FragmentShadingRateKHR" -> [ RequireFeature - { featureName = "pipelineFragmentShadingRate" - , checkFeature = pipelineFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool + { featureName = "pipelineFragmentShadingRate" + , checkFeature = pipelineFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool , enableFeature = \f -> f { pipelineFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR - , requireMinVersion = Nothing - , requireExtensions = [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - } - , RequireFeature - { featureName = "primitiveFragmentShadingRate" - , checkFeature = primitiveFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool - , enableFeature = \f -> f { primitiveFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR - , requireMinVersion = Nothing - , requireExtensions = [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] - } - , RequireFeature - { featureName = "attachmentFragmentShadingRate" - , checkFeature = attachmentFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool - , enableFeature = \f -> f { attachmentFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR - , requireMinVersion = Nothing - , requireExtensions = [KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME] } + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_CREATE_RENDERPASS_2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_CREATE_RENDERPASS_2_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MULTIVIEW_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_MAINTENANCE2_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_MAINTENANCE2_SPEC_VERSION + } ] _ -> [] diff --git a/vulkan.cabal b/vulkan.cabal index 85f1ad2fc..f90bf2232 100644 --- a/vulkan.cabal +++ b/vulkan.cabal @@ -485,6 +485,7 @@ library base <5 , bytestring , transformers + , unordered-containers , vector if os(windows) extra-libraries: From e5631ad416ed36e9cd2a8ef12064a99e563e36df Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Wed, 25 Nov 2020 22:06:39 +0800 Subject: [PATCH 12/70] Correct spirv req generation --- generate-new/vk/VK/SPIRVElements.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs index 695b06e1c..e19be2482 100644 --- a/generate-new/vk/VK/SPIRVElements.hs +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -106,7 +106,7 @@ renderReq = \case checkTDoc <- renderType (sTy ~> ConT ''Bool) sTyDoc <- renderType sTy otherReqs <- minVersionAndExtensionsReqs rs - let featureMemberName = mkMemberName f + let featureMemberName = mkMemberName s f let xs = [ ("featureName" , viaShow f) , ("checkFeature", pretty featureMemberName <+> "::" <+> checkTDoc) @@ -128,7 +128,7 @@ renderReq = \case sTy <- cToHsType DoNotPreserve (TypeName p) traverse_ tellImportWithAll (allTypeNames sTy) sTyDoc <- renderType sTy - let propertyMemberName = mkMemberName m + let propertyMemberName = mkMemberName p m propertyValueName = mkPatternName v otherReqs <- minVersionAndExtensionsReqs rs -- TODO, do this properly From 0ffa248235f5987258e6c5b2cc8b3024909fd57b Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Wed, 25 Nov 2020 22:12:39 +0800 Subject: [PATCH 13/70] regenerate --- src/Vulkan/SPIRVRequirements.hs | 144 +++++++++++++++++++------------- 1 file changed, 86 insertions(+), 58 deletions(-) diff --git a/src/Vulkan/SPIRVRequirements.hs b/src/Vulkan/SPIRVRequirements.hs index 14f648d60..2d63f7cdf 100644 --- a/src/Vulkan/SPIRVRequirements.hs +++ b/src/Vulkan/SPIRVRequirements.hs @@ -1,5 +1,6 @@ {-# language CPP #-} {-# language OverloadedLists #-} +-- No documentation found for Chapter "SPIRVRequirements" module Vulkan.SPIRVRequirements ( spirvExtensionRequirements , spirvCapabilityRequirements ) where @@ -26,8 +27,10 @@ import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (PhysicalDeviceFragmen import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (PhysicalDeviceFragmentShaderInterlockFeaturesEXT(..)) import Vulkan.Extensions.VK_KHR_fragment_shading_rate (PhysicalDeviceFragmentShadingRateFeaturesKHR) import Vulkan.Extensions.VK_KHR_fragment_shading_rate (PhysicalDeviceFragmentShadingRateFeaturesKHR(..)) -import Vulkan.Extensions.VK_KHR_ray_tracing (PhysicalDeviceRayTracingFeaturesKHR) -import Vulkan.Extensions.VK_KHR_ray_tracing (PhysicalDeviceRayTracingFeaturesKHR(..)) +import Vulkan.Extensions.VK_KHR_ray_query (PhysicalDeviceRayQueryFeaturesKHR) +import Vulkan.Extensions.VK_KHR_ray_query (PhysicalDeviceRayQueryFeaturesKHR(..)) +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline (PhysicalDeviceRayTracingPipelineFeaturesKHR) +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline (PhysicalDeviceRayTracingPipelineFeaturesKHR(..)) import Vulkan.Extensions.VK_EXT_shader_atomic_float (PhysicalDeviceShaderAtomicFloatFeaturesEXT) import Vulkan.Extensions.VK_EXT_shader_atomic_float (PhysicalDeviceShaderAtomicFloatFeaturesEXT(..)) import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT) @@ -108,6 +111,8 @@ import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_EXTENSI import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_EXTENSION_NAME) import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_acceleration_structure (pattern KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_acceleration_structure (pattern KHR_ACCELERATION_STRUCTURE_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_create_renderpass2 (pattern KHR_CREATE_RENDERPASS_2_EXTENSION_NAME) @@ -130,10 +135,10 @@ import Vulkan.Extensions.VK_KHR_maintenance3 (pattern KHR_MAINTENANCE3_EXTENSION import Vulkan.Extensions.VK_KHR_maintenance3 (pattern KHR_MAINTENANCE3_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_EXTENSION_NAME) import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_SPEC_VERSION) -import Vulkan.Extensions.VK_KHR_pipeline_library (pattern KHR_PIPELINE_LIBRARY_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_pipeline_library (pattern KHR_PIPELINE_LIBRARY_SPEC_VERSION) -import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_EXTENSION_NAME) -import Vulkan.Extensions.VK_KHR_ray_tracing (pattern KHR_RAY_TRACING_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_ray_query (pattern KHR_RAY_QUERY_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_query (pattern KHR_RAY_QUERY_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline (pattern KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline (pattern KHR_RAY_TRACING_PIPELINE_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME) import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_EXTENSION_NAME) @@ -148,6 +153,8 @@ import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON import Vulkan.Extensions.VK_KHR_shader_non_semantic_info (pattern KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME) import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION) +import Vulkan.Extensions.VK_KHR_spirv_1_4 (pattern KHR_SPIRV_1_4_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_spirv_1_4 (pattern KHR_SPIRV_1_4_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME) import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION) import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_EXTENSION_NAME) @@ -414,12 +421,20 @@ spirvExtensionRequirements = \case , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + , deviceExtensionName = KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_PIPELINE_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + , deviceExtensionName = KHR_SPIRV_1_4_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SPIRV_1_4_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_ACCELERATION_STRUCTURE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME @@ -433,10 +448,6 @@ spirvExtensionRequirements = \case , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION @@ -448,12 +459,20 @@ spirvExtensionRequirements = \case , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + , deviceExtensionName = KHR_RAY_QUERY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_QUERY_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + , deviceExtensionName = KHR_SPIRV_1_4_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SPIRV_1_4_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_ACCELERATION_STRUCTURE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME @@ -467,10 +486,6 @@ spirvExtensionRequirements = \case , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION @@ -1649,22 +1664,31 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = NV_MESH_SHADER_SPEC_VERSION } ] - "RayTracingProvisionalKHR" -> - [ RequireFeature { featureName = "rayTracing" - , checkFeature = rayTracing :: PhysicalDeviceRayTracingFeaturesKHR -> Bool - , enableFeature = \f -> f { rayTracing = True } :: PhysicalDeviceRayTracingFeaturesKHR - } + "RayTracingKHR" -> + [ RequireFeature + { featureName = "rayTracingPipeline" + , checkFeature = rayTracingPipeline :: PhysicalDeviceRayTracingPipelineFeaturesKHR -> Bool + , enableFeature = \f -> f { rayTracingPipeline = True } :: PhysicalDeviceRayTracingPipelineFeaturesKHR + } , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + , deviceExtensionName = KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_PIPELINE_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + , deviceExtensionName = KHR_SPIRV_1_4_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SPIRV_1_4_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_ACCELERATION_STRUCTURE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME @@ -1678,31 +1702,35 @@ spirvCapabilityRequirements = \case , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "RayQueryProvisionalKHR" -> + "RayQueryKHR" -> [ RequireFeature { featureName = "rayQuery" - , checkFeature = rayQuery :: PhysicalDeviceRayTracingFeaturesKHR -> Bool - , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayTracingFeaturesKHR + , checkFeature = rayQuery :: PhysicalDeviceRayQueryFeaturesKHR -> Bool + , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayQueryFeaturesKHR } , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + , deviceExtensionName = KHR_RAY_QUERY_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_QUERY_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + , deviceExtensionName = KHR_SPIRV_1_4_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SPIRV_1_4_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_ACCELERATION_STRUCTURE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME @@ -1716,32 +1744,36 @@ spirvCapabilityRequirements = \case , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "RayTraversalPrimitiveCullingProvisionalKHR" -> + "RayTraversalPrimitiveCullingKHR" -> [ RequireFeature - { featureName = "rayTracingPrimitiveCulling" - , checkFeature = rayTracingPrimitiveCulling :: PhysicalDeviceRayTracingFeaturesKHR -> Bool - , enableFeature = \f -> f { rayTracingPrimitiveCulling = True } :: PhysicalDeviceRayTracingFeaturesKHR + { featureName = "rayTraversalPrimitiveCulling" + , checkFeature = rayTraversalPrimitiveCulling :: PhysicalDeviceRayTracingPipelineFeaturesKHR -> Bool + , enableFeature = \f -> f { rayTraversalPrimitiveCulling = True } :: PhysicalDeviceRayTracingPipelineFeaturesKHR } , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_RAY_TRACING_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_RAY_TRACING_SPEC_VERSION + , deviceExtensionName = KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_RAY_TRACING_PIPELINE_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION + , deviceExtensionName = KHR_SPIRV_1_4_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SPIRV_1_4_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_ACCELERATION_STRUCTURE_SPEC_VERSION + } + , RequireDeviceExtension { deviceExtensionLayerName = Nothing + , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME @@ -1755,10 +1787,6 @@ spirvCapabilityRequirements = \case , deviceExtensionName = KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing - , deviceExtensionName = KHR_PIPELINE_LIBRARY_EXTENSION_NAME - , deviceExtensionMinVersion = KHR_PIPELINE_LIBRARY_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_MAINTENANCE3_EXTENSION_NAME , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION From 948d47cb0ba044a7fbb8655db195a1553060ef53 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 12:34:41 +0800 Subject: [PATCH 14/70] Copy HLSL examples to rays --- examples/hie.yaml | 3 + examples/package.yaml | 29 ++++ examples/rays/Cache.hs | 182 ++++++++++++++++++++++++ examples/rays/Frame.hs | 135 ++++++++++++++++++ examples/rays/Framebuffer.hs | 49 +++++++ examples/rays/Init.hs | 247 +++++++++++++++++++++++++++++++++ examples/rays/Main.hs | 50 +++++++ examples/rays/MonadFrame.hs | 152 ++++++++++++++++++++ examples/rays/MonadVulkan.hs | 239 +++++++++++++++++++++++++++++++ examples/rays/Pipeline.hs | 173 +++++++++++++++++++++++ examples/rays/RefCounted.hs | 49 +++++++ examples/rays/Render.hs | 123 ++++++++++++++++ examples/rays/RenderPass.hs | 55 ++++++++ examples/rays/Swapchain.hs | 231 ++++++++++++++++++++++++++++++ examples/rays/Utils.hs | 14 ++ examples/rays/Window.hs | 71 ++++++++++ examples/vulkan-examples.cabal | 52 ++++++- 17 files changed, 1853 insertions(+), 1 deletion(-) create mode 100644 examples/rays/Cache.hs create mode 100644 examples/rays/Frame.hs create mode 100644 examples/rays/Framebuffer.hs create mode 100644 examples/rays/Init.hs create mode 100644 examples/rays/Main.hs create mode 100644 examples/rays/MonadFrame.hs create mode 100644 examples/rays/MonadVulkan.hs create mode 100644 examples/rays/Pipeline.hs create mode 100644 examples/rays/RefCounted.hs create mode 100644 examples/rays/Render.hs create mode 100644 examples/rays/RenderPass.hs create mode 100644 examples/rays/Swapchain.hs create mode 100644 examples/rays/Utils.hs create mode 100644 examples/rays/Window.hs diff --git a/examples/hie.yaml b/examples/hie.yaml index 6494a08d3..3952dcf57 100644 --- a/examples/hie.yaml +++ b/examples/hie.yaml @@ -20,3 +20,6 @@ cradle: - path: "./hlsl/" component: "exe:hlsl" + + - path: "./rays/" + component: "exe:rays" diff --git a/examples/package.yaml b/examples/package.yaml index d7a72aafe..0044a817c 100644 --- a/examples/package.yaml +++ b/examples/package.yaml @@ -143,6 +143,35 @@ executables: - condition: '!flag(have-shaderc)' buildable: false + rays: + main: Main.hs + source-dirs: rays + dependencies: + - VulkanMemoryAllocator + - autoapply >= 0.4 + - base <5 + - bytestring + - containers + - primitive-unlifted + - resourcet >= 1.2.4 + - say + - sdl2 >= 2.5.2.0 + - template-haskell + - text + - transformers + - unagi-chan + - unliftio + - vector + - vulkan + - vulkan-utils + - file-embed + - extra + - filepath + - temporary + - typed-process + when: + - condition: impl(ghc < 8.10.0) + buildable: false when: - condition: os(windows) diff --git a/examples/rays/Cache.hs b/examples/rays/Cache.hs new file mode 100644 index 000000000..65a580f4b --- /dev/null +++ b/examples/rays/Cache.hs @@ -0,0 +1,182 @@ +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE PartialTypeSignatures #-} + +module Cache + ( Cache + , Token + , newCache + , newCacheR + , cachedCreate + , cachedCreateR + ) +where + +import Control.Concurrent.MVar +import Data.IORef +import Data.Primitive.Unlifted.Weak.IO +import qualified Data.Map as Map +import Data.Map ( Map ) +import Control.Monad.IO.Class ( MonadIO(..) ) +import Data.Primitive.Unlifted.Class ( PrimUnlifted ) +import Control.Monad ( join ) +import UnliftIO.Exception ( mask ) +import UnliftIO ( MonadUnliftIO ) +import Data.Functor ( void ) +import Control.Monad.Trans.Resource ( ReleaseKey ) +import qualified Control.Monad.Trans.Resource as R +import Data.Bifunctor ( Bifunctor(first) ) + +data Cache m k v = Cache + { cacheCreate :: k -> m (IO (), v) + -- ^ Action to create new cache elements + , cacheMap :: MVar (Map k (UnliftedWeak (MVar (IO (), Token v, v)))) + -- ^ A map containing weak pointers to (release action, touch token, value) + } + +-- | Create a cache +newCache :: MonadIO n => (k -> m (IO (), v)) -> n (Cache m k v) +newCache c = liftIO $ Cache c <$> newMVar Map.empty + +-- | Create a cache which creates objects with a 'ReleaseKey' instead of a +-- release action. +newCacheR + :: (Functor m, MonadIO n) => (k -> m (ReleaseKey, v)) -> n (Cache m k v) +newCacheR c = liftIO $ Cache (fmap (first R.release) . c) <$> newMVar Map.empty + +newtype Token a = Token { unToken :: IORef () } + deriving newtype PrimUnlifted + +-- | Keep the object referred to by this token alive until at least now +-- +-- Note that if the object has been explicitly released before now this won't +-- do anything. +touchToken :: MonadIO m => Token v -> m () +touchToken = liftIO . touchUnlifted . unToken + +-- | The same as cachedCreate but doesn't return the destroy action. +-- +-- This is intended to be used when using a monad, m, which performs its own +-- resource tracking where the destroy action would be unnecessary. +-- +-- Keep in mind that the cache has no visibility into when the user generated +-- destroy action is called, so it's possible to destroy objects from under the +-- nose of the cache. To avoid this, make sure not to use the cache after one +-- of these destructors has been called, i.e. don't return the 'Cache' out of +-- 'runResourceT' +cachedCreateR :: (MonadUnliftIO m, Ord k) => Cache m k b -> k -> m (Token b, b) +cachedCreateR c k = do + (_, t, r) <- cachedCreate c k + pure (t, r) + +-- | Fetch an element from a cache, or create a new one and insert it. +-- +-- If the element is already in the cache it's returned immediately, otherwise +-- it's created and inserted. +-- +-- Elements are kept in the cache using weak pointers, so if they only exist in +-- the cache then they may be collected and deallocated (not promptly). +-- +-- Note that there is no reference counting, so manually releasing a resource +-- (using the returned release action) better be done when all other users of +-- it are done. +-- +-- If you need your resources to be deallocated without fail then make sure you +-- use a monad, @m@, which supports that, such as the 'ResourceT' monad. +cachedCreate + :: forall m k v + . (MonadUnliftIO m, Ord k) + => Cache m k v + -> k + -- ^ The key to lookup + -> m (IO (), Token v, v) + -- ^ + -- ( An action which can be called to release this resource immediately (this + -- may be called more than once) + -- , A token to pass to 'touchToken' to indicate that the value must be alive + -- until at least this point (can be called with no effect after the + -- release action) + -- , the created value + -- ) +cachedCreate Cache {..} k = do + let insert m = do + -- Tie the knot for the release action. The release action is required + -- when we create the weak pointer, however we don't want to have to + -- create it now as we have taken the Map MVar. + -- + -- Create an empty action here in case there's an exception between + -- creating the finalizer and setting the release action. + releaseRef <- newMVar (pure ()) + let runRelease = join . readMVar $ releaseRef + + v <- newEmptyMVar + i <- newToken + w <- mkWeakFromUnliftedToUnlifted i v (Just runRelease) + let m' = Map.insert k w m + + -- Return the new map, along with an action to create the object and + -- put it in the map + pure . (m', ) $ do + -- If we have a new one: + -- - Create the object + -- - Create a weak pointer with the release action as finalizer + -- - Put it into the MVar + a <- mask $ \_ -> do + (release, a) <- cacheCreate k + void . liftIO $ swapMVar releaseRef release + -- Make sure the Weak stays alive until at least it's been given + -- the correct release action. + touchToken i + pure a + let r = (finalizeUnlifted w, i, a) + liftIO $ putMVar v r + pure r + + -- This takes the MVar and returns an action to run after, do this so we + -- spend as little time as possible locking the cache. + join . liftIO . modifyMVar cacheMap $ \m -> do + case Map.lookup k m of + -- It's never been in the map, make a new one + Nothing -> insert m + Just w -> deRefUnliftedWeak w >>= \case + -- It was in the map but has been released, make a new one + Nothing -> insert m + -- It's in the map and still alive, return it without modifying the map + Just v -> pure (m, liftIO $ readMVar v) + +newToken :: IO (Token v) +newToken = Token <$> newIORef () + +-- test :: IO () +-- test = do +-- runResourceT $ do +-- c <- newCacheR $ \k -> allocate (sayShow ("create", k) >> pure k) +-- (\l -> (sayShow ("destroy", l))) +-- say "new cache" + +-- (releaseTwo, two, _) <- cachedCreate c 2 +-- say "created 2" + +-- liftIO performGC +-- liftIO $ threadDelay 1e6 +-- liftIO performGC + +-- (releaseThree, three, _) <- cachedCreate c 3 +-- say "created 3" + +-- liftIO performGC +-- liftIO $ threadDelay 1e6 +-- liftIO performGC +-- liftIO $ threadDelay 1e6 +-- liftIO performGC + +-- say "release 2" +-- say "released 2" + +-- (releaseTwo2, two2, _) <- cachedCreate c 2 +-- say "created another 2" + +-- say "touching" +-- touchToken two +-- say "touched" + +-- say "end" diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs new file mode 100644 index 000000000..f1de9c858 --- /dev/null +++ b/examples/rays/Frame.hs @@ -0,0 +1,135 @@ +-- | Defines the 'Frame' type, most interesting operations regarding 'Frame's +-- can be found in 'MonadFrame' +module Frame where + +import Control.Monad ( replicateM_ ) +import Control.Monad.IO.Class ( MonadIO(liftIO) ) +import Control.Monad.Trans.Reader ( asks ) +import Control.Monad.Trans.Resource ( InternalState + , ReleaseKey + , allocate + , closeInternalState + , createInternalState + ) +import Data.IORef +import Data.Word +import MonadVulkan +import qualified Pipeline +import qualified SDL +import SDL ( Window ) +import qualified SDL.Video.Vulkan as SDL +import Say +import Swapchain +import Vulkan.CStruct.Extends +import Vulkan.Core10 +import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore +import Vulkan.Extensions.VK_KHR_surface +import Vulkan.Utils.QueueAssignment +import Vulkan.Zero + +-- | Must be positive, duh +numConcurrentFrames :: Int +numConcurrentFrames = 3 + +-- | All the information required to render a single frame +data Frame = Frame + { fIndex :: Word64 -- ^ Which number frame is this + -- SDL things + , fWindow :: SDL.Window + -- Vulkan things + , fSurface :: SurfaceKHR + , fSwapchainResources :: SwapchainResources + , fPipeline :: Pipeline + , fRenderFinishedHostSemaphore :: Semaphore + -- ^ A timeline semaphore which increments to fIndex when this frame is + -- done, the host can wait on this semaphore + , fRecycledResources :: RecycledResources + -- ^ Resources which can be used for this frame and are then passed on to a + -- later frame. + , fGPUWork :: IORef [(Semaphore, Word64)] + -- ^ Timeline semaphores and corresponding wait values, updates as the + -- frame progresses. + , fResources :: (ReleaseKey, InternalState) + -- ^ The 'InternalState' for tracking frame-local resources along with the + -- key to release it in the global scope. This will be released when the + -- frame is done with GPU work. + } + +initialRecycledResources :: V RecycledResources +initialRecycledResources = do + (_, fImageAvailableSemaphore) <- withSemaphore' + (zero ::& SemaphoreTypeCreateInfo SEMAPHORE_TYPE_BINARY 0 :& ()) + + (_, fRenderFinishedSemaphore) <- withSemaphore' + (zero ::& SemaphoreTypeCreateInfo SEMAPHORE_TYPE_BINARY 0 :& ()) + + graphicsQueueFamilyIndex <- getGraphicsQueueFamilyIndex + (_, fCommandPool) <- withCommandPool' zero + { queueFamilyIndex = unQueueFamilyIndex graphicsQueueFamilyIndex + } + + pure RecycledResources { .. } + +initialFrame :: Window -> SurfaceKHR -> V Frame +initialFrame fWindow fSurface = do + let fIndex = 1 + SDL.V2 width height <- SDL.vkGetDrawableSize fWindow + let windowSize = Extent2D (fromIntegral width) (fromIntegral height) + oldSwapchain = NULL_HANDLE + fSwapchainResources <- allocSwapchainResources oldSwapchain + windowSize + fSurface + + -- TODO: Cache this + -- TODO: Recreate this if the swapchain format changes + (_releasePipeline, fPipeline) <- Pipeline.createPipeline + (srRenderPass fSwapchainResources) + + -- Don't keep the release key, this semaphore lives for the lifetime of the + -- application + (_, fRenderFinishedHostSemaphore) <- withSemaphore' + (zero ::& SemaphoreTypeCreateInfo SEMAPHORE_TYPE_TIMELINE 0 :& ()) + + bin <- V $ asks ghRecycleBin + replicateM_ (numConcurrentFrames - 1) + $ liftIO + . bin + =<< initialRecycledResources + fRecycledResources <- initialRecycledResources + + fGPUWork <- liftIO $ newIORef mempty + -- Create this resource object at the global level so it's closed correctly + -- on exception + fResources <- allocate createInternalState closeInternalState + + pure Frame { .. } + +-- | Create the next frame +advanceFrame :: Bool -> Frame -> V Frame +advanceFrame needsNewSwapchain f = do + -- Wait for a prior frame to finish, then we can steal it's resources! + nib <- V $ asks ghRecycleNib + fRecycledResources <- liftIO $ nib >>= \case + Left block -> do + sayErr "CPU is running ahead" + block + Right rs -> pure rs + + fSwapchainResources <- if needsNewSwapchain + then recreateSwapchainResources (fWindow f) (fSwapchainResources f) + else pure $ fSwapchainResources f + + -- The per-frame resource helpers need to be created fresh + fGPUWork <- liftIO $ newIORef mempty + fResources <- allocate createInternalState closeInternalState + + pure Frame { fIndex = succ (fIndex f) + , fWindow = fWindow f + , fSurface = fSurface f + , fSwapchainResources + , fPipeline = fPipeline f + , fRenderFinishedHostSemaphore = fRenderFinishedHostSemaphore f + , fGPUWork + , fResources + , fRecycledResources + } diff --git a/examples/rays/Framebuffer.hs b/examples/rays/Framebuffer.hs new file mode 100644 index 000000000..adfdbc8c6 --- /dev/null +++ b/examples/rays/Framebuffer.hs @@ -0,0 +1,49 @@ +{-# LANGUAGE OverloadedLists #-} +module Framebuffer + ( Framebuffer.createFramebuffer + , Framebuffer.createImageView + ) where + +import Control.Monad.Trans.Resource +import MonadVulkan +import Vulkan.Core10 as Vk + hiding ( withBuffer + , withImage + ) +import Vulkan.Zero + +-- | Create a framebuffer filling the whole image. +createFramebuffer + :: RenderPass -> ImageView -> Extent2D -> V (ReleaseKey, Framebuffer) +createFramebuffer renderPass imageView imageSize = do + -- Create a framebuffer + let framebufferCreateInfo :: FramebufferCreateInfo '[] + framebufferCreateInfo = zero { renderPass = renderPass + , attachments = [imageView] + , width = width (imageSize :: Extent2D) + , height = height (imageSize :: Extent2D) + , layers = 1 + } + withFramebuffer' framebufferCreateInfo + +-- | Create a pretty vanilla ImageView covering the whole image +createImageView :: Format -> Image -> V (ReleaseKey, ImageView) +createImageView format = \image -> + withImageView' imageViewCreateInfo { image = image } + where + imageViewCreateInfo = zero + { viewType = IMAGE_VIEW_TYPE_2D + , format = format + , components = zero { r = COMPONENT_SWIZZLE_IDENTITY + , g = COMPONENT_SWIZZLE_IDENTITY + , b = COMPONENT_SWIZZLE_IDENTITY + , a = COMPONENT_SWIZZLE_IDENTITY + } + , subresourceRange = zero { aspectMask = IMAGE_ASPECT_COLOR_BIT + , baseMipLevel = 0 + , levelCount = 1 + , baseArrayLayer = 0 + , layerCount = 1 + } + } + diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs new file mode 100644 index 000000000..3c7a878c5 --- /dev/null +++ b/examples/rays/Init.hs @@ -0,0 +1,247 @@ +module Init + ( Init.createInstance + , Init.createDevice + , createVMA + , createCommandPools + ) where + +import Control.Monad ( unless ) +import Control.Monad.IO.Class +import Control.Monad.Trans.Maybe ( MaybeT(..) ) +import Control.Monad.Trans.Resource +import qualified Data.Vector as V +import Data.Word +import Say +import UnliftIO.Exception +import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore + ( PhysicalDeviceTimelineSemaphoreFeatures(..) + ) +import Vulkan.Extensions.VK_KHR_timeline_semaphore + +import Control.Applicative +import qualified Data.ByteString as BS +import Data.Foldable ( for_ ) +import Data.Vector ( Vector ) +import GHC.IO.Exception ( IOErrorType(NoSuchThing) + , IOException(IOError) + ) +import MonadVulkan ( Queues(..) + , checkCommands + , noAllocationCallbacks + ) +import qualified SDL.Video as SDL +import qualified SDL.Video.Vulkan as SDL +import Vulkan.CStruct.Extends +import Vulkan.Core10 as Vk + hiding ( withBuffer + , withImage + ) +import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 +import Vulkan.Extensions.VK_KHR_surface +import Vulkan.Extensions.VK_KHR_swapchain +import Vulkan.Utils.Initialization +import Vulkan.Utils.QueueAssignment +import Vulkan.Zero +import VulkanMemoryAllocator ( Allocator + , AllocatorCreateInfo(..) + , withAllocator + ) +import Window + +myApiVersion :: Word32 +myApiVersion = API_VERSION_1_0 + +---------------------------------------------------------------- +-- Instance Creation +---------------------------------------------------------------- + +-- | Create an instance with a debug messenger +createInstance :: MonadResource m => SDL.Window -> m Instance +createInstance win = do + windowExtensions <- + liftIO $ traverse BS.packCString =<< SDL.vkGetInstanceExtensions win + let createInfo = zero + { applicationInfo = Just zero { applicationName = Nothing + , apiVersion = myApiVersion + } + } + extensions = + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + <> windowExtensions + createDebugInstanceWithExtensions [] [] extensions [] createInfo + +---------------------------------------------------------------- +-- Device creation +---------------------------------------------------------------- + +createDevice + :: forall m + . (MonadResource m) + => Instance + -> SDL.Window + -> m + ( PhysicalDevice + , Device + , Queues (QueueFamilyIndex, Queue) + , SurfaceKHR + ) +createDevice inst win = do + (_ , surf) <- createSurface inst win + (pdi, phys) <- + maybe (noSuchThing "Unable to find appropriate PhysicalDevice") pure + =<< pickPhysicalDevice inst (physicalDeviceInfo surf) pdiScore + sayErr . ("Using device: " <>) =<< physicalDeviceName phys + let deviceCreateInfo = + zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } + ::& PhysicalDeviceTimelineSemaphoreFeatures True + :& () + extensions = + [KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, KHR_SWAPCHAIN_EXTENSION_NAME] + dev <- createDeviceWithExtensions phys [] extensions deviceCreateInfo + requireCommands inst dev + queues <- liftIO $ pdiGetQueues pdi dev + pure (phys, dev, queues, surf) + +---------------------------------------------------------------- +-- Physical device tools +---------------------------------------------------------------- + +-- | The Ord instance prioritises devices with more memory +data PhysicalDeviceInfo = PhysicalDeviceInfo + { pdiTotalMemory :: Word64 + , pdiQueueCreateInfos :: Vector (DeviceQueueCreateInfo '[]) + , pdiGetQueues :: Device -> IO (Queues (QueueFamilyIndex, Queue)) + } + +pdiScore :: PhysicalDeviceInfo -> Word64 +pdiScore = pdiTotalMemory + +physicalDeviceInfo + :: MonadIO m => SurfaceKHR -> PhysicalDevice -> m (Maybe PhysicalDeviceInfo) +physicalDeviceInfo surf phys = runMaybeT $ do + deviceName <- physicalDeviceName phys + + hasTimelineSemaphores <- deviceHasTimelineSemaphores phys + unless hasTimelineSemaphores $ do + sayErr + $ "Not using physical device " + <> deviceName + <> " because it doesn't support timeline semaphores" + empty + + hasSwapchainSupport <- deviceHasSwapchain phys + unless hasSwapchainSupport $ do + sayErr + $ "Not using physical device " + <> deviceName + <> " because it doesn't support swapchains" + empty + + (pdiQueueCreateInfos, pdiGetQueues) <- MaybeT + $ assignQueues phys (queueRequirements phys surf) + + -- + -- We'll use the amount of memory to pick the "best" device + -- + pdiTotalMemory <- do + heaps <- memoryHeaps <$> getPhysicalDeviceMemoryProperties phys + pure $ sum ((size :: MemoryHeap -> DeviceSize) <$> heaps) + + pure PhysicalDeviceInfo { .. } + +-- | Requirements for a 'Queue' which has graphics suppor and can present to +-- the specified surface. +queueRequirements + :: MonadIO m => PhysicalDevice -> SurfaceKHR -> Queues (QueueSpec m) +queueRequirements phys surf = Queues (QueueSpec 1 isGraphicsPresentQueue) + where + isGraphicsPresentQueue queueFamilyIndex queueFamilyProperties = + pure (isGraphicsQueueFamily queueFamilyProperties) + <&&> isPresentQueueFamily phys surf queueFamilyIndex + +---------------------------------------------------------------- +-- Physical device tools +---------------------------------------------------------------- + +deviceHasSwapchain :: MonadIO m => PhysicalDevice -> m Bool +deviceHasSwapchain dev = do + (_, extensions) <- enumerateDeviceExtensionProperties dev Nothing + pure $ V.any ((KHR_SWAPCHAIN_EXTENSION_NAME ==) . extensionName) extensions + +deviceHasTimelineSemaphores :: MonadIO m => PhysicalDevice -> m Bool +deviceHasTimelineSemaphores phys = do + let + hasExt = do + (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing + pure $ V.any + ((KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME ==) . extensionName) + extensions + + hasFeat = do + feats <- getPhysicalDeviceFeatures2KHR phys + let + _ ::& (PhysicalDeviceTimelineSemaphoreFeatures hasTimelineSemaphores :& ()) + = feats + pure hasTimelineSemaphores + + hasExt <&&> hasFeat + +---------------------------------------------------------------- +-- VulkanMemoryAllocator +---------------------------------------------------------------- + +createVMA + :: MonadResource m => Instance -> PhysicalDevice -> Device -> m Allocator +createVMA inst phys dev = + snd + <$> withAllocator + zero { flags = zero + , physicalDevice = physicalDeviceHandle phys + , device = deviceHandle dev + , instance' = instanceHandle inst + , vulkanApiVersion = myApiVersion + } + allocate + +---------------------------------------------------------------- +-- Command pools +---------------------------------------------------------------- + +-- | Create several command pools for a queue family +createCommandPools + :: MonadResource m + => Device + -> Int + -- ^ Number of pools to create + -> QueueFamilyIndex + -- ^ Queue family for the pools + -> m (Vector CommandPool) +createCommandPools dev n (QueueFamilyIndex queueFamilyIndex) = do + let commandPoolCreateInfo :: CommandPoolCreateInfo + commandPoolCreateInfo = zero { queueFamilyIndex = queueFamilyIndex } + V.replicateM + n + ( snd + <$> withCommandPool dev + commandPoolCreateInfo + noAllocationCallbacks + allocate + ) + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +requireCommands :: MonadIO f => Instance -> Device -> f () +requireCommands inst dev = case checkCommands inst dev of + [] -> pure () + xs -> do + for_ xs $ \n -> sayErr ("Failed to load function pointer for: " <> n) + noSuchThing "Missing commands" + +noSuchThing :: MonadIO m => String -> m a +noSuchThing message = + liftIO . throwIO $ IOError Nothing NoSuchThing "" message Nothing Nothing + +(<&&>) :: Applicative f => f Bool -> f Bool -> f Bool +(<&&>) = liftA2 (&&) diff --git a/examples/rays/Main.hs b/examples/rays/Main.hs new file mode 100644 index 000000000..bf238960d --- /dev/null +++ b/examples/rays/Main.hs @@ -0,0 +1,50 @@ +module Main where + +import Control.Monad.IO.Class +import Control.Monad.Trans.Resource +import Frame +import Init +import MonadFrame +import MonadVulkan +import Render +import SDL ( showWindow + , time + ) +import Swapchain ( threwSwapchainError ) +import Utils +import Window + +main :: IO () +main = runResourceT $ do + -- + -- Initialization + -- + withSDL + win <- createWindow "Vulkan 🚀 Haskell" 1280 720 + inst <- Init.createInstance win + (phys, dev, qs, surf) <- Init.createDevice inst win + vma <- createVMA inst phys dev + + -- + -- Go + -- + start <- SDL.time @Double + let reportFPS f = do + end <- SDL.time + let frames = fIndex f + mean = realToFrac frames / (end - start) + liftIO $ putStrLn $ "Average: " <> show mean + + let frame f = do + shouldQuit >>= \case + True -> do + reportFPS f + pure Nothing + False -> Just <$> do + needsNewSwapchain <- threwSwapchainError (runFrame f renderFrame) + advanceFrame needsNewSwapchain f + + runV inst phys dev qs vma $ do + initial <- initialFrame win surf + showWindow win + loopJust frame initial diff --git a/examples/rays/MonadFrame.hs b/examples/rays/MonadFrame.hs new file mode 100644 index 000000000..cc06ec8a8 --- /dev/null +++ b/examples/rays/MonadFrame.hs @@ -0,0 +1,152 @@ +module MonadFrame + ( F + , runFrame + , liftV + , queueSubmitFrame + , allocateGlobal + , allocateGlobal_ + , frameRefCount + , askFrame + , asksFrame + ) where + + +import Control.Monad +import Control.Monad.IO.Class +import Control.Monad.Trans.Class ( lift ) +import Control.Monad.Trans.Reader ( ReaderT + , ask + , asks + , runReaderT + ) +import Control.Monad.Trans.Resource +import qualified Data.Vector as V +import Data.Vector ( Vector ) +import Data.Word +import Frame +import GHC.IO.Exception ( IOErrorType(TimeExpired) + , IOException(IOError) + ) +import MonadVulkan +import RefCounted +import Say ( sayErrString ) +import UnliftIO +import Vulkan.CStruct.Extends ( SomeStruct ) +import Vulkan.Core10 +import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore +import Vulkan.Zero ( Zero(zero) ) + +newtype F a = F {unF :: ReaderT Frame V a } + deriving newtype ( Functor + , Applicative + , Monad + , MonadIO + , HasVulkan + ) + +instance MonadUnliftIO F where + withRunInIO a = F $ withRunInIO (\r -> a (r . unF)) + +---------------------------------------------------------------- +-- Vulkan Operations +---------------------------------------------------------------- + +-- | Runs a frame and spawns a thread to wait for the GPU work to complete, at +-- which point the frame-specific resources are collected. +runFrame :: Frame -> F a -> V a +runFrame f@Frame {..} (F r) = runReaderT r f `finally` do + waits <- liftIO $ readIORef fGPUWork + let oneSecond = 1e9 -- one second + spawn_ $ do + -- Wait for the GPU work to finish (if we have any) + unless (null waits) $ do + let waitInfo = zero { semaphores = V.fromList (fst <$> waits) + , values = V.fromList (snd <$> waits) + } + waitSemaphoresSafe' waitInfo oneSecond >>= \case + TIMEOUT -> + timeoutError "Timed out (1s) waiting for frame to finish on Device" + _ -> pure () + + -- Free resources wanted elsewhere now, all those in RecycledResources + resetCommandPool' (fCommandPool fRecycledResources) zero + + -- Signal we're done by making the recycled resources available + bin <- V $ asks ghRecycleBin + liftIO $ bin fRecycledResources + + -- Destroy frame-specific resources at our leisure + retireFrame f + +-- | 'queueSubmit' and add wait for the 'Fence' before retiring the frame. +queueSubmitFrame + :: Queue -> Vector (SomeStruct SubmitInfo) -> Semaphore -> Word64 -> F () +queueSubmitFrame q ss sem value = do + gpuWork <- asksFrame fGPUWork + -- Make sure we don't get interrupted between submitting the work and + -- recording the wait + mask $ \_ -> do + queueSubmit q ss NULL_HANDLE + liftIO $ atomicModifyIORef' gpuWork ((, ()) . ((sem, value) :)) + +liftV :: V a -> F a +liftV = F . lift + +---------------------------------------------------------------- +-- Resource handling +---------------------------------------------------------------- + +-- | By default resources allocated will only last until the frame is retired, +-- i.e. the GPU work is complete. +-- +-- To allocate something globally use 'allocateGlobal' +instance MonadResource F where + liftResourceT r = do + i <- asksFrame (snd . fResources) + liftIO $ runInternalState r i + +-- | Allocate a resource in the 'V' scope +allocateGlobal + :: F a + -- ^ Create to be calle dnow + -> (a -> F ()) + -- ^ Destroy, to be called at program termination + -> F (ReleaseKey, a) +allocateGlobal create destroy = do + createIO <- toIO create + run <- askRunInIO + F $ allocate createIO (run . destroy) + +-- | c.f. 'bracket' and 'bracket_' +allocateGlobal_ :: F a -> F () -> F (ReleaseKey, a) +allocateGlobal_ create destroy = allocateGlobal create (const destroy) + +-- | Free frame resources, the frame must have finished GPU execution first. +retireFrame :: MonadIO m => Frame -> m () +retireFrame Frame {..} = do + sayErrString ("retiring frame " <> show fIndex) + release (fst fResources) + +-- | Make sure a reference is held until this frame is retired +frameRefCount :: RefCounted -> F () +frameRefCount = resourceTRefCount + +---------------------------------------------------------------- +-- Small Operations +---------------------------------------------------------------- + +-- | Get the current 'Frame' +askFrame :: F Frame +askFrame = F ask + +-- | Get a function of the current 'Frame' +asksFrame :: (Frame -> a) -> F a +asksFrame = F . asks + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +timeoutError :: MonadIO m => String -> m a +timeoutError message = + liftIO . throwIO $ IOError Nothing TimeExpired "" message Nothing Nothing diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs new file mode 100644 index 000000000..d7b5180b6 --- /dev/null +++ b/examples/rays/MonadVulkan.hs @@ -0,0 +1,239 @@ +{-# LANGUAGE TemplateHaskell #-} +{-# OPTIONS_GHC -Wno-missing-signatures #-} + +module MonadVulkan where + +import AutoApply +import Control.Monad ( void ) +import Control.Monad.IO.Class +import Control.Monad.Trans.Class ( lift ) +import Control.Monad.Trans.Reader +import Control.Monad.Trans.Resource +import UnliftIO ( Async + , MonadUnliftIO(withRunInIO) + , async + , toIO + , uninterruptibleCancel + ) + +import Control.Concurrent.Chan.Unagi +import Language.Haskell.TH.Syntax ( addTopDecls ) +import Vulkan.CStruct.Extends +import Vulkan.Core10 as Vk + hiding ( withBuffer + , withImage + ) +import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore + as Timeline +import Vulkan.Extensions.VK_KHR_surface +import Vulkan.Extensions.VK_KHR_swapchain +import Vulkan.Utils.CommandCheck +import Vulkan.Utils.QueueAssignment +import VulkanMemoryAllocator as VMA + hiding ( getPhysicalDeviceProperties ) + +---------------------------------------------------------------- +-- Define the monad in which most of the program will run +---------------------------------------------------------------- + +-- | @V@ keeps track of a bunch of "global" handles and performs resource +-- management. +newtype V a = V { unV :: ReaderT GlobalHandles (ResourceT IO) a } + deriving newtype ( Functor + , Applicative + , Monad + , MonadIO + , MonadResource + ) + +instance MonadUnliftIO V where + withRunInIO a = V $ withRunInIO (\r -> a (r . unV)) + +newtype CmdT m a = CmdT { unCmdT :: ReaderT CommandBuffer m a } + deriving newtype ( Functor + , Applicative + , Monad + , MonadIO + , MonadResource + , HasVulkan + ) + +instance MonadUnliftIO m => MonadUnliftIO (CmdT m) where + withRunInIO a = CmdT $ withRunInIO (\r -> a (r . unCmdT)) + +class HasVulkan m where + getInstance :: m Instance + getGraphicsQueue :: m Queue + getPhysicalDevice :: m PhysicalDevice + getDevice :: m Device + getAllocator :: m Allocator + +instance HasVulkan V where + getInstance = V (asks ghInstance) + getGraphicsQueue = V (asks (snd . graphicsQueue . ghQueues)) + getPhysicalDevice = V (asks ghPhysicalDevice) + getDevice = V (asks ghDevice) + getAllocator = V (asks ghAllocator) + +instance (Monad m, HasVulkan m) => HasVulkan (ReaderT r m) where + getInstance = lift getInstance + getGraphicsQueue = lift getGraphicsQueue + getPhysicalDevice = lift getPhysicalDevice + getDevice = lift getDevice + getAllocator = lift getAllocator + +getGraphicsQueueFamilyIndex :: V QueueFamilyIndex +getGraphicsQueueFamilyIndex = V (asks (fst . graphicsQueue . ghQueues)) + +getCommandBuffer :: Monad m => CmdT m CommandBuffer +getCommandBuffer = CmdT ask + +useCommandBuffer' + :: forall a m r + . (Extendss CommandBufferBeginInfo a, PokeChain a, MonadIO m) + => CommandBuffer + -> CommandBufferBeginInfo a + -> CmdT m r + -> m r +useCommandBuffer' commandBuffer beginInfo (CmdT a) = + useCommandBuffer commandBuffer beginInfo (runReaderT a commandBuffer) + +runV + :: Instance + -> PhysicalDevice + -> Device + -> Queues (QueueFamilyIndex, Queue) + -> Allocator + -> V a + -> ResourceT IO a +runV ghInstance ghPhysicalDevice ghDevice ghQueues ghAllocator v = do + (bin, nib) <- liftIO newChan + let ghRecycleBin = writeChan bin + ghRecycleNib = do + (try, block) <- tryReadChan nib + maybe (Left block) Right <$> tryRead try + + flip runReaderT GlobalHandles { .. } . unV $ v + +-- | A bunch of global, unchanging state we cart around +data GlobalHandles = GlobalHandles + { ghInstance :: Instance + , ghPhysicalDevice :: PhysicalDevice + , ghDevice :: Device + , ghAllocator :: Allocator + , ghQueues :: Queues (QueueFamilyIndex, Queue) + , ghRecycleBin :: RecycledResources -> IO () + -- ^ Filled with resources which aren't destroyed after finishing a frame, + -- but instead are used by another frame which executes after that one is + -- retired, (taken from ghRecycleNib) + -- + -- Make sure not to pass any resources which were created with a frame-only + -- scope however! + , ghRecycleNib :: IO (Either (IO RecycledResources) RecycledResources) + -- ^ The resources of prior frames waiting to be taken + } + +-- | These are resources which are reused by a later frame when the current +-- frame is retired +data RecycledResources = RecycledResources + { fImageAvailableSemaphore :: Semaphore + -- ^ A binary semaphore passed to 'acquireNextImageKHR' + , fRenderFinishedSemaphore :: Semaphore + -- ^ A binary semaphore to synchronize rendering and presenting + , fCommandPool :: CommandPool + -- ^ Pool for this frame's commands (might want more than one of these for + -- multithreaded recording) + } + +-- | The shape of all the queues we use for our program, parameterized over the +-- queue type so we can use it with 'Vulkan.Utils.QueueAssignment.assignQueues' +newtype Queues q = Queues { graphicsQueue :: q } + deriving (Functor, Foldable, Traversable) + +---------------------------------------------------------------- +-- Helpers +---------------------------------------------------------------- + +-- Start an async thread which will be cancelled at the end of the ResourceT +-- block +spawn :: V a -> V (Async a) +spawn a = do + aIO <- toIO a + snd <$> allocate (async aIO) uninterruptibleCancel + +spawn_ :: V () -> V () +spawn_ = void . spawn + +---------------------------------------------------------------- +-- Commands +---------------------------------------------------------------- + +noAllocationCallbacks :: Maybe AllocationCallbacks +noAllocationCallbacks = Nothing + +-- +-- Wrap a bunch of Vulkan commands so that they automatically pull global +-- handles from any `HasVulkan` instance. +-- +-- Wrapped functions are suffixed with "'" +-- +do + let vmaCommands = + [ 'withBuffer + , 'invalidateAllocation + ] + commands = + [ 'acquireNextImageKHR + , 'allocateCommandBuffers + , 'allocateDescriptorSets + , 'cmdBindDescriptorSets + , 'cmdBindPipeline + , 'cmdDispatch + , 'cmdDraw + , 'cmdPushConstants + , 'cmdSetScissor + , 'cmdSetViewport + , 'cmdUseRenderPass + , 'deviceWaitIdle + , 'deviceWaitIdleSafe + , 'getDeviceQueue + , 'getPhysicalDeviceSurfaceCapabilitiesKHR + , 'getPhysicalDeviceSurfaceFormatsKHR + , 'getPhysicalDeviceSurfacePresentModesKHR + , 'getSwapchainImagesKHR + , 'resetCommandPool + , 'updateDescriptorSets + , 'waitForFences + , 'waitForFencesSafe + , 'Timeline.waitSemaphores + , 'Timeline.waitSemaphoresSafe + , 'withCommandBuffers + , 'withCommandPool + , 'withComputePipelines + , 'withDescriptorPool + , 'withDescriptorSetLayout + , 'withFence + , 'withFramebuffer + , 'withGraphicsPipelines + , 'withImageView + , 'withInstance + , 'withPipelineLayout + , 'withRenderPass + , 'withSemaphore + , 'withShaderModule + , 'withSwapchainKHR + ] + addTopDecls =<< [d|checkCommands = $(checkCommandsExp commands)|] + autoapplyDecs + (<> "'") + [ 'getDevice + , 'getPhysicalDevice + , 'getInstance + , 'getAllocator + , 'noAllocationCallbacks + , 'getCommandBuffer + ] + -- Allocate doesn't subsume the continuation type on the "with" commands, so + -- put it in the unifying group. + ['allocate] + (vmaCommands <> commands) diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs new file mode 100644 index 000000000..f8e2b57d9 --- /dev/null +++ b/examples/rays/Pipeline.hs @@ -0,0 +1,173 @@ +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedLists #-} + +module Pipeline + ( createPipeline + , Pipeline.createRenderPass + ) where + +import Control.Monad.Trans.Resource +import Data.Bits +import Data.Foldable ( traverse_ ) +import qualified Data.Vector as V +import MonadVulkan +import Vulkan.CStruct.Extends +import Vulkan.Core10 as Vk + hiding ( withBuffer + , withImage + ) +import Vulkan.Utils.ShaderQQ.Shaderc +import Vulkan.Zero + +-- Create the most vanilla rendering pipeline +createPipeline :: RenderPass -> V (ReleaseKey, Pipeline) +createPipeline renderPass = do + (shaderKeys, shaderStages ) <- V.unzip <$> createShaders + (layoutKey , pipelineLayout) <- withPipelineLayout' zero + let + pipelineCreateInfo :: GraphicsPipelineCreateInfo '[] + pipelineCreateInfo = zero + { stages = shaderStages + , vertexInputState = Just zero + , inputAssemblyState = Just zero + { topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST + , primitiveRestartEnable = False + } + , viewportState = Just + $ SomeStruct zero { viewportCount = 1, scissorCount = 1 } + , rasterizationState = SomeStruct $ zero + { depthClampEnable = False + , rasterizerDiscardEnable = False + , lineWidth = 1 + , polygonMode = POLYGON_MODE_FILL + , cullMode = CULL_MODE_NONE + , frontFace = FRONT_FACE_CLOCKWISE + , depthBiasEnable = False + } + , multisampleState = Just . SomeStruct $ zero + { sampleShadingEnable = False + , rasterizationSamples = SAMPLE_COUNT_1_BIT + , minSampleShading = 1 + , sampleMask = [maxBound] + } + , depthStencilState = Nothing + , colorBlendState = Just . SomeStruct $ zero + { logicOpEnable = False + , attachments = [ zero + { colorWriteMask = + COLOR_COMPONENT_R_BIT + .|. COLOR_COMPONENT_G_BIT + .|. COLOR_COMPONENT_B_BIT + .|. COLOR_COMPONENT_A_BIT + , blendEnable = False + } + ] + } + , dynamicState = Just zero + { dynamicStates = [ DYNAMIC_STATE_VIEWPORT + , DYNAMIC_STATE_SCISSOR + ] + } + , layout = pipelineLayout + , renderPass = renderPass + , subpass = 0 + , basePipelineHandle = zero + } + (key, (_, ~[graphicsPipeline])) <- withGraphicsPipelines' + zero + [SomeStruct pipelineCreateInfo] + release layoutKey + traverse_ release shaderKeys + pure (key, graphicsPipeline) + +-- | Create a renderpass with a single subpass +createRenderPass :: Format -> V (ReleaseKey, RenderPass) +createRenderPass imageFormat = do + let + attachmentDescription :: AttachmentDescription + attachmentDescription = zero + { format = imageFormat + , samples = SAMPLE_COUNT_1_BIT + , loadOp = ATTACHMENT_LOAD_OP_CLEAR + , storeOp = ATTACHMENT_STORE_OP_STORE + , stencilLoadOp = ATTACHMENT_LOAD_OP_DONT_CARE + , stencilStoreOp = ATTACHMENT_STORE_OP_DONT_CARE + , initialLayout = IMAGE_LAYOUT_UNDEFINED + , finalLayout = IMAGE_LAYOUT_PRESENT_SRC_KHR + } + subpass :: SubpassDescription + subpass = zero + { pipelineBindPoint = PIPELINE_BIND_POINT_GRAPHICS + , colorAttachments = + [ zero { attachment = 0 + , layout = IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + } + ] + } + subpassDependency :: SubpassDependency + subpassDependency = zero + { srcSubpass = SUBPASS_EXTERNAL + , dstSubpass = 0 + , srcStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + , srcAccessMask = zero + , dstStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + , dstAccessMask = ACCESS_COLOR_ATTACHMENT_READ_BIT + .|. ACCESS_COLOR_ATTACHMENT_WRITE_BIT + } + withRenderPass' zero { attachments = [attachmentDescription] + , subpasses = [subpass] + , dependencies = [subpassDependency] + } + +-- | Create a vertex and fragment shader which render a colored triangle +createShaders + :: V (V.Vector (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo)) +createShaders = do + let fragCode = [frag| + float4 main([[vk::location(0)]] const float3 col) : SV_TARGET + { + return float4(col, 1); + } + |] + vertCode = [vert| + const static float2 positions[3] = { + {0.0, -0.5}, + {0.5, 0.5}, + {-0.5, 0.5} + }; + + const static float3 colors[3] = { + {1.0, 1.0, 0.0}, + {0.0, 1.0, 1.0}, + {1.0, 0.0, 1.0} + }; + + struct VSOutput + { + float4 pos : SV_POSITION; + [[vk::location(0)]] float3 col; + }; + + VSOutput main(const uint i : SV_VertexID) + { + VSOutput output; + output.pos = float4(positions[i], 0, 1.0); + output.col = colors[i]; + return output; + } + |] + (fragKey, fragModule) <- withShaderModule' zero { code = fragCode } + (vertKey, vertModule) <- withShaderModule' zero { code = vertCode } + let vertShaderStageCreateInfo = zero { stage = SHADER_STAGE_VERTEX_BIT + , module' = vertModule + , name = "main" + } + fragShaderStageCreateInfo = zero { stage = SHADER_STAGE_FRAGMENT_BIT + , module' = fragModule + , name = "main" + } + pure + [ (vertKey, SomeStruct vertShaderStageCreateInfo) + , (fragKey, SomeStruct fragShaderStageCreateInfo) + ] diff --git a/examples/rays/RefCounted.hs b/examples/rays/RefCounted.hs new file mode 100644 index 000000000..e8f16bb4e --- /dev/null +++ b/examples/rays/RefCounted.hs @@ -0,0 +1,49 @@ +module RefCounted where + +import Control.Exception ( throwIO ) +import Control.Monad.IO.Class ( MonadIO + , liftIO + ) +import Data.IORef +import GHC.IO.Exception ( IOErrorType(UserError) + , IOException(IOError) + ) +import UnliftIO.Exception ( mask ) +import Control.Monad +import Control.Monad.Trans.Resource (MonadResource, allocate_) + +-- | A 'RefCounted' will perform the specified action when the count reaches 0 +data RefCounted = RefCounted + { rcCount :: IORef Int + , rcAction :: IO () + } + +-- | Create a counter with a value of 1 +newRefCounted :: MonadIO m => IO () -> m RefCounted +newRefCounted rcAction = do + rcCount <- liftIO $ newIORef 1 + pure RefCounted { .. } + +-- | Decrement the value, the action will be run promptly and in +-- this thread if the counter reached 0. +releaseRefCounted :: MonadIO m => RefCounted -> m () +releaseRefCounted RefCounted {..} = liftIO $ mask $ \_ -> + atomicModifyIORef' rcCount (\c -> (pred c, pred c)) >>= \case + 0 -> rcAction + n | n < 0 -> liftIO . throwIO $ IOError + Nothing + UserError + "" + "Ref counted value decremented below 0" + Nothing + Nothing + _ -> pure () + +-- | Increment the counter by 1 +takeRefCounted :: MonadIO m => RefCounted -> m () +takeRefCounted RefCounted {..} = + liftIO $ atomicModifyIORef' rcCount (\c -> (succ c, ())) + +-- | Hold a reference for the duration of the 'MonadResource' action +resourceTRefCount :: MonadResource f => RefCounted -> f () +resourceTRefCount r = void $ allocate_ (takeRefCounted r) (releaseRefCounted r) diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs new file mode 100644 index 000000000..7fc97223b --- /dev/null +++ b/examples/rays/Render.hs @@ -0,0 +1,123 @@ +{-# LANGUAGE OverloadedLists #-} + +module Render + ( renderFrame + ) where + +import Control.Exception ( throwIO ) +import Control.Monad.IO.Class +import Data.Vector ( (!) ) +import Data.Word +import Frame +import GHC.IO.Exception ( IOErrorType(TimeExpired) + , IOException(IOError) + ) +import MonadFrame +import MonadVulkan +import Say +import Swapchain +import UnliftIO.Exception ( throwString ) +import Vulkan.CStruct.Extends +import Vulkan.Core10 as Core10 +import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore +import Vulkan.Extensions.VK_KHR_swapchain + as Swap +import Vulkan.Zero + +renderFrame :: F () +renderFrame = do + f@Frame {..} <- askFrame + let RecycledResources {..} = fRecycledResources + let oneSecond = 1e9 + SwapchainResources {..} = fSwapchainResources + SwapchainInfo {..} = srInfo + + -- Ensure that the swapchain survives for the duration of this frame + frameRefCount srRelease + + -- Make sure we'll have an image to render to + imageIndex <- + acquireNextImageKHR' siSwapchain + oneSecond + fImageAvailableSemaphore + NULL_HANDLE + >>= \case + (SUCCESS, imageIndex) -> pure imageIndex + (TIMEOUT, _) -> + timeoutError "Timed out (1s) trying to acquire next image" + _ -> throwString "Unexpected Result from acquireNextImageKHR" + + -- Allocate a command buffer and populate it + let commandBufferAllocateInfo = zero { commandPool = fCommandPool + , level = COMMAND_BUFFER_LEVEL_PRIMARY + , commandBufferCount = 1 + } + ~[commandBuffer] <- allocateCommandBuffers' commandBufferAllocateInfo + useCommandBuffer' commandBuffer zero $ myRecordCommandBuffer f imageIndex + + -- Submit the work + let -- Wait for the 'imageAvailableSemaphore' before outputting to the color + -- attachment + submitInfo = + zero + { Core10.waitSemaphores = [fImageAvailableSemaphore] + , waitDstStageMask = [PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT] + , commandBuffers = [commandBufferHandle commandBuffer] + , signalSemaphores = [ fRenderFinishedSemaphore + , fRenderFinishedHostSemaphore + ] + } + ::& zero { waitSemaphoreValues = [1] + , signalSemaphoreValues = [1, fIndex] + } + :& () + graphicsQueue <- getGraphicsQueue + queueSubmitFrame graphicsQueue + [SomeStruct submitInfo] + fRenderFinishedHostSemaphore + fIndex + + -- Present the frame when the render is finished + -- The return code here could be SUBOPTIMAL_KHR + -- TODO, check for that + _ <- queuePresentKHR + graphicsQueue + zero { Swap.waitSemaphores = [fRenderFinishedSemaphore] + , swapchains = [siSwapchain] + , imageIndices = [imageIndex] + } + sayErrString ("submitted " <> show fIndex) + +-- | Clear and render a triangle +myRecordCommandBuffer :: MonadIO m => Frame -> Word32 -> CmdT m () +myRecordCommandBuffer Frame {..} imageIndex = do + let SwapchainResources {..} = fSwapchainResources + SwapchainInfo {..} = srInfo + renderPassBeginInfo = zero + { renderPass = srRenderPass + , framebuffer = srFramebuffers ! fromIntegral imageIndex + , renderArea = Rect2D { offset = zero, extent = siImageExtent } + , clearValues = [Color (Float32 (0.3, 0.4, 0.8, 1))] + } + cmdUseRenderPass' renderPassBeginInfo SUBPASS_CONTENTS_INLINE $ do + cmdSetViewport' + 0 + [ Viewport { x = 0 + , y = 0 + , width = realToFrac (width (siImageExtent :: Extent2D)) + , height = realToFrac (height (siImageExtent :: Extent2D)) + , minDepth = 0 + , maxDepth = 1 + } + ] + cmdSetScissor' 0 [Rect2D { offset = Offset2D 0 0, extent = siImageExtent }] + cmdBindPipeline' PIPELINE_BIND_POINT_GRAPHICS fPipeline + cmdDraw' 3 1 0 0 + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +timeoutError :: MonadIO m => String -> m a +timeoutError message = + liftIO . throwIO $ IOError Nothing TimeExpired "" message Nothing Nothing diff --git a/examples/rays/RenderPass.hs b/examples/rays/RenderPass.hs new file mode 100644 index 000000000..0e083fa73 --- /dev/null +++ b/examples/rays/RenderPass.hs @@ -0,0 +1,55 @@ +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE OverloadedLists #-} + +module RenderPass + ( RenderPass.createRenderPass + ) where + +import Control.Monad.Trans.Resource +import Data.Bits +import MonadVulkan +import Vulkan.Core10 as Vk + hiding ( withBuffer + , withImage + ) +import Vulkan.Zero + +-- | Create a renderpass with a single subpass +createRenderPass :: Format -> V (ReleaseKey, RenderPass) +createRenderPass imageFormat = do + let + attachmentDescription :: AttachmentDescription + attachmentDescription = zero + { format = imageFormat + , samples = SAMPLE_COUNT_1_BIT + , loadOp = ATTACHMENT_LOAD_OP_CLEAR + , storeOp = ATTACHMENT_STORE_OP_STORE + , stencilLoadOp = ATTACHMENT_LOAD_OP_DONT_CARE + , stencilStoreOp = ATTACHMENT_STORE_OP_DONT_CARE + , initialLayout = IMAGE_LAYOUT_UNDEFINED + , finalLayout = IMAGE_LAYOUT_PRESENT_SRC_KHR + } + subpass :: SubpassDescription + subpass = zero + { pipelineBindPoint = PIPELINE_BIND_POINT_GRAPHICS + , colorAttachments = + [ zero { attachment = 0 + , layout = IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + } + ] + } + subpassDependency :: SubpassDependency + subpassDependency = zero + { srcSubpass = SUBPASS_EXTERNAL + , dstSubpass = 0 + , srcStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + , srcAccessMask = zero + , dstStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + , dstAccessMask = ACCESS_COLOR_ATTACHMENT_READ_BIT + .|. ACCESS_COLOR_ATTACHMENT_WRITE_BIT + } + withRenderPass' zero { attachments = [attachmentDescription] + , subpasses = [subpass] + , dependencies = [subpassDependency] + } diff --git a/examples/rays/Swapchain.hs b/examples/rays/Swapchain.hs new file mode 100644 index 000000000..8498d2896 --- /dev/null +++ b/examples/rays/Swapchain.hs @@ -0,0 +1,231 @@ +module Swapchain + ( SwapchainInfo(..) + , SwapchainResources(..) + , allocSwapchainResources + , recreateSwapchainResources + , threwSwapchainError + ) where + +import Control.Monad +import Control.Monad.Trans.Resource +import Data.Bits +import Data.Either +import Data.Foldable ( for_ + , traverse_ + ) +import Data.Ord ( comparing ) +import qualified Data.Vector as V +import Data.Vector ( Vector ) +import Framebuffer +import MonadVulkan +import RefCounted +import RenderPass +import qualified SDL +import qualified SDL.Video.Vulkan as SDL +import UnliftIO.Exception ( throwString + , tryJust + ) +import Vulkan.Core10 +import Vulkan.Exception +import Vulkan.Extensions.VK_KHR_surface +import Vulkan.Extensions.VK_KHR_swapchain +import Vulkan.Utils.Misc +import Vulkan.Zero + +data SwapchainInfo = SwapchainInfo + { siSwapchain :: SwapchainKHR + , siSwapchainReleaseKey :: ReleaseKey + , siPresentMode :: PresentModeKHR + , siSurfaceFormat :: SurfaceFormatKHR + , siImageExtent :: Extent2D + , siSurface :: SurfaceKHR + } + +data SwapchainResources = SwapchainResources + { srInfo :: SwapchainInfo + , srFramebuffers :: Vector Framebuffer + , srImageViews :: Vector ImageView + , srImages :: Vector Image + , srRenderPass :: RenderPass + , srRelease :: RefCounted + } + +---------------------------------------------------------------- +-- All the resources which depend on the swapchain +---------------------------------------------------------------- + +-- | Allocate everything which depends on the swapchain +allocSwapchainResources + :: SwapchainKHR + -- ^ Previous swapchain, can be NULL_HANDLE + -> Extent2D + -- ^ If the swapchain size determines the surface size, use this size + -> SurfaceKHR + -> V SwapchainResources +allocSwapchainResources oldSwapchain windowSize surface = do + info@SwapchainInfo {..} <- createSwapchain oldSwapchain windowSize surface + + -- TODO: cache this, it's probably not going to change + (renderPassKey, srRenderPass) <- RenderPass.createRenderPass + (format (siSurfaceFormat :: SurfaceFormatKHR)) + + -- Get all the swapchain images, and create views for them + (_ , swapchainImages) <- getSwapchainImagesKHR' siSwapchain + (imageViewKeys, imageViews ) <- + fmap V.unzip . V.forM swapchainImages $ \image -> + Framebuffer.createImageView + (format (siSurfaceFormat :: SurfaceFormatKHR)) + image + + -- Also create a framebuffer for each one + (framebufferKeys, framebuffers) <- + fmap V.unzip . V.forM imageViews $ \imageView -> + Framebuffer.createFramebuffer srRenderPass imageView siImageExtent + + -- This refcount is released in 'recreateSwapchainResources' + releaseResources <- newRefCounted $ do + traverse_ release framebufferKeys + traverse_ release imageViewKeys + release renderPassKey + release siSwapchainReleaseKey + + pure $ SwapchainResources info + framebuffers + imageViews + swapchainImages + srRenderPass + releaseResources + +recreateSwapchainResources + :: SDL.Window + -> SwapchainResources + -- ^ The reference to these resources will be dropped + -> V SwapchainResources +recreateSwapchainResources win oldResources = do + SDL.V2 width height <- SDL.vkGetDrawableSize win + let oldSwapchain = siSwapchain . srInfo $ oldResources + oldSurface = siSurface . srInfo $ oldResources + r <- allocSwapchainResources + oldSwapchain + (Extent2D (fromIntegral width) (fromIntegral height)) + oldSurface + releaseRefCounted (srRelease oldResources) + pure r + +---------------------------------------------------------------- +-- Creating the actual swapchain +---------------------------------------------------------------- + +-- | Create a swapchain from a 'SurfaceKHR' +createSwapchain + :: SwapchainKHR + -- ^ Old swapchain, can be NULL_HANDLE + -> Extent2D + -- ^ If the swapchain size determines the surface size, use this size + -> SurfaceKHR + -> V SwapchainInfo +createSwapchain oldSwapchain explicitSize surf = do + surfaceCaps <- getPhysicalDeviceSurfaceCapabilitiesKHR' surf + + -- Check flags + for_ requiredUsageFlags $ \f -> + unless (supportedUsageFlags surfaceCaps .&&. f) + $ throwString ("Surface images do not support " <> show f) + + -- Select a present mode + (_, availablePresentModes) <- getPhysicalDeviceSurfacePresentModesKHR' surf + presentMode <- + case filter (`V.elem` availablePresentModes) desiredPresentModes of + [] -> throwString "Unable to find a suitable present mode for swapchain" + x : _ -> pure x + + -- Select a surface format + -- getPhysicalDeviceSurfaceFormatsKHR doesn't return an empty list + (_, availableFormats) <- getPhysicalDeviceSurfaceFormatsKHR' surf + let surfaceFormat = selectSurfaceFormat availableFormats + + -- Calculate the extent + let imageExtent = + case currentExtent (surfaceCaps :: SurfaceCapabilitiesKHR) of + Extent2D w h | w == maxBound, h == maxBound -> explicitSize + e -> e + + let + imageCount = + let + limit = case maxImageCount (surfaceCaps :: SurfaceCapabilitiesKHR) of + 0 -> maxBound + n -> n + -- Request one additional image to prevent us having to wait for + -- the driver to finish + buffer = 1 + desired = + buffer + minImageCount (surfaceCaps :: SurfaceCapabilitiesKHR) + in + min limit desired + + compositeAlphaMode <- + if COMPOSITE_ALPHA_OPAQUE_BIT_KHR .&&. supportedCompositeAlpha surfaceCaps + then pure COMPOSITE_ALPHA_OPAQUE_BIT_KHR + else throwString "Surface doesn't support COMPOSITE_ALPHA_OPAQUE_BIT_KHR" + + let + swapchainCreateInfo = SwapchainCreateInfoKHR + { surface = surf + , next = () + , flags = zero + , queueFamilyIndices = mempty -- No need to specify when not using concurrent access + , minImageCount = imageCount + , imageFormat = format (surfaceFormat :: SurfaceFormatKHR) + , imageColorSpace = colorSpace surfaceFormat + , imageExtent = imageExtent + , imageArrayLayers = 1 + , imageUsage = foldr (.|.) zero requiredUsageFlags + , imageSharingMode = SHARING_MODE_EXCLUSIVE + , preTransform = currentTransform (surfaceCaps :: SurfaceCapabilitiesKHR) + , compositeAlpha = compositeAlphaMode + , presentMode = presentMode + , clipped = True + , oldSwapchain = oldSwapchain + } + + (key, swapchain) <- withSwapchainKHR' swapchainCreateInfo + + pure $ SwapchainInfo swapchain key presentMode surfaceFormat imageExtent surf + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +-- | Catch an ERROR_OUT_OF_DATE_KHR exception and return 'True' if that happened +threwSwapchainError :: V a -> V Bool +threwSwapchainError = fmap isLeft . tryJust swapchainError + where + swapchainError = \case + VulkanException e@ERROR_OUT_OF_DATE_KHR -> Just e + -- TODO handle this case + -- VulkanException e@ERROR_SURFACE_LOST_KHR -> Just e + VulkanException _ -> Nothing + +---------------------------------------------------------------- +-- Specifications +---------------------------------------------------------------- + +-- The vector passed will have at least one element +selectSurfaceFormat :: Vector SurfaceFormatKHR -> SurfaceFormatKHR +selectSurfaceFormat = V.maximumBy (comparing surfaceFormatScore) + where + -- An ordered list of formats to choose for the swapchain images, if none + -- match then the first available format will be chosen. + surfaceFormatScore :: SurfaceFormatKHR -> Int + surfaceFormatScore = \case + _ -> 0 + +-- | An ordered list of the present mode to be chosen for the swapchain. +desiredPresentModes :: [PresentModeKHR] +desiredPresentModes = + [PRESENT_MODE_MAILBOX_KHR, PRESENT_MODE_FIFO_KHR, PRESENT_MODE_IMMEDIATE_KHR] + +-- | The images in the swapchain must support these flags. +requiredUsageFlags :: [ImageUsageFlagBits] +requiredUsageFlags = [IMAGE_USAGE_COLOR_ATTACHMENT_BIT] diff --git a/examples/rays/Utils.hs b/examples/rays/Utils.hs new file mode 100644 index 000000000..d3197ae55 --- /dev/null +++ b/examples/rays/Utils.hs @@ -0,0 +1,14 @@ +module Utils where + +import Control.Concurrent ( ) +import Control.Monad + +loopJust :: Monad m => (a -> m (Maybe a)) -> a -> m () +loopJust f x = f x >>= \case + Nothing -> pure () + Just x' -> loopJust f x' + +loopUntilM :: Monad m => m Bool -> m () +loopUntilM m = do + q <- m + unless q $ loopUntilM m diff --git a/examples/rays/Window.hs b/examples/rays/Window.hs new file mode 100644 index 000000000..e00517a7c --- /dev/null +++ b/examples/rays/Window.hs @@ -0,0 +1,71 @@ +module Window + ( withSDL + , createWindow + , createSurface + , shouldQuit + ) where + +import Control.Monad ( void ) +import Control.Monad.IO.Class +import Control.Monad.Trans.Resource +import Data.Text ( Text ) +import Foreign.Ptr ( castPtr ) +import qualified SDL +import qualified SDL.Video.Vulkan as SDL +import Vulkan.Core10 +import Vulkan.Extensions.VK_KHR_surface + +withSDL :: MonadResource m => m () +withSDL = void $ allocate_ (SDL.initialize @[] [SDL.InitEvents]) SDL.quit + +-- | The caller is responsible to initializing SDL +createWindow + :: MonadResource m + => Text + -- ^ Title + -> Int + -- ^ Width + -> Int + -- ^ Height + -> m SDL.Window +createWindow title width height = do + SDL.initialize @[] [SDL.InitVideo] + _ <- allocate_ (SDL.vkLoadLibrary Nothing) SDL.vkUnloadLibrary + (_, window) <- allocate + (SDL.createWindow + title + (SDL.defaultWindow + { SDL.windowInitialSize = SDL.V2 (fromIntegral width) + (fromIntegral height) + , SDL.windowGraphicsContext = SDL.VulkanContext + , SDL.windowResizable = True + , SDL.windowHighDPI = True + , SDL.windowVisible = False + } + ) + ) + SDL.destroyWindow + pure window + +createSurface + :: MonadResource m => Instance -> SDL.Window -> m (ReleaseKey, SurfaceKHR) +createSurface inst window = allocate + (SurfaceKHR <$> SDL.vkCreateSurface window (castPtr (instanceHandle inst))) + (\s -> destroySurfaceKHR inst s Nothing) + +---------------------------------------------------------------- +-- SDL helpers +---------------------------------------------------------------- + +-- | Consumes all events in the queue and reports if any of them instruct the +-- application to quit. +shouldQuit :: MonadIO m => m Bool +shouldQuit = any isQuitEvent <$> SDL.pollEvents + where + isQuitEvent :: SDL.Event -> Bool + isQuitEvent = \case + (SDL.Event _ SDL.QuitEvent) -> True + SDL.Event _ (SDL.KeyboardEvent (SDL.KeyboardEventData _ SDL.Released False (SDL.Keysym _ code _))) + | code == SDL.KeycodeQ || code == SDL.KeycodeEscape + -> True + _ -> False diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index f9cd131ea..7e352069c 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -4,7 +4,7 @@ cabal-version: 2.2 -- -- see: https://github.com/sol/hpack -- --- hash: 07469fd86a282e5431bb11f41a2b513268d1238cb7897b4d75f8a5ecda9438f5 +-- hash: bc5abd880f041e8504775a9c3c25fe244ed6f7424022d9f3d8e9952babf82155 name: vulkan-examples version: 0.1.0.0 @@ -160,6 +160,56 @@ executable offscreen , inline-c default-language: Haskell2010 +executable rays + main-is: Main.hs + other-modules: + Cache + Frame + Framebuffer + Init + MonadFrame + MonadVulkan + Pipeline + RefCounted + Render + RenderPass + Swapchain + Utils + Window + Paths_vulkan_examples + hs-source-dirs: + rays + default-extensions: DataKinds DefaultSignatures DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NamedFieldPuns NoMonomorphismRestriction NumDecimals OverloadedStrings PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns + ghc-options: -Wall -threaded -O2 -rtsopts -with-rtsopts=-N + build-depends: + VulkanMemoryAllocator + , autoapply >=0.4 + , base <5 + , bytestring + , containers + , extra + , file-embed + , filepath + , primitive-unlifted + , resourcet >=1.2.4 + , say + , sdl2 >=2.5.2.0 + , template-haskell + , temporary + , text + , transformers + , typed-process + , unagi-chan + , unliftio + , vector + , vulkan + , vulkan-utils + if os(windows) + ghc-options: -optl-mconsole + if impl(ghc < 8.10.0) + buildable: False + default-language: Haskell2010 + executable resize main-is: Main.hs other-modules: From 5ef12ab5ee6bcd317d1c4e780d323edbfa3ff103 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 12:55:22 +0800 Subject: [PATCH 15/70] Clean example readme for swiftshader --- examples/readme.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/readme.md b/examples/readme.md index e3eb51414..134952145 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -140,9 +140,11 @@ stack --system-ghc --nix --no-nix-pure run sdl-triangle Note that not all of the examples run under SwiftShader. ```bash -swiftshader=$(nix-build --no-out-link --expr '(import ../nix/nixpkgs.nix).swiftshader') -export VK_ICD_FILENAMES=$swiftshader/share/vulkan/icd.d/vk_swiftshader_icd.json -cabal run sdl-triangle +# This will set VK_ICD_FILENAMES to the swiftshader ICD +# It will also enable the timeline-semaphore emulation layer as swiftshader +# lacks support +nix-shell --arg withSwiftshader true +cabal run hlsl ``` ### Troubleshooting From 7fdffaf7b2ad7e40650253922f6818a53e72e333 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 13:37:38 +0800 Subject: [PATCH 16/70] Check for RT support --- examples/rays/Init.hs | 46 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index 3c7a878c5..d255048c0 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -36,7 +36,17 @@ import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) +import Vulkan.Extensions.VK_KHR_buffer_device_address + ( pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + ) +import Vulkan.Extensions.VK_KHR_deferred_host_operations + ( pattern KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + ) import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 +import Vulkan.Extensions.VK_KHR_pipeline_library + ( pattern KHR_PIPELINE_LIBRARY_EXTENSION_NAME + ) +import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.Initialization @@ -95,8 +105,15 @@ createDevice inst win = do zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } ::& PhysicalDeviceTimelineSemaphoreFeatures True :& () + rayTracingExtensions = + [ KHR_RAY_TRACING_EXTENSION_NAME + , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , KHR_PIPELINE_LIBRARY_EXTENSION_NAME + ] extensions = [KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, KHR_SWAPCHAIN_EXTENSION_NAME] + <> rayTracingExtensions dev <- createDeviceWithExtensions phys [] extensions deviceCreateInfo requireCommands inst dev queues <- liftIO $ pdiGetQueues pdi dev @@ -129,6 +146,14 @@ physicalDeviceInfo surf phys = runMaybeT $ do <> " because it doesn't support timeline semaphores" empty + hasRayTracing <- deviceHasRayTracing phys + unless hasRayTracing $ do + sayErr + $ "Not using physical device " + <> deviceName + <> " because it doesn't support ray tracing" + empty + hasSwapchainSupport <- deviceHasSwapchain phys unless hasSwapchainSupport $ do sayErr @@ -180,12 +205,31 @@ deviceHasTimelineSemaphores phys = do hasFeat = do feats <- getPhysicalDeviceFeatures2KHR phys let - _ ::& (PhysicalDeviceTimelineSemaphoreFeatures hasTimelineSemaphores :& ()) + _ ::& PhysicalDeviceTimelineSemaphoreFeatures hasTimelineSemaphores :& () = feats pure hasTimelineSemaphores hasExt <&&> hasFeat +deviceHasRayTracing :: MonadIO m => PhysicalDevice -> m Bool +deviceHasRayTracing phys = do + let hasExt = do + (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing + pure $ V.any ((KHR_RAY_TRACING_EXTENSION_NAME ==) . extensionName) + extensions + + hasFeat = do + feats <- getPhysicalDeviceFeatures2KHR phys + let _ ::& PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats + pure rayTracing + + hasProps = do + props <- getPhysicalDeviceProperties2KHR phys + let _ ::& PhysicalDeviceRayTracingPropertiesKHR {..} :& () = props + pure True + + hasExt <&&> hasFeat <&&> hasProps + ---------------------------------------------------------------- -- VulkanMemoryAllocator ---------------------------------------------------------------- From ecbd1645dc66c568761d6f445d2f12d3eb025861 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 16:04:18 +0800 Subject: [PATCH 17/70] Initial working version of ray tracing, Just a blue background at the moment written from the ray generation shader Big thanks to https://nvpro-samples.github.io/vk_raytracing_tutorial_KHR --- examples/rays/DescriptorSet.hs | 4 + examples/rays/Frame.hs | 18 ++- examples/rays/Init.hs | 50 +++++-- examples/rays/Main.hs | 13 +- examples/rays/MonadVulkan.hs | 22 ++- examples/rays/Pipeline.hs | 249 ++++++++++++++++++--------------- examples/rays/Render.hs | 85 ++++++++--- examples/rays/Swapchain.hs | 3 +- examples/vulkan-examples.cabal | 3 +- 9 files changed, 296 insertions(+), 151 deletions(-) create mode 100644 examples/rays/DescriptorSet.hs diff --git a/examples/rays/DescriptorSet.hs b/examples/rays/DescriptorSet.hs new file mode 100644 index 000000000..6fe435a1f --- /dev/null +++ b/examples/rays/DescriptorSet.hs @@ -0,0 +1,4 @@ +module DescriptorSet where + +createDescriptorSet = do + pure () diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index f1de9c858..dfb9e8d01 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -26,6 +26,7 @@ import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore import Vulkan.Extensions.VK_KHR_surface import Vulkan.Utils.QueueAssignment import Vulkan.Zero +import Data.Vector (Vector) -- | Must be positive, duh numConcurrentFrames :: Int @@ -40,6 +41,9 @@ data Frame = Frame , fSurface :: SurfaceKHR , fSwapchainResources :: SwapchainResources , fPipeline :: Pipeline + , fPipelineLayout :: PipelineLayout + , fDescriptorSets :: Vector DescriptorSet + , fShaderBindingTable :: Buffer , fRenderFinishedHostSemaphore :: Semaphore -- ^ A timeline semaphore which increments to fIndex when this frame is -- done, the host can wait on this semaphore @@ -82,8 +86,17 @@ initialFrame fWindow fSurface = do -- TODO: Cache this -- TODO: Recreate this if the swapchain format changes + (_releaseDescriptorSetLayout, descriptorSetLayout) <- + Pipeline.createRTDescriptorSetLayout + (_releasePipelineLayout, fPipelineLayout) <- Pipeline.createRTPipelineLayout + descriptorSetLayout (_releasePipeline, fPipeline) <- Pipeline.createPipeline - (srRenderPass fSwapchainResources) + fPipelineLayout + (_releaseSBT, fShaderBindingTable) <- Pipeline.createShaderBindingTable + fPipeline + fDescriptorSets <- Pipeline.createRTDescriptorSets + descriptorSetLayout + (srImageViews fSwapchainResources) -- Don't keep the release key, this semaphore lives for the lifetime of the -- application @@ -128,6 +141,9 @@ advanceFrame needsNewSwapchain f = do , fSurface = fSurface f , fSwapchainResources , fPipeline = fPipeline f + , fPipelineLayout = fPipelineLayout f + , fDescriptorSets = fDescriptorSets f + , fShaderBindingTable = fShaderBindingTable f , fRenderFinishedHostSemaphore = fRenderFinishedHostSemaphore f , fGPUWork , fResources diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index d255048c0..a707e975a 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -1,6 +1,7 @@ module Init ( Init.createInstance , Init.createDevice + , PhysicalDeviceInfo(..) , createVMA , createCommandPools ) where @@ -26,6 +27,7 @@ import GHC.IO.Exception ( IOErrorType(NoSuchThing) , IOException(IOError) ) import MonadVulkan ( Queues(..) + , RTInfo(..) , checkCommands , noAllocationCallbacks ) @@ -36,13 +38,22 @@ import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) +import Vulkan.Extensions.VK_EXT_descriptor_indexing + ( pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + ) import Vulkan.Extensions.VK_KHR_buffer_device_address ( pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME ) import Vulkan.Extensions.VK_KHR_deferred_host_operations ( pattern KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME ) +import Vulkan.Extensions.VK_KHR_get_memory_requirements2 + ( pattern KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + ) import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 +import Vulkan.Extensions.VK_KHR_maintenance3 + ( pattern KHR_MAINTENANCE3_EXTENSION_NAME + ) import Vulkan.Extensions.VK_KHR_pipeline_library ( pattern KHR_PIPELINE_LIBRARY_EXTENSION_NAME ) @@ -91,6 +102,7 @@ createDevice -> SDL.Window -> m ( PhysicalDevice + , PhysicalDeviceInfo , Device , Queues (QueueFamilyIndex, Queue) , SurfaceKHR @@ -104,11 +116,15 @@ createDevice inst win = do let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } ::& PhysicalDeviceTimelineSemaphoreFeatures True + :& zero { rayTracing = True } :& () rayTracingExtensions = [ KHR_RAY_TRACING_EXTENSION_NAME + , EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , KHR_MAINTENANCE3_EXTENSION_NAME , KHR_PIPELINE_LIBRARY_EXTENSION_NAME ] extensions = @@ -117,7 +133,7 @@ createDevice inst win = do dev <- createDeviceWithExtensions phys [] extensions deviceCreateInfo requireCommands inst dev queues <- liftIO $ pdiGetQueues pdi dev - pure (phys, dev, queues, surf) + pure (phys, pdi, dev, queues, surf) ---------------------------------------------------------------- -- Physical device tools @@ -126,6 +142,7 @@ createDevice inst win = do -- | The Ord instance prioritises devices with more memory data PhysicalDeviceInfo = PhysicalDeviceInfo { pdiTotalMemory :: Word64 + , pdiRTInfo :: RTInfo , pdiQueueCreateInfos :: Vector (DeviceQueueCreateInfo '[]) , pdiGetQueues :: Device -> IO (Queues (QueueFamilyIndex, Queue)) } @@ -146,13 +163,7 @@ physicalDeviceInfo surf phys = runMaybeT $ do <> " because it doesn't support timeline semaphores" empty - hasRayTracing <- deviceHasRayTracing phys - unless hasRayTracing $ do - sayErr - $ "Not using physical device " - <> deviceName - <> " because it doesn't support ray tracing" - empty + pdiRTInfo <- deviceHasRayTracing phys hasSwapchainSupport <- deviceHasSwapchain phys unless hasSwapchainSupport $ do @@ -211,8 +222,11 @@ deviceHasTimelineSemaphores phys = do hasExt <&&> hasFeat -deviceHasRayTracing :: MonadIO m => PhysicalDevice -> m Bool +deviceHasRayTracing :: MonadIO m => PhysicalDevice -> MaybeT m RTInfo + -- ^ Shader group size and alignment deviceHasRayTracing phys = do + deviceName <- physicalDeviceName phys + let hasExt = do (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing pure $ V.any ((KHR_RAY_TRACING_EXTENSION_NAME ==) . extensionName) @@ -223,12 +237,22 @@ deviceHasRayTracing phys = do let _ ::& PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats pure rayTracing - hasProps = do + getProps = do props <- getPhysicalDeviceProperties2KHR phys let _ ::& PhysicalDeviceRayTracingPropertiesKHR {..} :& () = props - pure True - - hasExt <&&> hasFeat <&&> hasProps + pure RTInfo { rtiShaderGroupHandleSize = shaderGroupHandleSize + , rtiShaderGroupBaseAlignment = shaderGroupBaseAlignment + } + + has <- hasExt <&&> hasFeat + if has + then getProps + else do + sayErr + $ "Not using physical device " + <> deviceName + <> " because it doesn't support ray tracing" + empty ---------------------------------------------------------------- -- VulkanMemoryAllocator diff --git a/examples/rays/Main.hs b/examples/rays/Main.hs index bf238960d..44bc04805 100644 --- a/examples/rays/Main.hs +++ b/examples/rays/Main.hs @@ -13,6 +13,7 @@ import SDL ( showWindow import Swapchain ( threwSwapchainError ) import Utils import Window +import System.Exit (exitSuccess) main :: IO () main = runResourceT $ do @@ -20,15 +21,15 @@ main = runResourceT $ do -- Initialization -- withSDL - win <- createWindow "Vulkan 🚀 Haskell" 1280 720 - inst <- Init.createInstance win - (phys, dev, qs, surf) <- Init.createDevice inst win - vma <- createVMA inst phys dev + win <- createWindow "Vulkan ⚡ Haskell" 1280 720 + inst <- Init.createInstance win + (phys, PhysicalDeviceInfo {..}, dev, qs, surf) <- Init.createDevice inst win + vma <- createVMA inst phys dev -- -- Go -- - start <- SDL.time @Double + start <- SDL.time @Double let reportFPS f = do end <- SDL.time let frames = fIndex f @@ -44,7 +45,7 @@ main = runResourceT $ do needsNewSwapchain <- threwSwapchainError (runFrame f renderFrame) advanceFrame needsNewSwapchain f - runV inst phys dev qs vma $ do + runV inst phys pdiRTInfo dev qs vma $ do initial <- initialFrame win surf showWindow win loopJust frame initial diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index d7b5180b6..a41bcbaeb 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -17,6 +17,7 @@ import UnliftIO ( Async ) import Control.Concurrent.Chan.Unagi +import Data.Word import Language.Haskell.TH.Syntax ( addTopDecls ) import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk @@ -25,12 +26,14 @@ import Vulkan.Core10 as Vk ) import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore as Timeline +import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.CommandCheck import Vulkan.Utils.QueueAssignment import VulkanMemoryAllocator as VMA hiding ( getPhysicalDeviceProperties ) +import Vulkan.Utils.Debug (nameObject) ---------------------------------------------------------------- -- Define the monad in which most of the program will run @@ -85,6 +88,9 @@ instance (Monad m, HasVulkan m) => HasVulkan (ReaderT r m) where getGraphicsQueueFamilyIndex :: V QueueFamilyIndex getGraphicsQueueFamilyIndex = V (asks (fst . graphicsQueue . ghQueues)) +getRTInfo :: V RTInfo +getRTInfo = V (asks ghRTInfo) + getCommandBuffer :: Monad m => CmdT m CommandBuffer getCommandBuffer = CmdT ask @@ -101,12 +107,13 @@ useCommandBuffer' commandBuffer beginInfo (CmdT a) = runV :: Instance -> PhysicalDevice + -> RTInfo -> Device -> Queues (QueueFamilyIndex, Queue) -> Allocator -> V a -> ResourceT IO a -runV ghInstance ghPhysicalDevice ghDevice ghQueues ghAllocator v = do +runV ghInstance ghPhysicalDevice ghRTInfo ghDevice ghQueues ghAllocator v = do (bin, nib) <- liftIO newChan let ghRecycleBin = writeChan bin ghRecycleNib = do @@ -131,6 +138,13 @@ data GlobalHandles = GlobalHandles -- scope however! , ghRecycleNib :: IO (Either (IO RecycledResources) RecycledResources) -- ^ The resources of prior frames waiting to be taken + , ghRTInfo :: RTInfo + } + +-- | Information for ray tracing +data RTInfo = RTInfo + { rtiShaderGroupHandleSize :: Word32 + , rtiShaderGroupBaseAlignment :: Word32 } -- | These are resources which are reused by a later frame when the current @@ -180,6 +194,7 @@ noAllocationCallbacks = Nothing do let vmaCommands = [ 'withBuffer + , 'VMA.withMappedMemory , 'invalidateAllocation ] commands = @@ -190,9 +205,11 @@ do , 'cmdBindPipeline , 'cmdDispatch , 'cmdDraw + , 'cmdPipelineBarrier , 'cmdPushConstants , 'cmdSetScissor , 'cmdSetViewport + , 'cmdTraceRaysKHR , 'cmdUseRenderPass , 'deviceWaitIdle , 'deviceWaitIdleSafe @@ -200,7 +217,9 @@ do , 'getPhysicalDeviceSurfaceCapabilitiesKHR , 'getPhysicalDeviceSurfaceFormatsKHR , 'getPhysicalDeviceSurfacePresentModesKHR + , 'getRayTracingShaderGroupHandlesKHR , 'getSwapchainImagesKHR + , 'nameObject , 'resetCommandPool , 'updateDescriptorSets , 'waitForFences @@ -218,6 +237,7 @@ do , 'withImageView , 'withInstance , 'withPipelineLayout + , 'withRayTracingPipelinesKHR , 'withRenderPass , 'withSemaphore , 'withShaderModule diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index f8e2b57d9..50dcfb0bc 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -1,9 +1,14 @@ +{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedLists #-} module Pipeline ( createPipeline + , createRTPipelineLayout + , createRTDescriptorSetLayout + , createRTDescriptorSets + , createShaderBindingTable , Pipeline.createRenderPass ) where @@ -11,75 +16,152 @@ import Control.Monad.Trans.Resource import Data.Bits import Data.Foldable ( traverse_ ) import qualified Data.Vector as V +import Foreign ( nullPtr ) import MonadVulkan import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) -import Vulkan.Utils.ShaderQQ.Shaderc +import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Utils.ShaderQQ import Vulkan.Zero +import VulkanMemoryAllocator +import Data.Vector (Vector) --- Create the most vanilla rendering pipeline -createPipeline :: RenderPass -> V (ReleaseKey, Pipeline) -createPipeline renderPass = do - (shaderKeys, shaderStages ) <- V.unzip <$> createShaders - (layoutKey , pipelineLayout) <- withPipelineLayout' zero - let - pipelineCreateInfo :: GraphicsPipelineCreateInfo '[] - pipelineCreateInfo = zero - { stages = shaderStages - , vertexInputState = Just zero - , inputAssemblyState = Just zero - { topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST - , primitiveRestartEnable = False - } - , viewportState = Just - $ SomeStruct zero { viewportCount = 1, scissorCount = 1 } - , rasterizationState = SomeStruct $ zero - { depthClampEnable = False - , rasterizerDiscardEnable = False - , lineWidth = 1 - , polygonMode = POLYGON_MODE_FILL - , cullMode = CULL_MODE_NONE - , frontFace = FRONT_FACE_CLOCKWISE - , depthBiasEnable = False - } - , multisampleState = Just . SomeStruct $ zero - { sampleShadingEnable = False - , rasterizationSamples = SAMPLE_COUNT_1_BIT - , minSampleShading = 1 - , sampleMask = [maxBound] - } - , depthStencilState = Nothing - , colorBlendState = Just . SomeStruct $ zero - { logicOpEnable = False - , attachments = [ zero - { colorWriteMask = - COLOR_COMPONENT_R_BIT - .|. COLOR_COMPONENT_G_BIT - .|. COLOR_COMPONENT_B_BIT - .|. COLOR_COMPONENT_A_BIT - , blendEnable = False - } - ] - } - , dynamicState = Just zero - { dynamicStates = [ DYNAMIC_STATE_VIEWPORT - , DYNAMIC_STATE_SCISSOR - ] - } - , layout = pipelineLayout - , renderPass = renderPass - , subpass = 0 - , basePipelineHandle = zero - } - (key, (_, ~[graphicsPipeline])) <- withGraphicsPipelines' +-- Create the most vanilla ray tracing pipeline +createPipeline :: PipelineLayout -> V (ReleaseKey, Pipeline) +createPipeline pipelineLayout = do + (shaderKeys, shaderStages) <- V.unzip <$> sequence [createRayGenerationShader] + + let rtsgci :: RayTracingShaderGroupCreateInfoKHR + rtsgci = RayTracingShaderGroupCreateInfoKHR + RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR + 0 -- The index of our general shader + SHADER_UNUSED_KHR + SHADER_UNUSED_KHR + SHADER_UNUSED_KHR + nullPtr + shaderGroups = [rtsgci] + + let pipelineCreateInfo :: RayTracingPipelineCreateInfoKHR '[] + pipelineCreateInfo = zero { stages = shaderStages + , groups = shaderGroups + , maxRecursionDepth = 1 + , layout = pipelineLayout + } + (key, (_, ~[rtPipeline])) <- withRayTracingPipelinesKHR' zero [SomeStruct pipelineCreateInfo] - release layoutKey + traverse_ release shaderKeys - pure (key, graphicsPipeline) + + pure (key, rtPipeline) + +createRTPipelineLayout :: DescriptorSetLayout -> V (ReleaseKey, PipelineLayout) +createRTPipelineLayout descriptorSetLayout = + withPipelineLayout' zero { setLayouts = [descriptorSetLayout] } + +createRTDescriptorSetLayout :: V (ReleaseKey, DescriptorSetLayout) +createRTDescriptorSetLayout = withDescriptorSetLayout' zero + { bindings = [ zero { binding = 1 + , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE + , descriptorCount = 1 + , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR + } + ] + } + +createRTDescriptorSets + :: DescriptorSetLayout -> Vector ImageView -> V (Vector DescriptorSet) +createRTDescriptorSets descriptorSetLayout imageViews = do + -- Create a descriptor pool + (_, descriptorPool) <- withDescriptorPool' zero + { maxSets = fromIntegral (V.length imageViews) + , poolSizes = [ DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_IMAGE + (fromIntegral (V.length imageViews)) + ] + } + + -- Allocate a descriptor set from the pool with that layout + -- Don't use `withDescriptorSets` here as the set will be cleaned up when + -- the pool is destroyed. + descriptorSets <- allocateDescriptorSets' zero + { descriptorPool = descriptorPool + , setLayouts = V.replicate (V.length imageViews) descriptorSetLayout + } + + -- Assign the buffer in this descriptor set + updateDescriptorSets' + (V.zipWith + (\set view -> SomeStruct zero + { dstSet = set + , dstBinding = 1 + , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE + , descriptorCount = 1 + , imageInfo = [ DescriptorImageInfo { sampler = NULL_HANDLE + , imageView = view + , imageLayout = IMAGE_LAYOUT_GENERAL + } + ] + } + ) + descriptorSets + imageViews + ) + [] + + pure descriptorSets + +createRayGenerationShader + :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) +createRayGenerationShader = do + let code = $(compileShaderQ "rgen" [glsl| + #version 460 + #extension GL_EXT_ray_tracing : require + + layout(binding = 1, set = 0, rgba32f) uniform image2D image; + + void main() + { + imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(0.5, 0.6, 0.8, 1.0)); + } + |]) + + (key, module') <- withShaderModule' zero { code } + let shaderStageCreateInfo = + zero { stage = SHADER_STAGE_RAYGEN_BIT_KHR, module', name = "main" } + pure (key, SomeStruct shaderStageCreateInfo) + +---------------------------------------------------------------- +-- Shader binding table +---------------------------------------------------------------- + +createShaderBindingTable :: Pipeline -> V (ReleaseKey, Buffer) +createShaderBindingTable pipeline = do + RTInfo {..} <- getRTInfo + let groupCount = 1 -- Just a generation shader + groupHandleSize = rtiShaderGroupHandleSize + baseAlignment = rtiShaderGroupBaseAlignment + sbtSize = fromIntegral (baseAlignment * groupCount) + + (bufferReleaseKey, (sbtBuffer, sbtAllocation, _sbtAllocationInfo)) <- withBuffer' + zero { usage = BUFFER_USAGE_TRANSFER_SRC_BIT, size = sbtSize } + zero + { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + .|. MEMORY_PROPERTY_HOST_COHERENT_BIT + } + nameObject' sbtBuffer "SBT" + + (memKey, mem) <- withMappedMemory' sbtAllocation + -- TODO: Fix alignment here + getRayTracingShaderGroupHandlesKHR' pipeline 0 groupCount sbtSize mem + release memKey + pure (bufferReleaseKey, sbtBuffer) + +---------------------------------------------------------------- +-- Render pass creation +---------------------------------------------------------------- -- | Create a renderpass with a single subpass createRenderPass :: Format -> V (ReleaseKey, RenderPass) @@ -120,54 +202,3 @@ createRenderPass imageFormat = do , dependencies = [subpassDependency] } --- | Create a vertex and fragment shader which render a colored triangle -createShaders - :: V (V.Vector (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo)) -createShaders = do - let fragCode = [frag| - float4 main([[vk::location(0)]] const float3 col) : SV_TARGET - { - return float4(col, 1); - } - |] - vertCode = [vert| - const static float2 positions[3] = { - {0.0, -0.5}, - {0.5, 0.5}, - {-0.5, 0.5} - }; - - const static float3 colors[3] = { - {1.0, 1.0, 0.0}, - {0.0, 1.0, 1.0}, - {1.0, 0.0, 1.0} - }; - - struct VSOutput - { - float4 pos : SV_POSITION; - [[vk::location(0)]] float3 col; - }; - - VSOutput main(const uint i : SV_VertexID) - { - VSOutput output; - output.pos = float4(positions[i], 0, 1.0); - output.col = colors[i]; - return output; - } - |] - (fragKey, fragModule) <- withShaderModule' zero { code = fragCode } - (vertKey, vertModule) <- withShaderModule' zero { code = vertCode } - let vertShaderStageCreateInfo = zero { stage = SHADER_STAGE_VERTEX_BIT - , module' = vertModule - , name = "main" - } - fragShaderStageCreateInfo = zero { stage = SHADER_STAGE_FRAGMENT_BIT - , module' = fragModule - , name = "main" - } - pure - [ (vertKey, SomeStruct vertShaderStageCreateInfo) - , (fragKey, SomeStruct fragShaderStageCreateInfo) - ] diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 7fc97223b..27d52db38 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -20,9 +20,11 @@ import UnliftIO.Exception ( throwString ) import Vulkan.CStruct.Extends import Vulkan.Core10 as Core10 import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore +import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Extensions.VK_KHR_swapchain as Swap import Vulkan.Zero +import Control.Monad.Trans.Class (MonadTrans(lift)) renderFrame :: F () renderFrame = do @@ -89,30 +91,75 @@ renderFrame = do sayErrString ("submitted " <> show fIndex) -- | Clear and render a triangle -myRecordCommandBuffer :: MonadIO m => Frame -> Word32 -> CmdT m () +myRecordCommandBuffer :: Frame -> Word32 -> CmdT F () myRecordCommandBuffer Frame {..} imageIndex = do + -- TODO: neaten + RTInfo {..} <- CmdT . lift . liftV $ getRTInfo let SwapchainResources {..} = fSwapchainResources SwapchainInfo {..} = srInfo - renderPassBeginInfo = zero - { renderPass = srRenderPass - , framebuffer = srFramebuffers ! fromIntegral imageIndex - , renderArea = Rect2D { offset = zero, extent = siImageExtent } - , clearValues = [Color (Float32 (0.3, 0.4, 0.8, 1))] + image = srImages ! fromIntegral imageIndex + imageWidth = width (siImageExtent :: Extent2D) + imageHeight = height (siImageExtent :: Extent2D) + imageSubresourceRange = ImageSubresourceRange + { aspectMask = IMAGE_ASPECT_COLOR_BIT + , baseMipLevel = 0 + , levelCount = 1 + , baseArrayLayer = 0 + , layerCount = 1 } - cmdUseRenderPass' renderPassBeginInfo SUBPASS_CONTENTS_INLINE $ do - cmdSetViewport' - 0 - [ Viewport { x = 0 - , y = 0 - , width = realToFrac (width (siImageExtent :: Extent2D)) - , height = realToFrac (height (siImageExtent :: Extent2D)) - , minDepth = 0 - , maxDepth = 1 - } + sbtRegion = StridedBufferRegionKHR + { buffer = fShaderBindingTable + , offset = 0 + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment -- * 1 + } + do + -- Transition image to general, to write from the compute shader + cmdPipelineBarrier' + PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT + PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR + zero + [] + [] + [ SomeStruct zero { srcAccessMask = zero + , dstAccessMask = ACCESS_SHADER_WRITE_BIT + , oldLayout = IMAGE_LAYOUT_UNDEFINED + , newLayout = IMAGE_LAYOUT_GENERAL + , image = image + , subresourceRange = imageSubresourceRange + } + ] + + -- Bind descriptor sets + cmdBindPipeline' PIPELINE_BIND_POINT_RAY_TRACING_KHR fPipeline + cmdBindDescriptorSets' PIPELINE_BIND_POINT_RAY_TRACING_KHR + fPipelineLayout + 0 + [fDescriptorSets ! fromIntegral imageIndex] + [] + + -- + -- The actual ray tracing + -- + cmdTraceRaysKHR' sbtRegion zero zero zero imageWidth imageHeight 1 + + -- Transition image back to present + cmdPipelineBarrier' + PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR + -- No need to get anything to wait because we're synchronizing with + -- the semaphore + PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT + zero + [] + [] + [ SomeStruct zero { srcAccessMask = ACCESS_SHADER_WRITE_BIT + , dstAccessMask = zero + , oldLayout = IMAGE_LAYOUT_GENERAL + , newLayout = IMAGE_LAYOUT_PRESENT_SRC_KHR + , image = image + , subresourceRange = imageSubresourceRange + } ] - cmdSetScissor' 0 [Rect2D { offset = Offset2D 0 0, extent = siImageExtent }] - cmdBindPipeline' PIPELINE_BIND_POINT_GRAPHICS fPipeline - cmdDraw' 3 1 0 0 ---------------------------------------------------------------- -- Utils diff --git a/examples/rays/Swapchain.hs b/examples/rays/Swapchain.hs index 8498d2896..98bb2a6a5 100644 --- a/examples/rays/Swapchain.hs +++ b/examples/rays/Swapchain.hs @@ -228,4 +228,5 @@ desiredPresentModes = -- | The images in the swapchain must support these flags. requiredUsageFlags :: [ImageUsageFlagBits] -requiredUsageFlags = [IMAGE_USAGE_COLOR_ATTACHMENT_BIT] +requiredUsageFlags = + [IMAGE_USAGE_COLOR_ATTACHMENT_BIT, IMAGE_USAGE_STORAGE_BIT] diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index 7e352069c..9e8b81cf6 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -4,7 +4,7 @@ cabal-version: 2.2 -- -- see: https://github.com/sol/hpack -- --- hash: bc5abd880f041e8504775a9c3c25fe244ed6f7424022d9f3d8e9952babf82155 +-- hash: a843da210d6f8f5df19d3c5f19576cf06d02a5f36665a5e8e78d0e877e4c7a04 name: vulkan-examples version: 0.1.0.0 @@ -164,6 +164,7 @@ executable rays main-is: Main.hs other-modules: Cache + DescriptorSet Frame Framebuffer Init From c8b69ddabf7104f343632f0a3989189cb964a698 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 18:01:47 +0800 Subject: [PATCH 18/70] Neaten resource handling in rays --- examples/rays/Frame.hs | 29 ++++++++++-------- examples/rays/Init.hs | 4 +-- examples/rays/Main.hs | 11 +++---- examples/rays/Pipeline.hs | 24 +-------------- examples/rays/Render.hs | 23 +++++++++++++- examples/rays/RenderPass.hs | 55 ---------------------------------- examples/rays/Swapchain.hs | 33 +++++--------------- examples/vulkan-examples.cabal | 3 +- 8 files changed, 55 insertions(+), 127 deletions(-) delete mode 100644 examples/rays/RenderPass.hs diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index dfb9e8d01..6c2fa18d2 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -10,8 +10,10 @@ import Control.Monad.Trans.Resource ( InternalState , allocate , closeInternalState , createInternalState + ) import Data.IORef +import Data.Vector ( Vector ) import Data.Word import MonadVulkan import qualified Pipeline @@ -26,7 +28,6 @@ import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore import Vulkan.Extensions.VK_KHR_surface import Vulkan.Utils.QueueAssignment import Vulkan.Zero -import Data.Vector (Vector) -- | Must be positive, duh numConcurrentFrames :: Int @@ -74,9 +75,13 @@ initialRecycledResources = do pure RecycledResources { .. } +-- | Create a 'Frame' from scratch initialFrame :: Window -> SurfaceKHR -> V Frame initialFrame fWindow fSurface = do let fIndex = 1 + + -- Create our swapchain for this 'Window' + -- These resources will last for longer than this frame SDL.V2 width height <- SDL.vkGetDrawableSize fWindow let windowSize = Extent2D (fromIntegral width) (fromIntegral height) oldSwapchain = NULL_HANDLE @@ -84,17 +89,13 @@ initialFrame fWindow fSurface = do windowSize fSurface - -- TODO: Cache this - -- TODO: Recreate this if the swapchain format changes - (_releaseDescriptorSetLayout, descriptorSetLayout) <- + -- Create the RT pipeline + (_, descriptorSetLayout) <- Pipeline.createRTDescriptorSetLayout - (_releasePipelineLayout, fPipelineLayout) <- Pipeline.createRTPipelineLayout - descriptorSetLayout - (_releasePipeline, fPipeline) <- Pipeline.createPipeline - fPipelineLayout - (_releaseSBT, fShaderBindingTable) <- Pipeline.createShaderBindingTable - fPipeline - fDescriptorSets <- Pipeline.createRTDescriptorSets + (_, fPipelineLayout) <- Pipeline.createRTPipelineLayout descriptorSetLayout + (_, fPipeline ) <- Pipeline.createPipeline fPipelineLayout + (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline + fDescriptorSets <- Pipeline.createRTDescriptorSets descriptorSetLayout (srImageViews fSwapchainResources) @@ -103,6 +104,8 @@ initialFrame fWindow fSurface = do (_, fRenderFinishedHostSemaphore) <- withSemaphore' (zero ::& SemaphoreTypeCreateInfo SEMAPHORE_TYPE_TIMELINE 0 :& ()) + -- Create the 'RecycledResources' necessary to kick off the rest of the + -- concurrent frames and push them into the chan. bin <- V $ asks ghRecycleBin replicateM_ (numConcurrentFrames - 1) $ liftIO @@ -111,8 +114,8 @@ initialFrame fWindow fSurface = do fRecycledResources <- initialRecycledResources fGPUWork <- liftIO $ newIORef mempty - -- Create this resource object at the global level so it's closed correctly - -- on exception + -- Create the frame resource tracker at the global level so it's closed + -- correctly on exception fResources <- allocate createInternalState closeInternalState pure Frame { .. } diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index a707e975a..239426b77 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -139,10 +139,10 @@ createDevice inst win = do -- Physical device tools ---------------------------------------------------------------- --- | The Ord instance prioritises devices with more memory data PhysicalDeviceInfo = PhysicalDeviceInfo { pdiTotalMemory :: Word64 , pdiRTInfo :: RTInfo + -- ^ The relevant information from PhysicalDeviceProperties2KHR , pdiQueueCreateInfos :: Vector (DeviceQueueCreateInfo '[]) , pdiGetQueues :: Device -> IO (Queues (QueueFamilyIndex, Queue)) } @@ -163,7 +163,7 @@ physicalDeviceInfo surf phys = runMaybeT $ do <> " because it doesn't support timeline semaphores" empty - pdiRTInfo <- deviceHasRayTracing phys + pdiRTInfo <- deviceHasRayTracing phys hasSwapchainSupport <- deviceHasSwapchain phys unless hasSwapchainSupport $ do diff --git a/examples/rays/Main.hs b/examples/rays/Main.hs index 44bc04805..a4518faaf 100644 --- a/examples/rays/Main.hs +++ b/examples/rays/Main.hs @@ -13,7 +13,6 @@ import SDL ( showWindow import Swapchain ( threwSwapchainError ) import Utils import Window -import System.Exit (exitSuccess) main :: IO () main = runResourceT $ do @@ -21,9 +20,9 @@ main = runResourceT $ do -- Initialization -- withSDL - win <- createWindow "Vulkan ⚡ Haskell" 1280 720 - inst <- Init.createInstance win - (phys, PhysicalDeviceInfo {..}, dev, qs, surf) <- Init.createDevice inst win + win <- createWindow "Vulkan ⚡ Haskell" 1280 720 + inst <- Init.createInstance win + (phys, pdi, dev, qs, surf) <- Init.createDevice inst win vma <- createVMA inst phys dev -- @@ -36,6 +35,8 @@ main = runResourceT $ do mean = realToFrac frames / (end - start) liftIO $ putStrLn $ "Average: " <> show mean + let rtInfo = pdiRTInfo pdi + let frame f = do shouldQuit >>= \case True -> do @@ -45,7 +46,7 @@ main = runResourceT $ do needsNewSwapchain <- threwSwapchainError (runFrame f renderFrame) advanceFrame needsNewSwapchain f - runV inst phys pdiRTInfo dev qs vma $ do + runV inst phys rtInfo dev qs vma $ do initial <- initialFrame win surf showWindow win loopJust frame initial diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 50dcfb0bc..1671612fa 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -86,33 +86,11 @@ createRTDescriptorSets descriptorSetLayout imageViews = do -- Allocate a descriptor set from the pool with that layout -- Don't use `withDescriptorSets` here as the set will be cleaned up when -- the pool is destroyed. - descriptorSets <- allocateDescriptorSets' zero + allocateDescriptorSets' zero { descriptorPool = descriptorPool , setLayouts = V.replicate (V.length imageViews) descriptorSetLayout } - -- Assign the buffer in this descriptor set - updateDescriptorSets' - (V.zipWith - (\set view -> SomeStruct zero - { dstSet = set - , dstBinding = 1 - , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE - , descriptorCount = 1 - , imageInfo = [ DescriptorImageInfo { sampler = NULL_HANDLE - , imageView = view - , imageLayout = IMAGE_LAYOUT_GENERAL - } - ] - } - ) - descriptorSets - imageViews - ) - [] - - pure descriptorSets - createRayGenerationShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) createRayGenerationShader = do diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 27d52db38..dda12fc34 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -49,6 +49,23 @@ renderFrame = do timeoutError "Timed out (1s) trying to acquire next image" _ -> throwString "Unexpected Result from acquireNextImageKHR" + -- Update the necessary descriptor sets + updateDescriptorSets' + [ SomeStruct zero + { dstSet = fDescriptorSets ! fromIntegral imageIndex + , dstBinding = 1 + , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE + , descriptorCount = 1 + , imageInfo = [ DescriptorImageInfo + { sampler = NULL_HANDLE + , imageView = srImageViews ! fromIntegral imageIndex + , imageLayout = IMAGE_LAYOUT_GENERAL + } + ] + } + ] + [] + -- Allocate a command buffer and populate it let commandBufferAllocateInfo = zero { commandPool = fCommandPool , level = COMMAND_BUFFER_LEVEL_PRIMARY @@ -90,6 +107,10 @@ renderFrame = do } sayErrString ("submitted " <> show fIndex) +---------------------------------------------------------------- +-- Command buffer recording +---------------------------------------------------------------- + -- | Clear and render a triangle myRecordCommandBuffer :: Frame -> Word32 -> CmdT F () myRecordCommandBuffer Frame {..} imageIndex = do @@ -114,7 +135,7 @@ myRecordCommandBuffer Frame {..} imageIndex = do , size = fromIntegral rtiShaderGroupBaseAlignment -- * 1 } do - -- Transition image to general, to write from the compute shader + -- Transition image to general, to write from the ray tracing shader cmdPipelineBarrier' PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR diff --git a/examples/rays/RenderPass.hs b/examples/rays/RenderPass.hs deleted file mode 100644 index 0e083fa73..000000000 --- a/examples/rays/RenderPass.hs +++ /dev/null @@ -1,55 +0,0 @@ -{-# LANGUAGE QuasiQuotes #-} -{-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE OverloadedLists #-} - -module RenderPass - ( RenderPass.createRenderPass - ) where - -import Control.Monad.Trans.Resource -import Data.Bits -import MonadVulkan -import Vulkan.Core10 as Vk - hiding ( withBuffer - , withImage - ) -import Vulkan.Zero - --- | Create a renderpass with a single subpass -createRenderPass :: Format -> V (ReleaseKey, RenderPass) -createRenderPass imageFormat = do - let - attachmentDescription :: AttachmentDescription - attachmentDescription = zero - { format = imageFormat - , samples = SAMPLE_COUNT_1_BIT - , loadOp = ATTACHMENT_LOAD_OP_CLEAR - , storeOp = ATTACHMENT_STORE_OP_STORE - , stencilLoadOp = ATTACHMENT_LOAD_OP_DONT_CARE - , stencilStoreOp = ATTACHMENT_STORE_OP_DONT_CARE - , initialLayout = IMAGE_LAYOUT_UNDEFINED - , finalLayout = IMAGE_LAYOUT_PRESENT_SRC_KHR - } - subpass :: SubpassDescription - subpass = zero - { pipelineBindPoint = PIPELINE_BIND_POINT_GRAPHICS - , colorAttachments = - [ zero { attachment = 0 - , layout = IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - } - ] - } - subpassDependency :: SubpassDependency - subpassDependency = zero - { srcSubpass = SUBPASS_EXTERNAL - , dstSubpass = 0 - , srcStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - , srcAccessMask = zero - , dstStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - , dstAccessMask = ACCESS_COLOR_ATTACHMENT_READ_BIT - .|. ACCESS_COLOR_ATTACHMENT_WRITE_BIT - } - withRenderPass' zero { attachments = [attachmentDescription] - , subpasses = [subpass] - , dependencies = [subpassDependency] - } diff --git a/examples/rays/Swapchain.hs b/examples/rays/Swapchain.hs index 98bb2a6a5..a3208940a 100644 --- a/examples/rays/Swapchain.hs +++ b/examples/rays/Swapchain.hs @@ -19,7 +19,6 @@ import Data.Vector ( Vector ) import Framebuffer import MonadVulkan import RefCounted -import RenderPass import qualified SDL import qualified SDL.Video.Vulkan as SDL import UnliftIO.Exception ( throwString @@ -42,12 +41,10 @@ data SwapchainInfo = SwapchainInfo } data SwapchainResources = SwapchainResources - { srInfo :: SwapchainInfo - , srFramebuffers :: Vector Framebuffer - , srImageViews :: Vector ImageView - , srImages :: Vector Image - , srRenderPass :: RenderPass - , srRelease :: RefCounted + { srInfo :: SwapchainInfo + , srImageViews :: Vector ImageView + , srImages :: Vector Image + , srRelease :: RefCounted } ---------------------------------------------------------------- @@ -65,36 +62,20 @@ allocSwapchainResources allocSwapchainResources oldSwapchain windowSize surface = do info@SwapchainInfo {..} <- createSwapchain oldSwapchain windowSize surface - -- TODO: cache this, it's probably not going to change - (renderPassKey, srRenderPass) <- RenderPass.createRenderPass - (format (siSurfaceFormat :: SurfaceFormatKHR)) - -- Get all the swapchain images, and create views for them - (_ , swapchainImages) <- getSwapchainImagesKHR' siSwapchain - (imageViewKeys, imageViews ) <- + (_, swapchainImages) <- getSwapchainImagesKHR' siSwapchain + (imageViewKeys, imageViews) <- fmap V.unzip . V.forM swapchainImages $ \image -> Framebuffer.createImageView (format (siSurfaceFormat :: SurfaceFormatKHR)) image - -- Also create a framebuffer for each one - (framebufferKeys, framebuffers) <- - fmap V.unzip . V.forM imageViews $ \imageView -> - Framebuffer.createFramebuffer srRenderPass imageView siImageExtent - -- This refcount is released in 'recreateSwapchainResources' releaseResources <- newRefCounted $ do - traverse_ release framebufferKeys traverse_ release imageViewKeys - release renderPassKey release siSwapchainReleaseKey - pure $ SwapchainResources info - framebuffers - imageViews - swapchainImages - srRenderPass - releaseResources + pure $ SwapchainResources info imageViews swapchainImages releaseResources recreateSwapchainResources :: SDL.Window diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index 9e8b81cf6..1f748b9a9 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -4,7 +4,7 @@ cabal-version: 2.2 -- -- see: https://github.com/sol/hpack -- --- hash: a843da210d6f8f5df19d3c5f19576cf06d02a5f36665a5e8e78d0e877e4c7a04 +-- hash: df7c91cabff895392135364841ad4ee792099d899627bda5044375bc27a7d301 name: vulkan-examples version: 0.1.0.0 @@ -173,7 +173,6 @@ executable rays Pipeline RefCounted Render - RenderPass Swapchain Utils Window From 0e950fd16ac09417e07a99b209d717691cb91341 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 18:19:45 +0800 Subject: [PATCH 19/70] Correct descriptor set allocation to one per concurrent frame --- examples/rays/Frame.hs | 37 +++++++++++++++++------------------- examples/rays/MonadVulkan.hs | 2 ++ examples/rays/Pipeline.hs | 14 ++++++++------ examples/rays/Render.hs | 9 +++++---- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index 6c2fa18d2..f6297df61 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -2,7 +2,8 @@ -- can be found in 'MonadFrame' module Frame where -import Control.Monad ( replicateM_ ) +import Control.Arrow ( Arrow((&&&)) ) +import Control.Monad ((<=<) ) import Control.Monad.IO.Class ( MonadIO(liftIO) ) import Control.Monad.Trans.Reader ( asks ) import Control.Monad.Trans.Resource ( InternalState @@ -10,10 +11,10 @@ import Control.Monad.Trans.Resource ( InternalState , allocate , closeInternalState , createInternalState - ) +import Data.Foldable import Data.IORef -import Data.Vector ( Vector ) +import qualified Data.Vector as V import Data.Word import MonadVulkan import qualified Pipeline @@ -43,7 +44,6 @@ data Frame = Frame , fSwapchainResources :: SwapchainResources , fPipeline :: Pipeline , fPipelineLayout :: PipelineLayout - , fDescriptorSets :: Vector DescriptorSet , fShaderBindingTable :: Buffer , fRenderFinishedHostSemaphore :: Semaphore -- ^ A timeline semaphore which increments to fIndex when this frame is @@ -60,8 +60,8 @@ data Frame = Frame -- frame is done with GPU work. } -initialRecycledResources :: V RecycledResources -initialRecycledResources = do +initialRecycledResources :: DescriptorSet -> V RecycledResources +initialRecycledResources fDescriptorSet = do (_, fImageAvailableSemaphore) <- withSemaphore' (zero ::& SemaphoreTypeCreateInfo SEMAPHORE_TYPE_BINARY 0 :& ()) @@ -90,14 +90,13 @@ initialFrame fWindow fSurface = do fSurface -- Create the RT pipeline - (_, descriptorSetLayout) <- - Pipeline.createRTDescriptorSetLayout + (_, descriptorSetLayout) <- Pipeline.createRTDescriptorSetLayout (_, fPipelineLayout) <- Pipeline.createRTPipelineLayout descriptorSetLayout (_, fPipeline ) <- Pipeline.createPipeline fPipelineLayout (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline - fDescriptorSets <- Pipeline.createRTDescriptorSets + descriptorSets <- Pipeline.createRTDescriptorSets descriptorSetLayout - (srImageViews fSwapchainResources) + (fromIntegral numConcurrentFrames) -- Don't keep the release key, this semaphore lives for the lifetime of the -- application @@ -106,17 +105,16 @@ initialFrame fWindow fSurface = do -- Create the 'RecycledResources' necessary to kick off the rest of the -- concurrent frames and push them into the chan. - bin <- V $ asks ghRecycleBin - replicateM_ (numConcurrentFrames - 1) - $ liftIO - . bin - =<< initialRecycledResources - fRecycledResources <- initialRecycledResources - - fGPUWork <- liftIO $ newIORef mempty + let (ourDescriptorSet, otherDescriptorSets) = + (V.head &&& V.tail) descriptorSets + fRecycledResources <- initialRecycledResources ourDescriptorSet + bin <- V $ asks ghRecycleBin + for_ otherDescriptorSets ((liftIO . bin) <=< initialRecycledResources) + + fGPUWork <- liftIO $ newIORef mempty -- Create the frame resource tracker at the global level so it's closed -- correctly on exception - fResources <- allocate createInternalState closeInternalState + fResources <- allocate createInternalState closeInternalState pure Frame { .. } @@ -145,7 +143,6 @@ advanceFrame needsNewSwapchain f = do , fSwapchainResources , fPipeline = fPipeline f , fPipelineLayout = fPipelineLayout f - , fDescriptorSets = fDescriptorSets f , fShaderBindingTable = fShaderBindingTable f , fRenderFinishedHostSemaphore = fRenderFinishedHostSemaphore f , fGPUWork diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index a41bcbaeb..395dadebc 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -157,6 +157,8 @@ data RecycledResources = RecycledResources , fCommandPool :: CommandPool -- ^ Pool for this frame's commands (might want more than one of these for -- multithreaded recording) + , fDescriptorSet :: DescriptorSet + -- ^ A descriptor set for ray tracing } -- | The shape of all the queues we use for our program, parameterized over the diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 1671612fa..13099295a 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -16,6 +16,8 @@ import Control.Monad.Trans.Resource import Data.Bits import Data.Foldable ( traverse_ ) import qualified Data.Vector as V +import Data.Vector ( Vector ) +import Data.Word import Foreign ( nullPtr ) import MonadVulkan import Vulkan.CStruct.Extends @@ -27,7 +29,6 @@ import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Utils.ShaderQQ import Vulkan.Zero import VulkanMemoryAllocator -import Data.Vector (Vector) -- Create the most vanilla ray tracing pipeline createPipeline :: PipelineLayout -> V (ReleaseKey, Pipeline) @@ -73,13 +74,13 @@ createRTDescriptorSetLayout = withDescriptorSetLayout' zero } createRTDescriptorSets - :: DescriptorSetLayout -> Vector ImageView -> V (Vector DescriptorSet) -createRTDescriptorSets descriptorSetLayout imageViews = do + :: DescriptorSetLayout -> Word32 -> V (Vector DescriptorSet) +createRTDescriptorSets descriptorSetLayout numDescriptorSets = do -- Create a descriptor pool (_, descriptorPool) <- withDescriptorPool' zero - { maxSets = fromIntegral (V.length imageViews) + { maxSets = numDescriptorSets , poolSizes = [ DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_IMAGE - (fromIntegral (V.length imageViews)) + numDescriptorSets ] } @@ -88,7 +89,8 @@ createRTDescriptorSets descriptorSetLayout imageViews = do -- the pool is destroyed. allocateDescriptorSets' zero { descriptorPool = descriptorPool - , setLayouts = V.replicate (V.length imageViews) descriptorSetLayout + , setLayouts = V.replicate (fromIntegral numDescriptorSets) + descriptorSetLayout } createRayGenerationShader diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index dda12fc34..68f1e83a1 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -6,6 +6,7 @@ module Render import Control.Exception ( throwIO ) import Control.Monad.IO.Class +import Control.Monad.Trans.Class ( MonadTrans(lift) ) import Data.Vector ( (!) ) import Data.Word import Frame @@ -24,7 +25,6 @@ import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Extensions.VK_KHR_swapchain as Swap import Vulkan.Zero -import Control.Monad.Trans.Class (MonadTrans(lift)) renderFrame :: F () renderFrame = do @@ -52,7 +52,7 @@ renderFrame = do -- Update the necessary descriptor sets updateDescriptorSets' [ SomeStruct zero - { dstSet = fDescriptorSets ! fromIntegral imageIndex + { dstSet = fDescriptorSet , dstBinding = 1 , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE , descriptorCount = 1 @@ -116,7 +116,8 @@ myRecordCommandBuffer :: Frame -> Word32 -> CmdT F () myRecordCommandBuffer Frame {..} imageIndex = do -- TODO: neaten RTInfo {..} <- CmdT . lift . liftV $ getRTInfo - let SwapchainResources {..} = fSwapchainResources + let RecycledResources {..} = fRecycledResources + SwapchainResources {..} = fSwapchainResources SwapchainInfo {..} = srInfo image = srImages ! fromIntegral imageIndex imageWidth = width (siImageExtent :: Extent2D) @@ -156,7 +157,7 @@ myRecordCommandBuffer Frame {..} imageIndex = do cmdBindDescriptorSets' PIPELINE_BIND_POINT_RAY_TRACING_KHR fPipelineLayout 0 - [fDescriptorSets ! fromIntegral imageIndex] + [fDescriptorSet] [] -- From ab81fa2b7cea2fb0627bdaa5ba1e7d0e38fec881 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 19:06:58 +0800 Subject: [PATCH 20/70] formatting --- examples/rays/RefCounted.hs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/rays/RefCounted.hs b/examples/rays/RefCounted.hs index e8f16bb4e..31848143b 100644 --- a/examples/rays/RefCounted.hs +++ b/examples/rays/RefCounted.hs @@ -1,16 +1,18 @@ module RefCounted where import Control.Exception ( throwIO ) +import Control.Monad import Control.Monad.IO.Class ( MonadIO , liftIO ) +import Control.Monad.Trans.Resource ( MonadResource + , allocate_ + ) import Data.IORef import GHC.IO.Exception ( IOErrorType(UserError) , IOException(IOError) ) import UnliftIO.Exception ( mask ) -import Control.Monad -import Control.Monad.Trans.Resource (MonadResource, allocate_) -- | A 'RefCounted' will perform the specified action when the count reaches 0 data RefCounted = RefCounted From 50a3228e9a03fc046eb22dfa4ea012f8e89c77de Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 20:12:40 +0800 Subject: [PATCH 21/70] Use correct stride in SBT --- examples/rays/Pipeline.hs | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 13099295a..7dd0ea93f 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -12,6 +12,7 @@ module Pipeline , Pipeline.createRenderPass ) where +import Control.Monad.IO.Class import Control.Monad.Trans.Resource import Data.Bits import Data.Foldable ( traverse_ ) @@ -19,6 +20,10 @@ import qualified Data.Vector as V import Data.Vector ( Vector ) import Data.Word import Foreign ( nullPtr ) +import Foreign.Marshal.Utils ( moveBytes ) +import Foreign.Ptr ( Ptr + , plusPtr + ) import MonadVulkan import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk @@ -120,25 +125,51 @@ createRayGenerationShader = do createShaderBindingTable :: Pipeline -> V (ReleaseKey, Buffer) createShaderBindingTable pipeline = do RTInfo {..} <- getRTInfo - let groupCount = 1 -- Just a generation shader - groupHandleSize = rtiShaderGroupHandleSize - baseAlignment = rtiShaderGroupBaseAlignment - sbtSize = fromIntegral (baseAlignment * groupCount) - - (bufferReleaseKey, (sbtBuffer, sbtAllocation, _sbtAllocationInfo)) <- withBuffer' - zero { usage = BUFFER_USAGE_TRANSFER_SRC_BIT, size = sbtSize } - zero - { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT - .|. MEMORY_PROPERTY_HOST_COHERENT_BIT - } + let groupCount = 1 -- Just a generation shader + handleSize = rtiShaderGroupHandleSize + baseAlignment = rtiShaderGroupBaseAlignment + handleStride = max handleSize baseAlignment + -- Make the buffer big enough for all the groups, with spacing between + -- them equal to their alignment + sbtSize = fromIntegral $ handleStride * (groupCount - 1) + handleSize + + (bufferReleaseKey, (sbtBuffer, sbtAllocation, _sbtAllocationInfo)) <- + withBuffer' + zero { usage = BUFFER_USAGE_TRANSFER_SRC_BIT, size = sbtSize } + zero + { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + .|. MEMORY_PROPERTY_HOST_COHERENT_BIT + } nameObject' sbtBuffer "SBT" (memKey, mem) <- withMappedMemory' sbtAllocation - -- TODO: Fix alignment here getRayTracingShaderGroupHandlesKHR' pipeline 0 groupCount sbtSize mem + unpackObjects groupCount handleSize handleStride mem release memKey pure (bufferReleaseKey, sbtBuffer) +-- | Move densely packed objects so that they have a desired stride +unpackObjects + :: MonadIO m + => Word32 + -- ^ Num objects + -> Word32 + -- ^ Object size, the initial stride + -> Word32 + -- ^ Desired stride + -> Ptr () + -- ^ Initial, packed data, in a buffer big enough for the unpacked data + -> m () +unpackObjects numObjs size desiredStride buf = do + let + objectInitalPosition n = buf `plusPtr` fromIntegral (size * n) + objectFinalPosition n = buf `plusPtr` fromIntegral (desiredStride * n) + moveObject n = moveBytes (objectFinalPosition n) + (objectInitalPosition n) + (fromIntegral size) + -- Move the object last to first + liftIO $ traverse_ @[] moveObject [(numObjs - 1) .. 0] + ---------------------------------------------------------------- -- Render pass creation ---------------------------------------------------------------- @@ -181,4 +212,3 @@ createRenderPass imageFormat = do , subpasses = [subpass] , dependencies = [subpassDependency] } - From 1e047269818f8c5b1c3680b4e94e7866750f4486 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 21 Nov 2020 21:35:42 +0800 Subject: [PATCH 22/70] Build acceleration structure on CPU Sadly this does not play with the nvidia driver --- examples/rays/AccelerationStructure.hs | 65 ++++++++++++++++++++++++++ examples/rays/Frame.hs | 14 ++++-- examples/rays/Init.hs | 8 ++-- examples/rays/MonadVulkan.hs | 3 ++ examples/rays/Pipeline.hs | 20 ++++---- examples/vulkan-examples.cabal | 3 +- 6 files changed, 94 insertions(+), 19 deletions(-) create mode 100644 examples/rays/AccelerationStructure.hs diff --git a/examples/rays/AccelerationStructure.hs b/examples/rays/AccelerationStructure.hs new file mode 100644 index 000000000..8d8bb4e8b --- /dev/null +++ b/examples/rays/AccelerationStructure.hs @@ -0,0 +1,65 @@ +{-# LANGUAGE OverloadedLists #-} + +module AccelerationStructure where + +import MonadVulkan +import UnliftIO.Foreign ( allocaBytesAligned + , castPtr + , withArray + ) +import Vulkan.CStruct.Extends +import Vulkan.Core10 +import Vulkan.Core11 ( MemoryRequirements2(..) ) +import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Zero + +createBLAS :: V () +createBLAS = do + let asci :: AccelerationStructureCreateInfoKHR + asci = zero + { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR + , flags = BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR + , geometryInfos = [ zero { geometryType = GEOMETRY_TYPE_AABBS_KHR + , maxPrimitiveCount = 1 + } + ] + } + (blasKey, blas) <- withAccelerationStructureKHR' asci + MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' + zero + { type' = + ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR + , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR + , accelerationStructure = blas + } + let -- a bounding box for the unit sphere + box = AabbPositionsKHR (-1) (-1) (-1) 1 1 1 + withArray [box] $ \boxData -> do + allocaBytesAligned (fromIntegral (size (reqs :: MemoryRequirements))) + (fromIntegral (alignment reqs)) + $ \scratch -> do + let + infos = + [ SomeStruct zero + { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR + , update = False + , dstAccelerationStructure = blas + , scratchData = HostAddress scratch + , geometries = + [ zero + { geometryType = GEOMETRY_TYPE_AABBS_KHR + , flags = GEOMETRY_OPAQUE_BIT_KHR + , geometry = + Aabbs $ AccelerationStructureGeometryAabbsDataKHR + { data' = HostAddressConst (castPtr boxData) + , stride = 0 + } + } + ] + } + ] + offsetInfos = [zero { primitiveCount = 1, primitiveOffset = 0 }] + buildAccelerationStructureKHR' infos offsetInfos >>= \case + SUCCESS -> pure () + _ -> error "oops" + pure () diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index f6297df61..c859119e7 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -2,8 +2,9 @@ -- can be found in 'MonadFrame' module Frame where +import AccelerationStructure import Control.Arrow ( Arrow((&&&)) ) -import Control.Monad ((<=<) ) +import Control.Monad ( (<=<) ) import Control.Monad.IO.Class ( MonadIO(liftIO) ) import Control.Monad.Trans.Reader ( asks ) import Control.Monad.Trans.Resource ( InternalState @@ -90,11 +91,12 @@ initialFrame fWindow fSurface = do fSurface -- Create the RT pipeline - (_, descriptorSetLayout) <- Pipeline.createRTDescriptorSetLayout + (_, descriptorSetLayout) <- Pipeline.createRTDescriptorSetLayout (_, fPipelineLayout) <- Pipeline.createRTPipelineLayout descriptorSetLayout - (_, fPipeline ) <- Pipeline.createPipeline fPipelineLayout - (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline - descriptorSets <- Pipeline.createRTDescriptorSets + (_, fPipeline, numGroups) <- Pipeline.createPipeline fPipelineLayout + (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline + numGroups + descriptorSets <- Pipeline.createRTDescriptorSets descriptorSetLayout (fromIntegral numConcurrentFrames) @@ -116,6 +118,8 @@ initialFrame fWindow fSurface = do -- correctly on exception fResources <- allocate createInternalState closeInternalState + createBLAS + pure Frame { .. } -- | Create the next frame diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index 239426b77..4248e8cb0 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -116,7 +116,9 @@ createDevice inst win = do let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } ::& PhysicalDeviceTimelineSemaphoreFeatures True - :& zero { rayTracing = True } + :& zero { rayTracing = True + , rayTracingHostAccelerationStructureCommands = True + } :& () rayTracingExtensions = [ KHR_RAY_TRACING_EXTENSION_NAME @@ -234,8 +236,8 @@ deviceHasRayTracing phys = do hasFeat = do feats <- getPhysicalDeviceFeatures2KHR phys - let _ ::& PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats - pure rayTracing + let _ ::& f@PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats + pure $ rayTracing && rayTracingHostAccelerationStructureCommands getProps = do props <- getPhysicalDeviceProperties2KHR phys diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index 395dadebc..a9c63c834 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -203,6 +203,7 @@ do [ 'acquireNextImageKHR , 'allocateCommandBuffers , 'allocateDescriptorSets + , 'buildAccelerationStructureKHR , 'cmdBindDescriptorSets , 'cmdBindPipeline , 'cmdDispatch @@ -215,6 +216,7 @@ do , 'cmdUseRenderPass , 'deviceWaitIdle , 'deviceWaitIdleSafe + , 'getAccelerationStructureMemoryRequirementsKHR , 'getDeviceQueue , 'getPhysicalDeviceSurfaceCapabilitiesKHR , 'getPhysicalDeviceSurfaceFormatsKHR @@ -228,6 +230,7 @@ do , 'waitForFencesSafe , 'Timeline.waitSemaphores , 'Timeline.waitSemaphoresSafe + , 'withAccelerationStructureKHR , 'withCommandBuffers , 'withCommandPool , 'withComputePipelines diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 7dd0ea93f..344b69f5b 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -35,8 +35,9 @@ import Vulkan.Utils.ShaderQQ import Vulkan.Zero import VulkanMemoryAllocator --- Create the most vanilla ray tracing pipeline -createPipeline :: PipelineLayout -> V (ReleaseKey, Pipeline) +-- Create the most vanilla ray tracing pipeline, returns the number of shader +-- groups +createPipeline :: PipelineLayout -> V (ReleaseKey, Pipeline, Word32) createPipeline pipelineLayout = do (shaderKeys, shaderStages) <- V.unzip <$> sequence [createRayGenerationShader] @@ -62,7 +63,7 @@ createPipeline pipelineLayout = do traverse_ release shaderKeys - pure (key, rtPipeline) + pure (key, rtPipeline, fromIntegral (length shaderStages)) createRTPipelineLayout :: DescriptorSetLayout -> V (ReleaseKey, PipelineLayout) createRTPipelineLayout descriptorSetLayout = @@ -122,16 +123,15 @@ createRayGenerationShader = do -- Shader binding table ---------------------------------------------------------------- -createShaderBindingTable :: Pipeline -> V (ReleaseKey, Buffer) -createShaderBindingTable pipeline = do +createShaderBindingTable :: Pipeline -> Word32 -> V (ReleaseKey, Buffer) +createShaderBindingTable pipeline numGroups = do RTInfo {..} <- getRTInfo - let groupCount = 1 -- Just a generation shader - handleSize = rtiShaderGroupHandleSize + let handleSize = rtiShaderGroupHandleSize baseAlignment = rtiShaderGroupBaseAlignment handleStride = max handleSize baseAlignment -- Make the buffer big enough for all the groups, with spacing between -- them equal to their alignment - sbtSize = fromIntegral $ handleStride * (groupCount - 1) + handleSize + sbtSize = fromIntegral $ handleStride * (numGroups - 1) + handleSize (bufferReleaseKey, (sbtBuffer, sbtAllocation, _sbtAllocationInfo)) <- withBuffer' @@ -143,8 +143,8 @@ createShaderBindingTable pipeline = do nameObject' sbtBuffer "SBT" (memKey, mem) <- withMappedMemory' sbtAllocation - getRayTracingShaderGroupHandlesKHR' pipeline 0 groupCount sbtSize mem - unpackObjects groupCount handleSize handleStride mem + getRayTracingShaderGroupHandlesKHR' pipeline 0 numGroups sbtSize mem + unpackObjects numGroups handleSize handleStride mem release memKey pure (bufferReleaseKey, sbtBuffer) diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index 1f748b9a9..cfdfe7215 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -4,7 +4,7 @@ cabal-version: 2.2 -- -- see: https://github.com/sol/hpack -- --- hash: df7c91cabff895392135364841ad4ee792099d899627bda5044375bc27a7d301 +-- hash: 8160fb6fed8915e2c12af69faf0370f418c57bd3969f3086e1ec1911c86d0047 name: vulkan-examples version: 0.1.0.0 @@ -163,6 +163,7 @@ executable offscreen executable rays main-is: Main.hs other-modules: + AccelerationStructure Cache DescriptorSet Frame From ed4a95618bbf820d9b3851a75d32cba4499160a9 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sun, 22 Nov 2020 22:14:49 +0800 Subject: [PATCH 23/70] Ray tracing an AABB --- examples/rays/AccelerationStructure.hs | 341 ++++++++++++++++++++++--- examples/rays/Frame.hs | 24 +- examples/rays/Init.hs | 14 +- examples/rays/MonadFrame.hs | 4 +- examples/rays/MonadVulkan.hs | 9 +- examples/rays/Pipeline.hs | 206 ++++++++++----- examples/rays/Render.hs | 66 +++-- examples/rays/Swapchain.hs | 2 + 8 files changed, 528 insertions(+), 138 deletions(-) diff --git a/examples/rays/AccelerationStructure.hs b/examples/rays/AccelerationStructure.hs index 8d8bb4e8b..54b289e28 100644 --- a/examples/rays/AccelerationStructure.hs +++ b/examples/rays/AccelerationStructure.hs @@ -2,19 +2,178 @@ module AccelerationStructure where +import Control.Monad.IO.Class +import Control.Monad.Trans.Resource +import Data.Bits +import Data.Coerce ( coerce ) +import Foreign.Storable ( Storable(sizeOf) ) +import Foreign.Storable ( Storable(poke) ) import MonadVulkan -import UnliftIO.Foreign ( allocaBytesAligned - , castPtr - , withArray - ) +import Say +import UnliftIO.Foreign ( castPtr ) +import Vulkan.CStruct import Vulkan.CStruct.Extends import Vulkan.Core10 import Vulkan.Core11 ( MemoryRequirements2(..) ) +import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Utils.QueueAssignment import Vulkan.Zero +import VulkanMemoryAllocator -createBLAS :: V () -createBLAS = do +---------------------------------------------------------------- +-- TLAS +---------------------------------------------------------------- + +createTLAS :: V (ReleaseKey, AccelerationStructureKHR) +createTLAS = do + let geomType = zero { geometryType = GEOMETRY_TYPE_INSTANCES_KHR + , maxPrimitiveCount = 1 + , allowsTransforms = False + } + asci = zero + { type' = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + , flags = BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR + , geometryInfos = [geomType] + } + (tlasKey, tlas) <- withAccelerationStructureKHR' asci + createAndBindAccelerationMemory tlas + nameObject' tlas "TLAS" + + let numInstances = 1 + instanceDescsSize = + numInstances * cStructSize @AccelerationStructureInstanceKHR + (instBufferReleaseKey, (instBuffer, instBufferAllocation, _)) <- withBuffer' + zero + { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR + .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + , size = fromIntegral instanceDescsSize + } + -- TODO: Make this GPU only and transfer to it + zero + { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + .|. MEMORY_PROPERTY_HOST_COHERENT_BIT + } + nameObject' instBuffer "TLAS instances" + instBufferDeviceAddress <- getBufferDeviceAddress' zero { buffer = instBuffer + } + + (blasReleaseKey, blas) <- createBlasOnDevice + blasAddress <- getAccelerationStructureDeviceAddressKHR' zero + { accelerationStructure = blas + } + let identity = TransformMatrixKHR ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0)) + inst :: AccelerationStructureInstanceKHR + inst = zero + { transform = identity + , instanceCustomIndex = complement 0 -- TODO: unnecessary + , mask = complement 0 + , instanceShaderBindingTableRecordOffset = 0 + , flags = GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR + , accelerationStructureReference = coerce blasAddress + } + (instMapKey, instMapPtr) <- withMappedMemory' instBufferAllocation + liftIO $ poke (castPtr @_ @AccelerationStructureInstanceKHR instMapPtr) inst + release instMapKey + + let geomData = AccelerationStructureGeometryInstancesDataKHR + { arrayOfPointers = False + , data' = DeviceAddressConst instBufferDeviceAddress + } + geom :: AccelerationStructureGeometryKHR + geom = zero { geometryType = GEOMETRY_TYPE_INSTANCES_KHR + , geometry = Instances geomData + , flags = GEOMETRY_OPAQUE_BIT_KHR + } + let offsetInfo = zero { primitiveCount = 1, primitiveOffset = 0 } + + buildTlasOnDevice tlas geom offsetInfo + + pure (tlasKey, tlas) + +-- TODO: deduplicate this and buildBlasOnDevice +buildTlasOnDevice + :: AccelerationStructureKHR + -> AccelerationStructureGeometryKHR + -> AccelerationStructureBuildOffsetInfoKHR + -> V () +buildTlasOnDevice tlas geom offsetInfo = do + -- + -- Get the memory requirements for building the AS + -- + MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' + zero + { type' = + ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR + , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR + , accelerationStructure = tlas + } + + -- + -- Allocate that space on the device + -- + (scratchKey, (scratch, scratchAllocation, scratchAllocationInfo)) <- + withBuffer' + zero + { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR + .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + , size = size (reqs :: MemoryRequirements) + } + zero + scratchAddr <- getBufferDeviceAddress' zero { buffer = scratch } + + -- + -- Create command buffers + -- + graphicsQueue <- getGraphicsQueue + QueueFamilyIndex graphicsQueueFamilyIndex <- getGraphicsQueueFamilyIndex + (poolKey, commandPool) <- withCommandPool' zero + { queueFamilyIndex = graphicsQueueFamilyIndex + } + ~[commandBuffer] <- allocateCommandBuffers' zero + { commandPool = commandPool + , level = COMMAND_BUFFER_LEVEL_PRIMARY + , commandBufferCount = 1 + } + + let buildGeomInfo = zero { type' = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + , update = False + , dstAccelerationStructure = tlas + , scratchData = DeviceAddress scratchAddr + , geometries = [geom] + } + + -- + -- Record and kick off the build commands + -- + useCommandBuffer' commandBuffer zero $ do + cmdBuildAccelerationStructureKHR' [SomeStruct buildGeomInfo] [offsetInfo] + (fenceKey, fence) <- withFence' zero + queueSubmit + graphicsQueue + [SomeStruct zero { commandBuffers = [commandBufferHandle commandBuffer] }] + fence + let oneSecond = 1e9 + waitForFencesSafe' [fence] True oneSecond >>= \case + SUCCESS -> pure () + TIMEOUT -> error "Timed out building acceleration structure" + _ -> error "blah" + sayErr "Built acceleration structure" + + -- free our building resources + release fenceKey + release poolKey + release scratchKey + +---------------------------------------------------------------- +-- BLAS +---------------------------------------------------------------- + +createBlasOnDevice :: V (ReleaseKey, AccelerationStructureKHR) +createBlasOnDevice = do + -- + -- Create the AS + -- let asci :: AccelerationStructureCreateInfoKHR asci = zero { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR @@ -24,42 +183,152 @@ createBLAS = do } ] } - (blasKey, blas) <- withAccelerationStructureKHR' asci + (blasKey, blas) <- withAccelerationStructureKHR' asci + createAndBindAccelerationMemory blas + nameObject' blas "BLAS" + + (_, geom, offsetInfo) <- biunitBoxGeometry + + buildBlasOnDevice blas geom offsetInfo + + pure (blasKey, blas) + +buildBlasOnDevice + :: AccelerationStructureKHR + -> AccelerationStructureGeometryKHR + -> AccelerationStructureBuildOffsetInfoKHR + -> V () +buildBlasOnDevice blas geom offsetInfo = do + -- + -- Get the memory requirements for building the AS + -- MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' zero { type' = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR - , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR + , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR , accelerationStructure = blas } + + -- + -- Allocate that space on the device + -- + (scratchKey, (scratch, scratchAllocation, scratchAllocationInfo)) <- + withBuffer' + zero + { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR + .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + , size = size (reqs :: MemoryRequirements) + } + zero + scratchAddr <- getBufferDeviceAddress' zero { buffer = scratch } + + -- + -- Create command buffers + -- + graphicsQueue <- getGraphicsQueue + QueueFamilyIndex graphicsQueueFamilyIndex <- getGraphicsQueueFamilyIndex + (poolKey, commandPool) <- withCommandPool' zero + { queueFamilyIndex = graphicsQueueFamilyIndex + } + ~[commandBuffer] <- allocateCommandBuffers' zero + { commandPool = commandPool + , level = COMMAND_BUFFER_LEVEL_PRIMARY + , commandBufferCount = 1 + } + + let buildGeomInfo = zero + { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR + , update = False + , dstAccelerationStructure = blas + , scratchData = DeviceAddress scratchAddr + , geometries = [geom] + } + + -- + -- Record and kick off the build commands + -- + useCommandBuffer' commandBuffer zero $ do + cmdBuildAccelerationStructureKHR' [SomeStruct buildGeomInfo] [offsetInfo] + (fenceKey, fence) <- withFence' zero + queueSubmit + graphicsQueue + [SomeStruct zero { commandBuffers = [commandBufferHandle commandBuffer] }] + fence + let oneSecond = 1e9 + waitForFencesSafe' [fence] True oneSecond >>= \case + SUCCESS -> pure () + TIMEOUT -> error "Timed out building acceleration structure" + _ -> error "blah" + sayErr "Built acceleration structure" + + -- free our building resources + release fenceKey + release poolKey + release scratchKey + pure () + +---------------------------------------------------------------- +-- Helpers +---------------------------------------------------------------- + +-- +-- The geometry for a biunit AABB on the device +-- +biunitBoxGeometry + :: V + ( ReleaseKey + , AccelerationStructureGeometryKHR + , AccelerationStructureBuildOffsetInfoKHR + ) +biunitBoxGeometry = do let -- a bounding box for the unit sphere box = AabbPositionsKHR (-1) (-1) (-1) 1 1 1 - withArray [box] $ \boxData -> do - allocaBytesAligned (fromIntegral (size (reqs :: MemoryRequirements))) - (fromIntegral (alignment reqs)) - $ \scratch -> do - let - infos = - [ SomeStruct zero - { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR - , update = False - , dstAccelerationStructure = blas - , scratchData = HostAddress scratch - , geometries = - [ zero - { geometryType = GEOMETRY_TYPE_AABBS_KHR - , flags = GEOMETRY_OPAQUE_BIT_KHR - , geometry = - Aabbs $ AccelerationStructureGeometryAabbsDataKHR - { data' = HostAddressConst (castPtr boxData) - , stride = 0 - } - } - ] + (bufferKey, (buffer, bufferAllocation, _)) <- withBuffer' + zero + { usage = BUFFER_USAGE_TRANSFER_SRC_BIT + .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + .|. BUFFER_USAGE_RAY_TRACING_BIT_KHR + , size = fromIntegral (sizeOf box) + } + zero + { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + .|. MEMORY_PROPERTY_HOST_COHERENT_BIT + } + (boxMapKey, boxMapPtr) <- withMappedMemory' bufferAllocation + liftIO $ poke (castPtr boxMapPtr) box + release boxMapKey + boxAddr <- getBufferDeviceAddress' zero { buffer = buffer } + let boxData = AccelerationStructureGeometryAabbsDataKHR + { data' = DeviceAddressConst boxAddr + , stride = fromIntegral (sizeOf box) + } + let geom :: AccelerationStructureGeometryKHR + geom = zero { geometryType = GEOMETRY_TYPE_AABBS_KHR + , flags = GEOMETRY_OPAQUE_BIT_KHR + , geometry = Aabbs boxData } - ] - offsetInfos = [zero { primitiveCount = 1, primitiveOffset = 0 }] - buildAccelerationStructureKHR' infos offsetInfos >>= \case - SUCCESS -> pure () - _ -> error "oops" - pure () + let offsetInfo = zero { primitiveCount = 1, primitiveOffset = 0 } + pure (bufferKey, geom, offsetInfo) + +createAndBindAccelerationMemory :: AccelerationStructureKHR -> V () +createAndBindAccelerationMemory as = do + MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' + zero { type' = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR + , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR + , accelerationStructure = as + } + + (releaseMem, (allocation, allocationInfo)) <- withMemory' + reqs + zero { usage = MEMORY_USAGE_GPU_ONLY + , requiredFlags = MEMORY_PROPERTY_DEVICE_LOCAL_BIT + } + + let bindInfo :: BindAccelerationStructureMemoryInfoKHR + bindInfo = zero + { accelerationStructure = as + , memory = deviceMemory allocationInfo + , memoryOffset = offset (allocationInfo :: AllocationInfo) + } + bindAccelerationStructureMemoryKHR' [bindInfo] diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index c859119e7..47653211c 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -22,7 +22,6 @@ import qualified Pipeline import qualified SDL import SDL ( Window ) import qualified SDL.Video.Vulkan as SDL -import Say import Swapchain import Vulkan.CStruct.Extends import Vulkan.Core10 @@ -30,6 +29,7 @@ import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore import Vulkan.Extensions.VK_KHR_surface import Vulkan.Utils.QueueAssignment import Vulkan.Zero +import Vulkan.Extensions.VK_KHR_ray_tracing -- | Must be positive, duh numConcurrentFrames :: Int @@ -45,6 +45,7 @@ data Frame = Frame , fSwapchainResources :: SwapchainResources , fPipeline :: Pipeline , fPipelineLayout :: PipelineLayout + , fAccelerationStructure :: AccelerationStructureKHR , fShaderBindingTable :: Buffer , fRenderFinishedHostSemaphore :: Semaphore -- ^ A timeline semaphore which increments to fIndex when this frame is @@ -90,14 +91,18 @@ initialFrame fWindow fSurface = do windowSize fSurface + -- The acceleration structure + (_, fAccelerationStructure) <- createTLAS + -- Create the RT pipeline - (_, descriptorSetLayout) <- Pipeline.createRTDescriptorSetLayout + (_, descriptorSetLayout ) <- Pipeline.createRTDescriptorSetLayout (_, fPipelineLayout) <- Pipeline.createRTPipelineLayout descriptorSetLayout - (_, fPipeline, numGroups) <- Pipeline.createPipeline fPipelineLayout - (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline - numGroups + (_, fPipeline, numGroups) <- Pipeline.createPipeline fPipelineLayout + (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline + numGroups descriptorSets <- Pipeline.createRTDescriptorSets descriptorSetLayout + fAccelerationStructure (fromIntegral numConcurrentFrames) -- Don't keep the release key, this semaphore lives for the lifetime of the @@ -118,8 +123,6 @@ initialFrame fWindow fSurface = do -- correctly on exception fResources <- allocate createInternalState closeInternalState - createBLAS - pure Frame { .. } -- | Create the next frame @@ -128,10 +131,8 @@ advanceFrame needsNewSwapchain f = do -- Wait for a prior frame to finish, then we can steal it's resources! nib <- V $ asks ghRecycleNib fRecycledResources <- liftIO $ nib >>= \case - Left block -> do - sayErr "CPU is running ahead" - block - Right rs -> pure rs + Left block -> block + Right rs -> pure rs fSwapchainResources <- if needsNewSwapchain then recreateSwapchainResources (fWindow f) (fSwapchainResources f) @@ -148,6 +149,7 @@ advanceFrame needsNewSwapchain f = do , fPipeline = fPipeline f , fPipelineLayout = fPipelineLayout f , fShaderBindingTable = fShaderBindingTable f + , fAccelerationStructure = fAccelerationStructure f , fRenderFinishedHostSemaphore = fRenderFinishedHostSemaphore f , fGPUWork , fResources diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index 4248e8cb0..37d175219 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -38,6 +38,7 @@ import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) +import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address import Vulkan.Extensions.VK_EXT_descriptor_indexing ( pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME ) @@ -64,6 +65,7 @@ import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment import Vulkan.Zero import VulkanMemoryAllocator ( Allocator + , AllocatorCreateFlagBits(..) , AllocatorCreateInfo(..) , withAllocator ) @@ -95,6 +97,7 @@ createInstance win = do -- Device creation ---------------------------------------------------------------- +-- TODO: check VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress. createDevice :: forall m . (MonadResource m) @@ -116,9 +119,8 @@ createDevice inst win = do let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } ::& PhysicalDeviceTimelineSemaphoreFeatures True - :& zero { rayTracing = True - , rayTracingHostAccelerationStructureCommands = True - } + :& zero { rayTracing = True } + :& zero { bufferDeviceAddress = True } :& () rayTracingExtensions = [ KHR_RAY_TRACING_EXTENSION_NAME @@ -236,8 +238,8 @@ deviceHasRayTracing phys = do hasFeat = do feats <- getPhysicalDeviceFeatures2KHR phys - let _ ::& f@PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats - pure $ rayTracing && rayTracingHostAccelerationStructureCommands + let _ ::& PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats + pure rayTracing getProps = do props <- getPhysicalDeviceProperties2KHR phys @@ -265,7 +267,7 @@ createVMA createVMA inst phys dev = snd <$> withAllocator - zero { flags = zero + zero { flags = ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT , physicalDevice = physicalDeviceHandle phys , device = deviceHandle dev , instance' = instanceHandle inst diff --git a/examples/rays/MonadFrame.hs b/examples/rays/MonadFrame.hs index cc06ec8a8..ae1d71f59 100644 --- a/examples/rays/MonadFrame.hs +++ b/examples/rays/MonadFrame.hs @@ -123,9 +123,7 @@ allocateGlobal_ create destroy = allocateGlobal create (const destroy) -- | Free frame resources, the frame must have finished GPU execution first. retireFrame :: MonadIO m => Frame -> m () -retireFrame Frame {..} = do - sayErrString ("retiring frame " <> show fIndex) - release (fst fResources) +retireFrame Frame {..} = release (fst fResources) -- | Make sure a reference is held until this frame is retired frameRefCount :: RefCounted -> F () diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index a9c63c834..64bd85bd7 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -24,16 +24,18 @@ import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) +import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address + ( getBufferDeviceAddress ) import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore as Timeline import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.CommandCheck +import Vulkan.Utils.Debug ( nameObject ) import Vulkan.Utils.QueueAssignment import VulkanMemoryAllocator as VMA hiding ( getPhysicalDeviceProperties ) -import Vulkan.Utils.Debug (nameObject) ---------------------------------------------------------------- -- Define the monad in which most of the program will run @@ -197,15 +199,18 @@ do let vmaCommands = [ 'withBuffer , 'VMA.withMappedMemory + , 'VMA.withMemory , 'invalidateAllocation ] commands = [ 'acquireNextImageKHR , 'allocateCommandBuffers , 'allocateDescriptorSets + , 'bindAccelerationStructureMemoryKHR , 'buildAccelerationStructureKHR , 'cmdBindDescriptorSets , 'cmdBindPipeline + , 'cmdBuildAccelerationStructureKHR , 'cmdDispatch , 'cmdDraw , 'cmdPipelineBarrier @@ -216,7 +221,9 @@ do , 'cmdUseRenderPass , 'deviceWaitIdle , 'deviceWaitIdleSafe + , 'getAccelerationStructureDeviceAddressKHR , 'getAccelerationStructureMemoryRequirementsKHR + , 'getBufferDeviceAddress , 'getDeviceQueue , 'getPhysicalDeviceSurfaceCapabilitiesKHR , 'getPhysicalDeviceSurfaceFormatsKHR diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 344b69f5b..e6d7537ff 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -9,13 +9,12 @@ module Pipeline , createRTDescriptorSetLayout , createRTDescriptorSets , createShaderBindingTable - , Pipeline.createRenderPass ) where import Control.Monad.IO.Class import Control.Monad.Trans.Resource import Data.Bits -import Data.Foldable ( traverse_ ) +import Data.Foldable (for_, traverse_ ) import qualified Data.Vector as V import Data.Vector ( Vector ) import Data.Word @@ -34,22 +33,41 @@ import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Utils.ShaderQQ import Vulkan.Zero import VulkanMemoryAllocator +import Say -- Create the most vanilla ray tracing pipeline, returns the number of shader -- groups createPipeline :: PipelineLayout -> V (ReleaseKey, Pipeline, Word32) createPipeline pipelineLayout = do - (shaderKeys, shaderStages) <- V.unzip <$> sequence [createRayGenerationShader] + (shaderKeys, shaderStages) <- V.unzip <$> sequence + [ createRayGenerationShader + , createRayIntShader + , createRayMissShader + , createRayHitShader + ] - let rtsgci :: RayTracingShaderGroupCreateInfoKHR - rtsgci = RayTracingShaderGroupCreateInfoKHR + let genGroup = RayTracingShaderGroupCreateInfoKHR RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR 0 -- The index of our general shader SHADER_UNUSED_KHR SHADER_UNUSED_KHR SHADER_UNUSED_KHR nullPtr - shaderGroups = [rtsgci] + intGroup = RayTracingShaderGroupCreateInfoKHR + RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR + SHADER_UNUSED_KHR + 3 -- closest hit + SHADER_UNUSED_KHR + 1 -- intersection + nullPtr + missGroup = RayTracingShaderGroupCreateInfoKHR + RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR + 2 + SHADER_UNUSED_KHR + SHADER_UNUSED_KHR + SHADER_UNUSED_KHR + nullPtr + shaderGroups = [genGroup, intGroup, missGroup] let pipelineCreateInfo :: RayTracingPipelineCreateInfoKHR '[] pipelineCreateInfo = zero { stages = shaderStages @@ -63,7 +81,7 @@ createPipeline pipelineLayout = do traverse_ release shaderKeys - pure (key, rtPipeline, fromIntegral (length shaderStages)) + pure (key, rtPipeline, fromIntegral (V.length shaderGroups)) createRTPipelineLayout :: DescriptorSetLayout -> V (ReleaseKey, PipelineLayout) createRTPipelineLayout descriptorSetLayout = @@ -76,29 +94,58 @@ createRTDescriptorSetLayout = withDescriptorSetLayout' zero , descriptorCount = 1 , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR } + , zero + { binding = 0 + , descriptorType = DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + , descriptorCount = 1 + , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR + } ] } createRTDescriptorSets - :: DescriptorSetLayout -> Word32 -> V (Vector DescriptorSet) -createRTDescriptorSets descriptorSetLayout numDescriptorSets = do + :: DescriptorSetLayout + -> AccelerationStructureKHR + -> Word32 + -> V (Vector DescriptorSet) +createRTDescriptorSets descriptorSetLayout tlas numDescriptorSets = do + let numImagesPerSet = 1 + numAccelerationStructuresPerSet = 1 -- Create a descriptor pool (_, descriptorPool) <- withDescriptorPool' zero { maxSets = numDescriptorSets , poolSizes = [ DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_IMAGE - numDescriptorSets + (numDescriptorSets * numImagesPerSet) + , DescriptorPoolSize + DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + (numDescriptorSets * numAccelerationStructuresPerSet) ] } -- Allocate a descriptor set from the pool with that layout -- Don't use `withDescriptorSets` here as the set will be cleaned up when -- the pool is destroyed. - allocateDescriptorSets' zero + sets <- allocateDescriptorSets' zero { descriptorPool = descriptorPool , setLayouts = V.replicate (fromIntegral numDescriptorSets) descriptorSetLayout } + -- Put the static accelerationStructure into the set + for_ sets $ \set -> updateDescriptorSets' + [ SomeStruct + $ zero { dstSet = set + , dstBinding = 0 + , descriptorType = DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + , descriptorCount = 1 + } + ::& zero { accelerationStructures = [tlas] } + :& () + ] + [] + + pure sets + createRayGenerationShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) createRayGenerationShader = do @@ -106,11 +153,36 @@ createRayGenerationShader = do #version 460 #extension GL_EXT_ray_tracing : require - layout(binding = 1, set = 0, rgba32f) uniform image2D image; + layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; + layout(binding = 1, set = 0, rgba8) uniform image2D image; + layout(location = 0) rayPayloadEXT vec3 prd; void main() { - imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(0.5, 0.6, 0.8, 1.0)); + const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); + const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); + const vec2 d = inUV * 2.0 - 1.0; + const vec3 origin = vec3(-10,0,0); + const vec3 direction = vec3(1,d); + const uint rayFlags = gl_RayFlagsOpaqueEXT; + const float tMin = 0.001; + const float tMax = 10000.0; + const uint cullMask = 0xff; + const uint sbtRecordOffset = 0; + const uint sbtRecordStride = 1; + const uint missIndex = 0; + traceRayEXT(topLevelAS, + rayFlags, + cullMask, + sbtRecordOffset, + sbtRecordStride, + missIndex, + origin.xyz, + tMin, + direction.xyz, + tMax, + 0); + imageStore(image, ivec2(gl_LaunchIDEXT.xy), vec4(prd, 1.0)); } |]) @@ -119,6 +191,62 @@ createRayGenerationShader = do zero { stage = SHADER_STAGE_RAYGEN_BIT_KHR, module', name = "main" } pure (key, SomeStruct shaderStageCreateInfo) +createRayHitShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) +createRayHitShader = do + let code = $(compileShaderQ "rchit" [glsl| + #version 460 + #extension GL_EXT_ray_tracing : require + + layout(location = 0) rayPayloadInEXT vec3 hitValue; + + void main() + { + hitValue = vec3(0.2, 0.5, 0.5); + } + |]) + + (key, module') <- withShaderModule' zero { code } + let shaderStageCreateInfo = + zero { stage = SHADER_STAGE_CLOSEST_HIT_BIT_KHR, module', name = "main" } + pure (key, SomeStruct shaderStageCreateInfo) + +createRayIntShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) +createRayIntShader = do + let code = $(compileShaderQ "rint" [glsl| + #version 460 + #extension GL_EXT_ray_tracing : require + + void main() + { + const float hitT = 1; + const uint hitKind = 0; + reportIntersectionEXT(hitT, hitKind); + } + |]) + + (key, module') <- withShaderModule' zero { code } + let shaderStageCreateInfo = + zero { stage = SHADER_STAGE_INTERSECTION_BIT_KHR, module', name = "main" } + pure (key, SomeStruct shaderStageCreateInfo) + +createRayMissShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) +createRayMissShader = do + let code = $(compileShaderQ "rmiss" [glsl| + #version 460 + #extension GL_EXT_ray_tracing : require + + layout(location = 0) rayPayloadInEXT vec3 hitValue; + + void main() + { + hitValue = vec3(1.0, 0.1, 0.3); + } + |]) + + (key, module') <- withShaderModule' zero { code } + let shaderStageCreateInfo = + zero { stage = SHADER_STAGE_MISS_BIT_KHR, module', name = "main" } + pure (key, SomeStruct shaderStageCreateInfo) ---------------------------------------------------------------- -- Shader binding table ---------------------------------------------------------------- @@ -133,9 +261,11 @@ createShaderBindingTable pipeline numGroups = do -- them equal to their alignment sbtSize = fromIntegral $ handleStride * (numGroups - 1) + handleSize + sayErrShow (handleStride, rtiShaderGroupBaseAlignment) + (bufferReleaseKey, (sbtBuffer, sbtAllocation, _sbtAllocationInfo)) <- withBuffer' - zero { usage = BUFFER_USAGE_TRANSFER_SRC_BIT, size = sbtSize } + zero { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR, size = sbtSize } zero { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT .|. MEMORY_PROPERTY_HOST_COHERENT_BIT @@ -167,48 +297,6 @@ unpackObjects numObjs size desiredStride buf = do moveObject n = moveBytes (objectFinalPosition n) (objectInitalPosition n) (fromIntegral size) - -- Move the object last to first - liftIO $ traverse_ @[] moveObject [(numObjs - 1) .. 0] - ----------------------------------------------------------------- --- Render pass creation ----------------------------------------------------------------- - --- | Create a renderpass with a single subpass -createRenderPass :: Format -> V (ReleaseKey, RenderPass) -createRenderPass imageFormat = do - let - attachmentDescription :: AttachmentDescription - attachmentDescription = zero - { format = imageFormat - , samples = SAMPLE_COUNT_1_BIT - , loadOp = ATTACHMENT_LOAD_OP_CLEAR - , storeOp = ATTACHMENT_STORE_OP_STORE - , stencilLoadOp = ATTACHMENT_LOAD_OP_DONT_CARE - , stencilStoreOp = ATTACHMENT_STORE_OP_DONT_CARE - , initialLayout = IMAGE_LAYOUT_UNDEFINED - , finalLayout = IMAGE_LAYOUT_PRESENT_SRC_KHR - } - subpass :: SubpassDescription - subpass = zero - { pipelineBindPoint = PIPELINE_BIND_POINT_GRAPHICS - , colorAttachments = - [ zero { attachment = 0 - , layout = IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - } - ] - } - subpassDependency :: SubpassDependency - subpassDependency = zero - { srcSubpass = SUBPASS_EXTERNAL - , dstSubpass = 0 - , srcStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - , srcAccessMask = zero - , dstStageMask = PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - , dstAccessMask = ACCESS_COLOR_ATTACHMENT_READ_BIT - .|. ACCESS_COLOR_ATTACHMENT_WRITE_BIT - } - withRenderPass' zero { attachments = [attachmentDescription] - , subpasses = [subpass] - , dependencies = [subpassDependency] - } + -- Move the object last to first + indicesToMove = drop 1 [numObjs, numObjs-1 .. 1] + liftIO $ traverse_ @[] moveObject indicesToMove diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 68f1e83a1..9043f5985 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -15,7 +15,6 @@ import GHC.IO.Exception ( IOErrorType(TimeExpired) ) import MonadFrame import MonadVulkan -import Say import Swapchain import UnliftIO.Exception ( throwString ) import Vulkan.CStruct.Extends @@ -105,7 +104,7 @@ renderFrame = do , swapchains = [siSwapchain] , imageIndices = [imageIndex] } - sayErrString ("submitted " <> show fIndex) + pure () ---------------------------------------------------------------- -- Command buffer recording @@ -116,25 +115,42 @@ myRecordCommandBuffer :: Frame -> Word32 -> CmdT F () myRecordCommandBuffer Frame {..} imageIndex = do -- TODO: neaten RTInfo {..} <- CmdT . lift . liftV $ getRTInfo - let RecycledResources {..} = fRecycledResources - SwapchainResources {..} = fSwapchainResources - SwapchainInfo {..} = srInfo - image = srImages ! fromIntegral imageIndex - imageWidth = width (siImageExtent :: Extent2D) - imageHeight = height (siImageExtent :: Extent2D) - imageSubresourceRange = ImageSubresourceRange - { aspectMask = IMAGE_ASPECT_COLOR_BIT - , baseMipLevel = 0 - , levelCount = 1 - , baseArrayLayer = 0 - , layerCount = 1 - } - sbtRegion = StridedBufferRegionKHR - { buffer = fShaderBindingTable - , offset = 0 - , stride = fromIntegral rtiShaderGroupBaseAlignment - , size = fromIntegral rtiShaderGroupBaseAlignment -- * 1 - } + let + RecycledResources {..} = fRecycledResources + SwapchainResources {..} = fSwapchainResources + SwapchainInfo {..} = srInfo + image = srImages ! fromIntegral imageIndex + imageWidth = width (siImageExtent :: Extent2D) + imageHeight = height (siImageExtent :: Extent2D) + imageSubresourceRange = ImageSubresourceRange + { aspectMask = IMAGE_ASPECT_COLOR_BIT + , baseMipLevel = 0 + , levelCount = 1 + , baseArrayLayer = 0 + , layerCount = 1 + } + numRayGenShaderGroups = 1 + rayGenRegion = StridedBufferRegionKHR + { buffer = fShaderBindingTable + , offset = 0 + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment * numRayGenShaderGroups + } + numHitShaderGroups = 1 + hitRegion = StridedBufferRegionKHR + { buffer = fShaderBindingTable + , offset = 1 * fromIntegral rtiShaderGroupBaseAlignment + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment * numHitShaderGroups + } + numMissShaderGroups = 1 + missRegion = StridedBufferRegionKHR + { buffer = fShaderBindingTable + , offset = 2 * fromIntegral rtiShaderGroupBaseAlignment + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment * numMissShaderGroups + } + callableRegion = zero do -- Transition image to general, to write from the ray tracing shader cmdPipelineBarrier' @@ -163,7 +179,13 @@ myRecordCommandBuffer Frame {..} imageIndex = do -- -- The actual ray tracing -- - cmdTraceRaysKHR' sbtRegion zero zero zero imageWidth imageHeight 1 + cmdTraceRaysKHR' rayGenRegion + missRegion + hitRegion + callableRegion + imageWidth + imageHeight + 1 -- Transition image back to present cmdPipelineBarrier' diff --git a/examples/rays/Swapchain.hs b/examples/rays/Swapchain.hs index a3208940a..a0b77fef9 100644 --- a/examples/rays/Swapchain.hs +++ b/examples/rays/Swapchain.hs @@ -30,6 +30,7 @@ import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.Misc import Vulkan.Zero +import Say data SwapchainInfo = SwapchainInfo { siSwapchain :: SwapchainKHR @@ -124,6 +125,7 @@ createSwapchain oldSwapchain explicitSize surf = do -- getPhysicalDeviceSurfaceFormatsKHR doesn't return an empty list (_, availableFormats) <- getPhysicalDeviceSurfaceFormatsKHR' surf let surfaceFormat = selectSurfaceFormat availableFormats + sayErrString $ "Using surface format: " <> show surfaceFormat -- Calculate the extent let imageExtent = From bd04e35f7ab90c975e3f1dcf5179a7f52aed3782 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 00:11:49 +0800 Subject: [PATCH 24/70] Intersect with a sphere --- examples/rays/Pipeline.hs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index e6d7537ff..1fa0bd96b 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -163,7 +163,7 @@ createRayGenerationShader = do const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); const vec2 d = inUV * 2.0 - 1.0; const vec3 origin = vec3(-10,0,0); - const vec3 direction = vec3(1,d); + const vec3 direction = normalize(vec3(1,d)); const uint rayFlags = gl_RayFlagsOpaqueEXT; const float tMin = 0.001; const float tMax = 10000.0; @@ -218,9 +218,20 @@ createRayIntShader = do void main() { - const float hitT = 1; - const uint hitKind = 0; - reportIntersectionEXT(hitT, hitKind); + const vec3 o = gl_WorldRayOriginEXT; + const vec3 d = gl_WorldRayDirectionEXT; + const vec3 s = vec3(0,0,0); + const float r = 1; + + const vec3 diff = o - s; + + const float x = (dot(d, diff) * dot(d, diff)) - (dot(diff, diff) - r*r); + if (x < 0) + return; + + const float m = -(dot(d, diff)); + reportIntersectionEXT(m - sqrt(x), 0); + reportIntersectionEXT(m + sqrt(x), 0); } |]) @@ -298,5 +309,5 @@ unpackObjects numObjs size desiredStride buf = do (objectInitalPosition n) (fromIntegral size) -- Move the object last to first - indicesToMove = drop 1 [numObjs, numObjs-1 .. 1] - liftIO $ traverse_ @[] moveObject indicesToMove + indicesToMove = drop 1 [numObjs, numObjs - 1 .. 1] + liftIO $ traverse_ moveObject indicesToMove From 9dcfcc4ff6f7868fc82f111c5cce69745040f962 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 23 Nov 2020 13:36:44 +0800 Subject: [PATCH 25/70] Better hie yaml for root --- hie.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hie.yaml b/hie.yaml index 04cd24395..77eb39540 100644 --- a/hie.yaml +++ b/hie.yaml @@ -1,2 +1,12 @@ cradle: cabal: + - path: "./generate-new/src/" + component: "lib:generate-new" + - path: "./generate-new/vk/" + component: "exe:vk" + - path: "./generate-new/vma/" + component: "exe:vma" + - path: "./src/" + component: "lib:vulkan" + - path: "./VulkanMemoryAllocator/" + component: "lib:VulkanMemoryAllocator" From 336a31529c4ca35869b32f2a21b3d14a393cdfc4 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 18:52:42 +0800 Subject: [PATCH 26/70] Update rays example for 1.2.162 --- examples/rays/AccelerationStructure.hs | 400 ++++++++++--------------- examples/rays/Frame.hs | 8 +- examples/rays/Init.hs | 74 ++++- examples/rays/MonadVulkan.hs | 14 +- examples/rays/Pipeline.hs | 20 +- examples/rays/Render.hs | 73 +++-- 6 files changed, 287 insertions(+), 302 deletions(-) diff --git a/examples/rays/AccelerationStructure.hs b/examples/rays/AccelerationStructure.hs index 54b289e28..bd10d4bd1 100644 --- a/examples/rays/AccelerationStructure.hs +++ b/examples/rays/AccelerationStructure.hs @@ -6,20 +6,25 @@ import Control.Monad.IO.Class import Control.Monad.Trans.Resource import Data.Bits import Data.Coerce ( coerce ) -import Foreign.Storable ( Storable(sizeOf) ) -import Foreign.Storable ( Storable(poke) ) +import Data.Vector ( Vector ) +import Foreign.Storable ( Storable(poke, sizeOf) ) import MonadVulkan -import Say import UnliftIO.Foreign ( castPtr ) import Vulkan.CStruct import Vulkan.CStruct.Extends import Vulkan.Core10 -import Vulkan.Core11 ( MemoryRequirements2(..) ) import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address -import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Extensions.VK_KHR_acceleration_structure import Vulkan.Utils.QueueAssignment import Vulkan.Zero -import VulkanMemoryAllocator +import VulkanMemoryAllocator ( AllocationCreateInfo + ( requiredFlags + , usage + ) + , MemoryUsage + ( MEMORY_USAGE_GPU_ONLY + ) + ) ---------------------------------------------------------------- -- TLAS @@ -27,26 +32,35 @@ import VulkanMemoryAllocator createTLAS :: V (ReleaseKey, AccelerationStructureKHR) createTLAS = do - let geomType = zero { geometryType = GEOMETRY_TYPE_INSTANCES_KHR - , maxPrimitiveCount = 1 - , allowsTransforms = False - } - asci = zero - { type' = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR - , flags = BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR - , geometryInfos = [geomType] + -- + -- Create the bottom level accelerationStructures + -- + (_blasReleaseKey, blas) <- createBLAS + blasAddress <- getAccelerationStructureDeviceAddressKHR' zero + { accelerationStructure = blas + } + let identity = TransformMatrixKHR (1, 0, 0, 0) (0, 1, 0, 0) (0, 0, 1, 0) + inst :: AccelerationStructureInstanceKHR + inst = zero + { transform = identity + , instanceCustomIndex = complement 0 -- TODO: unnecessary + , mask = complement 0 + , instanceShaderBindingTableRecordOffset = 0 + , flags = GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR + , accelerationStructureReference = coerce blasAddress } - (tlasKey, tlas) <- withAccelerationStructureKHR' asci - createAndBindAccelerationMemory tlas - nameObject' tlas "TLAS" + -- + -- Create the buffer for the top level instances + -- let numInstances = 1 instanceDescsSize = numInstances * cStructSize @AccelerationStructureInstanceKHR - (instBufferReleaseKey, (instBuffer, instBufferAllocation, _)) <- withBuffer' + (_instBufferReleaseKey, (instBuffer, instBufferAllocation, _)) <- withBuffer' zero - { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR - .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + { usage = + BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR + .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT , size = fromIntegral instanceDescsSize } -- TODO: Make this GPU only and transfer to it @@ -58,220 +72,116 @@ createTLAS = do instBufferDeviceAddress <- getBufferDeviceAddress' zero { buffer = instBuffer } - (blasReleaseKey, blas) <- createBlasOnDevice - blasAddress <- getAccelerationStructureDeviceAddressKHR' zero - { accelerationStructure = blas - } - let identity = TransformMatrixKHR ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0)) - inst :: AccelerationStructureInstanceKHR - inst = zero - { transform = identity - , instanceCustomIndex = complement 0 -- TODO: unnecessary - , mask = complement 0 - , instanceShaderBindingTableRecordOffset = 0 - , flags = GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR - , accelerationStructureReference = coerce blasAddress - } + -- + -- populate the instance buffer + -- (instMapKey, instMapPtr) <- withMappedMemory' instBufferAllocation liftIO $ poke (castPtr @_ @AccelerationStructureInstanceKHR instMapPtr) inst release instMapKey - let geomData = AccelerationStructureGeometryInstancesDataKHR - { arrayOfPointers = False - , data' = DeviceAddressConst instBufferDeviceAddress - } - geom :: AccelerationStructureGeometryKHR - geom = zero { geometryType = GEOMETRY_TYPE_INSTANCES_KHR - , geometry = Instances geomData - , flags = GEOMETRY_OPAQUE_BIT_KHR - } - let offsetInfo = zero { primitiveCount = 1, primitiveOffset = 0 } - - buildTlasOnDevice tlas geom offsetInfo + let buildGeometries = + [ zero + { geometryType = GEOMETRY_TYPE_INSTANCES_KHR + , geometry = Instances AccelerationStructureGeometryInstancesDataKHR + { arrayOfPointers = False + , data' = DeviceAddressConst instBufferDeviceAddress + } + , flags = GEOMETRY_OPAQUE_BIT_KHR + } + ] + buildInfo = zero { type' = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + , mode = BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR -- ignored but used later + , srcAccelerationStructure = NULL_HANDLE -- ignored + , dstAccelerationStructure = NULL_HANDLE -- ignored + , geometries = buildGeometries + , scratchData = zero + } + maxPrimitiveCounts = [1] + rangeInfos = [zero { primitiveCount = 1, primitiveOffset = 0 }] + sizes <- getAccelerationStructureBuildSizesKHR' + ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR + buildInfo + maxPrimitiveCounts + (_tlasBufferKey, tlasKey, tlas) <- buildAccelerationStructure buildInfo + rangeInfos + sizes + nameObject' tlas "TLAS" pure (tlasKey, tlas) --- TODO: deduplicate this and buildBlasOnDevice -buildTlasOnDevice - :: AccelerationStructureKHR - -> AccelerationStructureGeometryKHR - -> AccelerationStructureBuildOffsetInfoKHR - -> V () -buildTlasOnDevice tlas geom offsetInfo = do - -- - -- Get the memory requirements for building the AS - -- - MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' - zero - { type' = - ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR - , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR - , accelerationStructure = tlas - } - +buildAccelerationStructure + :: AccelerationStructureBuildGeometryInfoKHR + -> Vector AccelerationStructureBuildRangeInfoKHR + -> AccelerationStructureBuildSizesInfoKHR + -> V (ReleaseKey, ReleaseKey, AccelerationStructureKHR) +buildAccelerationStructure geom ranges sizes = do -- - -- Allocate that space on the device + -- Allocate the buffer to hold the acceleration structure -- - (scratchKey, (scratch, scratchAllocation, scratchAllocationInfo)) <- - withBuffer' - zero - { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR - .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - , size = size (reqs :: MemoryRequirements) - } - zero - scratchAddr <- getBufferDeviceAddress' zero { buffer = scratch } + let bufferSize = accelerationStructureSize sizes + (asBufferKey, (asBuffer, _, _)) <- withBuffer' + zero { size = bufferSize + , usage = BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR + } + zero { usage = MEMORY_USAGE_GPU_ONLY } -- - -- Create command buffers + -- Allocate scratch space for building -- - graphicsQueue <- getGraphicsQueue - QueueFamilyIndex graphicsQueueFamilyIndex <- getGraphicsQueueFamilyIndex - (poolKey, commandPool) <- withCommandPool' zero - { queueFamilyIndex = graphicsQueueFamilyIndex - } - ~[commandBuffer] <- allocateCommandBuffers' zero - { commandPool = commandPool - , level = COMMAND_BUFFER_LEVEL_PRIMARY - , commandBufferCount = 1 + (scratchBufferKey, (scratchBuffer, _, _)) <- withBuffer' + zero { size = buildScratchSize sizes + , usage = BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + } + zero { usage = MEMORY_USAGE_GPU_ONLY } + scratchBufferDeviceAddress <- getBufferDeviceAddress' zero + { buffer = scratchBuffer } - let buildGeomInfo = zero { type' = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR - , update = False - , dstAccelerationStructure = tlas - , scratchData = DeviceAddress scratchAddr - , geometries = [geom] - } - - -- - -- Record and kick off the build commands - -- - useCommandBuffer' commandBuffer zero $ do - cmdBuildAccelerationStructureKHR' [SomeStruct buildGeomInfo] [offsetInfo] - (fenceKey, fence) <- withFence' zero - queueSubmit - graphicsQueue - [SomeStruct zero { commandBuffers = [commandBufferHandle commandBuffer] }] - fence - let oneSecond = 1e9 - waitForFencesSafe' [fence] True oneSecond >>= \case - SUCCESS -> pure () - TIMEOUT -> error "Timed out building acceleration structure" - _ -> error "blah" - sayErr "Built acceleration structure" + let asci = zero { type' = ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + , buffer = asBuffer + , offset = 0 + , size = bufferSize + } + (asKey, as) <- withAccelerationStructureKHR' asci - -- free our building resources - release fenceKey - release poolKey - release scratchKey + oneShotComputeCommands $ do + cmdBuildAccelerationStructuresKHR' + [ geom { dstAccelerationStructure = as + , scratchData = DeviceAddress scratchBufferDeviceAddress + } + ] + [ranges] ----------------------------------------------------------------- --- BLAS ----------------------------------------------------------------- + release scratchBufferKey -createBlasOnDevice :: V (ReleaseKey, AccelerationStructureKHR) -createBlasOnDevice = do - -- - -- Create the AS - -- - let asci :: AccelerationStructureCreateInfoKHR - asci = zero - { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR - , flags = BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR - , geometryInfos = [ zero { geometryType = GEOMETRY_TYPE_AABBS_KHR - , maxPrimitiveCount = 1 - } - ] - } - (blasKey, blas) <- withAccelerationStructureKHR' asci - createAndBindAccelerationMemory blas - nameObject' blas "BLAS" + pure (asKey, asBufferKey, as) - (_, geom, offsetInfo) <- biunitBoxGeometry +-- +-- Create the bottom level acceleration structure +-- +createBLAS :: V (ReleaseKey, AccelerationStructureKHR) +createBLAS = do + (_, boxGeom, boxOffsets) <- biunitBoxGeometry - buildBlasOnDevice blas geom offsetInfo + let buildInfo = zero { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR + , mode = BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR -- ignored but used later + , srcAccelerationStructure = NULL_HANDLE -- ignored + , dstAccelerationStructure = NULL_HANDLE -- ignored + , geometries = [boxGeom] + , scratchData = zero + } + maxPrimitiveCounts = [1] + sizes <- getAccelerationStructureBuildSizesKHR' + ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR + buildInfo + maxPrimitiveCounts + (_blasBufferKey, blasKey, blas) <- buildAccelerationStructure buildInfo + boxOffsets + sizes + nameObject' blas "BLAS" pure (blasKey, blas) -buildBlasOnDevice - :: AccelerationStructureKHR - -> AccelerationStructureGeometryKHR - -> AccelerationStructureBuildOffsetInfoKHR - -> V () -buildBlasOnDevice blas geom offsetInfo = do - -- - -- Get the memory requirements for building the AS - -- - MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' - zero - { type' = - ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR - , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR - , accelerationStructure = blas - } - - -- - -- Allocate that space on the device - -- - (scratchKey, (scratch, scratchAllocation, scratchAllocationInfo)) <- - withBuffer' - zero - { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR - .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - , size = size (reqs :: MemoryRequirements) - } - zero - scratchAddr <- getBufferDeviceAddress' zero { buffer = scratch } - - -- - -- Create command buffers - -- - graphicsQueue <- getGraphicsQueue - QueueFamilyIndex graphicsQueueFamilyIndex <- getGraphicsQueueFamilyIndex - (poolKey, commandPool) <- withCommandPool' zero - { queueFamilyIndex = graphicsQueueFamilyIndex - } - ~[commandBuffer] <- allocateCommandBuffers' zero - { commandPool = commandPool - , level = COMMAND_BUFFER_LEVEL_PRIMARY - , commandBufferCount = 1 - } - - let buildGeomInfo = zero - { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR - , update = False - , dstAccelerationStructure = blas - , scratchData = DeviceAddress scratchAddr - , geometries = [geom] - } - - -- - -- Record and kick off the build commands - -- - useCommandBuffer' commandBuffer zero $ do - cmdBuildAccelerationStructureKHR' [SomeStruct buildGeomInfo] [offsetInfo] - (fenceKey, fence) <- withFence' zero - queueSubmit - graphicsQueue - [SomeStruct zero { commandBuffers = [commandBufferHandle commandBuffer] }] - fence - let oneSecond = 1e9 - waitForFencesSafe' [fence] True oneSecond >>= \case - SUCCESS -> pure () - TIMEOUT -> error "Timed out building acceleration structure" - _ -> error "blah" - sayErr "Built acceleration structure" - - -- free our building resources - release fenceKey - release poolKey - release scratchKey - pure () - ----------------------------------------------------------------- --- Helpers ----------------------------------------------------------------- - -- -- The geometry for a biunit AABB on the device -- @@ -279,16 +189,16 @@ biunitBoxGeometry :: V ( ReleaseKey , AccelerationStructureGeometryKHR - , AccelerationStructureBuildOffsetInfoKHR + , Vector AccelerationStructureBuildRangeInfoKHR ) biunitBoxGeometry = do let -- a bounding box for the unit sphere box = AabbPositionsKHR (-1) (-1) (-1) 1 1 1 (bufferKey, (buffer, bufferAllocation, _)) <- withBuffer' zero - { usage = BUFFER_USAGE_TRANSFER_SRC_BIT - .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - .|. BUFFER_USAGE_RAY_TRACING_BIT_KHR + { usage = + BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + .|. BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR , size = fromIntegral (sizeOf box) } zero @@ -308,27 +218,45 @@ biunitBoxGeometry = do , flags = GEOMETRY_OPAQUE_BIT_KHR , geometry = Aabbs boxData } - let offsetInfo = zero { primitiveCount = 1, primitiveOffset = 0 } + let offsetInfo = [zero { primitiveCount = 1, primitiveOffset = 0 }] pure (bufferKey, geom, offsetInfo) -createAndBindAccelerationMemory :: AccelerationStructureKHR -> V () -createAndBindAccelerationMemory as = do - MemoryRequirements2 () reqs <- getAccelerationStructureMemoryRequirementsKHR' - zero { type' = ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR - , buildType = ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR - , accelerationStructure = as - } - (releaseMem, (allocation, allocationInfo)) <- withMemory' - reqs - zero { usage = MEMORY_USAGE_GPU_ONLY - , requiredFlags = MEMORY_PROPERTY_DEVICE_LOCAL_BIT - } - let bindInfo :: BindAccelerationStructureMemoryInfoKHR - bindInfo = zero - { accelerationStructure = as - , memory = deviceMemory allocationInfo - , memoryOffset = offset (allocationInfo :: AllocationInfo) - } - bindAccelerationStructureMemoryKHR' [bindInfo] +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +-- TODO: use compute queue here +oneShotComputeCommands :: CmdT V () -> V () +oneShotComputeCommands cmds = do + -- + -- Create command buffers + -- + graphicsQueue <- getGraphicsQueue + QueueFamilyIndex graphicsQueueFamilyIndex <- getGraphicsQueueFamilyIndex + (poolKey, commandPool) <- withCommandPool' zero + { queueFamilyIndex = graphicsQueueFamilyIndex + } + ~[commandBuffer] <- allocateCommandBuffers' zero + { commandPool = commandPool + , level = COMMAND_BUFFER_LEVEL_PRIMARY + , commandBufferCount = 1 + } + + -- + -- Record and kick off the build commands + -- + useCommandBuffer' commandBuffer zero cmds + (fenceKey, fence) <- withFence' zero + queueSubmit + graphicsQueue + [SomeStruct zero { commandBuffers = [commandBufferHandle commandBuffer] }] + fence + let oneSecond = 1e9 + waitForFencesSafe' [fence] True oneSecond >>= \case + SUCCESS -> pure () + TIMEOUT -> error "Timed out running one shot commands" + _ -> error "Unhandled exit code in oneShotComputeCommands" + release fenceKey + release poolKey diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index 47653211c..ba5a31817 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -25,11 +25,12 @@ import qualified SDL.Video.Vulkan as SDL import Swapchain import Vulkan.CStruct.Extends import Vulkan.Core10 +import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore +import Vulkan.Extensions.VK_KHR_acceleration_structure import Vulkan.Extensions.VK_KHR_surface import Vulkan.Utils.QueueAssignment import Vulkan.Zero -import Vulkan.Extensions.VK_KHR_ray_tracing -- | Must be positive, duh numConcurrentFrames :: Int @@ -47,6 +48,7 @@ data Frame = Frame , fPipelineLayout :: PipelineLayout , fAccelerationStructure :: AccelerationStructureKHR , fShaderBindingTable :: Buffer + , fShaderBindingTableAddress :: DeviceAddress , fRenderFinishedHostSemaphore :: Semaphore -- ^ A timeline semaphore which increments to fIndex when this frame is -- done, the host can wait on this semaphore @@ -100,6 +102,9 @@ initialFrame fWindow fSurface = do (_, fPipeline, numGroups) <- Pipeline.createPipeline fPipelineLayout (_, fShaderBindingTable) <- Pipeline.createShaderBindingTable fPipeline numGroups + fShaderBindingTableAddress <- getBufferDeviceAddress' zero + { buffer = fShaderBindingTable + } descriptorSets <- Pipeline.createRTDescriptorSets descriptorSetLayout fAccelerationStructure @@ -149,6 +154,7 @@ advanceFrame needsNewSwapchain f = do , fPipeline = fPipeline f , fPipelineLayout = fPipelineLayout f , fShaderBindingTable = fShaderBindingTable f + , fShaderBindingTableAddress = fShaderBindingTableAddress f , fAccelerationStructure = fAccelerationStructure f , fRenderFinishedHostSemaphore = fRenderFinishedHostSemaphore f , fGPUWork diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index 37d175219..25b432d69 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -6,7 +6,9 @@ module Init , createCommandPools ) where -import Control.Monad ( unless ) +import Control.Monad ( unless + , when + ) import Control.Monad.IO.Class import Control.Monad.Trans.Maybe ( MaybeT(..) ) import Control.Monad.Trans.Resource @@ -42,6 +44,7 @@ import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address import Vulkan.Extensions.VK_EXT_descriptor_indexing ( pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME ) +import Vulkan.Extensions.VK_KHR_acceleration_structure import Vulkan.Extensions.VK_KHR_buffer_device_address ( pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME ) @@ -58,11 +61,12 @@ import Vulkan.Extensions.VK_KHR_maintenance3 import Vulkan.Extensions.VK_KHR_pipeline_library ( pattern KHR_PIPELINE_LIBRARY_EXTENSION_NAME ) -import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment +import Vulkan.Version ( pattern MAKE_VERSION ) import Vulkan.Zero import VulkanMemoryAllocator ( Allocator , AllocatorCreateFlagBits(..) @@ -91,7 +95,7 @@ createInstance win = do extensions = [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] <> windowExtensions - createDebugInstanceWithExtensions [] [] extensions [] createInfo + createInstanceWithExtensions [] [] extensions [] createInfo ---------------------------------------------------------------- -- Device creation @@ -119,11 +123,14 @@ createDevice inst win = do let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } ::& PhysicalDeviceTimelineSemaphoreFeatures True - :& zero { rayTracing = True } + :& zero { rayTracingPipeline = True } + :& (zero { accelerationStructure = True } :: PhysicalDeviceAccelerationStructureFeaturesKHR + ) :& zero { bufferDeviceAddress = True } :& () rayTracingExtensions = - [ KHR_RAY_TRACING_EXTENSION_NAME + [ KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME + , KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME , EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME @@ -157,7 +164,16 @@ pdiScore = pdiTotalMemory physicalDeviceInfo :: MonadIO m => SurfaceKHR -> PhysicalDevice -> m (Maybe PhysicalDeviceInfo) physicalDeviceInfo surf phys = runMaybeT $ do - deviceName <- physicalDeviceName phys + deviceName <- physicalDeviceName phys + deviceProps <- getPhysicalDeviceProperties phys + unless + ( apiVersion (deviceProps :: PhysicalDeviceProperties) + >= MAKE_VERSION 1 2 162 + ) + $ do + sayErr + "This application requires a device supporing at lease Vulkan 1.2.162" + empty hasTimelineSemaphores <- deviceHasTimelineSemaphores phys unless hasTimelineSemaphores $ do @@ -167,7 +183,15 @@ physicalDeviceInfo surf phys = runMaybeT $ do <> " because it doesn't support timeline semaphores" empty - pdiRTInfo <- deviceHasRayTracing phys + pdiRTInfo <- deviceHasRayTracingPipeline phys + + hasAccelerationStructureSupport <- deviceHasAccelerationStructure phys + unless hasAccelerationStructureSupport $ do + sayErr + $ "Not using physical device " + <> deviceName + <> " because it doesn't support acceleration structures" + empty hasSwapchainSupport <- deviceHasSwapchain phys unless hasSwapchainSupport $ do @@ -226,24 +250,44 @@ deviceHasTimelineSemaphores phys = do hasExt <&&> hasFeat -deviceHasRayTracing :: MonadIO m => PhysicalDevice -> MaybeT m RTInfo +deviceHasAccelerationStructure :: MonadIO m => PhysicalDevice -> m Bool + -- ^ Shader group size and alignment +deviceHasAccelerationStructure phys = do + let hasExt = do + (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing + pure $ V.any + ((KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME ==) . extensionName) + extensions + + hasFeat = do + feats <- getPhysicalDeviceFeatures2KHR phys + let _ ::& PhysicalDeviceAccelerationStructureFeaturesKHR {..} :& () = + feats + pure accelerationStructure + + hasExt <&&> hasFeat + +deviceHasRayTracingPipeline :: MonadIO m => PhysicalDevice -> MaybeT m RTInfo -- ^ Shader group size and alignment -deviceHasRayTracing phys = do +deviceHasRayTracingPipeline phys = do deviceName <- physicalDeviceName phys let hasExt = do (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing - pure $ V.any ((KHR_RAY_TRACING_EXTENSION_NAME ==) . extensionName) - extensions + pure $ V.any + ((KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME ==) . extensionName) + extensions hasFeat = do feats <- getPhysicalDeviceFeatures2KHR phys - let _ ::& PhysicalDeviceRayTracingFeaturesKHR {..} :& () = feats - pure rayTracing + let _ ::& PhysicalDeviceRayTracingPipelineFeaturesKHR {..} :& () = + feats + pure rayTracingPipeline getProps = do props <- getPhysicalDeviceProperties2KHR phys - let _ ::& PhysicalDeviceRayTracingPropertiesKHR {..} :& () = props + let _ ::& PhysicalDeviceRayTracingPipelinePropertiesKHR {..} :& () = + props pure RTInfo { rtiShaderGroupHandleSize = shaderGroupHandleSize , rtiShaderGroupBaseAlignment = shaderGroupBaseAlignment } @@ -255,7 +299,7 @@ deviceHasRayTracing phys = do sayErr $ "Not using physical device " <> deviceName - <> " because it doesn't support ray tracing" + <> " because it doesn't support ray tracing pipelines" empty ---------------------------------------------------------------- diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index 64bd85bd7..db1325a86 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -28,7 +28,6 @@ import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address ( getBufferDeviceAddress ) import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore as Timeline -import Vulkan.Extensions.VK_KHR_ray_tracing import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.CommandCheck @@ -36,6 +35,8 @@ import Vulkan.Utils.Debug ( nameObject ) import Vulkan.Utils.QueueAssignment import VulkanMemoryAllocator as VMA hiding ( getPhysicalDeviceProperties ) +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline +import Vulkan.Extensions.VK_KHR_acceleration_structure ---------------------------------------------------------------- -- Define the monad in which most of the program will run @@ -189,6 +190,9 @@ spawn_ = void . spawn noAllocationCallbacks :: Maybe AllocationCallbacks noAllocationCallbacks = Nothing +noPipelineCache :: PipelineCache +noPipelineCache = NULL_HANDLE + -- -- Wrap a bunch of Vulkan commands so that they automatically pull global -- handles from any `HasVulkan` instance. @@ -206,11 +210,10 @@ do [ 'acquireNextImageKHR , 'allocateCommandBuffers , 'allocateDescriptorSets - , 'bindAccelerationStructureMemoryKHR - , 'buildAccelerationStructureKHR + , 'buildAccelerationStructuresKHR , 'cmdBindDescriptorSets , 'cmdBindPipeline - , 'cmdBuildAccelerationStructureKHR + , 'cmdBuildAccelerationStructuresKHR , 'cmdDispatch , 'cmdDraw , 'cmdPipelineBarrier @@ -221,8 +224,8 @@ do , 'cmdUseRenderPass , 'deviceWaitIdle , 'deviceWaitIdleSafe + , 'getAccelerationStructureBuildSizesKHR , 'getAccelerationStructureDeviceAddressKHR - , 'getAccelerationStructureMemoryRequirementsKHR , 'getBufferDeviceAddress , 'getDeviceQueue , 'getPhysicalDeviceSurfaceCapabilitiesKHR @@ -263,6 +266,7 @@ do , 'getInstance , 'getAllocator , 'noAllocationCallbacks + , 'noPipelineCache , 'getCommandBuffer ] -- Allocate doesn't subsume the continuation type on the "with" commands, so diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 1fa0bd96b..722a95e95 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -14,7 +14,9 @@ module Pipeline import Control.Monad.IO.Class import Control.Monad.Trans.Resource import Data.Bits -import Data.Foldable (for_, traverse_ ) +import Data.Foldable ( for_ + , traverse_ + ) import qualified Data.Vector as V import Data.Vector ( Vector ) import Data.Word @@ -24,16 +26,17 @@ import Foreign.Ptr ( Ptr , plusPtr ) import MonadVulkan +import Say import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) -import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Extensions.VK_KHR_acceleration_structure +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Utils.ShaderQQ import Vulkan.Zero import VulkanMemoryAllocator -import Say -- Create the most vanilla ray tracing pipeline, returns the number of shader -- groups @@ -70,10 +73,11 @@ createPipeline pipelineLayout = do shaderGroups = [genGroup, intGroup, missGroup] let pipelineCreateInfo :: RayTracingPipelineCreateInfoKHR '[] - pipelineCreateInfo = zero { stages = shaderStages - , groups = shaderGroups - , maxRecursionDepth = 1 - , layout = pipelineLayout + pipelineCreateInfo = zero { flags = zero + , stages = shaderStages + , groups = shaderGroups + , maxPipelineRayRecursionDepth = 1 + , layout = pipelineLayout } (key, (_, ~[rtPipeline])) <- withRayTracingPipelinesKHR' zero @@ -276,7 +280,7 @@ createShaderBindingTable pipeline numGroups = do (bufferReleaseKey, (sbtBuffer, sbtAllocation, _sbtAllocationInfo)) <- withBuffer' - zero { usage = BUFFER_USAGE_RAY_TRACING_BIT_KHR, size = sbtSize } + zero { usage = BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, size = sbtSize } zero { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT .|. MEMORY_PROPERTY_HOST_COHERENT_BIT diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 9043f5985..84f5b148e 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -20,7 +20,7 @@ import UnliftIO.Exception ( throwString ) import Vulkan.CStruct.Extends import Vulkan.Core10 as Core10 import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore -import Vulkan.Extensions.VK_KHR_ray_tracing +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Extensions.VK_KHR_swapchain as Swap import Vulkan.Zero @@ -115,42 +115,41 @@ myRecordCommandBuffer :: Frame -> Word32 -> CmdT F () myRecordCommandBuffer Frame {..} imageIndex = do -- TODO: neaten RTInfo {..} <- CmdT . lift . liftV $ getRTInfo - let - RecycledResources {..} = fRecycledResources - SwapchainResources {..} = fSwapchainResources - SwapchainInfo {..} = srInfo - image = srImages ! fromIntegral imageIndex - imageWidth = width (siImageExtent :: Extent2D) - imageHeight = height (siImageExtent :: Extent2D) - imageSubresourceRange = ImageSubresourceRange - { aspectMask = IMAGE_ASPECT_COLOR_BIT - , baseMipLevel = 0 - , levelCount = 1 - , baseArrayLayer = 0 - , layerCount = 1 - } - numRayGenShaderGroups = 1 - rayGenRegion = StridedBufferRegionKHR - { buffer = fShaderBindingTable - , offset = 0 - , stride = fromIntegral rtiShaderGroupBaseAlignment - , size = fromIntegral rtiShaderGroupBaseAlignment * numRayGenShaderGroups - } - numHitShaderGroups = 1 - hitRegion = StridedBufferRegionKHR - { buffer = fShaderBindingTable - , offset = 1 * fromIntegral rtiShaderGroupBaseAlignment - , stride = fromIntegral rtiShaderGroupBaseAlignment - , size = fromIntegral rtiShaderGroupBaseAlignment * numHitShaderGroups - } - numMissShaderGroups = 1 - missRegion = StridedBufferRegionKHR - { buffer = fShaderBindingTable - , offset = 2 * fromIntegral rtiShaderGroupBaseAlignment - , stride = fromIntegral rtiShaderGroupBaseAlignment - , size = fromIntegral rtiShaderGroupBaseAlignment * numMissShaderGroups - } - callableRegion = zero + let RecycledResources {..} = fRecycledResources + SwapchainResources {..} = fSwapchainResources + SwapchainInfo {..} = srInfo + image = srImages ! fromIntegral imageIndex + imageWidth = width (siImageExtent :: Extent2D) + imageHeight = height (siImageExtent :: Extent2D) + imageSubresourceRange = ImageSubresourceRange + { aspectMask = IMAGE_ASPECT_COLOR_BIT + , baseMipLevel = 0 + , levelCount = 1 + , baseArrayLayer = 0 + , layerCount = 1 + } + numRayGenShaderGroups = 1 + rayGenRegion = StridedDeviceAddressRegionKHR + { deviceAddress = fShaderBindingTableAddress + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment + * numRayGenShaderGroups + } + numHitShaderGroups = 1 + hitRegion = StridedDeviceAddressRegionKHR + { deviceAddress = fShaderBindingTableAddress + + (1 * fromIntegral rtiShaderGroupBaseAlignment) + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment * numHitShaderGroups + } + numMissShaderGroups = 1 + missRegion = StridedDeviceAddressRegionKHR + { deviceAddress = fShaderBindingTableAddress + + (2 * fromIntegral rtiShaderGroupBaseAlignment) + , stride = fromIntegral rtiShaderGroupBaseAlignment + , size = fromIntegral rtiShaderGroupBaseAlignment * numMissShaderGroups + } + callableRegion = zero do -- Transition image to general, to write from the ray tracing shader cmdPipelineBarrier' From cdcf05367ce81de55bedff5ec527a2b8ab1799b8 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Tue, 24 Nov 2020 18:56:16 +0800 Subject: [PATCH 27/70] bounds for rays example --- examples/package.yaml | 4 ++-- examples/vulkan-examples.cabal | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/package.yaml b/examples/package.yaml index 0044a817c..332084176 100644 --- a/examples/package.yaml +++ b/examples/package.yaml @@ -162,8 +162,8 @@ executables: - unagi-chan - unliftio - vector - - vulkan - - vulkan-utils + - vulkan >= 3.7 + - vulkan-utils >= 0.3 - file-embed - extra - filepath diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index cfdfe7215..ac76ce00d 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -4,7 +4,7 @@ cabal-version: 2.2 -- -- see: https://github.com/sol/hpack -- --- hash: 8160fb6fed8915e2c12af69faf0370f418c57bd3969f3086e1ec1911c86d0047 +-- hash: c051f4aea0c23de2816e028f1846fa45d3e3688d483c5c0c9e59f68ae8e064c0 name: vulkan-examples version: 0.1.0.0 @@ -203,8 +203,8 @@ executable rays , unagi-chan , unliftio , vector - , vulkan - , vulkan-utils + , vulkan >=3.7 + , vulkan-utils >=0.3 if os(windows) ghc-options: -optl-mconsole if impl(ghc < 8.10.0) From 2bcc55b8a1ac8f2964d5b0b817f73de1e30e3cef Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Wed, 25 Nov 2020 17:46:48 +0800 Subject: [PATCH 28/70] Remove hpack hash --- examples/vulkan-examples.cabal | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index ac76ce00d..b90664b9d 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -3,8 +3,6 @@ cabal-version: 2.2 -- This file has been generated from package.yaml by hpack version 0.34.2. -- -- see: https://github.com/sol/hpack --- --- hash: c051f4aea0c23de2816e028f1846fa45d3e3688d483c5c0c9e59f68ae8e064c0 name: vulkan-examples version: 0.1.0.0 From 58f050e3177568110ef0059a9b8153552c00e240 Mon Sep 17 00:00:00 2001 From: sheaf Date: Wed, 25 Nov 2020 19:57:09 +0100 Subject: [PATCH 29/70] Functionality for handling requirements --- src-manual/Vulkan/Requirements.hs | 504 ++++++++++++++++------- utils/package.yaml | 4 +- utils/src/Vulkan/Utils/Initialization.hs | 386 +++++++++++------ utils/src/Vulkan/Utils/Internal.hs | 21 + utils/src/Vulkan/Utils/Misc.hs | 19 +- 5 files changed, 648 insertions(+), 286 deletions(-) create mode 100644 utils/src/Vulkan/Utils/Internal.hs diff --git a/src-manual/Vulkan/Requirements.hs b/src-manual/Vulkan/Requirements.hs index aa52379a7..1a02a0df5 100644 --- a/src-manual/Vulkan/Requirements.hs +++ b/src-manual/Vulkan/Requirements.hs @@ -1,4 +1,6 @@ {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} @@ -10,17 +12,34 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE Strict #-} {-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} -module Vulkan.Requirements where +module Vulkan.Requirements + ( -- * Vulkan requirements + Requirement(..) + + -- * Requesting certain requirements + , Request(Require,Option,..) + , Requests(..), ReqAndOpt(..), KnownRequestTarget(..) + , addRequests, mkRequests + + -- * Utility functionality for handling structure chains + , SLength(..), KnownChain(..) -- TODO: move to Vulkan.CStruct.Extends + ) + where -- base +import Control.Applicative + ( liftA2 ) import Control.Arrow ( Arrow(first,second,(***)) ) +import Control.Monad + ( unless ) import Data.Foldable - ( foldr' ) + ( foldl' ) import Data.Kind ( Type ) import Data.Type.Equality @@ -36,19 +55,34 @@ import GHC.Exts import Data.ByteString ( ByteString ) +-- transformers +import Control.Monad.IO.Class + ( MonadIO ) + -- unordered-containers import Data.HashMap.Strict ( HashMap ) import qualified Data.HashMap.Strict as HashMap - ( empty, insertWith, singleton, unionWith ) + ( elems, empty, insertWith, keys, singleton, unionWith ) import Data.HashSet ( HashSet ) import qualified Data.HashSet as HashSet - ( empty, insert ) + ( empty, insert, member, null ) + +-- vector +import qualified Data.Vector as Boxed + ( Vector ) +import qualified Data.Vector as Boxed.Vector + ( fromList ) -- vulkan +import Vulkan.Core10.Device + ( Device, DeviceCreateInfo(..), DeviceQueueCreateInfo + ) import Vulkan.Core10.DeviceInitialization - ( InstanceCreateInfo, PhysicalDeviceFeatures, PhysicalDeviceProperties ) + ( AllocationCallbacks, ApplicationInfo(..), Instance, InstanceCreateInfo(..) + , PhysicalDevice, PhysicalDeviceFeatures, PhysicalDeviceProperties + ) import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 ( PhysicalDeviceFeatures2(..) ) import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 @@ -56,47 +90,54 @@ import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 import Vulkan.CStruct ( FromCStruct, ToCStruct ) import Vulkan.CStruct.Extends - ( Chain, PeekChain, PokeChain, Extends, Extendss ) + ( Chain, Extends, Extendss, PeekChain, PokeChain, SomeStruct(..) ) import Vulkan.Version ( pattern MAKE_VERSION ) import Vulkan.Zero ( Zero(zero) ) ---------------------------------------------------------------------------- +-- Vulkan requirements. --- | A Vulkan requirement. -data Requirement where - -- | Require a minimum Vulkan API version. - RequireVersion +-- | A Vulkan requirement, such as an 'Instance' layer or a 'PhysicalDevice' feature. +data family Requirement (t :: Type) +-- | A requirement on a Vulkan 'Instance'. +data instance Requirement Instance where + -- | Require a minimum Vulkan instance version. + RequireInstanceVersion :: { version :: Word32 } - -> Requirement + -> Requirement Instance -- | Require a Vulkan layer. RequireInstanceLayer :: { instanceLayerName :: ByteString , instanceLayerMinVersion :: Word32 + -- | Specifying order in which to enable a layer. + -- Lower order: enabled first. + , instanceLayerOrder :: Int } - -> Requirement + -> Requirement Instance + -- | Require a Vulkan instance setting (e.g. a validation feature). + RequireInstanceSetting + :: forall struct + . KnownInstanceSettingStruct struct + => { -- | Specify a Vulkan structure that extends 'InstanceCreateInfo'. + instanceSetting :: struct + } + -> Requirement Instance -- | Require a Vulkan instance extension. RequireInstanceExtension :: { instanceExtensionLayerName :: Maybe ByteString , instanceExtensionName :: ByteString , instanceExtensionMinVersion :: Word32 } - -> Requirement - -- | Require a Vulkan device extension. - RequireDeviceExtension - :: { deviceExtensionLayerName :: Maybe ByteString - , deviceExtensionName :: ByteString - , deviceExtensionMinVersion :: Word32 - } - -> Requirement - -- | Require a Vulkan instance setting (e.g. enable or disable a validation feature). - RequireInstanceSetting - :: forall struct - . KnownInstanceSettingStruct struct - => { setInstanceSetting :: struct -> struct } - -> Requirement - -- | Require a Vulkan device feature. + -> Requirement Instance +-- A requirement on a Vulkan 'PhysicalDevice'. +data instance Requirement PhysicalDevice where + -- | Require a minimum device version. + RequireDeviceVersion + :: { version :: Word32 } + -> Requirement PhysicalDevice + -- | Require a Vulkan physical device feature. RequireFeature :: forall struct . KnownFeatureStruct struct @@ -104,15 +145,22 @@ data Requirement where , checkFeature :: struct -> Bool , enableFeature :: struct -> struct } - -> Requirement - -- | Require a Vulkan device property. + -> Requirement PhysicalDevice + -- | Require a Vulkan physical device property. RequireProperty :: forall struct . KnownPropertyStruct struct => { propertyName :: ByteString , checkProperty :: struct -> Bool } - -> Requirement + -> Requirement PhysicalDevice + -- | Require a Vulkan device extension. + RequireDeviceExtension + :: { deviceExtensionLayerName :: Maybe ByteString + , deviceExtensionName :: ByteString + , deviceExtensionMinVersion :: Word32 + } + -> Requirement PhysicalDevice -- | A Vulkan structure that can appear in 'InstanceCreateInfo'. class ( Typeable sett, Extends InstanceCreateInfo sett, Zero sett, FromCStruct sett, ToCStruct sett ) @@ -127,7 +175,10 @@ data SFeatureStruct feat where BasicFeatureStruct :: SFeatureStruct PhysicalDeviceFeatures ExtendedFeatureStruct - :: ( Typeable feat, Extends PhysicalDeviceFeatures2 feat, Zero feat, FromCStruct feat, ToCStruct feat ) + :: ( Typeable feat + , Extends PhysicalDeviceFeatures2 feat, Extends DeviceCreateInfo feat + , Zero feat, FromCStruct feat, ToCStruct feat + ) => SFeatureStruct feat -- | A Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. class KnownFeatureStruct feat where @@ -135,7 +186,10 @@ class KnownFeatureStruct feat where instance KnownFeatureStruct PhysicalDeviceFeatures where sFeatureStruct = BasicFeatureStruct instance {-# OVERLAPPABLE #-} - ( Typeable feat, Extends PhysicalDeviceFeatures2 feat, Zero feat, FromCStruct feat, ToCStruct feat ) + ( Typeable feat + , Extends PhysicalDeviceFeatures2 feat, Extends DeviceCreateInfo feat + , Zero feat, FromCStruct feat, ToCStruct feat + ) => KnownFeatureStruct feat where sFeatureStruct = ExtendedFeatureStruct @@ -158,188 +212,328 @@ instance {-# OVERLAPPABLE #-} => KnownPropertyStruct prop where sPropertyStruct = ExtendedPropertyStruct +-- | Singleton allowing inspection of the length of a list. +data SLength (xs :: [Type]) where + SNil :: SLength '[] + SCons :: SLength xs -> SLength (x ': xs) -- | Enough information to focus on any structure within a Vulkan structure chain. class (PeekChain xs, PokeChain xs) => KnownChain (xs :: [Type]) where + sLength :: SLength xs -- | If the given structure can be found within a chain, return a lens to it. -- Otherwise, return 'Nothing'. has :: forall a. Typeable a => Proxy# a -> Maybe (Chain xs -> a, (a -> a) -> (Chain xs -> Chain xs)) instance KnownChain '[] where + sLength = SNil has _ = Nothing instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain (x ': xs) where + sLength = SCons (sLength @xs) has (px :: Proxy# a) | Just Refl <- eqT @a @x = Just (fst,first) | otherwise = ((. snd) *** (second .)) <$> has px -data LayerName - = BaseLayer - | LayerName ByteString +---------------------------------------------------------------------------- +-- Requesting certain requirements. + +-- | Request a Vulkan feature/extension/layer to be enabled (possibly optionally). +data Request t = Request { request :: Requirement t, requestIsOptional :: Bool } --- | A collection of Vulkan requirements. +{-# COMPLETE Require, Option #-} +pattern Require, Option :: Requirement t -> Request t +pattern Require en = Request en False +pattern Option en = Request en True + +-- | Keep track of required and optional terms of a given type. +data ReqAndOpt a = + ReqAndOpt + { req :: a + , opt :: a + } + deriving stock ( Show, Functor, Foldable, Traversable ) +instance Applicative ReqAndOpt where + pure a = ReqAndOpt a a + ReqAndOpt f g <*> ReqAndOpt a b = ReqAndOpt (f a) (g b) + +-- | A collection of requests, which pertain either to an 'Instance' or to a 'PhysicalDevice'. +data family Requests (t :: Type) +-- | A collection of requests on a Vulkan 'Instance'. -- --- Parameterised over the structure chains used by 'PhysicalDeviceFeatures2' and 'PhysicalDeviceProperties2'. -data Requirements where - Requirements - :: forall setts feats props - . ( KnownChain setts, Extendss InstanceCreateInfo setts - , KnownChain feats, Extendss PhysicalDeviceFeatures2 feats +-- Parameterised over the structure chain used in 'InstanceCreateInfo'. +data instance Requests Instance where + InstanceRequests + :: forall setts + . ( KnownChain setts, Extendss InstanceCreateInfo setts ) + => { + -- | Required and optional minimum Vulkan instance version. + version :: ReqAndOpt Word32 + -- | Required and optional Vulkan layer names and their minimum versions. + -- Each instance layer has an ordering value which defines the order in which layers should be enabled. + -- Lower value: enabled first. + , instanceLayers :: ReqAndOpt (HashMap ByteString (Int,Word32)) + -- | Required and optional Vulkan instance extension names and their minimum versions, + -- collected by the Vulkan layer name they come from. + , instanceExtensions :: HashMap (Maybe ByteString) (ReqAndOpt (HashMap ByteString Word32)) + -- | Required Vulkan instance settings ('InstanceCreateInfo' structure extension chain). + , enableSettings :: Chain setts + } + -> Requests Instance +-- | A collection of requests on a Vulkan 'PhysicalDevice' +-- +-- Parameterised over the structure chains used by 'PhysicalDeviceFeatures2'/'DeviceCreateInfo' and 'PhysicalDeviceProperties2'. +data instance Requests PhysicalDevice where + PhysicalDeviceRequests + :: forall feats props + . ( KnownChain feats, Extendss PhysicalDeviceFeatures2 feats, Extendss DeviceCreateInfo feats , KnownChain props, Extendss PhysicalDeviceProperties2 props ) => { - -- | Minimum Vulkan API version required. - version :: Word32 - -- | Required Vulkan layer names and their minimum versions. - , instanceLayers :: HashMap ByteString Word32 - -- | Required Vulkan instance extension names and their minimum versions, - -- collected by the Vulkan layer name they come from. - , instanceExtensions :: HashMap (Maybe ByteString) (HashMap ByteString Word32) - -- | Required Vulkan device extension names and their minimum versions, + -- | Required and optional minimum device version. + version :: ReqAndOpt Word32 + -- | Required and optional Vulkan device extension names and their minimum versions, -- collected by the Vulkan layer name they come from. - , deviceExtensions :: HashMap (Maybe ByteString) (HashMap ByteString Word32) - -- | Required Vulkan instance settings ('InstanceCreateInfo' structure extension chain). - , neededSettings :: Chain setts - -- | Returns all the required features that were not enabled in 'PhysicalDeviceFeatures2'. - , missingFeatures :: PhysicalDeviceFeatures2 feats -> HashSet ByteString + , deviceExtensions :: HashMap (Maybe ByteString) (ReqAndOpt (HashMap ByteString Word32)) + -- | Returns all the required and optional features that were not enabled in 'PhysicalDeviceFeatures2'. + , missingFeatures :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) -- | All required features, to be used in 'DeviceCreateInfo'. - , neededFeatures :: PhysicalDeviceFeatures2 feats - -- | Returns all the required properties that were not satisfied in 'PhysicalDeviceProperties2' - , missingProperties :: PhysicalDeviceProperties2 props -> HashSet ByteString + -- + -- Argument: optional features that should __not__ be enabled. + -- These must be the missing optional features returned by 'missingFeatures'. + , enableFeaturesOtherThan :: HashSet ByteString -> PhysicalDeviceFeatures2 feats + -- | Returns all the required and optional properties that were not satisfied in 'PhysicalDeviceProperties2' + , missingProperties :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) } - -> Requirements + -> Requests PhysicalDevice --- | Collect up requirements. -requirements :: Foldable f => f Requirement -> Requirements -requirements = foldr' addRequirement noRequire +class KnownRequestTarget (t :: Type) where + -- | Make no requests. + noRequests :: Requests t + -- | Specify a single request. + addRequest :: Request t -> Requests t -> Requests t +instance KnownRequestTarget Instance where + noRequests = + InstanceRequests @'[] + (ReqAndOpt (MAKE_VERSION 1 0 0) (MAKE_VERSION 1 0 0)) + (ReqAndOpt HashMap.empty HashMap.empty) + HashMap.empty + () + addRequest (Request req isOptional) = case req of + RequireInstanceVersion {..} + -> requestInstanceVersion isOptional version + RequireInstanceLayer {..} + -> requestInstanceLayer isOptional instanceLayerName instanceLayerOrder instanceLayerMinVersion + RequireInstanceSetting {..} + -> requestInstanceSetting isOptional instanceSetting + RequireInstanceExtension {..} + -> requestInstanceExtension isOptional instanceExtensionLayerName instanceExtensionName instanceExtensionMinVersion + +instance KnownRequestTarget PhysicalDevice where + noRequests = + PhysicalDeviceRequests @'[] @'[] + (ReqAndOpt (MAKE_VERSION 1 0 0) (MAKE_VERSION 1 0 0)) + HashMap.empty + (const $ ReqAndOpt HashSet.empty HashSet.empty) + (const zero) + (const $ ReqAndOpt HashSet.empty HashSet.empty) + addRequest (Request req isOptional) = case req of + RequireDeviceVersion {..} + -> requestDeviceVersion isOptional version + RequireDeviceExtension {..} + -> requestDeviceExtension isOptional deviceExtensionLayerName deviceExtensionName deviceExtensionMinVersion + RequireFeature {..} + -> requestFeature isOptional featureName checkFeature enableFeature + RequireProperty {..} + -> requestProperty isOptional propertyName checkProperty + +-- | Add a single request to a collection of requests. +addRequests + :: forall f t + . (Foldable f, KnownRequestTarget t) + => Requests t -> f (Request t) -> Requests t +addRequests = foldl' (flip $ addRequest @t) + +-- | Collect up requests. +mkRequests + :: forall f t + . (Foldable f, KnownRequestTarget t) + => f (Request t) -> Requests t +mkRequests = addRequests @f @t (noRequests @t) + +requestInstanceVersion :: Bool -> Word32 -> Requests Instance -> Requests Instance +requestInstanceVersion isOptional ver req@(InstanceRequests{version = ReqAndOpt reqVer optVer}) + | isOptional + = req {version = ReqAndOpt reqVer (max ver optVer)} + | otherwise + = req {version = ReqAndOpt (max ver reqVer) optVer} + +requestDeviceVersion :: Bool -> Word32 -> Requests PhysicalDevice -> Requests PhysicalDevice +requestDeviceVersion isOptional ver req@(PhysicalDeviceRequests{version = ReqAndOpt reqVer optVer}) + | isOptional + = req {version = ReqAndOpt reqVer (max ver optVer)} + | otherwise + = req {version = ReqAndOpt (max ver reqVer) optVer} + +requestInstanceLayer :: Bool -> ByteString -> Int -> Word32 -> Requests Instance -> Requests Instance +requestInstanceLayer isOptional layName layOrder layVer req@(InstanceRequests{instanceLayers = ReqAndOpt reqLays optLays}) + | isOptional + = req {instanceLayers = ReqAndOpt reqLays (HashMap.insertWith minMax layName (layOrder,layVer) optLays)} + | otherwise + = req {instanceLayers = ReqAndOpt (HashMap.insertWith minMax layName (layOrder,layVer) reqLays) optLays} where - noRequire :: Requirements - noRequire = - Requirements @'[] @'[] @'[] - (MAKE_VERSION 1 0 0) - HashMap.empty HashMap.empty HashMap.empty - () - (const HashSet.empty) zero (const HashSet.empty) - addRequirement :: Requirement -> Requirements -> Requirements - addRequirement (RequireVersion {..}) = - requireVersion version - addRequirement (RequireInstanceLayer {..}) = - requireInstanceLayer instanceLayerName instanceLayerMinVersion - addRequirement (RequireInstanceExtension {..}) = - requireInstanceExtension instanceExtensionLayerName instanceExtensionName instanceExtensionMinVersion - addRequirement (RequireDeviceExtension {..}) = - requireDeviceExtension deviceExtensionLayerName deviceExtensionName deviceExtensionMinVersion - addRequirement (RequireInstanceSetting {..}) = - requireInstanceSetting setInstanceSetting - addRequirement (RequireFeature {..}) = - requireFeature featureName checkFeature enableFeature - addRequirement (RequireProperty {..}) = - requireProperty propertyName checkProperty - - -requireVersion :: Word32 -> Requirements -> Requirements -requireVersion ver1 req@(Requirements{version = ver2}) = - req {version = max ver1 ver2} - -requireInstanceLayer :: ByteString -> Word32-> Requirements -> Requirements -requireInstanceLayer layName layVer req@(Requirements{instanceLayers = lays}) = - req {instanceLayers = HashMap.insertWith max layName layVer lays} - -requireInstanceExtension :: Maybe ByteString -> ByteString -> Word32 -> Requirements -> Requirements -requireInstanceExtension mbLayName extName extVer req@(Requirements{instanceExtensions = exts}) = - (case mbLayName of { Just layName -> requireInstanceLayer layName 0; Nothing -> id }) $ - req {instanceExtensions = HashMap.insertWith (HashMap.unionWith max) mbLayName (HashMap.singleton extName extVer) exts} - -requireDeviceExtension :: Maybe ByteString -> ByteString -> Word32 -> Requirements -> Requirements -requireDeviceExtension mbLayName extName extVer req@(Requirements{deviceExtensions = exts}) = - (case mbLayName of { Just layName -> requireInstanceLayer layName 0; Nothing -> id }) $ - req {deviceExtensions = HashMap.insertWith (HashMap.unionWith max) mbLayName (HashMap.singleton extName extVer) exts} - -requireInstanceSetting :: forall struct - . ( KnownInstanceSettingStruct struct ) - => (struct -> struct) -> Requirements -> Requirements -requireInstanceSetting setSetting - ( Requirements ver lays instExts devExts + minMax :: (Int, Word32) -> (Int, Word32) -> (Int, Word32) + minMax (o1,v1) (o2,v2) = (min o1 o2, max v1 v2) + +requestInstanceExtension :: Bool -> Maybe ByteString -> ByteString -> Word32 -> Requests Instance -> Requests Instance +requestInstanceExtension isOptional mbLayName extName extVer req@(InstanceRequests{instanceExtensions = exts}) + | isOptional + = req + { instanceExtensions = + HashMap.insertWith (liftA2 $ HashMap.unionWith max) + mbLayName + (ReqAndOpt (HashMap.singleton extName extVer) HashMap.empty) + exts + } + | otherwise + = req + { instanceExtensions = + HashMap.insertWith (liftA2 $ HashMap.unionWith max) + mbLayName + (ReqAndOpt HashMap.empty (HashMap.singleton extName extVer)) + exts + } + +requestDeviceExtension :: Bool -> Maybe ByteString -> ByteString -> Word32 -> Requests PhysicalDevice -> Requests PhysicalDevice +requestDeviceExtension isOptional mbLayName extName extVer req@(PhysicalDeviceRequests{deviceExtensions = exts}) + | isOptional + = req + { deviceExtensions = + HashMap.insertWith (liftA2 $ HashMap.unionWith max) + mbLayName + (ReqAndOpt (HashMap.singleton extName extVer) HashMap.empty) + exts + } + | otherwise + = req + { deviceExtensions = + HashMap.insertWith (liftA2 $ HashMap.unionWith max) + mbLayName + (ReqAndOpt HashMap.empty (HashMap.singleton extName extVer)) + exts + } + +requestInstanceSetting + :: forall struct + . ( KnownInstanceSettingStruct struct ) + => Bool -> struct -> Requests Instance -> Requests Instance +requestInstanceSetting _isOptional setting + ( InstanceRequests ver lays instExts (setts :: Chain setts) - missingFeats enabledFeats missingProps ) = case has @setts @struct proxy# of + -- TODO: throw a warning when a setting is set twice. Just (_, modifySettingStruct) | let setts' :: Chain setts - setts' = modifySettingStruct setSetting setts - -> Requirements ver lays instExts devExts setts' missingFeats enabledFeats missingProps - Nothing + setts' = modifySettingStruct (const setting) setts + -> InstanceRequests ver lays instExts setts' + Nothing | let setts' :: Chain (struct ': setts) - setts' = (setSetting zero, setts) - -> Requirements ver lays instExts devExts setts' missingFeats enabledFeats missingProps - -requireFeature :: forall struct - . ( KnownFeatureStruct struct ) - => ByteString -> (struct -> Bool) -> (struct -> struct) -> Requirements -> Requirements -requireFeature featName checkFeat enableFeat - ( Requirements ver lays instExts devExts setts - (missingFeats :: PhysicalDeviceFeatures2 feats -> HashSet ByteString) - enabledFeats@(PhysicalDeviceFeatures2{next=nextEnabledFeats,features=prevEnabledFeats}) + setts' = (setting, setts) + -> InstanceRequests ver lays instExts setts' + +requestFeature + :: forall struct + . ( KnownFeatureStruct struct ) + => Bool -> ByteString -> (struct -> Bool) -> (struct -> struct) -> Requests PhysicalDevice -> Requests PhysicalDevice +requestFeature isOptional featName checkFeat enableFeat + ( PhysicalDeviceRequests ver devExts + (missingFeats :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString)) + enableFeats missingProps ) = case sFeatureStruct @struct of BasicFeatureStruct -> let - missingFeats' :: PhysicalDeviceFeatures2 feats -> HashSet ByteString + missingFeats' :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) missingFeats' feats2@(PhysicalDeviceFeatures2{features}) = - (if checkFeat features then id else HashSet.insert featName) + insertReqOptUnless (checkFeat features) featName isOptional (missingFeats feats2) - enabledFeats' :: PhysicalDeviceFeatures2 feats - enabledFeats' = enabledFeats { features = enableFeat prevEnabledFeats } - in Requirements ver lays instExts devExts setts missingFeats' enabledFeats' missingProps + enabledFeats' :: HashSet ByteString -> PhysicalDeviceFeatures2 feats + enabledFeats' don'tEnable + | isOptional && featName `HashSet.member` don'tEnable + = enableFeats don'tEnable + | enabled@(PhysicalDeviceFeatures2{features=prevEnabledFeats}) + <- enableFeats don'tEnable + = enabled { features = enableFeat prevEnabledFeats } + in PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps ExtendedFeatureStruct | Just (getFeatureStruct, modifyFeatureStruct) <- has @feats @struct proxy# , let - missingFeats' :: PhysicalDeviceFeatures2 feats -> HashSet ByteString + missingFeats' :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) missingFeats' feats2@(PhysicalDeviceFeatures2{next}) = - (if checkFeat (getFeatureStruct next) then id else HashSet.insert featName) + insertReqOptUnless (checkFeat (getFeatureStruct next)) featName isOptional (missingFeats feats2) - enabledFeats' :: PhysicalDeviceFeatures2 feats - enabledFeats' = enabledFeats { next = modifyFeatureStruct enableFeat nextEnabledFeats } - -> Requirements ver lays instExts devExts setts missingFeats' enabledFeats' missingProps + enabledFeats' :: HashSet ByteString -> PhysicalDeviceFeatures2 feats + enabledFeats' don'tEnable + | isOptional && featName `HashSet.member` don'tEnable + = enableFeats don'tEnable + | enabled@(PhysicalDeviceFeatures2{next=nextEnabledFeats}) + <- enableFeats don'tEnable + = enabled { next = modifyFeatureStruct enableFeat nextEnabledFeats } + -> PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps | let - missingFeats' :: PhysicalDeviceFeatures2 (struct ': feats) -> HashSet ByteString + missingFeats' :: PhysicalDeviceFeatures2 (struct ': feats) -> ReqAndOpt (HashSet ByteString) missingFeats' feats2@(PhysicalDeviceFeatures2{next=(struct,feats)}) = - (if checkFeat struct then id else HashSet.insert featName) + insertReqOptUnless (checkFeat struct) featName isOptional (missingFeats (feats2{next=feats})) - enabledFeats' :: PhysicalDeviceFeatures2 (struct ': feats) - enabledFeats' = enabledFeats { next = (enableFeat zero, nextEnabledFeats) } - -> Requirements ver lays instExts devExts setts missingFeats' enabledFeats' missingProps - -requireProperty :: forall struct - . ( KnownPropertyStruct struct ) - => ByteString -> (struct -> Bool) -> Requirements -> Requirements -requireProperty propName checkProp - ( Requirements ver lays instExts devExts setts missingFeats enabledFeats - (missingProps :: PhysicalDeviceProperties2 props -> HashSet ByteString) + enabledFeats' :: HashSet ByteString -> PhysicalDeviceFeatures2 (struct ': feats) + enabledFeats' don'tEnable + | let + struct :: struct + struct + | isOptional && featName `HashSet.member` don'tEnable + = zero + | otherwise + = enableFeat zero + , enabled@(PhysicalDeviceFeatures2{next=nextEnabledFeats}) + <- enableFeats don'tEnable + = enabled { next = (struct, nextEnabledFeats) } + -> PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps + +requestProperty + :: forall struct + . ( KnownPropertyStruct struct ) + => Bool -> ByteString -> (struct -> Bool) -> Requests PhysicalDevice -> Requests PhysicalDevice +requestProperty isOptional propName checkProp + ( PhysicalDeviceRequests ver devExts missingFeats enabledFeats + (missingProps :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString)) ) = case sPropertyStruct @struct of BasicPropertyStruct -> let - missingProps' :: PhysicalDeviceProperties2 props -> HashSet ByteString + missingProps' :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) missingProps' props2@(PhysicalDeviceProperties2{properties}) = - (if checkProp properties then id else HashSet.insert propName) + insertReqOptUnless (checkProp properties) propName isOptional (missingProps props2) - in Requirements ver lays instExts devExts setts missingFeats enabledFeats missingProps' - + in PhysicalDeviceRequests ver devExts missingFeats enabledFeats missingProps' ExtendedPropertyStruct | Just (getPropertyStruct,_) <- has @props @struct proxy# , let - missingProps' :: PhysicalDeviceProperties2 props -> HashSet ByteString + missingProps' :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) missingProps' props2@(PhysicalDeviceProperties2{next}) = - (if checkProp (getPropertyStruct next) then id else HashSet.insert propName) + insertReqOptUnless (checkProp (getPropertyStruct next)) propName isOptional (missingProps props2) - -> Requirements ver lays instExts devExts setts missingFeats enabledFeats missingProps' + -> PhysicalDeviceRequests ver devExts missingFeats enabledFeats missingProps' | let - missingProps' :: PhysicalDeviceProperties2 (struct ': props) -> HashSet ByteString + missingProps' :: PhysicalDeviceProperties2 (struct ': props) -> ReqAndOpt (HashSet ByteString) missingProps' props2@(PhysicalDeviceProperties2{next=(struct,props)}) = - (if checkProp struct then id else HashSet.insert propName) + insertReqOptUnless (checkProp struct) propName isOptional (missingProps (props2{next=props})) - -> Requirements ver lays instExts devExts setts missingFeats enabledFeats missingProps' + -> PhysicalDeviceRequests ver devExts missingFeats enabledFeats missingProps' + +insertReqOptUnless :: Bool -> ByteString -> Bool -> ReqAndOpt (HashSet ByteString) -> ReqAndOpt (HashSet ByteString) +insertReqOptUnless True _ _ = id +insertReqOptUnless False name True = \ (ReqAndOpt reqs opts) -> ReqAndOpt reqs (HashSet.insert name opts) +insertReqOptUnless False name False = \ (ReqAndOpt reqs opts) -> ReqAndOpt (HashSet.insert name reqs) opts diff --git a/utils/package.yaml b/utils/package.yaml index 51e8fc65e..72c20b01b 100644 --- a/utils/package.yaml +++ b/utils/package.yaml @@ -13,7 +13,8 @@ extra-source-files: library: source-dirs: src c-sources: cbits/DebugCallback.c - other-modules: "" + other-modules: + - Vulkan.Utils.Internal dependencies: - base <5 - bytestring @@ -26,6 +27,7 @@ library: - text - transformers - typed-process + - unordered-containers - vector - vulkan >= 3.6.14 && < 3.8 diff --git a/utils/src/Vulkan/Utils/Initialization.hs b/utils/src/Vulkan/Utils/Initialization.hs index 1637462de..95e662b50 100644 --- a/utils/src/Vulkan/Utils/Initialization.hs +++ b/utils/src/Vulkan/Utils/Initialization.hs @@ -1,146 +1,271 @@ -{-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedLists, NamedFieldPuns #-} module Vulkan.Utils.Initialization - ( createDebugInstanceWithExtensions - , createInstanceWithExtensions + ( createInstanceFromRequirements + , addDebugRequirements , pickPhysicalDevice , physicalDeviceName - , createDeviceWithExtensions + , createDeviceFromRequirements ) where +import Control.Applicative +import Control.Monad import Control.Monad.IO.Class import Control.Monad.Trans.Resource import Data.Bits import Data.ByteString ( ByteString ) import Data.Foldable +import Data.HashMap.Strict ( HashMap ) +import qualified Data.HashMap.Strict as HashMap +import Data.HashSet ( HashSet ) +import qualified Data.HashSet as HashSet import Data.Maybe import Data.Ord import Data.Text ( Text ) +import qualified Data.Text as Text import Data.Text.Encoding ( decodeUtf8 ) import qualified Data.Vector as V +import Data.Word import Vulkan.CStruct.Extends import Vulkan.Core10 import Vulkan.Extensions.VK_EXT_debug_utils import Vulkan.Extensions.VK_EXT_validation_features +import Vulkan.Requirements import Vulkan.Utils.Debug +import Vulkan.Utils.Internal import Vulkan.Utils.Misc +import Vulkan.Version import Vulkan.Zero ---------------------------------------------------------------- -- * Instance Creation ---------------------------------------------------------------- --- | Like 'createInstanceWithExtensions' except it will create a debug utils --- messenger (from the @VK_EXT_debug_utils@ extension). --- --- If the @VK_EXT_validation_features@ extension (from the --- @VK_LAYER_KHRONOS_validation@ layer) is available is it will be enabled and --- best practices messages enabled. -createDebugInstanceWithExtensions - :: forall es m - . (Extendss InstanceCreateInfo es, PokeChain es, MonadResource m) - => [ByteString] - -- ^ Required layers - -> [ByteString] - -- ^ Optional layers - -> [ByteString] - -- ^ Required extensions - -> [ByteString] - -- ^ Optional extensions - -> InstanceCreateInfo es - -> m Instance -createDebugInstanceWithExtensions requiredLayers optionalLayers requiredExtensions optionalExtensions instanceCreateInfo - = do - let debugMessengerCreateInfo = zero - { messageSeverity = DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT - .|. DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT - , messageType = DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT - .|. DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT - .|. DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT - , pfnUserCallback = debugCallbackPtr - } - validationFeatures = ValidationFeaturesEXT - [VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT] - [] - instanceCreateInfo' - :: InstanceCreateInfo - (DebugUtilsMessengerCreateInfoEXT : ValidationFeaturesEXT : es) - instanceCreateInfo' = instanceCreateInfo - { next = debugMessengerCreateInfo :& validationFeatures :& next - (instanceCreateInfo :: InstanceCreateInfo es) - } - inst <- createInstanceWithExtensions - requiredLayers - ("VK_LAYER_KHRONOS_validation" : optionalLayers) - (EXT_DEBUG_UTILS_EXTENSION_NAME : requiredExtensions) - (EXT_VALIDATION_FEATURES_EXTENSION_NAME : optionalExtensions) - instanceCreateInfo' - _ <- withDebugUtilsMessengerEXT inst - debugMessengerCreateInfo - Nothing - allocate - pure inst - -- | Create an 'Instance' with some layers and extensions, the layers and -- extensions will be added to the provided 'InstanceCreateInfo'. -- +-- Returns all the names of instance layers which were enabled. +-- -- Will throw an 'IOError in the case of missing layers or extensions. Details -- on missing layers and extensions will be reported in stderr. -createInstanceWithExtensions - :: forall es m - . (Extendss InstanceCreateInfo es, PokeChain es, MonadResource m) - => [ByteString] - -- ^ Required layers - -> [ByteString] - -- ^ Optional layers - -> [ByteString] - -- ^ Required extensions - -> [ByteString] - -- ^ Optional extensions - -> InstanceCreateInfo es - -> m Instance -createInstanceWithExtensions requiredLayers optionalLayers requiredExtensions optionalExtensions instanceCreateInfo +createInstanceFromRequests + :: forall m + . MonadResource m + => Requests Instance + -> InstanceCreateInfo '[] + -> m (Instance, [ByteString]) +createInstanceFromRequests + ( InstanceRequests + { version = ReqAndOpt reqVersion optVersion + , instanceLayers = ReqAndOpt requiredLayers optionalLayers + , instanceExtensions = reqAndOptExtensions + , enableSettingsOtherThan = enableSettingsOtherThan :: HashSet ByteString -> Chain settings + } + ) + instanceCreateInfo = do -- - -- First get the layers, they're needed to get the list of supported + -- We start by checking that the Vulkan API version + -- that the user asked for is compatible with the requirements. + -- + let + mbGivenVersion :: Maybe Word32 + mbGivenVersion = ( apiVersion :: ApplicationInfo -> Word32 ) <$> applicationInfo ( instanceCreateInfo :: InstanceCreateInfo '[] ) + for_ mbGivenVersion $ \ givenVersion -> do + unless (givenVersion >= reqVersion) + ( liftIO $ noSuchThing + ( "Requirements imply a minimum Vulkan API version " <> showVersion reqVersion <> ",\n\ + \but the version specified by the application is " <> showVersion givenVersion <> "." + ) + ) + unless (givenVersion >= optVersion) + ( sayErr + ( "Optional preference: minimum Vulkan API version " <> showVersion optVersion <> ",\n\ + \but the version specified by the application is " <> showVersion givenVersion <> "." + ) + ) + -- + -- Next get the layers, they're needed to get the list of supported -- extensions, as some of them may only be present in layers. -- availableLayerNames <- toList . fmap layerName . snd <$> enumerateInstanceLayerProperties - layers <- partitionOptReqIO "layer" - availableLayerNames - optionalLayers - requiredLayers - + (okLayers, missingOptLayers) + <- partitionOptReqIO "layer" + availableLayerNames + (HashMap.keys $ optionalLayers) + (HashMap.keys $ requiredLayers) -- Run 'enumerateInstanceExtensionProperties' once for the instance itself, -- and once for each layer and collect the results. availableExtensionNames <- concat <$> traverse ( fmap (toList . fmap extensionName . snd) . enumerateInstanceExtensionProperties ) - (Nothing : (Just <$> layers)) - extensions <- partitionOptReqIO "instance extension" - availableExtensionNames - optionalExtensions - requiredExtensions - + (Nothing : (Just <$> okLayers)) + let + optionalExtensions, requiredExtensions :: [ByteString] + ReqAndOpt requiredExtensions optionalExtensions + = ( ( \ ( req, opt ) -> ReqAndOpt ( HashMap.keys =<< req ) ( HashMap.keys =<< opt ) ) ) + . unzip + . map ( \ ( ReqAndOpt req opt ) -> (req,opt) ) + $ HashMap.elems reqAndOptExtensions + (okExts, missingOptExts) + <- partitionOptReqIO "instance extension" + availableExtensionNames + optionalExtensions + requiredExtensions let - instanceCreateInfo' :: InstanceCreateInfo es + enabledLayers, enabledExtensions :: V.Vector ByteString + enabledLayers + = enabledLayerNames (instanceCreateInfo :: InstanceCreateInfo '[]) + <> V.fromList okLayers + enabledExtensions + = enabledExtensionNames (instanceCreateInfo :: InstanceCreateInfo '[]) + <> V.fromList okExts + instanceCreateInfo' :: InstanceCreateInfo settings instanceCreateInfo' = instanceCreateInfo - { enabledLayerNames = - enabledLayerNames (instanceCreateInfo :: InstanceCreateInfo es) - <> V.fromList layers - , enabledExtensionNames = - enabledExtensionNames (instanceCreateInfo :: InstanceCreateInfo es) - <> V.fromList extensions + { next = enableSettingsOtherThan HashSet.empty -- not using the 'OtherThan' functionality here + , enabledLayerNames = enabledLayers + , enabledExtensionNames = enabledExtensions } (_, inst) <- withInstance instanceCreateInfo' Nothing allocate - pure inst + pure (inst, okLayers) + +-- | Like 'createInstanceFromExtensions' except it will create a debug utils +-- messenger (from the @VK_EXT_debug_utils@ extension). +-- +-- If the @VK_EXT_validation_features@ extension (from the +-- @VK_LAYER_KHRONOS_validation@ layer) is available is it will be enabled and +-- best practices messages enabled. +createDebugInstanceFromRequests + :: forall m + . MonadResource m + => Requests Instance + -> InstanceCreateInfo '[] + -> m (Instance, [ByteString]) +createDebugInstanceFromRequests reqs createInfo = do + res@(inst,_) <- createInstanceFromRequests debugReqs createInfo + _ <- withDebugUtilsMessengerEXT inst + debugMessengerCreateInfo + Nothing + allocate + pure res + + where + debugReqs :: Requests Instance + debugReqs = addRequests reqs + [ Option $ RequireInstanceLayer "VK_LAYER_KHRONOS_validation" 0 + , Require $ RequireInstanceExtension Nothing EXT_DEBUG_UTILS_EXTENSION_NAME 0 + , Option $ RequireInstanceExtension Nothing EXT_VALIDATION_FEATURES_EXTENSION_NAME 0 + , Require $ RequireInstanceSetting validationFeatures + , Require $ RequireInstanceSetting debugMessengerInfo + ] + validationFeatures :: ValidationFeaturesEXT + validationFeatures = ValidationFeaturesEXT + [VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT] + [] + debugMessengerCreateInfo :: DebugUtilsMessengerCreateInfoEXT + debugMessengerCreateInfo = zero + { messageSeverity = DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT + .|. DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT + , messageType = DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT + .|. DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT + .|. DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT + , pfnUserCallback = debugCallbackPtr + } ---------------------------------------------------------------- -- * Physical device selection ---------------------------------------------------------------- +-- | Check whether a 'PhysicalDevice' meets the provided 'Requests'. +-- +-- If the 'PhysicalDevice' meets the 'Requests': +-- - returns 'Just' the optional properties, features and extensions (in this order) that did not meet the 'Requests'. +-- If the 'PhysicalDevice' did not fit the 'Requests': +-- - returns 'Nothing'. +physicalDeviceFitsRequests + :: MonadIO m + => Requests PhysicalDevice + -> PhysicalDevice + -> m (Maybe (HashSet ByteString, HashSet ByteString, HashSet ByteString)) +physicalDeviceFitsRequests + ( PhysicalDeviceRequests + { missingProperties = missingProperties :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) + , missingFeatures = missingFeatures :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) + , deviceExtensions = reqAndOptExtensions + } + ) + physicalDevice = do + devName <- physicalDeviceName physicalDevice + physicalDeviceProperties <- getPhysicalDeviceProperties physicalDevice + let + vulkan1p1 :: Word32 + vulkan1p1 = MAKE_VERSION 1 1 0 + deviceVersion :: Word32 + deviceVersion = (apiVersion :: VkPhysicalDeviceProperties -> Word32) physicalDeviceProperties + ( ReqAndOpt missingReqProps missingOptProps :: ReqAndOpt ( HashSet ByteString ) ) <- + case sLength @props of + SNil -> do + pure $ missingProperties ( zero { properties = physicalDeviceProperties } ) + SCons _ -> do + when (deviceVersion < vulkan1p1) + ( liftIO $ noSuchThing + ( "Device properties need Vulkan API version " <> showVersion vulkan1p1 <> ",\n\ + \but the current device Vulkan version is " <> showVersion deviceVersion <> "." + ) + ) + physicalDeviceProperties2 <- getPhysicalDeviceProperties2 @props physicalDevice + pure $ missingProperties physicalDeviceProperties2 + ( ReqAndOpt missingReqFeats missingOptFeats :: ReqAndOpt ( HashSet ByteString ) ) <- + case sLength @feats of + SNil -> do + physicalDeviceFeatures <- getPhysicalDeviceFeatures physicalDevice + pure $ missingFeatures ( zero { features = physicalDeviceFeatures } ) + SCons _ -> do + when (deviceVersion < vulkan1p1) + ( liftIO $ noSuchThing + ( "Device features need Vulkan API version " <> showVersion vulkan1p1 <> ",\n\ + \but the current device Vulkan version is " <> showVersion deviceVersion <> "." + ) + ) + physicalDeviceFeatures2 <- getPhysicalDeviceFeatures2 @feats physicalDevice + pure $ missingFeatures physicalDeviceFeatures2 + if HashSet.null missingReqProps && HashSet.null missingReqFeats + then do + let + optionalExtensions, requiredExtensions :: [ByteString] + ReqAndOpt requiredExtensions optionalExtensions + = ( ( \ ( req, opt ) -> ReqAndOpt ( HashMap.keys =<< req ) ( HashMap.keys =<< opt ) ) ) + . unzip + . map ( \ ( ReqAndOpt req opt ) -> (req,opt) ) + $ HashMap.elems reqAndOptExtensions + availableExtensionNames <- + fmap extensionName . snd <$> enumerateDeviceExtensionProperties phys Nothing + ( missingOptExts, eitherMissingReqExtsOrEnabledExts) <- + partitionOptReq + availableExtensionNames + optionalExtensions + requiredExtensions + case eitherMissingReqExtsOrEnabledExts of + Left missingExts -> do + devName <- physicalDeviceName physicalDevice + sayErr + ( "Physical device " <> Text.unpack devName + <> " is missing the following required extensions:\n" + <> show missingExts + ) + pure Nothing + Right _ -> + pure ( Just ( missingOptProps, missingOptFeats, missingOptExts ) ) + else do + sayErr + ( "Physical device " <> Text.unpack devName <> " does not meet requirements.\n\ + \Missing required properties: " <> show missingReqProps <> "\n\ + \Missing required features : " <> show missingReqFeats + ) + pure Nothing + -- | Get a single 'PhysicalDevice' deciding with a scoring function -- -- Pass a function which will extract any required values from a device in the @@ -182,39 +307,60 @@ physicalDeviceName = -- | Create a 'Device' with some extensions, the extensions will be added to -- the provided 'DeviceCreateInfo'. -- +-- Assumes the provided 'PhysicalDevice' satisfies the 'Requirements', +-- and that the provided layers have indeed been enabled in the current Vulkan instance. +-- -- Will throw an 'IOError in the case of missing extensions. Missing extensions -- will be listed on stderr. -createDeviceWithExtensions - :: forall es m - . (Extendss DeviceCreateInfo es, PokeChain es, MonadResource m) +createDeviceFromRequests + :: MonadResource m => PhysicalDevice + -> Requests PhysicalDevice + -> HashSet ByteString + -- ^ Optional features that the device does not support, + -- as returned in the second component by 'physicalDeviceFitsRequirements'. -> [ByteString] - -- ^ Required extensions - -> [ByteString] - -- ^ Optional extensions - -> DeviceCreateInfo es + -- ^ Enabled instance layers, + -- as returned by 'createInstanceFromRequirements'. + -> V.Vector (SomeStruct DeviceQueueCreateInfo) -> m Device -createDeviceWithExtensions phys requiredExtensions optionalExtensions deviceCreateInfo +createDeviceFromRequests + phys + ( PhysicalDeviceRequests + { enableFeaturesOtherThan = enableFeaturesOtherThan :: HashSet ByteString -> PhysicalDeviceFeatures2 feats + } + ) + don'tEnableThese + enabledLayers + queueCreateInfos = do - availableExtensionNames <- - fmap extensionName - . snd - <$> enumerateDeviceExtensionProperties phys Nothing - extensions <- partitionOptReqIO "device extension" - (toList availableExtensionNames) - requiredExtensions - optionalExtensions - - let - deviceCreateInfo' :: DeviceCreateInfo es - deviceCreateInfo' = deviceCreateInfo - { enabledExtensionNames = - enabledExtensionNames (deviceCreateInfo :: DeviceCreateInfo es) - <> V.fromList extensions - } - - (_, dev) <- withDevice phys deviceCreateInfo' Nothing allocate - pure dev + case sLength @feats of + SNil -> do + let + deviceCreateInfo :: DeviceCreateInfo '[] + deviceCreateInfo = deviceCreateInfo + { next = () + , flags = zero + , queueCreateInfos + , enabledLayerNames = V.fromList enabledLayers + , enabledExtensionNames = V.fromList okExtensions + , enabledFeatures = Just $ features ( enableFeaturesOtherThan don'tEnableThese ) + } + snd <$> withDevice phys deviceCreateInfo Nothing allocate + SCons _ -> do + let + deviceCreateInfo :: DeviceCreateInfo ( PhysicalDeviceFeatures2 '[] ': feats ) + deviceCreateInfo + | PhysicalDeviceFeatures2 {next, features} <- enableFeaturesOtherThan don'tEnableThese + = DeviceCreateInfo + { next = (zero {features}, next) + , flags = zero + , queueCreateInfos + , enabledLayerNames = V.fromList enabledLayers + , enabledExtensionNames = V.fromList okExtensions + , enabledFeatures = Nothing + } + snd <$> withDevice phys deviceCreateInfo Nothing allocate ---------------------------------------------------------------- -- Utils @@ -222,3 +368,11 @@ createDeviceWithExtensions phys requiredExtensions optionalExtensions deviceCrea maximumByMay :: Foldable t => (a -> a -> Ordering) -> t a -> Maybe a maximumByMay f xs = if null xs then Nothing else Just (maximumBy f xs) + +showVersion :: Word32 -> String +showVersion ver = show maj <> " " <> show min <> " " <> show patch + where + maj, min, patch :: Word32 + maj = _VERSION_MAJOR ver + min = _VERSION_MINOR ver + patch = _VERSION_PATCH ver diff --git a/utils/src/Vulkan/Utils/Internal.hs b/utils/src/Vulkan/Utils/Internal.hs new file mode 100644 index 000000000..98be76bfc --- /dev/null +++ b/utils/src/Vulkan/Utils/Internal.hs @@ -0,0 +1,21 @@ +module Vulkan.Utils.Internal where + +import Control.Monad.IO.Class +import GHC.IO ( throwIO ) +import GHC.IO.Exception ( IOErrorType(NoSuchThing) + , IOException(..) + ) +import System.IO ( hPutStrLn + , stderr + ) + +---------------------------------------------------------------- +-- Internal utils +---------------------------------------------------------------- + +noSuchThing :: String -> IO a +noSuchThing message = + throwIO $ IOError Nothing NoSuchThing "" message Nothing Nothing + +sayErr :: MonadIO m => String -> m () +sayErr = liftIO . hPutStrLn stderr diff --git a/utils/src/Vulkan/Utils/Misc.hs b/utils/src/Vulkan/Utils/Misc.hs index 2de812c63..5b40f1bcd 100644 --- a/utils/src/Vulkan/Utils/Misc.hs +++ b/utils/src/Vulkan/Utils/Misc.hs @@ -20,6 +20,7 @@ import GHC.IO.Exception ( IOErrorType(NoSuchThing) import System.IO ( hPutStrLn , stderr ) +import Vulkan.Utils.Internal -- | From a list of things, take all the required things and as many optional -- things as possible. @@ -59,8 +60,9 @@ partitionOptReqIO -- ^ Optional desired elements -> [a] -- ^ Required desired elements - -> m [a] - -- ^ All the required elements and as many optional elements as possible + -> m ([a],[a]) + -- ^ All the required elements and as many optional elements as possible, + -- as well as the missing optional elements. partitionOptReqIO type' available optional required = liftIO $ do let (optMissing, exts) = partitionOptReq available optional required for_ optMissing @@ -70,7 +72,7 @@ partitionOptReqIO type' available optional required = liftIO $ do for_ reqMissing $ \r -> sayErr $ "Missing required " <> type' <> ": " <> show r noSuchThing $ "Don't have all required " <> type' <> "s" - Right xs -> pure xs + Right xs -> pure (xs, optMissing) ---------------------------------------------------------------- -- * Bit utils @@ -104,14 +106,3 @@ showBits a = if a == zeroBits -- | Check if the intersection of bits is non-zero (.&&.) :: Bits a => a -> a -> Bool x .&&. y = (x .&. y) /= zeroBits - ----------------------------------------------------------------- --- Internal utils ----------------------------------------------------------------- - -noSuchThing :: String -> IO a -noSuchThing message = - throwIO $ IOError Nothing NoSuchThing "" message Nothing Nothing - -sayErr :: MonadIO m => String -> m () -sayErr = liftIO . hPutStrLn stderr From 183637f613bfe3a271d04a19372338366920d795 Mon Sep 17 00:00:00 2001 From: sheaf Date: Wed, 25 Nov 2020 23:11:54 +0100 Subject: [PATCH 30/70] Rename RequireFeature/RequireProperty to RequireDeviceFeature/RequireDeviceProperty --- src-manual/Vulkan/Requirements.hs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src-manual/Vulkan/Requirements.hs b/src-manual/Vulkan/Requirements.hs index 1a02a0df5..43437997c 100644 --- a/src-manual/Vulkan/Requirements.hs +++ b/src-manual/Vulkan/Requirements.hs @@ -138,7 +138,7 @@ data instance Requirement PhysicalDevice where :: { version :: Word32 } -> Requirement PhysicalDevice -- | Require a Vulkan physical device feature. - RequireFeature + RequireDeviceFeature :: forall struct . KnownFeatureStruct struct => { featureName :: ByteString @@ -147,7 +147,7 @@ data instance Requirement PhysicalDevice where } -> Requirement PhysicalDevice -- | Require a Vulkan physical device property. - RequireProperty + RequireDeviceProperty :: forall struct . KnownPropertyStruct struct => { propertyName :: ByteString @@ -341,10 +341,10 @@ instance KnownRequestTarget PhysicalDevice where -> requestDeviceVersion isOptional version RequireDeviceExtension {..} -> requestDeviceExtension isOptional deviceExtensionLayerName deviceExtensionName deviceExtensionMinVersion - RequireFeature {..} - -> requestFeature isOptional featureName checkFeature enableFeature - RequireProperty {..} - -> requestProperty isOptional propertyName checkProperty + RequireDeviceFeature {..} + -> requestDeviceFeature isOptional featureName checkFeature enableFeature + RequireDeviceProperty {..} + -> requestDeviceProperty isOptional propertyName checkProperty -- | Add a single request to a collection of requests. addRequests @@ -443,11 +443,11 @@ requestInstanceSetting _isOptional setting setts' = (setting, setts) -> InstanceRequests ver lays instExts setts' -requestFeature +requestDeviceFeature :: forall struct . ( KnownFeatureStruct struct ) => Bool -> ByteString -> (struct -> Bool) -> (struct -> struct) -> Requests PhysicalDevice -> Requests PhysicalDevice -requestFeature isOptional featName checkFeat enableFeat +requestDeviceFeature isOptional featName checkFeat enableFeat ( PhysicalDeviceRequests ver devExts (missingFeats :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString)) enableFeats @@ -502,11 +502,11 @@ requestFeature isOptional featName checkFeat enableFeat = enabled { next = (struct, nextEnabledFeats) } -> PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps -requestProperty +requestDeviceProperty :: forall struct . ( KnownPropertyStruct struct ) => Bool -> ByteString -> (struct -> Bool) -> Requests PhysicalDevice -> Requests PhysicalDevice -requestProperty isOptional propName checkProp +requestDeviceProperty isOptional propName checkProp ( PhysicalDeviceRequests ver devExts missingFeats enabledFeats (missingProps :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString)) ) From e0a10d467c8def6388e4ea9283a12b51f0fee37a Mon Sep 17 00:00:00 2001 From: sheaf Date: Wed, 25 Nov 2020 23:12:23 +0100 Subject: [PATCH 31/70] Update generate-new for Requirement changes --- generate-new/src/Render/Element/Write.hs | 13 ++++- generate-new/vk/VK/SPIRVElements.hs | 72 ++++++++++++++---------- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/generate-new/src/Render/Element/Write.hs b/generate-new/src/Render/Element/Write.hs index aa31121b3..96b4f1f78 100644 --- a/generate-new/src/Render/Element/Write.hs +++ b/generate-new/src/Render/Element/Write.hs @@ -280,8 +280,17 @@ renderModule out boot getDoc findModule findLocalModule (Segment modName unsorte let t = layoutDoc (d <> line <> line) if getAll (reCanFormat e) then liftIO (parsePrintModule brittanyConfig t) >>= \case - Left _ -> error "Fail" - Right f -> pure f + Left err -> error $ "Fail: Brittany failed to handle module:\n" <> + T.intercalate "\n" (fmap (T.pack . showBError) err) + <> "\n\n\n" <> t + where showBError = \case + ErrorInput x -> "ErrorInput " <> x + ErrorUnusedComment x -> "ErrorUnusedComent " <> x + ErrorMacroConfig x y -> "ErrorMacroConfig " <> x <> " " <> y + LayoutWarning x -> "LayoutWarning " <> x + ErrorUnknownNode x _ -> "ErrorUnknownNode " <> x <> " <<>>" + ErrorOutputCheck -> "ErrorOutputCheck" + Right f -> pure f else pure t contentsTexts <- mapMaybeM layoutContent (V.toList es) let moduleText = diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs index e19be2482..229125a98 100644 --- a/generate-new/vk/VK/SPIRVElements.hs +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -73,26 +73,29 @@ renderSPIRVThing -> Vector a -> Sem r () renderSPIRVThing funName name reqs xs = do + tellLanguageExtension (LanguageExtension "TupleSections") let case' x = do let mergeReqs = Prelude.head -- TODO: this is probably wrong! discarding the -- other reqs - reqs' <- mergeReqs <$> traverse renderReq (V.toList (reqs x)) - pure $ viaShow (name x) <+> "->" <+> list reqs' - cases <- (<> ["_ -> []"]) <$> traverse case' (V.toList xs) + (instReqs', devReqs') <- mergeReqs <$> traverse renderReq (V.toList (reqs x)) + pure $ viaShow (name x) <+> "-> (,)" <+> list instReqs' <+> list devReqs' + cases <- (<> ["_ -> ([],[])"]) <$> traverse case' (V.toList xs) tellImport ''ByteString + tellImport (TyConName "Instance") + tellImport (TyConName "PhysicalDevice") tellImport (mkName "Vulkan.Requirements.Requirement") tellExport (ETerm (TermName funName)) tellDoc $ vsep - [ pretty funName <+> ":: ByteString -> [Requirement]" + [ pretty funName <+> ":: ByteString -> ([Requirement Instance], [Requirement PhysicalDevice])" , pretty funName <+> "= \\case" <> line <> indent 2 (vsep cases) ] renderReq :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) => SPIRVRequirement - -> Sem r [Doc ()] + -> Sem r ([Doc ()],[Doc ()]) renderReq = \case - SPIRVReqVersion v -> pure <$> versionReq v + SPIRVReqVersion v -> ( \(iReq,devReq) -> ([iReq],[devReq]) ) <$> versionReq v SPIRVReqExtension p -> minVersionAndExtensionsReqs (V.singleton p) @@ -105,8 +108,9 @@ renderReq = \case traverse_ tellImportWithAll (allTypeNames sTy) checkTDoc <- renderType (sTy ~> ConT ''Bool) sTyDoc <- renderType sTy - otherReqs <- minVersionAndExtensionsReqs rs - let featureMemberName = mkMemberName s f + (otherInstReqs, otherDevReqs) <- minVersionAndExtensionsReqs rs + let + featureMemberName = mkMemberName s f let xs = [ ("featureName" , viaShow f) , ("checkFeature", pretty featureMemberName <+> "::" <+> checkTDoc) @@ -118,7 +122,9 @@ renderReq = \case <+> sTyDoc ) ] - pure $ "RequireFeature" <> braceAssignmentList xs : otherReqs + pure ( otherInstReqs + , "RequireDeviceFeature" <> braceAssignmentList xs : otherDevReqs + ) SPIRVReqProperty p m v rs -> do RenderParams {..} <- input @@ -130,7 +136,7 @@ renderReq = \case sTyDoc <- renderType sTy let propertyMemberName = mkMemberName p m propertyValueName = mkPatternName v - otherReqs <- minVersionAndExtensionsReqs rs + (otherInstReqs, otherDevReqs) <- minVersionAndExtensionsReqs rs -- TODO, do this properly checker <- if | v == "VK_TRUE" @@ -155,12 +161,14 @@ renderReq = \case <+> pretty propertyMemberName <+> parens ("p ::" <+> sTyDoc) let xs = [("propertyName", viaShow p), ("checkProperty", checker)] - pure $ "RequireProperty" <> braceAssignmentList xs : otherReqs + pure ( otherInstReqs + , "RequireDeviceProperty" <> braceAssignmentList xs : otherDevReqs + ) minVersionAndExtensionsReqs :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) => Vector Text - -> Sem r [Doc ()] + -> Sem r ([Doc ()],[Doc ()]) minVersionAndExtensionsReqs rs = do SpecInfo {..} <- input let dependencies = nubOrd $ toList rs <> concatMap siExtensionDeps rs @@ -177,22 +185,23 @@ minVersionAndExtensionsReqs rs = do [] -> pure Nothing xs -> Just <$> versionReq (maximum xs) - pure - $ maybeToList v - <> [ "RequireInstanceExtension" <> braceAssignmentList - [ ("instanceExtensionLayerName" , "Nothing") - , ("instanceExtensionName" , e) - , ("instanceExtensionMinVersion", v) - ] - | (e, v) <- instanceExtensions - ] - <> [ "RequireDeviceExtension" <> braceAssignmentList - [ ("deviceExtensionLayerName" , "Nothing") - , ("deviceExtensionName" , e) - , ("deviceExtensionMinVersion", v) - ] - | (e, v) <- deviceExtensions - ] + pure ( maybe id ((:) . fst) v + [ "RequireInstanceExtension" <> braceAssignmentList + [ ("instanceExtensionLayerName" , "Nothing") + , ("instanceExtensionName" , e) + , ("instanceExtensionMinVersion", v) + ] + | (e, v) <- instanceExtensions + ] + , maybe id ((:) . snd) v + [ "RequireDeviceExtension" <> braceAssignmentList + [ ("deviceExtensionLayerName" , "Nothing") + , ("deviceExtensionName" , e) + , ("deviceExtensionMinVersion", v) + ] + | (e, v) <- deviceExtensions + ] + ) extensionNamePattern :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) @@ -234,11 +243,14 @@ data RequireType -- ^ _EXTENSION_NAME and _SPEC_VERSION versionReq - :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) + :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc (), Doc()) versionReq v = do tellImportWithAll (mkName "Vulkan.Requirements.Requirement") vDoc <- versionDoc v - pure $ "RequireVersion $" <+> vDoc + pure + ( "RequireInstanceVersion $" <+> vDoc + , "RequireDeviceVersion $" <+> vDoc + ) versionDoc :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) From 43222eecf54c41546bbcda1e4b467c7ba35d18a6 Mon Sep 17 00:00:00 2001 From: sheaf Date: Wed, 25 Nov 2020 23:29:40 +0100 Subject: [PATCH 32/70] Update vulkan-utils Initialization --- utils/src/Vulkan/Utils/Initialization.hs | 72 ++++++++++++++---------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/utils/src/Vulkan/Utils/Initialization.hs b/utils/src/Vulkan/Utils/Initialization.hs index 95e662b50..cbdae1dd7 100644 --- a/utils/src/Vulkan/Utils/Initialization.hs +++ b/utils/src/Vulkan/Utils/Initialization.hs @@ -1,11 +1,11 @@ {-# LANGUAGE OverloadedLists, NamedFieldPuns #-} module Vulkan.Utils.Initialization - ( createInstanceFromRequirements - , addDebugRequirements + ( createInstanceFromRequests + , createDebugInstanceFromRequests , pickPhysicalDevice , physicalDeviceName - , createDeviceFromRequirements + , createDeviceFromRequests ) where import Control.Applicative @@ -28,6 +28,7 @@ import qualified Data.Vector as V import Data.Word import Vulkan.CStruct.Extends import Vulkan.Core10 +import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 import Vulkan.Extensions.VK_EXT_debug_utils import Vulkan.Extensions.VK_EXT_validation_features import Vulkan.Requirements @@ -56,10 +57,10 @@ createInstanceFromRequests -> m (Instance, [ByteString]) createInstanceFromRequests ( InstanceRequests - { version = ReqAndOpt reqVersion optVersion - , instanceLayers = ReqAndOpt requiredLayers optionalLayers - , instanceExtensions = reqAndOptExtensions - , enableSettingsOtherThan = enableSettingsOtherThan :: HashSet ByteString -> Chain settings + { version = ReqAndOpt reqVersion optVersion + , instanceLayers = ReqAndOpt requiredLayers optionalLayers + , instanceExtensions = reqAndOptExtensions + , enableSettings = enableSettings :: Chain settings } ) instanceCreateInfo @@ -124,7 +125,7 @@ createInstanceFromRequests <> V.fromList okExts instanceCreateInfo' :: InstanceCreateInfo settings instanceCreateInfo' = instanceCreateInfo - { next = enableSettingsOtherThan HashSet.empty -- not using the 'OtherThan' functionality here + { next = enableSettings , enabledLayerNames = enabledLayers , enabledExtensionNames = enabledExtensions } @@ -153,12 +154,12 @@ createDebugInstanceFromRequests reqs createInfo = do where debugReqs :: Requests Instance - debugReqs = addRequests reqs - [ Option $ RequireInstanceLayer "VK_LAYER_KHRONOS_validation" 0 + debugReqs = addRequests @[] reqs + [ Option $ RequireInstanceLayer "VK_LAYER_KHRONOS_validation" 0 100 , Require $ RequireInstanceExtension Nothing EXT_DEBUG_UTILS_EXTENSION_NAME 0 , Option $ RequireInstanceExtension Nothing EXT_VALIDATION_FEATURES_EXTENSION_NAME 0 , Require $ RequireInstanceSetting validationFeatures - , Require $ RequireInstanceSetting debugMessengerInfo + , Require $ RequireInstanceSetting debugMessengerCreateInfo ] validationFeatures :: ValidationFeaturesEXT validationFeatures = ValidationFeaturesEXT @@ -181,14 +182,20 @@ createDebugInstanceFromRequests reqs createInfo = do -- | Check whether a 'PhysicalDevice' meets the provided 'Requests'. -- -- If the 'PhysicalDevice' meets the 'Requests': --- - returns 'Just' the optional properties, features and extensions (in this order) that did not meet the 'Requests'. +-- - returns 'Just' the enabled extensions, +-- together with the optional properties, features and extensions (in this order) +-- which were requested but could not be enabled. -- If the 'PhysicalDevice' did not fit the 'Requests': -- - returns 'Nothing'. physicalDeviceFitsRequests :: MonadIO m => Requests PhysicalDevice -> PhysicalDevice - -> m (Maybe (HashSet ByteString, HashSet ByteString, HashSet ByteString)) + -> m ( Maybe + ( V.Vector ByteString + , (HashSet ByteString, HashSet ByteString, HashSet ByteString) + ) + ) physicalDeviceFitsRequests ( PhysicalDeviceRequests { missingProperties = missingProperties :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) @@ -203,7 +210,7 @@ physicalDeviceFitsRequests vulkan1p1 :: Word32 vulkan1p1 = MAKE_VERSION 1 1 0 deviceVersion :: Word32 - deviceVersion = (apiVersion :: VkPhysicalDeviceProperties -> Word32) physicalDeviceProperties + deviceVersion = (apiVersion :: PhysicalDeviceProperties -> Word32) physicalDeviceProperties ( ReqAndOpt missingReqProps missingOptProps :: ReqAndOpt ( HashSet ByteString ) ) <- case sLength @props of SNil -> do @@ -241,12 +248,15 @@ physicalDeviceFitsRequests . map ( \ ( ReqAndOpt req opt ) -> (req,opt) ) $ HashMap.elems reqAndOptExtensions availableExtensionNames <- - fmap extensionName . snd <$> enumerateDeviceExtensionProperties phys Nothing - ( missingOptExts, eitherMissingReqExtsOrEnabledExts) <- - partitionOptReq - availableExtensionNames - optionalExtensions - requiredExtensions + fmap extensionName . snd <$> enumerateDeviceExtensionProperties physicalDevice Nothing + let + missingOptExts :: [ByteString] + eitherMissingReqExtsOrEnabledExts :: Either [ByteString] [ByteString] + (missingOptExts, eitherMissingReqExtsOrEnabledExts) + = partitionOptReq + (V.toList availableExtensionNames) + optionalExtensions + requiredExtensions case eitherMissingReqExtsOrEnabledExts of Left missingExts -> do devName <- physicalDeviceName physicalDevice @@ -256,8 +266,8 @@ physicalDeviceFitsRequests <> show missingExts ) pure Nothing - Right _ -> - pure ( Just ( missingOptProps, missingOptFeats, missingOptExts ) ) + Right enabledExts -> + pure ( Just (V.fromList enabledExts, (missingOptProps, missingOptFeats, HashSet.fromList missingOptExts)) ) else do sayErr ( "Physical device " <> Text.unpack devName <> " does not meet requirements.\n\ @@ -318,10 +328,10 @@ createDeviceFromRequests -> Requests PhysicalDevice -> HashSet ByteString -- ^ Optional features that the device does not support, - -- as returned in the second component by 'physicalDeviceFitsRequirements'. - -> [ByteString] - -- ^ Enabled instance layers, - -- as returned by 'createInstanceFromRequirements'. + -- as returned by 'physicalDeviceFitsRequirements'. + -> V.Vector ByteString + -- ^ Enabled extensions, + -- as returned by 'physicalDeviceFitsRequirement'. -> V.Vector (SomeStruct DeviceQueueCreateInfo) -> m Device createDeviceFromRequests @@ -331,7 +341,7 @@ createDeviceFromRequests } ) don'tEnableThese - enabledLayers + okExtensions queueCreateInfos = do case sLength @feats of @@ -342,8 +352,8 @@ createDeviceFromRequests { next = () , flags = zero , queueCreateInfos - , enabledLayerNames = V.fromList enabledLayers - , enabledExtensionNames = V.fromList okExtensions + , enabledLayerNames = V.empty -- device layers aren't used + , enabledExtensionNames = okExtensions , enabledFeatures = Just $ features ( enableFeaturesOtherThan don'tEnableThese ) } snd <$> withDevice phys deviceCreateInfo Nothing allocate @@ -356,8 +366,8 @@ createDeviceFromRequests { next = (zero {features}, next) , flags = zero , queueCreateInfos - , enabledLayerNames = V.fromList enabledLayers - , enabledExtensionNames = V.fromList okExtensions + , enabledLayerNames = V.empty -- device layers aren't used + , enabledExtensionNames = okExtensions , enabledFeatures = Nothing } snd <$> withDevice phys deviceCreateInfo Nothing allocate From e8b27829b8d43d6bc34848f9b7bd97b5f3784d61 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Thu, 26 Nov 2020 10:24:53 +0800 Subject: [PATCH 33/70] regenerate --- src/Vulkan/SPIRVRequirements.hs | 1424 ++++++++++++++++++------------- 1 file changed, 814 insertions(+), 610 deletions(-) diff --git a/src/Vulkan/SPIRVRequirements.hs b/src/Vulkan/SPIRVRequirements.hs index 2d63f7cdf..bdd442c9a 100644 --- a/src/Vulkan/SPIRVRequirements.hs +++ b/src/Vulkan/SPIRVRequirements.hs @@ -1,5 +1,6 @@ {-# language CPP #-} {-# language OverloadedLists #-} +{-# language TupleSections #-} -- No documentation found for Chapter "SPIRVRequirements" module Vulkan.SPIRVRequirements ( spirvExtensionRequirements , spirvCapabilityRequirements @@ -11,6 +12,8 @@ import Data.Bits ((.&.)) import Data.Bits (zeroBits) import Data.Bits (Bits) import Data.ByteString (ByteString) +import Vulkan.Core10.Handles (Instance) +import Vulkan.Core10.Handles (PhysicalDevice) import Vulkan.Extensions.VK_EXT_buffer_device_address (PhysicalDeviceBufferDeviceAddressFeaturesEXT) import Vulkan.Extensions.VK_EXT_buffer_device_address (PhysicalDeviceBufferDeviceAddressFeaturesEXT(..)) import Vulkan.Extensions.VK_NV_compute_shader_derivatives (PhysicalDeviceComputeShaderDerivativesFeaturesNV) @@ -210,147 +213,174 @@ import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBG (.&&.) :: Bits a => a -> a -> Bool x .&&. y = (x .&. y) /= zeroBits -spirvExtensionRequirements :: ByteString -> [Requirement] +spirvExtensionRequirements :: ByteString -> ([Requirement Instance], [Requirement PhysicalDevice]) spirvExtensionRequirements = \case - "SPV_KHR_variable_pointers" -> [RequireVersion $ MAKE_VERSION 1 1 0] - "SPV_AMD_shader_explicit_vertex_parameter" -> + "SPV_KHR_variable_pointers" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 1 0] [RequireDeviceVersion $ MAKE_VERSION 1 1 0] + "SPV_AMD_shader_explicit_vertex_parameter" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION } ] - "SPV_AMD_gcn_shader" -> + "SPV_AMD_gcn_shader" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_GCN_SHADER_EXTENSION_NAME , deviceExtensionMinVersion = AMD_GCN_SHADER_SPEC_VERSION } ] - "SPV_AMD_gpu_shader_half_float" -> + "SPV_AMD_gpu_shader_half_float" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME , deviceExtensionMinVersion = AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION } ] - "SPV_AMD_gpu_shader_int16" -> + "SPV_AMD_gpu_shader_int16" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_GPU_SHADER_INT16_EXTENSION_NAME , deviceExtensionMinVersion = AMD_GPU_SHADER_INT16_SPEC_VERSION } ] - "SPV_AMD_shader_ballot" -> + "SPV_AMD_shader_ballot" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_BALLOT_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_BALLOT_SPEC_VERSION } ] - "SPV_AMD_shader_fragment_mask" -> + "SPV_AMD_shader_fragment_mask" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION } ] - "SPV_AMD_shader_image_load_store_lod" -> + "SPV_AMD_shader_image_load_store_lod" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION } ] - "SPV_AMD_shader_trinary_minmax" -> + "SPV_AMD_shader_trinary_minmax" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION } ] - "SPV_AMD_texture_gather_bias_lod" -> + "SPV_AMD_texture_gather_bias_lod" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME , deviceExtensionMinVersion = AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION } ] - "SPV_KHR_shader_draw_parameters" -> [RequireVersion $ MAKE_VERSION 1 1 0] - "SPV_KHR_8bit_storage" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "SPV_KHR_16bit_storage" -> [RequireVersion $ MAKE_VERSION 1 1 0] - "SPV_KHR_shader_clock" -> + "SPV_KHR_shader_draw_parameters" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 1 0] [RequireDeviceVersion $ MAKE_VERSION 1 1 0] + "SPV_KHR_8bit_storage" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "SPV_KHR_16bit_storage" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 1 0] [RequireDeviceVersion $ MAKE_VERSION 1 1 0] + "SPV_KHR_shader_clock" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_CLOCK_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_CLOCK_SPEC_VERSION } ] - "SPV_KHR_float_controls" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "SPV_KHR_storage_buffer_storage_class" -> [RequireVersion $ MAKE_VERSION 1 1 0] - "SPV_KHR_post_depth_coverage" -> + "SPV_KHR_float_controls" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "SPV_KHR_storage_buffer_storage_class" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 1 0] [RequireDeviceVersion $ MAKE_VERSION 1 1 0] + "SPV_KHR_post_depth_coverage" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME , deviceExtensionMinVersion = EXT_POST_DEPTH_COVERAGE_SPEC_VERSION } ] - "SPV_EXT_shader_stencil_export" -> + "SPV_EXT_shader_stencil_export" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION } ] - "SPV_KHR_shader_ballot" -> + "SPV_KHR_shader_ballot" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION } ] - "SPV_KHR_subgroup_vote" -> + "SPV_KHR_subgroup_vote" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION } ] - "SPV_NV_sample_mask_override_coverage" -> + "SPV_NV_sample_mask_override_coverage" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME , deviceExtensionMinVersion = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION } ] - "SPV_NV_geometry_shader_passthrough" -> + "SPV_NV_geometry_shader_passthrough" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME , deviceExtensionMinVersion = NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION } ] - "SPV_NV_mesh_shader" -> + "SPV_NV_mesh_shader" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_MESH_SHADER_EXTENSION_NAME , deviceExtensionMinVersion = NV_MESH_SHADER_SPEC_VERSION } ] - "SPV_NV_viewport_array2" -> + "SPV_NV_viewport_array2" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_VIEWPORT_ARRAY2_EXTENSION_NAME , deviceExtensionMinVersion = NV_VIEWPORT_ARRAY2_SPEC_VERSION } ] - "SPV_NV_shader_subgroup_partitioned" -> + "SPV_NV_shader_subgroup_partitioned" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION } ] - "SPV_EXT_shader_viewport_index_layer" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "SPV_NVX_multiview_per_view_attributes" -> + "SPV_EXT_shader_viewport_index_layer" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "SPV_NVX_multiview_per_view_attributes" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME , deviceExtensionMinVersion = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION } @@ -359,54 +389,61 @@ spirvExtensionRequirements = \case , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION } ] - "SPV_EXT_descriptor_indexing" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "SPV_KHR_vulkan_memory_model" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "SPV_NV_compute_shader_derivatives" -> + "SPV_EXT_descriptor_indexing" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "SPV_KHR_vulkan_memory_model" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "SPV_NV_compute_shader_derivatives" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME , deviceExtensionMinVersion = NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION } ] - "SPV_NV_fragment_shader_barycentric" -> + "SPV_NV_fragment_shader_barycentric" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME , deviceExtensionMinVersion = NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION } ] - "SPV_NV_shader_image_footprint" -> + "SPV_NV_shader_image_footprint" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION } ] - "SPV_NV_shading_rate" -> + "SPV_NV_shading_rate" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADING_RATE_IMAGE_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADING_RATE_IMAGE_SPEC_VERSION } ] - "SPV_NV_ray_tracing" -> + "SPV_NV_ray_tracing" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_RAY_TRACING_EXTENSION_NAME , deviceExtensionMinVersion = NV_RAY_TRACING_SPEC_VERSION } @@ -415,12 +452,13 @@ spirvExtensionRequirements = \case , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION } ] - "SPV_KHR_ray_tracing" -> + "SPV_KHR_ray_tracing" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_RAY_TRACING_PIPELINE_SPEC_VERSION } @@ -453,12 +491,13 @@ spirvExtensionRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "SPV_KHR_ray_query" -> + "SPV_KHR_ray_query" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_RAY_QUERY_EXTENSION_NAME , deviceExtensionMinVersion = KHR_RAY_QUERY_SPEC_VERSION } @@ -491,87 +530,98 @@ spirvExtensionRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "SPV_GOOGLE_hlsl_functionality1" -> + "SPV_GOOGLE_hlsl_functionality1" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME , deviceExtensionMinVersion = GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION } ] - "SPV_GOOGLE_user_type" -> + "SPV_GOOGLE_user_type" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = GOOGLE_USER_TYPE_EXTENSION_NAME , deviceExtensionMinVersion = GOOGLE_USER_TYPE_SPEC_VERSION } ] - "SPV_GOOGLE_decorate_string" -> + "SPV_GOOGLE_decorate_string" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = GOOGLE_DECORATE_STRING_EXTENSION_NAME , deviceExtensionMinVersion = GOOGLE_DECORATE_STRING_SPEC_VERSION } ] - "SPV_EXT_fragment_invocation_density" -> + "SPV_EXT_fragment_invocation_density" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME , deviceExtensionMinVersion = EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION } ] - "SPV_KHR_physical_storage_buffer" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "SPV_EXT_physical_storage_buffer" -> + "SPV_KHR_physical_storage_buffer" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "SPV_EXT_physical_storage_buffer" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME , deviceExtensionMinVersion = EXT_BUFFER_DEVICE_ADDRESS_SPEC_VERSION } ] - "SPV_NV_cooperative_matrix" -> + "SPV_NV_cooperative_matrix" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_COOPERATIVE_MATRIX_EXTENSION_NAME , deviceExtensionMinVersion = NV_COOPERATIVE_MATRIX_SPEC_VERSION } ] - "SPV_NV_shader_sm_builtins" -> + "SPV_NV_shader_sm_builtins" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADER_SM_BUILTINS_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADER_SM_BUILTINS_SPEC_VERSION } ] - "SPV_EXT_fragment_shader_interlock" -> + "SPV_EXT_fragment_shader_interlock" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION } ] - "SPV_EXT_demote_to_helper_invocation" -> + "SPV_EXT_demote_to_helper_invocation" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION } ] - "SPV_KHR_fragment_shading_rate" -> + "SPV_KHR_fragment_shading_rate" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION } @@ -588,296 +638,338 @@ spirvExtensionRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE2_SPEC_VERSION } ] - "SPV_KHR_non_semantic_info" -> + "SPV_KHR_non_semantic_info" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION } ] - "SPV_EXT_shader_image_int64" -> + "SPV_EXT_shader_image_int64" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION } ] - "SPV_KHR_terminate_invocation" -> + "SPV_KHR_terminate_invocation" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION } ] - _ -> [] + _ -> ([], []) -spirvCapabilityRequirements :: ByteString -> [Requirement] +spirvCapabilityRequirements :: ByteString -> ([Requirement Instance], [Requirement PhysicalDevice]) spirvCapabilityRequirements = \case - "Matrix" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "Shader" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "InputAttachment" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "Sampled1D" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "Image1D" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "SampledBuffer" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "ImageBuffer" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "ImageQuery" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "DerivativeControl" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "Geometry" -> - [ RequireFeature { featureName = "geometryShader" - , checkFeature = geometryShader :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { geometryShader = True } :: PhysicalDeviceFeatures - } - ] - "Tessellation" -> - [ RequireFeature { featureName = "tessellationShader" - , checkFeature = tessellationShader :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { tessellationShader = True } :: PhysicalDeviceFeatures - } - ] - "Float64" -> - [ RequireFeature { featureName = "shaderFloat64" - , checkFeature = shaderFloat64 :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderFloat64 = True } :: PhysicalDeviceFeatures - } - ] - "Int64" -> - [ RequireFeature { featureName = "shaderInt64" - , checkFeature = shaderInt64 :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderInt64 = True } :: PhysicalDeviceFeatures - } - ] - "Int64Atomics" -> - [ RequireFeature { featureName = "shaderBufferInt64Atomics" - , checkFeature = shaderBufferInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderBufferInt64Atomics = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "Matrix" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "Shader" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "InputAttachment" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "Sampled1D" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "Image1D" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "SampledBuffer" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "ImageBuffer" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "ImageQuery" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "DerivativeControl" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "Geometry" -> (,) + [] + [ RequireDeviceFeature { featureName = "geometryShader" + , checkFeature = geometryShader :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { geometryShader = True } :: PhysicalDeviceFeatures + } + ] + "Tessellation" -> (,) + [] + [ RequireDeviceFeature { featureName = "tessellationShader" + , checkFeature = tessellationShader :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { tessellationShader = True } :: PhysicalDeviceFeatures + } + ] + "Float64" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderFloat64" + , checkFeature = shaderFloat64 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderFloat64 = True } :: PhysicalDeviceFeatures + } + ] + "Int64" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderInt64" + , checkFeature = shaderInt64 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderInt64 = True } :: PhysicalDeviceFeatures + } + ] + "Int64Atomics" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shaderBufferInt64Atomics" + , checkFeature = shaderBufferInt64Atomics :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderBufferInt64Atomics = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_ATOMIC_INT64_SPEC_VERSION } ] - "AtomicFloat32AddEXT" -> - [ RequireFeature + "AtomicFloat32AddEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderBufferFloat32AtomicAdd" , checkFeature = shaderBufferFloat32AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool , enableFeature = \f -> f { shaderBufferFloat32AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION } ] - "AtomicFloat64AddEXT" -> - [ RequireFeature + "AtomicFloat64AddEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderBufferFloat64AtomicAdd" , checkFeature = shaderBufferFloat64AtomicAdd :: PhysicalDeviceShaderAtomicFloatFeaturesEXT -> Bool , enableFeature = \f -> f { shaderBufferFloat64AtomicAdd = True } :: PhysicalDeviceShaderAtomicFloatFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_ATOMIC_FLOAT_SPEC_VERSION } ] - "Int64ImageEXT" -> - [ RequireFeature + "Int64ImageEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderImageInt64Atomics" , checkFeature = shaderImageInt64Atomics :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT -> Bool , enableFeature = \f -> f { shaderImageInt64Atomics = True } :: PhysicalDeviceShaderImageAtomicInt64FeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_IMAGE_ATOMIC_INT64_SPEC_VERSION } ] - "Int16" -> - [ RequireFeature { featureName = "shaderInt16" - , checkFeature = shaderInt16 :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderInt16 = True } :: PhysicalDeviceFeatures - } + "Int16" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderInt16" + , checkFeature = shaderInt16 :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderInt16 = True } :: PhysicalDeviceFeatures + } ] - "TessellationPointSize" -> - [ RequireFeature + "TessellationPointSize" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderTessellationAndGeometryPointSize" , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures } ] - "GeometryPointSize" -> - [ RequireFeature + "GeometryPointSize" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderTessellationAndGeometryPointSize" , checkFeature = shaderTessellationAndGeometryPointSize :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderTessellationAndGeometryPointSize = True } :: PhysicalDeviceFeatures } ] - "ImageGatherExtended" -> - [ RequireFeature { featureName = "shaderImageGatherExtended" - , checkFeature = shaderImageGatherExtended :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderImageGatherExtended = True } :: PhysicalDeviceFeatures - } - ] - "StorageImageMultisample" -> - [ RequireFeature { featureName = "shaderStorageImageMultisample" - , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures - } - ] - "UniformBufferArrayDynamicIndexing" -> - [ RequireFeature + "ImageGatherExtended" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderImageGatherExtended" + , checkFeature = shaderImageGatherExtended :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderImageGatherExtended = True } :: PhysicalDeviceFeatures + } + ] + "StorageImageMultisample" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderStorageImageMultisample" + , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures + } + ] + "UniformBufferArrayDynamicIndexing" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderUniformBufferArrayDynamicIndexing" , checkFeature = shaderUniformBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderUniformBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] - "SampledImageArrayDynamicIndexing" -> - [ RequireFeature + "SampledImageArrayDynamicIndexing" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderSampledImageArrayDynamicIndexing" , checkFeature = shaderSampledImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderSampledImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] - "StorageBufferArrayDynamicIndexing" -> - [ RequireFeature + "StorageBufferArrayDynamicIndexing" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderStorageBufferArrayDynamicIndexing" , checkFeature = shaderStorageBufferArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderStorageBufferArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] - "StorageImageArrayDynamicIndexing" -> - [ RequireFeature + "StorageImageArrayDynamicIndexing" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderStorageImageArrayDynamicIndexing" , checkFeature = shaderStorageImageArrayDynamicIndexing :: PhysicalDeviceFeatures -> Bool , enableFeature = \f -> f { shaderStorageImageArrayDynamicIndexing = True } :: PhysicalDeviceFeatures } ] - "ClipDistance" -> - [ RequireFeature { featureName = "shaderClipDistance" - , checkFeature = shaderClipDistance :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderClipDistance = True } :: PhysicalDeviceFeatures - } - ] - "CullDistance" -> - [ RequireFeature { featureName = "shaderCullDistance" - , checkFeature = shaderCullDistance :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderCullDistance = True } :: PhysicalDeviceFeatures - } - ] - "ImageCubeArray" -> - [ RequireFeature { featureName = "imageCubeArray" - , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures - } - ] - "SampleRateShading" -> - [ RequireFeature { featureName = "sampleRateShading" - , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures - } - ] - "SparseResidency" -> - [ RequireFeature { featureName = "shaderResourceResidency" - , checkFeature = shaderResourceResidency :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderResourceResidency = True } :: PhysicalDeviceFeatures - } - ] - "MinLod" -> - [ RequireFeature { featureName = "shaderResourceMinLod" - , checkFeature = shaderResourceMinLod :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderResourceMinLod = True } :: PhysicalDeviceFeatures - } - ] - "SampledCubeArray" -> - [ RequireFeature { featureName = "imageCubeArray" - , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures - } - ] - "ImageMSArray" -> - [ RequireFeature { featureName = "shaderStorageImageMultisample" - , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures - } - ] - "StorageImageExtendedFormats" -> [RequireVersion $ MAKE_VERSION 1 0 0] - "InterpolationFunction" -> - [ RequireFeature { featureName = "sampleRateShading" - , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures - } - ] - "StorageImageReadWithoutFormat" -> - [ RequireFeature { featureName = "shaderStorageImageReadWithoutFormat" - , checkFeature = shaderStorageImageReadWithoutFormat :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageReadWithoutFormat = True } :: PhysicalDeviceFeatures - } - ] - "StorageImageWriteWithoutFormat" -> - [ RequireFeature { featureName = "shaderStorageImageWriteWithoutFormat" - , checkFeature = shaderStorageImageWriteWithoutFormat :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { shaderStorageImageWriteWithoutFormat = True } :: PhysicalDeviceFeatures - } - ] - "MultiViewport" -> - [ RequireFeature { featureName = "multiViewport" - , checkFeature = multiViewport :: PhysicalDeviceFeatures -> Bool - , enableFeature = \f -> f { multiViewport = True } :: PhysicalDeviceFeatures - } - ] - "DrawParameters" -> - [ RequireFeature { featureName = "shaderDrawParameters" - , checkFeature = shaderDrawParameters :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { shaderDrawParameters = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 - ] - "MultiView" -> - [ RequireFeature { featureName = "multiview" - , checkFeature = multiview :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { multiview = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "ClipDistance" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderClipDistance" + , checkFeature = shaderClipDistance :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderClipDistance = True } :: PhysicalDeviceFeatures + } + ] + "CullDistance" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderCullDistance" + , checkFeature = shaderCullDistance :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderCullDistance = True } :: PhysicalDeviceFeatures + } + ] + "ImageCubeArray" -> (,) + [] + [ RequireDeviceFeature { featureName = "imageCubeArray" + , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures + } + ] + "SampleRateShading" -> (,) + [] + [ RequireDeviceFeature { featureName = "sampleRateShading" + , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures + } + ] + "SparseResidency" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderResourceResidency" + , checkFeature = shaderResourceResidency :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderResourceResidency = True } :: PhysicalDeviceFeatures + } + ] + "MinLod" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderResourceMinLod" + , checkFeature = shaderResourceMinLod :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderResourceMinLod = True } :: PhysicalDeviceFeatures + } + ] + "SampledCubeArray" -> (,) + [] + [ RequireDeviceFeature { featureName = "imageCubeArray" + , checkFeature = imageCubeArray :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { imageCubeArray = True } :: PhysicalDeviceFeatures + } + ] + "ImageMSArray" -> (,) + [] + [ RequireDeviceFeature { featureName = "shaderStorageImageMultisample" + , checkFeature = shaderStorageImageMultisample :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageMultisample = True } :: PhysicalDeviceFeatures + } + ] + "StorageImageExtendedFormats" -> + (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] + "InterpolationFunction" -> (,) + [] + [ RequireDeviceFeature { featureName = "sampleRateShading" + , checkFeature = sampleRateShading :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { sampleRateShading = True } :: PhysicalDeviceFeatures + } + ] + "StorageImageReadWithoutFormat" -> (,) + [] + [ RequireDeviceFeature + { featureName = "shaderStorageImageReadWithoutFormat" + , checkFeature = shaderStorageImageReadWithoutFormat :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageReadWithoutFormat = True } :: PhysicalDeviceFeatures + } + ] + "StorageImageWriteWithoutFormat" -> (,) + [] + [ RequireDeviceFeature + { featureName = "shaderStorageImageWriteWithoutFormat" + , checkFeature = shaderStorageImageWriteWithoutFormat :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { shaderStorageImageWriteWithoutFormat = True } :: PhysicalDeviceFeatures + } + ] + "MultiViewport" -> (,) + [] + [ RequireDeviceFeature { featureName = "multiViewport" + , checkFeature = multiViewport :: PhysicalDeviceFeatures -> Bool + , enableFeature = \f -> f { multiViewport = True } :: PhysicalDeviceFeatures + } + ] + "DrawParameters" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceFeature { featureName = "shaderDrawParameters" + , checkFeature = shaderDrawParameters :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { shaderDrawParameters = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 + ] + "MultiView" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "multiview" + , checkFeature = multiview :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { multiview = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_MULTIVIEW_EXTENSION_NAME , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION } ] - "DeviceGroup" -> [RequireVersion $ MAKE_VERSION 1 1 0] - "VariablePointersStorageBuffer" -> - [ RequireFeature - { featureName = "variablePointersStorageBuffer" - , checkFeature = variablePointersStorageBuffer :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { variablePointersStorageBuffer = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "DeviceGroup" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 1 0] [RequireDeviceVersion $ MAKE_VERSION 1 1 0] + "VariablePointersStorageBuffer" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "variablePointersStorageBuffer" + , checkFeature = variablePointersStorageBuffer :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { variablePointersStorageBuffer = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_VARIABLE_POINTERS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_VARIABLE_POINTERS_SPEC_VERSION @@ -887,16 +979,18 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "VariablePointers" -> - [ RequireFeature { featureName = "variablePointers" - , checkFeature = variablePointers :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { variablePointers = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "VariablePointers" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "variablePointers" + , checkFeature = variablePointers :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { variablePointers = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_VARIABLE_POINTERS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_VARIABLE_POINTERS_SPEC_VERSION @@ -906,106 +1000,122 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "ShaderClockKHR" -> + "ShaderClockKHR" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_CLOCK_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_CLOCK_SPEC_VERSION } ] - "StencilExportEXT" -> + "StencilExportEXT" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION } ] - "SubgroupBallotKHR" -> + "SubgroupBallotKHR" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION } ] - "SubgroupVoteKHR" -> + "SubgroupVoteKHR" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION } ] - "ImageReadWriteLodAMD" -> + "ImageReadWriteLodAMD" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_IMAGE_LOAD_STORE_LOD_SPEC_VERSION } ] - "ImageGatherBiasLodAMD" -> + "ImageGatherBiasLodAMD" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME , deviceExtensionMinVersion = AMD_TEXTURE_GATHER_BIAS_LOD_SPEC_VERSION } ] - "FragmentMaskAMD" -> + "FragmentMaskAMD" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME , deviceExtensionMinVersion = AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION } ] - "SampleMaskOverrideCoverageNV" -> + "SampleMaskOverrideCoverageNV" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME , deviceExtensionMinVersion = NV_SAMPLE_MASK_OVERRIDE_COVERAGE_SPEC_VERSION } ] - "GeometryShaderPassthroughNV" -> + "GeometryShaderPassthroughNV" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME , deviceExtensionMinVersion = NV_GEOMETRY_SHADER_PASSTHROUGH_SPEC_VERSION } ] - "ShaderViewportIndex" -> - [ RequireFeature { featureName = "shaderOutputViewportIndex" - , checkFeature = shaderOutputViewportIndex :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderOutputViewportIndex = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 - ] - "ShaderLayer" -> - [ RequireFeature { featureName = "shaderOutputLayer" - , checkFeature = shaderOutputLayer :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderOutputLayer = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 - ] - "ShaderViewportIndexLayerEXT" -> + "ShaderViewportIndex" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 2 0] + [ RequireDeviceFeature + { featureName = "shaderOutputViewportIndex" + , checkFeature = shaderOutputViewportIndex :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderOutputViewportIndex = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 + ] + "ShaderLayer" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 2 0] + [ RequireDeviceFeature { featureName = "shaderOutputLayer" + , checkFeature = shaderOutputLayer :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderOutputLayer = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 + ] + "ShaderViewportIndexLayerEXT" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_VIEWPORT_INDEX_LAYER_SPEC_VERSION } ] - "ShaderViewportIndexLayerNV" -> + "ShaderViewportIndexLayerNV" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_VIEWPORT_ARRAY2_EXTENSION_NAME , deviceExtensionMinVersion = NV_VIEWPORT_ARRAY2_SPEC_VERSION } ] - "ShaderViewportMaskNV" -> + "ShaderViewportMaskNV" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_VIEWPORT_ARRAY2_EXTENSION_NAME , deviceExtensionMinVersion = NV_VIEWPORT_ARRAY2_SPEC_VERSION } ] - "PerViewAttributesNV" -> + "PerViewAttributesNV" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME , deviceExtensionMinVersion = NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION } @@ -1014,16 +1124,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MULTIVIEW_SPEC_VERSION } ] - "StorageBuffer16BitAccess" -> - [ RequireFeature { featureName = "storageBuffer16BitAccess" - , checkFeature = storageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { storageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "StorageBuffer16BitAccess" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "storageBuffer16BitAccess" + , checkFeature = storageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION @@ -1033,17 +1146,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "UniformAndStorageBuffer16BitAccess" -> - [ RequireFeature - { featureName = "uniformAndStorageBuffer16BitAccess" - , checkFeature = uniformAndStorageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { uniformAndStorageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "UniformAndStorageBuffer16BitAccess" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "uniformAndStorageBuffer16BitAccess" + , checkFeature = uniformAndStorageBuffer16BitAccess :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { uniformAndStorageBuffer16BitAccess = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION @@ -1053,16 +1168,18 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "StoragePushConstant16" -> - [ RequireFeature { featureName = "storagePushConstant16" - , checkFeature = storagePushConstant16 :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { storagePushConstant16 = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "StoragePushConstant16" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "storagePushConstant16" + , checkFeature = storagePushConstant16 :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storagePushConstant16 = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION @@ -1072,16 +1189,18 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "StorageInputOutput16" -> - [ RequireFeature { featureName = "storageInputOutput16" - , checkFeature = storageInputOutput16 :: PhysicalDeviceVulkan11Features -> Bool - , enableFeature = \f -> f { storageInputOutput16 = True } :: PhysicalDeviceVulkan11Features - } - , RequireVersion $ MAKE_VERSION 1 1 0 + "StorageInputOutput16" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 1 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "storageInputOutput16" + , checkFeature = storageInputOutput16 :: PhysicalDeviceVulkan11Features -> Bool + , enableFeature = \f -> f { storageInputOutput16 = True } :: PhysicalDeviceVulkan11Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_16BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_16BIT_STORAGE_SPEC_VERSION @@ -1091,72 +1210,81 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "GroupNonUniform" -> - [ RequireProperty + "GroupNonUniform" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_BASIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformVote" -> - [ RequireProperty + "GroupNonUniformVote" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_VOTE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformArithmetic" -> - [ RequireProperty + "GroupNonUniformArithmetic" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_ARITHMETIC_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformBallot" -> - [ RequireProperty + "GroupNonUniformBallot" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_BALLOT_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformShuffle" -> - [ RequireProperty + "GroupNonUniformShuffle" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_SHUFFLE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformShuffleRelative" -> - [ RequireProperty + "GroupNonUniformShuffleRelative" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformClustered" -> - [ RequireProperty + "GroupNonUniformClustered" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_CLUSTERED_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformQuad" -> - [ RequireProperty + "GroupNonUniformQuad" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 1 0] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_QUAD_BIT .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) } - , RequireVersion $ MAKE_VERSION 1 1 0 + , RequireDeviceVersion $ MAKE_VERSION 1 1 0 ] - "GroupNonUniformPartitionedNV" -> - [ RequireProperty + "GroupNonUniformPartitionedNV" -> (,) + [] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan11Properties" , checkProperty = \p -> SUBGROUP_FEATURE_PARTITIONED_BIT_NV .&&. subgroupSupportedOperations (p :: PhysicalDeviceVulkan11Properties) @@ -1166,23 +1294,26 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION } ] - "SampleMaskPostDepthCoverage" -> + "SampleMaskPostDepthCoverage" -> (,) + [] [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_POST_DEPTH_COVERAGE_EXTENSION_NAME , deviceExtensionMinVersion = EXT_POST_DEPTH_COVERAGE_SPEC_VERSION } ] - "ShaderNonUniform" -> [RequireVersion $ MAKE_VERSION 1 2 0] - "RuntimeDescriptorArray" -> - [ RequireFeature { featureName = "runtimeDescriptorArray" - , checkFeature = runtimeDescriptorArray :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { runtimeDescriptorArray = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "ShaderNonUniform" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 2 0] [RequireDeviceVersion $ MAKE_VERSION 1 2 0] + "RuntimeDescriptorArray" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "runtimeDescriptorArray" + , checkFeature = runtimeDescriptorArray :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { runtimeDescriptorArray = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1192,17 +1323,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "InputAttachmentArrayDynamicIndexing" -> - [ RequireFeature - { featureName = "shaderInputAttachmentArrayDynamicIndexing" - , checkFeature = shaderInputAttachmentArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderInputAttachmentArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "InputAttachmentArrayDynamicIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shaderInputAttachmentArrayDynamicIndexing" + , checkFeature = shaderInputAttachmentArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderInputAttachmentArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1212,18 +1345,20 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "UniformTexelBufferArrayDynamicIndexing" -> - [ RequireFeature + "UniformTexelBufferArrayDynamicIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderUniformTexelBufferArrayDynamicIndexing" , checkFeature = shaderUniformTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { shaderUniformTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features } - , RequireVersion $ MAKE_VERSION 1 2 0 - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1233,18 +1368,20 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "StorageTexelBufferArrayDynamicIndexing" -> - [ RequireFeature + "StorageTexelBufferArrayDynamicIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderStorageTexelBufferArrayDynamicIndexing" , checkFeature = shaderStorageTexelBufferArrayDynamicIndexing :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { shaderStorageTexelBufferArrayDynamicIndexing = True } :: PhysicalDeviceVulkan12Features } - , RequireVersion $ MAKE_VERSION 1 2 0 - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1254,17 +1391,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "UniformBufferArrayNonUniformIndexing" -> - [ RequireFeature - { featureName = "shaderUniformBufferArrayNonUniformIndexing" - , checkFeature = shaderUniformBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderUniformBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "UniformBufferArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shaderUniformBufferArrayNonUniformIndexing" + , checkFeature = shaderUniformBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderUniformBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1274,17 +1413,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "SampledImageArrayNonUniformIndexing" -> - [ RequireFeature - { featureName = "shaderSampledImageArrayNonUniformIndexing" - , checkFeature = shaderSampledImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderSampledImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "SampledImageArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shaderSampledImageArrayNonUniformIndexing" + , checkFeature = shaderSampledImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderSampledImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1294,17 +1435,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "StorageBufferArrayNonUniformIndexing" -> - [ RequireFeature - { featureName = "shaderStorageBufferArrayNonUniformIndexing" - , checkFeature = shaderStorageBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderStorageBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "StorageBufferArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shaderStorageBufferArrayNonUniformIndexing" + , checkFeature = shaderStorageBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderStorageBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1314,17 +1457,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "StorageImageArrayNonUniformIndexing" -> - [ RequireFeature - { featureName = "shaderStorageImageArrayNonUniformIndexing" - , checkFeature = shaderStorageImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderStorageImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "StorageImageArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shaderStorageImageArrayNonUniformIndexing" + , checkFeature = shaderStorageImageArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderStorageImageArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1334,18 +1479,20 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "InputAttachmentArrayNonUniformIndexing" -> - [ RequireFeature + "InputAttachmentArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderInputAttachmentArrayNonUniformIndexing" , checkFeature = shaderInputAttachmentArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { shaderInputAttachmentArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features } - , RequireVersion $ MAKE_VERSION 1 2 0 - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1355,18 +1502,20 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "UniformTexelBufferArrayNonUniformIndexing" -> - [ RequireFeature + "UniformTexelBufferArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderUniformTexelBufferArrayNonUniformIndexing" , checkFeature = shaderUniformTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { shaderUniformTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features } - , RequireVersion $ MAKE_VERSION 1 2 0 - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1376,18 +1525,20 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "StorageTexelBufferArrayNonUniformIndexing" -> - [ RequireFeature + "StorageTexelBufferArrayNonUniformIndexing" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 + , RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderStorageTexelBufferArrayNonUniformIndexing" , checkFeature = shaderStorageTexelBufferArrayNonUniformIndexing :: PhysicalDeviceVulkan12Features -> Bool , enableFeature = \f -> f { shaderStorageTexelBufferArrayNonUniformIndexing = True } :: PhysicalDeviceVulkan12Features } - , RequireVersion $ MAKE_VERSION 1 2 0 - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME , deviceExtensionMinVersion = EXT_DESCRIPTOR_INDEXING_SPEC_VERSION @@ -1397,46 +1548,53 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "Float16" -> - [ RequireFeature { featureName = "shaderFloat16" - , checkFeature = shaderFloat16 :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderFloat16 = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "Float16" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "shaderFloat16" + , checkFeature = shaderFloat16 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderFloat16 = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT16_INT8_SPEC_VERSION } ] - "Int8" -> - [ RequireFeature { featureName = "shaderInt8" - , checkFeature = shaderInt8 :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { shaderInt8 = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "Int8" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "shaderInt8" + , checkFeature = shaderInt8 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { shaderInt8 = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT16_INT8_SPEC_VERSION } ] - "StorageBuffer8BitAccess" -> - [ RequireFeature { featureName = "storageBuffer8BitAccess" - , checkFeature = storageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { storageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "StorageBuffer8BitAccess" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "storageBuffer8BitAccess" + , checkFeature = storageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { storageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_8BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_8BIT_STORAGE_SPEC_VERSION @@ -1446,17 +1604,19 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "UniformAndStorageBuffer8BitAccess" -> - [ RequireFeature - { featureName = "uniformAndStorageBuffer8BitAccess" - , checkFeature = uniformAndStorageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { uniformAndStorageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "UniformAndStorageBuffer8BitAccess" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "uniformAndStorageBuffer8BitAccess" + , checkFeature = uniformAndStorageBuffer8BitAccess :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { uniformAndStorageBuffer8BitAccess = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_8BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_8BIT_STORAGE_SPEC_VERSION @@ -1466,16 +1626,18 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "StoragePushConstant8" -> - [ RequireFeature { featureName = "storagePushConstant8" - , checkFeature = storagePushConstant8 :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { storagePushConstant8 = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "StoragePushConstant8" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "storagePushConstant8" + , checkFeature = storagePushConstant8 :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { storagePushConstant8 = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_8BIT_STORAGE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_8BIT_STORAGE_SPEC_VERSION @@ -1485,195 +1647,218 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_STORAGE_BUFFER_STORAGE_CLASS_SPEC_VERSION } ] - "VulkanMemoryModel" -> - [ RequireFeature { featureName = "vulkanMemoryModel" - , checkFeature = vulkanMemoryModel :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { vulkanMemoryModel = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "VulkanMemoryModel" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 2 0] + [ RequireDeviceFeature { featureName = "vulkanMemoryModel" + , checkFeature = vulkanMemoryModel :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { vulkanMemoryModel = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME , deviceExtensionMinVersion = KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION } ] - "VulkanMemoryModelDeviceScope" -> - [ RequireFeature { featureName = "vulkanMemoryModelDeviceScope" - , checkFeature = vulkanMemoryModelDeviceScope :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { vulkanMemoryModelDeviceScope = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "VulkanMemoryModelDeviceScope" -> (,) + [RequireInstanceVersion $ MAKE_VERSION 1 2 0] + [ RequireDeviceFeature + { featureName = "vulkanMemoryModelDeviceScope" + , checkFeature = vulkanMemoryModelDeviceScope :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { vulkanMemoryModelDeviceScope = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME , deviceExtensionMinVersion = KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION } ] - "DenormPreserve" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "DenormPreserve" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } ] - "DenormFlushToZero" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderDenormFlushToZeroFloat16 (p :: PhysicalDeviceVulkan12Properties) - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "DenormFlushToZero" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceProperty + { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderDenormFlushToZeroFloat16 (p :: PhysicalDeviceVulkan12Properties) + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } ] - "SignedZeroInfNanPreserve" -> - [ RequireProperty - { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "SignedZeroInfNanPreserve" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceProperty + { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderSignedZeroInfNanPreserveFloat16 (p :: PhysicalDeviceVulkan12Properties) + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } ] - "RoundingModeRTE" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTEFloat16 (p :: PhysicalDeviceVulkan12Properties) - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "RoundingModeRTE" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTEFloat16 (p :: PhysicalDeviceVulkan12Properties) + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } ] - "RoundingModeRTZ" -> - [ RequireProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" - , checkProperty = \p -> shaderRoundingModeRTZFloat16 (p :: PhysicalDeviceVulkan12Properties) - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "RoundingModeRTZ" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceProperty { propertyName = "VkPhysicalDeviceVulkan12Properties" + , checkProperty = \p -> shaderRoundingModeRTZFloat16 (p :: PhysicalDeviceVulkan12Properties) + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION } ] - "ComputeDerivativeGroupQuadsNV" -> - [ RequireFeature + "ComputeDerivativeGroupQuadsNV" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "computeDerivativeGroupQuads" , checkFeature = computeDerivativeGroupQuads :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool , enableFeature = \f -> f { computeDerivativeGroupQuads = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME , deviceExtensionMinVersion = NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION } ] - "ComputeDerivativeGroupLinearNV" -> - [ RequireFeature + "ComputeDerivativeGroupLinearNV" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "computeDerivativeGroupLinear" , checkFeature = computeDerivativeGroupLinear :: PhysicalDeviceComputeShaderDerivativesFeaturesNV -> Bool , enableFeature = \f -> f { computeDerivativeGroupLinear = True } :: PhysicalDeviceComputeShaderDerivativesFeaturesNV } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME , deviceExtensionMinVersion = NV_COMPUTE_SHADER_DERIVATIVES_SPEC_VERSION } ] - "FragmentBarycentricNV" -> - [ RequireFeature + "FragmentBarycentricNV" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "fragmentShaderBarycentric" , checkFeature = fragmentShaderBarycentric :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV -> Bool , enableFeature = \f -> f { fragmentShaderBarycentric = True } :: PhysicalDeviceFragmentShaderBarycentricFeaturesNV } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME , deviceExtensionMinVersion = NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION } ] - "ImageFootprintNV" -> - [ RequireFeature { featureName = "imageFootprint" - , checkFeature = imageFootprint :: PhysicalDeviceShaderImageFootprintFeaturesNV -> Bool - , enableFeature = \f -> f { imageFootprint = True } :: PhysicalDeviceShaderImageFootprintFeaturesNV - } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing + "ImageFootprintNV" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "imageFootprint" + , checkFeature = imageFootprint :: PhysicalDeviceShaderImageFootprintFeaturesNV -> Bool + , enableFeature = \f -> f { imageFootprint = True } :: PhysicalDeviceShaderImageFootprintFeaturesNV + } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADER_IMAGE_FOOTPRINT_SPEC_VERSION } ] - "ShadingRateNV" -> - [ RequireFeature { featureName = "shadingRateImage" - , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool - , enableFeature = \f -> f { shadingRateImage = True } :: PhysicalDeviceShadingRateImageFeaturesNV - } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing + "ShadingRateNV" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "shadingRateImage" + , checkFeature = shadingRateImage :: PhysicalDeviceShadingRateImageFeaturesNV -> Bool + , enableFeature = \f -> f { shadingRateImage = True } :: PhysicalDeviceShadingRateImageFeaturesNV + } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADING_RATE_IMAGE_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADING_RATE_IMAGE_SPEC_VERSION } ] - "MeshShadingNV" -> + "MeshShadingNV" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_MESH_SHADER_EXTENSION_NAME , deviceExtensionMinVersion = NV_MESH_SHADER_SPEC_VERSION } ] - "RayTracingKHR" -> - [ RequireFeature + "RayTracingKHR" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "rayTracingPipeline" , checkFeature = rayTracingPipeline :: PhysicalDeviceRayTracingPipelineFeaturesKHR -> Bool , enableFeature = \f -> f { rayTracingPipeline = True } :: PhysicalDeviceRayTracingPipelineFeaturesKHR } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_RAY_TRACING_PIPELINE_SPEC_VERSION @@ -1707,15 +1892,16 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "RayQueryKHR" -> - [ RequireFeature { featureName = "rayQuery" - , checkFeature = rayQuery :: PhysicalDeviceRayQueryFeaturesKHR -> Bool - , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayQueryFeaturesKHR - } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing + "RayQueryKHR" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "rayQuery" + , checkFeature = rayQuery :: PhysicalDeviceRayQueryFeaturesKHR -> Bool + , enableFeature = \f -> f { rayQuery = True } :: PhysicalDeviceRayQueryFeaturesKHR + } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_RAY_QUERY_EXTENSION_NAME , deviceExtensionMinVersion = KHR_RAY_QUERY_SPEC_VERSION @@ -1749,16 +1935,17 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "RayTraversalPrimitiveCullingKHR" -> - [ RequireFeature + "RayTraversalPrimitiveCullingKHR" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "rayTraversalPrimitiveCulling" , checkFeature = rayTraversalPrimitiveCulling :: PhysicalDeviceRayTracingPipelineFeaturesKHR -> Bool , enableFeature = \f -> f { rayTraversalPrimitiveCulling = True } :: PhysicalDeviceRayTracingPipelineFeaturesKHR } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_RAY_TRACING_PIPELINE_SPEC_VERSION @@ -1792,12 +1979,13 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE3_SPEC_VERSION } ] - "RayTracingNV" -> + "RayTracingNV" -> (,) [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } - , RequireDeviceExtension { deviceExtensionLayerName = Nothing + ] + [ RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_RAY_TRACING_EXTENSION_NAME , deviceExtensionMinVersion = NV_RAY_TRACING_SPEC_VERSION } @@ -1806,178 +1994,194 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION } ] - "TransformFeedback" -> - [ RequireFeature + "TransformFeedback" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "transformFeedback" , checkFeature = transformFeedback :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool , enableFeature = \f -> f { transformFeedback = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME , deviceExtensionMinVersion = EXT_TRANSFORM_FEEDBACK_SPEC_VERSION } ] - "GeometryStreams" -> - [ RequireFeature { featureName = "geometryStreams" - , checkFeature = geometryStreams :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool - , enableFeature = \f -> f { geometryStreams = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT - } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing + "GeometryStreams" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "geometryStreams" + , checkFeature = geometryStreams :: PhysicalDeviceTransformFeedbackFeaturesEXT -> Bool + , enableFeature = \f -> f { geometryStreams = True } :: PhysicalDeviceTransformFeedbackFeaturesEXT + } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME , deviceExtensionMinVersion = EXT_TRANSFORM_FEEDBACK_SPEC_VERSION } ] - "FragmentDensityEXT" -> - [ RequireFeature + "FragmentDensityEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "fragmentDensityMap" , checkFeature = fragmentDensityMap :: PhysicalDeviceFragmentDensityMapFeaturesEXT -> Bool , enableFeature = \f -> f { fragmentDensityMap = True } :: PhysicalDeviceFragmentDensityMapFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME , deviceExtensionMinVersion = EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION } ] - "PhysicalStorageBufferAddresses" -> - [ RequireFeature { featureName = "bufferDeviceAddress" - , checkFeature = bufferDeviceAddress :: PhysicalDeviceVulkan12Features -> Bool - , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceVulkan12Features - } - , RequireVersion $ MAKE_VERSION 1 2 0 + "PhysicalStorageBufferAddresses" -> (,) + [ RequireInstanceVersion $ MAKE_VERSION 1 2 0 , RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature { featureName = "bufferDeviceAddress" + , checkFeature = bufferDeviceAddress :: PhysicalDeviceVulkan12Features -> Bool + , enableFeature = \f -> f { bufferDeviceAddress = True } :: PhysicalDeviceVulkan12Features + } + , RequireDeviceVersion $ MAKE_VERSION 1 2 0 , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME , deviceExtensionMinVersion = KHR_BUFFER_DEVICE_ADDRESS_SPEC_VERSION } ] - "CooperativeMatrixNV" -> - [ RequireFeature { featureName = "cooperativeMatrix" - , checkFeature = cooperativeMatrix :: PhysicalDeviceCooperativeMatrixFeaturesNV -> Bool - , enableFeature = \f -> f { cooperativeMatrix = True } :: PhysicalDeviceCooperativeMatrixFeaturesNV - } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing + "CooperativeMatrixNV" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION } + ] + [ RequireDeviceFeature + { featureName = "cooperativeMatrix" + , checkFeature = cooperativeMatrix :: PhysicalDeviceCooperativeMatrixFeaturesNV -> Bool + , enableFeature = \f -> f { cooperativeMatrix = True } :: PhysicalDeviceCooperativeMatrixFeaturesNV + } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_COOPERATIVE_MATRIX_EXTENSION_NAME , deviceExtensionMinVersion = NV_COOPERATIVE_MATRIX_SPEC_VERSION } ] - "IntegerFunctions2INTEL" -> - [ RequireFeature + "IntegerFunctions2INTEL" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderIntegerFunctions2" , checkFeature = shaderIntegerFunctions2 :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL -> Bool , enableFeature = \f -> f { shaderIntegerFunctions2 = True } :: PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME , deviceExtensionMinVersion = INTEL_SHADER_INTEGER_FUNCTIONS_2_SPEC_VERSION } ] - "ShaderSMBuiltinsNV" -> - [ RequireFeature { featureName = "shaderSMBuiltins" - , checkFeature = shaderSMBuiltins :: PhysicalDeviceShaderSMBuiltinsFeaturesNV -> Bool - , enableFeature = \f -> f { shaderSMBuiltins = True } :: PhysicalDeviceShaderSMBuiltinsFeaturesNV - } + "ShaderSMBuiltinsNV" -> (,) + [] + [ RequireDeviceFeature + { featureName = "shaderSMBuiltins" + , checkFeature = shaderSMBuiltins :: PhysicalDeviceShaderSMBuiltinsFeaturesNV -> Bool + , enableFeature = \f -> f { shaderSMBuiltins = True } :: PhysicalDeviceShaderSMBuiltinsFeaturesNV + } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = NV_SHADER_SM_BUILTINS_EXTENSION_NAME , deviceExtensionMinVersion = NV_SHADER_SM_BUILTINS_SPEC_VERSION } ] - "FragmentShaderSampleInterlockEXT" -> - [ RequireFeature + "FragmentShaderSampleInterlockEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "fragmentShaderSampleInterlock" , checkFeature = fragmentShaderSampleInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool , enableFeature = \f -> f { fragmentShaderSampleInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION } ] - "FragmentShaderPixelInterlockEXT" -> - [ RequireFeature + "FragmentShaderPixelInterlockEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "fragmentShaderPixelInterlock" , checkFeature = fragmentShaderPixelInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool , enableFeature = \f -> f { fragmentShaderPixelInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION } ] - "FragmentShaderShadingRateInterlockEXT" -> - [ RequireFeature + "FragmentShaderShadingRateInterlockEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "fragmentShaderShadingRateInterlock" , checkFeature = fragmentShaderShadingRateInterlock :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT -> Bool , enableFeature = \f -> f { fragmentShaderShadingRateInterlock = True } :: PhysicalDeviceFragmentShaderInterlockFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME , deviceExtensionMinVersion = EXT_FRAGMENT_SHADER_INTERLOCK_SPEC_VERSION } ] - "DemoteToHelperInvocationEXT" -> - [ RequireFeature + "DemoteToHelperInvocationEXT" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "shaderDemoteToHelperInvocation" , checkFeature = shaderDemoteToHelperInvocation :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT -> Bool , enableFeature = \f -> f { shaderDemoteToHelperInvocation = True } :: PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME , deviceExtensionMinVersion = EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION } ] - "FragmentShadingRateKHR" -> - [ RequireFeature + "FragmentShadingRateKHR" -> (,) + [ RequireInstanceExtension { instanceExtensionLayerName = Nothing + , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION + } + ] + [ RequireDeviceFeature { featureName = "pipelineFragmentShadingRate" , checkFeature = pipelineFragmentShadingRate :: PhysicalDeviceFragmentShadingRateFeaturesKHR -> Bool , enableFeature = \f -> f { pipelineFragmentShadingRate = True } :: PhysicalDeviceFragmentShadingRateFeaturesKHR } - , RequireInstanceExtension { instanceExtensionLayerName = Nothing - , instanceExtensionName = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME - , instanceExtensionMinVersion = KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION - } , RequireDeviceExtension { deviceExtensionLayerName = Nothing , deviceExtensionName = KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME , deviceExtensionMinVersion = KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION @@ -1995,5 +2199,5 @@ spirvCapabilityRequirements = \case , deviceExtensionMinVersion = KHR_MAINTENANCE2_SPEC_VERSION } ] - _ -> [] + _ -> ([], []) From e2bde1c1c5f91f67005bbe55dc4df73ec8659bea Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Thu, 26 Nov 2020 20:21:17 +0800 Subject: [PATCH 34/70] Simplify Requirement system - Split Requirement into DeviceRequirement and InstanceRequirement - Move non-essential functionality into `vulkan-utils` - `Vulkan.Requirements` -> `Vulkan.Requirement` as the `Requirements` type is gone. - Change types of device creation helpers --- changelog.md | 2 + generate-new/vk/VK/SPIRVElements.hs | 14 +- package.yaml | 1 - src-manual/Vulkan/Requirement.hs | 163 +++++++ src-manual/Vulkan/Requirements.hs | 539 ---------------------- src/Vulkan/SPIRVRequirements.hs | 8 +- utils/changelog.md | 5 + utils/package.yaml | 5 + utils/src/Vulkan/Utils/Initialization.hs | 437 +++++------------- utils/src/Vulkan/Utils/Internal.hs | 6 +- utils/src/Vulkan/Utils/Misc.hs | 9 +- utils/src/Vulkan/Utils/Requirements.hs | 554 +++++++++++++++++++++++ utils/vulkan-utils.cabal | 13 +- vulkan.cabal | 3 +- 14 files changed, 880 insertions(+), 879 deletions(-) create mode 100644 src-manual/Vulkan/Requirement.hs delete mode 100644 src-manual/Vulkan/Requirements.hs create mode 100644 utils/src/Vulkan/Utils/Requirements.hs diff --git a/changelog.md b/changelog.md index 123ebc0b7..27e36d293 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,8 @@ ## WIP +- Add `Vulkan.Requirement`, a module for specifying requirements for `Device`s + and `Instance`s - Expose SPIR-V Extensions and Capabilities in `Vulkan.SPIRVRequirements` - Squash some warnings diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs index 229125a98..6d2bd0a78 100644 --- a/generate-new/vk/VK/SPIRVElements.hs +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -83,10 +83,11 @@ renderSPIRVThing funName name reqs xs = do tellImport ''ByteString tellImport (TyConName "Instance") tellImport (TyConName "PhysicalDevice") - tellImport (mkName "Vulkan.Requirements.Requirement") + tellImportWithAll (mkName "Vulkan.Requirement.DeviceRequirement") + tellImportWithAll (mkName "Vulkan.Requirement.InstanceRequirement") tellExport (ETerm (TermName funName)) tellDoc $ vsep - [ pretty funName <+> ":: ByteString -> ([Requirement Instance], [Requirement PhysicalDevice])" + [ pretty funName <+> ":: ByteString -> ([InstanceRequirement], [DeviceRequirement])" , pretty funName <+> "= \\case" <> line <> indent 2 (vsep cases) ] @@ -101,7 +102,8 @@ renderReq = \case SPIRVReqFeature s f rs -> do RenderParams {..} <- input - tellImportWithAll (mkName "Vulkan.Requirements.Requirement") + tellImportWithAll (mkName "Vulkan.Requirement.DeviceRequirement") + tellImportWithAll (mkName "Vulkan.Requirement.InstanceRequirement") tellLanguageExtension (LanguageExtension "OverloadedLists") sTy <- cToHsType DoNotPreserve (TypeName s) -- TODO: this is pretty lazy, import the accessors properly @@ -128,7 +130,8 @@ renderReq = \case SPIRVReqProperty p m v rs -> do RenderParams {..} <- input - tellImportWithAll (mkName "Vulkan.Requirements.Requirement") + tellImportWithAll (mkName "Vulkan.Requirement.DeviceRequirement") + tellImportWithAll (mkName "Vulkan.Requirement.InstanceRequirement") tellLanguageExtension (LanguageExtension "OverloadedLists") -- TODO: this is pretty lazy, import the accessors properly sTy <- cToHsType DoNotPreserve (TypeName p) @@ -245,7 +248,8 @@ data RequireType versionReq :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc (), Doc()) versionReq v = do - tellImportWithAll (mkName "Vulkan.Requirements.Requirement") + tellImportWithAll (mkName "Vulkan.Requirement.DeviceRequirement") + tellImportWithAll (mkName "Vulkan.Requirement.InstanceRequirement") vDoc <- versionDoc v pure ( "RequireInstanceVersion $" <+> vDoc diff --git a/package.yaml b/package.yaml index f6aae3830..91fc0035d 100644 --- a/package.yaml +++ b/package.yaml @@ -20,7 +20,6 @@ library: - base <5 - bytestring - transformers - - unordered-containers - vector when: - condition: os(windows) diff --git a/src-manual/Vulkan/Requirement.hs b/src-manual/Vulkan/Requirement.hs new file mode 100644 index 000000000..0abfcdd52 --- /dev/null +++ b/src-manual/Vulkan/Requirement.hs @@ -0,0 +1,163 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DeriveTraversable #-} +{-# LANGUAGE DuplicateRecordFields #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE PolyKinds #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE Strict #-} +{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE UndecidableSuperClasses #-} + +module Vulkan.Requirement + ( -- * Vulkan requirements + InstanceRequirement(..) + , DeviceRequirement(..) + , -- * Utility functionality for handling structure chains + KnownFeatureStruct(..) + , KnownPropertyStruct(..) + , SFeatureStruct(..) + , SPropertyStruct(..) + ) where + +-- base +import Data.Typeable + ( Typeable ) +import Data.Word + ( Word32 ) + +-- bytestring +import Data.ByteString + ( ByteString ) + +-- vulkan +import Vulkan.Core10.Device + ( DeviceCreateInfo(..) + ) +import Vulkan.Core10.DeviceInitialization + ( PhysicalDeviceFeatures, PhysicalDeviceProperties + ) +import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 + ( PhysicalDeviceFeatures2(..), PhysicalDeviceProperties2(..) ) +import Vulkan.CStruct + ( FromCStruct, ToCStruct ) +import Vulkan.CStruct.Extends + ( Extends ) +import Vulkan.Zero + +---------------------------------------------------------------- +-- Instance Requirements +---------------------------------------------------------------- + +-- | A requirement on a Vulkan 'Instance'. +data InstanceRequirement where + -- | Require a minimum Vulkan instance version. + RequireInstanceVersion + :: { version :: Word32 } + -> InstanceRequirement + -- | Require a Vulkan layer. + RequireInstanceLayer + :: { instanceLayerName :: ByteString + , instanceLayerMinVersion :: Word32 + -- ^ The 'implementationVersion' of the layer must meet or exceed this + -- version + } + -> InstanceRequirement + -- | Require a Vulkan instance extension. + RequireInstanceExtension + :: { instanceExtensionLayerName :: Maybe ByteString + , instanceExtensionName :: ByteString + , instanceExtensionMinVersion :: Word32 + } + -> InstanceRequirement + +---------------------------------------------------------------- +-- Device Requirements +---------------------------------------------------------------- + +-- A requirement on a Vulkan 'PhysicalDevice'. +data DeviceRequirement where + -- | Require a minimum device version. + RequireDeviceVersion + :: { version :: Word32 } + -> DeviceRequirement + -- | Require a Vulkan physical device feature. + RequireDeviceFeature + :: forall struct + . KnownFeatureStruct struct + => { featureName :: ByteString + , checkFeature :: struct -> Bool + , enableFeature :: struct -> struct + } + -> DeviceRequirement + -- | Require a Vulkan physical device property. + RequireDeviceProperty + :: forall struct + . KnownPropertyStruct struct + => { propertyName :: ByteString + , checkProperty :: struct -> Bool + } + -> DeviceRequirement + -- | Require a Vulkan device extension. + RequireDeviceExtension + :: { deviceExtensionLayerName :: Maybe ByteString + , deviceExtensionName :: ByteString + , deviceExtensionMinVersion :: Word32 + } + -> DeviceRequirement + +-- | Singleton for a Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. +-- +-- It is either 'PhysicalDeviceFeatures', or it 'Extends' 'PhysicalDeviceFeatures2'. +data SFeatureStruct feat where + BasicFeatureStruct + :: SFeatureStruct PhysicalDeviceFeatures + ExtendedFeatureStruct + :: ( Show feat + , Extends PhysicalDeviceFeatures2 feat, Extends DeviceCreateInfo feat + , Zero feat, FromCStruct feat, ToCStruct feat + ) + => SFeatureStruct feat + +-- | A Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. +class Typeable feat => KnownFeatureStruct feat where + sFeatureStruct :: SFeatureStruct feat + +instance KnownFeatureStruct PhysicalDeviceFeatures where + sFeatureStruct = BasicFeatureStruct + +instance {-# OVERLAPPABLE #-} + ( Typeable feat, Show feat + , Extends PhysicalDeviceFeatures2 feat, Extends DeviceCreateInfo feat + , Zero feat, FromCStruct feat, ToCStruct feat + ) + => KnownFeatureStruct feat where + sFeatureStruct = ExtendedFeatureStruct + +-- | Singleton for a Vulkan structure that can appear in 'PhysicalDeviceProperties2'. +-- +-- It is either 'PhysicalDeviceProperties', or it 'Extends' 'PhysicalDeviceProperties2'. +data SPropertyStruct prop where + BasicPropertyStruct + :: SPropertyStruct PhysicalDeviceProperties + ExtendedPropertyStruct + :: ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) + => SPropertyStruct prop + +-- | A Vulkan structure that can appear in 'PhysicalDeviceProperties2'. +class Typeable prop => KnownPropertyStruct prop where + sPropertyStruct :: SPropertyStruct prop +instance KnownPropertyStruct PhysicalDeviceProperties where + sPropertyStruct = BasicPropertyStruct +instance {-# OVERLAPPABLE #-} + ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) + => KnownPropertyStruct prop where + sPropertyStruct = ExtendedPropertyStruct diff --git a/src-manual/Vulkan/Requirements.hs b/src-manual/Vulkan/Requirements.hs deleted file mode 100644 index 43437997c..000000000 --- a/src-manual/Vulkan/Requirements.hs +++ /dev/null @@ -1,539 +0,0 @@ -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE DerivingStrategies #-} -{-# LANGUAGE DeriveTraversable #-} -{-# LANGUAGE DuplicateRecordFields #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE MagicHash #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE PatternSynonyms #-} -{-# LANGUAGE PolyKinds #-} -{-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE Strict #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} -{-# LANGUAGE UndecidableSuperClasses #-} - -module Vulkan.Requirements - ( -- * Vulkan requirements - Requirement(..) - - -- * Requesting certain requirements - , Request(Require,Option,..) - , Requests(..), ReqAndOpt(..), KnownRequestTarget(..) - , addRequests, mkRequests - - -- * Utility functionality for handling structure chains - , SLength(..), KnownChain(..) -- TODO: move to Vulkan.CStruct.Extends - ) - where - --- base -import Control.Applicative - ( liftA2 ) -import Control.Arrow - ( Arrow(first,second,(***)) ) -import Control.Monad - ( unless ) -import Data.Foldable - ( foldl' ) -import Data.Kind - ( Type ) -import Data.Type.Equality - ( (:~:)(Refl) ) -import Data.Typeable - ( Typeable, eqT ) -import Data.Word - ( Word32 ) -import GHC.Exts - ( Proxy#, proxy# ) - --- bytestring -import Data.ByteString - ( ByteString ) - --- transformers -import Control.Monad.IO.Class - ( MonadIO ) - --- unordered-containers -import Data.HashMap.Strict - ( HashMap ) -import qualified Data.HashMap.Strict as HashMap - ( elems, empty, insertWith, keys, singleton, unionWith ) -import Data.HashSet - ( HashSet ) -import qualified Data.HashSet as HashSet - ( empty, insert, member, null ) - --- vector -import qualified Data.Vector as Boxed - ( Vector ) -import qualified Data.Vector as Boxed.Vector - ( fromList ) - --- vulkan -import Vulkan.Core10.Device - ( Device, DeviceCreateInfo(..), DeviceQueueCreateInfo - ) -import Vulkan.Core10.DeviceInitialization - ( AllocationCallbacks, ApplicationInfo(..), Instance, InstanceCreateInfo(..) - , PhysicalDevice, PhysicalDeviceFeatures, PhysicalDeviceProperties - ) -import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 - ( PhysicalDeviceFeatures2(..) ) -import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 - ( PhysicalDeviceProperties2(..) ) -import Vulkan.CStruct - ( FromCStruct, ToCStruct ) -import Vulkan.CStruct.Extends - ( Chain, Extends, Extendss, PeekChain, PokeChain, SomeStruct(..) ) -import Vulkan.Version - ( pattern MAKE_VERSION ) -import Vulkan.Zero - ( Zero(zero) ) - ----------------------------------------------------------------------------- --- Vulkan requirements. - --- | A Vulkan requirement, such as an 'Instance' layer or a 'PhysicalDevice' feature. -data family Requirement (t :: Type) --- | A requirement on a Vulkan 'Instance'. -data instance Requirement Instance where - -- | Require a minimum Vulkan instance version. - RequireInstanceVersion - :: { version :: Word32 } - -> Requirement Instance - -- | Require a Vulkan layer. - RequireInstanceLayer - :: { instanceLayerName :: ByteString - , instanceLayerMinVersion :: Word32 - -- | Specifying order in which to enable a layer. - -- Lower order: enabled first. - , instanceLayerOrder :: Int - } - -> Requirement Instance - -- | Require a Vulkan instance setting (e.g. a validation feature). - RequireInstanceSetting - :: forall struct - . KnownInstanceSettingStruct struct - => { -- | Specify a Vulkan structure that extends 'InstanceCreateInfo'. - instanceSetting :: struct - } - -> Requirement Instance - -- | Require a Vulkan instance extension. - RequireInstanceExtension - :: { instanceExtensionLayerName :: Maybe ByteString - , instanceExtensionName :: ByteString - , instanceExtensionMinVersion :: Word32 - } - -> Requirement Instance --- A requirement on a Vulkan 'PhysicalDevice'. -data instance Requirement PhysicalDevice where - -- | Require a minimum device version. - RequireDeviceVersion - :: { version :: Word32 } - -> Requirement PhysicalDevice - -- | Require a Vulkan physical device feature. - RequireDeviceFeature - :: forall struct - . KnownFeatureStruct struct - => { featureName :: ByteString - , checkFeature :: struct -> Bool - , enableFeature :: struct -> struct - } - -> Requirement PhysicalDevice - -- | Require a Vulkan physical device property. - RequireDeviceProperty - :: forall struct - . KnownPropertyStruct struct - => { propertyName :: ByteString - , checkProperty :: struct -> Bool - } - -> Requirement PhysicalDevice - -- | Require a Vulkan device extension. - RequireDeviceExtension - :: { deviceExtensionLayerName :: Maybe ByteString - , deviceExtensionName :: ByteString - , deviceExtensionMinVersion :: Word32 - } - -> Requirement PhysicalDevice - --- | A Vulkan structure that can appear in 'InstanceCreateInfo'. -class ( Typeable sett, Extends InstanceCreateInfo sett, Zero sett, FromCStruct sett, ToCStruct sett ) - => KnownInstanceSettingStruct sett where -instance ( Typeable sett, Extends InstanceCreateInfo sett, Zero sett, FromCStruct sett, ToCStruct sett ) - => KnownInstanceSettingStruct sett where - --- | Singleton for a Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. --- --- It is either 'PhysicalDeviceFeatures', or it 'Extends' 'PhysicalDeviceFeatures2'. -data SFeatureStruct feat where - BasicFeatureStruct - :: SFeatureStruct PhysicalDeviceFeatures - ExtendedFeatureStruct - :: ( Typeable feat - , Extends PhysicalDeviceFeatures2 feat, Extends DeviceCreateInfo feat - , Zero feat, FromCStruct feat, ToCStruct feat - ) - => SFeatureStruct feat --- | A Vulkan structure that can appear in 'PhysicalDeviceFeatures2'. -class KnownFeatureStruct feat where - sFeatureStruct :: SFeatureStruct feat -instance KnownFeatureStruct PhysicalDeviceFeatures where - sFeatureStruct = BasicFeatureStruct -instance {-# OVERLAPPABLE #-} - ( Typeable feat - , Extends PhysicalDeviceFeatures2 feat, Extends DeviceCreateInfo feat - , Zero feat, FromCStruct feat, ToCStruct feat - ) - => KnownFeatureStruct feat where - sFeatureStruct = ExtendedFeatureStruct - --- | Singleton for a Vulkan structure that can appear in 'PhysicalDeviceProperties2'. --- --- It is either 'PhysicalDeviceProperties', or it 'Extends' 'PhysicalDeviceProperties2'. -data SPropertyStruct prop where - BasicPropertyStruct - :: SPropertyStruct PhysicalDeviceProperties - ExtendedPropertyStruct - :: ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) - => SPropertyStruct prop --- | A Vulkan structure that can appear in 'PhysicalDeviceProperties2'. -class KnownPropertyStruct prop where - sPropertyStruct :: SPropertyStruct prop -instance KnownPropertyStruct PhysicalDeviceProperties where - sPropertyStruct = BasicPropertyStruct -instance {-# OVERLAPPABLE #-} - ( Typeable prop, Extends PhysicalDeviceProperties2 prop, FromCStruct prop, ToCStruct prop ) - => KnownPropertyStruct prop where - sPropertyStruct = ExtendedPropertyStruct - --- | Singleton allowing inspection of the length of a list. -data SLength (xs :: [Type]) where - SNil :: SLength '[] - SCons :: SLength xs -> SLength (x ': xs) - --- | Enough information to focus on any structure within a Vulkan structure chain. -class (PeekChain xs, PokeChain xs) => KnownChain (xs :: [Type]) where - sLength :: SLength xs - -- | If the given structure can be found within a chain, return a lens to it. - -- Otherwise, return 'Nothing'. - has :: forall a. Typeable a => Proxy# a -> Maybe (Chain xs -> a, (a -> a) -> (Chain xs -> Chain xs)) -instance KnownChain '[] where - sLength = SNil - has _ = Nothing -instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain (x ': xs) where - sLength = SCons (sLength @xs) - has (px :: Proxy# a) - | Just Refl <- eqT @a @x - = Just (fst,first) - | otherwise - = ((. snd) *** (second .)) <$> has px - ----------------------------------------------------------------------------- --- Requesting certain requirements. - --- | Request a Vulkan feature/extension/layer to be enabled (possibly optionally). -data Request t = Request { request :: Requirement t, requestIsOptional :: Bool } - -{-# COMPLETE Require, Option #-} -pattern Require, Option :: Requirement t -> Request t -pattern Require en = Request en False -pattern Option en = Request en True - --- | Keep track of required and optional terms of a given type. -data ReqAndOpt a = - ReqAndOpt - { req :: a - , opt :: a - } - deriving stock ( Show, Functor, Foldable, Traversable ) -instance Applicative ReqAndOpt where - pure a = ReqAndOpt a a - ReqAndOpt f g <*> ReqAndOpt a b = ReqAndOpt (f a) (g b) - --- | A collection of requests, which pertain either to an 'Instance' or to a 'PhysicalDevice'. -data family Requests (t :: Type) --- | A collection of requests on a Vulkan 'Instance'. --- --- Parameterised over the structure chain used in 'InstanceCreateInfo'. -data instance Requests Instance where - InstanceRequests - :: forall setts - . ( KnownChain setts, Extendss InstanceCreateInfo setts ) - => { - -- | Required and optional minimum Vulkan instance version. - version :: ReqAndOpt Word32 - -- | Required and optional Vulkan layer names and their minimum versions. - -- Each instance layer has an ordering value which defines the order in which layers should be enabled. - -- Lower value: enabled first. - , instanceLayers :: ReqAndOpt (HashMap ByteString (Int,Word32)) - -- | Required and optional Vulkan instance extension names and their minimum versions, - -- collected by the Vulkan layer name they come from. - , instanceExtensions :: HashMap (Maybe ByteString) (ReqAndOpt (HashMap ByteString Word32)) - -- | Required Vulkan instance settings ('InstanceCreateInfo' structure extension chain). - , enableSettings :: Chain setts - } - -> Requests Instance --- | A collection of requests on a Vulkan 'PhysicalDevice' --- --- Parameterised over the structure chains used by 'PhysicalDeviceFeatures2'/'DeviceCreateInfo' and 'PhysicalDeviceProperties2'. -data instance Requests PhysicalDevice where - PhysicalDeviceRequests - :: forall feats props - . ( KnownChain feats, Extendss PhysicalDeviceFeatures2 feats, Extendss DeviceCreateInfo feats - , KnownChain props, Extendss PhysicalDeviceProperties2 props - ) - => { - -- | Required and optional minimum device version. - version :: ReqAndOpt Word32 - -- | Required and optional Vulkan device extension names and their minimum versions, - -- collected by the Vulkan layer name they come from. - , deviceExtensions :: HashMap (Maybe ByteString) (ReqAndOpt (HashMap ByteString Word32)) - -- | Returns all the required and optional features that were not enabled in 'PhysicalDeviceFeatures2'. - , missingFeatures :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) - -- | All required features, to be used in 'DeviceCreateInfo'. - -- - -- Argument: optional features that should __not__ be enabled. - -- These must be the missing optional features returned by 'missingFeatures'. - , enableFeaturesOtherThan :: HashSet ByteString -> PhysicalDeviceFeatures2 feats - -- | Returns all the required and optional properties that were not satisfied in 'PhysicalDeviceProperties2' - , missingProperties :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) - } - -> Requests PhysicalDevice - -class KnownRequestTarget (t :: Type) where - -- | Make no requests. - noRequests :: Requests t - -- | Specify a single request. - addRequest :: Request t -> Requests t -> Requests t -instance KnownRequestTarget Instance where - noRequests = - InstanceRequests @'[] - (ReqAndOpt (MAKE_VERSION 1 0 0) (MAKE_VERSION 1 0 0)) - (ReqAndOpt HashMap.empty HashMap.empty) - HashMap.empty - () - addRequest (Request req isOptional) = case req of - RequireInstanceVersion {..} - -> requestInstanceVersion isOptional version - RequireInstanceLayer {..} - -> requestInstanceLayer isOptional instanceLayerName instanceLayerOrder instanceLayerMinVersion - RequireInstanceSetting {..} - -> requestInstanceSetting isOptional instanceSetting - RequireInstanceExtension {..} - -> requestInstanceExtension isOptional instanceExtensionLayerName instanceExtensionName instanceExtensionMinVersion - -instance KnownRequestTarget PhysicalDevice where - noRequests = - PhysicalDeviceRequests @'[] @'[] - (ReqAndOpt (MAKE_VERSION 1 0 0) (MAKE_VERSION 1 0 0)) - HashMap.empty - (const $ ReqAndOpt HashSet.empty HashSet.empty) - (const zero) - (const $ ReqAndOpt HashSet.empty HashSet.empty) - addRequest (Request req isOptional) = case req of - RequireDeviceVersion {..} - -> requestDeviceVersion isOptional version - RequireDeviceExtension {..} - -> requestDeviceExtension isOptional deviceExtensionLayerName deviceExtensionName deviceExtensionMinVersion - RequireDeviceFeature {..} - -> requestDeviceFeature isOptional featureName checkFeature enableFeature - RequireDeviceProperty {..} - -> requestDeviceProperty isOptional propertyName checkProperty - --- | Add a single request to a collection of requests. -addRequests - :: forall f t - . (Foldable f, KnownRequestTarget t) - => Requests t -> f (Request t) -> Requests t -addRequests = foldl' (flip $ addRequest @t) - --- | Collect up requests. -mkRequests - :: forall f t - . (Foldable f, KnownRequestTarget t) - => f (Request t) -> Requests t -mkRequests = addRequests @f @t (noRequests @t) - -requestInstanceVersion :: Bool -> Word32 -> Requests Instance -> Requests Instance -requestInstanceVersion isOptional ver req@(InstanceRequests{version = ReqAndOpt reqVer optVer}) - | isOptional - = req {version = ReqAndOpt reqVer (max ver optVer)} - | otherwise - = req {version = ReqAndOpt (max ver reqVer) optVer} - -requestDeviceVersion :: Bool -> Word32 -> Requests PhysicalDevice -> Requests PhysicalDevice -requestDeviceVersion isOptional ver req@(PhysicalDeviceRequests{version = ReqAndOpt reqVer optVer}) - | isOptional - = req {version = ReqAndOpt reqVer (max ver optVer)} - | otherwise - = req {version = ReqAndOpt (max ver reqVer) optVer} - -requestInstanceLayer :: Bool -> ByteString -> Int -> Word32 -> Requests Instance -> Requests Instance -requestInstanceLayer isOptional layName layOrder layVer req@(InstanceRequests{instanceLayers = ReqAndOpt reqLays optLays}) - | isOptional - = req {instanceLayers = ReqAndOpt reqLays (HashMap.insertWith minMax layName (layOrder,layVer) optLays)} - | otherwise - = req {instanceLayers = ReqAndOpt (HashMap.insertWith minMax layName (layOrder,layVer) reqLays) optLays} - where - minMax :: (Int, Word32) -> (Int, Word32) -> (Int, Word32) - minMax (o1,v1) (o2,v2) = (min o1 o2, max v1 v2) - -requestInstanceExtension :: Bool -> Maybe ByteString -> ByteString -> Word32 -> Requests Instance -> Requests Instance -requestInstanceExtension isOptional mbLayName extName extVer req@(InstanceRequests{instanceExtensions = exts}) - | isOptional - = req - { instanceExtensions = - HashMap.insertWith (liftA2 $ HashMap.unionWith max) - mbLayName - (ReqAndOpt (HashMap.singleton extName extVer) HashMap.empty) - exts - } - | otherwise - = req - { instanceExtensions = - HashMap.insertWith (liftA2 $ HashMap.unionWith max) - mbLayName - (ReqAndOpt HashMap.empty (HashMap.singleton extName extVer)) - exts - } - -requestDeviceExtension :: Bool -> Maybe ByteString -> ByteString -> Word32 -> Requests PhysicalDevice -> Requests PhysicalDevice -requestDeviceExtension isOptional mbLayName extName extVer req@(PhysicalDeviceRequests{deviceExtensions = exts}) - | isOptional - = req - { deviceExtensions = - HashMap.insertWith (liftA2 $ HashMap.unionWith max) - mbLayName - (ReqAndOpt (HashMap.singleton extName extVer) HashMap.empty) - exts - } - | otherwise - = req - { deviceExtensions = - HashMap.insertWith (liftA2 $ HashMap.unionWith max) - mbLayName - (ReqAndOpt HashMap.empty (HashMap.singleton extName extVer)) - exts - } - -requestInstanceSetting - :: forall struct - . ( KnownInstanceSettingStruct struct ) - => Bool -> struct -> Requests Instance -> Requests Instance -requestInstanceSetting _isOptional setting - ( InstanceRequests ver lays instExts - (setts :: Chain setts) - ) - = case has @setts @struct proxy# of - -- TODO: throw a warning when a setting is set twice. - Just (_, modifySettingStruct) - | let - setts' :: Chain setts - setts' = modifySettingStruct (const setting) setts - -> InstanceRequests ver lays instExts setts' - Nothing - | let - setts' :: Chain (struct ': setts) - setts' = (setting, setts) - -> InstanceRequests ver lays instExts setts' - -requestDeviceFeature - :: forall struct - . ( KnownFeatureStruct struct ) - => Bool -> ByteString -> (struct -> Bool) -> (struct -> struct) -> Requests PhysicalDevice -> Requests PhysicalDevice -requestDeviceFeature isOptional featName checkFeat enableFeat - ( PhysicalDeviceRequests ver devExts - (missingFeats :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString)) - enableFeats - missingProps - ) - = case sFeatureStruct @struct of - BasicFeatureStruct -> - let - missingFeats' :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) - missingFeats' feats2@(PhysicalDeviceFeatures2{features}) = - insertReqOptUnless (checkFeat features) featName isOptional - (missingFeats feats2) - enabledFeats' :: HashSet ByteString -> PhysicalDeviceFeatures2 feats - enabledFeats' don'tEnable - | isOptional && featName `HashSet.member` don'tEnable - = enableFeats don'tEnable - | enabled@(PhysicalDeviceFeatures2{features=prevEnabledFeats}) - <- enableFeats don'tEnable - = enabled { features = enableFeat prevEnabledFeats } - in PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps - ExtendedFeatureStruct - | Just (getFeatureStruct, modifyFeatureStruct) <- has @feats @struct proxy# - , let - missingFeats' :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) - missingFeats' feats2@(PhysicalDeviceFeatures2{next}) = - insertReqOptUnless (checkFeat (getFeatureStruct next)) featName isOptional - (missingFeats feats2) - enabledFeats' :: HashSet ByteString -> PhysicalDeviceFeatures2 feats - enabledFeats' don'tEnable - | isOptional && featName `HashSet.member` don'tEnable - = enableFeats don'tEnable - | enabled@(PhysicalDeviceFeatures2{next=nextEnabledFeats}) - <- enableFeats don'tEnable - = enabled { next = modifyFeatureStruct enableFeat nextEnabledFeats } - -> PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps - | let - missingFeats' :: PhysicalDeviceFeatures2 (struct ': feats) -> ReqAndOpt (HashSet ByteString) - missingFeats' feats2@(PhysicalDeviceFeatures2{next=(struct,feats)}) = - insertReqOptUnless (checkFeat struct) featName isOptional - (missingFeats (feats2{next=feats})) - enabledFeats' :: HashSet ByteString -> PhysicalDeviceFeatures2 (struct ': feats) - enabledFeats' don'tEnable - | let - struct :: struct - struct - | isOptional && featName `HashSet.member` don'tEnable - = zero - | otherwise - = enableFeat zero - , enabled@(PhysicalDeviceFeatures2{next=nextEnabledFeats}) - <- enableFeats don'tEnable - = enabled { next = (struct, nextEnabledFeats) } - -> PhysicalDeviceRequests ver devExts missingFeats' enabledFeats' missingProps - -requestDeviceProperty - :: forall struct - . ( KnownPropertyStruct struct ) - => Bool -> ByteString -> (struct -> Bool) -> Requests PhysicalDevice -> Requests PhysicalDevice -requestDeviceProperty isOptional propName checkProp - ( PhysicalDeviceRequests ver devExts missingFeats enabledFeats - (missingProps :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString)) - ) - = case sPropertyStruct @struct of - BasicPropertyStruct -> - let - missingProps' :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) - missingProps' props2@(PhysicalDeviceProperties2{properties}) = - insertReqOptUnless (checkProp properties) propName isOptional - (missingProps props2) - in PhysicalDeviceRequests ver devExts missingFeats enabledFeats missingProps' - ExtendedPropertyStruct - | Just (getPropertyStruct,_) <- has @props @struct proxy# - , let - missingProps' :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) - missingProps' props2@(PhysicalDeviceProperties2{next}) = - insertReqOptUnless (checkProp (getPropertyStruct next)) propName isOptional - (missingProps props2) - -> PhysicalDeviceRequests ver devExts missingFeats enabledFeats missingProps' - | let - missingProps' :: PhysicalDeviceProperties2 (struct ': props) -> ReqAndOpt (HashSet ByteString) - missingProps' props2@(PhysicalDeviceProperties2{next=(struct,props)}) = - insertReqOptUnless (checkProp struct) propName isOptional - (missingProps (props2{next=props})) - -> PhysicalDeviceRequests ver devExts missingFeats enabledFeats missingProps' - -insertReqOptUnless :: Bool -> ByteString -> Bool -> ReqAndOpt (HashSet ByteString) -> ReqAndOpt (HashSet ByteString) -insertReqOptUnless True _ _ = id -insertReqOptUnless False name True = \ (ReqAndOpt reqs opts) -> ReqAndOpt reqs (HashSet.insert name opts) -insertReqOptUnless False name False = \ (ReqAndOpt reqs opts) -> ReqAndOpt (HashSet.insert name reqs) opts diff --git a/src/Vulkan/SPIRVRequirements.hs b/src/Vulkan/SPIRVRequirements.hs index bdd442c9a..5c627f707 100644 --- a/src/Vulkan/SPIRVRequirements.hs +++ b/src/Vulkan/SPIRVRequirements.hs @@ -6,8 +6,8 @@ module Vulkan.SPIRVRequirements ( spirvExtensionRequirements , spirvCapabilityRequirements ) where -import Vulkan.Requirements (Requirement) -import Vulkan.Requirements (Requirement(..)) +import Vulkan.Requirement (DeviceRequirement(..)) +import Vulkan.Requirement (InstanceRequirement(..)) import Data.Bits ((.&.)) import Data.Bits (zeroBits) import Data.Bits (Bits) @@ -213,7 +213,7 @@ import Vulkan.Core11.Enums.SubgroupFeatureFlagBits (SubgroupFeatureFlagBits(SUBG (.&&.) :: Bits a => a -> a -> Bool x .&&. y = (x .&. y) /= zeroBits -spirvExtensionRequirements :: ByteString -> ([Requirement Instance], [Requirement PhysicalDevice]) +spirvExtensionRequirements :: ByteString -> ([InstanceRequirement], [DeviceRequirement]) spirvExtensionRequirements = \case "SPV_KHR_variable_pointers" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 1 0] [RequireDeviceVersion $ MAKE_VERSION 1 1 0] @@ -669,7 +669,7 @@ spirvExtensionRequirements = \case ] _ -> ([], []) -spirvCapabilityRequirements :: ByteString -> ([Requirement Instance], [Requirement PhysicalDevice]) +spirvCapabilityRequirements :: ByteString -> ([InstanceRequirement], [DeviceRequirement]) spirvCapabilityRequirements = \case "Matrix" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] "Shader" -> (,) [RequireInstanceVersion $ MAKE_VERSION 1 0 0] [RequireDeviceVersion $ MAKE_VERSION 1 0 0] diff --git a/utils/changelog.md b/utils/changelog.md index 58b6e691e..b74fdad0e 100644 --- a/utils/changelog.md +++ b/utils/changelog.md @@ -2,6 +2,11 @@ ## WIP +- Add `Vulkan.Utils.Requirements`, a module with several helpers for the + `Requirement` types found in `Vulkan.Requirement` +- Change the creation helpers in `Vulkan.Utils.Initialization` to use the new + `Requirement` types. + ## [0.3] - 2020-11-24 - Change type of pickPhysicalDevice to return Nothing instead of throwing diff --git a/utils/package.yaml b/utils/package.yaml index 72c20b01b..f5c3f387d 100644 --- a/utils/package.yaml +++ b/utils/package.yaml @@ -18,6 +18,9 @@ library: dependencies: - base <5 - bytestring + - containers + - dependent-map + - dependent-sum - extra - file-embed - filepath @@ -49,6 +52,7 @@ custom-setup: - cabal-doctest >= 1 && <1.1 default-extensions: + - ConstraintKinds - DataKinds - DefaultSignatures - DeriveAnyClass @@ -64,6 +68,7 @@ default-extensions: - InstanceSigs - LambdaCase - MagicHash + - NamedFieldPuns - NoMonomorphismRestriction - OverloadedStrings - PartialTypeSignatures diff --git a/utils/src/Vulkan/Utils/Initialization.hs b/utils/src/Vulkan/Utils/Initialization.hs index cbdae1dd7..fa87011d9 100644 --- a/utils/src/Vulkan/Utils/Initialization.hs +++ b/utils/src/Vulkan/Utils/Initialization.hs @@ -1,281 +1,155 @@ -{-# LANGUAGE OverloadedLists, NamedFieldPuns #-} +{-# LANGUAGE OverloadedLists #-} module Vulkan.Utils.Initialization - ( createInstanceFromRequests - , createDebugInstanceFromRequests - , pickPhysicalDevice + ( -- * Instance creation + createInstanceFromRequirements + , createDebugInstanceFromRequirements + -- * Device creation + , createDeviceFromRequirements + , -- * Physical device selection + pickPhysicalDevice , physicalDeviceName - , createDeviceFromRequests ) where -import Control.Applicative -import Control.Monad import Control.Monad.IO.Class -import Control.Monad.Trans.Resource -import Data.Bits -import Data.ByteString ( ByteString ) import Data.Foldable -import Data.HashMap.Strict ( HashMap ) -import qualified Data.HashMap.Strict as HashMap -import Data.HashSet ( HashSet ) -import qualified Data.HashSet as HashSet import Data.Maybe import Data.Ord import Data.Text ( Text ) -import qualified Data.Text as Text import Data.Text.Encoding ( decodeUtf8 ) -import qualified Data.Vector as V -import Data.Word -import Vulkan.CStruct.Extends import Vulkan.Core10 -import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 import Vulkan.Extensions.VK_EXT_debug_utils import Vulkan.Extensions.VK_EXT_validation_features -import Vulkan.Requirements +import Data.Bits +import Vulkan.Zero import Vulkan.Utils.Debug +import Control.Monad.Trans.Resource +import Vulkan.Requirement +import Vulkan.CStruct.Extends import Vulkan.Utils.Internal -import Vulkan.Utils.Misc -import Vulkan.Version -import Vulkan.Zero +import Vulkan.Utils.Requirements ---------------------------------------------------------------- --- * Instance Creation +-- Instance ---------------------------------------------------------------- --- | Create an 'Instance' with some layers and extensions, the layers and --- extensions will be added to the provided 'InstanceCreateInfo'. --- --- Returns all the names of instance layers which were enabled. --- --- Will throw an 'IOError in the case of missing layers or extensions. Details --- on missing layers and extensions will be reported in stderr. -createInstanceFromRequests - :: forall m - . MonadResource m - => Requests Instance - -> InstanceCreateInfo '[] - -> m (Instance, [ByteString]) -createInstanceFromRequests - ( InstanceRequests - { version = ReqAndOpt reqVersion optVersion - , instanceLayers = ReqAndOpt requiredLayers optionalLayers - , instanceExtensions = reqAndOptExtensions - , enableSettings = enableSettings :: Chain settings - } - ) - instanceCreateInfo - = do - -- - -- We start by checking that the Vulkan API version - -- that the user asked for is compatible with the requirements. - -- - let - mbGivenVersion :: Maybe Word32 - mbGivenVersion = ( apiVersion :: ApplicationInfo -> Word32 ) <$> applicationInfo ( instanceCreateInfo :: InstanceCreateInfo '[] ) - for_ mbGivenVersion $ \ givenVersion -> do - unless (givenVersion >= reqVersion) - ( liftIO $ noSuchThing - ( "Requirements imply a minimum Vulkan API version " <> showVersion reqVersion <> ",\n\ - \but the version specified by the application is " <> showVersion givenVersion <> "." - ) - ) - unless (givenVersion >= optVersion) - ( sayErr - ( "Optional preference: minimum Vulkan API version " <> showVersion optVersion <> ",\n\ - \but the version specified by the application is " <> showVersion givenVersion <> "." - ) - ) - -- - -- Next get the layers, they're needed to get the list of supported - -- extensions, as some of them may only be present in layers. - -- - availableLayerNames <- - toList . fmap layerName . snd <$> enumerateInstanceLayerProperties - (okLayers, missingOptLayers) - <- partitionOptReqIO "layer" - availableLayerNames - (HashMap.keys $ optionalLayers) - (HashMap.keys $ requiredLayers) - -- Run 'enumerateInstanceExtensionProperties' once for the instance itself, - -- and once for each layer and collect the results. - availableExtensionNames <- concat <$> traverse - ( fmap (toList . fmap extensionName . snd) - . enumerateInstanceExtensionProperties - ) - (Nothing : (Just <$> okLayers)) - let - optionalExtensions, requiredExtensions :: [ByteString] - ReqAndOpt requiredExtensions optionalExtensions - = ( ( \ ( req, opt ) -> ReqAndOpt ( HashMap.keys =<< req ) ( HashMap.keys =<< opt ) ) ) - . unzip - . map ( \ ( ReqAndOpt req opt ) -> (req,opt) ) - $ HashMap.elems reqAndOptExtensions - (okExts, missingOptExts) - <- partitionOptReqIO "instance extension" - availableExtensionNames - optionalExtensions - requiredExtensions - let - enabledLayers, enabledExtensions :: V.Vector ByteString - enabledLayers - = enabledLayerNames (instanceCreateInfo :: InstanceCreateInfo '[]) - <> V.fromList okLayers - enabledExtensions - = enabledExtensionNames (instanceCreateInfo :: InstanceCreateInfo '[]) - <> V.fromList okExts - instanceCreateInfo' :: InstanceCreateInfo settings - instanceCreateInfo' = instanceCreateInfo - { next = enableSettings - , enabledLayerNames = enabledLayers - , enabledExtensionNames = enabledExtensions - } - (_, inst) <- withInstance instanceCreateInfo' Nothing allocate - pure (inst, okLayers) - --- | Like 'createInstanceFromExtensions' except it will create a debug utils +-- | Like 'createInstanceFromRequirements' except it will create a debug utils -- messenger (from the @VK_EXT_debug_utils@ extension). -- -- If the @VK_EXT_validation_features@ extension (from the -- @VK_LAYER_KHRONOS_validation@ layer) is available is it will be enabled and -- best practices messages enabled. -createDebugInstanceFromRequests +createDebugInstanceFromRequirements + :: forall m es r o + . ( MonadResource m + , Extendss InstanceCreateInfo es + , PokeChain es + , Foldable r + , Foldable o + ) + => r InstanceRequirement + -> o InstanceRequirement + -> InstanceCreateInfo es + -> m Instance +createDebugInstanceFromRequirements required optional baseCreateInfo = do + let debugMessengerCreateInfo = zero + { messageSeverity = DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT + .|. DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT + , messageType = DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT + .|. DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT + .|. DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT + , pfnUserCallback = debugCallbackPtr + } + validationFeatures = + ValidationFeaturesEXT [VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT] [] + instanceCreateInfo + :: InstanceCreateInfo + (DebugUtilsMessengerCreateInfoEXT : ValidationFeaturesEXT : es) + instanceCreateInfo = baseCreateInfo + { next = debugMessengerCreateInfo :& validationFeatures :& next + (baseCreateInfo :: InstanceCreateInfo es) + } + additionalRequirements = + [ RequireInstanceExtension + { instanceExtensionLayerName = Nothing + , instanceExtensionName = EXT_DEBUG_UTILS_EXTENSION_NAME + , instanceExtensionMinVersion = minBound + } + ] + additionalOptionalRequirements = + [ RequireInstanceLayer + { instanceLayerName = "VK_LAYER_KHRONOS_validation" + , instanceLayerMinVersion = minBound + } + , RequireInstanceExtension + { instanceExtensionLayerName = Just "VK_LAYER_KHRONOS_validation" + , instanceExtensionName = EXT_VALIDATION_FEATURES_EXTENSION_NAME + , instanceExtensionMinVersion = minBound + } + ] + inst <- createInstanceFromRequirements + (additionalRequirements <> toList required) + (additionalOptionalRequirements <> toList optional) + instanceCreateInfo + _ <- withDebugUtilsMessengerEXT inst debugMessengerCreateInfo Nothing allocate + pure inst + +-- | Create an 'Instance from some requirements. +-- +-- Will throw an 'IOError in the case of unsatisfied non-optional requirements. +-- Unsatisfied requirements will be listed on stderr. +createInstanceFromRequirements + :: ( MonadResource m + , Extendss InstanceCreateInfo es + , PokeChain es + , Traversable r + , Traversable o + ) + => r InstanceRequirement + -> o InstanceRequirement + -> InstanceCreateInfo es + -> m Instance +createInstanceFromRequirements required optional baseCreateInfo = do + (mbICI, rrs, ors) <- checkInstanceRequirements required + optional + baseCreateInfo + traverse_ sayErr (requirementReport rrs ors) + case mbICI of + Nothing -> liftIO $ unsatisfiedConstraints "Failed to create instance" + Just ici -> snd <$> withInstance ici Nothing allocate + +---------------------------------------------------------------- +-- * Device creation +---------------------------------------------------------------- + +-- | Create a 'Device' from some requirements. +-- +-- Will throw an 'IOError in the case of unsatisfied non-optional requirements. +-- Unsatisfied requirements will be listed on stderr. +createDeviceFromRequirements :: forall m . MonadResource m - => Requests Instance - -> InstanceCreateInfo '[] - -> m (Instance, [ByteString]) -createDebugInstanceFromRequests reqs createInfo = do - res@(inst,_) <- createInstanceFromRequests debugReqs createInfo - _ <- withDebugUtilsMessengerEXT inst - debugMessengerCreateInfo - Nothing - allocate - pure res - - where - debugReqs :: Requests Instance - debugReqs = addRequests @[] reqs - [ Option $ RequireInstanceLayer "VK_LAYER_KHRONOS_validation" 0 100 - , Require $ RequireInstanceExtension Nothing EXT_DEBUG_UTILS_EXTENSION_NAME 0 - , Option $ RequireInstanceExtension Nothing EXT_VALIDATION_FEATURES_EXTENSION_NAME 0 - , Require $ RequireInstanceSetting validationFeatures - , Require $ RequireInstanceSetting debugMessengerCreateInfo - ] - validationFeatures :: ValidationFeaturesEXT - validationFeatures = ValidationFeaturesEXT - [VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT] - [] - debugMessengerCreateInfo :: DebugUtilsMessengerCreateInfoEXT - debugMessengerCreateInfo = zero - { messageSeverity = DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT - .|. DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT - , messageType = DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT - .|. DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT - .|. DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT - , pfnUserCallback = debugCallbackPtr - } + => PhysicalDevice + -> [DeviceRequirement] + -- ^ Required + -> [DeviceRequirement] + -- ^ Optional + -> DeviceCreateInfo '[] + -> m Device +createDeviceFromRequirements phys required optional baseCreateInfo = do + (mbDCI, rrs, ors) <- checkDeviceRequirements required + optional + phys + baseCreateInfo + traverse_ sayErr (requirementReport rrs ors) + case mbDCI of + Nothing -> liftIO $ unsatisfiedConstraints "Failed to create instance" + Just (SomeStruct dci) -> snd <$> withDevice phys dci Nothing allocate ---------------------------------------------------------------- -- * Physical device selection ---------------------------------------------------------------- --- | Check whether a 'PhysicalDevice' meets the provided 'Requests'. --- --- If the 'PhysicalDevice' meets the 'Requests': --- - returns 'Just' the enabled extensions, --- together with the optional properties, features and extensions (in this order) --- which were requested but could not be enabled. --- If the 'PhysicalDevice' did not fit the 'Requests': --- - returns 'Nothing'. -physicalDeviceFitsRequests - :: MonadIO m - => Requests PhysicalDevice - -> PhysicalDevice - -> m ( Maybe - ( V.Vector ByteString - , (HashSet ByteString, HashSet ByteString, HashSet ByteString) - ) - ) -physicalDeviceFitsRequests - ( PhysicalDeviceRequests - { missingProperties = missingProperties :: PhysicalDeviceProperties2 props -> ReqAndOpt (HashSet ByteString) - , missingFeatures = missingFeatures :: PhysicalDeviceFeatures2 feats -> ReqAndOpt (HashSet ByteString) - , deviceExtensions = reqAndOptExtensions - } - ) - physicalDevice = do - devName <- physicalDeviceName physicalDevice - physicalDeviceProperties <- getPhysicalDeviceProperties physicalDevice - let - vulkan1p1 :: Word32 - vulkan1p1 = MAKE_VERSION 1 1 0 - deviceVersion :: Word32 - deviceVersion = (apiVersion :: PhysicalDeviceProperties -> Word32) physicalDeviceProperties - ( ReqAndOpt missingReqProps missingOptProps :: ReqAndOpt ( HashSet ByteString ) ) <- - case sLength @props of - SNil -> do - pure $ missingProperties ( zero { properties = physicalDeviceProperties } ) - SCons _ -> do - when (deviceVersion < vulkan1p1) - ( liftIO $ noSuchThing - ( "Device properties need Vulkan API version " <> showVersion vulkan1p1 <> ",\n\ - \but the current device Vulkan version is " <> showVersion deviceVersion <> "." - ) - ) - physicalDeviceProperties2 <- getPhysicalDeviceProperties2 @props physicalDevice - pure $ missingProperties physicalDeviceProperties2 - ( ReqAndOpt missingReqFeats missingOptFeats :: ReqAndOpt ( HashSet ByteString ) ) <- - case sLength @feats of - SNil -> do - physicalDeviceFeatures <- getPhysicalDeviceFeatures physicalDevice - pure $ missingFeatures ( zero { features = physicalDeviceFeatures } ) - SCons _ -> do - when (deviceVersion < vulkan1p1) - ( liftIO $ noSuchThing - ( "Device features need Vulkan API version " <> showVersion vulkan1p1 <> ",\n\ - \but the current device Vulkan version is " <> showVersion deviceVersion <> "." - ) - ) - physicalDeviceFeatures2 <- getPhysicalDeviceFeatures2 @feats physicalDevice - pure $ missingFeatures physicalDeviceFeatures2 - if HashSet.null missingReqProps && HashSet.null missingReqFeats - then do - let - optionalExtensions, requiredExtensions :: [ByteString] - ReqAndOpt requiredExtensions optionalExtensions - = ( ( \ ( req, opt ) -> ReqAndOpt ( HashMap.keys =<< req ) ( HashMap.keys =<< opt ) ) ) - . unzip - . map ( \ ( ReqAndOpt req opt ) -> (req,opt) ) - $ HashMap.elems reqAndOptExtensions - availableExtensionNames <- - fmap extensionName . snd <$> enumerateDeviceExtensionProperties physicalDevice Nothing - let - missingOptExts :: [ByteString] - eitherMissingReqExtsOrEnabledExts :: Either [ByteString] [ByteString] - (missingOptExts, eitherMissingReqExtsOrEnabledExts) - = partitionOptReq - (V.toList availableExtensionNames) - optionalExtensions - requiredExtensions - case eitherMissingReqExtsOrEnabledExts of - Left missingExts -> do - devName <- physicalDeviceName physicalDevice - sayErr - ( "Physical device " <> Text.unpack devName - <> " is missing the following required extensions:\n" - <> show missingExts - ) - pure Nothing - Right enabledExts -> - pure ( Just (V.fromList enabledExts, (missingOptProps, missingOptFeats, HashSet.fromList missingOptExts)) ) - else do - sayErr - ( "Physical device " <> Text.unpack devName <> " does not meet requirements.\n\ - \Missing required properties: " <> show missingReqProps <> "\n\ - \Missing required features : " <> show missingReqFeats - ) - pure Nothing - -- | Get a single 'PhysicalDevice' deciding with a scoring function -- -- Pass a function which will extract any required values from a device in the @@ -288,6 +162,9 @@ physicalDeviceFitsRequests -- 'Vulkan.Utils.QueueAssignment.assignQueues' to find your desired queues in -- the suitability function. -- +-- Pehaps also use the functionality in 'Vulkan.Utils.Requirements' and return +-- the 'DeviceCreateInfo' too. +-- -- If no devices are deemed suitable then a 'NoSuchThing' 'IOError' is thrown. pickPhysicalDevice :: (MonadIO m, Ord b) @@ -310,67 +187,6 @@ physicalDeviceName :: MonadIO m => PhysicalDevice -> m Text physicalDeviceName = fmap (decodeUtf8 . deviceName) . getPhysicalDeviceProperties ----------------------------------------------------------------- --- * Device initialization ----------------------------------------------------------------- - --- | Create a 'Device' with some extensions, the extensions will be added to --- the provided 'DeviceCreateInfo'. --- --- Assumes the provided 'PhysicalDevice' satisfies the 'Requirements', --- and that the provided layers have indeed been enabled in the current Vulkan instance. --- --- Will throw an 'IOError in the case of missing extensions. Missing extensions --- will be listed on stderr. -createDeviceFromRequests - :: MonadResource m - => PhysicalDevice - -> Requests PhysicalDevice - -> HashSet ByteString - -- ^ Optional features that the device does not support, - -- as returned by 'physicalDeviceFitsRequirements'. - -> V.Vector ByteString - -- ^ Enabled extensions, - -- as returned by 'physicalDeviceFitsRequirement'. - -> V.Vector (SomeStruct DeviceQueueCreateInfo) - -> m Device -createDeviceFromRequests - phys - ( PhysicalDeviceRequests - { enableFeaturesOtherThan = enableFeaturesOtherThan :: HashSet ByteString -> PhysicalDeviceFeatures2 feats - } - ) - don'tEnableThese - okExtensions - queueCreateInfos - = do - case sLength @feats of - SNil -> do - let - deviceCreateInfo :: DeviceCreateInfo '[] - deviceCreateInfo = deviceCreateInfo - { next = () - , flags = zero - , queueCreateInfos - , enabledLayerNames = V.empty -- device layers aren't used - , enabledExtensionNames = okExtensions - , enabledFeatures = Just $ features ( enableFeaturesOtherThan don'tEnableThese ) - } - snd <$> withDevice phys deviceCreateInfo Nothing allocate - SCons _ -> do - let - deviceCreateInfo :: DeviceCreateInfo ( PhysicalDeviceFeatures2 '[] ': feats ) - deviceCreateInfo - | PhysicalDeviceFeatures2 {next, features} <- enableFeaturesOtherThan don'tEnableThese - = DeviceCreateInfo - { next = (zero {features}, next) - , flags = zero - , queueCreateInfos - , enabledLayerNames = V.empty -- device layers aren't used - , enabledExtensionNames = okExtensions - , enabledFeatures = Nothing - } - snd <$> withDevice phys deviceCreateInfo Nothing allocate ---------------------------------------------------------------- -- Utils @@ -379,10 +195,3 @@ createDeviceFromRequests maximumByMay :: Foldable t => (a -> a -> Ordering) -> t a -> Maybe a maximumByMay f xs = if null xs then Nothing else Just (maximumBy f xs) -showVersion :: Word32 -> String -showVersion ver = show maj <> " " <> show min <> " " <> show patch - where - maj, min, patch :: Word32 - maj = _VERSION_MAJOR ver - min = _VERSION_MINOR ver - patch = _VERSION_PATCH ver diff --git a/utils/src/Vulkan/Utils/Internal.hs b/utils/src/Vulkan/Utils/Internal.hs index 98be76bfc..373dec1a6 100644 --- a/utils/src/Vulkan/Utils/Internal.hs +++ b/utils/src/Vulkan/Utils/Internal.hs @@ -2,7 +2,7 @@ module Vulkan.Utils.Internal where import Control.Monad.IO.Class import GHC.IO ( throwIO ) -import GHC.IO.Exception ( IOErrorType(NoSuchThing) +import GHC.IO.Exception ( IOErrorType(..) , IOException(..) ) import System.IO ( hPutStrLn @@ -13,6 +13,10 @@ import System.IO ( hPutStrLn -- Internal utils ---------------------------------------------------------------- +unsatisfiedConstraints :: String -> IO a +unsatisfiedConstraints message = + throwIO $ IOError Nothing UnsatisfiedConstraints "" message Nothing Nothing + noSuchThing :: String -> IO a noSuchThing message = throwIO $ IOError Nothing NoSuchThing "" message Nothing Nothing diff --git a/utils/src/Vulkan/Utils/Misc.hs b/utils/src/Vulkan/Utils/Misc.hs index 5b40f1bcd..688a38c12 100644 --- a/utils/src/Vulkan/Utils/Misc.hs +++ b/utils/src/Vulkan/Utils/Misc.hs @@ -13,13 +13,6 @@ import Data.Foldable import Data.List ( intercalate , partition ) -import GHC.IO ( throwIO ) -import GHC.IO.Exception ( IOErrorType(NoSuchThing) - , IOException(..) - ) -import System.IO ( hPutStrLn - , stderr - ) import Vulkan.Utils.Internal -- | From a list of things, take all the required things and as many optional @@ -61,7 +54,7 @@ partitionOptReqIO -> [a] -- ^ Required desired elements -> m ([a],[a]) - -- ^ All the required elements and as many optional elements as possible, + -- ^ All the required elements and as many optional elements as possible, -- as well as the missing optional elements. partitionOptReqIO type' available optional required = liftIO $ do let (optMissing, exts) = partitionOptReq available optional required diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs new file mode 100644 index 000000000..2bfc38fb1 --- /dev/null +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -0,0 +1,554 @@ +{-# LANGUAGE AllowAmbiguousTypes #-} +{-# LANGUAGE UndecidableSuperClasses #-} +{-# LANGUAGE UndecidableInstances #-} + +module Vulkan.Utils.Requirements + ( -- * Instance requirements + checkInstanceRequirements + , -- * Device requirements + checkDeviceRequirements + , -- * Results + RequirementResult(..) + , Unsatisfied(..) + , requirementReport + , prettyRequirementResult + ) where + +import Control.Arrow ( Arrow((***)) ) +import Control.Monad +import Control.Monad.IO.Class +import Control.Monad.Trans.State +import Data.Bifunctor +import Data.ByteString ( ByteString ) +import qualified Data.Dependent.Map as DMap +import Data.Dependent.Map ( DMap ) +import Data.Dependent.Sum ( DSum((:=>)) ) +import Data.Foldable +import Data.Functor.Product ( Product(..) ) +import qualified Data.HashMap.Strict as Map +import Data.Kind ( Type ) +import Data.List.Extra ( nubOrd ) +import Data.Proxy +import Data.Semigroup ( Endo(..) ) +import Data.Traversable +import Data.Typeable ( eqT ) +import qualified Data.Vector as V +import Data.Vector ( Vector ) +import Data.Word +import GHC.Base ( Proxy# ) +import GHC.Exts ( proxy# ) +import Type.Reflection +import Vulkan.CStruct ( FromCStruct + , ToCStruct + ) +import Vulkan.CStruct.Extends +import Vulkan.Core10 +import Vulkan.Core11.DeviceInitialization +import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 +import Vulkan.NamedType +import Vulkan.Requirement +import Vulkan.Version +import Vulkan.Zero ( Zero(..) ) + +---------------------------------------------------------------- +-- * Instance Creation +---------------------------------------------------------------- + +checkInstanceRequirements + :: forall m o r es + . (MonadIO m, Traversable r, Traversable o) + => r InstanceRequirement + -- ^ Required requests + -> o InstanceRequirement + -- ^ Optional requests + -> InstanceCreateInfo es + -- ^ An 'InstanceCreateInfo' with no extensions. If you need elements in the + -- struct chain you can add them later with + -- 'Vulkan.CStruct.Extends.extendSomeStruct' + -> m + ( Maybe (InstanceCreateInfo es) + , r RequirementResult + , o RequirementResult + ) +checkInstanceRequirements required optional baseCreateInfo = do + let requiredList = toList required + allAsList = requiredList <> toList optional + foundVersion <- enumerateInstanceVersion + (_, layerProps) <- enumerateInstanceLayerProperties + lookupExtension <- getLookupExtension + Nothing + [ instanceExtensionLayerName + | RequireInstanceExtension { instanceExtensionLayerName } <- allAsList + ] + + (r, continue) <- flip runStateT True $ for required $ \r -> + case checkInstanceRequest foundVersion layerProps lookupExtension r of + res -> do + unless (res == Satisfied) (put False) + pure res + + (o, goodOptions) <- flip runStateT mempty $ for optional $ \r -> + case checkInstanceRequest foundVersion layerProps lookupExtension r of + res -> do + when (res == Satisfied) $ modify (r :) + pure res + + let ici = do + guard continue + pure $ makeInstanceCreateInfo (requiredList <> goodOptions) + baseCreateInfo + pure (ici, r, o) + +-- | Insert the settings of the requirements in to the provided instance create +-- info +makeInstanceCreateInfo + :: forall es + . [InstanceRequirement] + -> InstanceCreateInfo es + -> InstanceCreateInfo es +makeInstanceCreateInfo reqs baseCreateInfo = + let + layers = [ instanceLayerName | RequireInstanceLayer {..} <- reqs ] + extensions = + [ instanceExtensionName | RequireInstanceExtension {..} <- reqs ] + in + baseCreateInfo + { enabledLayerNames = + enabledLayerNames (baseCreateInfo :: InstanceCreateInfo es) + <> V.fromList layers + , enabledExtensionNames = + enabledExtensionNames (baseCreateInfo :: InstanceCreateInfo es) + <> V.fromList extensions + } + +checkInstanceRequest + :: ("apiVersion" ::: Word32) + -> ("properties" ::: Vector LayerProperties) + -> ( ("layerName" ::: Maybe ByteString) + -> ByteString + -> Maybe ExtensionProperties + ) + -> InstanceRequirement + -> RequirementResult +checkInstanceRequest foundVersion layerProps lookupExtension = \case + RequireInstanceVersion minVersion -> if foundVersion >= minVersion + then Satisfied + else UnsatisfiedInstanceVersion (Unsatisfied minVersion foundVersion) + + RequireInstanceLayer { instanceLayerName, instanceLayerMinVersion } + | Just props <- find ((== instanceLayerName) . layerName) layerProps + , foundLayerVersion <- implementationVersion props + -> if foundVersion >= instanceLayerMinVersion + then Satisfied + else UnsatisfiedLayerVersion + instanceLayerName + (Unsatisfied instanceLayerMinVersion foundLayerVersion) + | otherwise + -> MissingLayer instanceLayerName + + RequireInstanceExtension { instanceExtensionLayerName, instanceExtensionName, instanceExtensionMinVersion } + | Just eProps <- lookupExtension instanceExtensionLayerName + instanceExtensionName + , specVersion (eProps :: ExtensionProperties) >= instanceExtensionMinVersion + -> Satisfied + | otherwise + -> UnsatisfiedInstanceExtension instanceExtensionName + +---------------------------------------------------------------- +-- Device +---------------------------------------------------------------- + +checkDeviceRequirements + :: forall m o r + . (MonadIO m, Traversable r, Traversable o) + => r DeviceRequirement + -- ^ Required requests + -> o DeviceRequirement + -- ^ Optional requests + -> PhysicalDevice + -> DeviceCreateInfo '[] + -- ^ A deviceCreateInfo with no extensions. If you need elements in the + -- struct chain you can add them later with + -- 'Vulkan.CStruct.Extends.extendSomeStruct' + -> m + ( Maybe (SomeStruct DeviceCreateInfo) + , r RequirementResult + , o RequirementResult + ) +checkDeviceRequirements required optional phys baseCreateInfo = do + let requiredList = toList required + allAsList = requiredList <> toList optional + + -- + -- First collect the types and properties that we'll need to query using + -- getPhysicalDeviceProperties2 and getPhysicalDeviceFeatures2 + -- + withDeviceFeatureStructs allAsList $ \(_ :: Proxy fs) -> + withDevicePropertyStructs allAsList $ \(_ :: Proxy ps) -> do + -- + -- Fetch everything + -- + feats <- getPhysicalDeviceFeatures2 @fs phys + props <- getPhysicalDeviceProperties2 @ps phys + lookupExtension <- getLookupExtension + (Just phys) + [ deviceExtensionLayerName + | RequireDeviceExtension { deviceExtensionLayerName } <- allAsList + ] + + (r, continue) <- flip runStateT True $ for required $ \r -> + case checkDeviceRequest feats props lookupExtension r of + res -> do + unless (res == Satisfied) (put False) + pure res + + (o, goodOptions) <- flip runStateT mempty $ for optional $ \r -> + case checkDeviceRequest feats props lookupExtension r of + res -> do + when (res == Satisfied) $ modify (r :) + pure res + + -- + -- Now create the types for just the available features + -- + let dci = do + guard continue + pure $ makeDeviceCreateInfo (requiredList <> goodOptions) + baseCreateInfo + pure (dci, r, o) + + +{-# ANN makeDeviceCreateInfo ("HLint: ignore Move guards forward" :: String) #-} +-- | Generate 'DeviceCreateInfo' from some requirements. +-- +-- The returned struct chain will enable all required features and extensions. +makeDeviceCreateInfo + :: [DeviceRequirement] + -> DeviceCreateInfo '[] + -> SomeStruct DeviceCreateInfo +makeDeviceCreateInfo allReqs baseCreateInfo = + let + featureSetters :: DMap TypeRep (Product (Has KnownFeatureStruct) Endo) + featureSetters = DMap.fromListWithKey + (\_ l r -> catProducts l r) + [ typeRep :=> Pair Has (Endo enableFeature) + | RequireDeviceFeature { enableFeature } <- allReqs + ] + + makeZeroFeatureExts :: [Endo (SomeStruct DeviceCreateInfo)] + makeZeroFeatureExts = + [ Endo (extendSomeStruct s) + | _ :=> Pair Has (f :: Endo s) <- DMap.toList featureSetters + , ExtendedFeatureStruct <- pure $ sFeatureStruct @s + , let s = appEndo f zero + ] + + addBasicFeatures :: Endo (SomeStruct DeviceCreateInfo) + addBasicFeatures = + case DMap.lookup (typeRep @PhysicalDeviceFeatures) featureSetters of + Nothing -> mempty + Just (Pair _ s) -> Endo + (extendSomeStruct + ((zero :: PhysicalDeviceFeatures2 '[]) { features = appEndo s zero } + ) + ) + + extensionNames :: [ByteString] + extensionNames = + [ deviceExtensionName + | RequireDeviceExtension { deviceExtensionName } <- allReqs + ] + + newFeatures :: SomeStruct DeviceCreateInfo + newFeatures = appEndo + (fold (addBasicFeatures : makeZeroFeatureExts)) + (SomeStruct (baseCreateInfo :: DeviceCreateInfo '[]) + { enabledExtensionNames = V.fromList extensionNames + } + ) + in + newFeatures + +checkDeviceRequest + :: forall fs ps + . (KnownChain fs, KnownChain ps) + => PhysicalDeviceFeatures2 fs + -> PhysicalDeviceProperties2 ps + -> ( ("layerName" ::: Maybe ByteString) + -> ("extensionName" ::: ByteString) + -> Maybe ExtensionProperties + ) + -- ^ Lookup an extension + -> DeviceRequirement + -- ^ The requirement to test + -> RequirementResult + -- ^ The result +checkDeviceRequest feats props lookupExtension = \case + RequireDeviceVersion minVersion + | foundVersion <- apiVersion + (properties (props :: PhysicalDeviceProperties2 ps) :: PhysicalDeviceProperties + ) + -> if foundVersion >= minVersion + then Satisfied + else UnsatisfiedDeviceVersion (Unsatisfied minVersion foundVersion) + + RequireDeviceFeature { featureName, checkFeature } -> + case getFeatureStruct feats of + Nothing -> + error "Impossible: didn't find requested feature in struct chain" + Just s -> + if checkFeature s then Satisfied else UnsatisfiedFeature featureName + + RequireDeviceProperty { propertyName, checkProperty } -> + case getPropertyStruct props of + Nothing -> + error "Impossible: didn't find requested property in struct chain" + Just s -> + if checkProperty s then Satisfied else UnsatisfiedProperty propertyName + + RequireDeviceExtension { deviceExtensionLayerName, deviceExtensionName, deviceExtensionMinVersion } + | Just eProps <- lookupExtension deviceExtensionLayerName + deviceExtensionName + , specVersion (eProps :: ExtensionProperties) >= deviceExtensionMinVersion + -> Satisfied + | otherwise + -> UnsatisfiedDeviceExtension deviceExtensionName + +---------------------------------------------------------------- +-- Results +---------------------------------------------------------------- + +-- TODO, better version reporting for extensions +-- TODO, better reporting for properties +data RequirementResult + = Satisfied + -- ^ All the requirements were met + | MissingLayer ByteString + -- ^ A Layer was not found + | UnsatisfiedDeviceVersion (Unsatisfied Word32) + -- ^ A device version didn't meet the minimum requested + | UnsatisfiedInstanceVersion (Unsatisfied Word32) + -- ^ The instance version didn't meet the minimum requested + | UnsatisfiedLayerVersion ByteString (Unsatisfied Word32) + -- ^ A layer version didn't meet the minimum requested + | UnsatisfiedFeature ByteString + -- ^ A feature was missing + | UnsatisfiedProperty ByteString + -- ^ A propery was not an appropriate value + | UnsatisfiedDeviceExtension ByteString + -- ^ A device extension was missing + | UnsatisfiedInstanceExtension ByteString + -- ^ An instance extension was missing + deriving (Eq, Ord) + +data Unsatisfied a = Unsatisfied + { unsatisfiedMinimum :: a + -- ^ The minimum value to be accepted + , unsatisfiedActual :: a + -- ^ The value we got, less than 'unsatisfiedMinumum' + } + deriving (Eq, Ord) + +-- | Generate a string describing which requirements were not met, if +-- everything was satisfied return 'Nothing'. +requirementReport + :: (Foldable r, Foldable o) + => r RequirementResult + -> o RequirementResult + -> Maybe String +requirementReport required optional = + let pList xs = + nubOrd [ prettyRequirementResult r | r <- toList xs, r /= Satisfied ] + reqStrings = pList required + optStrings = pList optional + withHeader s = \case + [] -> [] + xs -> (s <> " requirements not met:") : ((" " <>) <$> xs) + reportLines = + withHeader "Required" reqStrings <> withHeader "Optional" optStrings + in if null reportLines then Nothing else Just $ unlines reportLines + +prettyRequirementResult :: RequirementResult -> String +prettyRequirementResult = \case + Satisfied -> "Satisfied" + MissingLayer n -> "Missing layer: " <> show n + UnsatisfiedInstanceVersion u -> "Unsatisfied Instance Version: " <> p u + UnsatisfiedDeviceVersion u -> "Unsatisfied Device Version: " <> p u + UnsatisfiedLayerVersion n u -> + "Unsatisfied layer version for " <> show n <> ": " <> p u + UnsatisfiedFeature n -> "Missing feature: " <> show n + UnsatisfiedProperty n -> "Unsatisfied property: " <> show n + UnsatisfiedInstanceExtension n -> "Missing device extension: " <> show n + UnsatisfiedDeviceExtension n -> "Missing instance extension: " <> show n + where p = prettyUnsatisfied showVersion + +-- How I'm feeling after writing all this type level nonsense +prettyUnsatisfied :: (t -> String) -> Unsatisfied t -> String +prettyUnsatisfied s Unsatisfied {..} = + "Wanted minimum of " + <> s unsatisfiedMinimum + <> ", got: " + <> s unsatisfiedActual + +---------------------------------------------------------------- +-- Chain lenses +---------------------------------------------------------------- + +-- | Enough information to focus on any structure within a Vulkan structure chain. +class (PeekChain xs, PokeChain xs) => KnownChain (xs :: [Type]) where + -- | If the given structure can be found within a chain, return a lens to it. + -- Otherwise, return 'Nothing'. + has :: forall a. Typeable a => Proxy# a -> Maybe (Chain xs -> a, (a -> a) -> (Chain xs -> Chain xs)) + +instance KnownChain '[] where + has _ = Nothing + +instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain (x ': xs) where + has (px :: Proxy# a) + | Just Refl <- eqT @a @x + = Just (fst,first) + | otherwise + = ((. snd) *** (second .)) <$> has px + +getPropertyStruct + :: forall s es + . (Typeable s, KnownChain es) + => PhysicalDeviceProperties2 es + -> Maybe s +getPropertyStruct c = case eqT @PhysicalDeviceProperties @s of + Just Refl -> Just (properties (c :: PhysicalDeviceProperties2 es)) + Nothing -> getStruct c + +getFeatureStruct + :: forall s es + . (Typeable s, KnownChain es) + => PhysicalDeviceFeatures2 es + -> Maybe s +getFeatureStruct c = case eqT @PhysicalDeviceFeatures @s of + Just Refl -> Just (features (c :: PhysicalDeviceFeatures2 es)) + Nothing -> getStruct c + +getStruct + :: forall s h es + . (Typeable h, Typeable s, KnownChain es, Extensible h) + => h es + -> Maybe s +getStruct c = ($ getNext c) . fst <$> has (proxy# @s) + +---------------------------------------------------------------- +-- Helpers for 'Device' and 'Instance' extensions +---------------------------------------------------------------- + +-- | Make a lookup function for extensions in layers +getLookupExtension + :: MonadIO m + => Maybe PhysicalDevice + -- ^ Pass 'Nothing' for 'Instance' extensions, pass a PhysicalDevice for + -- device extensions. + -> ["layerName" ::: Maybe ByteString] + -> m + ( ("layerName" ::: Maybe ByteString) + -> ByteString + -> Maybe ExtensionProperties + ) +getLookupExtension mbPhys deviceExtensionLayers = do + let enumerate = maybe enumerateInstanceExtensionProperties + enumerateDeviceExtensionProperties + mbPhys + extensions <- for (nubOrd deviceExtensionLayers) $ \layer -> do + (_, props) <- enumerate layer + pure (layer, props) + let extensionMap = Map.fromListWith (<>) extensions + pure $ \layer name -> + let es = Map.lookupDefault mempty layer extensionMap + in find ((== name) . extensionName) es + +---------------------------------------------------------------- +-- Helpers for extracting the type of chain used by a set of requirements +---------------------------------------------------------------- + +withDevicePropertyStructs + :: forall a + . [DeviceRequirement] + -> ChainCont PhysicalDeviceProperties2 DevicePropertyChain a + -> a +withDevicePropertyStructs = go @'[] [] + where + go + :: forall (fs :: [Type]) + . DevicePropertyChain fs + => [SomeTypeRep] + -> [DeviceRequirement] + -> ChainCont PhysicalDeviceProperties2 DevicePropertyChain a + -> a + go seen reqs f = case reqs of + -- We've been through all the reqs, call the continuation with the types + [] -> f (Proxy @fs) + -- This is a device property, add it to the list if we've not seen it before + (RequireDeviceProperty _ (_ :: s -> Bool)) : rs + | ExtendedPropertyStruct <- sPropertyStruct @s + , sRep <- SomeTypeRep (typeRep @s) + , sRep `notElem` seen + -> go @(s:fs) (sRep : seen) rs f + -- Otherwise skip + _ : rs -> go @fs seen rs f + +withDeviceFeatureStructs + :: forall a + . [DeviceRequirement] + -> ChainCont PhysicalDeviceFeatures2 DeviceFeatureChain a + -> a +withDeviceFeatureStructs = go @'[] [] + where + go + :: forall (fs :: [Type]) + . DeviceFeatureChain fs + => [SomeTypeRep] + -> [DeviceRequirement] + -> ChainCont PhysicalDeviceFeatures2 DeviceFeatureChain a + -> a + go seen reqs f = case reqs of + -- We've been through all the reqs, call the continuation with the types + [] -> f (Proxy @fs) + -- This is a device feature, add it to the list if we've not seen it before + (RequireDeviceFeature _ _ (_ :: s -> s)) : rs + | ExtendedFeatureStruct <- sFeatureStruct @s + , sRep <- SomeTypeRep (typeRep @s) + , sRep `notElem` seen + -> go @(s:fs) (sRep : seen) rs f + -- Otherwise skip + _ : rs -> go @fs seen rs f + +class (KnownChain es, Extendss PhysicalDeviceFeatures2 es, Show (Chain es)) => DeviceFeatureChain es where +instance (KnownChain es, Extendss PhysicalDeviceFeatures2 es, Show (Chain es)) => DeviceFeatureChain es where + +class (KnownChain es, Extendss PhysicalDeviceProperties2 es) => DevicePropertyChain es where +instance (KnownChain es, Extendss PhysicalDeviceProperties2 es) => DevicePropertyChain es where + +type ChainCont h c a = + forall (es :: [Type]) + . (c es) -- + => Proxy es + -> a + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +showVersion :: Word32 -> String +showVersion ver = unwords ["MAKE_VERSION", show maj, show min, show patch] + where MAKE_VERSION maj min patch = ver + +data Has c a where + Has :: c a => Has c a + +instance Semigroup (Has c a) where + Has <> _ = Has + +-- | There is no Semigroup instance for 'Product' in base +catProducts + :: (Semigroup (f a), Semigroup (g a)) + => Product f g a + -> Product f g a + -> Product f g a +catProducts (Pair a1 b1) (Pair a2 b2) = Pair (a1 <> a2) (b1 <> b2) diff --git a/utils/vulkan-utils.cabal b/utils/vulkan-utils.cabal index a25abf554..ccaec0bed 100644 --- a/utils/vulkan-utils.cabal +++ b/utils/vulkan-utils.cabal @@ -3,8 +3,6 @@ cabal-version: 1.24 -- This file has been generated from package.yaml by hpack version 0.34.2. -- -- see: https://github.com/sol/hpack --- --- hash: 03fd72b5674b4b85451005687d857d0e9328528b514e5ba805729e54ad6ae761 name: vulkan-utils version: 0.3 @@ -40,19 +38,23 @@ library Vulkan.Utils.Initialization Vulkan.Utils.Misc Vulkan.Utils.QueueAssignment + Vulkan.Utils.Requirements Vulkan.Utils.ShaderQQ Vulkan.Utils.ShaderQQ.Interpolate Vulkan.Utils.ShaderQQ.Shaderc other-modules: - + Vulkan.Utils.Internal hs-source-dirs: src - default-extensions: DataKinds DefaultSignatures DeriveAnyClass DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NoMonomorphismRestriction OverloadedStrings PartialTypeSignatures PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns + default-extensions: ConstraintKinds DataKinds DefaultSignatures DeriveAnyClass DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NamedFieldPuns NoMonomorphismRestriction OverloadedStrings PartialTypeSignatures PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns c-sources: cbits/DebugCallback.c build-depends: base <5 , bytestring + , containers + , dependent-map + , dependent-sum , extra , file-embed , filepath @@ -62,6 +64,7 @@ library , text , transformers , typed-process + , unordered-containers , vector , vulkan >=3.6.14 && <3.8 default-language: Haskell2010 @@ -73,7 +76,7 @@ test-suite doctests hs-source-dirs: test/doctest - default-extensions: DataKinds DefaultSignatures DeriveAnyClass DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NoMonomorphismRestriction OverloadedStrings PartialTypeSignatures PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns + default-extensions: ConstraintKinds DataKinds DefaultSignatures DeriveAnyClass DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NamedFieldPuns NoMonomorphismRestriction OverloadedStrings PartialTypeSignatures PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns build-depends: base , doctest diff --git a/vulkan.cabal b/vulkan.cabal index f90bf2232..05df0e255 100644 --- a/vulkan.cabal +++ b/vulkan.cabal @@ -475,7 +475,7 @@ library Vulkan.Version Vulkan.Zero Vulkan.Internal.Utils - Vulkan.Requirements + Vulkan.Requirement hs-source-dirs: src src-manual @@ -485,7 +485,6 @@ library base <5 , bytestring , transformers - , unordered-containers , vector if os(windows) extra-libraries: From 02a518bd81d41ba255576a0c0d1eb39ea34ea512 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 00:20:55 +0800 Subject: [PATCH 35/70] Add Vulkan.Extensions.Dependencies --- generate-new/generate-new.cabal | 2 + generate-new/src/Render/SpecInfo.hs | 3 +- generate-new/src/Spec/Parse.hs | 4 +- generate-new/src/Spec/Types.hs | 1 + generate-new/vk/VK/ExtensionDepElements.hs | 82 ++++++++++++++ generate-new/vk/VK/Render.hs | 3 + generate-new/vk/VK/SPIRVElements.hs | 125 ++++++++++----------- generate-new/vk/VK/Utils.hs | 46 ++++++++ 8 files changed, 197 insertions(+), 69 deletions(-) create mode 100644 generate-new/vk/VK/ExtensionDepElements.hs create mode 100644 generate-new/vk/VK/Utils.hs diff --git a/generate-new/generate-new.cabal b/generate-new/generate-new.cabal index 731e7bfd6..abcf03b14 100644 --- a/generate-new/generate-new.cabal +++ b/generate-new/generate-new.cabal @@ -139,8 +139,10 @@ executable vk other-modules: VK.AssignModules VK.Bracket + VK.ExtensionDepElements VK.Render VK.SPIRVElements + VK.Utils Paths_generate_new hs-source-dirs: vk diff --git a/generate-new/src/Render/SpecInfo.hs b/generate-new/src/Render/SpecInfo.hs index d25fe6e7b..e10a4aca5 100644 --- a/generate-new/src/Render/SpecInfo.hs +++ b/generate-new/src/Render/SpecInfo.hs @@ -10,6 +10,7 @@ import Polysemy import Polysemy.Input import Relude hiding ( Handle ) +import Data.List.Extra ( nubOrd ) import qualified Data.Vector as V import Render.Element import Spec.Types @@ -156,7 +157,7 @@ specSpecInfo Spec {..} siTypeSize = let immediateDeps = get n in concat (immediateDeps : (close <$> immediateDeps)) in - close + nubOrd . close in SpecInfo { .. } diff --git a/generate-new/src/Spec/Parse.hs b/generate-new/src/Spec/Parse.hs index a42c51566..960be64a8 100644 --- a/generate-new/src/Spec/Parse.hs +++ b/generate-new/src/Spec/Parse.hs @@ -363,7 +363,9 @@ parseExtensions parseDisabled es = V.fromList <$> sequenceV Nothing -> pure UnknownExtensionType exDependencies <- listAttr decode "requires" n exRequires <- parseRequires n - exSupported <- decode + exRequiresCore <- traverse (runReadP parseVersion) + (getAttr "requiresCore" n) + exSupported <- decode =<< note "extension has no supported attr" (getAttr "supported" n) pure Extension { .. } diff --git a/generate-new/src/Spec/Types.hs b/generate-new/src/Spec/Types.hs index 1ac237294..8cc91e7b3 100644 --- a/generate-new/src/Spec/Types.hs +++ b/generate-new/src/Spec/Types.hs @@ -47,6 +47,7 @@ data Feature = Feature data Extension = Extension { exName :: Text , exNumber :: Int + , exRequiresCore :: Maybe Version , exRequires :: Vector Require , exSupported :: Text , exType :: ExtensionType diff --git a/generate-new/vk/VK/ExtensionDepElements.hs b/generate-new/vk/VK/ExtensionDepElements.hs new file mode 100644 index 000000000..f471973cd --- /dev/null +++ b/generate-new/vk/VK/ExtensionDepElements.hs @@ -0,0 +1,82 @@ +{-# LANGUAGE QuasiQuotes #-} + +module VK.ExtensionDepElements + ( renderExtensionDepElements + ) where + +import VK.Utils +import Data.Text.Prettyprint.Doc +import Data.Vector ( Vector ) +import qualified Data.Vector as V +import Error +import Haskell ( HName(..) ) +import Relude +import Render.Element +import Render.SpecInfo +import Spec.Types +import VkModulePrefix +import Data.Traversable +import Polysemy.Input + +renderExtensionDepElements + :: (HasErr r, HasRenderParams r, HasSpecInfo r) + => Vector Extension + -> Sem r RenderElement +renderExtensionDepElements exts = genRe "Extension dependencies" $ do + tellExplicitModule (vulkanModule ["Extensions", "Dependencies"]) + tellCanFormat + renderDeps exts + renderCoreRequirements exts + +renderDeps + :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) + => Vector Extension + -> Sem r () +renderDeps exts = do + SpecInfo {..} <- input + let defaultCase = "_ -> []" + cases <- + for [ e | e@Extension {..} <- V.toList exts, not (V.null exDependencies) ] + $ \Extension {..} -> do + namePattern <- fst <$> extensionPatterns exName + let deps = siExtensionDeps exName + depPatterns <- traverse (fmap fst . extensionPatterns) deps + traverse_ tellImport (namePattern : depPatterns) + pure $ pretty namePattern <+> "->" <+> list (pretty <$> depPatterns) + tellImport (TyConName ":::") + tellImport ''ByteString + tellDoc $ vsep + [ "-- | The set of other extensions required to use this extension" + , "extensionDependencies :: (\"extensionName\" ::: ByteString) -> [ByteString]" + , "extensionDependencies = \\case" <> line <> indent + 2 + (vsep (cases <> [defaultCase])) + ] + +renderCoreRequirements + :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) + => Vector Extension + -> Sem r () +renderCoreRequirements exts = do + tellImport (ConName "API_VERSION_1_0") + let defaultCase = "_ -> API_VERSION_1_0" + cases <- + for + [ (exName, v) + | Extension {..} <- V.toList exts + , Just v <- pure exRequiresCore + ] + $ \(name, v) -> do + namePattern <- fst <$> extensionPatterns name + tellImport namePattern + vPat <- versionDoc v + pure $ pretty namePattern <+> "->" <+> vPat + tellImport (TyConName ":::") + tellImport ''Word32 + tellDoc $ vsep + [ "-- | The minimum required API version to use this extension" + , "extensionCoreRequirement :: (\"extensionName\" ::: ByteString) -> Word32" + , "extensionCoreRequirement = \\case" <> line <> indent + 2 + (vsep (cases <> [defaultCase])) + ] diff --git a/generate-new/vk/VK/Render.hs b/generate-new/vk/VK/Render.hs index 3b7141885..033e5c5cd 100644 --- a/generate-new/vk/VK/Render.hs +++ b/generate-new/vk/VK/Render.hs @@ -39,6 +39,7 @@ import Spec.Parse import Render.State ( HasRenderState ) import VK.Bracket import VK.SPIRVElements +import VK.ExtensionDepElements data RenderedSpec a = RenderedSpec { rsHandles :: Vector a @@ -133,6 +134,8 @@ renderSpec spec@Spec {..} getDoc ss us cs = do <> V.singleton (structExtends spec) <> V.singleton (renderSPIRVElements specSPIRVExtensions specSPIRVCapabilities) + <> V.singleton + (renderExtensionDepElements specExtensions) } -- | Render a command along with any associated bracketing function diff --git a/generate-new/vk/VK/SPIRVElements.hs b/generate-new/vk/VK/SPIRVElements.hs index 6d2bd0a78..182d33b0a 100644 --- a/generate-new/vk/VK/SPIRVElements.hs +++ b/generate-new/vk/VK/SPIRVElements.hs @@ -12,7 +12,7 @@ import qualified Data.Text as T import Data.Text.Prettyprint.Doc import Data.Vector ( Vector ) import qualified Data.Vector as V -import Data.Version ( Version(versionBranch) +import Data.Version ( Version , makeVersion ) import Error @@ -25,6 +25,7 @@ import Language.Haskell.TH ( Type(ConT) , mkName ) import Polysemy.Input +import qualified Prelude import Relude import Render.Element import Render.SpecInfo ( HasSpecInfo @@ -34,8 +35,8 @@ import Render.Type ( cToHsType ) import Render.Type.Preserve ( Preserve(DoNotPreserve) ) import Spec.Types import Text.InterpolatedString.Perl6.Unindented +import VK.Utils import VkModulePrefix -import qualified Prelude renderSPIRVElements :: (HasErr r, HasRenderParams r, HasSpecInfo r) @@ -74,11 +75,13 @@ renderSPIRVThing -> Sem r () renderSPIRVThing funName name reqs xs = do tellLanguageExtension (LanguageExtension "TupleSections") - let case' x = do - let mergeReqs = Prelude.head -- TODO: this is probably wrong! discarding the - -- other reqs - (instReqs', devReqs') <- mergeReqs <$> traverse renderReq (V.toList (reqs x)) - pure $ viaShow (name x) <+> "-> (,)" <+> list instReqs' <+> list devReqs' + let + case' x = do + let mergeReqs = Prelude.head -- TODO: this is probably wrong! discarding the + -- other reqs + (instReqs', devReqs') <- mergeReqs + <$> traverse renderReq (V.toList (reqs x)) + pure $ viaShow (name x) <+> "-> (,)" <+> list instReqs' <+> list devReqs' cases <- (<> ["_ -> ([],[])"]) <$> traverse case' (V.toList xs) tellImport ''ByteString tellImport (TyConName "Instance") @@ -87,18 +90,19 @@ renderSPIRVThing funName name reqs xs = do tellImportWithAll (mkName "Vulkan.Requirement.InstanceRequirement") tellExport (ETerm (TermName funName)) tellDoc $ vsep - [ pretty funName <+> ":: ByteString -> ([InstanceRequirement], [DeviceRequirement])" + [ pretty funName + <+> ":: ByteString -> ([InstanceRequirement], [DeviceRequirement])" , pretty funName <+> "= \\case" <> line <> indent 2 (vsep cases) ] renderReq :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) => SPIRVRequirement - -> Sem r ([Doc ()],[Doc ()]) + -> Sem r ([Doc ()], [Doc ()]) renderReq = \case - SPIRVReqVersion v -> ( \(iReq,devReq) -> ([iReq],[devReq]) ) <$> versionReq v + SPIRVReqVersion v -> (\(iReq, devReq) -> ([iReq], [devReq])) <$> versionReq v - SPIRVReqExtension p -> minVersionAndExtensionsReqs (V.singleton p) + SPIRVReqExtension p -> minVersionAndExtensionsReqs (V.singleton p) SPIRVReqFeature s f rs -> do RenderParams {..} <- input @@ -108,11 +112,10 @@ renderReq = \case sTy <- cToHsType DoNotPreserve (TypeName s) -- TODO: this is pretty lazy, import the accessors properly traverse_ tellImportWithAll (allTypeNames sTy) - checkTDoc <- renderType (sTy ~> ConT ''Bool) - sTyDoc <- renderType sTy + checkTDoc <- renderType (sTy ~> ConT ''Bool) + sTyDoc <- renderType sTy (otherInstReqs, otherDevReqs) <- minVersionAndExtensionsReqs rs - let - featureMemberName = mkMemberName s f + let featureMemberName = mkMemberName s f let xs = [ ("featureName" , viaShow f) , ("checkFeature", pretty featureMemberName <+> "::" <+> checkTDoc) @@ -124,9 +127,10 @@ renderReq = \case <+> sTyDoc ) ] - pure ( otherInstReqs - , "RequireDeviceFeature" <> braceAssignmentList xs : otherDevReqs - ) + pure + ( otherInstReqs + , "RequireDeviceFeature" <> braceAssignmentList xs : otherDevReqs + ) SPIRVReqProperty p m v rs -> do RenderParams {..} <- input @@ -141,7 +145,7 @@ renderReq = \case propertyValueName = mkPatternName v (otherInstReqs, otherDevReqs) <- minVersionAndExtensionsReqs rs -- TODO, do this properly - checker <- if + checker <- if | v == "VK_TRUE" -> pure $ "\\p ->" <+> pretty propertyMemberName <+> parens ("p ::" <+> sTyDoc) @@ -164,14 +168,15 @@ renderReq = \case <+> pretty propertyMemberName <+> parens ("p ::" <+> sTyDoc) let xs = [("propertyName", viaShow p), ("checkProperty", checker)] - pure ( otherInstReqs - , "RequireDeviceProperty" <> braceAssignmentList xs : otherDevReqs - ) + pure + ( otherInstReqs + , "RequireDeviceProperty" <> braceAssignmentList xs : otherDevReqs + ) minVersionAndExtensionsReqs :: (HasRenderParams r, HasRenderElem r, HasErr r, HasSpecInfo r) => Vector Text - -> Sem r ([Doc ()],[Doc ()]) + -> Sem r ([Doc ()], [Doc ()]) minVersionAndExtensionsReqs rs = do SpecInfo {..} <- input let dependencies = nubOrd $ toList rs <> concatMap siExtensionDeps rs @@ -188,44 +193,41 @@ minVersionAndExtensionsReqs rs = do [] -> pure Nothing xs -> Just <$> versionReq (maximum xs) - pure ( maybe id ((:) . fst) v - [ "RequireInstanceExtension" <> braceAssignmentList - [ ("instanceExtensionLayerName" , "Nothing") - , ("instanceExtensionName" , e) - , ("instanceExtensionMinVersion", v) - ] - | (e, v) <- instanceExtensions + pure + ( maybe + id + ((:) . fst) + v + [ "RequireInstanceExtension" <> braceAssignmentList + [ ("instanceExtensionLayerName" , "Nothing") + , ("instanceExtensionName" , e) + , ("instanceExtensionMinVersion", v) ] - , maybe id ((:) . snd) v - [ "RequireDeviceExtension" <> braceAssignmentList - [ ("deviceExtensionLayerName" , "Nothing") - , ("deviceExtensionName" , e) - , ("deviceExtensionMinVersion", v) - ] - | (e, v) <- deviceExtensions + | (e, v) <- instanceExtensions + ] + , maybe + id + ((:) . snd) + v + [ "RequireDeviceExtension" <> braceAssignmentList + [ ("deviceExtensionLayerName" , "Nothing") + , ("deviceExtensionName" , e) + , ("deviceExtensionMinVersion", v) ] - ) + | (e, v) <- deviceExtensions + ] + ) extensionNamePattern :: (HasRenderElem r, HasRenderParams r, HasErr r, HasSpecInfo r) => Text -> Sem r RequireType extensionNamePattern p = do - RenderParams {..} <- input - SpecInfo {..} <- input + SpecInfo {..} <- input case parseVersion p of Just v -> pure . RequireVersion $ v Nothing -> do - -- TODO: do this properly lol - let patternPrefix = if - | p == "VK_KHR_maintenance2" -> "VK_KHR_MAINTENANCE2" - | p == "VK_NV_viewport_array2" -> "VK_NV_VIEWPORT_ARRAY2" - | "2" `T.isSuffixOf` p -> T.toUpper (T.init p) <> "_2" - | otherwise -> T.toUpper p - nameName = CName $ patternPrefix <> "_EXTENSION_NAME" - versionName = CName $ patternPrefix <> "_SPEC_VERSION" - let namePattern = mkPatternName nameName - versionPattern = mkPatternName versionName + (namePattern, versionPattern) <- extensionPatterns p tellImport namePattern tellImport versionPattern case siExtensionType p of @@ -246,27 +248,15 @@ data RequireType -- ^ _EXTENSION_NAME and _SPEC_VERSION versionReq - :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc (), Doc()) + :: (HasRenderParams r, HasRenderElem r, HasErr r) + => Version + -> Sem r (Doc (), Doc ()) versionReq v = do tellImportWithAll (mkName "Vulkan.Requirement.DeviceRequirement") tellImportWithAll (mkName "Vulkan.Requirement.InstanceRequirement") vDoc <- versionDoc v pure - ( "RequireInstanceVersion $" <+> vDoc - , "RequireDeviceVersion $" <+> vDoc - ) - -versionDoc - :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) -versionDoc v = do - tellImport (ConName "MAKE_VERSION") - (ma, mi, pa) <- case versionBranch v of - [ma] -> pure (ma, 0, 0) - [ma, mi] -> pure (ma, mi, 0) - [ma, mi, pa] -> pure (ma, mi, pa) - [] -> throw "Version branch has no components" - _ -> throw "Version branch has more than three components" - pure $ "MAKE_VERSION" <+> hsep (viaShow <$> [ma, mi, pa]) + ("RequireInstanceVersion $" <+> vDoc, "RequireDeviceVersion $" <+> vDoc) parseVersion :: Text -> Maybe Version parseVersion t = do @@ -293,4 +283,5 @@ bespokeStuff = do ---------------------------------------------------------------- braceAssignmentList :: [(Doc ann, Doc ann)] -> Doc ann -braceAssignmentList = encloseSep "{" "}" ", " . fmap (\(l, r) -> l <+> "=" <+> r) +braceAssignmentList = + encloseSep "{" "}" ", " . fmap (\(l, r) -> l <+> "=" <+> r) diff --git a/generate-new/vk/VK/Utils.hs b/generate-new/vk/VK/Utils.hs new file mode 100644 index 000000000..9f2ad01e9 --- /dev/null +++ b/generate-new/vk/VK/Utils.hs @@ -0,0 +1,46 @@ +module VK.Utils where + +import Data.Text +import qualified Data.Text as T +import Haskell.Name +import Polysemy +import Polysemy.Input +import Relude +import Render.Element +import Spec.Name ( CName(CName) ) +import Prettyprinter +import Data.Version +import Error + +extensionPatterns :: HasRenderParams r => Text -> Sem r (HName, HName) + -- ^ EXTENSION_NAME, SPEC_VERSION +extensionPatterns p = do + RenderParams {..} <- input + let patternPrefix = if + | p == "VK_KHR_maintenance2" + -> "VK_KHR_MAINTENANCE2" + | p == "VK_NV_viewport_array2" + -> "VK_NV_VIEWPORT_ARRAY2" + | p == "VK_EXT_swapchain_colorspace" + -> "EXT_SWAPCHAIN_COLOR_SPACE" + | p == "VK_QCOM_rotated_copy_commands" + -> "QCOM_rotated_copy_commands" + | "2" `T.isSuffixOf` p && not ("32" `T.isSuffixOf` p) + -> T.toUpper (T.init p) <> "_2" + | otherwise + -> T.toUpper p + nameName = CName $ patternPrefix <> "_EXTENSION_NAME" + versionName = CName $ patternPrefix <> "_SPEC_VERSION" + pure (mkPatternName nameName, mkPatternName versionName) + +versionDoc + :: (HasRenderParams r, HasRenderElem r, HasErr r) => Version -> Sem r (Doc ()) +versionDoc v = do + tellImport (ConName "MAKE_VERSION") + (ma, mi, pa) <- case versionBranch v of + [ma] -> pure (ma, 0, 0) + [ma, mi] -> pure (ma, mi, 0) + [ma, mi, pa] -> pure (ma, mi, pa) + [] -> throw "Version branch has no components" + _ -> throw "Version branch has more than three components" + pure $ "MAKE_VERSION" <+> hsep (viaShow <$> [ma, mi, pa]) From 3f8b51c71bbf96eab55de50bd5affca409f22ae8 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 00:21:29 +0800 Subject: [PATCH 36/70] Bump changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 27e36d293..21ca01fe6 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,7 @@ - Add `Vulkan.Requirement`, a module for specifying requirements for `Device`s and `Instance`s - Expose SPIR-V Extensions and Capabilities in `Vulkan.SPIRVRequirements` +- Expose extension dependencies in `Vulkan.Extensions.Dependencies` - Squash some warnings ## [3.7] - 2020-11-24 From 11c1ae54a7f7ff4ab1340d98d5269b8098459d0d Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 00:22:03 +0800 Subject: [PATCH 37/70] regenerate with Vulkan.Extensions.Dependencies --- src/Vulkan/Extensions.hs | 4 +- src/Vulkan/Extensions/Dependencies.hs | 481 ++++++++++++++++++++++++++ vulkan.cabal | 1 + 3 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 src/Vulkan/Extensions/Dependencies.hs diff --git a/src/Vulkan/Extensions.hs b/src/Vulkan/Extensions.hs index 8091058db..c29d4ca27 100644 --- a/src/Vulkan/Extensions.hs +++ b/src/Vulkan/Extensions.hs @@ -1,6 +1,7 @@ {-# language CPP #-} -- No documentation found for Chapter "Extensions" -module Vulkan.Extensions ( module Vulkan.Extensions.Handles +module Vulkan.Extensions ( module Vulkan.Extensions.Dependencies + , module Vulkan.Extensions.Handles , module Vulkan.Extensions.VK_AMD_buffer_marker , module Vulkan.Extensions.VK_AMD_device_coherent_memory , module Vulkan.Extensions.VK_AMD_display_native_hdr @@ -223,6 +224,7 @@ module Vulkan.Extensions ( module Vulkan.Extensions.Handles , module Vulkan.Extensions.VK_QCOM_render_pass_transform , module Vulkan.Extensions.VK_QCOM_rotated_copy_commands ) where +import Vulkan.Extensions.Dependencies import Vulkan.Extensions.Handles import Vulkan.Extensions.VK_AMD_buffer_marker import Vulkan.Extensions.VK_AMD_device_coherent_memory diff --git a/src/Vulkan/Extensions/Dependencies.hs b/src/Vulkan/Extensions/Dependencies.hs new file mode 100644 index 000000000..30874e492 --- /dev/null +++ b/src/Vulkan/Extensions/Dependencies.hs @@ -0,0 +1,481 @@ +{-# language CPP #-} +-- No documentation found for Chapter "Dependencies" +module Vulkan.Extensions.Dependencies () where + +import Data.Word (Word32) +import Data.ByteString (ByteString) +import Vulkan.NamedType ((:::)) +import Vulkan.Extensions.VK_AMD_display_native_hdr (pattern AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_core_properties2 (pattern AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_shader_core_properties (pattern AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_AMD_texture_gather_bias_lod (pattern AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME) +import Vulkan.Extensions.VK_ANDROID_external_memory_android_hardware_buffer (pattern ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME) +import Vulkan.Core10 (pattern API_VERSION_1_0) +import Vulkan.Extensions.VK_EXT_4444_formats (pattern EXT_4444_FORMATS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_acquire_xlib_display (pattern EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_astc_decode_mode (pattern EXT_ASTC_DECODE_MODE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_buffer_device_address (pattern EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_conservative_rasterization (pattern EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_debug_marker (pattern EXT_DEBUG_MARKER_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_debug_report (pattern EXT_DEBUG_REPORT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_descriptor_indexing (pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_device_memory_report (pattern EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_directfb_surface (pattern EXT_DIRECTFB_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_direct_mode_display (pattern EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_discard_rectangles (pattern EXT_DISCARD_RECTANGLES_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_display_control (pattern EXT_DISPLAY_CONTROL_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_display_surface_counter (pattern EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_extended_dynamic_state (pattern EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_external_memory_dma_buf (pattern EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_external_memory_host (pattern EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_density_map2 (pattern EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_density_map (pattern EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_fragment_shader_interlock (pattern EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_full_screen_exclusive (pattern EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_hdr_metadata (pattern EXT_HDR_METADATA_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_headless_surface (pattern EXT_HEADLESS_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_host_query_reset (pattern EXT_HOST_QUERY_RESET_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_image_drm_format_modifier (pattern EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_image_robustness (pattern EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_inline_uniform_block (pattern EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_line_rasterization (pattern EXT_LINE_RASTERIZATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_memory_budget (pattern EXT_MEMORY_BUDGET_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_memory_priority (pattern EXT_MEMORY_PRIORITY_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_metal_surface (pattern EXT_METAL_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_pci_bus_info (pattern EXT_PCI_BUS_INFO_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_queue_family_foreign (pattern EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_sampler_filter_minmax (pattern EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_sample_locations (pattern EXT_SAMPLE_LOCATIONS_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_scalar_block_layout (pattern EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_atomic_float (pattern EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_demote_to_helper_invocation (pattern EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_shader_image_atomic_int64 (pattern EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_subgroup_size_control (pattern EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_swapchain_colorspace (pattern EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_texel_buffer_alignment (pattern EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_texture_compression_astc_hdr (pattern EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_transform_feedback (pattern EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_vertex_attribute_divisor (pattern EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) +import Vulkan.Extensions.VK_EXT_ycbcr_image_arrays (pattern EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME) +import Vulkan.Extensions.VK_FUCHSIA_imagepipe_surface (pattern FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_GGP_frame_token (pattern GGP_FRAME_TOKEN_EXTENSION_NAME) +import Vulkan.Extensions.VK_GGP_stream_descriptor_surface (pattern GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_GOOGLE_display_timing (pattern GOOGLE_DISPLAY_TIMING_EXTENSION_NAME) +import Vulkan.Extensions.VK_INTEL_shader_integer_functions2 (pattern INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_16bit_storage (pattern KHR_16BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_8bit_storage (pattern KHR_8BIT_STORAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_acceleration_structure (pattern KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_android_surface (pattern KHR_ANDROID_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_bind_memory2 (pattern KHR_BIND_MEMORY_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_buffer_device_address (pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_copy_commands2 (pattern KHR_COPY_COMMANDS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_create_renderpass2 (pattern KHR_CREATE_RENDERPASS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_dedicated_allocation (pattern KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_deferred_host_operations (pattern KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_depth_stencil_resolve (pattern KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_device_group_creation (pattern KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_device_group (pattern KHR_DEVICE_GROUP_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_display (pattern KHR_DISPLAY_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_display_swapchain (pattern KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_driver_properties (pattern KHR_DRIVER_PROPERTIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_fence_capabilities (pattern KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_fence (pattern KHR_EXTERNAL_FENCE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_fence_fd (pattern KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_fence_win32 (pattern KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_memory_capabilities (pattern KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_memory (pattern KHR_EXTERNAL_MEMORY_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_memory_fd (pattern KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_memory_win32 (pattern KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_semaphore_capabilities (pattern KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_semaphore (pattern KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_semaphore_fd (pattern KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_external_semaphore_win32 (pattern KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_fragment_shading_rate (pattern KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_get_display_properties2 (pattern KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_get_memory_requirements2 (pattern KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 (pattern KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_get_surface_capabilities2 (pattern KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_imageless_framebuffer (pattern KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_image_format_list (pattern KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_incremental_present (pattern KHR_INCREMENTAL_PRESENT_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_maintenance1 (pattern KHR_MAINTENANCE1_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_maintenance2 (pattern KHR_MAINTENANCE2_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_maintenance3 (pattern KHR_MAINTENANCE3_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_multiview (pattern KHR_MULTIVIEW_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_performance_query (pattern KHR_PERFORMANCE_QUERY_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_pipeline_executable_properties (pattern KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_portability_subset (pattern KHR_PORTABILITY_SUBSET_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_push_descriptor (pattern KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_query (pattern KHR_RAY_QUERY_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline (pattern KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_sampler_ycbcr_conversion (pattern KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_separate_depth_stencil_layouts (pattern KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_atomic_int64 (pattern KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_clock (pattern KHR_SHADER_CLOCK_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float16_int8 (pattern KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_float_controls (pattern KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_subgroup_extended_types (pattern KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shader_terminate_invocation (pattern KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_shared_presentable_image (pattern KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_spirv_1_4 (pattern KHR_SPIRV_1_4_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_storage_buffer_storage_class (pattern KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_surface (pattern KHR_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_surface_protected_capabilities (pattern KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_swapchain (pattern KHR_SWAPCHAIN_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_swapchain_mutable_format (pattern KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_timeline_semaphore (pattern KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_uniform_buffer_standard_layout (pattern KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_variable_pointers (pattern KHR_VARIABLE_POINTERS_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_wayland_surface (pattern KHR_WAYLAND_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_win32_keyed_mutex (pattern KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_win32_surface (pattern KHR_WIN32_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_xcb_surface (pattern KHR_XCB_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_KHR_xlib_surface (pattern KHR_XLIB_SURFACE_EXTENSION_NAME) +import Vulkan.Version (pattern MAKE_VERSION) +import Vulkan.Extensions.VK_MVK_ios_surface (pattern MVK_IOS_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_MVK_macos_surface (pattern MVK_MACOS_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NN_vi_surface (pattern NN_VI_SURFACE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NVX_multiview_per_view_attributes (pattern NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_compute_shader_derivatives (pattern NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_cooperative_matrix (pattern NV_COOPERATIVE_MATRIX_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_corner_sampled_image (pattern NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_coverage_reduction_mode (pattern NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_dedicated_allocation_image_aliasing (pattern NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_device_diagnostics_config (pattern NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_device_diagnostic_checkpoints (pattern NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_device_generated_commands (pattern NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_external_memory_capabilities (pattern NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_external_memory (pattern NV_EXTERNAL_MEMORY_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_external_memory_win32 (pattern NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_fragment_shader_barycentric (pattern NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_fragment_shading_rate_enums (pattern NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_framebuffer_mixed_samples (pattern NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_mesh_shader (pattern NV_MESH_SHADER_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_ray_tracing (pattern NV_RAY_TRACING_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_scissor_exclusive (pattern NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_image_footprint (pattern NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_sm_builtins (pattern NV_SHADER_SM_BUILTINS_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shader_subgroup_partitioned (pattern NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_shading_rate_image (pattern NV_SHADING_RATE_IMAGE_EXTENSION_NAME) +import Vulkan.Extensions.VK_NV_win32_keyed_mutex (pattern NV_WIN32_KEYED_MUTEX_EXTENSION_NAME) +import Vulkan.Extensions.VK_QCOM_render_pass_transform (pattern QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME) +import Vulkan.Extensions.VK_QCOM_rotated_copy_commands (pattern QCOM_rotated_copy_commands_EXTENSION_NAME) +-- | The set of other extensions required to use this extension +extensionDependencies :: ("extensionName" ::: ByteString) -> [ByteString] +extensionDependencies = \case + KHR_SWAPCHAIN_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_DISPLAY_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME -> + [KHR_SWAPCHAIN_EXTENSION_NAME, KHR_DISPLAY_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + KHR_XLIB_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_XCB_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_WAYLAND_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_ANDROID_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_WIN32_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + EXT_DEBUG_MARKER_EXTENSION_NAME -> [EXT_DEBUG_REPORT_EXTENSION_NAME] + EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + NV_CORNER_SAMPLED_IMAGE_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_MULTIVIEW_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_EXTERNAL_MEMORY_EXTENSION_NAME -> [NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME] + NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME -> + [NV_EXTERNAL_MEMORY_EXTENSION_NAME, NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME] + NV_WIN32_KEYED_MUTEX_EXTENSION_NAME -> + [ NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME + , NV_EXTERNAL_MEMORY_EXTENSION_NAME + , NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + ] + KHR_DEVICE_GROUP_EXTENSION_NAME -> [KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME] + NN_VI_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_ASTC_DECODE_MODE_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_MEMORY_EXTENSION_NAME -> + [KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME -> + [ KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME -> + [ KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME -> + [ KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME -> + [KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME -> + [ KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME + , KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME -> + [ KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME + , KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_PUSH_DESCRIPTOR_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_16BIT_STORAGE_EXTENSION_NAME -> + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] + KHR_INCREMENTAL_PRESENT_EXTENSION_NAME -> [KHR_SWAPCHAIN_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME -> [KHR_DISPLAY_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME -> + [EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME, KHR_DISPLAY_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME -> [KHR_DISPLAY_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + EXT_DISPLAY_CONTROL_EXTENSION_NAME -> + [ EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME + , KHR_SWAPCHAIN_EXTENSION_NAME + , KHR_DISPLAY_EXTENSION_NAME + , KHR_SURFACE_EXTENSION_NAME + ] + GOOGLE_DISPLAY_TIMING_EXTENSION_NAME -> [KHR_SWAPCHAIN_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME -> + [KHR_MULTIVIEW_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_DISCARD_RECTANGLES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + EXT_HDR_METADATA_EXTENSION_NAME -> [KHR_SWAPCHAIN_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME -> [KHR_MAINTENANCE2_EXTENSION_NAME, KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME] + KHR_CREATE_RENDERPASS_2_EXTENSION_NAME -> + [KHR_MULTIVIEW_EXTENSION_NAME, KHR_MAINTENANCE2_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME -> + [ KHR_SWAPCHAIN_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME + , KHR_SURFACE_EXTENSION_NAME + ] + KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_FENCE_EXTENSION_NAME -> + [KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME -> + [ KHR_EXTERNAL_FENCE_EXTENSION_NAME + , KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME -> + [ KHR_EXTERNAL_FENCE_EXTENSION_NAME + , KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_PERFORMANCE_QUERY_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_VARIABLE_POINTERS_EXTENSION_NAME -> + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] + KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME -> [KHR_DISPLAY_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + MVK_IOS_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + MVK_MACOS_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME -> + [ KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME -> + [ KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_DEDICATED_ALLOCATION_EXTENSION_NAME -> [KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME] + ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME -> + [ KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME + , KHR_DEDICATED_ALLOCATION_EXTENSION_NAME + , KHR_MAINTENANCE1_EXTENSION_NAME + , KHR_BIND_MEMORY_2_EXTENSION_NAME + , KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + ] + EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME -> + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, KHR_MAINTENANCE1_EXTENSION_NAME] + EXT_SAMPLE_LOCATIONS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME -> + [ EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_MAINTENANCE3_EXTENSION_NAME + ] + KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME -> + [ KHR_SPIRV_1_4_EXTENSION_NAME + , KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , KHR_MAINTENANCE3_EXTENSION_NAME + ] + KHR_RAY_QUERY_EXTENSION_NAME -> + [ KHR_SPIRV_1_4_EXTENSION_NAME + , KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME + , KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME + , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME + , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME + , KHR_MAINTENANCE3_EXTENSION_NAME + ] + KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME -> + [ KHR_MAINTENANCE1_EXTENSION_NAME + , KHR_BIND_MEMORY_2_EXTENSION_NAME + , KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME -> + [ KHR_BIND_MEMORY_2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME + , KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME + , KHR_MAINTENANCE1_EXTENSION_NAME + , KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + ] + EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME -> + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, KHR_MAINTENANCE3_EXTENSION_NAME] + KHR_PORTABILITY_SUBSET_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_SHADING_RATE_IMAGE_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_RAY_TRACING_EXTENSION_NAME -> + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME] + KHR_MAINTENANCE3_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_8BIT_STORAGE_EXTENSION_NAME -> + [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME] + EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME -> + [ KHR_EXTERNAL_MEMORY_EXTENSION_NAME + , KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_SHADER_CLOCK_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + GGP_FRAME_TOKEN_EXTENSION_NAME -> + [KHR_SWAPCHAIN_EXTENSION_NAME, GGP_STREAM_DESCRIPTOR_SURFACE_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + KHR_DRIVER_PROPERTIES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME -> + [ KHR_CREATE_RENDERPASS_2_EXTENSION_NAME + , KHR_MULTIVIEW_EXTENSION_NAME + , KHR_MAINTENANCE2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME -> + [ KHR_SWAPCHAIN_EXTENSION_NAME + , KHR_MAINTENANCE2_EXTENSION_NAME + , KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME + , KHR_SURFACE_EXTENSION_NAME + ] + NV_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_MESH_SHADER_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + INTEL_SHADER_INTEGER_FUNCTIONS_2_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_PCI_BUS_INFO_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME -> + [ KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME + , KHR_SWAPCHAIN_EXTENSION_NAME + , KHR_SURFACE_EXTENSION_NAME + ] + FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_METAL_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME -> + [ KHR_CREATE_RENDERPASS_2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_MULTIVIEW_EXTENSION_NAME + , KHR_MAINTENANCE2_EXTENSION_NAME + ] + AMD_SHADER_CORE_PROPERTIES_2_EXTENSION_NAME -> + [AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_SPIRV_1_4_EXTENSION_NAME -> + [KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_MEMORY_BUDGET_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_MEMORY_PRIORITY_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME -> + [KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + NV_DEDICATED_ALLOCATION_IMAGE_ALIASING_EXTENSION_NAME -> + [KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME] + KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME -> + [ KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_CREATE_RENDERPASS_2_EXTENSION_NAME + , KHR_MULTIVIEW_EXTENSION_NAME + , KHR_MAINTENANCE2_EXTENSION_NAME + ] + EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_COOPERATIVE_MATRIX_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME -> [NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME] + EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME -> + [ KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME + , KHR_MAINTENANCE1_EXTENSION_NAME + , KHR_BIND_MEMORY_2_EXTENSION_NAME + , KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + ] + KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME -> + [ KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_SURFACE_EXTENSION_NAME + , KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME + , KHR_SWAPCHAIN_EXTENSION_NAME + ] + EXT_HEADLESS_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_LINE_RASTERIZATION_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_HOST_QUERY_RESET_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME -> [KHR_SWAPCHAIN_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + NV_FRAGMENT_SHADING_RATE_ENUMS_EXTENSION_NAME -> + [ KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME + , KHR_CREATE_RENDERPASS_2_EXTENSION_NAME + , KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + , KHR_MULTIVIEW_EXTENSION_NAME + , KHR_MAINTENANCE2_EXTENSION_NAME + ] + EXT_FRAGMENT_DENSITY_MAP_2_EXTENSION_NAME -> + [EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + QCOM_rotated_copy_commands_EXTENSION_NAME -> + [KHR_SWAPCHAIN_EXTENSION_NAME, KHR_COPY_COMMANDS_2_EXTENSION_NAME, KHR_SURFACE_EXTENSION_NAME] + EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_4444_FORMATS_EXTENSION_NAME -> [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] + EXT_DIRECTFB_SURFACE_EXTENSION_NAME -> [KHR_SURFACE_EXTENSION_NAME] + _ -> [] + +-- | The minimum required API version to use this extension +extensionCoreRequirement :: ("extensionName" ::: ByteString) -> Word32 +extensionCoreRequirement = \case + KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + KHR_RAY_QUERY_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + NV_SHADER_SM_BUILTINS_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + KHR_SPIRV_1_4_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME -> MAKE_VERSION 1 1 0 + _ -> API_VERSION_1_0 + diff --git a/vulkan.cabal b/vulkan.cabal index 05df0e255..93c33e6ac 100644 --- a/vulkan.cabal +++ b/vulkan.cabal @@ -248,6 +248,7 @@ library Vulkan.Dynamic Vulkan.Exception Vulkan.Extensions + Vulkan.Extensions.Dependencies Vulkan.Extensions.Handles Vulkan.Extensions.VK_AMD_buffer_marker Vulkan.Extensions.VK_AMD_device_coherent_memory From 8e0240c4d3a4851b4e93787659fe806711e4d5af Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 00:49:15 +0800 Subject: [PATCH 38/70] Make instance/device creation functions less polymorphic --- utils/src/Vulkan/Utils/Initialization.hs | 38 ++++++++++-------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/utils/src/Vulkan/Utils/Initialization.hs b/utils/src/Vulkan/Utils/Initialization.hs index fa87011d9..1be9d3cc8 100644 --- a/utils/src/Vulkan/Utils/Initialization.hs +++ b/utils/src/Vulkan/Utils/Initialization.hs @@ -12,22 +12,22 @@ module Vulkan.Utils.Initialization ) where import Control.Monad.IO.Class +import Control.Monad.Trans.Resource +import Data.Bits import Data.Foldable import Data.Maybe import Data.Ord import Data.Text ( Text ) import Data.Text.Encoding ( decodeUtf8 ) +import Vulkan.CStruct.Extends import Vulkan.Core10 import Vulkan.Extensions.VK_EXT_debug_utils import Vulkan.Extensions.VK_EXT_validation_features -import Data.Bits -import Vulkan.Zero -import Vulkan.Utils.Debug -import Control.Monad.Trans.Resource import Vulkan.Requirement -import Vulkan.CStruct.Extends +import Vulkan.Utils.Debug import Vulkan.Utils.Internal import Vulkan.Utils.Requirements +import Vulkan.Zero ---------------------------------------------------------------- -- Instance @@ -40,15 +40,12 @@ import Vulkan.Utils.Requirements -- @VK_LAYER_KHRONOS_validation@ layer) is available is it will be enabled and -- best practices messages enabled. createDebugInstanceFromRequirements - :: forall m es r o - . ( MonadResource m - , Extendss InstanceCreateInfo es - , PokeChain es - , Foldable r - , Foldable o - ) - => r InstanceRequirement - -> o InstanceRequirement + :: forall m es + . (MonadResource m, Extendss InstanceCreateInfo es, PokeChain es) + => [InstanceRequirement] + -- ^ Required + -> [InstanceRequirement] + -- ^ Optional -> InstanceCreateInfo es -> m Instance createDebugInstanceFromRequirements required optional baseCreateInfo = do @@ -99,14 +96,11 @@ createDebugInstanceFromRequirements required optional baseCreateInfo = do -- Will throw an 'IOError in the case of unsatisfied non-optional requirements. -- Unsatisfied requirements will be listed on stderr. createInstanceFromRequirements - :: ( MonadResource m - , Extendss InstanceCreateInfo es - , PokeChain es - , Traversable r - , Traversable o - ) - => r InstanceRequirement - -> o InstanceRequirement + :: (MonadResource m, Extendss InstanceCreateInfo es, PokeChain es) + => [InstanceRequirement] + -- ^ Required + -> [InstanceRequirement] + -- ^ Optional -> InstanceCreateInfo es -> m Instance createInstanceFromRequirements required optional baseCreateInfo = do From c68d9ae6812b9895226bd47688b3bf9cee2d76c3 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 01:00:07 +0800 Subject: [PATCH 39/70] Use new requirements utils in examples --- examples/hlsl/Init.hs | 26 +++++++++++++++++--------- examples/resize/Init.hs | 9 ++++----- examples/timeline-semaphore/Main.hs | 23 +++++++++++++++++------ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/examples/hlsl/Init.hs b/examples/hlsl/Init.hs index 3c7a878c5..bf82ade3a 100644 --- a/examples/hlsl/Init.hs +++ b/examples/hlsl/Init.hs @@ -39,6 +39,7 @@ import Vulkan.Core10 as Vk import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain +import Vulkan.Requirement import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment import Vulkan.Zero @@ -65,10 +66,12 @@ createInstance win = do , apiVersion = myApiVersion } } - extensions = - [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] - <> windowExtensions - createDebugInstanceWithExtensions [] [] extensions [] createInfo + reqs = + (\n -> RequireInstanceExtension Nothing n minBound) + <$> ( KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + : windowExtensions + ) + createDebugInstanceFromRequirements reqs [] createInfo ---------------------------------------------------------------- -- Device creation @@ -93,11 +96,16 @@ createDevice inst win = do sayErr . ("Using device: " <>) =<< physicalDeviceName phys let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } - ::& PhysicalDeviceTimelineSemaphoreFeatures True - :& () - extensions = - [KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, KHR_SWAPCHAIN_EXTENSION_NAME] - dev <- createDeviceWithExtensions phys [] extensions deviceCreateInfo + reqs = + [ RequireDeviceExtension Nothing KHR_SWAPCHAIN_EXTENSION_NAME minBound + , RequireDeviceExtension Nothing + KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME + minBound + , RequireDeviceFeature "timeline semaphores" + timelineSemaphore + (\s -> s { timelineSemaphore = True }) + ] + dev <- createDeviceFromRequirements phys reqs [] deviceCreateInfo requireCommands inst dev queues <- liftIO $ pdiGetQueues pdi dev pure (phys, dev, queues, surf) diff --git a/examples/resize/Init.hs b/examples/resize/Init.hs index 36b6aa8da..f2b194b85 100644 --- a/examples/resize/Init.hs +++ b/examples/resize/Init.hs @@ -36,7 +36,8 @@ import VulkanMemoryAllocator ( Allocator , withAllocator ) -import Vulkan.Utils.Initialization ( createDebugInstanceWithExtensions +import Vulkan.Requirement +import Vulkan.Utils.Initialization ( createDebugInstanceFromRequirements ) myApiVersion :: Word32 @@ -49,10 +50,8 @@ myApiVersion = API_VERSION_1_0 -- | Create an instance with a debug messenger and validation createInstance :: forall m . MonadResource m => [ByteString] -> m Instance createInstance extraExtensions = do - createDebugInstanceWithExtensions - [] - [] - extraExtensions + createDebugInstanceFromRequirements + [RequireInstanceExtension Nothing n minBound | n <- extraExtensions] [] zero { applicationInfo = Just zero { applicationName = Nothing diff --git a/examples/timeline-semaphore/Main.hs b/examples/timeline-semaphore/Main.hs index 0d4f601ff..fca64e3d4 100644 --- a/examples/timeline-semaphore/Main.hs +++ b/examples/timeline-semaphore/Main.hs @@ -30,6 +30,7 @@ import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore import Vulkan.Exception import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 import Vulkan.Extensions.VK_KHR_timeline_semaphore +import Vulkan.Requirement import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment import Vulkan.Zero @@ -86,8 +87,13 @@ createInstance = , apiVersion = API_VERSION_1_0 } } - extensions = [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] - in createDebugInstanceWithExtensions [] [] extensions [] createInfo + reqs = + [ RequireInstanceExtension + Nothing + KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + minBound + ] + in createDebugInstanceFromRequirements reqs [] createInfo createDevice :: forall m @@ -101,10 +107,15 @@ createDevice inst = do sayErr . ("Using device: " <>) =<< physicalDeviceName phys let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } - ::& PhysicalDeviceTimelineSemaphoreFeatures True - :& () - extensions = [KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME] - dev <- createDeviceWithExtensions phys [] extensions deviceCreateInfo + reqs = + [ RequireDeviceExtension Nothing + KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME + minBound + , RequireDeviceFeature "timeline semaphores" + Timeline.timelineSemaphore + (\s -> s { Timeline.timelineSemaphore = True }) + ] + dev <- createDeviceFromRequirements phys reqs [] deviceCreateInfo queues <- liftIO $ pdiGetQueues pdi dev pure (phys, dev, queues) From ed7c5ec8c5aaa95ea6d42fd2af4eccd02bb7c43a Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 01:02:22 +0800 Subject: [PATCH 40/70] Credit sheaf in changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 21ca01fe6..826f262f1 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,8 @@ - Expose extension dependencies in `Vulkan.Extensions.Dependencies` - Squash some warnings +Thanks to @sheaf for their help with this release! + ## [3.7] - 2020-11-24 - Bump API version to v1.2.162 - This is a breaking change to anyone using VK_KHR_ray_tracing (which no From 852a85d7a71fb3c734b5115fdb8acb7cb8d01225 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 10:00:21 +0800 Subject: [PATCH 41/70] Remove unused variable --- utils/src/Vulkan/Utils/Requirements.hs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index 2bfc38fb1..b627726dc 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -470,7 +470,7 @@ getLookupExtension mbPhys deviceExtensionLayers = do withDevicePropertyStructs :: forall a . [DeviceRequirement] - -> ChainCont PhysicalDeviceProperties2 DevicePropertyChain a + -> ChainCont DevicePropertyChain a -> a withDevicePropertyStructs = go @'[] [] where @@ -479,7 +479,7 @@ withDevicePropertyStructs = go @'[] [] . DevicePropertyChain fs => [SomeTypeRep] -> [DeviceRequirement] - -> ChainCont PhysicalDeviceProperties2 DevicePropertyChain a + -> ChainCont DevicePropertyChain a -> a go seen reqs f = case reqs of -- We've been through all the reqs, call the continuation with the types @@ -496,7 +496,7 @@ withDevicePropertyStructs = go @'[] [] withDeviceFeatureStructs :: forall a . [DeviceRequirement] - -> ChainCont PhysicalDeviceFeatures2 DeviceFeatureChain a + -> ChainCont DeviceFeatureChain a -> a withDeviceFeatureStructs = go @'[] [] where @@ -505,7 +505,7 @@ withDeviceFeatureStructs = go @'[] [] . DeviceFeatureChain fs => [SomeTypeRep] -> [DeviceRequirement] - -> ChainCont PhysicalDeviceFeatures2 DeviceFeatureChain a + -> ChainCont DeviceFeatureChain a -> a go seen reqs f = case reqs of -- We've been through all the reqs, call the continuation with the types @@ -525,11 +525,7 @@ instance (KnownChain es, Extendss PhysicalDeviceFeatures2 es, Show (Chain es)) = class (KnownChain es, Extendss PhysicalDeviceProperties2 es) => DevicePropertyChain es where instance (KnownChain es, Extendss PhysicalDeviceProperties2 es) => DevicePropertyChain es where -type ChainCont h c a = - forall (es :: [Type]) - . (c es) -- - => Proxy es - -> a +type ChainCont c a = forall (es :: [Type]) . (c es) => Proxy es -> a ---------------------------------------------------------------- -- Utils From c3f412e961b476aad88041e0981d9eabdbfa939e Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 10:03:09 +0800 Subject: [PATCH 42/70] wobble argument ordering in createDeviceFromRequirements --- utils/src/Vulkan/Utils/Initialization.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/src/Vulkan/Utils/Initialization.hs b/utils/src/Vulkan/Utils/Initialization.hs index 1be9d3cc8..26cae3b51 100644 --- a/utils/src/Vulkan/Utils/Initialization.hs +++ b/utils/src/Vulkan/Utils/Initialization.hs @@ -123,14 +123,14 @@ createInstanceFromRequirements required optional baseCreateInfo = do createDeviceFromRequirements :: forall m . MonadResource m - => PhysicalDevice - -> [DeviceRequirement] + => [DeviceRequirement] -- ^ Required -> [DeviceRequirement] -- ^ Optional + -> PhysicalDevice -> DeviceCreateInfo '[] -> m Device -createDeviceFromRequirements phys required optional baseCreateInfo = do +createDeviceFromRequirements required optional phys baseCreateInfo = do (mbDCI, rrs, ors) <- checkDeviceRequirements required optional phys From 08a3c488b265faf17dfc9af69e72f261f3fa339e Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 10:03:26 +0800 Subject: [PATCH 43/70] Correct out of date comment --- utils/src/Vulkan/Utils/Requirements.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index b627726dc..649f5309f 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -62,9 +62,8 @@ checkInstanceRequirements -> o InstanceRequirement -- ^ Optional requests -> InstanceCreateInfo es - -- ^ An 'InstanceCreateInfo' with no extensions. If you need elements in the - -- struct chain you can add them later with - -- 'Vulkan.CStruct.Extends.extendSomeStruct' + -- ^ An 'InstanceCreateInfo', this will be returned appropriately modified by + -- the requirements -> m ( Maybe (InstanceCreateInfo es) , r RequirementResult From 5e1f949fa56293dac4f764b96937070ac3ae1394 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 10:06:45 +0800 Subject: [PATCH 44/70] Correct out of date variable name --- utils/src/Vulkan/Utils/Requirements.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index 649f5309f..42b6676f1 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -450,11 +450,11 @@ getLookupExtension -> ByteString -> Maybe ExtensionProperties ) -getLookupExtension mbPhys deviceExtensionLayers = do +getLookupExtension mbPhys extensionLayers = do let enumerate = maybe enumerateInstanceExtensionProperties enumerateDeviceExtensionProperties mbPhys - extensions <- for (nubOrd deviceExtensionLayers) $ \layer -> do + extensions <- for (nubOrd extensionLayers) $ \layer -> do (_, props) <- enumerate layer pure (layer, props) let extensionMap = Map.fromListWith (<>) extensions From 68f8c51d4297d49539b046bec3ff21ee5400e429 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 10:51:17 +0800 Subject: [PATCH 45/70] Squash warnings --- utils/package.yaml | 3 ++ utils/src/Vulkan/Utils/Misc.hs | 19 +++++---- utils/src/Vulkan/Utils/Requirements.hs | 59 ++++++++++++++++++++++---- utils/vulkan-utils.cabal | 2 + 4 files changed, 65 insertions(+), 18 deletions(-) diff --git a/utils/package.yaml b/utils/package.yaml index f5c3f387d..0b3587b76 100644 --- a/utils/package.yaml +++ b/utils/package.yaml @@ -51,6 +51,9 @@ custom-setup: - Cabal - cabal-doctest >= 1 && <1.1 +ghc-options: + - -Wall + default-extensions: - ConstraintKinds - DataKinds diff --git a/utils/src/Vulkan/Utils/Misc.hs b/utils/src/Vulkan/Utils/Misc.hs index 688a38c12..6637b94e5 100644 --- a/utils/src/Vulkan/Utils/Misc.hs +++ b/utils/src/Vulkan/Utils/Misc.hs @@ -86,15 +86,16 @@ showBits :: forall a . (Show a, FiniteBits a) => a -> String showBits a = if a == zeroBits then "zeroBits" else intercalate " .|. " $ fmap show (setBits a) - where - setBits :: a -> [a] - setBits a = - [ b - | -- lol, is this really necessary - p <- [countTrailingZeros a .. finiteBitSize a - countLeadingZeros a - 1] - , let b = bit p - , a .&&. b - ] + +-- | The list of bits which are set +setBits :: FiniteBits a => a -> [a] +setBits a = + [ b + | -- lol, is this really necessary + p <- [countTrailingZeros a .. finiteBitSize a - countLeadingZeros a - 1] + , let b = bit p + , a .&&. b + ] -- | Check if the intersection of bits is non-zero (.&&.) :: Bits a => a -> a -> Bool diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index 42b6676f1..3b3b77b21 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -86,10 +86,10 @@ checkInstanceRequirements required optional baseCreateInfo = do unless (res == Satisfied) (put False) pure res - (o, goodOptions) <- flip runStateT mempty $ for optional $ \r -> - case checkInstanceRequest foundVersion layerProps lookupExtension r of + (o, goodOptions) <- flip runStateT mempty $ for optional $ \o -> + case checkInstanceRequest foundVersion layerProps lookupExtension o of res -> do - when (res == Satisfied) $ modify (r :) + when (res == Satisfied) $ modify (o :) pure res let ici = do @@ -201,10 +201,10 @@ checkDeviceRequirements required optional phys baseCreateInfo = do unless (res == Satisfied) (put False) pure res - (o, goodOptions) <- flip runStateT mempty $ for optional $ \r -> - case checkDeviceRequest feats props lookupExtension r of + (o, goodOptions) <- flip runStateT mempty $ for optional $ \o -> + case checkDeviceRequest feats props lookupExtension o of res -> do - when (res == Satisfied) $ modify (r :) + when (res == Satisfied) $ modify (o :) pure res -- @@ -216,7 +216,6 @@ checkDeviceRequirements required optional phys baseCreateInfo = do baseCreateInfo pure (dci, r, o) - {-# ANN makeDeviceCreateInfo ("HLint: ignore Move guards forward" :: String) #-} -- | Generate 'DeviceCreateInfo' from some requirements. -- @@ -526,13 +525,55 @@ instance (KnownChain es, Extendss PhysicalDeviceProperties2 es) => DevicePropert type ChainCont c a = forall (es :: [Type]) . (c es) => Proxy es -> a +---------------------------------------------------------------- +-- Helpers for getting features and properties without using the extended +-- versions of the functions if possible. +---------------------------------------------------------------- + +getPhysicalDeviceFeaturesMaybe + :: forall fs m + . (MonadIO m, KnownChain fs, Extendss PhysicalDeviceFeatures2 fs) + => PhysicalDevice + -> m (Maybe (PhysicalDeviceFeatures2 fs)) +getPhysicalDeviceFeaturesMaybe = getMaybe pVkGetPhysicalDeviceFeatures2 + (PhysicalDeviceFeatures2 ()) + getPhysicalDeviceFeatures + getPhysicalDeviceFeatures2 + +getPhysicalDevicePropertiesMaybe + :: forall fs m + . (MonadIO m, KnownChain fs, Extendss PhysicalDeviceProperties2 fs) + => PhysicalDevice + -> m (Maybe (PhysicalDeviceProperties2 fs)) +getPhysicalDevicePropertiesMaybe = getMaybe pVkGetPhysicalDeviceProperties2 + (PhysicalDeviceProperties2 ()) + getPhysicalDeviceProperties + getPhysicalDeviceProperties2 + +getMaybe + :: forall fs s1 s2 m + . (MonadIO m, KnownChain fs, Extendss s2 fs) + => ( InstanceCmds + -> FunPtr (Ptr PhysicalDevice_T -> Ptr (SomeStruct s2) -> IO ()) + ) + -> (s1 -> s2 '[]) + -> (PhysicalDevice -> m s1) + -> (PhysicalDevice -> m (s2 fs)) + -> PhysicalDevice + -> m (Maybe (s2 fs)) +getMaybe funPtr wrapper2 get1 get2 phys = + let hasFunPtr = funPtr (instanceCmds (phys :: PhysicalDevice)) /= nullFunPtr + in case knownChainNull @fs of + Just Refl -> Just . wrapper2 <$> get1 phys + Nothing -> if hasFunPtr then Just <$> get2 phys else pure Nothing + ---------------------------------------------------------------- -- Utils ---------------------------------------------------------------- showVersion :: Word32 -> String -showVersion ver = unwords ["MAKE_VERSION", show maj, show min, show patch] - where MAKE_VERSION maj min patch = ver +showVersion ver = unwords ["MAKE_VERSION", show ma, show mi, show pa] + where MAKE_VERSION ma mi pa = ver data Has c a where Has :: c a => Has c a diff --git a/utils/vulkan-utils.cabal b/utils/vulkan-utils.cabal index ccaec0bed..fe78a3195 100644 --- a/utils/vulkan-utils.cabal +++ b/utils/vulkan-utils.cabal @@ -47,6 +47,7 @@ library hs-source-dirs: src default-extensions: ConstraintKinds DataKinds DefaultSignatures DeriveAnyClass DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NamedFieldPuns NoMonomorphismRestriction OverloadedStrings PartialTypeSignatures PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns + ghc-options: -Wall c-sources: cbits/DebugCallback.c build-depends: @@ -77,6 +78,7 @@ test-suite doctests hs-source-dirs: test/doctest default-extensions: ConstraintKinds DataKinds DefaultSignatures DeriveAnyClass DeriveFoldable DeriveFunctor DeriveTraversable DerivingStrategies DuplicateRecordFields FlexibleContexts FlexibleInstances GADTs GeneralizedNewtypeDeriving InstanceSigs LambdaCase MagicHash NamedFieldPuns NoMonomorphismRestriction OverloadedStrings PartialTypeSignatures PatternSynonyms PolyKinds QuantifiedConstraints RankNTypes RecordWildCards RoleAnnotations ScopedTypeVariables StandaloneDeriving Strict TupleSections TypeApplications TypeFamilyDependencies TypeOperators TypeSynonymInstances ViewPatterns + ghc-options: -Wall build-depends: base , doctest From e9192bfdc56baf48c86ba6e7d79ab31fa05060af Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 10:52:19 +0800 Subject: [PATCH 46/70] Use 1.0 api functions where possible and fail gracefully if not --- utils/src/Vulkan/Utils/Requirements.hs | 55 ++++++++++++++++++++------ 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index 3b3b77b21..a9335dd0f 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -35,6 +35,10 @@ import Data.Typeable ( eqT ) import qualified Data.Vector as V import Data.Vector ( Vector ) import Data.Word +import Foreign.Ptr ( FunPtr + , Ptr + , nullFunPtr + ) import GHC.Base ( Proxy# ) import GHC.Exts ( proxy# ) import Type.Reflection @@ -45,6 +49,11 @@ import Vulkan.CStruct.Extends import Vulkan.Core10 import Vulkan.Core11.DeviceInitialization import Vulkan.Core11.Promoted_From_VK_KHR_get_physical_device_properties2 +import Vulkan.Dynamic ( InstanceCmds + ( pVkGetPhysicalDeviceFeatures2 + , pVkGetPhysicalDeviceProperties2 + ) + ) import Vulkan.NamedType import Vulkan.Requirement import Vulkan.Version @@ -187,8 +196,8 @@ checkDeviceRequirements required optional phys baseCreateInfo = do -- -- Fetch everything -- - feats <- getPhysicalDeviceFeatures2 @fs phys - props <- getPhysicalDeviceProperties2 @ps phys + feats <- getPhysicalDeviceFeaturesMaybe @fs phys + props <- getPhysicalDevicePropertiesMaybe @ps phys lookupExtension <- getLookupExtension (Just phys) [ deviceExtensionLayerName @@ -270,8 +279,8 @@ makeDeviceCreateInfo allReqs baseCreateInfo = checkDeviceRequest :: forall fs ps . (KnownChain fs, KnownChain ps) - => PhysicalDeviceFeatures2 fs - -> PhysicalDeviceProperties2 ps + => Maybe (PhysicalDeviceFeatures2 fs) + -> Maybe (PhysicalDeviceProperties2 ps) -> ( ("layerName" ::: Maybe ByteString) -> ("extensionName" ::: ByteString) -> Maybe ExtensionProperties @@ -281,28 +290,33 @@ checkDeviceRequest -- ^ The requirement to test -> RequirementResult -- ^ The result -checkDeviceRequest feats props lookupExtension = \case +checkDeviceRequest mbFeats mbProps lookupExtension = \case RequireDeviceVersion minVersion - | foundVersion <- apiVersion + | Just props <- mbProps + , foundVersion <- apiVersion (properties (props :: PhysicalDeviceProperties2 ps) :: PhysicalDeviceProperties ) -> if foundVersion >= minVersion then Satisfied else UnsatisfiedDeviceVersion (Unsatisfied minVersion foundVersion) + | otherwise + -> UnattemptedProperties "apiVersion" - RequireDeviceFeature { featureName, checkFeature } -> - case getFeatureStruct feats of + RequireDeviceFeature { featureName, checkFeature } + | Just feats <- mbFeats -> case getFeatureStruct feats of Nothing -> error "Impossible: didn't find requested feature in struct chain" Just s -> if checkFeature s then Satisfied else UnsatisfiedFeature featureName + | otherwise -> UnattemptedFeatures featureName - RequireDeviceProperty { propertyName, checkProperty } -> - case getPropertyStruct props of + RequireDeviceProperty { propertyName, checkProperty } + | Just props <- mbProps -> case getPropertyStruct props of Nothing -> error "Impossible: didn't find requested property in struct chain" Just s -> if checkProperty s then Satisfied else UnsatisfiedProperty propertyName + | otherwise -> UnattemptedProperties propertyName RequireDeviceExtension { deviceExtensionLayerName, deviceExtensionName, deviceExtensionMinVersion } | Just eProps <- lookupExtension deviceExtensionLayerName @@ -312,6 +326,7 @@ checkDeviceRequest feats props lookupExtension = \case | otherwise -> UnsatisfiedDeviceExtension deviceExtensionName + ---------------------------------------------------------------- -- Results ---------------------------------------------------------------- @@ -321,6 +336,12 @@ checkDeviceRequest feats props lookupExtension = \case data RequirementResult = Satisfied -- ^ All the requirements were met + | UnattemptedProperties ByteString + -- ^ Didn't attempt this check because it required + -- getPhysicalDeviceProperties2 which wasn't loaded + | UnattemptedFeatures ByteString + -- ^ Didn't attempt this check because it required + -- getPhysicalDeviceFeatures2 which wasn't loaded | MissingLayer ByteString -- ^ A Layer was not found | UnsatisfiedDeviceVersion (Unsatisfied Word32) @@ -368,7 +389,15 @@ requirementReport required optional = prettyRequirementResult :: RequirementResult -> String prettyRequirementResult = \case - Satisfied -> "Satisfied" + Satisfied -> "Satisfied" + UnattemptedProperties n -> + "Did not attempt to check " + <> show n + <> " because the 'getPhysicalDeviceProperties' function was not loaded" + UnattemptedFeatures n -> + "Did not attempt to check " + <> show n + <> " because the 'getPhysicalDeviceFeatures' function was not loaded" MissingLayer n -> "Missing layer: " <> show n UnsatisfiedInstanceVersion u -> "Unsatisfied Instance Version: " <> p u UnsatisfiedDeviceVersion u -> "Unsatisfied Device Version: " <> p u @@ -397,9 +426,12 @@ class (PeekChain xs, PokeChain xs) => KnownChain (xs :: [Type]) where -- | If the given structure can be found within a chain, return a lens to it. -- Otherwise, return 'Nothing'. has :: forall a. Typeable a => Proxy# a -> Maybe (Chain xs -> a, (a -> a) -> (Chain xs -> Chain xs)) + -- | Is this chain empty? + knownChainNull :: Maybe (xs :~: '[]) instance KnownChain '[] where has _ = Nothing + knownChainNull = Just Refl instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain (x ': xs) where has (px :: Proxy# a) @@ -407,6 +439,7 @@ instance (Typeable x, ToCStruct x, FromCStruct x, KnownChain xs) => KnownChain ( = Just (fst,first) | otherwise = ((. snd) *** (second .)) <$> has px + knownChainNull = Nothing getPropertyStruct :: forall s es From 0a59ebc9ce87f6b60dca93afc122f1c78abe4e34 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 11:00:51 +0800 Subject: [PATCH 47/70] Fix utils for 8.8.4 and below --- utils/src/Vulkan/Utils/Requirements.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index a9335dd0f..3d8a5b777 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -464,7 +464,7 @@ getStruct . (Typeable h, Typeable s, KnownChain es, Extensible h) => h es -> Maybe s -getStruct c = ($ getNext c) . fst <$> has (proxy# @s) +getStruct c = ($ getNext c) . fst <$> has (proxy# :: Proxy# s) ---------------------------------------------------------------- -- Helpers for 'Device' and 'Instance' extensions From 411e42a02898d4057d98cf403ef5da6b69ed076e Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 14:31:02 +0800 Subject: [PATCH 48/70] Add QuasiQuoter for specifying device requirements --- utils/src/Vulkan/Utils/Internal.hs | 11 + utils/src/Vulkan/Utils/Requirements.hs | 10 +- utils/src/Vulkan/Utils/Requirements/TH.hs | 288 ++++++++++++++++++++++ utils/src/Vulkan/Utils/ShaderQQ.hs | 15 +- utils/vulkan-utils.cabal | 1 + 5 files changed, 306 insertions(+), 19 deletions(-) create mode 100644 utils/src/Vulkan/Utils/Requirements/TH.hs diff --git a/utils/src/Vulkan/Utils/Internal.hs b/utils/src/Vulkan/Utils/Internal.hs index 373dec1a6..dcaea23d5 100644 --- a/utils/src/Vulkan/Utils/Internal.hs +++ b/utils/src/Vulkan/Utils/Internal.hs @@ -8,6 +8,7 @@ import GHC.IO.Exception ( IOErrorType(..) import System.IO ( hPutStrLn , stderr ) +import Language.Haskell.TH.Quote ---------------------------------------------------------------- -- Internal utils @@ -23,3 +24,13 @@ noSuchThing message = sayErr :: MonadIO m => String -> m () sayErr = liftIO . hPutStrLn stderr + +badQQ :: String -> QuasiQuoter +badQQ name = QuasiQuoter (bad "expression") + (bad "pattern") + (bad "type") + (bad "declaration") + where + bad :: String -> a + bad context = + error $ "Can't use " <> name <> " quote in a " <> context <> " context" diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index 3d8a5b777..fd91812ed 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -398,15 +398,15 @@ prettyRequirementResult = \case "Did not attempt to check " <> show n <> " because the 'getPhysicalDeviceFeatures' function was not loaded" - MissingLayer n -> "Missing layer: " <> show n - UnsatisfiedInstanceVersion u -> "Unsatisfied Instance Version: " <> p u - UnsatisfiedDeviceVersion u -> "Unsatisfied Device Version: " <> p u + MissingLayer n -> "Couldn't find layer: " <> show n + UnsatisfiedInstanceVersion u -> "Unsatisfied Instance version: " <> p u + UnsatisfiedDeviceVersion u -> "Unsatisfied Device version: " <> p u UnsatisfiedLayerVersion n u -> "Unsatisfied layer version for " <> show n <> ": " <> p u UnsatisfiedFeature n -> "Missing feature: " <> show n UnsatisfiedProperty n -> "Unsatisfied property: " <> show n - UnsatisfiedInstanceExtension n -> "Missing device extension: " <> show n - UnsatisfiedDeviceExtension n -> "Missing instance extension: " <> show n + UnsatisfiedInstanceExtension n -> "Couldn't find instance extension: " <> show n + UnsatisfiedDeviceExtension n -> "Couldn't find device extension: " <> show n where p = prettyUnsatisfied showVersion -- How I'm feeling after writing all this type level nonsense diff --git a/utils/src/Vulkan/Utils/Requirements/TH.hs b/utils/src/Vulkan/Utils/Requirements/TH.hs new file mode 100644 index 000000000..0ea496030 --- /dev/null +++ b/utils/src/Vulkan/Utils/Requirements/TH.hs @@ -0,0 +1,288 @@ +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE QuasiQuotes #-} + +module Vulkan.Utils.Requirements.TH + ( req + , reqs + ) where + +import Control.Applicative +import Control.Category ( (>>>) ) +import Control.Monad +import Data.Char +import Data.Foldable +import Data.List ( intercalate + , isPrefixOf + ) +import Data.List.Extra ( nubOrd ) +import Data.Maybe +import Data.String +import Data.Traversable +import Data.Word +import Language.Haskell.TH +import Language.Haskell.TH.Quote +import Language.Haskell.TH.Syntax +import Prelude hiding ( GT ) +import Text.ParserCombinators.ReadP + hiding ( optional ) +import Text.Read ( readMaybe ) +import Vulkan.Requirement +import Vulkan.Utils.Internal +import Vulkan.Utils.Misc +import Vulkan.Version ( pattern MAKE_VERSION ) + +-- $setup +-- >>> import Vulkan.Core11.Promoted_From_VK_KHR_multiview +-- >>> import Vulkan.Core12 +-- >>> import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline +-- >>> import Vulkan.Zero + +-- | Parse a requirement and produce an appropriate 'DeviceRequirement' +-- +-- 'DeviceVersionRequirement's are specified by in the form +-- @.[.]@ +-- +-- 'DeviceFeatureRequirement's are specified in the form @.@ and produce a 'RequireDeviceFeature' which checks and sets this +-- feature. +-- +-- 'DevicePropertyRequirement's are specified like feature requirements except +-- with an additional description of the constraint. This may be any of +-- +-- - @myFunctioName@: To check with an in-scope function taking the property +-- type and returning 'Bool' +-- - @> 123@: To indicate a minimum bound on a integral property +-- - @>= 123@: To indicate an inclusive minimum bound on a integral property +-- - @& SOMETHING_BIT@: To indicate that the specified bit must be present in +-- the bitmask value +-- +-- 'DeviceExtensionRequirement's are specified in the form @ +-- @. @@ must start with @VK_@. The version +-- will be compared against the 'specVersion' field of the +-- 'ExtensionProperties' record. +-- +-- - Names may be qualified. +-- - The separator between the type and member can be any of @.@ @::@ @:@ @->@ +-- or any amount of space +-- +-- >>> let r = [req|PhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline|] +-- >>> featureName r +-- "PhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline" +-- +-- >>> let r = [req|PhysicalDeviceVulkan11Features.multiview|] +-- >>> featureName r +-- "PhysicalDeviceVulkan11Features.multiview" +-- +-- >>> let r = [req|PhysicalDeviceMultiviewFeatures.multiview|] +-- >>> featureName r +-- "PhysicalDeviceMultiviewFeatures.multiview" +req :: QuasiQuoter +req = (badQQ "req") { quoteExp = reqExp } + +-- | Like 'reqs' except that this parses a list of newline separated +-- requirements +-- +-- It ignores +-- - Blank lines +-- - Lines beginning with @--@ or @#@ +reqs :: QuasiQuoter +reqs = (badQQ "req") { quoteExp = exps reqExp . filterComments } + +reqExp :: String -> Q Exp +reqExp s = do + case parse s of + Nothing -> fail $ "Couldn't parse " <> show s + Just r -> do + r' <- nameRequest r + renderRequest s r' + +renderRequest :: String -> Request Name Name -> ExpQ +renderRequest input = \case + Feature s m -> + let t = conT s + check = [|$(varE m) :: $t -> Bool|] + enable = [|\str -> $(recUpdE [| str :: $t |] [fieldExp m [|True|]])|] + in [| let featureName = fromString $(lift input) + checkFeature = $(check) + enableFeature = $(enable) + in RequireDeviceFeature featureName checkFeature enableFeature + |] + Property s m c -> + let t = conT s + getProp = [|\str -> $(varE m) (str :: $t)|] + checker = case c of + GTE v -> [|(>= $(litE (IntegerL v)))|] + GT v -> [|(> $(litE (IntegerL v)))|] + AndBit b -> [|(.&&. $(conE b))|] + Fun f -> [|$(varE f)|] + check = [|$checker . $getProp|] + in [| let propertyName = fromString $(lift input) + checkProperty = $(check) + in RequireDeviceProperty propertyName checkProperty + |] + Extension s v -> + [| let deviceExtensionLayerName = Nothing + deviceExtensionName = fromString $(lift s) + deviceExtensionMinVersion = $(lift (fromMaybe minBound v)) + in RequireDeviceExtension + deviceExtensionLayerName + deviceExtensionName + deviceExtensionMinVersion + |] + Version v -> [| RequireDeviceVersion $(lift v) |] + +nameRequest :: Request [String] String -> Q (Request Name Name) +nameRequest = \case + Feature s m -> do + sName <- getQualTyName s + let mName = mkName m + pure $ Feature sName mName + Property s m c -> do + sName <- getQualTyName s + let mName = mkName m + c' <- for c getQualValueName + pure $ Property sName mName c' + Extension s v -> pure $ Extension s v + Version v -> pure $ Version v + where + getQualTyName n = do + let q = intercalate "." n + maybe (fail $ "Couldn't find type name " <> show q) pure + =<< lookupTypeName q + getQualValueName n = do + let q = intercalate "." n + maybe (fail $ "Couldn't find value name " <> show q) pure + =<< lookupValueName q + +data Request qual unqual + = Version Word32 + | Feature qual unqual + | Property qual unqual (Constraint qual) + | Extension String (Maybe Word32) + deriving (Show) + +data Constraint qual + = GTE Integer + | GT Integer + | AndBit qual + | Fun qual + deriving (Show, Functor, Foldable, Traversable) + +-- | +-- >>> parse "" +-- Nothing +-- +-- >>> parse "Foo->bar" +-- Just (Feature ["Foo"] "bar") +-- +-- >>> parse "V.Foo.bar" +-- Just (Feature ["V","Foo"] "bar") +-- +-- >>> parse "V.E.Foo bar" +-- Just (Feature ["V","E","Foo"] "bar") +-- +-- >>> parse "1.2" +-- Just (Version 4202496) +-- +-- >>> parse "1 2 1" +-- Just (Version 4202497) +-- +-- >>> parse "Foo.bar >= 10" +-- Just (Property ["Foo"] "bar" (GTE 10)) +-- +-- >>> parse "V.Foo.bar & A.B.C_BIT" +-- Just (Property ["V","Foo"] "bar" (AndBit ["A","B","C_BIT"])) +-- +-- >>> parse "V.Foo.bar even" +-- Just (Property ["V","Foo"] "bar" (Fun ["even"])) +-- +-- >>> parse "V.Foo.bar Prelude.even" +-- Just (Property ["V","Foo"] "bar" (Fun ["Prelude","even"])) +parse :: String -> Maybe (Request [String] String) +parse = + let + varRemChars = munch (isAlphaNum <||> (== '\'') <||> (== '_')) + var = (:) <$> satisfy (isLower <||> (== '_')) <*> varRemChars + con = (:) <$> satisfy isUpper <*> varRemChars + mod' = con + qual :: ReadP String -> ReadP [String] + qual x = (pure <$> x) <|> ((:) <$> (mod' <* char '.') <*> qual x) + separator = asum (skipSpaces : (void . string <$> [".", "->", "::", ":"])) + + digits = munch1 isDigit + integer = readS_to_P (reads @Integer) + word = do + Just w <- readMaybe <$> digits + pure w + + comp = do + c <- (GT <$ string ">") <|> (GTE <$ string ">=") + skipSpaces + w <- integer + pure $ c w + andBit = do + _ <- string "&" + skipSpaces + q <- qual con + pure $ AndBit q + fun = Fun <$> qual var + constraint = comp <|> andBit <|> fun + + version = do + ma <- word + separator + mi <- word + pa <- fromMaybe 0 <$> (separator *> optional word) + pure $ Version (MAKE_VERSION ma mi pa) + + feature = do + s <- qual con + _ <- separator + m <- var + pure $ Feature s m + + property = do + s <- qual con + _ <- separator + m <- var + skipSpaces + c <- constraint + pure $ Property s m c + + extension = do + let prefix = "VK_" + _ <- string prefix + e <- (prefix <>) <$> munch (isAlphaNum <||> (== '_')) + skipSpaces + v <- optional word + pure $ Extension e v + + request = do + skipSpaces + asum + [ p <* skipSpaces <* eof + | p <- [version, feature, property, extension] + ] + in + readP_to_S request >>> \case + -- xs -> pure $ Feature [] (show xs) + [(r, "")] -> pure r + _ -> Nothing +{-# ANN parse ("HLint: ignore Use <$>" :: String) #-} + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + +-- | Filters blank or commented lines, remove duplicates +filterComments :: String -> [String] +filterComments = + let bad = (("--" `isPrefixOf`) <||> ("#" `isPrefixOf`) <||> null) + in nubOrd . filter (not . bad) . fmap (dropWhile isSpace) . lines + +exps :: (String -> ExpQ) -> [String] -> ExpQ +exps f = listE . fmap f + +(<||>) :: Applicative f => f Bool -> f Bool -> f Bool +(<||>) = liftA2 (||) + diff --git a/utils/src/Vulkan/Utils/ShaderQQ.hs b/utils/src/Vulkan/Utils/ShaderQQ.hs index 78d8e6b71..f092e26b2 100644 --- a/utils/src/Vulkan/Utils/ShaderQQ.hs +++ b/utils/src/Vulkan/Utils/ShaderQQ.hs @@ -26,6 +26,7 @@ import System.Exit import System.FilePath import System.IO.Temp import System.Process.Typed +import Vulkan.Utils.Internal ( badQQ ) import Vulkan.Utils.ShaderQQ.Interpolate -- $setup @@ -207,17 +208,3 @@ insertLineDirective code Loc {..} = in case afterVersion of [] -> code v : xs -> unlines $ beforeVersion <> [v] <> lineDirective <> xs - ----------------------------------------------------------------- --- Utils ----------------------------------------------------------------- - -badQQ :: String -> QuasiQuoter -badQQ name = QuasiQuoter (bad "expression") - (bad "pattern") - (bad "type") - (bad "declaration") - where - bad :: String -> a - bad context = - error $ "Can't use " <> name <> " quote in a " <> context <> " context" diff --git a/utils/vulkan-utils.cabal b/utils/vulkan-utils.cabal index fe78a3195..f3ffb4588 100644 --- a/utils/vulkan-utils.cabal +++ b/utils/vulkan-utils.cabal @@ -39,6 +39,7 @@ library Vulkan.Utils.Misc Vulkan.Utils.QueueAssignment Vulkan.Utils.Requirements + Vulkan.Utils.Requirements.TH Vulkan.Utils.ShaderQQ Vulkan.Utils.ShaderQQ.Interpolate Vulkan.Utils.ShaderQQ.Shaderc From 355366a5ede91261de0b02efa05a16c660598fa1 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 14:31:31 +0800 Subject: [PATCH 49/70] Use quasiquoted requirements in hlsl and timeline-semaphore examples --- examples/hlsl/Init.hs | 21 +++++++++------------ examples/timeline-semaphore/Main.hs | 19 +++++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/examples/hlsl/Init.hs b/examples/hlsl/Init.hs index bf82ade3a..70a7b214a 100644 --- a/examples/hlsl/Init.hs +++ b/examples/hlsl/Init.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE QuasiQuotes #-} module Init ( Init.createInstance , Init.createDevice @@ -14,8 +15,6 @@ import Data.Word import Say import UnliftIO.Exception import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore - ( PhysicalDeviceTimelineSemaphoreFeatures(..) - ) import Vulkan.Extensions.VK_KHR_timeline_semaphore import Control.Applicative @@ -42,6 +41,7 @@ import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Requirement import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment +import qualified Vulkan.Utils.Requirements.TH as U import Vulkan.Zero import VulkanMemoryAllocator ( Allocator , AllocatorCreateInfo(..) @@ -96,16 +96,13 @@ createDevice inst win = do sayErr . ("Using device: " <>) =<< physicalDeviceName phys let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } - reqs = - [ RequireDeviceExtension Nothing KHR_SWAPCHAIN_EXTENSION_NAME minBound - , RequireDeviceExtension Nothing - KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME - minBound - , RequireDeviceFeature "timeline semaphores" - timelineSemaphore - (\s -> s { timelineSemaphore = True }) - ] - dev <- createDeviceFromRequirements phys reqs [] deviceCreateInfo + reqs = [U.reqs| + 1.0 + VK_KHR_swapchain + VK_KHR_timeline_semaphore + PhysicalDeviceTimelineSemaphoreFeatures.timelineSemaphore + |] + dev <- createDeviceFromRequirements reqs [] phys deviceCreateInfo requireCommands inst dev queues <- liftIO $ pdiGetQueues pdi dev pure (phys, dev, queues, surf) diff --git a/examples/timeline-semaphore/Main.hs b/examples/timeline-semaphore/Main.hs index fca64e3d4..89e772449 100644 --- a/examples/timeline-semaphore/Main.hs +++ b/examples/timeline-semaphore/Main.hs @@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -Wno-missing-signatures #-} @@ -29,10 +30,10 @@ import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore as Timeline import Vulkan.Exception import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 -import Vulkan.Extensions.VK_KHR_timeline_semaphore import Vulkan.Requirement import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment +import qualified Vulkan.Utils.Requirements.TH as U import Vulkan.Zero main :: IO () @@ -107,15 +108,13 @@ createDevice inst = do sayErr . ("Using device: " <>) =<< physicalDeviceName phys let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } - reqs = - [ RequireDeviceExtension Nothing - KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME - minBound - , RequireDeviceFeature "timeline semaphores" - Timeline.timelineSemaphore - (\s -> s { Timeline.timelineSemaphore = True }) - ] - dev <- createDeviceFromRequirements phys reqs [] deviceCreateInfo + reqs = [U.reqs| + 1.0 + VK_KHR_timeline_semaphore + PhysicalDeviceTimelineSemaphoreFeatures.timelineSemaphore + PhysicalDeviceTimelineSemaphoreProperties.maxTimelineSemaphoreValueDifference >= 1 + |] + dev <- createDeviceFromRequirements reqs [] phys deviceCreateInfo queues <- liftIO $ pdiGetQueues pdi dev pure (phys, dev, queues) From f9406c679d99f53b519ebe8a1367ec6dcc3dab46 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 14:35:36 +0800 Subject: [PATCH 50/70] Add missing deps to stack.yaml --- stack.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stack.yaml b/stack.yaml index 72d5b4d31..af870bf23 100644 --- a/stack.yaml +++ b/stack.yaml @@ -11,6 +11,9 @@ extra-deps: - resourcet-1.2.4 - pretty-simple-3.3.0.0 - primitive-unlifted-1.0.0.0 +- dependent-map-0.4.0.0 +- dependent-sum-0.7.1.0 + nix: enable: false packages: [vulkan-loader vulkan-headers glslang pkg-config SDL2 zlib] From 4c7e99e8b88d474446dbeb6d1aa56856753a56da Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 14:39:06 +0800 Subject: [PATCH 51/70] bump changelog --- utils/changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/changelog.md b/utils/changelog.md index b74fdad0e..0337bad6a 100644 --- a/utils/changelog.md +++ b/utils/changelog.md @@ -6,6 +6,7 @@ `Requirement` types found in `Vulkan.Requirement` - Change the creation helpers in `Vulkan.Utils.Initialization` to use the new `Requirement` types. +- Add QuasiQuoters for creating device requirements in `Vulkan.Utils.Requirements.TH` ## [0.3] - 2020-11-24 From 4966912f905755977242f45fc712e5888739dead Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 14:53:18 +0800 Subject: [PATCH 52/70] Use requirements quasiquoter in rays example --- examples/rays/Init.hs | 75 ++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index 25b432d69..d36620760 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE QuasiQuotes #-} + module Init ( Init.createInstance , Init.createDevice @@ -7,7 +9,7 @@ module Init ) where import Control.Monad ( unless - , when + ) import Control.Monad.IO.Class import Control.Monad.Trans.Maybe ( MaybeT(..) ) @@ -41,31 +43,15 @@ import Vulkan.Core10 as Vk , withImage ) import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address -import Vulkan.Extensions.VK_EXT_descriptor_indexing - ( pattern EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME - ) import Vulkan.Extensions.VK_KHR_acceleration_structure -import Vulkan.Extensions.VK_KHR_buffer_device_address - ( pattern KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME - ) -import Vulkan.Extensions.VK_KHR_deferred_host_operations - ( pattern KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME - ) -import Vulkan.Extensions.VK_KHR_get_memory_requirements2 - ( pattern KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - ) import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 -import Vulkan.Extensions.VK_KHR_maintenance3 - ( pattern KHR_MAINTENANCE3_EXTENSION_NAME - ) -import Vulkan.Extensions.VK_KHR_pipeline_library - ( pattern KHR_PIPELINE_LIBRARY_EXTENSION_NAME - ) import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain +import Vulkan.Requirement import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment +import Vulkan.Utils.Requirements.TH ( reqs ) import Vulkan.Version ( pattern MAKE_VERSION ) import Vulkan.Zero import VulkanMemoryAllocator ( Allocator @@ -92,10 +78,12 @@ createInstance win = do , apiVersion = myApiVersion } } - extensions = - [KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME] - <> windowExtensions - createInstanceWithExtensions [] [] extensions [] createInfo + requirements = + (\n -> RequireInstanceExtension Nothing n minBound) + <$> ( KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME + : windowExtensions + ) + createInstanceFromRequirements requirements [] createInfo ---------------------------------------------------------------- -- Device creation @@ -122,26 +110,27 @@ createDevice inst win = do sayErr . ("Using device: " <>) =<< physicalDeviceName phys let deviceCreateInfo = zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } - ::& PhysicalDeviceTimelineSemaphoreFeatures True - :& zero { rayTracingPipeline = True } - :& (zero { accelerationStructure = True } :: PhysicalDeviceAccelerationStructureFeaturesKHR - ) - :& zero { bufferDeviceAddress = True } - :& () - rayTracingExtensions = - [ KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME - , KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME - , EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME - , KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME - , KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME - , KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME - , KHR_MAINTENANCE3_EXTENSION_NAME - , KHR_PIPELINE_LIBRARY_EXTENSION_NAME - ] - extensions = - [KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, KHR_SWAPCHAIN_EXTENSION_NAME] - <> rayTracingExtensions - dev <- createDeviceWithExtensions phys [] extensions deviceCreateInfo + requirements = [reqs| + VK_KHR_swapchain + + VK_KHR_timeline_semaphore + PhysicalDeviceTimelineSemaphoreFeatures.timelineSemaphore + + -- Ray tracing + 1.2.162 + PhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline + PhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure + PhysicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress + VK_KHR_ray_tracing_pipeline + VK_KHR_acceleration_structure + VK_EXT_descriptor_indexing + VK_KHR_buffer_device_address + VK_KHR_deferred_host_operations + VK_KHR_get_memory_requirements2 + VK_KHR_maintenance3 + VK_KHR_pipeline_library + |] + dev <- createDeviceFromRequirements requirements [] phys deviceCreateInfo requireCommands inst dev queues <- liftIO $ pdiGetQueues pdi dev pure (phys, pdi, dev, queues, surf) From b313a1301ede943c5409d2120d46ae44c9c1c8ab Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 14:58:33 +0800 Subject: [PATCH 53/70] please stack --- stack.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/stack.yaml b/stack.yaml index af870bf23..dde366f83 100644 --- a/stack.yaml +++ b/stack.yaml @@ -13,6 +13,7 @@ extra-deps: - primitive-unlifted-1.0.0.0 - dependent-map-0.4.0.0 - dependent-sum-0.7.1.0 +- constraints-extras-0.3.0.2 nix: enable: false From 15a95d0a03feedd4f2332150c79aa021f694dce9 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Fri, 27 Nov 2020 16:48:00 +0800 Subject: [PATCH 54/70] Prettier version showing --- utils/src/Vulkan/Utils/Requirements.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/src/Vulkan/Utils/Requirements.hs b/utils/src/Vulkan/Utils/Requirements.hs index fd91812ed..72fab6a1d 100644 --- a/utils/src/Vulkan/Utils/Requirements.hs +++ b/utils/src/Vulkan/Utils/Requirements.hs @@ -58,6 +58,7 @@ import Vulkan.NamedType import Vulkan.Requirement import Vulkan.Version import Vulkan.Zero ( Zero(..) ) +import Data.List (intercalate) ---------------------------------------------------------------- -- * Instance Creation @@ -605,7 +606,7 @@ getMaybe funPtr wrapper2 get1 get2 phys = ---------------------------------------------------------------- showVersion :: Word32 -> String -showVersion ver = unwords ["MAKE_VERSION", show ma, show mi, show pa] +showVersion ver = intercalate "." [show ma, show mi, show pa] where MAKE_VERSION ma mi pa = ver data Has c a where From 3b832b45f9f323bfe0fc08fd2da112c071aecd8e Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sat, 28 Nov 2020 21:38:10 +0800 Subject: [PATCH 55/70] Multiple spheres in RT example --- examples/package.yaml | 13 +- examples/rays/AccelerationStructure.hs | 58 ++----- examples/rays/Frame.hs | 6 +- examples/rays/Init.hs | 230 ++++++++----------------- examples/rays/Pipeline.hs | 131 +++++++++----- examples/rays/Scene.hs | 124 +++++++++++++ examples/vulkan-examples.cabal | 4 + 7 files changed, 325 insertions(+), 241 deletions(-) create mode 100644 examples/rays/Scene.hs diff --git a/examples/package.yaml b/examples/package.yaml index 332084176..f9532fa84 100644 --- a/examples/package.yaml +++ b/examples/package.yaml @@ -152,23 +152,26 @@ executables: - base <5 - bytestring - containers + - extra + - file-embed + - filepath + - lens + - linear - primitive-unlifted - resourcet >= 1.2.4 - say - sdl2 >= 2.5.2.0 - template-haskell + - temporary - text + - th-utilities - transformers + - typed-process - unagi-chan - unliftio - vector - vulkan >= 3.7 - vulkan-utils >= 0.3 - - file-embed - - extra - - filepath - - temporary - - typed-process when: - condition: impl(ghc < 8.10.0) buildable: false diff --git a/examples/rays/AccelerationStructure.hs b/examples/rays/AccelerationStructure.hs index bd10d4bd1..9f56792de 100644 --- a/examples/rays/AccelerationStructure.hs +++ b/examples/rays/AccelerationStructure.hs @@ -9,6 +9,7 @@ import Data.Coerce ( coerce ) import Data.Vector ( Vector ) import Foreign.Storable ( Storable(poke, sizeOf) ) import MonadVulkan +import Scene import UnliftIO.Foreign ( castPtr ) import Vulkan.CStruct import Vulkan.CStruct.Extends @@ -30,12 +31,12 @@ import VulkanMemoryAllocator ( AllocationCreateInfo -- TLAS ---------------------------------------------------------------- -createTLAS :: V (ReleaseKey, AccelerationStructureKHR) -createTLAS = do +createTLAS :: SceneBuffers -> V (ReleaseKey, AccelerationStructureKHR) +createTLAS sceneBuffers = do -- -- Create the bottom level accelerationStructures -- - (_blasReleaseKey, blas) <- createBLAS + (_blasReleaseKey, blas) <- createBLAS sceneBuffers blasAddress <- getAccelerationStructureDeviceAddressKHR' zero { accelerationStructure = blas } @@ -159,15 +160,15 @@ buildAccelerationStructure geom ranges sizes = do -- -- Create the bottom level acceleration structure -- -createBLAS :: V (ReleaseKey, AccelerationStructureKHR) -createBLAS = do - (_, boxGeom, boxOffsets) <- biunitBoxGeometry +createBLAS :: SceneBuffers -> V (ReleaseKey, AccelerationStructureKHR) +createBLAS sceneBuffers = do + (sceneGeom, sceneOffsets) <- sceneGeometry sceneBuffers let buildInfo = zero { type' = ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR , mode = BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR -- ignored but used later , srcAccelerationStructure = NULL_HANDLE -- ignored , dstAccelerationStructure = NULL_HANDLE -- ignored - , geometries = [boxGeom] + , geometries = [sceneGeom] , scratchData = zero } maxPrimitiveCounts = [1] @@ -177,51 +178,30 @@ createBLAS = do maxPrimitiveCounts (_blasBufferKey, blasKey, blas) <- buildAccelerationStructure buildInfo - boxOffsets + sceneOffsets sizes nameObject' blas "BLAS" pure (blasKey, blas) --- --- The geometry for a biunit AABB on the device --- -biunitBoxGeometry - :: V - ( ReleaseKey - , AccelerationStructureGeometryKHR +sceneGeometry + :: SceneBuffers + -> V + ( AccelerationStructureGeometryKHR , Vector AccelerationStructureBuildRangeInfoKHR ) -biunitBoxGeometry = do - let -- a bounding box for the unit sphere - box = AabbPositionsKHR (-1) (-1) (-1) 1 1 1 - (bufferKey, (buffer, bufferAllocation, _)) <- withBuffer' - zero - { usage = - BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - .|. BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR - , size = fromIntegral (sizeOf box) - } - zero - { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT - .|. MEMORY_PROPERTY_HOST_COHERENT_BIT - } - (boxMapKey, boxMapPtr) <- withMappedMemory' bufferAllocation - liftIO $ poke (castPtr boxMapPtr) box - release boxMapKey - boxAddr <- getBufferDeviceAddress' zero { buffer = buffer } +sceneGeometry SceneBuffers {..} = do + boxAddr <- getBufferDeviceAddress' zero { buffer = sceneAabbs } let boxData = AccelerationStructureGeometryAabbsDataKHR { data' = DeviceAddressConst boxAddr - , stride = fromIntegral (sizeOf box) + , stride = fromIntegral (sizeOf (undefined :: AabbPositionsKHR)) } - let geom :: AccelerationStructureGeometryKHR + geom :: AccelerationStructureGeometryKHR geom = zero { geometryType = GEOMETRY_TYPE_AABBS_KHR , flags = GEOMETRY_OPAQUE_BIT_KHR , geometry = Aabbs boxData } - let offsetInfo = [zero { primitiveCount = 1, primitiveOffset = 0 }] - pure (bufferKey, geom, offsetInfo) - - + let offsetInfo = [zero { primitiveCount = sceneSize, primitiveOffset = 0 }] + pure (geom, offsetInfo) ---------------------------------------------------------------- -- Utils diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index ba5a31817..ba89f7c08 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -22,6 +22,7 @@ import qualified Pipeline import qualified SDL import SDL ( Window ) import qualified SDL.Video.Vulkan as SDL +import Scene import Swapchain import Vulkan.CStruct.Extends import Vulkan.Core10 @@ -93,8 +94,10 @@ initialFrame fWindow fSurface = do windowSize fSurface + sceneBuffers <- makeSceneBuffers + -- The acceleration structure - (_, fAccelerationStructure) <- createTLAS + (_, fAccelerationStructure) <- createTLAS sceneBuffers -- Create the RT pipeline (_, descriptorSetLayout ) <- Pipeline.createRTDescriptorSetLayout @@ -108,6 +111,7 @@ initialFrame fWindow fSurface = do descriptorSets <- Pipeline.createRTDescriptorSets descriptorSetLayout fAccelerationStructure + sceneBuffers (fromIntegral numConcurrentFrames) -- Don't keep the release key, this semaphore lives for the lifetime of the diff --git a/examples/rays/Init.hs b/examples/rays/Init.hs index d36620760..983939b57 100644 --- a/examples/rays/Init.hs +++ b/examples/rays/Init.hs @@ -8,25 +8,17 @@ module Init , createCommandPools ) where -import Control.Monad ( unless - - ) +import Control.Applicative import Control.Monad.IO.Class import Control.Monad.Trans.Maybe ( MaybeT(..) ) import Control.Monad.Trans.Resource -import qualified Data.Vector as V -import Data.Word -import Say -import UnliftIO.Exception -import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore - ( PhysicalDeviceTimelineSemaphoreFeatures(..) - ) -import Vulkan.Extensions.VK_KHR_timeline_semaphore - -import Control.Applicative import qualified Data.ByteString as BS -import Data.Foldable ( for_ ) +import Data.Foldable ( for_ + , traverse_ + ) +import qualified Data.Vector as V import Data.Vector ( Vector ) +import Data.Word import GHC.IO.Exception ( IOErrorType(NoSuchThing) , IOException(IOError) ) @@ -37,22 +29,27 @@ import MonadVulkan ( Queues(..) ) import qualified SDL.Video as SDL import qualified SDL.Video.Vulkan as SDL +import Say +import UnliftIO.Exception import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk hiding ( withBuffer , withImage ) +import Vulkan.Core11 ( pattern API_VERSION_1_1 ) import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address +import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore + ( PhysicalDeviceTimelineSemaphoreFeatures(..) + ) import Vulkan.Extensions.VK_KHR_acceleration_structure import Vulkan.Extensions.VK_KHR_get_physical_device_properties2 import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Extensions.VK_KHR_surface -import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Requirement import Vulkan.Utils.Initialization import Vulkan.Utils.QueueAssignment +import Vulkan.Utils.Requirements import Vulkan.Utils.Requirements.TH ( reqs ) -import Vulkan.Version ( pattern MAKE_VERSION ) import Vulkan.Zero import VulkanMemoryAllocator ( Allocator , AllocatorCreateFlagBits(..) @@ -62,7 +59,7 @@ import VulkanMemoryAllocator ( Allocator import Window myApiVersion :: Word32 -myApiVersion = API_VERSION_1_0 +myApiVersion = API_VERSION_1_1 ---------------------------------------------------------------- -- Instance Creation @@ -103,38 +100,43 @@ createDevice , SurfaceKHR ) createDevice inst win = do - (_ , surf) <- createSurface inst win - (pdi, phys) <- + (_ , surf) <- createSurface inst win + + ((pdi, SomeStruct dci), phys) <- maybe (noSuchThing "Unable to find appropriate PhysicalDevice") pure - =<< pickPhysicalDevice inst (physicalDeviceInfo surf) pdiScore + =<< pickPhysicalDevice inst (physicalDeviceInfo surf) (pdiScore . fst) sayErr . ("Using device: " <>) =<< physicalDeviceName phys - let deviceCreateInfo = - zero { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos pdi } - requirements = [reqs| - VK_KHR_swapchain - - VK_KHR_timeline_semaphore - PhysicalDeviceTimelineSemaphoreFeatures.timelineSemaphore - - -- Ray tracing - 1.2.162 - PhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline - PhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure - PhysicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress - VK_KHR_ray_tracing_pipeline - VK_KHR_acceleration_structure - VK_EXT_descriptor_indexing - VK_KHR_buffer_device_address - VK_KHR_deferred_host_operations - VK_KHR_get_memory_requirements2 - VK_KHR_maintenance3 - VK_KHR_pipeline_library - |] - dev <- createDeviceFromRequirements requirements [] phys deviceCreateInfo + + (_, dev) <- withDevice phys dci Nothing allocate + requireCommands inst dev + queues <- liftIO $ pdiGetQueues pdi dev + pure (phys, pdi, dev, queues, surf) +deviceRequirements :: [DeviceRequirement] +deviceRequirements = [reqs| + VK_KHR_swapchain + + VK_KHR_timeline_semaphore + PhysicalDeviceTimelineSemaphoreFeatures.timelineSemaphore + + -- Ray tracing + 1.2.162 + PhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline + PhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure + PhysicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress + VK_KHR_ray_tracing_pipeline + VK_KHR_acceleration_structure + VK_EXT_descriptor_indexing + VK_KHR_buffer_device_address + VK_KHR_deferred_host_operations + VK_KHR_get_memory_requirements2 + VK_KHR_maintenance3 + VK_KHR_pipeline_library +|] + ---------------------------------------------------------------- -- Physical device tools ---------------------------------------------------------------- @@ -151,47 +153,32 @@ pdiScore :: PhysicalDeviceInfo -> Word64 pdiScore = pdiTotalMemory physicalDeviceInfo - :: MonadIO m => SurfaceKHR -> PhysicalDevice -> m (Maybe PhysicalDeviceInfo) + :: MonadIO m + => SurfaceKHR + -> PhysicalDevice + -> m (Maybe (PhysicalDeviceInfo, SomeStruct DeviceCreateInfo)) physicalDeviceInfo surf phys = runMaybeT $ do - deviceName <- physicalDeviceName phys - deviceProps <- getPhysicalDeviceProperties phys - unless - ( apiVersion (deviceProps :: PhysicalDeviceProperties) - >= MAKE_VERSION 1 2 162 - ) - $ do - sayErr - "This application requires a device supporing at lease Vulkan 1.2.162" - empty - - hasTimelineSemaphores <- deviceHasTimelineSemaphores phys - unless hasTimelineSemaphores $ do - sayErr - $ "Not using physical device " - <> deviceName - <> " because it doesn't support timeline semaphores" - empty - - pdiRTInfo <- deviceHasRayTracingPipeline phys - - hasAccelerationStructureSupport <- deviceHasAccelerationStructure phys - unless hasAccelerationStructureSupport $ do - sayErr - $ "Not using physical device " - <> deviceName - <> " because it doesn't support acceleration structures" - empty - - hasSwapchainSupport <- deviceHasSwapchain phys - unless hasSwapchainSupport $ do - sayErr - $ "Not using physical device " - <> deviceName - <> " because it doesn't support swapchains" - empty + -- + -- Check device requirements + -- + (mbDCI, rs, os) <- checkDeviceRequirements deviceRequirements [] phys zero + -- Report any missing features + traverse_ sayErrString (requirementReport rs os) + -- Fail if we didn't meet requirements + SomeStruct dciNoQueues <- maybe empty pure mbDCI + -- + -- Assign queues + -- (pdiQueueCreateInfos, pdiGetQueues) <- MaybeT $ assignQueues phys (queueRequirements phys surf) + let dci = + dciNoQueues { queueCreateInfos = SomeStruct <$> pdiQueueCreateInfos } + + -- + -- Query properties + -- + pdiRTInfo <- getDeviceRTProps phys -- -- We'll use the amount of memory to pick the "best" device @@ -200,7 +187,7 @@ physicalDeviceInfo surf phys = runMaybeT $ do heaps <- memoryHeaps <$> getPhysicalDeviceMemoryProperties phys pure $ sum ((size :: MemoryHeap -> DeviceSize) <$> heaps) - pure PhysicalDeviceInfo { .. } + pure (PhysicalDeviceInfo { .. }, SomeStruct dci) -- | Requirements for a 'Queue' which has graphics suppor and can present to -- the specified surface. @@ -216,80 +203,13 @@ queueRequirements phys surf = Queues (QueueSpec 1 isGraphicsPresentQueue) -- Physical device tools ---------------------------------------------------------------- -deviceHasSwapchain :: MonadIO m => PhysicalDevice -> m Bool -deviceHasSwapchain dev = do - (_, extensions) <- enumerateDeviceExtensionProperties dev Nothing - pure $ V.any ((KHR_SWAPCHAIN_EXTENSION_NAME ==) . extensionName) extensions - -deviceHasTimelineSemaphores :: MonadIO m => PhysicalDevice -> m Bool -deviceHasTimelineSemaphores phys = do - let - hasExt = do - (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing - pure $ V.any - ((KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME ==) . extensionName) - extensions - - hasFeat = do - feats <- getPhysicalDeviceFeatures2KHR phys - let - _ ::& PhysicalDeviceTimelineSemaphoreFeatures hasTimelineSemaphores :& () - = feats - pure hasTimelineSemaphores - - hasExt <&&> hasFeat - -deviceHasAccelerationStructure :: MonadIO m => PhysicalDevice -> m Bool - -- ^ Shader group size and alignment -deviceHasAccelerationStructure phys = do - let hasExt = do - (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing - pure $ V.any - ((KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME ==) . extensionName) - extensions - - hasFeat = do - feats <- getPhysicalDeviceFeatures2KHR phys - let _ ::& PhysicalDeviceAccelerationStructureFeaturesKHR {..} :& () = - feats - pure accelerationStructure - - hasExt <&&> hasFeat - -deviceHasRayTracingPipeline :: MonadIO m => PhysicalDevice -> MaybeT m RTInfo - -- ^ Shader group size and alignment -deviceHasRayTracingPipeline phys = do - deviceName <- physicalDeviceName phys - - let hasExt = do - (_, extensions) <- enumerateDeviceExtensionProperties phys Nothing - pure $ V.any - ((KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME ==) . extensionName) - extensions - - hasFeat = do - feats <- getPhysicalDeviceFeatures2KHR phys - let _ ::& PhysicalDeviceRayTracingPipelineFeaturesKHR {..} :& () = - feats - pure rayTracingPipeline - - getProps = do - props <- getPhysicalDeviceProperties2KHR phys - let _ ::& PhysicalDeviceRayTracingPipelinePropertiesKHR {..} :& () = - props - pure RTInfo { rtiShaderGroupHandleSize = shaderGroupHandleSize - , rtiShaderGroupBaseAlignment = shaderGroupBaseAlignment - } - - has <- hasExt <&&> hasFeat - if has - then getProps - else do - sayErr - $ "Not using physical device " - <> deviceName - <> " because it doesn't support ray tracing pipelines" - empty +getDeviceRTProps :: MonadIO m => PhysicalDevice -> m RTInfo +getDeviceRTProps phys = do + props <- getPhysicalDeviceProperties2KHR phys + let _ ::& PhysicalDeviceRayTracingPipelinePropertiesKHR {..} :& () = props + pure RTInfo { rtiShaderGroupHandleSize = shaderGroupHandleSize + , rtiShaderGroupBaseAlignment = shaderGroupBaseAlignment + } ---------------------------------------------------------------- -- VulkanMemoryAllocator diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 722a95e95..11f28e076 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -37,6 +37,7 @@ import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Utils.ShaderQQ import Vulkan.Zero import VulkanMemoryAllocator +import Scene -- Create the most vanilla ray tracing pipeline, returns the number of shader -- groups @@ -93,16 +94,23 @@ createRTPipelineLayout descriptorSetLayout = createRTDescriptorSetLayout :: V (ReleaseKey, DescriptorSetLayout) createRTDescriptorSetLayout = withDescriptorSetLayout' zero - { bindings = [ zero { binding = 1 + { bindings = [ zero + { binding = 0 + , descriptorType = DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + , descriptorCount = 1 + , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR + } + , zero { binding = 1 , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE , descriptorCount = 1 , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR } , zero - { binding = 0 - , descriptorType = DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + { binding = 2 + , descriptorType = DESCRIPTOR_TYPE_STORAGE_BUFFER , descriptorCount = 1 - , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR + , stageFlags = SHADER_STAGE_INTERSECTION_BIT_KHR + .|. SHADER_STAGE_CLOSEST_HIT_BIT_KHR } ] } @@ -110,34 +118,40 @@ createRTDescriptorSetLayout = withDescriptorSetLayout' zero createRTDescriptorSets :: DescriptorSetLayout -> AccelerationStructureKHR + -> SceneBuffers -> Word32 -> V (Vector DescriptorSet) -createRTDescriptorSets descriptorSetLayout tlas numDescriptorSets = do - let numImagesPerSet = 1 - numAccelerationStructuresPerSet = 1 - -- Create a descriptor pool - (_, descriptorPool) <- withDescriptorPool' zero - { maxSets = numDescriptorSets - , poolSizes = [ DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_IMAGE - (numDescriptorSets * numImagesPerSet) - , DescriptorPoolSize - DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR - (numDescriptorSets * numAccelerationStructuresPerSet) - ] - } - - -- Allocate a descriptor set from the pool with that layout - -- Don't use `withDescriptorSets` here as the set will be cleaned up when - -- the pool is destroyed. - sets <- allocateDescriptorSets' zero - { descriptorPool = descriptorPool - , setLayouts = V.replicate (fromIntegral numDescriptorSets) - descriptorSetLayout - } - - -- Put the static accelerationStructure into the set - for_ sets $ \set -> updateDescriptorSets' - [ SomeStruct +createRTDescriptorSets descriptorSetLayout tlas SceneBuffers {..} numDescriptorSets + = do + let numImagesPerSet = 1 + numAccelerationStructuresPerSet = 1 + numStorageBuffersPerSet = 1 + -- Create a descriptor pool + (_, descriptorPool) <- withDescriptorPool' zero + { maxSets = numDescriptorSets + , poolSizes = + [ DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_IMAGE + (numDescriptorSets * numImagesPerSet) + , DescriptorPoolSize + DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR + (numDescriptorSets * numAccelerationStructuresPerSet) + , DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_BUFFER + (numDescriptorSets * numStorageBuffersPerSet) + ] + } + + -- Allocate a descriptor set from the pool with that layout + -- Don't use `withDescriptorSets` here as the set will be cleaned up when + -- the pool is destroyed. + sets <- allocateDescriptorSets' zero + { descriptorPool = descriptorPool + , setLayouts = V.replicate (fromIntegral numDescriptorSets) + descriptorSetLayout + } + + -- Put the static accelerationStructure into the set + for_ sets $ \set -> updateDescriptorSets' + [ SomeStruct $ zero { dstSet = set , dstBinding = 0 , descriptorType = DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR @@ -145,10 +159,21 @@ createRTDescriptorSets descriptorSetLayout tlas numDescriptorSets = do } ::& zero { accelerationStructures = [tlas] } :& () - ] - [] + , SomeStruct $ zero + { dstSet = set + , dstBinding = 2 + , descriptorType = DESCRIPTOR_TYPE_STORAGE_BUFFER + , descriptorCount = 1 + , bufferInfo = [ DescriptorBufferInfo { buffer = sceneSpheres + , offset = 0 + , range = WHOLE_SIZE + } + ] + } + ] + [] - pure sets + pure sets createRayGenerationShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) @@ -158,7 +183,7 @@ createRayGenerationShader = do #extension GL_EXT_ray_tracing : require layout(binding = 0, set = 0) uniform accelerationStructureEXT topLevelAS; - layout(binding = 1, set = 0, rgba8) uniform image2D image; + layout(binding = 1, set = 0, rgba8) uniform writeonly image2D image; layout(location = 0) rayPayloadEXT vec3 prd; void main() @@ -166,8 +191,8 @@ createRayGenerationShader = do const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); const vec2 d = inUV * 2.0 - 1.0; - const vec3 origin = vec3(-10,0,0); - const vec3 direction = normalize(vec3(1,d)); + const vec3 origin = vec3(0,0,-10); + const vec3 direction = normalize(vec3(d, 1)); const uint rayFlags = gl_RayFlagsOpaqueEXT; const float tMin = 0.001; const float tMax = 10000.0; @@ -201,11 +226,23 @@ createRayHitShader = do #version 460 #extension GL_EXT_ray_tracing : require - layout(location = 0) rayPayloadInEXT vec3 hitValue; + layout(set = 0, location = 0) rayPayloadInEXT vec3 hitValue; + + struct Sphere { + vec4 s; + vec4 color; + }; + + layout(std430, set = 0, binding = 2) readonly buffer Spheres + { + Sphere spheres[]; + }; void main() { - hitValue = vec3(0.2, 0.5, 0.5); + const int i = gl_PrimitiveID; + const Sphere sphere = spheres[i]; + hitValue = vec3(sphere.color.xyz); } |]) @@ -220,12 +257,24 @@ createRayIntShader = do #version 460 #extension GL_EXT_ray_tracing : require + struct Sphere { + vec4 s; + vec4 color; + }; + + layout(std430, set = 0, binding = 2) readonly buffer Spheres + { + Sphere spheres[]; + }; + void main() { + const int i = gl_PrimitiveID; const vec3 o = gl_WorldRayOriginEXT; const vec3 d = gl_WorldRayDirectionEXT; - const vec3 s = vec3(0,0,0); - const float r = 1; + const Sphere sphere = spheres[i]; + const vec3 s = sphere.s.xyz; + const float r = sphere.s.w; const vec3 diff = o - s; @@ -254,7 +303,7 @@ createRayMissShader = do void main() { - hitValue = vec3(1.0, 0.1, 0.3); + hitValue = vec3(0.1, 0.15, 0.15); } |]) diff --git a/examples/rays/Scene.hs b/examples/rays/Scene.hs new file mode 100644 index 000000000..11e237a7e --- /dev/null +++ b/examples/rays/Scene.hs @@ -0,0 +1,124 @@ +{-# LANGUAGE ParallelListComp #-} +{-# LANGUAGE TemplateHaskell #-} + +module Scene + where + +import Control.Lens +import Control.Monad.IO.Class +import Control.Monad.Trans.Resource +import Data.Bits +import Data.Word +import Foreign.Marshal.Array +import Foreign.Ptr +import Foreign.Storable ( Storable(..) ) +import Linear.V3 +import Linear.V4 +import MonadVulkan +import TH.Derive +import Vulkan.Core10 +import Vulkan.Extensions.VK_KHR_acceleration_structure +import Vulkan.Zero +import VulkanMemoryAllocator + +data Sphere = Sphere + { spherePos :: V4 Float + , sphereColor :: V4 Float + } + +$($(derive [d| + instance Deriving (Storable Sphere) + |])) + +scene :: [Sphere] +scene = + [ Sphere (V4 originx 0 0 radius) (V4 r g b 1) + | radius <- [1 .. 10] + | originx <- [ i*i | i <- [0 .. 10]] + | V3 r g b <- pastels + ] + +pastels :: [V3 Float] +pastels = (/ pure 256) <$> cycle + [ V3 138 255 167 + , V3 174 255 243 + , V3 212 204 255 + , V3 255 184 205 + , V3 128 255 254 + , V3 159 255 153 + , V3 255 250 184 + , V3 221 133 255 + , V3 221 255 199 + , V3 133 255 174 + , V3 184 255 229 + , V3 255 189 207 + , V3 255 179 148 + ] + +---------------------------------------------------------------- +-- Vulkan +---------------------------------------------------------------- + +data SceneBuffers = SceneBuffers + { sceneAabbs :: Buffer + , sceneSpheres :: Buffer + , sceneSize :: Word32 + } + +makeSceneBuffers :: V SceneBuffers +makeSceneBuffers = do + sceneAabbs <- initBuffer + ( BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR + .|. BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + ) + (sphereAABB <$> scene) + + sceneSpheres <- initBuffer BUFFER_USAGE_STORAGE_BUFFER_BIT scene + + let sceneSize = fromIntegral (length scene) + + pure SceneBuffers { .. } + +---------------------------------------------------------------- +-- Buffer tools +---------------------------------------------------------------- + +initBuffer :: forall a . Storable a => BufferUsageFlags -> [a] -> V Buffer +initBuffer usage xs = do + let bufferSize = sizeOf (head xs) * length xs + + (_, (buf, allocation, _)) <- withBuffer' + zero { flags = zero, size = fromIntegral bufferSize, usage } + zero + { requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + .|. MEMORY_PROPERTY_HOST_COHERENT_BIT + } + (unmapKey, p) <- withMappedMemory' allocation + liftIO $ pokeArray (castPtr @() @a p) xs + release unmapKey + + pure buf + +---------------------------------------------------------------- +-- Utils +---------------------------------------------------------------- + + +sphereRadius :: Sphere -> Float +sphereRadius = view _w . spherePos + +sphereOrigin :: Sphere -> V3 Float +sphereOrigin = view _xyz . spherePos + +sphereAABB :: Sphere -> AabbPositionsKHR +sphereAABB s = + let mini = sphereOrigin s - pure (sphereRadius s) + maxi = sphereOrigin s + pure (sphereRadius s) + in AabbPositionsKHR (mini ^. _x) + (mini ^. _y) + (mini ^. _z) + (maxi ^. _x) + (maxi ^. _y) + (maxi ^. _z) + + diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index b90664b9d..e1a6b6026 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -172,6 +172,7 @@ executable rays Pipeline RefCounted Render + Scene Swapchain Utils Window @@ -189,6 +190,8 @@ executable rays , extra , file-embed , filepath + , lens + , linear , primitive-unlifted , resourcet >=1.2.4 , say @@ -196,6 +199,7 @@ executable rays , template-haskell , temporary , text + , th-utilities , transformers , typed-process , unagi-chan From 46f70612f060668d542010093e988561ea72bb42 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sun, 29 Nov 2020 01:08:01 +0800 Subject: [PATCH 56/70] Remove unused packages --- examples/package.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/examples/package.yaml b/examples/package.yaml index f9532fa84..02a7044ae 100644 --- a/examples/package.yaml +++ b/examples/package.yaml @@ -132,11 +132,6 @@ executables: - vector - vulkan - vulkan-utils >= 0.3 - - file-embed - - extra - - filepath - - temporary - - typed-process when: - condition: impl(ghc < 8.10.0) buildable: false @@ -152,9 +147,6 @@ executables: - base <5 - bytestring - containers - - extra - - file-embed - - filepath - lens - linear - primitive-unlifted @@ -162,11 +154,9 @@ executables: - say - sdl2 >= 2.5.2.0 - template-haskell - - temporary - text - th-utilities - transformers - - typed-process - unagi-chan - unliftio - vector From 58fb495cf59033af1d412a7be7d1e0aca1be489a Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sun, 29 Nov 2020 01:08:38 +0800 Subject: [PATCH 57/70] rotating camera in rays example --- examples/rays/Camera.hs | 89 ++++++++++++++++++++++++++++++++++ examples/rays/Frame.hs | 19 ++++++++ examples/rays/MonadFrame.hs | 1 - examples/rays/MonadVulkan.hs | 18 ++++--- examples/rays/Pipeline.hs | 22 +++++++-- examples/rays/Render.hs | 48 +++++++++++++----- examples/rays/Scene.hs | 3 +- examples/vulkan-examples.cabal | 11 +---- 8 files changed, 179 insertions(+), 32 deletions(-) create mode 100644 examples/rays/Camera.hs diff --git a/examples/rays/Camera.hs b/examples/rays/Camera.hs new file mode 100644 index 000000000..ebd41b49d --- /dev/null +++ b/examples/rays/Camera.hs @@ -0,0 +1,89 @@ +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE NoStrict #-} -- https://github.com/fpco/th-utilities/issues/13 + +module Camera where + +import Control.Lens +import Foreign.Storable +import Linear +import TH.Derive + +data Camera = Camera + { camPosition :: V3 Float + , camOrientation :: Quaternion Float + , camAspect :: Float + , camFOV :: Float + -- ^ Vertical field of view in Radians + } + +data CameraMatrices = CameraMatrices + { cmViewInverse :: M44 Float + , cmProjInverse :: M44 Float + } + +$($(derive [d| + instance Deriving (Storable CameraMatrices) + |])) + +initialCamera :: Camera +initialCamera = Camera (V3 0 0 (-10)) (axisAngle (V3 0 0 1) 0) (16 / 9) 1.57 + +-- >>> viewMatrix initialCamera +-- V4 (V4 1.0 0.0 0.0 0.0) (V4 0.0 1.0 0.0 0.0) (V4 0.0 0.0 1.0 10.0) (V4 0.0 0.0 0.0 1.0) +viewMatrix :: Camera -> M44 Float +viewMatrix Camera {..} = inv44 $ mkTransformation camOrientation camPosition + +-- >>> projectionMatrix initialCamera +-- V4 (V4 0.3611771 0.0 0.0 0.0) (V4 0.0 0.6420926 0.0 0.0) (V4 0.0 0.0 0.0 0.1) (V4 0.0 0.0 1.0 0.0) +-- +-- >>> tan (1.5 / 2) +-- 0.9315964599440725 +projectionMatrix :: Camera -> M44 Float +projectionMatrix Camera {..} = + let tanFoV = tan (camFOV / 2) + left = -tanFoV * camAspect + right = tanFoV * camAspect + top = -tanFoV + bottom = tanFoV + dx = 1.0 / (right - left) + dy = 1.0 / (bottom - top) + zNear = 0.1 + in V4 (V4 (2 * dx) 0 0 0) (V4 0 (2 * dy) 0 0) (V4 0 0 0 zNear) (V4 0 0 1 0) + +-- >>> projectRay initialCamera (V2 0 0) +-- (V3 0.0 0.0 (-10.0),V3 0.0 0.0 1.0) +-- +-- >>> projectRay initialCamera (V2 0 1) +-- (V3 0.0 0.0 (-10.0),V3 0.0 0.7068252 0.70738816) +-- +-- >>> projectRay initialCamera (V2 1 0) +-- (V3 0.0 0.0 (-10.0),V3 0.87140864 0.0 0.4905578) +projectRay + :: Camera + -> V2 Float + -- ^ Ray position on screen in [-1..1]^2 + -> (V3 Float, V3 Float) + -- ^ Origin, Direction +projectRay c scr2 = + let viewInverse = inv44 $ viewMatrix c + projInverse = inv44 $ projectionMatrix c + origin = (viewInverse !* point (V3 0 0 0)) ^. _xyz + targetScreenSpace = V4 (scr2 ^. _x) (scr2 ^. _y) 1 1 + target = projInverse !* targetScreenSpace + dir = normalize ((viewInverse !* vector (target ^. _xyz)) ^. _xyz) + in (origin, dir) + +-- >>> projectToScreen initialCamera (V3 0 0 0) +-- V3 0.0 0.0 1.0000001e-2 +-- +-- >>> projectToScreen initialCamera (V3 0 0 (-10)) +-- V3 NaN NaN Infinity +-- +-- >>> projectToScreen initialCamera (V3 0 0 (-9.9)) +-- V3 0.0 0.0 0.9999962 +-- +-- >>> projectToScreen initialCamera (V3 0 0 1000) +-- V3 0.0 0.0 9.900991e-5 +projectToScreen :: Camera -> V3 Float -> V3 Float +projectToScreen c = + normalizePoint . (projectionMatrix c !*) . (viewMatrix c !*) . point diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index ba89f7c08..ca4cd5f1c 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -3,6 +3,7 @@ module Frame where import AccelerationStructure +import Camera import Control.Arrow ( Arrow((&&&)) ) import Control.Monad ( (<=<) ) import Control.Monad.IO.Class ( MonadIO(liftIO) ) @@ -17,6 +18,8 @@ import Data.Foldable import Data.IORef import qualified Data.Vector as V import Data.Word +import Foreign.Ptr ( castPtr ) +import Foreign.Storable import MonadVulkan import qualified Pipeline import qualified SDL @@ -32,6 +35,7 @@ import Vulkan.Extensions.VK_KHR_acceleration_structure import Vulkan.Extensions.VK_KHR_surface import Vulkan.Utils.QueueAssignment import Vulkan.Zero +import VulkanMemoryAllocator -- | Must be positive, duh numConcurrentFrames :: Int @@ -78,6 +82,21 @@ initialRecycledResources fDescriptorSet = do { queueFamilyIndex = unQueueFamilyIndex graphicsQueueFamilyIndex } + (_, (fCameraMatricesBuffer, fCameraMatricesAllocation, bufferAllocInfo)) <- + withBuffer' + zero + { size = fromIntegral + (sizeOf (error "sizeof evaluated" :: CameraMatrices)) + , usage = BUFFER_USAGE_UNIFORM_BUFFER_BIT + } + zero { flags = ALLOCATION_CREATE_MAPPED_BIT + , usage = MEMORY_USAGE_CPU_TO_GPU + , requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + } + let fCameraMatricesBufferData = + castPtr @() @CameraMatrices (mappedData bufferAllocInfo) + + pure RecycledResources { .. } -- | Create a 'Frame' from scratch diff --git a/examples/rays/MonadFrame.hs b/examples/rays/MonadFrame.hs index ae1d71f59..f2fbb0743 100644 --- a/examples/rays/MonadFrame.hs +++ b/examples/rays/MonadFrame.hs @@ -29,7 +29,6 @@ import GHC.IO.Exception ( IOErrorType(TimeExpired) ) import MonadVulkan import RefCounted -import Say ( sayErrString ) import UnliftIO import Vulkan.CStruct.Extends ( SomeStruct ) import Vulkan.Core10 diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index db1325a86..db93bbab9 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -16,8 +16,10 @@ import UnliftIO ( Async , uninterruptibleCancel ) +import Camera import Control.Concurrent.Chan.Unagi import Data.Word +import Foreign.Ptr import Language.Haskell.TH.Syntax ( addTopDecls ) import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk @@ -28,6 +30,8 @@ import Vulkan.Core12.Promoted_From_VK_KHR_buffer_device_address ( getBufferDeviceAddress ) import Vulkan.Core12.Promoted_From_VK_KHR_timeline_semaphore as Timeline +import Vulkan.Extensions.VK_KHR_acceleration_structure +import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain import Vulkan.Utils.CommandCheck @@ -35,8 +39,6 @@ import Vulkan.Utils.Debug ( nameObject ) import Vulkan.Utils.QueueAssignment import VulkanMemoryAllocator as VMA hiding ( getPhysicalDeviceProperties ) -import Vulkan.Extensions.VK_KHR_ray_tracing_pipeline -import Vulkan.Extensions.VK_KHR_acceleration_structure ---------------------------------------------------------------- -- Define the monad in which most of the program will run @@ -153,15 +155,18 @@ data RTInfo = RTInfo -- | These are resources which are reused by a later frame when the current -- frame is retired data RecycledResources = RecycledResources - { fImageAvailableSemaphore :: Semaphore + { fImageAvailableSemaphore :: Semaphore -- ^ A binary semaphore passed to 'acquireNextImageKHR' - , fRenderFinishedSemaphore :: Semaphore + , fRenderFinishedSemaphore :: Semaphore -- ^ A binary semaphore to synchronize rendering and presenting - , fCommandPool :: CommandPool + , fCommandPool :: CommandPool -- ^ Pool for this frame's commands (might want more than one of these for -- multithreaded recording) - , fDescriptorSet :: DescriptorSet + , fDescriptorSet :: DescriptorSet -- ^ A descriptor set for ray tracing + , fCameraMatricesBuffer :: Buffer + , fCameraMatricesAllocation :: Allocation + , fCameraMatricesBufferData :: Ptr CameraMatrices } -- | The shape of all the queues we use for our program, parameterized over the @@ -205,6 +210,7 @@ do , 'VMA.withMappedMemory , 'VMA.withMemory , 'invalidateAllocation + , 'flushAllocation ] commands = [ 'acquireNextImageKHR diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 11f28e076..481564d20 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -112,6 +112,11 @@ createRTDescriptorSetLayout = withDescriptorSetLayout' zero , stageFlags = SHADER_STAGE_INTERSECTION_BIT_KHR .|. SHADER_STAGE_CLOSEST_HIT_BIT_KHR } + , zero { binding = 3 + , descriptorType = DESCRIPTOR_TYPE_UNIFORM_BUFFER + , descriptorCount = 1 + , stageFlags = SHADER_STAGE_RAYGEN_BIT_KHR + } ] } @@ -126,6 +131,7 @@ createRTDescriptorSets descriptorSetLayout tlas SceneBuffers {..} numDescriptorS let numImagesPerSet = 1 numAccelerationStructuresPerSet = 1 numStorageBuffersPerSet = 1 + numUniformBuffersPerSet = 1 -- Create a descriptor pool (_, descriptorPool) <- withDescriptorPool' zero { maxSets = numDescriptorSets @@ -137,6 +143,8 @@ createRTDescriptorSets descriptorSetLayout tlas SceneBuffers {..} numDescriptorS (numDescriptorSets * numAccelerationStructuresPerSet) , DescriptorPoolSize DESCRIPTOR_TYPE_STORAGE_BUFFER (numDescriptorSets * numStorageBuffersPerSet) + , DescriptorPoolSize DESCRIPTOR_TYPE_UNIFORM_BUFFER + (numDescriptorSets * numUniformBuffersPerSet) ] } @@ -186,13 +194,21 @@ createRayGenerationShader = do layout(binding = 1, set = 0, rgba8) uniform writeonly image2D image; layout(location = 0) rayPayloadEXT vec3 prd; + + layout(set = 0, binding = 3) uniform CameraBuffer + { + mat4x4 viewInverse; + mat4x4 projInverse; + }; + void main() { const vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5); const vec2 inUV = pixelCenter/vec2(gl_LaunchSizeEXT.xy); - const vec2 d = inUV * 2.0 - 1.0; - const vec3 origin = vec3(0,0,-10); - const vec3 direction = normalize(vec3(d, 1)); + const vec2 scr = inUV * 2.0 - 1.0; + const vec3 origin = (viewInverse * vec4(0,0,0,1)).xyz; + const vec3 direction = + normalize((viewInverse * vec4((projInverse * vec4(scr,1,1)).xyz, 0)).xyz); const uint rayFlags = gl_RayFlagsOpaqueEXT; const float tMin = 0.001; const float tMax = 10000.0; diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 84f5b148e..b0fba4c36 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -4,15 +4,20 @@ module Render ( renderFrame ) where +import Camera import Control.Exception ( throwIO ) import Control.Monad.IO.Class import Control.Monad.Trans.Class ( MonadTrans(lift) ) import Data.Vector ( (!) ) import Data.Word +import Foreign ( Storable(poke) ) import Frame import GHC.IO.Exception ( IOErrorType(TimeExpired) , IOException(IOError) ) +import Linear.Matrix +import Linear.Quaternion +import Linear.V3 import MonadFrame import MonadVulkan import Swapchain @@ -51,20 +56,41 @@ renderFrame = do -- Update the necessary descriptor sets updateDescriptorSets' [ SomeStruct zero - { dstSet = fDescriptorSet - , dstBinding = 1 - , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE - , descriptorCount = 1 - , imageInfo = [ DescriptorImageInfo - { sampler = NULL_HANDLE - , imageView = srImageViews ! fromIntegral imageIndex - , imageLayout = IMAGE_LAYOUT_GENERAL - } - ] - } + { dstSet = fDescriptorSet + , dstBinding = 1 + , descriptorType = DESCRIPTOR_TYPE_STORAGE_IMAGE + , descriptorCount = 1 + , imageInfo = [ DescriptorImageInfo + { sampler = NULL_HANDLE + , imageView = srImageViews ! fromIntegral imageIndex + , imageLayout = IMAGE_LAYOUT_GENERAL + } + ] + } + , SomeStruct zero -- TODO, only set this once + { dstSet = fDescriptorSet + , dstBinding = 3 + , descriptorType = DESCRIPTOR_TYPE_UNIFORM_BUFFER + , descriptorCount = 1 + , bufferInfo = [ DescriptorBufferInfo { buffer = fCameraMatricesBuffer + , offset = 0 + , range = WHOLE_SIZE + } + ] + } ] [] + let spin = axisAngle (V3 0 1 0) (realToFrac fIndex / 100) + forwards = axisAngle (V3 0 0 1) 0 + camera = Camera (V3 0 0 (-10)) (spin * forwards) (9 / 16) 1.56 + cameraMats = CameraMatrices + { cmViewInverse = transpose $ inv44 (viewMatrix camera) + , cmProjInverse = transpose $ inv44 (projectionMatrix camera) + } + liftIO $ poke fCameraMatricesBufferData cameraMats + flushAllocation' fCameraMatricesAllocation 0 WHOLE_SIZE + -- Allocate a command buffer and populate it let commandBufferAllocateInfo = zero { commandPool = fCommandPool , level = COMMAND_BUFFER_LEVEL_PRIMARY diff --git a/examples/rays/Scene.hs b/examples/rays/Scene.hs index 11e237a7e..10e51dc12 100644 --- a/examples/rays/Scene.hs +++ b/examples/rays/Scene.hs @@ -34,10 +34,11 @@ scene :: [Sphere] scene = [ Sphere (V4 originx 0 0 radius) (V4 r g b 1) | radius <- [1 .. 10] - | originx <- [ i*i | i <- [0 .. 10]] + | originx <- [ i**1.3 | i <- [0 .. 10]] | V3 r g b <- pastels ] + pastels :: [V3 Float] pastels = (/ pure 256) <$> cycle [ V3 138 255 167 diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index e1a6b6026..785c7db4f 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -84,18 +84,13 @@ executable hlsl , base <5 , bytestring , containers - , extra - , file-embed - , filepath , primitive-unlifted >=1.0 , resourcet >=1.2.4 , say , sdl2 >=2.5.2.0 , template-haskell - , temporary , text , transformers - , typed-process , unagi-chan , unliftio , vector @@ -163,6 +158,7 @@ executable rays other-modules: AccelerationStructure Cache + Camera DescriptorSet Frame Framebuffer @@ -187,9 +183,6 @@ executable rays , base <5 , bytestring , containers - , extra - , file-embed - , filepath , lens , linear , primitive-unlifted @@ -197,11 +190,9 @@ executable rays , say , sdl2 >=2.5.2.0 , template-haskell - , temporary , text , th-utilities , transformers - , typed-process , unagi-chan , unliftio , vector From fc9cc35e5c7220ab0ebdf6bdbec7b029c1247e58 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sun, 29 Nov 2020 21:45:58 +0800 Subject: [PATCH 58/70] Handle being suspended in waits Fixes #205 --- examples/hlsl/MonadFrame.hs | 11 +++++++++-- examples/rays/MonadFrame.hs | 11 +++++++++-- examples/resize/Frame.hs | 38 +++++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/examples/hlsl/MonadFrame.hs b/examples/hlsl/MonadFrame.hs index cc06ec8a8..64c3d9eeb 100644 --- a/examples/hlsl/MonadFrame.hs +++ b/examples/hlsl/MonadFrame.hs @@ -64,8 +64,15 @@ runFrame f@Frame {..} (F r) = runReaderT r f `finally` do , values = V.fromList (snd <$> waits) } waitSemaphoresSafe' waitInfo oneSecond >>= \case - TIMEOUT -> - timeoutError "Timed out (1s) waiting for frame to finish on Device" + TIMEOUT -> do + -- Give the frame one last chance to complete, + -- It could be that the program was suspended during the preceding + -- wait causing it to timeout, this will check if it actually + -- finished. + waitSemaphores' waitInfo 0 >>= \case + TIMEOUT -> timeoutError + "Timed out (1s) waiting for frame to finish on Device" + _ -> pure () _ -> pure () -- Free resources wanted elsewhere now, all those in RecycledResources diff --git a/examples/rays/MonadFrame.hs b/examples/rays/MonadFrame.hs index f2fbb0743..50649bf66 100644 --- a/examples/rays/MonadFrame.hs +++ b/examples/rays/MonadFrame.hs @@ -63,8 +63,15 @@ runFrame f@Frame {..} (F r) = runReaderT r f `finally` do , values = V.fromList (snd <$> waits) } waitSemaphoresSafe' waitInfo oneSecond >>= \case - TIMEOUT -> - timeoutError "Timed out (1s) waiting for frame to finish on Device" + TIMEOUT -> do + -- Give the frame one last chance to complete, + -- It could be that the program was suspended during the preceding + -- wait causing it to timeout, this will check if it actually + -- finished. + waitSemaphores' waitInfo 0 >>= \case + TIMEOUT -> timeoutError + "Timed out (1s) waiting for frame to finish on Device" + _ -> pure () _ -> pure () -- Free resources wanted elsewhere now, all those in RecycledResources diff --git a/examples/resize/Frame.hs b/examples/resize/Frame.hs index cb889dcc4..0cec49469 100644 --- a/examples/resize/Frame.hs +++ b/examples/resize/Frame.hs @@ -4,31 +4,31 @@ -- | This module defines the 'Frame' data type, as well as functions for using -- it easily. The 'F' monad is a reader for a 'Frame' and can be consumed by -- 'runFrame'. -module Frame - where +module Frame where +import Control.Monad ( void ) import Control.Monad.IO.Class +import Control.Monad.Trans.Class ( lift ) import Control.Monad.Trans.Reader import Control.Monad.Trans.Resource as ResourceT -import Control.Monad.Trans.Class ( lift ) -import Control.Monad ( void ) import qualified SDL import UnliftIO ( MonadUnliftIO(..) , askRunInIO , mask , toIO ) -import UnliftIO.MVar -import UnliftIO.Exception ( throwString - , finally +import UnliftIO.Exception ( finally + , throwString ) +import UnliftIO.MVar import Data.IORef -import Data.Word import Data.Vector ( Vector , cons ) +import Data.Word +import Vulkan.CStruct.Extends ( SomeStruct ) import Vulkan.Core10 as Vk hiding ( createDevice , createFramebuffer @@ -39,7 +39,6 @@ import Vulkan.Core10 as Vk ) import Vulkan.Extensions.VK_KHR_surface import Vulkan.Extensions.VK_KHR_swapchain -import Vulkan.CStruct.Extends ( SomeStruct ) import Vulkan.Zero import MonadVulkan @@ -110,8 +109,8 @@ instance MonadResource F where -- | Allocate a resource in the 'V' scope allocateGlobal :: F a -> (a -> F ()) -> F (ReleaseKey, a) allocateGlobal create destroy = do - createIO <- toIO create - run <- askRunInIO + createIO <- toIO create + run <- askRunInIO F $ allocate createIO (run . destroy) -- | c.f. 'bracket' and 'bracket_' @@ -128,8 +127,16 @@ runFrame f (F r) = runReaderT r f `finally` do -- Wait for this frame to be presented in another thread before retiring spawn_ $ do waitForFencesSafe' fences True 1e9 >>= \case - TIMEOUT -> throwString "Timed out waiting for frame to finish on the GPU" - _ -> pure () + TIMEOUT -> do + -- Give the frame one last chance to complete, + -- It could be that the program was suspended during the preceding + -- wait causing it to timeout, this will check if it actually + -- finished. + waitForFencesSafe' fences True 0 >>= \case + TIMEOUT -> + throwString "Timed out waiting for frame to finish on the GPU" + _ -> pure () + _ -> pure () commandPool <- getCommandPool (commandPoolIndex f) resetCommandPool' commandPool zero @@ -150,12 +157,11 @@ frameCommandPool = do F . lift . getCommandPool $ fromIntegral poolIndex commandPoolIndex :: Frame -> Int -commandPoolIndex Frame{..} = fromIntegral fIndex `mod` numConcurrentFrames +commandPoolIndex Frame {..} = fromIntegral fIndex `mod` numConcurrentFrames -- | Free frame resources, the frame must have finished GPU execution first. retireFrame :: MonadIO m => Frame -> m () -retireFrame Frame {..} = - release (fst fResources) +retireFrame Frame {..} = release (fst fResources) -- | 'queueSubmit' and add wait for the 'Fence' before retiring the frame. queueSubmitFrame :: Queue -> Vector (SomeStruct SubmitInfo) -> Fence -> F () From 917d6107ba02417cc692e081f1e4b6f06296fe25 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Sun, 29 Nov 2020 21:46:18 +0800 Subject: [PATCH 59/70] Neater camera config --- examples/rays/Camera.hs | 23 ++++++++++------------- examples/rays/Render.hs | 2 +- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/examples/rays/Camera.hs b/examples/rays/Camera.hs index ebd41b49d..fe84964c0 100644 --- a/examples/rays/Camera.hs +++ b/examples/rays/Camera.hs @@ -26,7 +26,8 @@ $($(derive [d| |])) initialCamera :: Camera -initialCamera = Camera (V3 0 0 (-10)) (axisAngle (V3 0 0 1) 0) (16 / 9) 1.57 +initialCamera = + Camera (V3 0 0 (-10)) (axisAngle (V3 0 0 1) 0) (16 / 9) (pi / 4) -- >>> viewMatrix initialCamera -- V4 (V4 1.0 0.0 0.0 0.0) (V4 0.0 1.0 0.0 0.0) (V4 0.0 0.0 1.0 10.0) (V4 0.0 0.0 0.0 1.0) @@ -40,24 +41,20 @@ viewMatrix Camera {..} = inv44 $ mkTransformation camOrientation camPosition -- 0.9315964599440725 projectionMatrix :: Camera -> M44 Float projectionMatrix Camera {..} = - let tanFoV = tan (camFOV / 2) - left = -tanFoV * camAspect - right = tanFoV * camAspect - top = -tanFoV - bottom = tanFoV - dx = 1.0 / (right - left) - dy = 1.0 / (bottom - top) + let cotFoV = 1 / tan (camFOV / 2) + dx = cotFoV / camAspect + dy = cotFoV zNear = 0.1 - in V4 (V4 (2 * dx) 0 0 0) (V4 0 (2 * dy) 0 0) (V4 0 0 0 zNear) (V4 0 0 1 0) + in V4 (V4 dx 0 0 0) (V4 0 dy 0 0) (V4 0 0 0 zNear) (V4 0 0 1 0) -- >>> projectRay initialCamera (V2 0 0) -- (V3 0.0 0.0 (-10.0),V3 0.0 0.0 1.0) -- -- >>> projectRay initialCamera (V2 0 1) --- (V3 0.0 0.0 (-10.0),V3 0.0 0.7068252 0.70738816) +-- (V3 0.0 0.0 (-10.0),V3 0.0 0.38268346 0.9238795) -- -- >>> projectRay initialCamera (V2 1 0) --- (V3 0.0 0.0 (-10.0),V3 0.87140864 0.0 0.4905578) +-- (V3 0.0 0.0 (-10.0),V3 0.5929577 0.0 0.8052336) projectRay :: Camera -> V2 Float @@ -73,8 +70,8 @@ projectRay c scr2 = dir = normalize ((viewInverse !* vector (target ^. _xyz)) ^. _xyz) in (origin, dir) --- >>> projectToScreen initialCamera (V3 0 0 0) --- V3 0.0 0.0 1.0000001e-2 +-- >>> projectToScreen initialCamera (V3 0 0 (-9.8)) +-- V3 0.0 0.0 0.5000005 -- -- >>> projectToScreen initialCamera (V3 0 0 (-10)) -- V3 NaN NaN Infinity diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index b0fba4c36..63a1dd02f 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -83,7 +83,7 @@ renderFrame = do let spin = axisAngle (V3 0 1 0) (realToFrac fIndex / 100) forwards = axisAngle (V3 0 0 1) 0 - camera = Camera (V3 0 0 (-10)) (spin * forwards) (9 / 16) 1.56 + camera = Camera (V3 0 0 (-10)) (spin * forwards) (16 / 9) 1.4 cameraMats = CameraMatrices { cmViewInverse = transpose $ inv44 (viewMatrix camera) , cmProjInverse = transpose $ inv44 (projectionMatrix camera) From 17166d7f48f94fa43366e22d7feb26307e775e60 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 15:56:56 +0800 Subject: [PATCH 60/70] Use a single buffer for camera matrices --- examples/rays/Frame.hs | 61 ++++++++++++++++++++++-------------- examples/rays/MonadVulkan.hs | 12 +++---- examples/rays/Render.hs | 26 +++++++++------ 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index ca4cd5f1c..95ef77b86 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -5,7 +5,8 @@ module Frame where import AccelerationStructure import Camera import Control.Arrow ( Arrow((&&&)) ) -import Control.Monad ( (<=<) ) +import Control.Monad ( zipWithM + ) import Control.Monad.IO.Class ( MonadIO(liftIO) ) import Control.Monad.Trans.Reader ( asks ) import Control.Monad.Trans.Resource ( InternalState @@ -18,7 +19,9 @@ import Data.Foldable import Data.IORef import qualified Data.Vector as V import Data.Word -import Foreign.Ptr ( castPtr ) +import Foreign.Ptr ( Ptr + , castPtr + ) import Foreign.Storable import MonadVulkan import qualified Pipeline @@ -38,7 +41,7 @@ import Vulkan.Zero import VulkanMemoryAllocator -- | Must be positive, duh -numConcurrentFrames :: Int +numConcurrentFrames :: Word64 numConcurrentFrames = 3 -- | All the information required to render a single frame @@ -54,6 +57,9 @@ data Frame = Frame , fAccelerationStructure :: AccelerationStructureKHR , fShaderBindingTable :: Buffer , fShaderBindingTableAddress :: DeviceAddress + , fCameraMatricesBuffer :: Buffer + , fCameraMatricesAllocation :: Allocation + , fCameraMatricesBufferData :: Ptr CameraMatrices , fRenderFinishedHostSemaphore :: Semaphore -- ^ A timeline semaphore which increments to fIndex when this frame is -- done, the host can wait on this semaphore @@ -69,8 +75,8 @@ data Frame = Frame -- frame is done with GPU work. } -initialRecycledResources :: DescriptorSet -> V RecycledResources -initialRecycledResources fDescriptorSet = do +initialRecycledResources :: Word64 -> DescriptorSet -> V RecycledResources +initialRecycledResources index fDescriptorSet = do (_, fImageAvailableSemaphore) <- withSemaphore' (zero ::& SemaphoreTypeCreateInfo SEMAPHORE_TYPE_BINARY 0 :& ()) @@ -81,21 +87,8 @@ initialRecycledResources fDescriptorSet = do (_, fCommandPool) <- withCommandPool' zero { queueFamilyIndex = unQueueFamilyIndex graphicsQueueFamilyIndex } - - (_, (fCameraMatricesBuffer, fCameraMatricesAllocation, bufferAllocInfo)) <- - withBuffer' - zero - { size = fromIntegral - (sizeOf (error "sizeof evaluated" :: CameraMatrices)) - , usage = BUFFER_USAGE_UNIFORM_BUFFER_BIT - } - zero { flags = ALLOCATION_CREATE_MAPPED_BIT - , usage = MEMORY_USAGE_CPU_TO_GPU - , requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT - } - let fCameraMatricesBufferData = - castPtr @() @CameraMatrices (mappedData bufferAllocInfo) - + let fCameraMatricesOffset = + index * fromIntegral (sizeOf (undefined :: CameraMatrices)) pure RecycledResources { .. } @@ -133,6 +126,20 @@ initialFrame fWindow fSurface = do sceneBuffers (fromIntegral numConcurrentFrames) + (_, (fCameraMatricesBuffer, fCameraMatricesAllocation, bufferAllocInfo)) <- + withBuffer' + zero + { size = numConcurrentFrames * fromIntegral + (sizeOf (error "sizeof evaluated" :: CameraMatrices)) + , usage = BUFFER_USAGE_UNIFORM_BUFFER_BIT + } + zero { flags = ALLOCATION_CREATE_MAPPED_BIT + , usage = MEMORY_USAGE_CPU_TO_GPU + , requiredFlags = MEMORY_PROPERTY_HOST_VISIBLE_BIT + } + let fCameraMatricesBufferData = + castPtr @() @CameraMatrices (mappedData bufferAllocInfo) + -- Don't keep the release key, this semaphore lives for the lifetime of the -- application (_, fRenderFinishedHostSemaphore) <- withSemaphore' @@ -141,10 +148,13 @@ initialFrame fWindow fSurface = do -- Create the 'RecycledResources' necessary to kick off the rest of the -- concurrent frames and push them into the chan. let (ourDescriptorSet, otherDescriptorSets) = - (V.head &&& V.tail) descriptorSets - fRecycledResources <- initialRecycledResources ourDescriptorSet - bin <- V $ asks ghRecycleBin - for_ otherDescriptorSets ((liftIO . bin) <=< initialRecycledResources) + (V.head &&& (toList . V.tail)) descriptorSets + ~(fRecycledResources : otherRecycledResources) <- zipWithM + initialRecycledResources + [0 ..] + (ourDescriptorSet : otherDescriptorSets) + bin <- V $ asks ghRecycleBin + liftIO $ for_ otherRecycledResources bin fGPUWork <- liftIO $ newIORef mempty -- Create the frame resource tracker at the global level so it's closed @@ -179,6 +189,9 @@ advanceFrame needsNewSwapchain f = do , fShaderBindingTable = fShaderBindingTable f , fShaderBindingTableAddress = fShaderBindingTableAddress f , fAccelerationStructure = fAccelerationStructure f + , fCameraMatricesBuffer = fCameraMatricesBuffer f + , fCameraMatricesAllocation = fCameraMatricesAllocation f + , fCameraMatricesBufferData = fCameraMatricesBufferData f , fRenderFinishedHostSemaphore = fRenderFinishedHostSemaphore f , fGPUWork , fResources diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index db93bbab9..b40f057cd 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -155,18 +155,16 @@ data RTInfo = RTInfo -- | These are resources which are reused by a later frame when the current -- frame is retired data RecycledResources = RecycledResources - { fImageAvailableSemaphore :: Semaphore + { fImageAvailableSemaphore :: Semaphore -- ^ A binary semaphore passed to 'acquireNextImageKHR' - , fRenderFinishedSemaphore :: Semaphore + , fRenderFinishedSemaphore :: Semaphore -- ^ A binary semaphore to synchronize rendering and presenting - , fCommandPool :: CommandPool + , fCommandPool :: CommandPool -- ^ Pool for this frame's commands (might want more than one of these for -- multithreaded recording) - , fDescriptorSet :: DescriptorSet + , fDescriptorSet :: DescriptorSet -- ^ A descriptor set for ray tracing - , fCameraMatricesBuffer :: Buffer - , fCameraMatricesAllocation :: Allocation - , fCameraMatricesBufferData :: Ptr CameraMatrices + , fCameraMatricesOffset :: Word64 } -- | The shape of all the queues we use for our program, parameterized over the diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 63a1dd02f..9dc4e75bf 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -11,6 +11,8 @@ import Control.Monad.Trans.Class ( MonadTrans(lift) ) import Data.Vector ( (!) ) import Data.Word import Foreign ( Storable(poke) ) +import Foreign.Ptr ( plusPtr ) +import Foreign.Storable import Frame import GHC.IO.Exception ( IOErrorType(TimeExpired) , IOException(IOError) @@ -33,8 +35,8 @@ import Vulkan.Zero renderFrame :: F () renderFrame = do f@Frame {..} <- askFrame - let RecycledResources {..} = fRecycledResources - let oneSecond = 1e9 + let RecycledResources {..} = fRecycledResources + oneSecond = 1e9 SwapchainResources {..} = fSwapchainResources SwapchainInfo {..} = srInfo @@ -72,11 +74,13 @@ renderFrame = do , dstBinding = 3 , descriptorType = DESCRIPTOR_TYPE_UNIFORM_BUFFER , descriptorCount = 1 - , bufferInfo = [ DescriptorBufferInfo { buffer = fCameraMatricesBuffer - , offset = 0 - , range = WHOLE_SIZE - } - ] + , bufferInfo = [ DescriptorBufferInfo + { buffer = fCameraMatricesBuffer + , offset = fCameraMatricesOffset + , range = fromIntegral + (sizeOf (undefined :: CameraMatrices)) + } + ] } ] [] @@ -88,8 +92,12 @@ renderFrame = do { cmViewInverse = transpose $ inv44 (viewMatrix camera) , cmProjInverse = transpose $ inv44 (projectionMatrix camera) } - liftIO $ poke fCameraMatricesBufferData cameraMats - flushAllocation' fCameraMatricesAllocation 0 WHOLE_SIZE + liftIO $ poke + (fCameraMatricesBufferData `plusPtr` fromIntegral fCameraMatricesOffset) + cameraMats + flushAllocation' fCameraMatricesAllocation + fCameraMatricesOffset + (fromIntegral (sizeOf (undefined :: CameraMatrices))) -- Allocate a command buffer and populate it let commandBufferAllocateInfo = zero { commandPool = fCommandPool From 159be93d5fc6cc603b8470deed96f2e6ab17205a Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 16:45:19 +0800 Subject: [PATCH 61/70] th-utilities -> derive-storable th-utilities does not respect alignment: https://github.com/fpco/th-utilities/issues/12 --- examples/package.yaml | 3 ++- examples/rays/Camera.hs | 15 +++++++-------- examples/rays/Frame.hs | 3 +-- examples/rays/MonadVulkan.hs | 2 -- examples/rays/Render.hs | 1 - examples/rays/Scene.hs | 27 ++++++++++++--------------- examples/vulkan-examples.cabal | 3 ++- nix/haskell-packages.nix | 14 ++++++++++++++ 8 files changed, 38 insertions(+), 30 deletions(-) diff --git a/examples/package.yaml b/examples/package.yaml index 02a7044ae..bb09edc84 100644 --- a/examples/package.yaml +++ b/examples/package.yaml @@ -155,7 +155,8 @@ executables: - sdl2 >= 2.5.2.0 - template-haskell - text - - th-utilities + - derive-storable >= 0.3 + - derive-storable-plugin - transformers - unagi-chan - unliftio diff --git a/examples/rays/Camera.hs b/examples/rays/Camera.hs index fe84964c0..0cb860765 100644 --- a/examples/rays/Camera.hs +++ b/examples/rays/Camera.hs @@ -1,12 +1,14 @@ -{-# LANGUAGE TemplateHaskell #-} -{-# LANGUAGE NoStrict #-} -- https://github.com/fpco/th-utilities/issues/13 +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# OPTIONS_GHC -fplugin=Foreign.Storable.Generic.Plugin #-} +{-# OPTIONS_GHC -fplugin-opt=Foreign.Storable.Generic.Plugin:-v0 #-} module Camera where import Control.Lens -import Foreign.Storable +import Foreign.Storable.Generic +import GHC.Generics ( Generic ) import Linear -import TH.Derive data Camera = Camera { camPosition :: V3 Float @@ -20,10 +22,7 @@ data CameraMatrices = CameraMatrices { cmViewInverse :: M44 Float , cmProjInverse :: M44 Float } - -$($(derive [d| - instance Deriving (Storable CameraMatrices) - |])) + deriving (Generic, GStorable) initialCamera :: Camera initialCamera = diff --git a/examples/rays/Frame.hs b/examples/rays/Frame.hs index 95ef77b86..bc426bf18 100644 --- a/examples/rays/Frame.hs +++ b/examples/rays/Frame.hs @@ -5,8 +5,7 @@ module Frame where import AccelerationStructure import Camera import Control.Arrow ( Arrow((&&&)) ) -import Control.Monad ( zipWithM - ) +import Control.Monad ( zipWithM ) import Control.Monad.IO.Class ( MonadIO(liftIO) ) import Control.Monad.Trans.Reader ( asks ) import Control.Monad.Trans.Resource ( InternalState diff --git a/examples/rays/MonadVulkan.hs b/examples/rays/MonadVulkan.hs index b40f057cd..d80762e11 100644 --- a/examples/rays/MonadVulkan.hs +++ b/examples/rays/MonadVulkan.hs @@ -16,10 +16,8 @@ import UnliftIO ( Async , uninterruptibleCancel ) -import Camera import Control.Concurrent.Chan.Unagi import Data.Word -import Foreign.Ptr import Language.Haskell.TH.Syntax ( addTopDecls ) import Vulkan.CStruct.Extends import Vulkan.Core10 as Vk diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index 9dc4e75bf..dd93d30c0 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -10,7 +10,6 @@ import Control.Monad.IO.Class import Control.Monad.Trans.Class ( MonadTrans(lift) ) import Data.Vector ( (!) ) import Data.Word -import Foreign ( Storable(poke) ) import Foreign.Ptr ( plusPtr ) import Foreign.Storable import Frame diff --git a/examples/rays/Scene.hs b/examples/rays/Scene.hs index 10e51dc12..936734e18 100644 --- a/examples/rays/Scene.hs +++ b/examples/rays/Scene.hs @@ -1,5 +1,8 @@ {-# LANGUAGE ParallelListComp #-} -{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# OPTIONS_GHC -fplugin=Foreign.Storable.Generic.Plugin #-} +{-# OPTIONS_GHC -fplugin-opt=Foreign.Storable.Generic.Plugin:-v0 #-} module Scene where @@ -11,25 +14,16 @@ import Data.Bits import Data.Word import Foreign.Marshal.Array import Foreign.Ptr -import Foreign.Storable ( Storable(..) ) +import Foreign.Storable.Generic +import GHC.Generics ( Generic ) import Linear.V3 import Linear.V4 import MonadVulkan -import TH.Derive import Vulkan.Core10 import Vulkan.Extensions.VK_KHR_acceleration_structure import Vulkan.Zero import VulkanMemoryAllocator -data Sphere = Sphere - { spherePos :: V4 Float - , sphereColor :: V4 Float - } - -$($(derive [d| - instance Deriving (Storable Sphere) - |])) - scene :: [Sphere] scene = [ Sphere (V4 originx 0 0 radius) (V4 r g b 1) @@ -101,9 +95,14 @@ initBuffer usage xs = do pure buf ---------------------------------------------------------------- --- Utils +-- Sphere ---------------------------------------------------------------- +data Sphere = Sphere + { spherePos :: V4 Float + , sphereColor :: V4 Float + } + deriving(Generic, GStorable) sphereRadius :: Sphere -> Float sphereRadius = view _w . spherePos @@ -121,5 +120,3 @@ sphereAABB s = (maxi ^. _x) (maxi ^. _y) (maxi ^. _z) - - diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index 785c7db4f..130997675 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -183,6 +183,8 @@ executable rays , base <5 , bytestring , containers + , derive-storable + , derive-storable-plugin , lens , linear , primitive-unlifted @@ -191,7 +193,6 @@ executable rays , sdl2 >=2.5.2.0 , template-haskell , text - , th-utilities , transformers , unagi-chan , unliftio diff --git a/nix/haskell-packages.nix b/nix/haskell-packages.nix index 93406d56d..5ce279868 100644 --- a/nix/haskell-packages.nix +++ b/nix/haskell-packages.nix @@ -63,6 +63,20 @@ in self: super: # pretty-simple = self.pretty-simple_4_0_0_0; prettyprinter = self.prettyprinter_1_7_0; + derive-storable = self.callHackageDirect { + pkg = "derive-storable"; + ver = "0.3.0.0"; + sha256 = "0h9v6k1651acsqs64mkidqrflld7ghhbiir7z9f0wm8vrqwc6wyp"; + } { }; + derive-storable-plugin = appendPatch (doJailbreak (self.callHackageDirect { + pkg = "derive-storable-plugin"; + ver = "0.2.3.1"; + sha256 = "0iibzdjlx2v5caib41a3i5l67dplwwhp8sys3hfc6m3lyhghzg16"; + } { })) (pkgs.fetchpatch { + url = "https://github.com/mkloczko/derive-storable-plugin/pull/4.patch"; + name = "pure.patch"; + sha256 = "11fm91062slgh25na3pmjpf2sn9z1gg9lg5jr4nv2q8a2bzg32zs"; + }); # # Overrides for generate From 876bc0935d3acc8a32b76a7853ca0fa7f0551094 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 17:25:15 +0800 Subject: [PATCH 62/70] Print device memory properties in info example --- examples/info/Main.hs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/info/Main.hs b/examples/info/Main.hs index c447963c0..58dc555c6 100644 --- a/examples/info/Main.hs +++ b/examples/info/Main.hs @@ -1,5 +1,4 @@ -module Main - where +module Main where import Control.Exception import Data.Foldable @@ -25,11 +24,9 @@ deviceInfo p = do traverse_ myPrint layers myPrint =<< getPhysicalDeviceFeatures p myPrint =<< getPhysicalDeviceProperties p + myPrint =<< getPhysicalDeviceMemoryProperties p myPrint :: Show a => a -> IO () -myPrint = - pPrintOpt - CheckColorTty - defaultOutputOptionsDarkBg - { outputOptionsStringStyle = Literal - } +myPrint = pPrintOpt + CheckColorTty + defaultOutputOptionsDarkBg { outputOptionsStringStyle = Literal } From 9f8461e131abbc9283b525fccca7f2d386c496f0 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 17:25:51 +0800 Subject: [PATCH 63/70] Add minmum bound on derive-storable --- examples/vulkan-examples.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index 130997675..45481cf4d 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -183,7 +183,7 @@ executable rays , base <5 , bytestring , containers - , derive-storable + , derive-storable >=0.3 , derive-storable-plugin , lens , linear From a3b66b0e17cbced3a7df256f70e7666b074ae5ee Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 18:11:29 +0800 Subject: [PATCH 64/70] Allow specifying target-env for glslangValidator --- examples/rays/Pipeline.hs | 8 +++--- examples/resize/Julia.hs | 2 +- utils/changelog.md | 1 + utils/src/Vulkan/Utils/ShaderQQ.hs | 40 +++++++++++++++++------------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/examples/rays/Pipeline.hs b/examples/rays/Pipeline.hs index 481564d20..241a780c6 100644 --- a/examples/rays/Pipeline.hs +++ b/examples/rays/Pipeline.hs @@ -186,7 +186,7 @@ createRTDescriptorSets descriptorSetLayout tlas SceneBuffers {..} numDescriptorS createRayGenerationShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) createRayGenerationShader = do - let code = $(compileShaderQ "rgen" [glsl| + let code = $(compileShaderQ (Just "spirv1.4") "rgen" [glsl| #version 460 #extension GL_EXT_ray_tracing : require @@ -238,7 +238,7 @@ createRayGenerationShader = do createRayHitShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) createRayHitShader = do - let code = $(compileShaderQ "rchit" [glsl| + let code = $(compileShaderQ (Just "spirv1.4") "rchit" [glsl| #version 460 #extension GL_EXT_ray_tracing : require @@ -269,7 +269,7 @@ createRayHitShader = do createRayIntShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) createRayIntShader = do - let code = $(compileShaderQ "rint" [glsl| + let code = $(compileShaderQ (Just "spirv1.4") "rint" [glsl| #version 460 #extension GL_EXT_ray_tracing : require @@ -311,7 +311,7 @@ createRayIntShader = do createRayMissShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) createRayMissShader = do - let code = $(compileShaderQ "rmiss" [glsl| + let code = $(compileShaderQ (Just "spirv1.4") "rmiss" [glsl| #version 460 #extension GL_EXT_ray_tracing : require diff --git a/examples/resize/Julia.hs b/examples/resize/Julia.hs index f03e76e48..2dc3e2df7 100644 --- a/examples/resize/Julia.hs +++ b/examples/resize/Julia.hs @@ -100,7 +100,7 @@ juliaDescriptorSet descriptorSetLayout imageViews = do juliaShader :: V (ReleaseKey, SomeStruct PipelineShaderStageCreateInfo) juliaShader = do - let compCode = $(compileShaderQ "comp" [glsl| + let compCode = $(compileShaderQ (Just "vulkan1.0") "comp" [glsl| #version 450 #extension GL_ARB_separate_shader_objects : enable diff --git a/utils/changelog.md b/utils/changelog.md index 0337bad6a..a5a904b80 100644 --- a/utils/changelog.md +++ b/utils/changelog.md @@ -7,6 +7,7 @@ - Change the creation helpers in `Vulkan.Utils.Initialization` to use the new `Requirement` types. - Add QuasiQuoters for creating device requirements in `Vulkan.Utils.Requirements.TH` +- Allow selecting target environment in `compileShader` ## [0.3] - 2020-11-24 diff --git a/utils/src/Vulkan/Utils/ShaderQQ.hs b/utils/src/Vulkan/Utils/ShaderQQ.hs index f092e26b2..47a6e9b21 100644 --- a/utils/src/Vulkan/Utils/ShaderQQ.hs +++ b/utils/src/Vulkan/Utils/ShaderQQ.hs @@ -113,7 +113,7 @@ vert :: QuasiQuoter vert = shaderQQ "vert" shaderQQ :: String -> QuasiQuoter -shaderQQ stage = (badQQ stage) { quoteExp = compileShaderQ stage } +shaderQQ stage = (badQQ stage) { quoteExp = compileShaderQ Nothing stage } -- * Utilities @@ -121,15 +121,17 @@ shaderQQ stage = (badQQ stage) { quoteExp = compileShaderQ stage } -- -- Messages are converted to GHC warnings or errors depending on compilation success. compileShaderQ - :: String + :: Maybe String + -- ^ Argument to pass to `--target-env` + -> String -- ^ stage -> String -- ^ glsl code -> Q Exp -- ^ Spir-V bytecode -compileShaderQ stage code = do +compileShaderQ targetEnv stage code = do loc <- location - (warnings, result) <- compileShader (Just loc) stage code + (warnings, result) <- compileShader (Just loc) targetEnv stage code case warnings of [] -> pure () _some -> reportWarning $ prepare warnings @@ -156,21 +158,26 @@ compileShader :: MonadIO m => Maybe Loc -- ^ Source location + -> Maybe String + -- ^ Argument to pass to `--target-env` -> String -- ^ stage -> String -- ^ glsl code -> m ([GLSLWarning], Either [GLSLError] ByteString) -- ^ Spir-V bytecode with warnings or errors -compileShader loc stage code = +compileShader loc targetEnv stage code = liftIO $ withSystemTempDirectory "th-shader" $ \dir -> do let codeWithLineDirective = maybe code (insertLineDirective code) loc let shader = dir <> "/shader." <> stage spirv = dir <> "/shader.spv" writeFile shader codeWithLineDirective - (rc, out, err) <- readProcess - $ proc "glslangValidator" ["-S", stage, "-V", shader, "-o", spirv] + let targetArgs = case targetEnv of + Nothing -> [] + Just t -> ["--target-env", t] + args = targetArgs ++ ["-S", stage, "-V", shader, "-o", spirv] + (rc, out, err) <- readProcess $ proc "glslangValidator" args let (warnings, errors) = processValidatorMessages (out <> err) case rc of ExitSuccess -> do @@ -179,16 +186,15 @@ compileShader loc stage code = ExitFailure _rc -> pure (warnings, Left errors) processValidatorMessages :: BSL.ByteString -> ([GLSLWarning], [GLSLError]) -processValidatorMessages = foldr grep ([], []) . filter (not . null) . lines . BSL.unpack - where - grep line (ws, es) - | "WARNING: " `isPrefixOf` line = (cut line : ws, es) - | "ERROR: " `isPrefixOf` line = (ws, cut line : es) - | otherwise = (ws, es) - - cut line = takeFileName path <> msg - where - (path, msg) = break (== ':') . drop 1 $ dropWhile (/= ' ') line +processValidatorMessages = + foldr grep ([], []) . filter (not . null) . lines . BSL.unpack + where + grep line (ws, es) | "WARNING: " `isPrefixOf` line = (cut line : ws, es) + | "ERROR: " `isPrefixOf` line = (ws, cut line : es) + | otherwise = (ws, es) + + cut line = takeFileName path <> msg + where (path, msg) = break (== ':') . drop 1 $ dropWhile (/= ' ') line -- If possible, insert a #line directive after the #version directive (as well -- as the extension which allows filenames in line directives. From b32d742ab03fb0933ab4dcadc1694e3c62cdea4a Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 18:13:34 +0800 Subject: [PATCH 65/70] Add derive-storable to stack.yaml --- stack.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stack.yaml b/stack.yaml index dde366f83..1cc2cc01d 100644 --- a/stack.yaml +++ b/stack.yaml @@ -14,6 +14,8 @@ extra-deps: - dependent-map-0.4.0.0 - dependent-sum-0.7.1.0 - constraints-extras-0.3.0.2 +- derive-storable-0.3.0.0 +- derive-storable-plugin-0.2.3.1 nix: enable: false From 53333dc7ed442a3dcc419c5b0eb74512e9a1885b Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 18:16:14 +0800 Subject: [PATCH 66/70] Add derive-storable 8.10 version to cabal.project and stack.yaml --- cabal.project | 5 +++++ stack.yaml | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cabal.project b/cabal.project index d84d1ffde..f1ca35171 100644 --- a/cabal.project +++ b/cabal.project @@ -10,4 +10,9 @@ source-repository-package location: https://github.com/expipiplus1/brittany.git tag: b80f77c36bda563665c616abbdb1eaaf35b1da1c +source-repository-package + type: git + location: https://github.com/expipiplus1/derive-storable-plugin.git + tag: e98e5835913e50a10cf8545af9a1f29f84a9d15a + allow-newer: strict diff --git a/stack.yaml b/stack.yaml index 1cc2cc01d..97a517233 100644 --- a/stack.yaml +++ b/stack.yaml @@ -15,7 +15,9 @@ extra-deps: - dependent-sum-0.7.1.0 - constraints-extras-0.3.0.2 - derive-storable-0.3.0.0 -- derive-storable-plugin-0.2.3.1 +- github: expipiplus1/derive-storable-plugin + commit: e98e5835913e50a10cf8545af9a1f29f84a9d15a + nix: enable: false From 338a0d12774d45cd96ecb3c6641994fee349bb09 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 21:17:17 +0800 Subject: [PATCH 67/70] formatting --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 72d11af61..c7ffdf607 100644 --- a/changelog.md +++ b/changelog.md @@ -1,8 +1,8 @@ # Change Log ## WIP -- Bump API version to v1.2.163 +- Bump API version to v1.2.163 - Add `Vulkan.Requirement`, a module for specifying requirements for `Device`s and `Instance`s - Expose SPIR-V Extensions and Capabilities in `Vulkan.SPIRVRequirements` From d8cfbeedbd332919e54bd654a6679f2b0bc20cfc Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 21:18:37 +0800 Subject: [PATCH 68/70] Add barrier for camera matrix update --- examples/rays/Render.hs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/examples/rays/Render.hs b/examples/rays/Render.hs index dd93d30c0..4c396f791 100644 --- a/examples/rays/Render.hs +++ b/examples/rays/Render.hs @@ -208,6 +208,20 @@ myRecordCommandBuffer Frame {..} imageIndex = do [fDescriptorSet] [] + cmdPipelineBarrier' + PIPELINE_STAGE_TOP_OF_PIPE_BIT + PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR + zero + [] + [ zero { srcAccessMask = ACCESS_HOST_WRITE_BIT + , dstAccessMask = ACCESS_SHADER_READ_BIT + , buffer = fCameraMatricesBuffer + , offset = fCameraMatricesOffset + , size = fromIntegral (sizeOf (undefined :: CameraMatrices)) + } + ] + [] + -- -- The actual ray tracing -- From ba51d4f1773f9049b9038016f4134ba073e5b94d Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 21:29:43 +0800 Subject: [PATCH 69/70] Disable raytracing example on CI (except good ol' nix) --- .github/workflows/ci.yml | 6 +++--- examples/package.yaml | 11 ++++++++++- examples/vulkan-examples.cabal | 9 ++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b131369c3..ad4a7df0b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,10 +119,10 @@ jobs: - run: | if command -v glslc &> /dev/null; then - cabal configure -fgeneric-instances -fhave-shaderc + cabal configure -fgeneric-instances -f-raytracing -fhave-shaderc else echo "glslc could not be found" - cabal configure -fgeneric-instances -f-have-shaderc + cabal configure -fgeneric-instances -f-raytracing -f-have-shaderc fi shell: bash @@ -155,7 +155,7 @@ jobs: strategy: matrix: os: [ubuntu-20.04, macOS-latest, windows-latest] - stack-args: ['--flag vulkan:generic-instances --flag VulkanMemoryAllocator:generic-instances --flag vulkan-examples:-have-shaderc --system-ghc'] + stack-args: ['--flag vulkan:generic-instances --flag VulkanMemoryAllocator:generic-instances --flag vulkan-examples:-raytracing --flag vulkan-examples:-have-shaderc --system-ghc'] exclude: # https://github.com/actions/setup-haskell/issues/49 - os: windows-latest diff --git a/examples/package.yaml b/examples/package.yaml index bb09edc84..7c63c03ce 100644 --- a/examples/package.yaml +++ b/examples/package.yaml @@ -166,6 +166,8 @@ executables: when: - condition: impl(ghc < 8.10.0) buildable: false + - condition: '!flag(raytracing)' + buildable: false when: - condition: os(windows) @@ -181,7 +183,14 @@ flags: have-shaderc: description: Set this flag if you have shaderc (and the glslc executable) installed. - It enables the examples which use HLSL shaders. + It enables building the examples which use HLSL shaders. + default: yes + manual: yes + raytracing: + description: + Set this flag if you have a version of glslValidator recent enough to + compile ray tracing shaders. It enables building the examples which use + ray tracing. default: yes manual: yes diff --git a/examples/vulkan-examples.cabal b/examples/vulkan-examples.cabal index 45481cf4d..317a642f8 100644 --- a/examples/vulkan-examples.cabal +++ b/examples/vulkan-examples.cabal @@ -22,7 +22,12 @@ source-repository head location: https://github.com/expipiplus1/vulkan flag have-shaderc - description: Set this flag if you have shaderc (and the glslc executable) installed. It enables the examples which use HLSL shaders. + description: Set this flag if you have shaderc (and the glslc executable) installed. It enables building the examples which use HLSL shaders. + manual: True + default: True + +flag raytracing + description: Set this flag if you have a version of glslValidator recent enough to compile ray tracing shaders. It enables building the examples which use ray tracing. manual: True default: True @@ -203,6 +208,8 @@ executable rays ghc-options: -optl-mconsole if impl(ghc < 8.10.0) buildable: False + if !flag(raytracing) + buildable: False default-language: Haskell2010 executable resize From 1c7584a3437e81c5e9f212b6134203bdaa03cf58 Mon Sep 17 00:00:00 2001 From: Joe Hermaszewski Date: Mon, 30 Nov 2020 21:37:48 +0800 Subject: [PATCH 70/70] Release v3.8, utils-v0.3, vma-v0.3.11 --- VulkanMemoryAllocator/VulkanMemoryAllocator.cabal | 6 ++---- VulkanMemoryAllocator/changelog.md | 4 ++++ VulkanMemoryAllocator/package.yaml | 4 ++-- changelog.md | 2 ++ package.yaml | 2 +- utils/changelog.md | 2 ++ utils/package.yaml | 4 ++-- utils/vulkan-utils.cabal | 4 ++-- vulkan.cabal | 2 +- 9 files changed, 18 insertions(+), 12 deletions(-) diff --git a/VulkanMemoryAllocator/VulkanMemoryAllocator.cabal b/VulkanMemoryAllocator/VulkanMemoryAllocator.cabal index d9d9673b4..1e83f6fed 100644 --- a/VulkanMemoryAllocator/VulkanMemoryAllocator.cabal +++ b/VulkanMemoryAllocator/VulkanMemoryAllocator.cabal @@ -3,11 +3,9 @@ cabal-version: 2.2 -- This file has been generated from package.yaml by hpack version 0.34.2. -- -- see: https://github.com/sol/hpack --- --- hash: fcf45270da7fe44091b7dee466087cd52abed25e68532b85a04a30915dd1da94 name: VulkanMemoryAllocator -version: 0.3.10 +version: 0.3.11 synopsis: Bindings to the VulkanMemoryAllocator library category: Graphics homepage: https://github.com/expipiplus1/vulkan#readme @@ -65,7 +63,7 @@ library , bytestring , transformers , vector - , vulkan >=3.6 && <3.8 + , vulkan >=3.6 && <3.9 if flag(safe-foreign-calls) cpp-options: -DSAFE_FOREIGN_CALLS if flag(vma-ndebug) diff --git a/VulkanMemoryAllocator/changelog.md b/VulkanMemoryAllocator/changelog.md index 36f6b9217..900cdff6f 100644 --- a/VulkanMemoryAllocator/changelog.md +++ b/VulkanMemoryAllocator/changelog.md @@ -2,6 +2,10 @@ ## WIP +## [0.3.11] - 2020-11-30 + +- Raise upper bound on `vulkan` + ## [0.3.10] - 2020-11-24 - Documentation fixes diff --git a/VulkanMemoryAllocator/package.yaml b/VulkanMemoryAllocator/package.yaml index 898aa7b51..6d5539d30 100644 --- a/VulkanMemoryAllocator/package.yaml +++ b/VulkanMemoryAllocator/package.yaml @@ -1,5 +1,5 @@ name: VulkanMemoryAllocator -version: "0.3.10" +version: "0.3.11" synopsis: Bindings to the VulkanMemoryAllocator library category: Graphics maintainer: Joe Hermaszewski @@ -20,7 +20,7 @@ library: src/lib.cpp dependencies: - base <5 - - vulkan >= 3.6 && < 3.8 + - vulkan >= 3.6 && < 3.9 - bytestring - transformers - vector diff --git a/changelog.md b/changelog.md index c7ffdf607..5871b5cf1 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,8 @@ ## WIP +## [3.8] - 2020-11-30 + - Bump API version to v1.2.163 - Add `Vulkan.Requirement`, a module for specifying requirements for `Device`s and `Instance`s diff --git a/package.yaml b/package.yaml index 91fc0035d..7f1be611f 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: vulkan -version: "3.7" +version: "3.8" synopsis: Bindings to the Vulkan graphics API. category: Graphics maintainer: Joe Hermaszewski diff --git a/utils/changelog.md b/utils/changelog.md index a5a904b80..bf11b8003 100644 --- a/utils/changelog.md +++ b/utils/changelog.md @@ -2,6 +2,8 @@ ## WIP +## [0.4] - 2020-11-30 + - Add `Vulkan.Utils.Requirements`, a module with several helpers for the `Requirement` types found in `Vulkan.Requirement` - Change the creation helpers in `Vulkan.Utils.Initialization` to use the new diff --git a/utils/package.yaml b/utils/package.yaml index 0b3587b76..43e647192 100644 --- a/utils/package.yaml +++ b/utils/package.yaml @@ -1,5 +1,5 @@ name: vulkan-utils -version: "0.3" +version: "0.4" synopsis: Utils for the vulkan package category: Graphics maintainer: Joe Hermaszewski @@ -32,7 +32,7 @@ library: - typed-process - unordered-containers - vector - - vulkan >= 3.6.14 && < 3.8 + - vulkan >= 3.6.14 && < 3.9 tests: doctests: diff --git a/utils/vulkan-utils.cabal b/utils/vulkan-utils.cabal index f3ffb4588..4bdcbd1d2 100644 --- a/utils/vulkan-utils.cabal +++ b/utils/vulkan-utils.cabal @@ -5,7 +5,7 @@ cabal-version: 1.24 -- see: https://github.com/sol/hpack name: vulkan-utils -version: 0.3 +version: 0.4 synopsis: Utils for the vulkan package category: Graphics homepage: https://github.com/expipiplus1/vulkan#readme @@ -68,7 +68,7 @@ library , typed-process , unordered-containers , vector - , vulkan >=3.6.14 && <3.8 + , vulkan >=3.6.14 && <3.9 default-language: Haskell2010 test-suite doctests diff --git a/vulkan.cabal b/vulkan.cabal index 93c33e6ac..81e25fbb3 100644 --- a/vulkan.cabal +++ b/vulkan.cabal @@ -5,7 +5,7 @@ cabal-version: 2.2 -- see: https://github.com/sol/hpack name: vulkan -version: 3.7 +version: 3.8 synopsis: Bindings to the Vulkan graphics API. category: Graphics homepage: https://github.com/expipiplus1/vulkan#readme