GPipe-Core-0.2.3.1: test/Graphics/GPipe/ExprSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Graphics.GPipe.ExprSpec where
import Test.Hspec (Spec, describe, it, shouldBe)
import Graphics.GPipe (V4 (..), identity, ifB, norm,
(==*))
import Graphics.GPipe.Internal.Expr
import Graphics.GPipe.Linear ((!*))
wrap :: FFloat -> IO ExprResult
wrap expr = runExprM (tellGlobal "") $ unS expr >>= tellAssignment' "result"
golden :: String -> IO ()
golden = mapM_ (\l -> putStrLn $ " , " ++ show l) . lines
spec :: Spec
spec = do
describe "(+)" $ do
it "should be able to add two numbers" $ do
let a = 1
b = 2
c = a + b
res <- wrap c
finalSource res `shouldBe` unlines
[ "#version 450"
, "void main() {"
, "float t0 = (1+2);"
, "result = t0;"
, "}"
]
it "should be able to add many numbers" $ do
let (a, b, c, d) = (1, 2, 3, 4)
result = a + b + c + d
res <- wrap result
finalSource res `shouldBe` unlines
[ "#version 450"
, "void main() {"
, "float t0 = (1+2);"
, "float t1 = (t0+3);"
, "float t2 = (t1+4);"
, "result = t2;"
, "}"
]
it "should reuse already computed values" $ do
let (a, b, c, d) = (1, 2, 3, 4)
e = a + b + c + d
result = e + e
res <- wrap result
finalSource res `shouldBe` unlines
[ "#version 450"
, "void main() {"
, "float t0 = (1+2);"
, "float t1 = (t0+3);"
, "float t2 = (t1+4);"
, "float t3 = (t2+t2);"
, "result = t3;"
, "}"
]
describe "ifB" $ do
it "should produce 4 separate 'if's for V4 branch values" $ do
let a = V4 1 2 3 4
b = V4 5 6 7 8
c = a ==* b
result = norm (ifB c a b)
res <- wrap result
finalSource res `shouldBe` unlines
[ "#version 450"
, "void main() {"
, "bool t0 = (1==5);"
, "bool t1 = (2==6);"
, "bool t2 = (3==7);"
, "bool t3 = (4==8);"
, "bool t4 = (t2&&t3);"
, "bool t5 = (t1&&t4);"
, "bool t6 = (t0&&t5);"
, "float t7;"
, "if(t6){"
, "t7 = 1;"
, "} else {"
, "t7 = 5;"
, "}"
, "float t8;"
, "if(t6){"
, "t8 = 2;"
, "} else {"
, "t8 = 6;"
, "}"
, "float t9;"
, "if(t6){"
, "t9 = 3;"
, "} else {"
, "t9 = 7;"
, "}"
, "float t10;"
, "if(t6){"
, "t10 = 4;"
, "} else {"
, "t10 = 8;"
, "}"
, "float t11 = length(vec4(t7,t8,t9,t10));"
, "result = t11;"
, "}"
]
describe "ifThenElse'" $ do
it "should produce only 2 'if's for V4 branch values" $ do
let a = V4 1 2 3 4
b = V4 5 6 7 8
c = a ==* b
result = norm $ ifThenElse' c a b
res <- wrap result
finalSource res `shouldBe` unlines
[ "#version 450"
, "void main() {"
, "bool t0 = (1==5);"
, "bool t1 = (2==6);"
, "bool t2 = (3==7);"
, "bool t3 = (4==8);"
, "bool t4 = (t2&&t3);"
, "bool t5 = (t1&&t4);"
, "bool t6 = (t0&&t5);"
, "float t7;"
, "float t8;"
, "float t9;"
, "float t10;"
, "if(t6){"
, "t7 = 1;"
, "t8 = 2;"
, "t9 = 3;"
, "t10 = 4;"
, "} else {"
, "t7 = 5;"
, "t8 = 6;"
, "t9 = 7;"
, "t10 = 8;"
, "}"
, "float t11 = length(vec4(t7,t8,t9,t10));"
, "result = t11;"
, "}"
]
describe "!*" $ do
it "should compile to GLSL multiplication operator '*'" $ do
let m = identity
v = V4 5 6 7 8
result = norm $ m !* v
res <- wrap result
golden $ finalSource res
finalSource res `shouldBe` unlines
[ "#version 450"
, "void main() {"
, "vec4 t0 = (vec4(5,6,7,8)*mat4x4(vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(0,0,0,1)));"
, "float t1 = length(vec4(t0[0],t0[1],t0[2],t0[3]));"
, "result = t1;"
, "}"
]