keid-core-0.1.8.0: src/Engine/SpirV/Compile.hs
module Engine.SpirV.Compile
( glsl
, glslStages
, glslPipelines
) where
import RIO
import RIO.ByteString qualified as ByteString
import RIO.Directory (createDirectoryIfMissing, doesFileExist)
import RIO.FilePath ((<.>), (</>))
import RIO.Map qualified as Map
import RIO.Process (HasProcessContext, proc, readProcess_)
import RIO.Text qualified as Text
import Render.Code (Code(..), targetEnv)
import Engine.Vulkan.Pipeline.Stages qualified as Stages
glsl
:: ( HasLogFunc env
, HasProcessContext env
)
=> Maybe FilePath
-> Text
-> Text
-> Code
-> RIO env ()
glsl outdir basename stage (Code source) = do
withDir \dir -> do
let
shaderFile = dir </> Text.unpack basename <.> Text.unpack stage
outFile = shaderFile <.> "spv"
outBytes = encodeUtf8 source
exists <- doesFileExist shaderFile
same <-
if exists then do
oldBytes <- ByteString.readFile shaderFile
pure $ oldBytes == outBytes
else
pure False
unless same do
ByteString.writeFile shaderFile outBytes
(_out, _err) <- proc
"glslangValidator"
[ "--target-env", targetEnv
, "-S", Text.unpack stage
, "-V", shaderFile
, "-o", outFile
]
readProcess_
logDebug $ displayShow (_out, _err)
where
withDir action =
case outdir of
Nothing ->
withSystemTempDirectory "keid-shader" action
Just dir -> do
createDirectoryIfMissing True dir
action dir
glslStages
:: ( Stages.StageInfo stages
, HasLogFunc env
, HasProcessContext env
)
=> Maybe FilePath
-> Text
-> stages (Maybe Code)
-> RIO env ()
glslStages outdir basename stages =
for_ (Stages.withLabels stages) \(label, mstage) ->
traverse_ (glsl outdir basename label) mstage
glslPipelines
:: ( Stages.StageInfo stages
, HasLogFunc env
, HasProcessContext env
)
=> Maybe FilePath
-> Map Text (stages (Maybe Code))
-> RIO env ()
glslPipelines outdir = traverse_ compile . Map.toList
where
compile (label, stages) = glslStages outdir label stages