packages feed

fir-0.1.0.0: src/SPIRV/PrimTy.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GADTs              #-}
{-# LANGUAGE NamedFieldPuns     #-}

{-|
Module: SPIRV.PrimTy

This module enumerates the types that exist within the SPIR-V type system.

These are logical types: they don't include any memory layout information.
The layout of a type in memory is specified separately, by a 'Layout'.

See the SPIR-V specification, §3.22.6 __Type-Declaration instructions__.
-}

module SPIRV.PrimTy
  ( PrimTy(..)
  , PointerTy(..)
  , componentLayout
  , tyOp
  , scalars
  ) where

-- base
import Data.Word
  ( Word32 )
import Prelude
  hiding (Integer, Floating)

-- text-short
import Data.Text.Short
  ( ShortText )

-- fir
import SPIRV.Image
  ( Image(texelComponent) )
import SPIRV.Layout
  ( Layout(blockKind) )
import SPIRV.Operation
  hiding ( Function, Image, SampledImage )
import SPIRV.ScalarTy
  ( ScalarTy(Integer, Floating) )
import SPIRV.Storage
  ( StorageClass )

--------------------------------------------------
-- SPIR-V types

data PrimTy where
  Unit    :: PrimTy -- known as Void in the SPIR-V specification
  Boolean :: PrimTy
  Scalar  :: ScalarTy -> PrimTy
  Vector  ::
    { size  :: Word32
    , eltTy :: PrimTy
    } -> PrimTy
  Matrix ::
    { rows    :: Word32
    , cols    :: Word32
    , entryTy :: ScalarTy
    } -> PrimTy
  Array ::
    { size  :: Word32
    , eltTy :: PrimTy
    } -> PrimTy
  RuntimeArray ::
    { eltTy :: PrimTy
    } -> PrimTy
  Struct ::
    { eltTys :: [ ( Maybe ShortText, PrimTy ) ]
    -- ^ the (optional) field names are only used to annotate the source code
    } -> PrimTy
  Pointer  :: PointerTy -> PrimTy
  Function ::
    { argumentTypes :: [PrimTy]
    , resultType    :: PrimTy
    } -> PrimTy
  Image        :: Image -> PrimTy
  Sampler      ::          PrimTy -- opaque
  SampledImage :: Image -> PrimTy
  AccelerationStructure :: PrimTy -- opaque
  RayQuery              :: PrimTy -- opaque
  deriving stock ( Show, Eq, Ord )

-- | A pointer type, to a type laid out in memory in the given way.
data PointerTy
  = PointerTy
  { pointerStorage :: StorageClass
  , pointerLayout  :: Layout
  , pointee        :: PrimTy
  }
  deriving stock ( Show, Eq, Ord )

-- | The layout of the components of a composite type with the given layout.
--
-- The elements of an array of interface blocks are interface blocks,
-- but the members of an interface block are not.
componentLayout :: PrimTy -> Layout -> Layout
componentLayout Array        {} lay = lay
componentLayout RuntimeArray {} lay = lay
componentLayout _               lay = lay { blockKind = Nothing }

tyOp :: PrimTy -> Operation
tyOp Unit                    = TypeVoid
tyOp Boolean                 = TypeBool
tyOp (Scalar Integer   {})   = TypeInt
tyOp (Scalar Floating  {})   = TypeFloat
tyOp (Vector _ (Vector _ _)) = TypeMatrix
  -- SPIR-V doesn't have vectors of vectors, so declare them as matrices instead.
  -- This is a bit of a workaround for issue #95.
tyOp Vector             {}   = TypeVector
tyOp Matrix             {}   = TypeMatrix
tyOp Array              {}   = TypeArray
tyOp RuntimeArray       {}   = TypeRuntimeArray
tyOp Struct             {}   = TypeStruct
tyOp Function           {}   = TypeFunction
tyOp Pointer            {}   = TypePointer
tyOp Image              {}   = TypeImage
tyOp Sampler                 = TypeSampler
tyOp SampledImage       {}   = TypeSampledImage
tyOp AccelerationStructure   = TypeAccelerationStructure
tyOp RayQuery                = TypeRayQuery

scalars :: PrimTy -> [ ScalarTy ]
scalars Unit                     = [ ]
scalars Boolean                  = [ ]
scalars (Scalar s)               = [ s ]
scalars (Vector _ a)             = scalars a
scalars (Matrix _ _ a)           = [ a ]
scalars (Array { eltTy })        = scalars eltTy
scalars (RuntimeArray { eltTy }) = scalars eltTy
scalars (Struct { eltTys })      = scalars . snd =<< eltTys
scalars (Pointer ptrTy)          = scalars ( pointee ptrTy )
scalars (Function as b)          = scalars b ++ ( scalars =<< as )
scalars (Image img)              = [ texelComponent img ]
scalars Sampler                  = [ ]
scalars (SampledImage img)       = [ texelComponent img ]
scalars AccelerationStructure    = []
scalars RayQuery                 = []