packages feed

spirv-reflect-ffi-0.3: lib/Data/SpirV/Reflect/FFI.hs

{-# LANGUAGE Strict #-}

module Data.SpirV.Reflect.FFI
  ( Module
  , load
  , loadBytes
  ) where

import Control.Exception (onException)
import Control.Monad.IO.Class (MonadIO(..))
import Data.ByteString (ByteString)
import Data.ByteString qualified as ByteString
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.SpirV.Reflect.FFI.Internal qualified as C
import Foreign (callocBytes, castPtr, free)
import System.Mem.Weak (addFinalizer)

import Data.SpirV.Reflect.Module (Module)

load :: MonadIO io => FilePath -> io Module
load path = liftIO $
  ByteString.readFile path >>= loadBytes

loadBytes :: MonadIO io => ByteString -> io Module
loadBytes bytes = liftIO do
  unsafeUseAsCStringLen bytes \(code, size) -> do
    smPtr <- callocBytes C.shaderModuleSize
    flip onException (free smPtr) do
      res <- C.createShaderModule2
        C.SpvReflectModuleFlagNoCopy
        (fromIntegral size)
        (castPtr code)
        smPtr
      case res of
        C.SpvReflectResultSuccess -> do
          m <- C.inflateModule smPtr `onException` C.destroyShaderModule smPtr
          addFinalizer m $ C.destroyShaderModule smPtr
          pure m
        err ->
          error $ "spvReflectCreateShaderModule2:" <> show err