module LambdaCube.Language.HOAS where import GHC.TypeLits import Data.ByteString.Char8 import Data.Int import LambdaCube.Core.Type hiding (FetchPrimitive, OutputPrimitive, Blending, RasterContext, Blend, TriangleCtx, Image, FragmentOperation, MipMap, TextureDataType, TextureType) import LambdaCube.Language.Type import LambdaCube.Language.ReifyType import LambdaCube.Language.PrimFun import Data.Typeable import Data.Dynamic import qualified LambdaCube.Core.DeBruijn as U (N) -- Common Exp, describes shader functions data Exp :: Frequency -> * -> * where Tag :: GPU t => Int -> String -> Exp stage t -- Needed for Let conversion Shr :: U.N -> Exp stage t Let :: (GPU a, GPU b) => Exp stage a -> (Exp stage a -> Exp stage b) -> Exp stage b -- Needed for conversion to de Bruijn form Var :: GPU t => Dynamic -> Exp stage t -- environment size at defining occurrence {- -- function support Lam :: (GPU a, GPU b) => (Exp stage a -> Exp stage b) -> Exp stage (a -> b) App :: (GPU a, GPU b) => Exp stage a -> Exp stage (a -> b) -> Exp stage b -} -- constant value Const :: (GPU t,IsScalar t) => t -> Exp stage t -- builtin variable PrimVar :: GPU t => Input t -> Exp stage t -- uniform value Uni :: GPU t => Input t -> Exp stage t -- conditional expression Cond :: GPU t => Exp stage Bool -> Exp stage t -> Exp stage t -> Exp stage t PrimApp :: (GPU a, GPU r) => PrimFun stage (a -> r) -> Exp stage a -> Exp stage r -- tuple support Tup :: (GPU t, IsTuple t) => Tuple (Exp stage) (TupleRepr t) -> Exp stage t Prj :: (GPU e, GPU t, IsTuple t) => TupleIdx (TupleRepr t) e -> Exp stage t -> Exp stage e -- sampler support Sampler :: GPU (Sampler dim arr t ar) => Filter -> EdgeMode -> Exp Obj (Texture dim arr t ar) -> Exp stage (Sampler dim arr t ar) TextureSlot :: (IsValidTextureSlot t) => ByteString -- texture slot name -> TextureType dim mip arr layerCount t ar -> Exp Obj (Texture dim arr t ar) -- TODO: -- add texture internal format specification Texture :: (IsScalar (TexSizeRepr dim), IsMipValid canMip mip {- ,Typeable (TexDataRepr ar t), Typeable (TextureType dim canMip arr layerCount t ar), Typeable (Image layerCount (TexDataRepr ar t))-}) => TextureType dim canMip arr layerCount t ar -> TexSizeRepr dim -> MipMap mip -- -> TexRepr dim mip gp layerCount (TexDataRepr ar t) -- FIXME: for cube it will give wrong type -> [Exp Obj (Image layerCount (TexDataRepr ar t))] -> Exp Obj (Texture dim arr t ar) -- loop support Loop :: (GPU s, GPU a{-, Typeable stage-}) => (Exp stage s -> Exp stage s) -- state transform function -> (Exp stage s -> Exp stage Bool) -- loop condition function -> (Exp stage s -> Exp stage a) -- state to result transform function -> Exp stage s -- initial state -> Exp stage a -- result -- GP -- hint: GP stands for Graphics Pipeline Fetch :: (InputTuple a, SGPU (InputTupleRepr a)) => ByteString -> FetchPrimitive primitive -> a -> Exp Obj (VertexStream primitive (InputTupleRepr a)) Transform :: (GPU a, GPU b{-, Typeable clipDistances-}) => (Exp V a -> VertexOut clipDistances b) -- vertex shader -> Exp Obj (VertexStream primitive a) -> Exp Obj (PrimitiveStream primitive clipDistances 1 V b) Reassemble :: GeometryShader inputPrimitive outputPrimitive inputClipDistances outputClipDistances layerCount a b -> Exp Obj (PrimitiveStream inputPrimitive inputClipDistances 1 V a) -> Exp Obj (PrimitiveStream outputPrimitive outputClipDistances layerCount G b) Rasterize :: RasterContext primitive -> Exp Obj (PrimitiveStream primitive clipDistances layerCount freq a) -> Exp Obj (FragmentStream layerCount a) FrameBuffer :: FrameBuffer layerCount t -> Exp Obj (FrameBuffer layerCount (FTRepr' t)) Accumulate :: ({-Typeable (NoStencilRepr b), -}GPU a, GPU (FTRepr' b), IsValidOutput b) -- restriction: depth and stencil optional, arbitrary color component => AccumulationContext b -> FragmentFilter a -> (Exp F a -> FragmentOut (NoStencilRepr b)) -- fragment shader -> Exp Obj (FragmentStream layerCount a) -> Exp Obj (FrameBuffer layerCount (FTRepr' b)) -> Exp Obj (FrameBuffer layerCount (FTRepr' b)) PrjFrameBuffer :: ByteString -- internal image output (can be allocated on request) -> TupleIdx (EltRepr b) t -> Exp Obj (FrameBuffer layerCount b) -> Exp Obj (Image layerCount t) PrjImage :: ((idx + 1) <= layerCount, 2 <= layerCount, KnownNat idx) => ByteString -- internal image output (can be allocated on request) -> NatNum idx -> Exp Obj (Image layerCount t) -> Exp Obj (Image 1 t) {- -- dynamic extension support AccumulateSet :: GPU a => ByteString -> Exp Obj (FrameBuffer layerCount a) -> Exp Obj (FrameBuffer layerCount a) -} type InterpolatedFlatExp stage a = FlatTuple GPU (Interpolated (Exp stage)) a type FlatExp stage a = FlatTuple GPU (Exp stage) a -- Vertex {- Vertex shader builtin output: gl_PerVertex { vec4 gl_Position float gl_PointSize float gl_ClipDistance[] } -} -- result of a vertex or geometry shader function data VertexOut clipDistances t where VertexOut :: IsFloatTuple clipDistances => Exp V V4F -- position -> Exp V Float -- point size -> FlatExp V clipDistances -- clip distance [] -> InterpolatedFlatExp V a -> VertexOut (FTRepr clipDistances) (FTRepr a) -- Geometry -- describes a geometry shader data GeometryShader (inPrimitive :: PrimitiveType) (outPrimitive :: PrimitiveType) inClipDistances outClipDistances (layerCount :: Nat) a b where GeometryShader :: (GPU j, GPU i, GPU b, GPU outputClipDistances, GPU input, KnownNat layerCount , inputVertex ~ (V4F,Float,inputClipDistances,a) , input ~ PrimitiveVertices inputPrimitive inputVertex ) => NatNum layerCount -- geometry shader: -> OutputPrimitive outputPrimitive -- output primitive -> Int -- max amount of generated vertices -> (Exp G input -> Exp G (i,Int32)) -- how many primitives? -> (Exp G i -> Exp G (Int32,Int32,i,j,Int32)) -- how many vertices? primtive loop, out: -- gl_PrimitiveID; gl_Layer; loop var; vertex loop seed; vertex loop iteration count) -> (Exp G j -> GeometryOut j outputClipDistances b) -- generate vertices -> GeometryShader inputPrimitive outputPrimitive inputClipDistances outputClipDistances layerCount a b {- GeometryShader :: (GPU (PrimitiveVertices primIn a), GPU i, GPU j, GPU b, IsPrimitive primIn, IsPrimitive primOut, KnownNat layerNum) => NatNum layerNum -- geometry shader: -> primOut -- output primitive -> Int -- max amount of generated vertices -> (Exp G (PrimitiveVertices primIn a) -> Exp G (i,Int32)) -- how many primitives? -> (Exp G i -> Exp G (i,j,Int32)) -- how many vertices? -> (Exp G j -> GeometryOut (j,b)) -- generate vertices -> GeometryShader primIn primOut layerNum a b -} {- Geometry shader builtin output: gl_PerVertex { vec4 gl_Position float gl_PointSize float gl_ClipDistance[] } int gl_PrimitiveID int gl_Layer -} -- result of a geometry shader function data GeometryOut i clipDistances t where GeometryOut :: IsFloatTuple clipDistances => Exp G i -> Exp G V4F -- position -> Exp G Float -- point size -> FlatExp G clipDistances -- clip distance [] -> InterpolatedFlatExp G a -> GeometryOut i (FTRepr clipDistances) (FTRepr a) -- Fragment {- Fragment shader builtin output: float gl_FragDepth -- Optional -} -- result of a fragment shader function data FragmentOut t where FragmentOut :: FlatExp F a -> FragmentOut (ColorRepr a) FragmentOutDepth :: Exp F Float -> FlatExp F a -> FragmentOut (Depth Float :+: ColorRepr a) FragmentOutRastDepth :: FlatExp F a -> FragmentOut (Depth Float :+: ColorRepr a) -- fragment filter function, we express discard using a filter function data FragmentFilter a where PassAll :: FragmentFilter a Filter :: (Exp F a -> Exp F Bool) -> FragmentFilter a data GPOutput (o :: OutputType) where SamplerOut :: GPU (Sampler dim arr t ar) => ByteString -> Exp Obj (Sampler dim arr t ar) -> GPOutput SingleOutput ScreenOut :: Exp Obj (Image 1 t) -> GPOutput SingleOutput MultiOut :: [GPOutput SingleOutput] -> GPOutput MultiOutput data AccumulationContext t = AccumulationContext { accViewportSize :: Maybe (Exp Obj V4U) , accOperations :: FlatTuple NoConstraint FragmentOperation t }