lambdacube-gl 0.5.2.0 → 0.5.2.2
raw patch · 4 files changed
+211/−115 lines, 4 filesdep ~timePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: time
API changes (from Hackage documentation)
- LambdaCube.GL.Backend: [textureBinding] :: CGState -> IntMap GLTexture
- LambdaCube.GL.Type: GLGenerateMipMap :: !GLenum -> !GLenum -> GLCommand
- LambdaCube.GL.Type: GLLoadImage :: ImageRef -> FrameBufferComponent -> GLCommand
- LambdaCube.GL.Type: GLSaveImage :: FrameBufferComponent -> ImageRef -> GLCommand
- LambdaCube.GL.Type: GLSetAccumulationContext :: !AccumulationContext -> GLCommand
- LambdaCube.GL.Type: GLSetProgram :: !GLuint -> GLCommand
- LambdaCube.GL.Type: GLSetRasterContext :: !RasterContext -> GLCommand
- LambdaCube.GL.Type: GLSetRenderTarget :: !GLuint -> !(Maybe [GLenum]) -> GLCommand
- LambdaCube.GL.Type: GLSetSampler :: !GLuint -> !GLuint -> GLCommand
- LambdaCube.GL.Type: GLSetSamplerUniform :: !GLint -> !GLint -> (IORef GLint) -> GLCommand
- LambdaCube.GL.Type: GLSetTexture :: !GLenum -> !GLuint -> !GLuint -> GLCommand
- LambdaCube.GL.Type: instance GHC.Show.Show LambdaCube.GL.Type.GLCommand
+ LambdaCube.GL.Backend: [accumulationContext] :: CGState -> AccumulationContext
+ LambdaCube.GL.Backend: [drawCommands] :: CGState -> [GLCommand]
+ LambdaCube.GL.Backend: [rasterContext] :: CGState -> RasterContext
+ LambdaCube.GL.Backend: [renderTarget] :: CGState -> GLRenderTarget
+ LambdaCube.GL.Backend: [samplerMapping] :: CGState -> IntMap GLSampler
+ LambdaCube.GL.Backend: [samplerUniformMapping] :: CGState -> IntMap GLSamplerUniform
+ LambdaCube.GL.Backend: [textureMapping] :: CGState -> IntMap GLTexture
+ LambdaCube.GL.Backend: drawContext :: MonadState CGState m => Vector GLProgram -> m GLDrawContext
+ LambdaCube.GL.Backend: emit :: GLCommand -> CG ()
+ LambdaCube.GL.Backend: setupDrawContext :: IORef Bool -> IORef GLDrawContext -> IORef (Maybe InputConnection) -> GLDrawContext -> IO ()
+ LambdaCube.GL.Backend: setupRenderTarget :: IORef (Maybe InputConnection) -> GLRenderTarget -> IO ()
+ LambdaCube.GL.Type: GLDrawContext :: !RasterContext -> !AccumulationContext -> !GLRenderTarget -> !GLuint -> ![(GLTextureUnit, GLTexture)] -> ![(GLTextureUnit, GLSampler)] -> ![(GLTextureUnit, GLSamplerUniform)] -> GLDrawContext
+ LambdaCube.GL.Type: GLSamplerUniform :: !GLUniformBinding -> IORef GLUniformBinding -> GLSamplerUniform
+ LambdaCube.GL.Type: [glAccumulationContext] :: GLDrawContext -> !AccumulationContext
+ LambdaCube.GL.Type: [glDrawCallCounterRef] :: GLRenderer -> IORef Int
+ LambdaCube.GL.Type: [glDrawContextRef] :: GLRenderer -> IORef GLDrawContext
+ LambdaCube.GL.Type: [glForceSetup] :: GLRenderer -> IORef Bool
+ LambdaCube.GL.Type: [glIndexBufferRef] :: GLRenderer -> IORef GLuint
+ LambdaCube.GL.Type: [glProgram] :: GLDrawContext -> !GLuint
+ LambdaCube.GL.Type: [glRasterContext] :: GLDrawContext -> !RasterContext
+ LambdaCube.GL.Type: [glRenderTarget] :: GLDrawContext -> !GLRenderTarget
+ LambdaCube.GL.Type: [glSamplerMapping] :: GLDrawContext -> ![(GLTextureUnit, GLSampler)]
+ LambdaCube.GL.Type: [glSamplerUniformMapping] :: GLDrawContext -> ![(GLTextureUnit, GLSamplerUniform)]
+ LambdaCube.GL.Type: [glTextureMapping] :: GLDrawContext -> ![(GLTextureUnit, GLTexture)]
+ LambdaCube.GL.Type: [glUniformBindingRef] :: GLSamplerUniform -> IORef GLUniformBinding
+ LambdaCube.GL.Type: [glUniformBinding] :: GLSamplerUniform -> !GLUniformBinding
+ LambdaCube.GL.Type: [glVertexBufferRef] :: GLRenderer -> IORef GLuint
+ LambdaCube.GL.Type: data GLDrawContext
+ LambdaCube.GL.Type: data GLSamplerUniform
+ LambdaCube.GL.Type: instance GHC.Classes.Eq LambdaCube.GL.Type.GLRenderTarget
+ LambdaCube.GL.Type: instance GHC.Classes.Eq LambdaCube.GL.Type.GLSampler
+ LambdaCube.GL.Type: instance GHC.Classes.Eq LambdaCube.GL.Type.GLSamplerUniform
+ LambdaCube.GL.Type: instance GHC.Classes.Eq LambdaCube.GL.Type.GLTexture
+ LambdaCube.GL.Type: type GLTextureUnit = Int
+ LambdaCube.GL.Type: type GLUniformBinding = GLint
- LambdaCube.GL.Backend: CGState :: ProgramName -> IntMap GLTexture -> CGState
+ LambdaCube.GL.Backend: CGState :: [GLCommand] -> RasterContext -> AccumulationContext -> GLRenderTarget -> ProgramName -> IntMap GLSamplerUniform -> IntMap GLTexture -> IntMap GLSampler -> CGState
- LambdaCube.GL.Backend: compileCommand :: Map String (IORef GLint) -> Vector GLSampler -> Vector GLTexture -> Vector GLRenderTarget -> Vector GLProgram -> Command -> CG GLCommand
+ LambdaCube.GL.Backend: compileCommand :: Map String (IORef GLint) -> Vector GLSampler -> Vector GLTexture -> Vector GLRenderTarget -> Vector GLProgram -> Command -> CG ()
- LambdaCube.GL.Backend: renderSlot :: [GLObjectCommand] -> IO ()
+ LambdaCube.GL.Backend: renderSlot :: IORef Int -> IORef GLuint -> IORef GLuint -> [GLObjectCommand] -> IO ()
- LambdaCube.GL.Type: GLClearRenderTarget :: [ClearImage] -> GLCommand
+ LambdaCube.GL.Type: GLClearRenderTarget :: !GLRenderTarget -> ![ClearImage] -> GLCommand
- LambdaCube.GL.Type: GLRenderSlot :: !SlotName -> !ProgramName -> GLCommand
+ LambdaCube.GL.Type: GLRenderSlot :: !GLDrawContext -> !SlotName -> !ProgramName -> GLCommand
- LambdaCube.GL.Type: GLRenderStream :: !StreamName -> !ProgramName -> GLCommand
+ LambdaCube.GL.Type: GLRenderStream :: !GLDrawContext -> !StreamName -> !ProgramName -> GLCommand
- LambdaCube.GL.Type: GLRenderer :: Vector GLProgram -> Vector GLTexture -> Vector GLSampler -> Vector GLRenderTarget -> [GLCommand] -> Vector [ProgramName] -> IORef (Maybe InputConnection) -> Vector String -> GLuint -> Map String (IORef GLint) -> Vector GLStream -> GLRenderer
+ LambdaCube.GL.Type: GLRenderer :: Vector GLProgram -> Vector GLTexture -> Vector GLSampler -> Vector GLRenderTarget -> [GLCommand] -> Vector [ProgramName] -> IORef (Maybe InputConnection) -> Vector String -> GLuint -> Map String (IORef GLint) -> Vector GLStream -> IORef GLDrawContext -> IORef Bool -> IORef GLuint -> IORef GLuint -> IORef Int -> GLRenderer
Files
- lambdacube-gl.cabal +2/−2
- src/LambdaCube/GL/Backend.hs +174/−95
- src/LambdaCube/GL/Mesh.hs +1/−1
- src/LambdaCube/GL/Type.hs +34/−17
lambdacube-gl.cabal view
@@ -1,5 +1,5 @@ name: lambdacube-gl-version: 0.5.2.0+version: 0.5.2.2 synopsis: OpenGL 3.3 Core Profile backend for LambdaCube 3D description: OpenGL 3.3 Core Profile backend for LambdaCube 3D homepage: http://lambdacube3d.com@@ -125,7 +125,7 @@ base < 5, containers >=0.5 && <0.6, text >= 1.2 && <1.3,- time >= 1.5 && <1.6,+ time >= 1.5 && <1.7, exceptions >= 0.8 && <0.9, bytestring >=0.10 && <0.11, base64-bytestring >=1 && <1.1,
src/LambdaCube/GL/Backend.hs view
@@ -1,9 +1,9 @@-{-# LANGUAGE TupleSections, MonadComprehensions, RecordWildCards, LambdaCase #-}+{-# LANGUAGE TupleSections, MonadComprehensions, RecordWildCards, LambdaCase, FlexibleContexts #-} module LambdaCube.GL.Backend where import Control.Applicative import Control.Monad-import Control.Monad.State+import Control.Monad.State.Strict import Data.Maybe import Data.Bits import Data.IORef@@ -13,10 +13,10 @@ import Data.Set (Set) import Data.Vector (Vector,(!),(//)) import qualified Data.Foldable as F-import qualified Data.IntMap as IM+import qualified Data.IntMap as IntMap import qualified Data.Map as Map import qualified Data.List as L-import qualified Data.Set as S+import qualified Data.Set as Set import qualified Data.Vector as V import qualified Data.Vector.Storable as SV @@ -279,7 +279,7 @@ , programObject = po , inputUniforms = Map.fromList inUniforms , inputTextures = Map.fromList inTextures- , inputTextureUniforms = S.fromList $ texUnis+ , inputTextureUniforms = Set.fromList $ texUnis , inputStreams = Map.fromList [(n,(idx, attrName)) | (n,idx) <- Map.toList $ attributes, let attrName = fromMaybe (error $ "missing attribute: " ++ n) $ Map.lookup n lcStreamName] } @@ -443,7 +443,7 @@ uniCmds = [GLSetUniform i u | (n,i) <- uniMap, let u = topUni n] uniMap = Map.toList $ inputUniforms prg topUni n = Map.findWithDefault (error "internal error (createStreamCommands)!") n topUnis- texUnis = S.toList $ inputTextureUniforms prg+ texUnis = Set.toList $ inputTextureUniforms prg texCmds = [ GLBindTexture (inputTypeToTextureTarget $ uniInputType u) texUnit u | n <- texUnis , let u = topUni n@@ -496,24 +496,34 @@ prgs <- V.mapM compileProgram $ programs p -- texture unit mapping ioref trie -- texUnitMapRefs :: Map UniformName (IORef TextureUnit)- texUnitMapRefs <- Map.fromList <$> mapM (\k -> (k,) <$> newIORef 0) (S.toList $ S.fromList $ concat $ V.toList $ V.map (Map.keys . programInTextures) $ programs p)- let (cmds,st) = runState (mapM (compileCommand texUnitMapRefs smps texs trgs prgs) $ V.toList $ commands p) initCGState+ texUnitMapRefs <- Map.fromList <$> mapM (\k -> (k,) <$> newIORef 0) (Set.toList $ Set.fromList $ concat $ V.toList $ V.map (Map.keys . programInTextures) $ programs p)+ let st = execState (mapM_ (compileCommand texUnitMapRefs smps texs trgs prgs) (V.toList $ commands p)) initCGState input <- newIORef Nothing -- default Vertex Array Object vao <- alloca $! \pvao -> glGenVertexArrays 1 pvao >> peek pvao strs <- V.mapM compileStreamData $ streams p+ drawContextRef <- newIORef $ error "missing DrawContext"+ forceSetup <- newIORef True+ vertexBufferRef <- newIORef 0+ indexBufferRef <- newIORef 0+ drawCallCounterRef <- newIORef 0 return $ GLRenderer { glPrograms = prgs , glTextures = texs , glSamplers = smps , glTargets = trgs- , glCommands = cmds+ , glCommands = reverse $ drawCommands st , glSlotPrograms = V.map (V.toList . slotPrograms) $ IR.slots p , glInput = input , glSlotNames = V.map slotName $ IR.slots p , glVAO = vao , glTexUnitMapping = texUnitMapRefs , glStreams = strs+ , glDrawContextRef = drawContextRef+ , glForceSetup = forceSetup+ , glVertexBufferRef = vertexBufferRef+ , glIndexBufferRef = indexBufferRef+ , glDrawCallCounterRef = drawCallCounterRef } disposeRenderer :: GLRenderer -> IO ()@@ -594,7 +604,7 @@ modifyIORef (pipelines icInput) $ \v -> v // [(icId,Nothing)] V.forM_ icSlotMapPipelineToInput $ \slotIdx -> do slot <- readIORef (slotRefs ! slotIdx)- forM_ (IM.elems $ objectMap slot) $ \obj -> do+ forM_ (objectMap slot) $ \obj -> do modifyIORef (objCommands obj) $ \v -> v // [(icId,V.empty)] {- addition:@@ -619,7 +629,7 @@ return (i,Nothing) -- create input connection let sm = slotMap input- pToI = [i | n <- glSlotNames, let i = fromMaybe (error $ "missing object array: " ++ n) $ Map.lookup n sm]+ pToI = [i | n <- glSlotNames, let i = fromMaybe (error $ "setStorage - missing object array: " ++ n) $ Map.lookup n sm] iToP = V.update (V.replicate (Map.size sm) Nothing) (V.imap (\i v -> (v, Just i)) pToI) writeIORef glInput $ Just $ InputConnection idx input pToI iToP @@ -641,7 +651,7 @@ Just l -> V.concat [v,V.replicate l V.empty] V.forM_ (V.zip pToI glSlotPrograms) $ \(slotIdx,prgs) -> do slot <- readIORef $ slotV ! slotIdx- forM_ (IM.elems $ objectMap slot) $ \obj -> do+ forM_ (objectMap slot) $ \obj -> do let cmdV = emptyV // [(prgIdx,createObjectCommands glTexUnitMapping topUnis obj (progV ! prgIdx)) | prgIdx <- prgs] modifyIORef (objCommands obj) $ \v -> extend v // [(idx,cmdV)] -- generate stream commands@@ -684,21 +694,28 @@ buffer binding on various targets: GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER glEnable/DisableVertexAttribArray -}-renderSlot :: [GLObjectCommand] -> IO ()-renderSlot cmds = forM_ cmds $ \cmd -> do+renderSlot :: IORef Int -> IORef GLuint -> IORef GLuint -> [GLObjectCommand] -> IO ()+renderSlot glDrawCallCounterRef glVertexBufferRef glIndexBufferRef cmds = forM_ cmds $ \cmd -> do+ let setup ref v m = do+ old <- readIORef ref+ unless (old == v) $ do+ writeIORef ref v+ m+ case cmd of GLSetVertexAttribArray idx buf size typ ptr -> do- glBindBuffer GL_ARRAY_BUFFER buf+ setup glVertexBufferRef buf $ glBindBuffer GL_ARRAY_BUFFER buf glEnableVertexAttribArray idx glVertexAttribPointer idx size typ (fromIntegral GL_FALSE) 0 ptr GLSetVertexAttribIArray idx buf size typ ptr -> do- glBindBuffer GL_ARRAY_BUFFER buf+ setup glVertexBufferRef buf $ glBindBuffer GL_ARRAY_BUFFER buf glEnableVertexAttribArray idx glVertexAttribIPointer idx size typ 0 ptr- GLDrawArrays mode first count -> glDrawArrays mode first count+ GLDrawArrays mode first count -> glDrawArrays mode first count >> modifyIORef glDrawCallCounterRef succ GLDrawElements mode count typ buf indicesPtr -> do- glBindBuffer GL_ELEMENT_ARRAY_BUFFER buf+ setup glIndexBufferRef buf $ glBindBuffer GL_ELEMENT_ARRAY_BUFFER buf glDrawElements mode count typ indicesPtr+ modifyIORef glDrawCallCounterRef succ GLSetUniform idx (GLUniform ty ref) -> setUniform idx ty ref GLBindTexture txTarget tuRef (GLUniform _ ref) -> do txObjVal <- readIORef ref@@ -715,105 +732,167 @@ --isOk <- checkGL --putStrLn $ isOk ++ " - " ++ show cmd +setupRenderTarget glInput GLRenderTarget{..} = do+ -- set target viewport+ ic' <- readIORef glInput+ case ic' of+ Nothing -> return ()+ Just ic -> do+ let input = icInput ic+ (w,h) <- readIORef $ screenSize input+ glViewport 0 0 (fromIntegral w) (fromIntegral h)+ -- TODO: set FBO target viewport+ glBindFramebuffer GL_DRAW_FRAMEBUFFER framebufferObject+ case framebufferDrawbuffers of+ Nothing -> return ()+ Just bl -> withArray bl $ glDrawBuffers (fromIntegral $ length bl)++setupDrawContext glForceSetup glDrawContextRef glInput new = do+ old <- readIORef glDrawContextRef+ writeIORef glDrawContextRef new+ force <- readIORef glForceSetup+ writeIORef glForceSetup False++ let setup :: Eq a => (GLDrawContext -> a) -> (a -> IO ()) -> IO ()+ setup f m = case force of+ True -> m $ f new+ False -> do+ let a = f new+ unless (a == f old) $ m a++ setup glRenderTarget $ setupRenderTarget glInput+ setup glRasterContext $ setupRasterContext+ setup glAccumulationContext setupAccumulationContext+ setup glProgram glUseProgram++ -- setup texture mapping+ setup glTextureMapping $ mapM_ $ \(textureUnit,GLTexture{..}) -> do+ glActiveTexture (GL_TEXTURE0 + fromIntegral textureUnit)+ glBindTexture glTextureTarget glTextureObject++ -- setup sampler mapping+ setup glSamplerMapping $ mapM_ $ \(textureUnit,GLSampler{..}) -> do+ glBindSampler (GL_TEXTURE0 + fromIntegral textureUnit) glSamplerObject++ -- setup sampler uniform mapping+ forM_ (glSamplerUniformMapping new) $ \(textureUnit,GLSamplerUniform{..}) -> do+ glUniform1i glUniformBinding (fromIntegral textureUnit)+ writeIORef glUniformBindingRef (fromIntegral textureUnit)+ renderFrame :: GLRenderer -> IO ()-renderFrame glp = do- glBindVertexArray (glVAO glp)- forM_ (glCommands glp) $ \cmd -> do+renderFrame GLRenderer{..} = do+ writeIORef glForceSetup True+ writeIORef glVertexBufferRef 0+ writeIORef glIndexBufferRef 0+ writeIORef glDrawCallCounterRef 0+ glBindVertexArray glVAO+ forM_ glCommands $ \cmd -> do case cmd of- GLSetRasterContext rCtx -> setupRasterContext rCtx- GLSetAccumulationContext aCtx -> setupAccumulationContext aCtx- GLSetRenderTarget rt bufs -> do- -- set target viewport- --when (rt == 0) $ do -- screen out- ic' <- readIORef $ glInput glp- case ic' of- Nothing -> return ()- Just ic -> do- let input = icInput ic- (w,h) <- readIORef $ screenSize input- glViewport 0 0 (fromIntegral w) (fromIntegral h)- -- TODO: set FBO target viewport- glBindFramebuffer GL_DRAW_FRAMEBUFFER rt- case bufs of- Nothing -> return ()- Just bl -> withArray bl $ glDrawBuffers (fromIntegral $ length bl)- GLSetProgram p -> glUseProgram p- GLSetSamplerUniform i tu ref -> glUniform1i i tu >> writeIORef ref tu- GLSetTexture tu target tx -> glActiveTexture tu >> glBindTexture target tx- GLSetSampler tu s -> glBindSampler tu s- GLClearRenderTarget vals -> clearRenderTarget vals- GLGenerateMipMap tu target -> glActiveTexture tu >> glGenerateMipmap target- GLRenderStream streamIdx progIdx -> do- renderSlot =<< readIORef (glStreamCommands $ glStreams glp ! streamIdx)- GLRenderSlot slotIdx progIdx -> do- input <- readIORef (glInput glp)- case input of- Nothing -> putStrLn "Warning: No pipeline input!" >> return ()- Just ic -> do- let draw obj = do- enabled <- readIORef $ objEnabled obj- when enabled $ do- cmd <- readIORef $ objCommands obj- --putStrLn "Render object"- renderSlot ((cmd ! icId ic) ! progIdx)- --putStrLn $ "Rendering " ++ show (V.length objs) ++ " objects"- readIORef (slotVector (icInput ic) ! (icSlotMapPipelineToInput ic ! slotIdx)) >>= \case- GLSlot _ objs Ordered -> forM_ objs $ draw . snd- GLSlot objMap _ _ -> forM_ objMap draw- {-- GLSetSampler- GLSaveImage- GLLoadImage- -}+ GLClearRenderTarget rt vals -> do+ setupRenderTarget glInput rt+ clearRenderTarget vals+ modifyIORef glDrawContextRef $ \ctx -> ctx {glRenderTarget = rt}++ GLRenderStream ctx streamIdx progIdx -> do+ setupDrawContext glForceSetup glDrawContextRef glInput ctx+ drawcmd <- readIORef (glStreamCommands $ glStreams ! streamIdx)+ renderSlot glDrawCallCounterRef glVertexBufferRef glIndexBufferRef drawcmd++ GLRenderSlot ctx slotIdx progIdx -> do+ input <- readIORef glInput+ case input of+ Nothing -> putStrLn "Warning: No pipeline input!" >> return ()+ Just ic -> do+ let draw setupDone obj = readIORef (objEnabled obj) >>= \case+ False -> return setupDone+ True -> do+ unless setupDone $ setupDrawContext glForceSetup glDrawContextRef glInput ctx+ drawcmd <- readIORef $ objCommands obj+ --putStrLn "Render object"+ renderSlot glDrawCallCounterRef glVertexBufferRef glIndexBufferRef ((drawcmd ! icId ic) ! progIdx)+ return True+ --putStrLn $ "Rendering " ++ show (V.length objs) ++ " objects"+ readIORef (slotVector (icInput ic) ! (icSlotMapPipelineToInput ic ! slotIdx)) >>= \case+ GLSlot _ objs Ordered -> foldM_ (\a -> draw a . snd) False objs+ GLSlot objMap _ _ -> foldM_ draw False objMap+ --isOk <- checkGL --putStrLn $ isOk ++ " - " ++ show cmd+ --readIORef glDrawCallCounterRef >>= \n -> putStrLn (show n ++ " draw calls") data CGState- = CGState- { currentProgram :: ProgramName- , textureBinding :: IntMap GLTexture- }+ = CGState+ { drawCommands :: [GLCommand]+ -- draw context data+ , rasterContext :: RasterContext+ , accumulationContext :: AccumulationContext+ , renderTarget :: GLRenderTarget+ , currentProgram :: ProgramName+ , samplerUniformMapping :: IntMap GLSamplerUniform+ , textureMapping :: IntMap GLTexture+ , samplerMapping :: IntMap GLSampler+ } initCGState = CGState- { currentProgram = error "CGState: empty currentProgram"- , textureBinding = IM.empty- }+ { drawCommands = mempty+ -- draw context data+ , rasterContext = error "compileCommand: missing RasterContext"+ , accumulationContext = error "compileCommand: missing AccumulationContext"+ , renderTarget = error "compileCommand: missing RenderTarget"+ , currentProgram = error "compileCommand: missing Program"+ , samplerUniformMapping = mempty+ , textureMapping = mempty+ , samplerMapping = mempty+ } type CG a = State CGState a -compileCommand :: Map String (IORef GLint) -> Vector GLSampler -> Vector GLTexture -> Vector GLRenderTarget -> Vector GLProgram -> Command -> CG GLCommand+emit :: GLCommand -> CG ()+emit cmd = modify $ \s -> s {drawCommands = cmd : drawCommands s}++drawContext programs = do+ GLProgram{..} <- (programs !) <$> gets currentProgram+ let f = take (Set.size inputTextureUniforms) . IntMap.toList+ GLDrawContext <$> gets rasterContext+ <*> gets accumulationContext+ <*> gets renderTarget+ <*> pure programObject+ <*> gets (f . textureMapping)+ <*> gets (f . samplerMapping)+ <*> gets (f . samplerUniformMapping)++compileCommand :: Map String (IORef GLint) -> Vector GLSampler -> Vector GLTexture -> Vector GLRenderTarget -> Vector GLProgram -> Command -> CG () compileCommand texUnitMap samplers textures targets programs cmd = case cmd of- SetRasterContext rCtx -> return $ GLSetRasterContext rCtx- SetAccumulationContext aCtx -> return $ GLSetAccumulationContext aCtx- SetRenderTarget rt -> let GLRenderTarget fbo bufs = targets ! rt in return $ GLSetRenderTarget fbo bufs- SetProgram p -> do- modify (\s -> s {currentProgram = p})- return $ GLSetProgram $ programObject $ programs ! p+ SetRasterContext rCtx -> modify $ \s -> s {rasterContext = rCtx}+ SetAccumulationContext aCtx -> modify $ \s -> s {accumulationContext = aCtx}+ SetRenderTarget rt -> modify $ \s -> s {renderTarget = targets ! rt}+ SetProgram p -> modify $ \s -> s {currentProgram = p} SetSamplerUniform n tu -> do p <- currentProgram <$> get case Map.lookup n (inputTextures $ programs ! p) of- Nothing -> return (GLSetProgram (programObject $ programs ! p) {-HACK!!! we have to emit something-}) -- TODO: some drivers does heavy cross stage (vertex/fragment) dead code elimination; fail $ "internal error (SetSamplerUniform)! - " ++ show cmd+ Nothing -> return () -- TODO: some drivers does heavy cross stage (vertex/fragment) dead code elimination; fail $ "internal error (SetSamplerUniform)! - " ++ show cmd Just i -> case Map.lookup n texUnitMap of Nothing -> fail $ "internal error (SetSamplerUniform - IORef)! - " ++ show cmd- Just r -> return $ GLSetSamplerUniform i (fromIntegral tu) r- SetTexture tu t -> do- let tex = textures ! t- modify (\s -> s {textureBinding = IM.insert tu tex $ textureBinding s})- return $ GLSetTexture (GL_TEXTURE0 + fromIntegral tu) (glTextureTarget tex) (glTextureObject tex)- SetSampler tu s -> return $ GLSetSampler (GL_TEXTURE0 + fromIntegral tu) (maybe 0 (glSamplerObject . (samplers !)) s)+ Just r -> modify $ \s -> s {samplerUniformMapping = IntMap.insert tu (GLSamplerUniform i r) $ samplerUniformMapping s}+ SetTexture tu t -> modify $ \s -> s {textureMapping = IntMap.insert tu (textures ! t) $ textureMapping s}+ SetSampler tu i -> modify $ \s -> s {samplerMapping = IntMap.insert tu (maybe (GLSampler 0) (samplers !) i) $ samplerMapping s}++ -- draw commands RenderSlot slot -> do- p <- currentProgram <$> get- return $ GLRenderSlot slot p+ p <- gets currentProgram+ ctx <- drawContext programs+ emit $ GLRenderSlot ctx slot p RenderStream stream -> do- p <- currentProgram <$> get- return $ GLRenderStream stream p- ClearRenderTarget vals -> return $ GLClearRenderTarget $ V.toList vals+ p <- gets currentProgram+ ctx <- drawContext programs+ emit $ GLRenderStream ctx stream p+ ClearRenderTarget vals -> do+ rt <- gets renderTarget+ emit $ GLClearRenderTarget rt $ V.toList vals+{- GenerateMipMap tu -> do tb <- textureBinding <$> get case IM.lookup tu tb of Nothing -> fail "internal error (GenerateMipMap)!" Just tex -> return $ GLGenerateMipMap (GL_TEXTURE0 + fromIntegral tu) (glTextureTarget tex)-{-- SaveImage _ _ -> undefined- LoadImage _ _ -> undefined -}
src/LambdaCube/GL/Mesh.hs view
@@ -50,7 +50,7 @@ addMeshToObjectArray :: GLStorage -> String -> [String] -> GPUMesh -> IO Object addMeshToObjectArray input slotName objUniNames (GPUMesh _ (GPUData prim streams indices _)) = do -- select proper attributes- let (ObjectArraySchema slotPrim slotStreams) = fromMaybe (error $ "missing object array: " ++ slotName) $ Map.lookup slotName $! objectArrays $! schema input+ let (ObjectArraySchema slotPrim slotStreams) = fromMaybe (error $ "addMeshToObjectArray - missing object array: " ++ slotName) $ Map.lookup slotName $! objectArrays $! schema input filterStream n _ = Map.member n slotStreams addObject input slotName prim indices (Map.filterWithKey filterStream streams) objUniNames
src/LambdaCube/GL/Type.hs view
@@ -128,7 +128,7 @@ = GLTexture { glTextureObject :: GLuint , glTextureTarget :: GLenum- }+ } deriving Eq data InputConnection = InputConnection@@ -159,34 +159,51 @@ , glVAO :: GLuint , glTexUnitMapping :: Map String (IORef GLint) -- maps texture uniforms to texture units , glStreams :: Vector GLStream+ , glDrawContextRef :: IORef GLDrawContext+ , glForceSetup :: IORef Bool+ , glVertexBufferRef :: IORef GLuint+ , glIndexBufferRef :: IORef GLuint+ , glDrawCallCounterRef :: IORef Int } data GLSampler = GLSampler { glSamplerObject :: GLuint- }+ } deriving Eq data GLRenderTarget = GLRenderTarget { framebufferObject :: GLuint , framebufferDrawbuffers :: Maybe [GLenum]- }+ } deriving Eq +type GLTextureUnit = Int+type GLUniformBinding = GLint++data GLSamplerUniform+ = GLSamplerUniform+ { glUniformBinding :: !GLUniformBinding+ , glUniformBindingRef :: IORef GLUniformBinding+ }++instance Eq GLSamplerUniform where+ a == b = glUniformBinding a == glUniformBinding b++data GLDrawContext+ = GLDrawContext+ { glRasterContext :: !RasterContext+ , glAccumulationContext :: !AccumulationContext+ , glRenderTarget :: !GLRenderTarget+ , glProgram :: !GLuint+ , glTextureMapping :: ![(GLTextureUnit,GLTexture)]+ , glSamplerMapping :: ![(GLTextureUnit,GLSampler)]+ , glSamplerUniformMapping :: ![(GLTextureUnit,GLSamplerUniform)]+ }+ data GLCommand- = GLSetRasterContext !RasterContext- | GLSetAccumulationContext !AccumulationContext- | GLSetRenderTarget !GLuint !(Maybe [GLenum])- | GLSetProgram !GLuint- | GLSetSamplerUniform !GLint !GLint (IORef GLint) -- sampler index, texture unit, IORef stores the actual texture unit mapping- | GLSetTexture !GLenum !GLuint !GLuint- | GLSetSampler !GLuint !GLuint- | GLRenderSlot !SlotName !ProgramName- | GLRenderStream !StreamName !ProgramName- | GLClearRenderTarget [ClearImage]- | GLGenerateMipMap !GLenum !GLenum- | GLSaveImage FrameBufferComponent ImageRef -- from framebuffer component to texture (image)- | GLLoadImage ImageRef FrameBufferComponent -- from texture (image) to framebuffer component- deriving Show+ = GLRenderSlot !GLDrawContext !SlotName !ProgramName+ | GLRenderStream !GLDrawContext !StreamName !ProgramName+ | GLClearRenderTarget !GLRenderTarget ![ClearImage] instance Show (IORef GLint) where show _ = "(IORef GLint)"