fir-0.1.0.0: src/FIR/AST/Exts.hs
{-# OPTIONS_GHC -fno-warn-missing-pattern-synonym-signatures -Wno-missing-signatures #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-|
Module: FIR.AST.Exts
Additional operations, such as ray tracing operations and Debug Printf.
-}
module FIR.AST.Exts where
-- base
import Data.Kind
( Type )
import Data.Proxy
( Proxy )
import Data.Word
( Word32 )
-- containers
import Data.Tree
( Tree(Node) )
-- text-short
import Data.Text.Short
( ShortText )
import qualified Data.Text.Short as ShortText
( unpack )
-- variant
import Data.Variant.EGADT
( pattern VF )
-- fir
import Data.Constraint.All
( All )
import FIR.AST.Display
( Display(toTreeArgs), named )
import FIR.AST.Type
( AugType(..), Eff
, Nullary, FunArgs, FunRes
)
import FIR.Prim.RayTracing
( AccelerationStructure
, RayQuery(..), IntersectionType(..)
)
import FIR.Prim.Types
( PrimTy )
import FIR.ProgramState
( ProgramState )
import Math.Linear
( V )
import qualified SPIRV.Operation as SPIRV
( Operation, showOperation )
------------------------------------------------------------
pattern DebugPrintf formatString = VF ( DebugPrintfF formatString )
pattern
TraceRay
{ traceRayAccelerationStructure
, traceRayRayFlags
, traceRayCullMask
, traceRaySBTOffset
, traceRaySBTStride
, traceRayMissIndex
, traceRayRayOrigin
, traceRayRayTMin
, traceRayRayDirection
, traceRayRayTMax
, traceRayPayloadID
} = VF
( TraceRayF
traceRayAccelerationStructure
traceRayRayFlags
traceRayCullMask
traceRaySBTOffset
traceRaySBTStride
traceRayMissIndex
traceRayRayOrigin
traceRayRayTMin
traceRayRayDirection
traceRayRayTMax
traceRayPayloadID
)
pattern ExecuteCallable sbtIndex dataID = VF ( ExecuteCallableF sbtIndex dataID )
pattern
RayQueryInitialize
{ rayQueryRayQueryName
, rayQueryAccelerationStructure
, rayQueryRayFlags
, rayQueryCullMask
, rayQueryRayOrigin
, rayQueryRayTMin
, rayQueryRayDirection
, rayQueryRayTMax
} = VF
( RayQueryInitializeF
rayQueryRayQueryName
rayQueryAccelerationStructure
rayQueryRayFlags
rayQueryCullMask
rayQueryRayOrigin
rayQueryRayTMin
rayQueryRayDirection
rayQueryRayTMax
)
pattern RayQueryPrimOp px rayQueryOp rayQueryName mbIntersectionType =
VF ( RayQueryPrimOpF px rayQueryOp rayQueryName mbIntersectionType )
-- | Printf debugging statement (SPIR-V non-semantic extension).
data DebugPrintfF ( ast :: AugType -> Type ) ( t :: AugType ) where
DebugPrintfF
:: All Nullary ( FunArgs ( PrintfAugType i as ) )
=> ShortText -- ^ PrintF format string
-> DebugPrintfF ast ( PrintfAugType i as )
type family PrintfAugType ( i :: ProgramState ) ( as :: [ Type ] ) = ( r :: AugType ) | r -> as i where
PrintfAugType i '[] = Eff i i ()
PrintfAugType i ( a ': as ) = Val a :--> PrintfAugType i as
data RayF ( ast :: AugType -> Type ) ( t :: AugType ) where
-- | Trace a ray into the given acceleration structure.
TraceRayF ::
{ traceRayFAccelerationStructure :: ast ( Val AccelerationStructure )
, traceRayFRayFlags :: ast ( Val Word32 )
, traceRayFCullMask :: ast ( Val Word32 )
, traceRayFSBTOffset :: ast ( Val Word32 )
, traceRayFSBTStride :: ast ( Val Word32 )
, traceRayFMissIndex :: ast ( Val Word32 )
, traceRayFRayOrigin :: ast ( Val ( V 3 Float ) )
, traceRayFRayTMin :: ast ( Val Float )
, traceRayFRayDirection :: ast ( Val ( V 3 Float ) )
, traceRayFRayTMax :: ast ( Val Float )
, traceRayFRayPayloadName :: ShortText
} -> RayF ast ( Eff i i () )
-- | Invoke a callable shader.
ExecuteCallableF ::
{ executeCallableFSBTIndex :: ast ( Val Word32 )
, executeCallableFDataName :: ShortText
} -> RayF ast ( Eff i i () )
-- | Initialise a ray query.
RayQueryInitializeF ::
{ rayQueryFRayQueryName :: RayQuery
, rayQueryFAccelerationStructure :: ast ( Val AccelerationStructure )
, rayQueryFRayFlags :: ast ( Val Word32 )
, rayQueryFCullMask :: ast ( Val Word32 )
, rayQueryFRayOrigin :: ast ( Val ( V 3 Float ) )
, rayQueryFRayTMin :: ast ( Val Float )
, rayQueryFRayDirection :: ast ( Val ( V 3 Float ) )
, rayQueryFRayTMax :: ast ( Val Float )
} -> RayF ast ( Eff i j () )
-- | Ray query operations.
RayQueryPrimOpF
:: ( All Nullary ( FunArgs opTy )
, FunRes opTy ~ Eff i i a
, PrimTy a
)
=> Proxy a
-> SPIRV.Operation
-> RayQuery
-> Maybe IntersectionType
-> RayF ast opTy
------------------------------------------------------------
-- displaying
instance Display ast => Display (DebugPrintfF ast) where
toTreeArgs = named \(DebugPrintfF formatString) ->
"DebugPrintf \"" <> ShortText.unpack formatString <> "\""
instance Display ast => Display (RayF ast) where
toTreeArgs as (TraceRayF {..}) = do
accelerationStructure <- toTreeArgs [] traceRayFAccelerationStructure
rayFlags <- toTreeArgs [] traceRayFRayFlags
cullMask <- toTreeArgs [] traceRayFCullMask
sbtOffset <- toTreeArgs [] traceRayFSBTOffset
sbtStride <- toTreeArgs [] traceRayFSBTStride
missIndex <- toTreeArgs [] traceRayFMissIndex
rayOrigin <- toTreeArgs [] traceRayFRayOrigin
rayTMin <- toTreeArgs [] traceRayFRayTMin
rayDirection <- toTreeArgs [] traceRayFRayDirection
rayTMax <- toTreeArgs [] traceRayFRayTMax
let
rayPayloadName = ShortText.unpack traceRayFRayPayloadName
pure $
Node "TraceRay"
( accelerationStructure
: rayFlags
: cullMask
: sbtOffset
: sbtStride
: missIndex
: rayOrigin
: rayTMin
: rayDirection
: rayTMax
: Node rayPayloadName []
: as
)
toTreeArgs as (ExecuteCallableF {..}) = do
sbtIndex <- toTreeArgs [] executeCallableFSBTIndex
let
callableDataName = ShortText.unpack executeCallableFDataName
pure $
Node "ExecuteCallable"
( sbtIndex
: Node callableDataName []
: as
)
toTreeArgs as (RayQueryInitializeF {..}) = do
let
RayQuery rayQueryName = rayQueryFRayQueryName
accelerationStructure <- toTreeArgs [] rayQueryFAccelerationStructure
rayFlags <- toTreeArgs [] rayQueryFRayFlags
cullMask <- toTreeArgs [] rayQueryFCullMask
rayOrigin <- toTreeArgs [] rayQueryFRayOrigin
rayTMin <- toTreeArgs [] rayQueryFRayTMin
rayDirection <- toTreeArgs [] rayQueryFRayDirection
rayTMax <- toTreeArgs [] rayQueryFRayTMax
pure $
Node "RayQueryInitialize"
( Node ( ShortText.unpack rayQueryName ) []
: accelerationStructure
: rayFlags
: cullMask
: rayOrigin
: rayTMin
: rayDirection
: rayTMax
: as
)
toTreeArgs as (RayQueryPrimOpF _ rayQueryOp (RayQuery rayQueryName) mbInterType) =
pure $
Node ( SPIRV.showOperation rayQueryOp )
( Node ( ShortText.unpack rayQueryName ) []
: ( case mbInterType of
Nothing -> id
Just Candidate -> ( Node "Candidate" [] : )
Just Committed -> ( Node "Committed" [] : )
) as
)