packages feed

glsl-0.0.1.0: src/Language/GLSL/Optimizer/Liveness.hs

{-# LANGUAGE OverloadedStrings #-}
module Language.GLSL.Optimizer.Liveness where

import qualified Data.IntSet            as S
import qualified Data.Text.Lazy.Builder as LTB
import           Language.GLSL.AST


newtype Liveness = Liveness { unLiveness :: S.IntSet }

empty :: Liveness
empty = Liveness S.empty

instance Annot Liveness where
  parseAnnot = pure empty
  ppAnnot = Just . LTB.fromString . show . S.toList . unLiveness


computeLiveness :: GLSL a -> GLSL Liveness
computeLiveness (GLSL v d) = GLSL v (map clTopDecl d)

clTopDecl :: TopDecl a -> TopDecl Liveness
clTopDecl (LayoutDecl s d) = LayoutDecl s d
clTopDecl (GlobalDecl d) = GlobalDecl d
clTopDecl (ProcDecl name params ss) =
  ProcDecl name params . fst . clStmtAnnots empty $ ss

clStmtAnnots :: Liveness -> [StmtAnnot a] -> ([StmtAnnot Liveness], Liveness)
clStmtAnnots ls = foldr clStmtAnnot ([], ls)

clStmtAnnot
  :: StmtAnnot a
  -> ([StmtAnnot Liveness], Liveness)
  -> ([StmtAnnot Liveness], Liveness)
clStmtAnnot (SA _ s) (ss, ls) =
  let (s', ls') = clStmt s ls in
  (SA ls' s':ss, ls')

clStmt :: Stmt a -> Liveness -> (Stmt Liveness, Liveness)
clStmt (AssignStmt n e) ls =
  (AssignStmt n e, clExpr e ls)
clStmt (DeclStmt d@(LDecl _ (NameId n) e)) ls =
  (DeclStmt d, delete n . maybe id clExpr e $ ls)
clStmt (EmitStmt e) ls =
  (EmitStmt e, clEmit e ls)
clStmt (IfStmt (NameId c) t e) ls =
  let (t', lsT) = clStmtAnnots ls t
      (e', lsE) = clStmtAnnots ls e
  in
  (IfStmt (NameId c) t' e', insert c $ lsT `union` lsE)


clEmit :: Emit -> Liveness -> Liveness
clEmit EmitFragDepth    = id
clEmit (EmitPosition e) = clExpr e

clExpr :: Expr -> Liveness -> Liveness
clExpr (UnaryExpr _ e) ls      = clExprAtom e ls
clExpr (BinaryExpr l _ r) ls   = clExprAtom l . clExprAtom r $ ls
clExpr (FunCallExpr _ args) ls = foldr clExprAtom ls args
clExpr (TextureExpr t x y) ls  = foldr clExprAtom ls [t, x, y]
clExpr (AtomExpr e) ls         = clExprAtom e ls

clExprAtom :: ExprAtom -> Liveness -> Liveness
clExprAtom (IdentifierExpr n) ls         = clNameExpr n ls
clExprAtom (SwizzleExpr (NameId n) _) ls = insert n ls
clExprAtom _ ls                          = ls

clNameExpr :: NameExpr -> Liveness -> Liveness
clNameExpr (NameExpr (Name NsT (NameId n))) ls = insert n ls
clNameExpr _ ls                                = ls

insert :: Int -> Liveness -> Liveness
insert n = Liveness . S.insert n . unLiveness

delete :: Int -> Liveness -> Liveness
delete n = Liveness . S.delete n . unLiveness

union :: Liveness -> Liveness -> Liveness
union a b = Liveness $ S.union (unLiveness a) (unLiveness b)