fir-0.1.0.0: src/SPIRV/Requirements.hs
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE ViewPatterns #-}
{-|
Module: SPIRV.Requrements
Functions computing capability/extension requirements
for various circumstances.
-}
module SPIRV.Requirements where
-- base
import Data.Bits
( Bits(testBit) )
import Data.Word
( Word32 )
-- containers
import Data.Set
( Set )
import qualified Data.Set as Set
( insert, unions )
-- fir
import SPIRV.Capability
import SPIRV.Extension
import qualified SPIRV.Image as Image
import SPIRV.Operation
hiding ( Capability )
import SPIRV.PrimOp
( PrimOp(..), VecPrimOp(..), GroupPrimOp(..), BitPrimOp(ReverseBits)
, op
)
import SPIRV.PrimTy
( PrimTy, scalars )
import qualified SPIRV.PrimTy as PrimTy
import SPIRV.ScalarTy
( ScalarTy, Width(..) )
import qualified SPIRV.ScalarTy as ScalarTy
import SPIRV.Stage
( ExecutionModel(Stage), Stage(..), Shader, Backend(..) )
import qualified SPIRV.Stage as Stage
( ExecutionModel(..), Shader(..) )
import SPIRV.Version
( Version(..) )
--------------------------------------------------------------------------
-- primitive operations
primOpCapabilities :: Backend -> PrimOp -> Set Capability
primOpCapabilities bk ( op bk -> SatConvertSToU ) = [ ComputeKernel ]
primOpCapabilities bk ( op bk -> SatConvertUToS ) = [ ComputeKernel ]
primOpCapabilities _ ( MatOp {} ) = [ Matrix ]
primOpCapabilities _ ( RayOp {} ) = [ RayTracingKHR ]
primOpCapabilities bk ( BitOp ReverseBits _ ) =
case bk of
SPIRV.Stage.Vulkan -> [ ] -- (requires the Shader capability)
SPIRV.Stage.OpenCL -> [ BitInstructions ]
primOpCapabilities bk ( GroupOp gpOp ) = groupOpCapabilities bk gpOp
primOpCapabilities bk ( VecOp ( Vectorise primop ) _ _ ) = primOpCapabilities bk primop
primOpCapabilities _ _ = [ ]
groupOpCapabilities :: Backend -> GroupPrimOp -> Set Capability
groupOpCapabilities bk _ =
case bk of
SPIRV.Stage.OpenCL -> [ Groups ]
SPIRV.Stage.Vulkan -> [ GroupNonUniformArithmetic ]
primOpExtensions :: Backend -> PrimOp -> Set Extension
primOpExtensions SPIRV.Stage.OpenCL ( BitOp ReverseBits _ ) = [ SPV_KHR_bit_instructions ]
primOpExtensions bk ( VecOp ( Vectorise primop ) _ _ ) = primOpExtensions bk primop
primOpExtensions _ _ = [ ]
-- | Why the backend doesn't support a primitive operation (regardless of capabilities,
-- extensions and SPIR-V version), if it doesn't.
primOpUnsupported :: Backend -> PrimOp -> Maybe String
primOpUnsupported SPIRV.Stage.Vulkan ( BitOp ReverseBits s )
| ScalarTy.scalarWidth s /= W32
= Just "Vulkan only supports OpBitReverse on 32-bit integers"
primOpUnsupported bk ( VecOp ( Vectorise primop ) _ _ ) = primOpUnsupported bk primop
primOpUnsupported _ _ = Nothing
primOpMinVersion :: Backend -> PrimOp -> Version
primOpMinVersion SPIRV.Stage.Vulkan ( GroupOp {} ) = Version 1 3
primOpMinVersion _ _ = Version 1 0
--------------------------------------------------------------------------
-- types
scalarCapabilities :: ScalarTy -> Set Capability
scalarCapabilities (ScalarTy.Integer _ W8 ) = [ Int8 ]
scalarCapabilities (ScalarTy.Integer _ W16) = [ Int16 ]
scalarCapabilities (ScalarTy.Integer _ W64) = [ Int64 ]
scalarCapabilities (ScalarTy.Integer _ _ ) = [ ]
scalarCapabilities (ScalarTy.Floating W16) = [ Float16 ]
scalarCapabilities (ScalarTy.Floating W64) = [ Float64 ]
scalarCapabilities (ScalarTy.Floating _ ) = [ ]
primTyCapabilities :: PrimTy -> Set Capability
primTyCapabilities ( PrimTy.Matrix _ _ ty )
= Set.insert Matrix $ scalarCapabilities ty
primTyCapabilities ( PrimTy.Vector n ty )
| n > 4 = Set.insert Vector16 $ primTyCapabilities ty
| otherwise = primTyCapabilities ty
primTyCapabilities ( PrimTy.Image img )
= imageCapabilities img <> scalarCapabilities ( Image.texelComponent img )
primTyCapabilities ( PrimTy.SampledImage img )
= imageCapabilities img <> scalarCapabilities ( Image.texelComponent img )
primTyCapabilities ty
= Set.unions ( map scalarCapabilities ( PrimTy.scalars ty) )
-- types when present in an interface
globalCapabilities :: PrimTy -> Set Capability
globalCapabilities = primTyCapabilities
globalScalarExtensions :: ScalarTy -> Set Extension
globalScalarExtensions (ScalarTy.Integer _ W8 ) = [ SPV_KHR_8bit_storage ]
globalScalarExtensions (ScalarTy.Integer _ W16) = [ SPV_KHR_16bit_storage ]
globalScalarExtensions (ScalarTy.Integer _ _ ) = [ ]
globalScalarExtensions (ScalarTy.Floating W16) = [ SPV_KHR_16bit_storage ]
globalScalarExtensions (ScalarTy.Floating _ ) = [ ]
globalExtensions :: PrimTy -> Set Extension
globalExtensions ty = Set.unions ( map globalScalarExtensions ( scalars ty ) )
--------------------------------------------------------------------------
-- stages / execution models
shaderCapabilities :: Shader -> Set Capability
shaderCapabilities Stage.VertexShader = [ Shader ]
shaderCapabilities Stage.TessellationControlShader = [ Tessellation ] --- |
shaderCapabilities Stage.TessellationEvaluationShader = [ Tessellation ] --- |-- shader capability implied
shaderCapabilities Stage.GeometryShader = [ Geometry ] --- |
shaderCapabilities Stage.FragmentShader = [ Shader ]
shaderCapabilities Stage.ComputeShader = [ Shader ]
stageCapabilities :: Stage -> Set Capability
stageCapabilities (ShaderStage s) = shaderCapabilities s
stageCapabilities (MeshStage _) = [ MeshShadingNV ]
stageCapabilities (RayStage _) = [ RayTracingKHR ]
executionModelCapabilities :: ExecutionModel -> Set Capability
executionModelCapabilities (Stage s) = stageCapabilities s
executionModelCapabilities Stage.Kernel = [ ComputeKernel, Addresses ]
stageExtensions :: Stage -> Set Extension
stageExtensions (ShaderStage _) = [ ]
stageExtensions (MeshStage _) = [ SPV_NV_mesh_shader ]
stageExtensions (RayStage _) = [ SPV_KHR_ray_tracing ]
executionModelExtensions :: ExecutionModel -> Set Extension
executionModelExtensions (Stage s) = stageExtensions s
executionModelExtensions Stage.Kernel = [ ]
--------------------------------------------------------------------------
-- images, image formats, image properties
formatCapabilities :: Image.ImageFormat Word32 -> Set Capability
formatCapabilities format
= case Image.requiredFormatUsage format of
Just Image.Storage -> [ Shader, StorageImageExtendedFormats ]
_ -> [ Shader ]
-- | Capabilities required to read from an image of the given dimensionality
-- and format using @OpImageRead@.
unknownFormatReadCapabilities :: Image.Dimensionality -> Maybe (Image.ImageFormat Word32) -> Set Capability
unknownFormatReadCapabilities Image.SubpassData _ = [ ]
unknownFormatReadCapabilities _ Nothing = [ StorageImageReadWithoutFormat ]
unknownFormatReadCapabilities _ _ = [ ]
-- | Capabilities required to write to an image of the given format
-- using @OpImageWrite@.
unknownFormatWriteCapabilities :: Maybe (Image.ImageFormat Word32) -> Set Capability
unknownFormatWriteCapabilities Nothing = [ StorageImageWriteWithoutFormat ]
unknownFormatWriteCapabilities _ = [ ]
-- | Capabilities required to declare an image type.
imageCapabilities :: Image.Image -> Set Capability
imageCapabilities img
= foldMap formatCapabilities ( Image.imageFormat img )
<> dimCapabilities ( Image.imageUsage img ) ( Image.dimensionality img ) ( Image.arrayness img )
<> msCapabilities ( Image.imageUsage img ) ( Image.arrayness img ) ( Image.multiSampling img )
dimCapabilities :: Maybe Image.ImageUsage -> Image.Dimensionality -> Image.Arrayness -> Set Capability
dimCapabilities _ Image.SubpassData _ = [ Shader, InputAttachment ]
dimCapabilities (Just Image.Storage) Image.Rect _ = [ Shader, SampledRect, ImageRect ]
dimCapabilities _ Image.Rect _ = [ Shader, SampledRect ]
dimCapabilities (Just Image.Storage) Image.OneD _ = [ Sampled1D, Image1D ]
dimCapabilities _ Image.OneD _ = [ Sampled1D ]
dimCapabilities (Just Image.Storage) Image.Cube Image.Arrayed = [ SampledCubeArray, ImageCubeArray ]
dimCapabilities _ Image.Cube Image.Arrayed = [ SampledCubeArray ]
dimCapabilities (Just Image.Storage) Image.Buffer _ = [ SampledBuffer, ImageBuffer ]
dimCapabilities _ Image.Buffer _ = [ SampledBuffer ]
dimCapabilities _ _ _ = [ ]
msCapabilities :: Maybe Image.ImageUsage -> Image.Arrayness -> Image.MultiSampling -> Set Capability
msCapabilities (Just Image.Storage) Image.Arrayed Image.MultiSampled = [ StorageImageMultisample, ImageMSArray ]
msCapabilities (Just Image.Storage) Image.NonArrayed Image.MultiSampled = [ StorageImageMultisample ]
msCapabilities _ _ _ = [ ]
-- lod capability from image operand bitmask
-- (note that the bitmask is shifted up one byte from what SPIR-V uses)
lodCapabilities :: Backend -> Word32 -> Set Capability
lodCapabilities bk bm
-- uses the LOD operand
| bm `testBit` 9
&& bk == SPIRV.Stage.OpenCL
= [ ImageBasic, ImageMipmap ]
-- uses the MinLOD opeand
| bm `testBit` 15
= [ MinLod ]
| otherwise
= [ ]
-- whether the ImageGatherExtended capability is required
gatherCapabilities :: Word32 -> Set Capability
gatherCapabilities bm
| bm `testBit` 12 -- Offset operand
|| bm `testBit` 13 -- ConstOffsets operand
= [ ImageGatherExtended ]
| otherwise
= [ ]