cuda-0.2: examples/src/simpleTexture/SimpleTexture.hs
{-# LANGUAGE ParallelListComp #-}
--------------------------------------------------------------------------------
--
-- Module : SimpleTexture
-- Copyright : (c) 2009 Trevor L. McDonell
-- License : BSD
--
-- Demonstrates texture references. Takes an input PGM file and generates an
-- output that has been rotated. The kernel performs a simple 2D transformation
-- on the texture coordinates (u,v).
--
--------------------------------------------------------------------------------
module Main where
import Data.Array.Unboxed
import Graphics.Pgm
import qualified Foreign.CUDA as CUDA
import qualified Foreign.CUDA.Runtime.Texture as CUDA
imageFile, outputFile, referenceFile :: FilePath
imageFile = "data/lena_bw.pgm"
outputFile = "data/lena_bw_out.pgm"
referenceFile = "data/ref_rotated.pgm"
rotation :: Float
rotation = 0.5 -- radians
main :: IO ()
main = do
img <- either (error . show) head `fmap` pgmsFromFile imageFile
ref <- either (error . show) head `fmap` pgmsFromFile referenceFile
runTest img ref
runTest :: UArray (Int,Int) Int -> UArray (Int,Int) Int -> IO ()
runTest img ref' = do
rotated <- transform (amap (\x-> fromIntegral x/255) img)
arrayToFile outputFile (amap (\x -> round (x*255)) rotated)
if verify (elems ref) (elems rotated)
then putStrLn "PASSED"
else putStrLn "FAILED!"
where
ref = amap (\x -> fromIntegral x / 255) ref'
verify xs ys = all (< epsilon) [abs ((x-y)/(x+y+epsilon)) | x <- xs | y <- ys]
epsilon = 0.05
transform :: UArray (Int,Int) Float -> IO (UArray (Int,Int) Float)
transform pgm =
let bnds@((x0,y0),(x1,y1)) = bounds pgm
width = x1-x0+1
height = y1-y0+1
desc = CUDA.FormatDesc (32,0,0,0) CUDA.Float
texture = CUDA.Texture True CUDA.Linear (CUDA.Wrap,CUDA.Wrap,CUDA.Wrap) desc
in
CUDA.allocaArray (width * height) $ \d_out ->
CUDA.withListArray (elems pgm) $ \d_tex -> do
CUDA.bind2D "tex" texture d_tex (width,height) (fromIntegral $ height * 4)
CUDA.setConfig (width `div` 8,height `div` 8) (8,8,1) 0 Nothing
CUDA.setParams [CUDA.VArg d_out, CUDA.IArg width, CUDA.IArg height, CUDA.FArg rotation]
CUDA.launch "transformKernel"
listArray bnds `fmap` CUDA.peekListArray (width*height) d_out