nano-ui-0.1.0.0: test/integration/Cases/SIMD.hs
module Cases.SIMD (runSimdWritesTest) where
import Control.Monad (forM, forM_)
import Data.IORef (IORef)
import Data.Word (Word32, Word8)
import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.Marshal.Utils (fillBytes)
import Foreign.Ptr (Ptr)
import Foreign.Storable (peekByteOff)
import NanoUI.SIMD
import NanoUI.Testing (Context)
import NanoUI.Testing.Assert (assertEq)
-- Check the renderer's interleaved vertex ABI, triangle winding and byte
-- offsets directly. Guard bytes also catch writes beyond either buffer range.
runSimdWritesTest :: Context -> IORef Int -> IO ()
runSimdWritesTest _ failed = do
let
solid vp ip = pokeQuadSIMD vp 16 ip 16 2 3 5 7 0 0.25 0.5 1 1 0 0.5 1 7
gradient vp ip =
pokeQuadGradientSIMD
vp
16
ip
16
2
3
5
7
0.25
0.5
(1, 0, 0, 1)
(0, 1, 0, 1)
(0, 0, 1, 1)
(1, 1, 1, 0.5)
7
solidVertices =
[ [2, 3, 1, 0, 0.5, 1, 0, 0.25]
, [7, 3, 1, 0, 0.5, 1, 0.5, 0.25]
, [7, 10, 1, 0, 0.5, 1, 0.5, 1]
, [2, 10, 1, 0, 0.5, 1, 0, 1]
]
gradientVertices =
[ [2, 3, 1, 0, 0, 1, 0.25, 0.5]
, [7, 3, 0, 1, 0, 1, 0.25, 0.5]
, [7, 10, 0, 0, 1, 1, 0.25, 0.5]
, [2, 10, 1, 1, 1, 0.5, 0.25, 0.5]
]
checkQuad :: (Ptr Word8 -> Ptr Word8 -> IO ()) -> [[Float]] -> IO ()
checkQuad write expected =
allocaBytes 160 $ \vp -> allocaBytes 56 $ \ip -> do
fillBytes vp 0xa5 160
fillBytes ip 0xa5 56
write vp ip
actual <- forM [0 .. 31 :: Int] $ \i -> peekByteOff vp (16 + i * 4)
indices <- forM [0 .. 5 :: Int] $ \i -> peekByteOff ip (16 + i * 4)
assertEq failed (concat expected) actual
assertEq failed ([7, 8, 9, 7, 9, 10] :: [Word32]) indices
forM_ [(vp, 144), (ip, 40)] $ \(ptr, end) -> do
guardBytes <- mapM (peekByteOff ptr) ([0 .. 15] ++ [end .. end + 15])
assertEq failed (replicate 32 0xa5 :: [Word8]) guardBytes
checkQuad solid solidVertices
checkQuad gradient gradientVertices
let
expectedOffsets = ((1, 2), (4, 6), (7, 10), (10, 14))
assertEq failed expectedOffsets (concentricOffsetsSIMD 1 2 3 4 0 1 2 3)