fir-0.1.0.0: src/FIR/AST/Images.hs
{-# OPTIONS_GHC -fno-warn-missing-pattern-synonym-signatures -Wno-missing-signatures #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeOperators #-}
{-|
Module: FIR.AST.Images
Handling image operands and image query operations.
-}
module FIR.AST.Images where
-- base
import Data.Kind
( Type )
import Data.Proxy
( Proxy )
import Data.Word
( Word32 )
import GHC.TypeLits
( KnownSymbol, symbolVal )
-- containers
import Data.Tree
( Tree(Node) )
-- variant
import Data.Variant.EGADT
( pattern VF )
-- fir
import FIR.AST.Display
( Display(toTreeArgs), named )
import FIR.AST.Type
( AugType(..), Eff )
import {-# SOURCE #-} FIR.Prim.Image
( ImageOperands, OperandName(..)
, GatherInfo(..), WhichGather
)
import {-# SOURCE #-} FIR.Prim.Types
( PrimTy )
import FIR.Validation.Images
( BasicDim, NotCubeDim
, CanAddProj, CanAddDref
, UsesAffineCoords
, NoDuplicate
, NoMS, CanMultiSample
, NoLODOps
, ValidImageCoordinate, ValidImageGradCoordinate, ValidImageOffsetCoordinate
)
import qualified SPIRV.Image as SPIRV
------------------------------------------------------------
infixl 5 `Dref`
infixl 5 `Bias`
infixl 5 `LOD`
infixl 5 `MinLOD`
infixl 5 `Grad`
infixl 5 `ConstOffsetBy`
infixl 5 `OffsetBy`
infixl 5 `Gather`
infixl 5 `SampleNo`
pattern NilOps = VF NilOpsF
pattern Proj ops = VF (ProjF ops)
pattern Dref ref ops = VF (DrefF ref ops)
pattern Bias bias ops = VF (BiasF bias ops)
pattern LOD lod ops = VF (LODF lod ops)
pattern MinLOD lod ops = VF (MinLODF lod ops)
pattern Grad grad ops = VF (GradF grad ops)
pattern ConstOffsetBy off ops = VF (ConstOffsetByF off ops)
pattern OffsetBy off ops = VF (OffsetByF off ops)
pattern Gather gath ops = VF (GatherF gath ops)
pattern SampleNo sno ops = VF (SampleNoF sno ops)
pattern QuerySize img res = VF ( QuerySizeF img res )
pattern QuerySizeLOD img res = VF ( QuerySizeLODF img res )
pattern QueryLOD img res = VF ( QueryLODF img res )
pattern QueryLevels img res = VF ( QueryLevelsF img res )
pattern QuerySamples img res = VF ( QuerySamplesF img res )
data ImgOpsF ( ast :: AugType -> Type ) ( t :: AugType ) where
-- | End of (snoc-)list of image operands.
NilOpsF :: ImgOpsF ast ( Val ( ImageOperands props '[] ) )
-- | Use projective coordinates.
--
-- Must be provided after all other operands,
-- except possibly 'Dref'.
ProjF
:: CanAddProj ops
=> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (ProjectiveCoords ': ops) ) )
-- | Provide a depth-comparison reference value.
--
-- Must be provided after all other operands,
-- except possibly 'Proj'.
DrefF
:: CanAddDref ops
=> ast ( Val Float ) -- ^ Reference value used to perform the depth comparison.
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (DepthComparison ': ops) ) )
-- | Add a bias to the implicit level of detail.
BiasF
:: ( BasicDim "Bias" props
, NoMS "Bias" props
, NoDuplicate (BaseOperand ('SPIRV.LODOperand SPIRV.Bias)) ops
, NoLODOps "Bias" '[SPIRV.LOD, SPIRV.Grad] ops
, ValidImageCoordinate props ops imgCoord
)
=> ast ( Val imgCoord ) -- ^ Bias.
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand ('SPIRV.LODOperand SPIRV.Bias) ': ops) ) )
-- | Provide an explicit level of detail.
LODF
:: ( BasicDim "LOD" props
, NoMS "LOD" props
, NoDuplicate (BaseOperand ('SPIRV.LODOperand SPIRV.LOD)) ops
, NoLODOps "LOD" '[SPIRV.Bias, SPIRV.Grad, SPIRV.MinLOD] ops
, ValidImageCoordinate props ops imgCoord
)
=> ast ( Val imgCoord ) -- ^ LOD.
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand ('SPIRV.LODOperand SPIRV.LOD ) ': ops) ) )
-- | Specify the minimum level of detail to use
-- when sampling the image.
MinLODF
:: ( BasicDim "MinLOD" props
, NoMS "MinLOD" props
, NoDuplicate (BaseOperand ('SPIRV.LODOperand SPIRV.MinLOD)) ops
, NoLODOps "MinLOD" '[SPIRV.LOD, SPIRV.Bias] ops
, ValidImageCoordinate props ops imgCoord
)
=> ast ( Val imgCoord ) -- ^ Minimum LOD.
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand ('SPIRV.LODOperand SPIRV.MinLOD ) ': ops) ) )
-- | Provide explicit derivatives.
GradF
:: ( PrimTy gradCoords
, NoMS "Grad" props
, NoDuplicate (BaseOperand ('SPIRV.LODOperand SPIRV.Grad)) ops
, NoLODOps "Grad" '[ SPIRV.Bias, SPIRV.LOD ] ops
, ValidImageGradCoordinate props ops gradCoords
)
=> ( ast (Val gradCoords), ast (Val gradCoords) ) -- ^ Gradient: ( df\/dx, df\/dy ).
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand ('SPIRV.LODOperand SPIRV.Grad) ': ops) ) )
-- | Add a constant offset to the coordinates.
ConstOffsetByF
:: ( PrimTy offCoords
, NoDuplicate (BaseOperand SPIRV.ConstOffset) ops
, NotCubeDim "ConstOffsetBy" props
, ValidImageOffsetCoordinate props ops offCoords
)
=> offCoords -- Offset (a Haskell constant).
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand SPIRV.ConstOffset ': ops) ) )
-- | Add an offset to the coordinates.
OffsetByF
:: ( PrimTy offCoords
, NoDuplicate (BaseOperand SPIRV.Offset) ops
, NotCubeDim "OffsetBy" props
, ValidImageOffsetCoordinate props ops offCoords
)
=> ast ( Val offCoords ) -- Offset.
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand SPIRV.Offset ': ops) ) )
-- | Specify an image gather operation: gather texel data from 4 specified texel coordinates.
GatherF
:: ( NotCubeDim "Gather" props
, NoDuplicate (BaseOperand SPIRV.ConstOffsets) ops
, NoLODOps "Gather" '[ SPIRV.LOD, SPIRV.Grad, SPIRV.Bias, SPIRV.MinLOD ] ops
, UsesAffineCoords ops
)
=> GatherInfo ( ast ( Val Word32 ) ) (WhichGather ops)
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand SPIRV.ConstOffsets ': ops) ) )
-- | Specify which sample number to use in a multi-sampled image.
SampleNoF
:: ( CanMultiSample props
, NoDuplicate (BaseOperand SPIRV.Sample) ops
)
=> ast ( Val Word32 ) -- ^ Sample number.
-> ast ( Val ( ImageOperands props ops ) )
-> ImgOpsF ast ( Val ( ImageOperands props (BaseOperand SPIRV.Sample ': ops) ) )
data ImgQueryF ( ast :: AugType -> Type ) ( t :: AugType ) where
-- | Query the size of an image with implicit LOD.
QuerySizeF
:: ( KnownSymbol imgName, PrimTy res )
=> Proxy imgName
-> Proxy res
-> ImgQueryF ast ( Eff i i res )
-- | Query the size of an image with explicit LOD.
QuerySizeLODF
:: ( KnownSymbol imgName, PrimTy res )
=> Proxy imgName
-> Proxy res
-> ImgQueryF ast ( Val Word32 :--> Eff i i res )
-- | Query the LOD of an image at given coordinates.
QueryLODF
:: ( KnownSymbol imgName, PrimTy res )
=> Proxy imgName
-> Proxy res
-> ImgQueryF ast ( Val coords :--> Eff i i res )
-- | Query the number of levels of detail supported by an image.
QueryLevelsF
:: ( KnownSymbol imgName, PrimTy res )
=> Proxy imgName
-> Proxy res
-> ImgQueryF ast ( Eff i i res )
-- | Query the number of samples of a multi-sampled image.
QuerySamplesF
:: ( KnownSymbol imgName, PrimTy res )
=> Proxy imgName
-> Proxy res
-> ImgQueryF ast ( Eff i i res )
------------------------------------------------------------
-- displaying
instance Display ast => Display (ImgOpsF ast) where
toTreeArgs as NilOpsF = pure $ Node "NilOps" as
toTreeArgs as (ProjF ops) = do
a <- toTreeArgs [] ops
pure $ Node "Proj" (a:as)
toTreeArgs as (DrefF ref ops) = do
r <- toTreeArgs [] ref
a <- toTreeArgs [] ops
pure $ Node "Dref" (r:a:as)
toTreeArgs as (BiasF bias ops) = do
b <- toTreeArgs [] bias
a <- toTreeArgs [] ops
pure $ Node "Bias=" (b:a:as)
toTreeArgs as (LODF lod ops) = do
l <- toTreeArgs [] lod
a <- toTreeArgs [] ops
pure $ Node "LOD" (l:a:as)
toTreeArgs as (MinLODF lod ops) = do
l <- toTreeArgs [] lod
a <- toTreeArgs [] ops
pure $ Node "MinLOD" (l:a:as)
toTreeArgs as (GradF (dfdx, dfdy) ops) = do
x <- toTreeArgs [] dfdx
y <- toTreeArgs [] dfdy
a <- toTreeArgs [] ops
pure $ Node "Grad" (x:y:a:as)
toTreeArgs as (ConstOffsetByF vec ops) = do
a <- toTreeArgs [] ops
pure $ Node "ConstOffsetBy" (pure (show vec):a:as)
toTreeArgs as (OffsetByF vec ops) = do
v <- toTreeArgs [] vec
a <- toTreeArgs [] ops
pure $ Node "OffsetBy" (v:a:as)
toTreeArgs as (GatherF (ComponentWithOffsets comp offs) ops) = do
c <- toTreeArgs [] comp
a <- toTreeArgs [] ops
pure $ Node "GatherComponentWithOffsets" (c:pure (show offs):a:as)
toTreeArgs as (GatherF (DepthWithOffsets offs) ops) = do
a <- toTreeArgs [] ops
pure $ Node "GatherDepthWithOffsets" (pure (show offs):a:as)
toTreeArgs as (SampleNoF no ops) = do
n <- toTreeArgs [] no
a <- toTreeArgs [] ops
pure $ Node "SampleNo" (n:a:as)
instance Display ast => Display (ImgQueryF ast) where
toTreeArgs = named \case
QuerySizeF imgName _ -> "ImageQuerySize @" ++ symbolVal imgName
QuerySizeLODF imgName _ -> "ImageQuerySizeLod @" ++ symbolVal imgName
QueryLODF imgName _ -> "ImageQueryLod @" ++ symbolVal imgName
QueryLevelsF imgName _ -> "ImageQueryLevels @" ++ symbolVal imgName
QuerySamplesF imgName _ -> "ImageQuerySamples @" ++ symbolVal imgName