   -- * Kernel Execution
   Fun(Fun), FunParam(..), FunAttribute(..), CacheConfig(..),
   requires, setBlockShape, setSharedSize, setParams, setCacheConfigFun,
-  launch, launchKernel
+  launch, launchKernel, launchKernel'
 
 ) where
 

  TArg :: Texture         -> FunParam
  VArg :: Storable a => a -> FunParam


--------------------------------------------------------------------------------
-- Execution Control

      TArg _ -> error "launchKernel: TArg is deprecated"


launchKernel' fn (gx,gy,gz) (tx,ty,tz) sm mst args
  = (=<<) nothingIfOk
  $ with bytes
  $ \pb -> withArray' args
  $ \pa -> withArray0 nullPtr [buffer, castPtr pa, size, castPtr pb]
  $ \pp -> cuLaunchKernel fn gx gy gz tx ty tz sm st nullPtr pp
  where
    buffer      = wordPtrToPtr 0x01     -- CU_LAUNCH_PARAM_BUFFER_POINTER
    size        = wordPtrToPtr 0x02     -- CU_LAUNCH_PARAM_BUFFER_SIZE
    bytes       = foldl (\a x -> a + sizeOf x) 0 args
    st          = fromMaybe (Stream nullPtr) mst

    -- can't use the standard 'withArray' because 'mallocArray' will pass
    -- 'undefined' to 'sizeOf' when determining how many bytes to allocate, but
    -- our Storable instance for FunParam needs to dispatch on each constructor,
    -- hence evaluating the undefined.
    --
    withArray' vals f =
      allocaBytes bytes $ \ptr -> do
        pokeArray ptr vals
        f ptr


{# fun unsafe cuLaunchKernel
  { useFun    `Fun'
  ,           `Int', `Int', `Int'
