packages feed

keid-render-basic 0.1.7.0 → 0.1.8.0

raw patch · 51 files changed

+1456/−1378 lines, 51 filesdep ~keid-corebinary-addedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: keid-core

API changes (from Hackage documentation)

- Render.Debug.Model: InstanceAttrs :: TextureParams -> Transform -> InstanceAttrs
- Render.Debug.Model: InstanceBuffers :: InstanceTexture textureStage -> InstanceTransform transformStage -> InstanceBuffers textureStage transformStage
- Render.Debug.Model: [$sel:ibTexture:InstanceBuffers] :: InstanceBuffers textureStage transformStage -> InstanceTexture textureStage
- Render.Debug.Model: [$sel:ibTransform:InstanceBuffers] :: InstanceBuffers textureStage transformStage -> InstanceTransform transformStage
- Render.Debug.Model: [$sel:textureParams:InstanceAttrs] :: InstanceAttrs -> TextureParams
- Render.Debug.Model: [$sel:transformMat4:InstanceAttrs] :: InstanceAttrs -> Transform
- Render.Debug.Model: allocateInstancesCoherent :: (MonadReader env m, HasVulkan env, MonadResource m, MonadUnliftIO m) => [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers 'Coherent 'Coherent)
- Render.Debug.Model: allocateInstancesCoherent_ :: HasVulkan env => Int -> ResourceT (RIO env) (InstanceBuffers 'Coherent 'Coherent)
- Render.Debug.Model: allocateInstancesWith :: (MonadResource m, MonadUnliftIO m) => (BufferUsageFlagBits -> Int -> Vector TextureParams -> m (InstanceTexture texture)) -> (BufferUsageFlagBits -> Int -> Vector Transform -> m (InstanceTransform transform)) -> (forall stage a. Allocated stage a -> m ()) -> [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers texture transform)
- Render.Debug.Model: data InstanceAttrs
- Render.Debug.Model: data InstanceBuffers textureStage transformStage
- Render.Debug.Model: data Transform
- Render.Debug.Model: instance Foreign.Storable.Storable Render.Debug.Model.TextureParams
- Render.Debug.Model: instance GHC.Show.Show Render.Debug.Model.TextureParams
- Render.Debug.Model: instance Resource.Model.HasVertexBuffers (Render.Debug.Model.InstanceBuffers textureStage transformStage)
- Render.Debug.Model: instance Vulkan.Zero.Zero Render.Debug.Model.InstanceAttrs
- Render.Debug.Model: instance Vulkan.Zero.Zero Render.Debug.Model.TextureParams
- Render.Debug.Model: instanceAttrs :: Int32 -> Int32 -> [Transform] -> InstanceAttrs
- Render.Debug.Model: storableAttrs1 :: Int32 -> Int32 -> [Transform] -> StorableAttrs
- Render.Debug.Model: type StorableAttrs = (Vector TextureParams, Vector Transform)
- Render.Debug.Model: updateCoherentResize_ :: (HasVulkan context, MonadUnliftIO m) => context -> InstanceBuffers 'Coherent 'Coherent -> (Vector TextureParams, Vector Transform) -> m (InstanceBuffers 'Coherent 'Coherent)
- Render.Debug.Model: vkInstanceTexture :: [Format]
- Render.Debug.Model: vkVertexAttrs :: [Format]
- Render.DescSets.Set0: instanceTransform :: (VertexInputRate, [Format])
- Render.DescSets.Set0: vertexPos :: (VertexInputRate, [Format])
- Render.Font.EvanwSdf.Model: instance Foreign.Storable.Storable Render.Font.EvanwSdf.Model.InstanceAttrs
- Render.Font.EvanwSdf.Model: type InstanceBuffer stage = Allocated stage InstanceAttrs
- Render.Font.EvanwSdf.Model: type Model buf = Indexed buf Packed VertexAttrs
- Render.Font.EvanwSdf.Model: type VertexAttrs = "uv" ::: Vec2
- Render.Font.EvanwSdf.Model: vkInstanceAttrs :: [Format]
- Render.Lit.Colored.Model: vkVertexAttrs :: [Format]
- Render.Lit.Material.Model: data Transform
- Render.Lit.Material.Model: vkVertexAttrs :: [Format]
- Render.Lit.Textured.Model: InstanceAttrs :: TextureParams -> Transform -> InstanceAttrs
- Render.Lit.Textured.Model: InstanceBuffers :: InstanceTexture textureStage -> InstanceTransform transformStage -> InstanceBuffers textureStage transformStage
- Render.Lit.Textured.Model: [$sel:ibTexture:InstanceBuffers] :: InstanceBuffers textureStage transformStage -> InstanceTexture textureStage
- Render.Lit.Textured.Model: [$sel:ibTransform:InstanceBuffers] :: InstanceBuffers textureStage transformStage -> InstanceTransform transformStage
- Render.Lit.Textured.Model: [$sel:textureParams:InstanceAttrs] :: InstanceAttrs -> TextureParams
- Render.Lit.Textured.Model: [$sel:transformMat4:InstanceAttrs] :: InstanceAttrs -> Transform
- Render.Lit.Textured.Model: allocateInstancesWith :: (MonadResource m, MonadUnliftIO m) => (BufferUsageFlagBits -> Int -> Vector TextureParams -> m (InstanceTexture texture)) -> (BufferUsageFlagBits -> Int -> Vector Transform -> m (InstanceTransform transform)) -> (forall stage a. Allocated stage a -> m ()) -> [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers texture transform)
- Render.Lit.Textured.Model: data InstanceAttrs
- Render.Lit.Textured.Model: data InstanceBuffers textureStage transformStage
- Render.Lit.Textured.Model: data Transform
- Render.Lit.Textured.Model: instance Foreign.Storable.Storable Render.Lit.Textured.Model.TextureParams
- Render.Lit.Textured.Model: instance Foreign.Storable.Storable Render.Lit.Textured.Model.VertexAttrs
- Render.Lit.Textured.Model: instance GHC.Show.Show Render.Lit.Textured.Model.TextureParams
- Render.Lit.Textured.Model: instance Resource.Model.HasVertexBuffers (Render.Lit.Textured.Model.InstanceBuffers textureStage transformStage)
- Render.Lit.Textured.Model: instance Vulkan.Zero.Zero Render.Lit.Textured.Model.InstanceAttrs
- Render.Lit.Textured.Model: instance Vulkan.Zero.Zero Render.Lit.Textured.Model.TextureParams
- Render.Lit.Textured.Model: vkInstanceTexture :: [Format]
- Render.Lit.Textured.Model: vkVertexAttrs :: [Format]
- Render.Unlit.Colored.Model: vkVertexAttrs :: [Format]
- Render.Unlit.Sprite.Model: vkInstanceAttrs :: [Format]
- Render.Unlit.Textured.Model: InstanceAttrs :: TextureParams -> Transform -> InstanceAttrs
- Render.Unlit.Textured.Model: InstanceBuffers :: InstanceTexture textureStage -> InstanceTransform transformStage -> InstanceBuffers textureStage transformStage
- Render.Unlit.Textured.Model: [$sel:ibTexture:InstanceBuffers] :: InstanceBuffers textureStage transformStage -> InstanceTexture textureStage
- Render.Unlit.Textured.Model: [$sel:ibTransform:InstanceBuffers] :: InstanceBuffers textureStage transformStage -> InstanceTransform transformStage
- Render.Unlit.Textured.Model: [$sel:textureParams:InstanceAttrs] :: InstanceAttrs -> TextureParams
- Render.Unlit.Textured.Model: [$sel:transformMat4:InstanceAttrs] :: InstanceAttrs -> Transform
- Render.Unlit.Textured.Model: allocateInstancesCoherent :: (MonadReader env m, HasVulkan env, MonadResource m, MonadUnliftIO m) => [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers 'Coherent 'Coherent)
- Render.Unlit.Textured.Model: allocateInstancesCoherent_ :: HasVulkan env => Int -> ResourceT (RIO env) (InstanceBuffers 'Coherent 'Coherent)
- Render.Unlit.Textured.Model: allocateInstancesWith :: (MonadResource m, MonadUnliftIO m) => (BufferUsageFlagBits -> Int -> Vector TextureParams -> m (InstanceTexture texture)) -> (BufferUsageFlagBits -> Int -> Vector Transform -> m (InstanceTransform transform)) -> (forall stage a. Allocated stage a -> m ()) -> [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers texture transform)
- Render.Unlit.Textured.Model: data InstanceAttrs
- Render.Unlit.Textured.Model: data InstanceBuffers textureStage transformStage
- Render.Unlit.Textured.Model: data Transform
- Render.Unlit.Textured.Model: instance Resource.Model.HasVertexBuffers (Render.Unlit.Textured.Model.InstanceBuffers textureStage transformStage)
- Render.Unlit.Textured.Model: instance Vulkan.Zero.Zero Render.Unlit.Textured.Model.InstanceAttrs
- Render.Unlit.Textured.Model: instanceAttrs :: Int32 -> Int32 -> [Transform] -> InstanceAttrs
- Render.Unlit.Textured.Model: storableAttrs1 :: Int32 -> Int32 -> [Transform] -> StorableAttrs
- Render.Unlit.Textured.Model: type StorableAttrs = (Vector TextureParams, Vector Transform)
- Render.Unlit.Textured.Model: updateCoherentResize_ :: (HasVulkan context, MonadUnliftIO m) => context -> InstanceBuffers 'Coherent 'Coherent -> (Vector TextureParams, Vector Transform) -> m (InstanceBuffers 'Coherent 'Coherent)
- Render.Unlit.Textured.Model: vkInstanceTexture :: [Format]
- Render.Unlit.Textured.Model: vkVertexAttrs :: [Format]
- Render.Unlit.TileMap.Model: InstanceAttrs :: TileMapParams -> Transform -> InstanceAttrs
- Render.Unlit.TileMap.Model: InstanceBuffers :: InstanceTileMap tilemapStage -> InstanceTransform transformStage -> InstanceBuffers tilemapStage transformStage
- Render.Unlit.TileMap.Model: [$sel:ibTileMap:InstanceBuffers] :: InstanceBuffers tilemapStage transformStage -> InstanceTileMap tilemapStage
- Render.Unlit.TileMap.Model: [$sel:ibTransform:InstanceBuffers] :: InstanceBuffers tilemapStage transformStage -> InstanceTransform transformStage
- Render.Unlit.TileMap.Model: [$sel:tilemapParams:InstanceAttrs] :: InstanceAttrs -> TileMapParams
- Render.Unlit.TileMap.Model: [$sel:transformMat4:InstanceAttrs] :: InstanceAttrs -> Transform
- Render.Unlit.TileMap.Model: allocateInstancesCoherent :: (MonadReader env m, HasVulkan env, MonadResource m, MonadUnliftIO m) => [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers 'Coherent 'Coherent)
- Render.Unlit.TileMap.Model: allocateInstancesCoherent_ :: HasVulkan env => Int -> ResourceT (RIO env) (InstanceBuffers 'Coherent 'Coherent)
- Render.Unlit.TileMap.Model: allocateInstancesWith :: (MonadResource m, MonadUnliftIO m) => (BufferUsageFlagBits -> Int -> Vector TileMapParams -> m (InstanceTileMap texture)) -> (BufferUsageFlagBits -> Int -> Vector Transform -> m (InstanceTransform transform)) -> (forall stage a. Allocated stage a -> m ()) -> [InstanceAttrs] -> m (ReleaseKey, InstanceBuffers texture transform)
- Render.Unlit.TileMap.Model: data InstanceAttrs
- Render.Unlit.TileMap.Model: data InstanceBuffers tilemapStage transformStage
- Render.Unlit.TileMap.Model: data Transform
- Render.Unlit.TileMap.Model: instance Foreign.Storable.Storable Render.Unlit.TileMap.Model.TileMapParams
- Render.Unlit.TileMap.Model: instance Resource.Model.HasVertexBuffers (Render.Unlit.TileMap.Model.InstanceBuffers tilemapStage transformStage)
- Render.Unlit.TileMap.Model: instance Vulkan.Zero.Zero Render.Unlit.TileMap.Model.InstanceAttrs
- Render.Unlit.TileMap.Model: type StorableAttrs = (Vector TileMapParams, Vector Transform)
- Render.Unlit.TileMap.Model: updateCoherentResize_ :: (HasVulkan context, MonadUnliftIO m) => context -> InstanceBuffers 'Coherent 'Coherent -> (Vector TileMapParams, Vector Transform) -> m (InstanceBuffers 'Coherent 'Coherent)
- Render.Unlit.TileMap.Model: vkInstanceTileMap :: [Format]
- Render.Unlit.TileMap.Model: vkVertexAttrs :: [Format]
- Resource.Font: allocateCollection :: (Traversable collection, MonadVulkan env m, HasLogFunc env, MonadThrow m, MonadResource m, HasCallStack) => Queues CommandPool -> collection Config -> m (ReleaseKey, collection Font)
- Resource.Font: allocateFont :: (HasCallStack, MonadVulkan env m, HasLogFunc env, MonadThrow m, MonadResource m) => Queues CommandPool -> Config -> m (ReleaseKey, Font)
+ Global.Resource.CubeMap.Base: type Textures = Collection (Texture CubeMap)
+ Global.Resource.CubeMap.Base.Paths: pattern BLACK_KTX2 :: FilePath
+ Global.Resource.Texture.Base: type Textures = Collection (Texture Flat)
+ Global.Resource.Texture.Base.Paths: pattern BLACK_KTX2 :: FilePath
+ Global.Resource.Texture.Base.Paths: pattern FLAT_KTX2 :: FilePath
+ Global.Resource.Texture.Base.Paths: pattern IBL_BRDF_LUT_KTX2 :: FilePath
+ Render.Basic: [$sel:pLine2d:Pipelines] :: PipelinesF (f :: Type -> Type) -> f ^ Pipeline
+ Render.Basic: [$sel:pLine2dNoDepth:Pipelines] :: PipelinesF (f :: Type -> Type) -> f ^ Pipeline
+ Render.Debug.Model: Attrs :: HKD f TextureParams -> HKD f Transform -> AttrsF f
+ Render.Debug.Model: [$sel:params:Attrs] :: AttrsF f -> HKD f TextureParams
+ Render.Debug.Model: [$sel:transforms:Attrs] :: AttrsF f -> HKD f Transform
+ Render.Debug.Model: attrs :: Int32 -> Int32 -> [Transform] -> Attrs
+ Render.Debug.Model: data AttrsF f
+ Render.Debug.Model: instance Engine.Vulkan.Pipeline.Graphics.HasVertexInputBindings Render.Debug.Model.Attrs
+ Render.Debug.Model: instance Foreign.Storable.Generic.Internal.GStorable Render.Debug.Model.Attrs
+ Render.Debug.Model: instance GHC.Generics.Generic (Render.Debug.Model.AttrsF f)
+ Render.Debug.Model: instance GHC.Show.Show Render.Debug.Model.Attrs
+ Render.Debug.Model: instance GHC.Show.Show Render.Debug.Model.Buffers
+ Render.Debug.Model: instance GHC.Show.Show Render.Debug.Model.Stores
+ Render.Debug.Model: instance Resource.Model.HasVertexBuffers Render.Debug.Model.Buffers
+ Render.Debug.Model: instance Resource.Model.Observer.UpdateCoherent Render.Debug.Model.Buffers Render.Debug.Model.Stores
+ Render.Debug.Model: instance Resource.Model.Observer.VertexBuffers Render.Debug.Model.Buffers
+ Render.Debug.Model: instance Vulkan.Zero.Zero Render.Debug.Model.Attrs
+ Render.Debug.Model: stores1 :: Int32 -> Int32 -> [Transform] -> Stores
+ Render.Debug.Model: type Attrs = AttrsF Identity
+ Render.Debug.Model: type Buffers = AttrsF (Allocated 'Coherent)
+ Render.Debug.Model: type ObserverCoherent = ObserverIO Buffers
+ Render.Debug.Model: type Stores = AttrsF Vector
+ Render.Debug.Model: type Vertex = Vertex3d VertexAttrs
+ Render.Font.EvanwSdf.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Font.EvanwSdf.Model.InstanceAttrs
+ Render.Font.EvanwSdf.Model: instance Engine.Vulkan.Pipeline.Graphics.HasVertexInputBindings Render.Font.EvanwSdf.Model.InstanceAttrs
+ Render.Font.EvanwSdf.Model: instance Foreign.Storable.Generic.Internal.GStorable Render.Font.EvanwSdf.Model.InstanceAttrs
+ Render.Font.EvanwSdf.Model: instance GHC.Generics.Generic Render.Font.EvanwSdf.Model.InstanceAttrs
+ Render.Lit.Colored.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Lit.Colored.Model.VertexAttrs
+ Render.Lit.Colored.Model: instance Geomancy.Gl.Block.Block Render.Lit.Colored.Model.VertexAttrs
+ Render.Lit.Colored.Model: type Vertex = Vertex3d VertexAttrs
+ Render.Lit.Material.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Lit.Material.Model.VertexAttrs
+ Render.Lit.Material.Model: instance Geomancy.Gl.Block.Block Render.Lit.Material.Model.VertexAttrs
+ Render.Lit.Material.Model: type Vertex = Vertex3d VertexAttrs
+ Render.Lit.Textured.Model: Attrs :: HKD f TextureParams -> HKD f Transform -> AttrsF f
+ Render.Lit.Textured.Model: [$sel:params:Attrs] :: AttrsF f -> HKD f TextureParams
+ Render.Lit.Textured.Model: [$sel:transforms:Attrs] :: AttrsF f -> HKD f Transform
+ Render.Lit.Textured.Model: attrStores :: Foldable t => t Attrs -> Stores
+ Render.Lit.Textured.Model: attrs :: Int32 -> Int32 -> [Transform] -> Attrs
+ Render.Lit.Textured.Model: data AttrsF f
+ Render.Lit.Textured.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Lit.Textured.Model.VertexAttrs
+ Render.Lit.Textured.Model: instance Foreign.Storable.Generic.Internal.GStorable Render.Lit.Textured.Model.VertexAttrs
+ Render.Lit.Textured.Model: stores1 :: Int32 -> Int32 -> [Transform] -> Stores
+ Render.Lit.Textured.Model: type Attrs = AttrsF Identity
+ Render.Lit.Textured.Model: type Buffers = AttrsF (Allocated 'Coherent)
+ Render.Lit.Textured.Model: type ObserverCoherent = ObserverIO Buffers
+ Render.Lit.Textured.Model: type Stores = AttrsF Vector
+ Render.Lit.Textured.Model: type Vertex = Vertex3d VertexAttrs
+ Render.Pass.Compose: Compose :: RenderPass -> Vector Framebuffer -> Rect2D -> Vector ClearValue -> RefCounted -> Compose
+ Render.Pass.Compose: [$sel:clear:Compose] :: Compose -> Vector ClearValue
+ Render.Pass.Compose: [$sel:frameBuffers:Compose] :: Compose -> Vector Framebuffer
+ Render.Pass.Compose: [$sel:release:Compose] :: Compose -> RefCounted
+ Render.Pass.Compose: [$sel:renderArea:Compose] :: Compose -> Rect2D
+ Render.Pass.Compose: [$sel:renderPass:Compose] :: Compose -> RenderPass
+ Render.Pass.Compose: allocate :: (MonadResource m, MonadVulkan env m, HasLogFunc env, HasSwapchain swapchain) => swapchain -> m Compose
+ Render.Pass.Compose: data Compose
+ Render.Pass.Compose: instance Engine.Vulkan.Types.HasRenderPass Render.Pass.Compose.Compose
+ Render.Pass.Compose: instance Engine.Vulkan.Types.RenderPass Render.Pass.Compose.Compose
+ Render.Pass.Compose: update :: (MonadResource m, MonadVulkan env m, HasSwapchain swapchain) => swapchain -> Compose -> m Compose
+ Render.Pass.Compose: usePass :: (MonadIO io, HasRenderPass a) => a -> Word32 -> CommandBuffer -> io r -> io r
+ Render.Unlit.Colored.Model: type Vertex = Vertex3d VertexAttrs
+ Render.Unlit.Line2d.Code: frag :: Code
+ Render.Unlit.Line2d.Code: vert :: Code
+ Render.Unlit.Line2d.Draw: batch :: (MonadIO m, Foldable t) => CommandBuffer -> Segment -> Allocated s InstanceAttrs -> t ("firstInstance" ::: Word32, "instanceCount" ::: Word32) -> Bound dsl vertices instances m ()
+ Render.Unlit.Line2d.Draw: bind :: MonadIO io => CommandBuffer -> Segment -> Buffer s -> io ()
+ Render.Unlit.Line2d.Draw: segments :: MonadIO io => CommandBuffer -> Allocated s a -> ("firstInstance" ::: Word32, "instanceCount" ::: Word32) -> io ()
+ Render.Unlit.Line2d.Draw: single :: MonadIO m => CommandBuffer -> Segment -> Allocated s InstanceAttrs -> Bound dsl vertices instances m ()
+ Render.Unlit.Line2d.Model: Batches :: [v a] -> Batches v a
+ Render.Unlit.Line2d.Model: InstanceAttrs :: Vec4 -> Packed -> Float -> InstanceAttrs
+ Render.Unlit.Line2d.Model: [$sel:color:InstanceAttrs] :: InstanceAttrs -> Vec4
+ Render.Unlit.Line2d.Model: [$sel:position:InstanceAttrs] :: InstanceAttrs -> Packed
+ Render.Unlit.Line2d.Model: [$sel:width:InstanceAttrs] :: InstanceAttrs -> Float
+ Render.Unlit.Line2d.Model: createVertices :: MonadVulkan env m => Maybe Text -> Queues CommandPool -> Float -> m Segment
+ Render.Unlit.Line2d.Model: data InstanceAttrs
+ Render.Unlit.Line2d.Model: instance Data.Foldable.Foldable v => Data.Foldable.Foldable (Render.Unlit.Line2d.Model.Batches v)
+ Render.Unlit.Line2d.Model: instance Data.Traversable.Traversable v => Data.Traversable.Traversable (Render.Unlit.Line2d.Model.Batches v)
+ Render.Unlit.Line2d.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Unlit.Line2d.Model.InstanceAttrs
+ Render.Unlit.Line2d.Model: instance Engine.Vulkan.Pipeline.Graphics.HasVertexInputBindings Render.Unlit.Line2d.Model.InstanceAttrs
+ Render.Unlit.Line2d.Model: instance Foreign.Storable.Generic.Internal.GStorable Render.Unlit.Line2d.Model.InstanceAttrs
+ Render.Unlit.Line2d.Model: instance GHC.Base.Functor v => GHC.Base.Functor (Render.Unlit.Line2d.Model.Batches v)
+ Render.Unlit.Line2d.Model: instance GHC.Base.Monoid (Render.Unlit.Line2d.Model.Batches v a)
+ Render.Unlit.Line2d.Model: instance GHC.Base.Semigroup (Render.Unlit.Line2d.Model.Batches v a)
+ Render.Unlit.Line2d.Model: instance GHC.Classes.Eq (v a) => GHC.Classes.Eq (Render.Unlit.Line2d.Model.Batches v a)
+ Render.Unlit.Line2d.Model: instance GHC.Classes.Eq Render.Unlit.Line2d.Model.InstanceAttrs
+ Render.Unlit.Line2d.Model: instance GHC.Classes.Ord (v a) => GHC.Classes.Ord (Render.Unlit.Line2d.Model.Batches v a)
+ Render.Unlit.Line2d.Model: instance GHC.Generics.Generic Render.Unlit.Line2d.Model.InstanceAttrs
+ Render.Unlit.Line2d.Model: instance GHC.Show.Show (v a) => GHC.Show.Show (Render.Unlit.Line2d.Model.Batches v a)
+ Render.Unlit.Line2d.Model: instance GHC.Show.Show Render.Unlit.Line2d.Model.InstanceAttrs
+ Render.Unlit.Line2d.Model: newBatchObserver :: (MonadVulkan env m, MonadResource m) => ("initial size" ::: Int) -> m BatchObserver
+ Render.Unlit.Line2d.Model: newtype Batches v a
+ Render.Unlit.Line2d.Model: observeCoherentBatches :: (GetOutput output ~ Batches Vector InstanceAttrs, HasOutput output, MonadVulkan env m) => output -> BatchObserver -> m ()
+ Render.Unlit.Line2d.Model: observeCoherentResize_ :: (MonadVulkan env m, HasOutput source, GetOutput source ~ Vector output, Storable output) => source -> ObserverCoherent output -> m ()
+ Render.Unlit.Line2d.Model: point :: Float -> Vec4 -> Vec2 -> InstanceAttrs
+ Render.Unlit.Line2d.Model: type BatchObserver = ObserverIO (Buffer 'Coherent, Ranges)
+ Render.Unlit.Line2d.Model: type Buffer s = Allocated s InstanceAttrs
+ Render.Unlit.Line2d.Model: type Observer = ObserverCoherent InstanceAttrs
+ Render.Unlit.Line2d.Model: type Points = Vector InstanceAttrs
+ Render.Unlit.Line2d.Model: type Segment = Allocated 'Staged Packed
+ Render.Unlit.Line2d.Model: type Vertex = Vertex3d ()
+ Render.Unlit.Line2d.Model: verticesRoundRound :: Float -> Vector Packed
+ Render.Unlit.Line2d.Pipeline: allocate :: (MonadVulkan env m, MonadResource m, HasRenderPass renderpass) => Bool -> SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT m Pipeline
+ Render.Unlit.Line2d.Pipeline: config :: Bool -> Tagged Scene DsLayoutBindings -> Config
+ Render.Unlit.Line2d.Pipeline: stageCode :: StageCode
+ Render.Unlit.Line2d.Pipeline: stageSpirv :: StageSpirv
+ Render.Unlit.Line2d.Pipeline: type Config = Configure Pipeline
+ Render.Unlit.Line2d.Pipeline: type Pipeline = Pipeline '[Scene] Vertex InstanceAttrs
+ Render.Unlit.Sprite.Model: [$sel:animation:InstanceAttrs] :: InstanceAttrs -> Vec4
+ Render.Unlit.Sprite.Model: animate_ :: ("margin" ::: Float) -> ("num.frames" ::: Int) -> ("frame duration" ::: Float) -> ("phase" ::: Float) -> InstanceAttrs -> InstanceAttrs
+ Render.Unlit.Sprite.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Unlit.Sprite.Model.InstanceAttrs
+ Render.Unlit.Sprite.Model: instance Engine.Vulkan.Pipeline.Graphics.HasVertexInputBindings Render.Unlit.Sprite.Model.InstanceAttrs
+ Render.Unlit.Textured.Model: Attrs :: HKD f TextureParams -> HKD f Transform -> AttrsF f
+ Render.Unlit.Textured.Model: [$sel:params:Attrs] :: AttrsF f -> HKD f TextureParams
+ Render.Unlit.Textured.Model: [$sel:transforms:Attrs] :: AttrsF f -> HKD f Transform
+ Render.Unlit.Textured.Model: attrStores :: Foldable t => t Attrs -> Stores
+ Render.Unlit.Textured.Model: attrs :: Int32 -> Int32 -> [Transform] -> Attrs
+ Render.Unlit.Textured.Model: data AttrsF f
+ Render.Unlit.Textured.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Unlit.Textured.Model.TextureParams
+ Render.Unlit.Textured.Model: instance Engine.Vulkan.Pipeline.Graphics.HasVertexInputBindings Render.Unlit.Textured.Model.Attrs
+ Render.Unlit.Textured.Model: instance GHC.Generics.Generic (Render.Unlit.Textured.Model.AttrsF f)
+ Render.Unlit.Textured.Model: instance GHC.Generics.Generic Render.Unlit.Textured.Model.TextureParams
+ Render.Unlit.Textured.Model: instance GHC.Show.Show Render.Unlit.Textured.Model.Attrs
+ Render.Unlit.Textured.Model: instance GHC.Show.Show Render.Unlit.Textured.Model.Buffers
+ Render.Unlit.Textured.Model: instance GHC.Show.Show Render.Unlit.Textured.Model.Stores
+ Render.Unlit.Textured.Model: instance Geomancy.Gl.Block.Block Render.Unlit.Textured.Model.TextureParams
+ Render.Unlit.Textured.Model: instance Resource.Model.HasVertexBuffers Render.Unlit.Textured.Model.Buffers
+ Render.Unlit.Textured.Model: instance Resource.Model.Observer.UpdateCoherent Render.Unlit.Textured.Model.Buffers Render.Unlit.Textured.Model.Stores
+ Render.Unlit.Textured.Model: instance Resource.Model.Observer.VertexBuffers Render.Unlit.Textured.Model.Buffers
+ Render.Unlit.Textured.Model: instance Vulkan.Zero.Zero Render.Unlit.Textured.Model.Attrs
+ Render.Unlit.Textured.Model: stores1 :: Int32 -> Int32 -> [Transform] -> Stores
+ Render.Unlit.Textured.Model: type Attrs = AttrsF Identity
+ Render.Unlit.Textured.Model: type Buffers = AttrsF (Allocated 'Coherent)
+ Render.Unlit.Textured.Model: type ObserverCoherent = ObserverIO Buffers
+ Render.Unlit.Textured.Model: type Stores = AttrsF Vector
+ Render.Unlit.Textured.Model: type Vertex = Vertex3d VertexAttrs
+ Render.Unlit.TileMap.Model: Attrs :: HKD f TileMapParams -> HKD f Transform -> AttrsF f
+ Render.Unlit.TileMap.Model: [$sel:params:Attrs] :: AttrsF f -> HKD f TileMapParams
+ Render.Unlit.TileMap.Model: [$sel:tmpTilesetBorder:TileMapParams] :: TileMapParams -> Vec2
+ Render.Unlit.TileMap.Model: [$sel:tmpTilesetOffset:TileMapParams] :: TileMapParams -> Vec2
+ Render.Unlit.TileMap.Model: [$sel:transforms:Attrs] :: AttrsF f -> HKD f Transform
+ Render.Unlit.TileMap.Model: data AttrsF f
+ Render.Unlit.TileMap.Model: instance Engine.Vulkan.Format.HasVkFormat Render.Unlit.TileMap.Model.TileMapParams
+ Render.Unlit.TileMap.Model: instance Engine.Vulkan.Pipeline.Graphics.HasVertexInputBindings Render.Unlit.TileMap.Model.Attrs
+ Render.Unlit.TileMap.Model: instance Foreign.Storable.Generic.Internal.GStorable Render.Unlit.TileMap.Model.TileMapParams
+ Render.Unlit.TileMap.Model: instance GHC.Generics.Generic (Render.Unlit.TileMap.Model.AttrsF f)
+ Render.Unlit.TileMap.Model: instance GHC.Generics.Generic Render.Unlit.TileMap.Model.TileMapParams
+ Render.Unlit.TileMap.Model: instance GHC.Show.Show Render.Unlit.TileMap.Model.Attrs
+ Render.Unlit.TileMap.Model: instance GHC.Show.Show Render.Unlit.TileMap.Model.Buffers
+ Render.Unlit.TileMap.Model: instance GHC.Show.Show Render.Unlit.TileMap.Model.Stores
+ Render.Unlit.TileMap.Model: instance Resource.Model.HasVertexBuffers Render.Unlit.TileMap.Model.Buffers
+ Render.Unlit.TileMap.Model: instance Resource.Model.Observer.UpdateCoherent Render.Unlit.TileMap.Model.Buffers Render.Unlit.TileMap.Model.Stores
+ Render.Unlit.TileMap.Model: instance Resource.Model.Observer.VertexBuffers Render.Unlit.TileMap.Model.Buffers
+ Render.Unlit.TileMap.Model: type Attrs = AttrsF Identity
+ Render.Unlit.TileMap.Model: type Buffers = AttrsF (Allocated 'Coherent)
+ Render.Unlit.TileMap.Model: type ObserverCoherent = ObserverIO Buffers
+ Render.Unlit.TileMap.Model: type Stores = AttrsF Vector
+ Render.Unlit.TileMap.Model: type Vertex = Vertex3d VertexAttrs
+ Resource.Font: allocate :: (HasCallStack, MonadVulkan env m, HasLogFunc env, MonadThrow m, MonadResource m) => Queues CommandPool -> Config -> m Font
- Engine.UI.Message: observe :: (HasVulkan env, HasOutput source, GetOutput source ~ Vector InstanceAttrs) => source -> Observer -> RIO env ()
+ Engine.UI.Message: observe :: (MonadVulkan env m, HasOutput source, GetOutput source ~ Vector InstanceAttrs) => source -> Observer -> m ()
- Engine.UI.Message: spawn :: (HasOutput box, GetOutput box ~ Box, HasOutput input, GetOutput input ~ Input) => box -> input -> RIO env Process
+ Engine.UI.Message: spawn :: (MonadResource m, MonadUnliftIO m, HasOutput box, GetOutput box ~ Box, HasOutput input, GetOutput input ~ Input) => box -> input -> m Process
- Engine.UI.Message: spawnFromR :: (MonadResource (RIO env), HasOutput box, GetOutput box ~ Box, HasOutput source) => box -> source -> (GetOutput source -> Input) -> RIO env (ReleaseKey, ReleaseKey, Process)
+ Engine.UI.Message: spawnFromR :: (MonadResource m, MonadUnliftIO m, HasOutput box, GetOutput box ~ Box, HasOutput source) => box -> source -> (GetOutput source -> Input) -> m Process
- Render.Basic: Pipelines :: SampleCountFlagBits -> Tagged Scene DsBindings -> Tagged '[Scene] DescriptorSetLayout -> Tagged Sun DsBindings -> Tagged '[Sun] DescriptorSetLayout -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> PipelinesF (f :: Type -> Type)
+ Render.Basic: Pipelines :: SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> Tagged '[Scene] DescriptorSetLayout -> Tagged Sun DsLayoutBindings -> Tagged '[Sun] DescriptorSetLayout -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> (f ^ Pipeline) -> PipelinesF (f :: Type -> Type)
- Render.Basic: [$sel:pSceneBinds:Pipelines] :: PipelinesF (f :: Type -> Type) -> Tagged Scene DsBindings
+ Render.Basic: [$sel:pSceneBinds:Pipelines] :: PipelinesF (f :: Type -> Type) -> Tagged Scene DsLayoutBindings
- Render.Basic: [$sel:pShadowBinds:Pipelines] :: PipelinesF (f :: Type -> Type) -> Tagged Sun DsBindings
+ Render.Basic: [$sel:pShadowBinds:Pipelines] :: PipelinesF (f :: Type -> Type) -> Tagged Sun DsLayoutBindings
- Render.Basic: allocatePipelines :: Tagged Scene DsBindings -> SampleCountFlagBits -> RenderPasses -> ResourceT (StageRIO st) Pipelines
+ Render.Basic: allocatePipelines :: Tagged Scene DsLayoutBindings -> SampleCountFlagBits -> RenderPasses -> ResourceT (StageRIO st) Pipelines
- Render.Basic: allocateWorkers :: Tagged Scene DsBindings -> SampleCountFlagBits -> RenderPasses -> ResourceT (StageRIO st) PipelineWorkers
+ Render.Basic: allocateWorkers :: Tagged Scene DsLayoutBindings -> SampleCountFlagBits -> RenderPasses -> ResourceT (StageRIO st) PipelineWorkers
- Render.Debug.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => Mode -> SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Debug.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => Mode -> SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Debug.Pipeline: config :: Mode -> Tagged Scene DsBindings -> Config
+ Render.Debug.Pipeline: config :: Mode -> Tagged Scene DsLayoutBindings -> Config
- Render.Debug.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Debug.Pipeline: type Pipeline = Pipeline '[Scene] Vertex Attrs
- Render.DepthOnly.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.DepthOnly.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.DepthOnly.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.DepthOnly.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.DepthOnly.Pipeline: type Pipeline = Pipeline '[Scene] () Transform
+ Render.DepthOnly.Pipeline: type Pipeline = Pipeline '[Scene] (Vertex3d ()) Transform
- Render.DescSets.Set0: allocate :: (Traversable textures, Traversable cubes, MonadVulkan env m) => Tagged '[Scene] DescriptorSetLayout -> textures (Texture Flat) -> cubes (Texture CubeMap) -> Maybe (Allocated 'Coherent Sun) -> ("shadow maps" ::: Vector ImageView) -> Maybe (Allocated 'Coherent Material) -> ResourceT m (FrameResource '[Scene])
+ Render.DescSets.Set0: allocate :: (Traversable textures, Traversable cubes, MonadVulkan env m, MonadResource m) => Tagged '[Scene] DescriptorSetLayout -> textures (Texture Flat) -> cubes (Texture CubeMap) -> Maybe (Allocated 'Coherent Sun) -> ("shadow maps" ::: Vector ImageView) -> Maybe (Allocated 'Coherent Material) -> ResourceT m (FrameResource '[Scene])
- Render.DescSets.Set0: allocateEmpty :: MonadVulkan env m => Tagged '[Scene] DescriptorSetLayout -> ResourceT m (FrameResource '[Scene])
+ Render.DescSets.Set0: allocateEmpty :: (MonadVulkan env m, MonadResource m) => Tagged '[Scene] DescriptorSetLayout -> ResourceT m (FrameResource '[Scene])
- Render.DescSets.Set0: mkBindings :: (Foldable samplers, Foldable textures, Foldable cubemaps) => samplers Sampler -> textures a -> cubemaps b -> Word32 -> Tagged Scene DsBindings
+ Render.DescSets.Set0: mkBindings :: (Foldable samplers, Foldable textures, Foldable cubemaps) => samplers Sampler -> textures a -> cubemaps b -> Word32 -> Tagged Scene DsLayoutBindings
- Render.DescSets.Sun: set0 :: Tagged Sun DsBindings
+ Render.DescSets.Sun: set0 :: Tagged Sun DsLayoutBindings
- Render.DescSets.Sun: spawn1 :: MonadUnliftIO m => SunInput -> m Process
+ Render.DescSets.Sun: spawn1 :: (MonadResource m, MonadUnliftIO m) => SunInput -> m Process
- Render.Font.EvanwSdf.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Font.EvanwSdf.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Font.EvanwSdf.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Font.EvanwSdf.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Colored.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Lit.Colored.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Lit.Colored.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Lit.Colored.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Lit.Colored.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Lit.Colored.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Colored.Pipeline: configBlend :: Tagged Scene DsBindings -> Config
+ Render.Lit.Colored.Pipeline: configBlend :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Colored.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Lit.Colored.Pipeline: type Pipeline = Pipeline '[Scene] Vertex InstanceAttrs
- Render.Lit.Material.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Lit.Material.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Lit.Material.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Lit.Material.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Lit.Material.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Lit.Material.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Material.Pipeline: configBlend :: Tagged Scene DsBindings -> Config
+ Render.Lit.Material.Pipeline: configBlend :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Material.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Lit.Material.Pipeline: type Pipeline = Pipeline '[Scene] Vertex InstanceAttrs
- Render.Lit.Textured.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Lit.Textured.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Lit.Textured.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Lit.Textured.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Lit.Textured.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Lit.Textured.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Textured.Pipeline: configBlend :: Tagged Scene DsBindings -> Config
+ Render.Lit.Textured.Pipeline: configBlend :: Tagged Scene DsLayoutBindings -> Config
- Render.Lit.Textured.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Lit.Textured.Pipeline: type Pipeline = Pipeline '[Scene] Vertex Attrs
- Render.ShadowMap.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => Tagged Sun DsBindings -> renderpass -> Settings -> ResourceT (RIO env) Pipeline
+ Render.ShadowMap.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => Tagged Sun DsLayoutBindings -> renderpass -> Settings -> ResourceT (RIO env) Pipeline
- Render.ShadowMap.Pipeline: config :: Tagged Sun DsBindings -> Settings -> Config
+ Render.ShadowMap.Pipeline: config :: Tagged Sun DsLayoutBindings -> Settings -> Config
- Render.ShadowMap.Pipeline: type Pipeline = Pipeline '[Sun] () Transform
+ Render.ShadowMap.Pipeline: type Pipeline = Pipeline '[Sun] (Vertex3d ()) Transform
- Render.Skybox.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Skybox.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Skybox.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Skybox.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.Colored.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => Bool -> SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.Colored.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => Bool -> SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.Colored.Pipeline: allocateWireframe :: (HasVulkan env, HasRenderPass renderpass) => Bool -> SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.Colored.Pipeline: allocateWireframe :: (HasVulkan env, HasRenderPass renderpass) => Bool -> SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.Colored.Pipeline: config :: Bool -> Tagged Scene DsBindings -> Config
+ Render.Unlit.Colored.Pipeline: config :: Bool -> Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.Colored.Pipeline: configWireframe :: Bool -> Tagged Scene DsBindings -> Config
+ Render.Unlit.Colored.Pipeline: configWireframe :: Bool -> Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.Colored.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Unlit.Colored.Pipeline: type Pipeline = Pipeline '[Scene] Vertex InstanceAttrs
- Render.Unlit.Sprite.Model: InstanceAttrs :: Vec4 -> Vec4 -> Vec4 -> Vec4 -> Int32 -> Int32 -> UVec2 -> InstanceAttrs
+ Render.Unlit.Sprite.Model: InstanceAttrs :: Vec4 -> Vec4 -> Vec4 -> Vec4 -> Vec4 -> UVec2 -> Int32 -> Int32 -> InstanceAttrs
- Render.Unlit.Sprite.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Maybe Float -> Bool -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.Sprite.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Maybe Float -> Bool -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.Sprite.Pipeline: config :: Maybe Float -> Bool -> Tagged Scene DsBindings -> Config
+ Render.Unlit.Sprite.Pipeline: config :: Maybe Float -> Bool -> Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.Textured.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.Textured.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.Textured.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.Textured.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.Textured.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Unlit.Textured.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.Textured.Pipeline: configBlend :: Tagged Scene DsBindings -> Config
+ Render.Unlit.Textured.Pipeline: configBlend :: Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.Textured.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Unlit.Textured.Pipeline: type Pipeline = Pipeline '[Scene] Vertex Attrs
- Render.Unlit.TileMap.Model: TileMapParams :: IVec4 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> TileMapParams
+ Render.Unlit.TileMap.Model: TileMapParams :: IVec4 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> Vec2 -> TileMapParams
- Render.Unlit.TileMap.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.TileMap.Pipeline: allocate :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.TileMap.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsBindings -> renderpass -> ResourceT (RIO env) Pipeline
+ Render.Unlit.TileMap.Pipeline: allocateBlend :: (HasVulkan env, HasRenderPass renderpass) => SampleCountFlagBits -> Tagged Scene DsLayoutBindings -> renderpass -> ResourceT (RIO env) Pipeline
- Render.Unlit.TileMap.Pipeline: config :: Tagged Scene DsBindings -> Config
+ Render.Unlit.TileMap.Pipeline: config :: Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.TileMap.Pipeline: configBlend :: Tagged Scene DsBindings -> Config
+ Render.Unlit.TileMap.Pipeline: configBlend :: Tagged Scene DsLayoutBindings -> Config
- Render.Unlit.TileMap.Pipeline: type Pipeline = Pipeline '[Scene] VertexAttrs InstanceAttrs
+ Render.Unlit.TileMap.Pipeline: type Pipeline = Pipeline '[Scene] Vertex Attrs
- Stage.Loader.Scene: spawn :: (MonadUnliftIO m, HasOutput projection, GetOutput projection ~ Projection 'Orthographic) => projection -> m Process
+ Stage.Loader.Scene: spawn :: (MonadResource m, MonadUnliftIO m, HasOutput projection, GetOutput projection ~ Projection 'Orthographic) => projection -> m Process
- Stage.Loader.UI: Observer :: [Observer] -> ObserverIO (InstanceBuffers 'Coherent 'Coherent) -> ObserverIO (InstanceBuffers 'Coherent 'Coherent) -> Observer
+ Stage.Loader.UI: Observer :: [Observer] -> ObserverCoherent -> ObserverCoherent -> Observer
- Stage.Loader.UI: UI :: Process -> Process -> Var Input -> Process -> Merge StorableAttrs -> Merge StorableAttrs -> Model 'Staged -> UI
+ Stage.Loader.UI: UI :: Process -> Process -> Var Input -> Process -> Merge Stores -> Merge Stores -> Model 'Staged -> UI
- Stage.Loader.UI: [$sel:background:Observer] :: Observer -> ObserverIO (InstanceBuffers 'Coherent 'Coherent)
+ Stage.Loader.UI: [$sel:background:Observer] :: Observer -> ObserverCoherent
- Stage.Loader.UI: [$sel:backgroundP:UI] :: UI -> Merge StorableAttrs
+ Stage.Loader.UI: [$sel:backgroundP:UI] :: UI -> Merge Stores
- Stage.Loader.UI: [$sel:spinner:Observer] :: Observer -> ObserverIO (InstanceBuffers 'Coherent 'Coherent)
+ Stage.Loader.UI: [$sel:spinner:Observer] :: Observer -> ObserverCoherent
- Stage.Loader.UI: [$sel:spinnerP:UI] :: UI -> Merge StorableAttrs
+ Stage.Loader.UI: [$sel:spinnerP:UI] :: UI -> Merge Stores

Files

ChangeLog.md view
@@ -1,5 +1,16 @@ # Changelog for keid-render-basic +## 0.1.8.0++- Embedded texture resources now using KTX2.+- Fixed grid artifacts in TileMap shader.+- Added multiscattering term for `Lit` pipelines, plugging an energy loss in metals.+- Added Unlit Line2D pipeline for batches of extra-fancy lines with rounded corners and segments.+- Fixed missing margins in sprite model generation from an atlas.+- Sprite LOD fixed to 0 to prevent issues with packed tilesets.+- Added tileset borders and offset.+- Changed TileMap pipeline model to use Tiled-style mod flags in A-channel.+ ## 0.1.7.0  - Pipelines updated to use `Engine.Vulkan.Pipeline.Graphics`.
+ embed/cubemaps/black.ktx2 view

binary file changed (absent → 265 bytes)

+ embed/textures/black.ktx2 view

binary file changed (absent → 278 bytes)

+ embed/textures/flat.ktx2 view

binary file changed (absent → 329 bytes)

+ embed/textures/ibl_brdf_lut.ktx2 view

binary file changed (absent → 193434 bytes)

keid-render-basic.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.4.+-- This file has been generated from package.yaml by hpack version 0.35.1. -- -- see: https://github.com/sol/hpack  name:           keid-render-basic-version:        0.1.7.0+version:        0.1.8.0 synopsis:       Basic rendering programs for Keid engine. category:       Game Engine homepage:       https://keid.haskell-game.dev@@ -20,9 +20,13 @@     ChangeLog.md data-files:     embed/cubemaps/black.ktx.zst+    embed/cubemaps/black.ktx2     embed/textures/black.ktx.zst+    embed/textures/black.ktx2     embed/textures/flat.ktx.zst+    embed/textures/flat.ktx2     embed/textures/ibl_brdf_lut.ktx.zst+    embed/textures/ibl_brdf_lut.ktx2  source-repository head   type: git@@ -60,6 +64,7 @@       Render.Lit.Textured.Code       Render.Lit.Textured.Model       Render.Lit.Textured.Pipeline+      Render.Pass.Compose       Render.ShadowMap.Code       Render.ShadowMap.Pipeline       Render.ShadowMap.RenderPass@@ -68,6 +73,10 @@       Render.Unlit.Colored.Code       Render.Unlit.Colored.Model       Render.Unlit.Colored.Pipeline+      Render.Unlit.Line2d.Code+      Render.Unlit.Line2d.Draw+      Render.Unlit.Line2d.Model+      Render.Unlit.Line2d.Pipeline       Render.Unlit.Sprite.Code       Render.Unlit.Sprite.Model       Render.Unlit.Sprite.Pipeline@@ -155,7 +164,7 @@     , derive-storable-plugin     , file-embed >=0.0.10     , geomancy-    , keid-core >=0.1.7.0+    , keid-core >=0.1.8.0     , keid-geometry     , neat-interpolation     , resourcet
src/Engine/UI/Message.hs view
@@ -19,11 +19,12 @@ import Data.Vector.Storable qualified as Storable import Geomancy (Vec4) import Geomancy.Vec4 qualified as Vec4+import UnliftIO.Resource (MonadResource) import Vulkan.Core10 qualified as Vk  import Engine.Types qualified as Engine import Engine.UI.Layout qualified as Layout-import Engine.Vulkan.Types (HasVulkan)+import Engine.Vulkan.Types (MonadVulkan) import Engine.Worker qualified as Worker import Render.Font.EvanwSdf.Model qualified as EvanwSdf import Render.Samplers qualified as Samplers@@ -33,15 +34,21 @@ type Process = Worker.Merge (Storable.Vector EvanwSdf.InstanceAttrs)  spawn-  :: ( Worker.HasOutput box+  :: ( MonadResource m+     , MonadUnliftIO m+     , Worker.HasOutput box      , Worker.GetOutput box ~ Layout.Box      , Worker.HasOutput input      , Worker.GetOutput input ~ Input-     ) => box -> input -> RIO env Process+     )+  => box+  -> input+  -> m Process spawn = Worker.spawnMerge2 mkAttrs  spawnFromR-  :: ( Resource.MonadResource (RIO env)+  :: ( MonadResource m+     , MonadUnliftIO m      , Worker.HasOutput box      , Worker.GetOutput box ~ Layout.Box      , Worker.HasOutput source@@ -49,14 +56,10 @@   => box   -> source   -> (Worker.GetOutput source -> Input)-  -> RIO env (Resource.ReleaseKey, Resource.ReleaseKey, Process)+  -> m Process spawnFromR parent inputProc mkMessage = do   inputP <- Worker.spawnMerge1 mkMessage inputProc-  messageP <- spawn parent inputP--  (,,messageP)-    <$> Worker.register inputP-    <*> Worker.register messageP+  spawn parent inputP  data Input = Input   { inputText         :: Text@@ -105,25 +108,23 @@  newObserver :: Int -> ResourceT (Engine.StageRIO st) Observer newObserver initialSize = do-  context <- ask--  messageData <- Buffer.createCoherent context Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT initialSize mempty+  messageData <- Buffer.createCoherent (Just "Message") Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT initialSize mempty   observer <- Worker.newObserverIO messageData +  context <- ask   void $! Resource.register do     vData <- readIORef observer-    Buffer.destroyAll context vData+    traverse_ (Buffer.destroy context) vData    pure observer  observe-  :: ( HasVulkan env+  :: ( MonadVulkan env m      , Worker.HasOutput source      , Worker.GetOutput source ~ Storable.Vector EvanwSdf.InstanceAttrs      )   => source-  -> Observer -> RIO env ()-observe messageP observer = do-  context <- ask-  Worker.observeIO_ messageP observer $-    Buffer.updateCoherentResize_ context+  -> Observer+  -> m ()+observe messageP observer =+  Worker.observeIO_ messageP observer Buffer.updateCoherentResize_
src/Global/Resource/CubeMap/Base.hs view
@@ -4,25 +4,29 @@  module Global.Resource.CubeMap.Base   ( Collection(..)+  , Textures   , sources   ) where  import RIO  import GHC.Generics (Generic1)+import Resource.Collection (Generically1(..)) import Resource.Source (Source) import Resource.Source qualified as Source-import Resource.Collection (Generically1(..))+import Resource.Texture (Texture, CubeMap)  import Global.Resource.CubeMap.Base.Paths qualified as Paths  data Collection a = Collection-  { black        :: a+  { black :: a   }   deriving stock (Show, Functor, Foldable, Traversable, Generic1)   deriving Applicative via Generically1 Collection +type Textures = Collection (Texture CubeMap)+ sources :: Collection Source sources = Collection-  { black        = $(Source.embedFile Paths.BLACK_KTX_ZST)+  { black = $(Source.embedFile Paths.BLACK_KTX2)   }
src/Global/Resource/Texture/Base.hs view
@@ -4,6 +4,7 @@  module Global.Resource.Texture.Base   ( Collection(..)+  , Textures   , sources   ) where @@ -13,6 +14,7 @@ import Resource.Collection (Generically1(..)) import Resource.Source (Source) import Resource.Source qualified as Source+import Resource.Texture (Texture, Flat)  import Global.Resource.Texture.Base.Paths qualified as Paths @@ -24,9 +26,11 @@   deriving stock (Show, Functor, Foldable, Traversable, Generic1)   deriving Applicative via Generically1 Collection +type Textures = Collection (Texture Flat)+ sources :: Collection Source sources = Collection-  { black        = $(Source.embedFile Paths.BLACK_KTX_ZST)-  , flat         = $(Source.embedFile Paths.FLAT_KTX_ZST)-  , ibl_brdf_lut = $(Source.embedFile Paths.IBL_BRDF_LUT_KTX_ZST)+  { black        = $(Source.embedFile Paths.BLACK_KTX2)+  , flat         = $(Source.embedFile Paths.FLAT_KTX2)+  , ibl_brdf_lut = $(Source.embedFile Paths.IBL_BRDF_LUT_KTX2)   }
src/Render/Basic.hs view
@@ -28,9 +28,7 @@ import Engine.Vulkan.Pipeline.Graphics qualified as Graphics import Engine.Vulkan.Shader qualified as Shader import Engine.Vulkan.Swapchain qualified as Swapchain-import Engine.Vulkan.Types (DsBindings, HasSwapchain, HasVulkan, RenderPass(..))-import Engine.Worker qualified as Worker-import Resource.Region qualified as Region+import Engine.Vulkan.Types (DsLayoutBindings, HasSwapchain, HasVulkan, RenderPass(..))  -- keid-render-basic @@ -52,6 +50,7 @@ import Render.ShadowMap.RenderPass qualified as ShadowPass import Render.Skybox.Pipeline qualified as Skybox import Render.Unlit.Colored.Pipeline qualified as UnlitColored+import Render.Unlit.Line2d.Pipeline qualified as UnlitLine2d import Render.Unlit.Sprite.Pipeline qualified as UnlitSprite import Render.Unlit.Textured.Pipeline qualified as UnlitTextured import Render.Unlit.TileMap.Pipeline qualified as UnlitTileMap@@ -130,10 +129,10 @@  data PipelinesF (f :: Type -> Type) = Pipelines   { pMSAA       :: Vk.SampleCountFlagBits-  , pSceneBinds :: Tagged Scene DsBindings+  , pSceneBinds :: Tagged Scene DsLayoutBindings   , pSceneLayout :: Tagged '[Scene] Vk.DescriptorSetLayout -  , pShadowBinds :: Tagged Sun DsBindings+  , pShadowBinds :: Tagged Sun DsLayoutBindings   , pShadowLayout :: Tagged '[Sun] Vk.DescriptorSetLayout    , pEvanwSdf :: f ^ EvanwSdf.Pipeline@@ -157,6 +156,9 @@   , pUnlitTextured       :: f ^ UnlitTextured.Pipeline   , pUnlitTexturedBlend  :: f ^ UnlitTextured.Pipeline +  , pLine2d        :: f ^ UnlitLine2d.Pipeline+  , pLine2dNoDepth :: f ^ UnlitLine2d.Pipeline+   , pSprite              :: f ^ UnlitSprite.Pipeline   , pSpriteOutline       :: f ^ UnlitSprite.Pipeline   , pTileMap             :: f ^ UnlitTileMap.Pipeline@@ -173,8 +175,7 @@   -> RenderPasses   -> ResourceT (StageRIO st) Pipelines allocatePipelines_ swapchain renderpasses = do-  (_, samplers) <- Samplers.allocate-    (Swapchain.getAnisotropy swapchain)+  samplers <- Samplers.allocate (Swapchain.getAnisotropy swapchain)    allocatePipelines     (Scene.mkBindings samplers Nothing Nothing 0)@@ -182,7 +183,7 @@     renderpasses  allocatePipelines-  :: Tagged Scene DsBindings+  :: Tagged Scene DsLayoutBindings   -> Vk.SampleCountFlagBits   -> RenderPasses   -> ResourceT (StageRIO st) Pipelines@@ -203,6 +204,8 @@   pLitTextured      <- LitTextured.allocate pMSAA pSceneBinds rpForwardMsaa   pLitTexturedBlend <- LitTextured.allocateBlend pMSAA pSceneBinds rpForwardMsaa +  pLine2d              <- UnlitLine2d.allocate True pMSAA pSceneBinds rpForwardMsaa+  pLine2dNoDepth       <- UnlitLine2d.allocate False pMSAA pSceneBinds rpForwardMsaa   pSprite              <- UnlitSprite.allocate pMSAA Nothing False pSceneBinds rpForwardMsaa   pSpriteOutline       <- UnlitSprite.allocate pMSAA Nothing True pSceneBinds rpForwardMsaa   pTileMap             <- UnlitTileMap.allocate pMSAA pSceneBinds rpForwardMsaa@@ -235,7 +238,7 @@   pure Pipelines{..}  allocateWorkers-  :: Tagged Scene DsBindings+  :: Tagged Scene DsLayoutBindings   -> Vk.SampleCountFlagBits   -> RenderPasses   -> ResourceT (StageRIO st) PipelineWorkers@@ -248,7 +251,7 @@         (shaderDir </> "evanw-sdf" <.> "vert" <.> "spv")         (shaderDir </> "evanw-sdf" <.> "frag" <.> "spv") -  evanwSdfWorker <- Region.local . Worker.registered $+  evanwSdfWorker <-     External.spawnReflect "evanw-sdf" evanwSdfFiles \(stageCode, reflect) ->       (EvanwSdf.config sceneBinds)         { Graphics.cStages = stageCode@@ -261,7 +264,7 @@         (shaderDir </> "skybox" <.> "vert" <.> "spv")         (shaderDir </> "skybox" <.> "frag" <.> "spv") -  skyboxWorker <- Region.local . Worker.registered $+  skyboxWorker <-     External.spawnReflect "skybox" skyboxFiles \(stageCode, reflect) ->       (Skybox.config sceneBinds)         { Graphics.cStages = stageCode@@ -274,21 +277,21 @@         (shaderDir </> "debug" <.> "vert" <.> "spv")         (shaderDir </> "debug" <.> "frag" <.> "spv") -  debugUVWorker <- Region.local . Worker.registered $+  debugUVWorker <-     External.spawnReflect "debug-uv" debugFiles \(stageCode, reflect) ->       (Debug.config Debug.UV sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  debugTextureWorker <- Region.local . Worker.registered $+  debugTextureWorker <-     External.spawnReflect "debug-texture" debugFiles \(stageCode, reflect) ->       (Debug.config Debug.Texture sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  debugShadowWorker <- Region.local . Worker.registered $+  debugShadowWorker <-     External.spawnReflect "debug-shadow" debugFiles \(stageCode, reflect) ->       (Debug.config (Debug.Shadow 1) sceneBinds)         { Graphics.cStages = stageCode@@ -299,7 +302,7 @@     depthOnlyFiles = Graphics.vertexOnly       (shaderDir </> "depth-only" <.> "vert" <.> "spv") -  depthOnlyWorker <- Region.local . Worker.registered $+  depthOnlyWorker <-     External.spawnReflect "debug" depthOnlyFiles \(stageCode, reflect) ->       (DepthOnly.config sceneBinds)         { Graphics.cStages = stageCode@@ -312,14 +315,14 @@         (shaderDir </> "lit-colored" <.> "vert" <.> "spv")         (shaderDir </> "lit-colored" <.> "frag" <.> "spv") -  litColoredWorker <- Region.local . Worker.registered $+  litColoredWorker <-     External.spawnReflect "lit-colored" litColoredFiles \(stageCode, reflect) ->       (LitColored.config sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  litColoredBlendWorker <- Region.local . Worker.registered $+  litColoredBlendWorker <-     External.spawnReflect "lit-colored-blend" litColoredFiles \(stageCode, reflect) ->       (LitColored.configBlend sceneBinds)         { Graphics.cStages = stageCode@@ -332,14 +335,14 @@         (shaderDir </> "lit-material" <.> "vert" <.> "spv")         (shaderDir </> "lit-material" <.> "frag" <.> "spv") -  litMaterialWorker <- Region.local . Worker.registered $+  litMaterialWorker <-     External.spawnReflect "lit-material" litMaterialFiles \(stageCode, reflect) ->       (LitMaterial.config sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  litMaterialBlendWorker <- Region.local . Worker.registered $+  litMaterialBlendWorker <-     External.spawnReflect "lit-material-blend" litMaterialFiles \(stageCode, reflect) ->       (LitMaterial.configBlend sceneBinds)         { Graphics.cStages = stageCode@@ -352,14 +355,14 @@         (shaderDir </> "lit-textured" <.> "vert" <.> "spv")         (shaderDir </> "lit-textured" <.> "frag" <.> "spv") -  litTexturedWorker <- Region.local . Worker.registered $+  litTexturedWorker <-     External.spawnReflect "lit-textured" litTexturedFiles \(stageCode, reflect) ->       (LitTextured.config sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  litTexturedBlendWorker <- Region.local . Worker.registered $+  litTexturedBlendWorker <-     External.spawnReflect "lit-textured-blend" litTexturedFiles \(stageCode, reflect) ->       (LitTextured.configBlend sceneBinds)         { Graphics.cStages = stageCode@@ -367,19 +370,39 @@         }    let+    line2dFiles =+      Graphics.basicStages+        (shaderDir </> "line-2d" <.> "vert" <.> "spv")+        (shaderDir </> "line-2d" <.> "frag" <.> "spv")++  line2dWorker <-+    External.spawnReflect "unlit-colored" line2dFiles \(stageCode, reflect) ->+      (UnlitLine2d.config True sceneBinds)+        { Graphics.cStages = stageCode+        , Graphics.cReflect = Just reflect+        }++  line2dNoDepthWorker <-+    External.spawnReflect "unlit-colored-nodepth" line2dFiles \(stageCode, reflect) ->+      (UnlitLine2d.config False sceneBinds)+        { Graphics.cStages = stageCode+        , Graphics.cReflect = Just reflect+        }++  let     unlitColoredFiles =       Graphics.basicStages         (shaderDir </> "unlit-colored" <.> "vert" <.> "spv")         (shaderDir </> "unlit-colored" <.> "frag" <.> "spv") -  unlitColoredWorker <- Region.local . Worker.registered $+  unlitColoredWorker <-     External.spawnReflect "unlit-colored" unlitColoredFiles \(stageCode, reflect) ->       (UnlitColored.config True sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  unlitColoredNoDepthWorker <- Region.local . Worker.registered $+  unlitColoredNoDepthWorker <-     External.spawnReflect "unlit-colored-nodepth" unlitColoredFiles \(stageCode, reflect) ->       (UnlitColored.config False sceneBinds)         { Graphics.cStages = stageCode@@ -392,14 +415,14 @@         (shaderDir </> "unlit-textured" <.> "vert" <.> "spv")         (shaderDir </> "unlit-textured" <.> "frag" <.> "spv") -  unlitTexturedWorker <- Region.local . Worker.registered $+  unlitTexturedWorker <-     External.spawnReflect "unlit-textured" unlitTexturedFiles \(stageCode, reflect) ->       (UnlitTextured.config sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  unlitTexturedBlendWorker <- Region.local . Worker.registered $+  unlitTexturedBlendWorker <-     External.spawnReflect "unlit-textured" unlitTexturedFiles \(stageCode, reflect) ->       (UnlitTextured.configBlend sceneBinds)         { Graphics.cStages = stageCode@@ -412,14 +435,14 @@         (shaderDir </> "sprite" <.> "vert" <.> "spv")         (shaderDir </> "sprite" <.> "frag" <.> "spv") -  spriteWorker <- Region.local . Worker.registered $+  spriteWorker <-     External.spawnReflect "sprite" spriteFiles \(stageCode, reflect) ->       (UnlitSprite.config Nothing False sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  spriteOutlineWorker <- Region.local . Worker.registered $+  spriteOutlineWorker <-     External.spawnReflect "sprite" spriteFiles \(stageCode, reflect) ->       (UnlitSprite.config Nothing True sceneBinds)         { Graphics.cStages = stageCode@@ -432,28 +455,28 @@         (shaderDir </> "tilemap" <.> "vert" <.> "spv")         (shaderDir </> "tilemap" <.> "frag" <.> "spv") -  tileMapWorker <- Region.local . Worker.registered $+  tileMapWorker <-     External.spawnReflect "tilemap" tileMapFiles \(stageCode, reflect) ->       (UnlitTileMap.config sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  tileMapBlendWorker <- Region.local . Worker.registered $+  tileMapBlendWorker <-     External.spawnReflect "tilemap" tileMapFiles \(stageCode, reflect) ->       (UnlitTileMap.configBlend sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  wireframeWorker <- Region.local . Worker.registered $+  wireframeWorker <-     External.spawnReflect "wireframe" unlitColoredFiles \(stageCode, reflect) ->       (UnlitColored.configWireframe True sceneBinds)         { Graphics.cStages = stageCode         , Graphics.cReflect = Just reflect         } -  wireframeNoDepthWorker <- Region.local . Worker.registered $+  wireframeNoDepthWorker <-     External.spawnReflect "wireframe-nodepth" unlitColoredFiles \(stageCode, reflect) ->       (UnlitColored.configWireframe False sceneBinds)         { Graphics.cStages = stageCode@@ -465,7 +488,7 @@       Graphics.vertexOnly         (shaderDir </> "shadow-cast" <.> "vert" <.> "spv") -  shadowCastWorker <- Region.local . Worker.registered $+  shadowCastWorker <-     External.spawnReflect "shadow-cast" shadowCastFiles \(stageCode, reflect) ->       (ShadowPipe.config (pShadowBinds builtin) ShadowPipe.defaults)         { Graphics.cStages = stageCode@@ -485,6 +508,8 @@     , pLitMaterialBlend = litMaterialBlendWorker     , pLitTextured = litTexturedWorker     , pLitTexturedBlend = litTexturedBlendWorker+    , pLine2d = line2dWorker+    , pLine2dNoDepth = line2dNoDepthWorker     , pUnlitColored = unlitColoredWorker     , pUnlitColoredNoDepth = unlitColoredNoDepthWorker     , pUnlitTextured = unlitTexturedWorker@@ -563,6 +588,16 @@     pMSAA     pLitTexturedBlend +  line2dExt <- External.newObserverGraphics+    forward+    pMSAA+    pLine2d++  line2dNoDepthExt <- External.newObserverGraphics+    forward+    pMSAA+    pLine2dNoDepth+   unlitColoredExt <- External.newObserverGraphics     forward     pMSAA@@ -631,6 +666,8 @@     , pLitMaterialBlend = litMaterialBlendExt     , pLitTextured = litTexturedExt     , pLitTexturedBlend = litTexturedBlendExt+    , pLine2d = line2dExt+    , pLine2dNoDepth = line2dNoDepthExt     , pUnlitColored = unlitColoredExt     , pUnlitColoredNoDepth = unlitColoredNoDepthExt     , pUnlitTextured = unlitTexturedExt@@ -734,6 +771,7 @@   , ("lit-textured", LitTextured.stageCode)   , ("unlit-colored", UnlitColored.stageCode)   , ("unlit-textured", UnlitTextured.stageCode)+  , ("line-2d", UnlitLine2d.stageCode)   , ("sprite", UnlitSprite.stageCode)   , ("tilemap", UnlitTileMap.stageCode)   , ("shadow-cast", ShadowPipe.stageCode)
src/Render/Code/Lit.hs view
@@ -177,22 +177,32 @@       ).rgb;     } +    // BUG: raw NdotV is sometimes negative, like we're looking at the back side.+    // Cubists would appreciate, but IBL term gives that edge and the dot artifacts.+    float NdotV = clamp(dot(normal, rayDir), 0.0, 1.0);+     // Specular reflectance     vec2 ibl = texture(       sampler2D(         textures[BRDF_LUT],         samplers[BRDF_LUT_SAMPLER]       ),-      vec2(roughness, max(dot(normal, rayDir), 0.0))+      vec2(NdotV, roughness),+      0.0     ).rg;-    vec3 F = F_SchlickR(max(dot(normal, rayDir), 0.0), F0, roughness);-    vec3 specular = nonOcclusion * reflection * (F * ibl.x + ibl.y); -    vec3 kD = (1.0 - F) * (1.0 - metallic);+    // Single scattering+    vec3 F = F_SchlickR(NdotV, F0, roughness);+    vec3 FssEss = F * ibl.x + ibl.y;+    vec3 specular = nonOcclusion * reflection * FssEss; -    // Diffuse based on irradiance-    vec3 diffuseI = nonOcclusion * irradiance * albedo;-    vec3 ambient = kD * diffuseI + specular;+    // Multiple scattering+    float Ems = 1.0 - (ibl.x + ibl.y);+    vec3 F_avg = F0 + (1.0 - F0) / 21.0;+    vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);++    vec3 kD = albedo * (1.0 - FssEss - FmsEms);+    vec3 ambient = specular + (FmsEms + kD) * irradiance;      // Combine with ambient     vec3 color = Lo + ambient;
src/Render/Debug/Code.hs view
@@ -62,8 +62,8 @@      layout(location = 0) out vec4 oColor; -    layout (constant_id=0) const uint mode = 0;-    layout (constant_id=1) const uint shadow_mask = 0;+    layout(constant_id=0) const uint mode = 0;+    layout(constant_id=1) const uint shadow_mask = 0;      void main() {       vec4 texel = vec4(0);
src/Render/Debug/Model.hs view
@@ -1,218 +1,106 @@+{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedRecordDot #-}++{- XXX: Copy-pasta from Unlit.Textured.Model.++Attept with newtypes ended up too disruptive.+Perhaps a better solution would be adding unique tag parameter to Pipeline type.+-}+ module Render.Debug.Model   ( Model+  , Vertex   , VertexAttrs-  , vkVertexAttrs -  , InstanceAttrs(..)-  , instanceAttrs--  , StorableAttrs-  , storableAttrs1+  , AttrsF(..)+  , Attrs+  , attrs -  , InstanceBuffers(..)+  , Stores+  , stores1+  , Buffers    , TextureParams(..)-  , vkInstanceTexture -    -- TODO: extract and merge with UnlitTextured-  , allocateInstancesWith-  , allocateInstancesCoherent-  , allocateInstancesCoherent_-  , updateCoherentResize_-  , Transform+  , ObserverCoherent   ) where  import RIO --import Foreign (Storable(..))-import Geomancy (Transform, Vec2, Vec4)+import Foreign.Storable.Generic (GStorable)+import Geomancy (Transform, Vec2) import Geomancy.Vec3 qualified as Vec3 import RIO.Vector.Storable qualified as Storable-import UnliftIO.Resource (MonadResource, ReleaseKey, ResourceT, allocate)-import Vulkan.Core10 qualified as Vk import Vulkan.NamedType ((:::)) import Vulkan.Zero (Zero(..)) -import Engine.Vulkan.Types (HasVulkan)+import Engine.Types (HKD)+import Engine.Vulkan.Pipeline.Graphics (HasVertexInputBindings(..), instanceFormat)+import Engine.Worker qualified as Worker+import Render.Unlit.Textured.Model (TextureParams(..)) import Resource.Buffer qualified as Buffer import Resource.Model qualified as Model+import Resource.Model.Observer qualified as Observer  type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  type VertexAttrs = "uv" ::: Vec2 -vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32_SFLOAT -- vTexCoord :: vec2-  ]---- | Data for a single element.-data InstanceAttrs = InstanceAttrs-  { textureParams :: TextureParams-  , transformMat4 :: Transform-  }--instance Zero InstanceAttrs where-  zero = InstanceAttrs-    { textureParams = zero-    , transformMat4 = mempty-    }--instanceAttrs :: Int32 -> Int32 -> [Transform] -> InstanceAttrs-instanceAttrs samplerId textureId transforms = InstanceAttrs-  { textureParams = zero-      { tpSamplerId = samplerId-      , tpTextureId = textureId-      }-  , transformMat4 = mconcat transforms+data AttrsF f = Attrs+  { params     :: HKD f TextureParams+  , transforms :: HKD f Transform   }---- | Intermediate data to be shipped.-type StorableAttrs =-  ( Storable.Vector TextureParams-  , Storable.Vector Transform-  )+  deriving (Generic) -storableAttrs1 :: Int32 -> Int32 -> [Transform] -> StorableAttrs-storableAttrs1 samplerId textureId transforms =-  ( Storable.singleton textureParams-  , Storable.singleton transformMat4-  )-  where-    InstanceAttrs{..} = instanceAttrs-      samplerId-      textureId-      transforms+type Attrs = AttrsF Identity+deriving instance Show Attrs+instance GStorable Attrs --- | GPU-bound data.-data InstanceBuffers textureStage transformStage = InstanceBuffers-  { ibTexture   :: InstanceTexture textureStage-  , ibTransform :: InstanceTransform transformStage-  }+instance HasVertexInputBindings Attrs where+  vertexInputBindings =+    [ instanceFormat @TextureParams+    , instanceFormat @Transform+    ] -type InstanceTexture stage = Buffer.Allocated stage TextureParams+type Stores = AttrsF Storable.Vector+deriving instance Show Stores -type InstanceTransform stage = Buffer.Allocated stage Transform+type Buffers = AttrsF (Buffer.Allocated 'Buffer.Coherent)+deriving instance Show Buffers+instance Observer.VertexBuffers Buffers+type ObserverCoherent = Worker.ObserverIO Buffers -instance Model.HasVertexBuffers (InstanceBuffers textureStage transformStage) where-  type VertexBuffersOf (InstanceBuffers textureStage transformStage) = InstanceAttrs+instance Observer.UpdateCoherent Buffers Stores -  {-# INLINE getVertexBuffers #-}-  getVertexBuffers InstanceBuffers{..} =-    [ Buffer.aBuffer ibTexture-    , Buffer.aBuffer ibTransform-    ]+instance Model.HasVertexBuffers Buffers where+  type VertexBuffersOf Buffers = Attrs -  {-# INLINE getInstanceCount #-}-  getInstanceCount InstanceBuffers{..} =-    min-      (Buffer.aUsed ibTexture)-      (Buffer.aUsed ibTransform)+instance Zero Attrs where+  zero = Attrs+    { params = zero+    , transforms = mempty+    } -data TextureParams = TextureParams-  { tpScale     :: Vec2-  , tpOffset    :: Vec2-  , tpGamma     :: Vec4-  , tpSamplerId :: Int32-  , tpTextureId :: Int32+attrs :: Int32 -> Int32 -> [Transform] -> Attrs+attrs samplerId textureId transforms = Attrs+  { params = zero+      { tpSamplerId = samplerId+      , tpTextureId = textureId+      }+  , transforms = mconcat transforms   }-  deriving (Show) -instance Zero TextureParams where-  zero = TextureParams-    { tpScale     = 1-    , tpOffset    = 0-    , tpGamma     = 1.0-    , tpSamplerId = minBound-    , tpTextureId = minBound+stores1 :: Int32 -> Int32 -> [Transform] -> Stores+stores1 samplerId textureId transforms =+  Attrs+    { params = Storable.singleton attrs1.params+    , transforms = Storable.singleton attrs1.transforms     }--instance Storable TextureParams where-  alignment ~_ = 4--  sizeOf ~_ = 8 + 8 + 16 + 4 + 4--  poke ptr TextureParams{..} = do-    pokeByteOff ptr  0 tpScale-    pokeByteOff ptr  8 tpOffset-    pokeByteOff ptr 16 tpGamma-    pokeByteOff ptr 32 tpSamplerId-    pokeByteOff ptr 36 tpTextureId--  peek ptr = do-    tpScale     <- peekByteOff ptr  0-    tpOffset    <- peekByteOff ptr  8-    tpGamma     <- peekByteOff ptr 16-    tpSamplerId <- peekByteOff ptr 32-    tpTextureId <- peekByteOff ptr 36-    pure TextureParams{..}--vkInstanceTexture :: [Vk.Format]-vkInstanceTexture =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureScaleOffset :: vec4-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureGamma       :: vec4-  , Vk.FORMAT_R32G32_SINT         -- iTextureIds         :: ivec2-  ]--allocateInstancesWith-  :: ( MonadResource m-     , MonadUnliftIO m-     )-  => (Vk.BufferUsageFlagBits -> Int -> Storable.Vector TextureParams -> m (InstanceTexture texture))-  -> (Vk.BufferUsageFlagBits -> Int -> Storable.Vector Transform -> m (InstanceTransform transform))-  -> (forall stage a . Buffer.Allocated stage a -> m ())-  -> [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers texture transform)-allocateInstancesWith createTextures createTransforms bufferDestroy instances = do-  ul <- askUnliftIO-  allocate (create ul) (destroy ul)   where-    textures   = Storable.fromList $ map textureParams instances-    transforms = Storable.fromList $ map transformMat4 instances-    numInstances = Storable.length textures--    create (UnliftIO ul) = ul do-      ibTexture   <- createTextures   Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances textures-      ibTransform <- createTransforms Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances transforms-      pure InstanceBuffers{..}--    destroy (UnliftIO ul) InstanceBuffers{..} = ul do-      bufferDestroy ibTexture-      bufferDestroy ibTransform--allocateInstancesCoherent-  :: ( MonadReader env m-     , HasVulkan env-     , MonadResource m-     , MonadUnliftIO m-     )-  => [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-allocateInstancesCoherent instances = do-  context <- ask-  allocateInstancesWith-    (Buffer.createCoherent context)-    (Buffer.createCoherent context)-    (Buffer.destroy context)-    instances--allocateInstancesCoherent_-  :: (HasVulkan env)-  => Int-  -> ResourceT (RIO env) (InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-allocateInstancesCoherent_ n =-  fmap snd $ allocateInstancesCoherent (replicate n zero)--updateCoherentResize_-  :: ( HasVulkan context-     , MonadUnliftIO m-     )-  => context-  -> InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent-  -> (Storable.Vector TextureParams, Storable.Vector Transform)-  -> m (InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-updateCoherentResize_ context InstanceBuffers{..} (textures, transforms) =-  InstanceBuffers-    <$> Buffer.updateCoherentResize_ context ibTexture textures-    <*> Buffer.updateCoherentResize_ context ibTransform transforms+    attrs1 = attrs+      samplerId+      textureId+      transforms
src/Render/Debug/Pipeline.hs view
@@ -16,13 +16,13 @@  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics import Engine.Vulkan.Shader qualified as Shader-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag) import Render.Debug.Code qualified as Code import Render.Debug.Model qualified as Model-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.Attrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = Mode @@ -47,26 +47,19 @@      )   => Mode   -> Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate mode multisample tset0 = do   fmap snd . Graphics.allocate Nothing multisample (config mode tset0) -config :: Mode -> Tagged Scene DsBindings -> Config+config :: Mode -> Tagged Scene DsLayoutBindings -> Config config mode (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts    = Tagged @'[Scene] [set0]   , Graphics.cStages         = stageSpirv-  , Graphics.cVertexInput    = vertexInput+  , Graphics.cVertexInput    = Graphics.vertexInput @Pipeline   , Graphics.cSpecialization = mode   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos -- vPosition-      , (Vk.VERTEX_INPUT_RATE_VERTEX,   Model.vkVertexAttrs)-      , (Vk.VERTEX_INPUT_RATE_INSTANCE, Model.vkInstanceTexture)-      , instanceTransform-      ]  stageCode :: Graphics.StageCode stageCode = Graphics.basicStages Code.vert Code.frag
src/Render/DepthOnly/Pipeline.hs view
@@ -15,14 +15,15 @@ import Data.Tagged (Tagged(..)) import Vulkan.Core10 qualified as Vk -import Geomancy (Transform) import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..))+import Geomancy (Transform) import Render.Code (compileVert) import Render.DepthOnly.Code qualified as Code-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene)+import Resource.Model (Vertex3d) -type Pipeline = Graphics.Pipeline '[Scene] () Transform+type Pipeline = Graphics.Pipeline '[Scene] (Vertex3d ()) Transform type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -31,7 +32,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 rp = do@@ -42,17 +43,12 @@     rp   pure p -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos-      , instanceTransform-      ]  stageCode  :: Graphics.StageCode stageCode = Graphics.vertexOnly Code.vert
src/Render/DescSets/Set0.hs view
@@ -1,5 +1,7 @@ {-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-} +{-# LANGUAGE OverloadedLists #-}+ module Render.DescSets.Set0   ( Scene(..)   , emptyScene@@ -11,10 +13,6 @@    , mkBindings -  -- TODO: extract to typeclass magic-  , vertexPos-  , instanceTransform-   , FrameResource(..)   , extendResourceDS @@ -30,7 +28,6 @@ import Control.Monad.Trans.Resource (ResourceT) import Control.Monad.Trans.Resource qualified as ResourceT import Data.Bits ((.|.))-import Data.ByteString.Char8 qualified as BS8 import Data.Kind (Type) import Data.Tagged (Tagged(..)) import Data.Vector qualified as Vector@@ -42,13 +39,12 @@ import Vulkan.Core12.Promoted_From_VK_EXT_descriptor_indexing qualified as Vk12 import Vulkan.CStruct.Extends (SomeStruct(..)) import Vulkan.NamedType ((:::))-import Vulkan.Utils.Debug qualified as Debug import Vulkan.Zero (Zero(..))  import Engine.Vulkan.DescSets (Bound, Extend, extendDS, withBoundDescriptorSets0) import Engine.Vulkan.Pipeline (Pipeline) import Engine.Vulkan.Pipeline qualified as Pipeline-import Engine.Vulkan.Types (DsBindings, MonadVulkan, HasVulkan(..))+import Engine.Vulkan.Types (DsLayoutBindings, MonadVulkan, HasVulkan(..)) import Engine.Worker qualified as Worker import Global.Resource.CubeMap.Base qualified as BaseCubeMap import Global.Resource.Texture.Base qualified as BaseTexture@@ -56,9 +52,11 @@ import Render.Lit.Material (Material) import Resource.Buffer qualified as Buffer import Resource.Collection qualified as Collection-import Resource.DescriptorSet qualified as DescriptorSet import Resource.Image qualified as Image+import Resource.Region qualified as Region import Resource.Texture qualified as Texture+import Resource.Vulkan.DescriptorPool qualified as DescriptorPool+import Resource.Vulkan.Named qualified as Named  -- * Set0 data @@ -109,7 +107,7 @@   -> textures a   -> cubemaps b   -> Word32-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings mkBindings samplers textures cubes shadows = Tagged   [ (set0bind0,          zero)   , (set0bind1 samplers, zero)@@ -219,29 +217,13 @@   , immutableSamplers = mempty   } -vertexPos :: (Vk.VertexInputRate, [Vk.Format])-vertexPos =-  ( Vk.VERTEX_INPUT_RATE_VERTEX-  , [ Vk.FORMAT_R32G32B32_SFLOAT -- vPosition :: vec3-    ]-  )--instanceTransform :: (Vk.VertexInputRate, [Vk.Format])-instanceTransform =-  ( Vk.VERTEX_INPUT_RATE_INSTANCE-  , [ Vk.FORMAT_R32G32B32A32_SFLOAT -- iModel :: mat4-    , Vk.FORMAT_R32G32B32A32_SFLOAT-    , Vk.FORMAT_R32G32B32A32_SFLOAT-    , Vk.FORMAT_R32G32B32A32_SFLOAT-    ]-  )- -- * Setup  allocate   :: ( Traversable textures      , Traversable cubes      , MonadVulkan env m+     , ResourceT.MonadResource m      )   => Tagged '[Scene] Vk.DescriptorSetLayout   -> textures (Texture.Texture Texture.Flat)@@ -251,21 +233,17 @@   -> Maybe (Buffer.Allocated 'Buffer.Coherent Material)   -> ResourceT m (FrameResource '[Scene]) allocate (Tagged set0layout) textures cubes lightsData shadowViews materialsData = do-  context <- asks id--  (_dpKey, descPool) <- DescriptorSet.allocatePool 1 dpSizes+  descPool <- Region.local $+    DescriptorPool.allocate (Just "Basic") 1 dpSizes -  let-    set0dsCI = zero-      { Vk.descriptorPool = descPool-      , Vk.setLayouts     = Vector.singleton set0layout-      }-  descSets <- fmap (Tagged @'[Scene]) $-    Vk.allocateDescriptorSets (getDevice context) set0dsCI+  descSets <- DescriptorPool.allocateSetsFrom descPool (Just "Basic") [set0layout] -  (_, sceneData) <- ResourceT.allocate-    (Buffer.createCoherent context Vk.BUFFER_USAGE_UNIFORM_BUFFER_BIT 1 $ VectorS.singleton emptyScene)-    (Buffer.destroy context)+  sceneData <- Region.local $+    Buffer.allocateCoherent+    (Just "Basic.Data")+    Vk.BUFFER_USAGE_UNIFORM_BUFFER_BIT+    1+    [emptyScene]    let     -- TODO: must be checked against depth format and TILING_OPTIMAL@@ -285,18 +263,33 @@    let ifor = flip Vector.imapM   shadowMaps <- ifor shadowViews \ix depthView -> do-    (_, shadowSampler) <- Vk.withSampler (getDevice context) shadowCI Nothing ResourceT.allocate-    Debug.nameObject (getDevice context) shadowSampler $-      "ShadowSampler." <> BS8.pack (show ix)+    shadowSampler <- Region.local do+      device <- asks getDevice+      Vk.withSampler device shadowCI Nothing ResourceT.allocate+    Named.object shadowSampler $+      "Basic.ShadowSampler." <> fromString (show ix)     pure (shadowSampler, depthView) -  updateSet0Ds context descSets sceneData textures cubes lightsData shadowMaps materialsData+  context <- ask+  updateSet0Ds+    context+    (Tagged descSets)+    sceneData+    textures+    cubes+    lightsData+    shadowMaps+    materialsData -  scene <- Worker.newObserverIO emptyScene+  observer <- Worker.newObserverIO emptyScene -  pure $ FrameResource descSets sceneData scene+  pure FrameResource+    { frDescSets = Tagged descSets+    , frBuffer = sceneData+    , frObserver = observer+    } -dpSizes :: DescriptorSet.TypeMap Word32+dpSizes :: [(Vk.DescriptorType, Word32)] dpSizes =   [ ( Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER     , uniformBuffers@@ -319,11 +312,13 @@  -- | Minimal viable 'Scene' without textures and lighting. allocateEmpty-  :: MonadVulkan env m+  :: ( MonadVulkan env m+     , ResourceT.MonadResource m+     )   => Tagged '[Scene] Vk.DescriptorSetLayout   -> ResourceT m (FrameResource '[Scene]) allocateEmpty taggedLayout =-  allocate taggedLayout [] [] Nothing mempty Nothing+  allocate taggedLayout Nothing Nothing Nothing mempty Nothing  updateSet0Ds   :: ( HasVulkan context@@ -459,7 +454,7 @@               , Vk.range  = Vk.WHOLE_SIZE               } -    writeSets = Vector.fromList $ concat+    writeSets = Vector.concat       [ pure writeSet0b0       -- XXX: binding 1 is immutable samplers, baked into layout.       , skipEmpty linearTextures writeSet0b2
src/Render/DescSets/Sun.hs view
@@ -1,5 +1,7 @@ {-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-} +{-# LANGUAGE OverloadedLists #-}+ module Render.DescSets.Sun   ( Sun(..)   , createSet0Ds@@ -23,8 +25,7 @@  import RIO -import Control.Monad.Trans.Resource (ResourceT)-import Control.Monad.Trans.Resource qualified as ResourceT+import Control.Monad.Trans.Resource (MonadResource, ResourceT) import Data.Tagged (Tagged(..)) import Data.Vector qualified as Vector import Data.Vector.Storable qualified as VectorS@@ -36,16 +37,16 @@ import Vulkan.Core10 qualified as Vk import Vulkan.CStruct.Extends (SomeStruct(..)) import Vulkan.NamedType ((:::))-import Vulkan.Utils.Debug qualified as Debug import Vulkan.Zero (Zero(..))  import Engine.Camera qualified as Camera import Engine.Types (StageRIO) import Engine.Vulkan.DescSets ()-import Engine.Vulkan.Types (DsBindings, HasVulkan(..))+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan(..)) import Engine.Worker qualified as Worker import Resource.Buffer qualified as Buffer-import Resource.DescriptorSet qualified as DescriptorSet+import Resource.Region qualified as Region+import Resource.Vulkan.DescriptorPool qualified as DescriptorPool  -- * Set0 data for light projection @@ -76,7 +77,7 @@ -- * Shadow casting descriptor set  set0-  :: Tagged Sun DsBindings+  :: Tagged Sun DsLayoutBindings set0 = Tagged   [ (set0bind0, zero)   ]@@ -101,55 +102,24 @@       , Buffer       ) createSet0Ds (Tagged set0layout) = do-  context <- asks id--  (_dpKey, descPool) <- DescriptorSet.allocatePool 1 dpSizes--  let-    set0dsCI = zero-      { Vk.descriptorPool = descPool-      , Vk.setLayouts     = Vector.singleton set0layout-      }-  descSets <- fmap (Tagged @'[Sun]) $-    Vk.allocateDescriptorSets (getDevice context) set0dsCI--  let-    initialSuns = VectorS.replicate MAX_VIEWS zero-  (_, sunData) <- ResourceT.allocate-    (Buffer.createCoherent context Vk.BUFFER_USAGE_UNIFORM_BUFFER_BIT MAX_VIEWS initialSuns)-    (Buffer.destroyAll context . Just)+  descPool <- Region.local $+    DescriptorPool.allocate (Just "Basic.Sun") 1+      [ ( Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER+        , 1 + 1+        )+      ] -  updateSet0Ds descSets sunData+  descSets <- DescriptorPool.allocateSetsFrom descPool (Just "Basic.Sun") [set0layout] -  let device = getDevice context-  Debug.nameObject device descPool "Sun.Pool"-  for_ (unTagged descSets) \ds ->-    Debug.nameObject device ds "Sun.DS"-  Debug.nameObject device (Buffer.aBuffer sunData) "Sun.Data"+  sunData <- Region.local $+    Buffer.allocateCoherent+      (Just "Basic.Sun.Data")+      Vk.BUFFER_USAGE_UNIFORM_BUFFER_BIT MAX_VIEWS+      (VectorS.replicate MAX_VIEWS zero) -  pure (descSets, sunData)+  updateSet0Ds (Tagged descSets) sunData -dpSizes :: DescriptorSet.TypeMap Word32-dpSizes =-  [ ( Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER-    , uniformBuffers-    )-  -- XXX: may be required to fetch textures for shadows from texture-masked models-  -- , ( Vk.DESCRIPTOR_TYPE_SAMPLED_IMAGE-  --   , sampledImages-  --   )-  -- , ( Vk.DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER-  --   , sampledImages + shadowMaps-  --   )-  -- , ( Vk.DESCRIPTOR_TYPE_SAMPLER-  --   , staticSamplers-  --   )-  ]-  where-    uniformBuffers = 2    -- 1 scene + 1 light array-    -- sampledImages  = 128  -- max dynamic textures and cubemaps-    -- staticSamplers = 8    -- immutable samplers-    -- shadowMaps     = 2    -- max shadowmaps+  pure (Tagged descSets, sunData)  updateSet0Ds   :: Tagged '[Sun] (Vector Vk.DescriptorSet)@@ -157,7 +127,7 @@   -> ResourceT (StageRIO st) () updateSet0Ds (Tagged ds) Buffer.Allocated{aBuffer} = do   context <- asks id-  Vk.updateDescriptorSets (getDevice context) writeSets mempty+  Vk.updateDescriptorSets (getDevice context) [writeSet0b0] mempty    where     destSet0 = case Vector.headM ds of@@ -172,7 +142,7 @@       , Vk.dstArrayElement = 0       , Vk.descriptorCount = 1       , Vk.descriptorType  = Vk.DESCRIPTOR_TYPE_UNIFORM_BUFFER-      , Vk.bufferInfo      = Vector.singleton set0bind0I+      , Vk.bufferInfo      = [set0bind0I]       }       where         set0bind0I = Vk.DescriptorBufferInfo@@ -181,9 +151,6 @@           , Vk.range  = Vk.WHOLE_SIZE           } -    writeSets =-      Vector.singleton writeSet0b0- data SunInput = SunInput   { siColor :: Vec4 @@ -213,7 +180,12 @@  type Process = Worker.Cell SunInput ("bounding box" ::: Transform, Sun) -spawn1 :: MonadUnliftIO m => SunInput -> m Process+spawn1+  :: ( MonadResource m+     , MonadUnliftIO m+     )+  => SunInput+  -> m Process spawn1 = Worker.spawnCell mkSun  mkSun :: SunInput -> ("bounding box" ::: Transform, Sun)
src/Render/Font/EvanwSdf/Model.hs view
@@ -1,25 +1,19 @@+{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}++{-# LANGUAGE DeriveAnyClass #-}+ module Render.Font.EvanwSdf.Model-  ( Model-  , VertexAttrs-  , InstanceAttrs(..)-  , vkInstanceAttrs-  , InstanceBuffer+  ( InstanceAttrs(..)   ) where  import RIO -import Foreign (Storable(..))-import Geomancy (Vec2, Vec4)-import Geomancy.Vec3 qualified as Vec3+import Foreign.Storable.Generic (GStorable)+import Geomancy (Vec4) import Vulkan.Core10 qualified as Vk-import Vulkan.NamedType ((:::)) -import Resource.Buffer qualified as Buffer-import Resource.Model qualified as Model--type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs--type VertexAttrs = "uv" ::: Vec2+import Engine.Vulkan.Format (HasVkFormat(..))+import Engine.Vulkan.Pipeline.Graphics (HasVertexInputBindings(..), instanceFormat)  data InstanceAttrs = InstanceAttrs   { vertRect     :: Vec4@@ -33,43 +27,21 @@   , smoothing    :: Float   , outlineWidth :: Float   }-  deriving (Eq, Show)--vkInstanceAttrs :: [Vk.Format]-vkInstanceAttrs =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- Quad scale+offset-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- UV scale+offset-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- Color-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- Outline color--  , Vk.FORMAT_R32G32_SINT         -- Sampler + texture IDs--  , Vk.FORMAT_R32G32_SFLOAT       -- Smoothing + outline width-  ]+  deriving (Eq, Show, Generic) -instance Storable InstanceAttrs where-  alignment ~_ = 4-  sizeOf ~_ = 16 + 16 + 16 + 16 + 4 + 4 + 4 + 4+-- XXX: Fine, the layout matches+instance GStorable InstanceAttrs -  peek ptr = do-    vertRect     <- peekByteOff ptr  0 -- +16-    fragRect     <- peekByteOff ptr 16 -- +16-    color        <- peekByteOff ptr 32 -- +16-    outlineColor <- peekByteOff ptr 48 -- +16-    samplerId    <- peekByteOff ptr 64 -- +4-    textureId    <- peekByteOff ptr 68 -- +4-    smoothing    <- peekByteOff ptr 72 -- +4-    outlineWidth <- peekByteOff ptr 76 -- +4-    pure InstanceAttrs{..}+instance HasVkFormat InstanceAttrs where+  getVkFormat =+    [ Vk.FORMAT_R32G32B32A32_SFLOAT -- Quad scale+offset+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- UV scale+offset+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- Color+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- Outline color -  poke ptr InstanceAttrs{..} = do-    pokeByteOff ptr  0 vertRect-    pokeByteOff ptr 16 fragRect-    pokeByteOff ptr 32 color-    pokeByteOff ptr 48 outlineColor-    pokeByteOff ptr 64 samplerId-    pokeByteOff ptr 68 textureId-    pokeByteOff ptr 72 smoothing-    pokeByteOff ptr 76 outlineWidth+    , Vk.FORMAT_R32G32_SINT         -- Sampler + texture IDs+    , Vk.FORMAT_R32G32_SFLOAT       -- Smoothing + outline width+    ] -type InstanceBuffer stage = Buffer.Allocated stage InstanceAttrs+instance HasVertexInputBindings InstanceAttrs where+  vertexInputBindings = [instanceFormat @InstanceAttrs]
src/Render/Font/EvanwSdf/Pipeline.hs view
@@ -16,7 +16,7 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag) import Render.DescSets.Set0 (Scene) import Render.Font.EvanwSdf.Code qualified as Code@@ -31,7 +31,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 = do@@ -40,20 +40,16 @@     multisample     (config tset0) -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts = Tagged @'[Scene] [set0]   , Graphics.cStages      = stageSpirv-  , Graphics.cVertexInput = vertexInput+  , Graphics.cVertexInput = Graphics.vertexInput @Pipeline   , Graphics.cDepthTest   = False   , Graphics.cDepthWrite  = False   , Graphics.cBlend       = True   , Graphics.cCull        = Vk.CULL_MODE_NONE   }-  where-    vertexInput = Graphics.vertexInput-      [ (Vk.VERTEX_INPUT_RATE_INSTANCE, Model.vkInstanceAttrs)-      ]  stageCode :: Graphics.StageCode stageCode = Graphics.basicStages Code.vert Code.frag
src/Render/ForwardMsaa.hs view
@@ -11,14 +11,16 @@ import Data.Bits ((.|.)) import Data.Vector qualified as Vector import Vulkan.Core10 qualified as Vk-import Vulkan.Utils.Debug qualified as Debug import Vulkan.Zero (zero) -import Engine.Types.RefCounted (RefCounted, newRefCounted, releaseRefCounted, resourceTRefCount)+import Engine.Types.RefCounted (RefCounted, releaseRefCounted, resourceTRefCount)+import Engine.Types.RefCounted qualified as RefCounted import Engine.Vulkan.Types (HasVulkan(..), HasSwapchain(..), HasRenderPass(..), RenderPass(..), MonadVulkan) import Render.Pass (usePass) import Resource.Image (AllocatedImage) import Resource.Image qualified as Image+import Resource.Region qualified as Region+import Resource.Vulkan.Named qualified as Named  -- * Simple MSAA-enabled pass @@ -51,10 +53,15 @@   => swapchain   -> m ForwardMsaa allocateMsaa swapchain = do-  logDebug "Allocating ForwardMsaa resources"   (_rpKey, renderPass) <- allocateRenderPassMsaa swapchain-  (refcounted, color, depth, framebuffers) <- allocateFramebufferMsaa swapchain renderPass +  (release, resources) <- RefCounted.wrapped $ Region.run do+    Region.logDebug+      "Allocating ForwardMsaa resources"+      "Releasing ForwardMsaa resources"+    allocateFramebufferMsaa swapchain renderPass+  let (color, depth, framebuffers) = resources+   pure ForwardMsaa     { fmRenderPass   = renderPass     , fmRenderArea   = fullSurface@@ -62,7 +69,7 @@     , fmColor        = color     , fmDepth        = depth     , fmFrameBuffers = framebuffers-    , fmRelease      = refcounted+    , fmRelease      = release     }   where     fullSurface = Vk.Rect2D@@ -87,12 +94,17 @@   -> m ForwardMsaa updateMsaa swapchain old@ForwardMsaa{fmRelease, fmRenderPass} = do   releaseRefCounted fmRelease-  (refcounted, color, depth, framebuffers) <- allocateFramebufferMsaa swapchain fmRenderPass+  (release, resources) <- RefCounted.wrapped $ Region.run do+    Region.logDebug+      "Updating ForwardMsaa resources"+      "Releasing ForwardMsaa resources"+    allocateFramebufferMsaa swapchain fmRenderPass+  let (color, depth, framebuffers) = resources   pure old     { fmColor        = color     , fmDepth        = depth     , fmFrameBuffers = framebuffers-    , fmRelease      = refcounted+    , fmRelease      = release     , fmRenderArea   = fullSurface     }   where@@ -112,40 +124,51 @@   -> m (Resource.ReleaseKey, Vk.RenderPass) allocateRenderPassMsaa swapchain = do   device <- asks getDevice-  let++  res <- Vk.withRenderPass device createInfo Nothing Resource.allocate+  Named.object (snd res) "ForwardMSAA"+  pure res+  where     format = getSurfaceFormat swapchain     depthFormat = getDepthFormat swapchain     msaa = getMultisample swapchain +    onMsaa :: a -> a -> a+    onMsaa none more = case msaa of+      Vk.SAMPLE_COUNT_1_BIT ->+        none+      _mucho ->+        more+     attachments =-      [ color format msaa-      , depth depthFormat msaa-      , colorResolve format-      ]+      color :+      depth :+      onMsaa [] [colorResolve] -  res@(_key, object) <- Vk.withRenderPass device (createInfo attachments) Nothing Resource.allocate-  Debug.nameObject device object "ForwardMSAA"-  pure res-  where-    createInfo attachments = zero+    createInfo = zero       { Vk.attachments  = Vector.fromList attachments       , Vk.subpasses    = Vector.fromList [subpass]       , Vk.dependencies = Vector.fromList [colorDeps, depthDeps]       } -    color format msaa = zero+    -- | Main color-rendering attachment. Used as presentation when MSAA is disabled.+    color = zero       { Vk.format         = format       , Vk.samples        = msaa-      , Vk.finalLayout    = Vk.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL+      , Vk.finalLayout    = finalColorLayout       , Vk.loadOp         = Vk.ATTACHMENT_LOAD_OP_CLEAR       , Vk.storeOp        = Vk.ATTACHMENT_STORE_OP_DONT_CARE       , Vk.stencilLoadOp  = Vk.ATTACHMENT_LOAD_OP_DONT_CARE       , Vk.stencilStoreOp = Vk.ATTACHMENT_STORE_OP_DONT_CARE       , Vk.initialLayout  = Vk.IMAGE_LAYOUT_UNDEFINED       }+    finalColorLayout =+      onMsaa+        Vk.IMAGE_LAYOUT_PRESENT_SRC_KHR+        Vk.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL -    depth format msaa = zero-      { Vk.format         = format+    depth = zero+      { Vk.format         = depthFormat       , Vk.samples        = msaa       , Vk.loadOp         = Vk.ATTACHMENT_LOAD_OP_CLEAR       , Vk.storeOp        = Vk.ATTACHMENT_STORE_OP_DONT_CARE@@ -155,7 +178,8 @@       , Vk.finalLayout    = Vk.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL       } -    colorResolve format = zero+    -- | Extra attachment to collect samples AND present.+    colorResolve = zero       { Vk.format      = format       , Vk.samples     = Vk.SAMPLE_COUNT_1_BIT       , Vk.finalLayout = Vk.IMAGE_LAYOUT_PRESENT_SRC_KHR@@ -172,10 +196,12 @@           { Vk.attachment = 1           , Vk.layout     = Vk.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL           }-      , Vk.resolveAttachments = Vector.singleton zero-          { Vk.attachment = 2-          , Vk.layout     = Vk.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL-          }+      , Vk.resolveAttachments =+          onMsaa mempty $+            Vector.singleton zero+            { Vk.attachment = 2+            , Vk.layout     = Vk.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL+            }       }      colorDeps = zero@@ -217,8 +243,7 @@ -- ** Framebuffer  type FramebuffersMsaa =-  ( RefCounted-  , Image.AllocatedImage+  ( Image.AllocatedImage   , Image.AllocatedImage   , Vector Vk.Framebuffer   )@@ -226,51 +251,45 @@ allocateFramebufferMsaa   :: ( Resource.MonadResource m      , MonadVulkan env m-     , HasLogFunc env      , HasSwapchain swapchain      )   => swapchain   -> Vk.RenderPass   -> m FramebuffersMsaa allocateFramebufferMsaa swapchain renderPass = do-  context <- ask-  let extent@Vk.Extent2D{width, height} = getSurfaceExtent swapchain--  (colorKey, color) <- Resource.allocate-    ( Image.create-        context-        (Just $ "ForwardMSAA.color")-        Vk.IMAGE_ASPECT_COLOR_BIT-        extent-        1-        1-        (getMultisample swapchain)-        (getSurfaceFormat swapchain)-        Vk.IMAGE_USAGE_COLOR_ATTACHMENT_BIT-    )-    (Image.destroy context)+  color <- Image.allocate+    (Just "ForwardMSAA.color")+    Vk.IMAGE_ASPECT_COLOR_BIT+    (Image.inflateExtent extent 1)+    1+    1+    (getMultisample swapchain)+    (getSurfaceFormat swapchain)+    Vk.IMAGE_USAGE_COLOR_ATTACHMENT_BIT -  (depthKey, depth) <- Resource.allocate-    ( Image.create-        context-        (Just $ "ForwardMSAA.depth")-        Vk.IMAGE_ASPECT_DEPTH_BIT-        extent-        1-        1-        (getMultisample swapchain)-        (getDepthFormat swapchain)-        Vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT-    )-    (Image.destroy context)+  depth <- Image.allocate+    (Just "ForwardMSAA.depth")+    Vk.IMAGE_ASPECT_DEPTH_BIT+    (Image.inflateExtent extent 1)+    1+    1+    (getMultisample swapchain)+    (getDepthFormat swapchain)+    Vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT    perView <- Vector.iforM (getSwapchainViews swapchain) \ix colorResolve -> do     let       attachments = Vector.fromList-        [ Image.aiImageView color-        , Image.aiImageView depth-        , colorResolve-        ]+        case getMultisample swapchain of+          Vk.SAMPLE_COUNT_1_BIT ->+            [ colorResolve+            , Image.aiImageView depth+            ]+          _ ->+            [ Image.aiImageView color+            , Image.aiImageView depth+            , colorResolve+            ]        fbCI = zero         { Vk.renderPass  = renderPass@@ -280,19 +299,12 @@         , Vk.layers      = 1         } -      device = getDevice context-    res <- Vk.withFramebuffer device fbCI Nothing Resource.allocate-    Debug.nameObject device (snd res) $+    device <- asks getDevice+    (_fbKey, fb) <- Vk.withFramebuffer device fbCI Nothing Resource.allocate+    Named.object fb $       "ForwardMSAA.FB:" <> fromString (show @Int ix)--    pure res--  let (framebufferKeys, framebuffers) = Vector.unzip perView-  releaseDebug <- toIO $ logDebug "Releasing ForwardMsaa resources"-  release <- newRefCounted do-    releaseDebug-    Resource.release colorKey-    Resource.release depthKey-    traverse_ Resource.release framebufferKeys+    pure fb -  pure (release, color, depth, framebuffers)+  pure (color, depth, perView)+  where+    extent@Vk.Extent2D{width, height} = getSurfaceExtent swapchain
src/Render/Lit/Colored/Model.hs view
@@ -1,21 +1,24 @@+{-# LANGUAGE DeriveAnyClass #-}+ module Render.Lit.Colored.Model   ( Model-+  , Vertex   , VertexAttrs(..)-  , vkVertexAttrs-   , InstanceAttrs   ) where  import RIO -import Foreign (Storable(..)) import Geomancy (Transform, Vec2, Vec4)+import Geomancy.Gl.Block (Block)+import Geomancy.Gl.Block qualified as Block import Geomancy.Vec3 qualified as Vec3 import Resource.Model qualified as Model-import Vulkan.Core10 qualified as Vk +import Engine.Vulkan.Format (HasVkFormat)+ type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  data VertexAttrs = VertexAttrs   { vaBaseColor         :: Vec4@@ -23,32 +26,7 @@   , vaMetallicRoughness :: Vec2   , vaNormal            :: Vec3.Packed   }-  deriving (Eq, Ord, Show, Generic)--instance Storable VertexAttrs where-  alignment ~_ = 4--  sizeOf ~_ = 16 + 16 + 8 + 12--  peek ptr = do-    vaBaseColor         <- peekByteOff ptr  0-    vaEmissiveColor     <- peekByteOff ptr 16-    vaMetallicRoughness <- peekByteOff ptr 32-    vaNormal            <- peekByteOff ptr 40-    pure VertexAttrs{..}--  poke ptr VertexAttrs{..} = do-    pokeByteOff ptr  0 vaBaseColor-    pokeByteOff ptr 16 vaEmissiveColor-    pokeByteOff ptr 32 vaMetallicRoughness-    pokeByteOff ptr 40 vaNormal+  deriving (Eq, Ord, Show, Generic, Block, HasVkFormat)+  deriving Storable via (Block.Packed VertexAttrs)  type InstanceAttrs = Transform--vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- vBaseColor         :: vec4-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- vEmissiveColor     :: vec4-  , Vk.FORMAT_R32G32_SFLOAT       -- vMetallicRoughness :: vec2-  , Vk.FORMAT_R32G32B32_SFLOAT    -- vNormal            :: vec3-  ]
src/Render/Lit/Colored/Pipeline.hs view
@@ -18,13 +18,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag)-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) import Render.Lit.Colored.Code qualified as Code import Render.Lit.Colored.Model qualified as Model -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.InstanceAttrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -33,7 +33,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 rp = do@@ -49,7 +49,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocateBlend multisample tset0 rp = do@@ -60,20 +60,14 @@     rp   pure p -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos-      , (Vk.VERTEX_INPUT_RATE_VERTEX, Model.vkVertexAttrs)-      , instanceTransform-      ] -configBlend :: Tagged Scene DsBindings -> Config+configBlend :: Tagged Scene DsLayoutBindings -> Config configBlend tset0 = (config tset0)   { Graphics.cBlend = True   }
src/Render/Lit/Material.hs view
@@ -26,6 +26,10 @@   }   deriving (Eq, Ord, Show, Generic) +{- XXX: The derived instance has padding, but its okay here.+It is only used for intermediate storage.+The instance uses per-vertex material data.+-} instance GStorable Material  instance Zero Material where
src/Render/Lit/Material/Code.hs view
@@ -166,6 +166,8 @@         vec3 normals = pow(normalsColor, vec3(1.0/2.2)) * 2.0 - 1.0;          normal = normalize(fTBN * normals);+      } else {+        normal = normalize(normal);       }        ${litMain}
src/Render/Lit/Material/Model.hs view
@@ -1,32 +1,26 @@-{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}+{-# LANGUAGE DeriveAnyClass #-}  module Render.Lit.Material.Model   ( Model+  , Vertex   , VertexAttrs(..)-  , vkVertexAttrs-   , InstanceAttrs-  -- , InstanceBuffers(..)--  -- , TextureParams(..)-  -- , vkInstanceTexture--  -- , allocateInstancesWith-  , Transform   , Material   ) where  import RIO -import Foreign (Storable(..)) import Geomancy (Transform, Vec2) import Geomancy.Vec3 qualified as Vec3-import Vulkan.Core10 qualified as Vk+import Geomancy.Gl.Block (Block)+import Geomancy.Gl.Block qualified as Block -import Resource.Model qualified as Model+import Engine.Vulkan.Format (HasVkFormat) import Render.Lit.Material (Material)+import Resource.Model qualified as Model  type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  data VertexAttrs = VertexAttrs   { vaTexCoord0 :: Vec2@@ -35,35 +29,7 @@   , vaTangent   :: Vec3.Packed   , vaMaterial  :: Word32   }-  deriving (Eq, Ord, Show, Generic)--instance Storable VertexAttrs where-  alignment ~_ = 4--  sizeOf ~_ = 8 + 8 + 12 + 12 + 4--  peek ptr = do-    vaTexCoord0 <- peekByteOff ptr 0-    vaTexCoord1 <- peekByteOff ptr 8-    vaNormal    <- peekByteOff ptr 16-    vaTangent   <- peekByteOff ptr 28-    vaMaterial  <- peekByteOff ptr 40-    pure VertexAttrs{..}--  poke ptr VertexAttrs{..} = do-    pokeByteOff ptr  0 vaTexCoord0-    pokeByteOff ptr  8 vaTexCoord1-    pokeByteOff ptr 16 vaNormal-    pokeByteOff ptr 28 vaTangent-    pokeByteOff ptr 40 vaMaterial--vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32_SFLOAT    -- vTexCoord0 :: vec2-  , Vk.FORMAT_R32G32_SFLOAT    -- vTexCoord1 :: vec2-  , Vk.FORMAT_R32G32B32_SFLOAT -- vNormal    :: vec3-  , Vk.FORMAT_R32G32B32_SFLOAT -- vTangent   :: vec3-  , Vk.FORMAT_R32_UINT         -- vMaterial  :: uint-  ]+  deriving (Eq, Ord, Show, Generic, Block, HasVkFormat)+  deriving Storable via (Block.Packed VertexAttrs)  type InstanceAttrs = Transform
src/Render/Lit/Material/Pipeline.hs view
@@ -18,13 +18,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag)-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) import Render.Lit.Material.Code qualified as Code import Render.Lit.Material.Model qualified as Model -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.InstanceAttrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -33,7 +33,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 rp = do@@ -49,7 +49,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocateBlend multisample tset0 rp = do@@ -60,22 +60,16 @@     rp   pure p -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   , Graphics.cDepthWrite   = False -- XXX: Lit pipelines require depth pre-pass   , Graphics.cDepthCompare = Vk.COMPARE_OP_EQUAL   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos -- vPosition-      , (Vk.VERTEX_INPUT_RATE_VERTEX, Model.vkVertexAttrs)-      , instanceTransform-      ] -configBlend :: Tagged Scene DsBindings -> Config+configBlend :: Tagged Scene DsLayoutBindings -> Config configBlend tset0 = (config tset0)   { Graphics.cBlend =       True
src/Render/Lit/Textured/Model.hs view
@@ -1,162 +1,32 @@+{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}++{-# LANGUAGE DeriveAnyClass #-}+ module Render.Lit.Textured.Model   ( Model+  , Vertex   , VertexAttrs(..)-  , vkVertexAttrs -  , InstanceAttrs(..)-  , InstanceBuffers(..)--  , TextureParams(..)-  , vkInstanceTexture--  , allocateInstancesWith-  , Transform+  , module Render.Unlit.Textured.Model   ) where  import RIO-+import Render.Unlit.Textured.Model hiding (Model, Vertex, VertexAttrs) -import Foreign (Storable(..))-import Geomancy (Transform, Vec2, Vec4)+import Foreign.Storable.Generic (GStorable)+import Geomancy (Vec2) import Geomancy.Vec3 qualified as Vec3-import RIO.Vector.Storable qualified as VectorS-import UnliftIO.Resource (MonadResource, ReleaseKey, allocate)-import Vulkan.Core10 qualified as Vk-import Vulkan.Zero (Zero(..)) -import Resource.Buffer qualified as Buffer+import Engine.Vulkan.Format (HasVkFormat) import Resource.Model qualified as Model  type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  data VertexAttrs = VertexAttrs   { vaTexCoord :: Vec2   , vaNormal   :: Vec3.Packed   }-  deriving (Eq, Ord, Show, Generic)--instance Storable VertexAttrs where-  alignment ~_ = 4--  sizeOf ~_ = 8 + 12--  peek ptr = do-    vaTexCoord <- peekByteOff ptr 0-    vaNormal   <- peekByteOff ptr 8-    pure VertexAttrs{..}--  poke ptr VertexAttrs{..} = do-    pokeByteOff ptr 0 vaTexCoord-    pokeByteOff ptr 8 vaNormal--vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32_SFLOAT    -- vTexCoord :: vec2-  , Vk.FORMAT_R32G32B32_SFLOAT -- vNormal   :: vec3-  ]--data InstanceAttrs = InstanceAttrs-  { textureParams :: TextureParams-  , transformMat4 :: Transform-  }--instance Zero InstanceAttrs where-  zero = InstanceAttrs-    { textureParams = zero-    , transformMat4 = mempty-    }--data InstanceBuffers textureStage transformStage = InstanceBuffers-  { ibTexture   :: InstanceTexture textureStage-  , ibTransform :: InstanceTransform transformStage-  }--type InstanceTexture stage = Buffer.Allocated stage TextureParams--type InstanceTransform stage = Buffer.Allocated stage Transform--instance Model.HasVertexBuffers (InstanceBuffers textureStage transformStage) where-  type VertexBuffersOf (InstanceBuffers textureStage transformStage) = InstanceAttrs--  {-# INLINE getVertexBuffers #-}-  getVertexBuffers InstanceBuffers{..} =-    [ Buffer.aBuffer ibTexture-    , Buffer.aBuffer ibTransform-    ]--  {-# INLINE getInstanceCount #-}-  getInstanceCount InstanceBuffers{..} =-    min-      (Buffer.aUsed ibTexture)-      (Buffer.aUsed ibTransform)--data TextureParams = TextureParams-  { tpScale     :: Vec2-  , tpOffset    :: Vec2-  , tpGamma     :: Vec4-  , tpSamplerId :: Int32-  , tpTextureId :: Int32-  }-  deriving (Show)--instance Zero TextureParams where-  zero = TextureParams-    { tpScale     = 1-    , tpOffset    = 0-    , tpGamma     = 1.0-    , tpSamplerId = minBound-    , tpTextureId = minBound-    }--instance Storable TextureParams where-  alignment ~_ = 8--  sizeOf ~_ = 8 + 8 + 16 + 4 + 4--  poke ptr TextureParams{..} = do-    pokeByteOff ptr  0 tpScale-    pokeByteOff ptr  8 tpOffset-    pokeByteOff ptr 16 tpGamma-    pokeByteOff ptr 32 tpSamplerId-    pokeByteOff ptr 36 tpTextureId--  peek ptr = do-    tpScale     <- peekByteOff ptr  0-    tpOffset    <- peekByteOff ptr  8-    tpGamma     <- peekByteOff ptr 16-    tpSamplerId <- peekByteOff ptr 32-    tpTextureId <- peekByteOff ptr 36-    pure TextureParams{..}--vkInstanceTexture :: [Vk.Format]-vkInstanceTexture =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureScaleOffset :: vec4-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureGamma       :: vec4-  , Vk.FORMAT_R32G32_SINT         -- iTextureIds         :: ivec2-  ]--allocateInstancesWith-  :: ( MonadResource m-     , MonadUnliftIO m-     )-  => (Vk.BufferUsageFlagBits -> Int -> VectorS.Vector TextureParams -> m (InstanceTexture texture))-  -> (Vk.BufferUsageFlagBits -> Int -> VectorS.Vector Transform -> m (InstanceTransform transform))-  -> (forall stage a . Buffer.Allocated stage a -> m ())-  -> [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers texture transform)-allocateInstancesWith createTextures createTransforms bufferDestroy instances = do-  ul <- askUnliftIO-  allocate (create ul) (destroy ul)-  where-    textures   = VectorS.fromList $ map textureParams instances-    transforms = VectorS.fromList $ map transformMat4 instances-    numInstances = VectorS.length textures--    create (UnliftIO ul) = ul do-      ibTexture   <- createTextures   Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances textures-      ibTransform <- createTransforms Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances transforms-      pure InstanceBuffers{..}+  deriving (Eq, Ord, Show, Generic, HasVkFormat) -    destroy (UnliftIO ul) InstanceBuffers{..} = ul do-      bufferDestroy ibTexture-      bufferDestroy ibTransform+instance GStorable VertexAttrs
src/Render/Lit/Textured/Pipeline.hs view
@@ -18,13 +18,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag)-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) import Render.Lit.Textured.Code qualified as Code import Render.Lit.Textured.Model qualified as Model -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.Attrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -33,7 +33,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 rp = do@@ -49,7 +49,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocateBlend multisample tset0 rp = do@@ -60,23 +60,16 @@     rp   pure p -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   , Graphics.cDepthWrite   = False -- XXX: Lit pipelines require depth pre-pass   , Graphics.cDepthCompare = Vk.COMPARE_OP_EQUAL   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos -- vPosition-      , (Vk.VERTEX_INPUT_RATE_VERTEX,   Model.vkVertexAttrs)-      , (Vk.VERTEX_INPUT_RATE_INSTANCE, Model.vkInstanceTexture)-      , instanceTransform-      ] -configBlend :: Tagged Scene DsBindings -> Config+configBlend :: Tagged Scene DsLayoutBindings -> Config configBlend tset0 = (config tset0)   { Graphics.cBlend      = True   , Graphics.cDepthCompare = Vk.COMPARE_OP_LESS_OR_EQUAL
+ src/Render/Pass/Compose.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE OverloadedLists #-}++module Render.Pass.Compose+  ( Compose(..)+  , allocate+  , update+  , usePass+  ) where++import RIO++import Control.Monad.Trans.Resource qualified as Resource+import Data.Bits ((.|.))+import Data.Vector qualified as Vector+import Vulkan.Core10 qualified as Vk+import Vulkan.Utils.Debug qualified as Debug+import Vulkan.Zero (zero)++import Engine.Types.RefCounted (RefCounted, releaseRefCounted, resourceTRefCount)+import Engine.Types.RefCounted qualified as RefCounted+import Engine.Vulkan.Types (HasSwapchain(..), HasRenderPass(..), MonadVulkan, RenderPass(..), getDevice)+import Render.Pass (usePass)+import Resource.Region qualified as Region++-- | Composition/postprocessing/presentation pass+--+-- Can be used to transfer images from "Render.Pass.Offscreen.Offscreen" passes and tonemapping.+--+-- Color attachments are derived from swapchain.+-- The pass optmized for image transfer: it has no depth attachment and does not clear.+-- Use image blitting that convers the whole area or a fullscreen shader.+data Compose = Compose+  { renderPass   :: Vk.RenderPass+  , frameBuffers :: Vector Vk.Framebuffer+  , renderArea   :: Vk.Rect2D+  , clear        :: Vector Vk.ClearValue+  , release      :: RefCounted+  }++instance HasRenderPass Compose where+  getRenderPass   = renderPass+  getFramebuffers = frameBuffers+  getClearValues  = clear+  getRenderArea   = renderArea++instance RenderPass Compose where+  updateRenderpass = update+  refcountRenderpass = resourceTRefCount . release++allocate+  :: ( Resource.MonadResource m+     , MonadVulkan env m+     , HasLogFunc env+     , HasSwapchain swapchain+     )+  => swapchain+  -> m Compose+allocate swapchain = do+  renderPass <- allocateRenderPass format+  (refcounted, framebuffers) <- RefCounted.wrapped $ Region.run do+    Region.logDebug+      "Allocating Compose resources"+      "Releasing Compose resources"+    allocateFramebufferSwapchain swapchain renderPass++  pure Compose+    { renderPass   = renderPass+    , renderArea   = fullSurface+    , clear        = mempty+    , frameBuffers = framebuffers+    , release      = refcounted+    }+  where+    format = getSurfaceFormat swapchain++    fullSurface = Vk.Rect2D+      { Vk.offset = zero+      , Vk.extent = getSurfaceExtent swapchain+      }++update+  :: ( Resource.MonadResource m+     , MonadVulkan env m+     , HasSwapchain swapchain+     )+  => swapchain+  -> Compose+  -> m Compose+update swapchain old@Compose{release, renderPass} = do+  releaseRefCounted release+  (refcounted, framebuffers) <- RefCounted.wrapped $ Region.run do+    allocateFramebufferSwapchain swapchain renderPass+  pure old+    { frameBuffers = framebuffers+    , release      = refcounted+    , renderArea   = fullSurface+    }+  where+    fullSurface = Vk.Rect2D+      { Vk.offset = zero+      , Vk.extent = getSurfaceExtent swapchain+      }++-- ** Render pass++allocateRenderPass+  :: ( MonadVulkan env m+     , Resource.MonadResource m+     )+  => Vk.Format+  -> m Vk.RenderPass+allocateRenderPass format = do+  device <- asks getDevice+  (_key, rp) <- Vk.withRenderPass device createInfo Nothing Resource.allocate+  Debug.nameObject device rp "Compose"+  pure rp+  where+    createInfo = zero+      { Vk.attachments  = [color]+      , Vk.subpasses    = [subpass]+      , Vk.dependencies = [colorDeps]+      }++    color = zero+      { Vk.format      = format+      , Vk.samples     = Vk.SAMPLE_COUNT_1_BIT+      , Vk.loadOp      = Vk.ATTACHMENT_LOAD_OP_DONT_CARE+      , Vk.finalLayout = Vk.IMAGE_LAYOUT_PRESENT_SRC_KHR+      }++    subpass = zero+      { Vk.pipelineBindPoint =+          Vk.PIPELINE_BIND_POINT_GRAPHICS+      , Vk.colorAttachments = Vector.singleton zero+          { Vk.attachment = 0+          , Vk.layout     = Vk.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL+          }+      }++    colorDeps = zero+      { Vk.srcSubpass    = Vk.SUBPASS_EXTERNAL+      , Vk.dstSubpass    = 0+      , Vk.srcStageMask  = colorOut+      , Vk.srcAccessMask = zero+      , Vk.dstStageMask  = colorOut+      , Vk.dstAccessMask = colorRW+      }+      where+        colorOut =+          Vk.PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT++        colorRW =+          Vk.ACCESS_COLOR_ATTACHMENT_READ_BIT .|.+          Vk.ACCESS_COLOR_ATTACHMENT_WRITE_BIT++-- ** Framebuffer++allocateFramebufferSwapchain+  :: ( Resource.MonadResource m+     , MonadVulkan env m+     , HasSwapchain swapchain+     )+  => swapchain+  -> Vk.RenderPass+  -> m (Vector Vk.Framebuffer)+allocateFramebufferSwapchain swapchain renderPass =+  Vector.iforM (getSwapchainViews swapchain) \ix colorView -> do+    let+      fbCI = zero+        { Vk.renderPass  = renderPass+        , Vk.width       = width+        , Vk.height      = height+        , Vk.attachments = [colorView]+        , Vk.layers      = 1+        }++    device <- asks getDevice+    (_key, fb) <- Vk.withFramebuffer device fbCI Nothing Resource.allocate+    Debug.nameObject device fb $+      "Compose.FB:" <> fromString (show @Int ix)+    pure fb+  where+    Vk.Extent2D{width, height} = getSurfaceExtent swapchain
src/Render/ShadowMap/Pipeline.hs view
@@ -20,13 +20,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert)-import Render.DescSets.Set0 (vertexPos, instanceTransform) import Render.DescSets.Sun (Sun) import Render.ShadowMap.Code qualified as Code+import Resource.Model (Vertex3d) -type Pipeline = Graphics.Pipeline '[Sun] () Transform+type Pipeline = Graphics.Pipeline '[Sun] (Vertex3d ()) Transform type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -45,7 +45,7 @@   :: ( HasVulkan env      , HasRenderPass renderpass      )-  => Tagged Sun DsBindings+  => Tagged Sun DsLayoutBindings   -> renderpass   -> Settings   -> ResourceT (RIO env) Pipeline@@ -57,19 +57,14 @@     rp   pure p -config :: Tagged Sun DsBindings -> Settings -> Config+config :: Tagged Sun DsLayoutBindings -> Settings -> Config config (Tagged set0) Settings{..} = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Sun] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   , Graphics.cDepthBias    = depthBias   , Graphics.cCull         = cull   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos-      , instanceTransform-      ]  stageSpirv :: Graphics.StageSpirv stageSpirv = Graphics.vertexOnly vertSpirv
src/Render/ShadowMap/RenderPass.hs view
@@ -18,11 +18,14 @@ import Vulkan.Zero (zero) import Vulkan.CStruct.Extends (pattern (:&), pattern (::&)) -import Engine.Types.RefCounted (RefCounted, newRefCounted, resourceTRefCount)+import Engine.Types.RefCounted (RefCounted, resourceTRefCount)+import Engine.Types.RefCounted qualified as RefCounted import Engine.Vulkan.Types (HasVulkan(..), HasSwapchain(..), HasRenderPass(..), RenderPass(..), MonadVulkan) import Render.Pass (usePass) import Resource.Image (AllocatedImage) import Resource.Image qualified as Image+import Resource.Region qualified as Region+import Resource.Vulkan.Named qualified as Named  -- * Depth-only pass for shadowmapping pipelines @@ -57,9 +60,13 @@   -> "light count" ::: Word32   -> m ShadowMap allocate context mapSize layerCount = do-  logDebug "Allocating ShadowMap resources"   (_rpKey, renderPass) <- allocateRenderPass context (2 ^ layerCount - 1) 0-  (refcounted, depthImage, framebuffer) <- allocateFramebuffer context extent layerCount renderPass+  (release, resources) <- RefCounted.wrapped $ Region.run do+    Region.logDebug+      "Allocating ShadowMap resources"+      "Releasing ShadowMap resources"+    allocateFramebuffer context extent layerCount renderPass+  let (depthImage, framebuffer) = resources    pure ShadowMap     { smRenderPass  = renderPass@@ -69,7 +76,7 @@     , smClear       = clear     , smDepthImage  = depthImage     , smFrameBuffer = framebuffer-    , smRelease     = refcounted+    , smRelease     = release     }   where     extent = Vk.Extent2D{width=mapSize, height=mapSize}@@ -162,15 +169,13 @@ -- ** Framebuffer  type Framebuffers =-  ( RefCounted-  , Image.AllocatedImage+  ( Image.AllocatedImage   , Vk.Framebuffer   )  allocateFramebuffer   :: ( Resource.MonadResource m      , MonadVulkan env m-     , HasLogFunc env      , HasSwapchain swapchain      )   => swapchain@@ -179,21 +184,15 @@   -> Vk.RenderPass   -> m Framebuffers allocateFramebuffer swapchain extent layerCount renderPass = do-  context <- ask--  (depthKey, depth) <- Resource.allocate-    ( Image.create-        context-        (Just "ShadowMap.depth")-        Vk.IMAGE_ASPECT_DEPTH_BIT-        extent-        1-        layerCount-        Vk.SAMPLE_COUNT_1_BIT-        (getDepthFormat swapchain)-        (Vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT .|. Vk.IMAGE_USAGE_SAMPLED_BIT)-    )-    (Image.destroy context)+  depth <- Image.allocate+    (Just "ShadowMap.depth")+    Vk.IMAGE_ASPECT_DEPTH_BIT+    (Image.inflateExtent extent 1)+    1+    layerCount+    Vk.SAMPLE_COUNT_1_BIT+    (getDepthFormat swapchain)+    (Vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT .|. Vk.IMAGE_USAGE_SAMPLED_BIT)    let     attachments = Vector.fromList@@ -216,14 +215,8 @@       , Vk.layers      = fbNumLayers       } -    device = getDevice context-  (framebufferKey, framebuffer) <- Vk.withFramebuffer device fbCI Nothing Resource.allocate-  Debug.nameObject device framebuffer "ShadowMap.FB"--  releaseDebug <- toIO $ logDebug "Releasing ShadowMap resources"-  release <- newRefCounted do-    releaseDebug-    Resource.release depthKey-    Resource.release framebufferKey+  device <- asks getDevice+  (_framebufferKey, framebuffer) <- Vk.withFramebuffer device fbCI Nothing Resource.allocate+  Named.object framebuffer "ShadowMap.FB" -  pure (release, depth, framebuffer)+  pure (depth, framebuffer)
src/Render/Skybox/Pipeline.hs view
@@ -17,7 +17,7 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag) import Render.DescSets.Set0 (Scene) import Render.Skybox.Code qualified as Code@@ -31,7 +31,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 = do@@ -40,7 +40,7 @@     multisample     (config tset0) -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cStages      = stageSpirv   , Graphics.cDescLayouts = Tagged @'[Scene] [set0]
src/Render/Unlit/Colored/Model.hs view
@@ -1,9 +1,9 @@+{-# LANGUAGE DeriveAnyClass #-}+ module Render.Unlit.Colored.Model   ( Model-+  , Vertex   , VertexAttrs-  , vkVertexAttrs-   , rgbF   , black   , white@@ -16,19 +16,14 @@ import Geomancy (Transform, Vec4, vec4) import Geomancy.Vec3 qualified as Vec3 import Resource.Model qualified as Model-import Vulkan.Core10 qualified as Vk import Vulkan.NamedType ((:::))  type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  type VertexAttrs = "RGBA" ::: Vec4  type InstanceAttrs = Transform--vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- vColor :: vec4-  ]  {-# INLINE rgbF #-} rgbF :: Float -> Float -> Float -> VertexAttrs
src/Render/Unlit/Colored/Pipeline.hs view
@@ -18,13 +18,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag)-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) import Render.Unlit.Colored.Code qualified as Code import Render.Unlit.Colored.Model qualified as Model -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.InstanceAttrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -34,7 +34,7 @@      )   => Bool   -> Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate useDepth multisample tset0 rp = do@@ -51,7 +51,7 @@      )   => Bool   -> Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocateWireframe useDepth multisample tset0 rp = do@@ -62,21 +62,15 @@     rp   pure p -config :: Bool -> Tagged Scene DsBindings -> Config+config :: Bool -> Tagged Scene DsLayoutBindings -> Config config useDepth (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   , Graphics.cBlend        = True   , Graphics.cDepthTest    = useDepth   , Graphics.cDepthWrite   = useDepth   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos-      , (Vk.VERTEX_INPUT_RATE_VERTEX, Model.vkVertexAttrs)-      , instanceTransform-      ]  stageCode  :: Graphics.StageCode stageCode = Graphics.basicStages Code.vert Code.frag@@ -90,7 +84,7 @@ fragSpirv :: ByteString fragSpirv = $(compileFrag Code.frag) -configWireframe :: Bool -> Tagged Scene DsBindings -> Config+configWireframe :: Bool -> Tagged Scene DsLayoutBindings -> Config configWireframe useDepth tset0 = (config useDepth tset0)   { Graphics.cTopology = Vk.PRIMITIVE_TOPOLOGY_LINE_LIST   }
+ src/Render/Unlit/Line2d/Code.hs view
@@ -0,0 +1,61 @@+module Render.Unlit.Line2d.Code+  ( vert+  , frag+  ) where++import RIO++import Render.Code (Code, glsl)+import Render.DescSets.Set0.Code (set0binding0)++vert :: Code+vert = fromString+  [glsl|+    #version 450++    ${set0binding0}++    layout(location = 0) in vec3 vPosition;++    layout(location = 2) in vec4 iPositionA;+    layout(location = 1) in vec4 iColorA;++    layout(location = 4) in vec4 iPositionB;+    layout(location = 3) in vec4 iColorB;++    layout(location = 0) out vec4 fColor;++    void main() {+      vec2 xBasis = normalize(iPositionB.xy - iPositionA.xy);+      vec2 yBasis = vec2(-xBasis.y, xBasis.x);++      float width = mix(iPositionA.w, iPositionB.w, vPosition.z);+      fColor = mix(iColorA, iColorB, vPosition.z);++      vec2 offsetA = iPositionA.xy + width * (vPosition.x * xBasis + vPosition.y * yBasis);+      vec2 offsetB = iPositionB.xy + width * (vPosition.x * xBasis + vPosition.y * yBasis);++      vec2 point = mix(offsetA, offsetB, vPosition.z);++      vec4 fPosition = vec4(point, 0, 1);++      gl_Position+        = scene.projection+        * scene.view+        * fPosition;+    }+  |]++frag :: Code+frag = fromString+  [glsl|+    #version 450++    layout(location = 0) in vec4 fColor;++    layout(location = 0) out vec4 oColor;++    void main() {+      oColor = fColor;+    }+  |]
+ src/Render/Unlit/Line2d/Draw.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE OverloadedLists #-}++module Render.Unlit.Line2d.Draw where++import RIO++import Vulkan.Core10 qualified as Vk+import Vulkan.NamedType ((:::))++import Engine.Vulkan.Types (Bound(..))+import Render.Unlit.Line2d.Model qualified as Model+import Resource.Buffer qualified as Buffer++batch+  :: (MonadIO m, Foldable t)+  => Vk.CommandBuffer+  -> Model.Segment+  -> Buffer.Allocated s Model.InstanceAttrs+  -> t ("firstInstance" ::: Word32, "instanceCount" ::: Word32)+  -> Bound dsl vertices instances m ()+batch cmd vertices points ranges =+  when (Buffer.aUsed points >= 2) do -- XXX: at least one segment to draw+    bind cmd vertices points+    -- TODO: check bindings+    Bound $+      traverse_ (segments cmd vertices) ranges++single+  :: MonadIO m+  => Vk.CommandBuffer+  -> Model.Segment+  -> Buffer.Allocated s Model.InstanceAttrs+  -> Bound dsl vertices instances m ()+single cmd vertices points =+  batch cmd vertices points $+    Just+      ( 0+      , Buffer.aUsed points+      )++bind+  :: MonadIO io+  => Vk.CommandBuffer+  -> Model.Segment+  -> Model.Buffer s+  -> io ()+bind cmd vertices points = do+  Vk.cmdBindVertexBuffers+    cmd+    0+    buffers+    offsets+  where+    buffers =+      [ Buffer.aBuffer vertices+      , Buffer.aBuffer points+      , Buffer.aBuffer points+      ]++    offsets =+      [ 0+      , 0+      , 4*4 + 4*4 -- vec4, vec4+      ]++segments+  :: MonadIO io+  => Vk.CommandBuffer+  -> Buffer.Allocated s a+  -> ("firstInstance" ::: Word32, "instanceCount" ::: Word32)+  -> io ()+segments cmd vertices (offset, size) =+  when (numSegments > 0) $+    Vk.cmdDraw+      cmd+      vertexCount+      instanceCount+      firstVertex+      firstInstance+  where+    firstVertex = 0+    vertexCount = Buffer.aUsed vertices++    numSegments = size - 1+    firstInstance = offset+    instanceCount = numSegments
+ src/Render/Unlit/Line2d/Model.hs view
@@ -0,0 +1,201 @@+{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}++{-# LANGUAGE OverloadedLists #-}++module Render.Unlit.Line2d.Model+  ( Segment++  , Vertex+  , createVertices+  , verticesRoundRound+  , Points++  , point+  , InstanceAttrs(..)++  , Buffer+  , Observer+  , Buffer.observeCoherentResize_++  , Batches(..)+  , BatchObserver+  , newBatchObserver+  , observeCoherentBatches+  ) where++import RIO++import Control.Monad.Trans.Resource qualified as Resource+import Data.Vector.Generic qualified as Generic+import Foreign.Storable.Generic (GStorable)+import Geomancy (Vec2, Vec4, vec3)+import Geomancy.Vec3 qualified as Vec3+import RIO.Vector qualified as Vector+import RIO.Vector.Storable qualified as Storable+import Vulkan.Core10 qualified as Vk+import Vulkan.NamedType ((:::))++import Engine.Vulkan.Format (HasVkFormat(..))+import Engine.Vulkan.Pipeline.Graphics (HasVertexInputBindings(..), instanceFormat)+import Engine.Vulkan.Types (MonadVulkan, Queues)+import Engine.Worker qualified as Worker+import Resource.Buffer qualified as Buffer+import Resource.Model qualified as Model++type Segment = Buffer.Allocated 'Buffer.Staged Vec3.Packed+type Vertex = Model.Vertex3d ()++createVertices+  :: MonadVulkan env m+  => Maybe Text+  -> Queues Vk.CommandPool+  -> Float+  -> m Segment+createVertices label pools resolution = do+  Buffer.createStaged+    label+    pools+    Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT+    (Storable.length vertices)+    vertices+  where+    vertices = verticesRoundRound resolution++{- |+  Generate mesh for the round joints / round caps special case.++  With a bit of vertex shader code it allows drawing a batch of+  smooth lines in one call.+-}+verticesRoundRound :: Float -> Storable.Vector Vec3.Packed+verticesRoundRound resolution =+  Storable.fromList . map Vec3.Packed $+    mconcat+      [ segment+      , leftSemi+      , rightSemi+      ]+  where+    segment =+      [ vec3 0 (-0.5) 0+      , vec3 0 (-0.5) 1+      , vec3 0   0.5  1+      , vec3 0 (-0.5) 0+      , vec3 0   0.5  1+      , vec3 0   0.5  0+      ]++    leftSemi = do+      step <- [0..resolution]+      let+        theta0 = pi / 2 + (step + 0) * pi / resolution+        theta1 = pi / 2 + (step + 1) * pi / resolution+        a = vec3 0 0 0+        b = vec3 (cos theta0) (sin theta0) 0 * 0.5+        c = vec3 (cos theta1) (sin theta1) 0 * 0.5+      [ a, b, c ]++    rightSemi = do+      step <- [0..resolution]+      let+        theta0 = 3 * pi / 2 + (step + 0) * pi / resolution+        theta1 = 3 * pi / 2 + (step + 1) * pi / resolution+        a = vec3 0 0 0+        b = vec3 (cos theta0) (sin theta0) 2 * 0.5+        c = vec3 (cos theta1) (sin theta1) 2 * 0.5+      [ a, b, c ]++type Points = Storable.Vector InstanceAttrs++point :: Float -> Vec4 -> Vec2 -> InstanceAttrs+point width color position = InstanceAttrs+  { color    = color+  , position = Vec3.Packed (Vec3.fromVec2 position 0)+  , width    = width+  }++data InstanceAttrs = InstanceAttrs+  { color    :: Vec4++  , position :: Vec3.Packed+  , width    :: Float+  } deriving (Eq, Show, Generic)++-- XXX: okay, the layout matches+instance GStorable InstanceAttrs++instance HasVkFormat InstanceAttrs where+  getVkFormat =+    [ Vk.FORMAT_R32G32B32A32_SFLOAT -- color+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- position+width+    ]++instance HasVertexInputBindings InstanceAttrs where+  vertexInputBindings =+    -- XXX: instance buffer is bound 2 times with a shift+    replicate 2 $ instanceFormat @InstanceAttrs++type Buffer s = Buffer.Allocated s InstanceAttrs++type Observer = Buffer.ObserverCoherent InstanceAttrs+type BatchObserver = Worker.ObserverIO (Buffer 'Buffer.Coherent, Ranges)+type Ranges = [(Word32, Word32)]++newtype Batches v a = Batches [v a]+  deriving (Eq, Show, Ord, Functor, Foldable, Traversable, Semigroup, Monoid)++newBatchObserver+  :: ( MonadVulkan env m+     , Resource.MonadResource m+     )+  => "initial size" ::: Int+  -> m BatchObserver+newBatchObserver initialSize = do+  initialBuffer <- Buffer.createCoherent+    (Just "Line2D")+    Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT+    initialSize+    mempty+  observer <- Worker.newObserverIO (initialBuffer, [])++  context <- ask+  void $! Resource.register do+    (currentBuffer, _ranges) <- Worker.readObservedIO observer+    Buffer.destroy context currentBuffer++  pure (observer :: BatchObserver)++observeCoherentBatches+  :: ( Worker.GetOutput output ~ Batches Storable.Vector InstanceAttrs+     , Worker.HasOutput output+     , MonadVulkan env m+     )+  => output+  -> BatchObserver+  -> m ()+observeCoherentBatches source observer =+  Worker.observeIO_ source observer \(buf, _ranges) (Batches batches) -> do+    let segments = filterSegments batches+    buf' <- Buffer.updateCoherentResize_ buf $+      Storable.concat segments+    pure (buf', toRanges segments)++filterSegments+  :: Generic.Vector v a+  => [v a]+  -> [v a]+filterSegments = filter \v ->+  Vector.length v >= 2++toRanges+  :: ( Generic.Vector v a+     , Integral i+     )+  => [v a]+  -> [(i, i)]+toRanges = collect . filter (not . Vector.null)+  where+    collect v = Vector.toList @Vector $ Vector.zip offsets sizes+      where+        sizes = Vector.fromList $ map (fromIntegral . Vector.length) v+        offsets = Vector.scanl' (+) 0 sizes
+ src/Render/Unlit/Line2d/Pipeline.hs view
@@ -0,0 +1,69 @@+module Render.Unlit.Line2d.Pipeline+  ( Pipeline+  , allocate++  , Config+  , config++  , stageCode+  , stageSpirv+  ) where++import RIO++import Control.Monad.Trans.Resource (MonadResource, ResourceT)+import Data.Tagged (Tagged(..))+import Vulkan.Core10 qualified as Vk++import Engine.Vulkan.Pipeline.Graphics qualified as Graphics+import Engine.Vulkan.Types (DsLayoutBindings, HasRenderPass(..), MonadVulkan)+import Render.Code (compileVert, compileFrag)+import Render.DescSets.Set0 (Scene)+import Render.Unlit.Line2d.Code qualified as Code+import Render.Unlit.Line2d.Model qualified as Model+import Resource.Region qualified as Region++type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.InstanceAttrs+type Config = Graphics.Configure Pipeline+type instance Graphics.Specialization Pipeline = ()++allocate+  :: ( MonadVulkan env m+     , MonadResource m+     , HasRenderPass renderpass+     )+  => Bool+  -> Vk.SampleCountFlagBits+  -> Tagged Scene DsLayoutBindings+  -> renderpass+  -> ResourceT m Pipeline+allocate useDepth multisample tset0 rp =+  Region.local $+    Graphics.allocate+      Nothing+      multisample+      (config useDepth tset0)+      rp++config :: Bool -> Tagged Scene DsLayoutBindings -> Config+config useDepth (Tagged set0) = Graphics.baseConfig+  { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]+  , Graphics.cStages       = stageSpirv+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline+  , Graphics.cBlend        = True+  , Graphics.cDepthTest    = useDepth+  , Graphics.cDepthWrite   = useDepth+  , Graphics.cCull         = Vk.CULL_MODE_NONE+  }++stageCode  :: Graphics.StageCode+stageCode = Graphics.basicStages Code.vert Code.frag++stageSpirv :: Graphics.StageSpirv+stageSpirv = Graphics.basicStages vertSpirv fragSpirv++vertSpirv :: ByteString+vertSpirv = $(compileVert Code.vert)++fragSpirv :: ByteString+fragSpirv = $(compileFrag Code.frag)
src/Render/Unlit/Sprite/Code.hs view
@@ -19,14 +19,15 @@     layout(location = 1) in  vec4 iFrag;     layout(location = 2) in  vec4 iTint;     layout(location = 3) in  vec4 iOutline;-    layout(location = 4) in ivec2 iTextureIds;+    layout(location = 4) in  vec4 iAnimation;     layout(location = 5) in uvec2 iTextureSize;+    layout(location = 6) in ivec2 iTextureIds;      layout(location = 0)      out  vec2 fTexCoord;     layout(location = 1) flat out  vec4 fTint;     layout(location = 2) flat out  vec4 fOutline;-    layout(location = 3) flat out ivec2 fTextureIds;-    layout(location = 4) flat out uvec2 fTextureSize;+    layout(location = 3) flat out  vec2 fStepSize;+    layout(location = 4) flat out ivec2 fTextureIds;      vec2 positions[6] = vec2[](       vec2(-0.5, -0.5),@@ -49,6 +50,12 @@     );      void main() {+      // pass-through+      fTint = iTint;+      fOutline = iOutline;+      fTextureIds = iTextureIds;+      fStepSize = 1.0 / vec2(iTextureSize);+       vec2 pos = positions[gl_VertexIndex];        gl_Position@@ -59,10 +66,17 @@       vec2 uv = texCoords[gl_VertexIndex];       fTexCoord = iFrag.xy + uv * iFrag.zw; -      fTint = iTint;-      fOutline = iOutline;-      fTextureIds = iTextureIds;-      fTextureSize = iTextureSize;+      float time = 0;+      float frame = 0;+      if (iAnimation[0] > 1) {+        time = scene.tweaks.a + iAnimation[3];+        frame = mod(trunc(time * iAnimation[1]), iAnimation[0]) - 1.0;+        fTexCoord +=+          vec2(+            frame * iFrag.z + frame * iAnimation[2] / float(iTextureSize.x),+            0+          );+      }     }   |] @@ -78,8 +92,8 @@     layout(location = 0)      in  vec2 fTexCoord;     layout(location = 1) flat in  vec4 fTint;     layout(location = 2) flat in  vec4 fOutline;-    layout(location = 3) flat in ivec2 fTextureIds;-    layout(location = 4) flat in uvec2 fTextureSize;+    layout(location = 3) flat in  vec2 fStepSize;+    layout(location = 4) flat in ivec2 fTextureIds;      layout(location = 0) out vec4 outColor; @@ -87,17 +101,16 @@     layout(constant_id=1) const bool  doOutline = false;      vec4 tap(vec2 uv) {-      return texture(+      return textureLod(         sampler2D(           textures[nonuniformEXT(fTextureIds.t)],           samplers[nonuniformEXT(fTextureIds.s)]         ),-        fTexCoord + uv+        fTexCoord + uv,+        0       );     } -    vec2 step_size = 1.0 / vec2(fTextureSize);-     void main() {       vec4 texel = tap(vec2(0)); @@ -113,10 +126,10 @@         if (fOutline.a > 0.0 && texel.a < 1.0) {           float alpha = 0.0; -          alpha += tap(vec2(step_size.x,  0.0)         ).a / 4.0;-          alpha += tap(vec2(-step_size.x, 0.0)         ).a / 4.0;-          alpha += tap(vec2(0.0,          step_size.y) ).a / 4.0;-          alpha += tap(vec2(0.0,          -step_size.y)).a / 4.0;+          alpha += tap(vec2(fStepSize.x,  0.0)         ).a / 4.0;+          alpha += tap(vec2(-fStepSize.x, 0.0)         ).a / 4.0;+          alpha += tap(vec2(0.0,          fStepSize.y) ).a / 4.0;+          alpha += tap(vec2(0.0,          -fStepSize.y)).a / 4.0;            outColor += fOutline * alpha;         }
src/Render/Unlit/Sprite/Model.hs view
@@ -7,13 +7,15 @@   , fromTexture   , fromAtlas -  , vkInstanceAttrs+  , animate_   ) where  import RIO +import Engine.Vulkan.Format (HasVkFormat(..))+import Engine.Vulkan.Pipeline.Graphics (HasVertexInputBindings(..), instanceFormat) import Foreign.Storable.Generic (GStorable)-import Geomancy (Vec2, Vec4, UVec2, withUVec2, vec2)+import Geomancy (Vec2, Vec4, UVec2, vec2, vec4, withUVec2, withVec2) import Geomancy.Vec4 qualified as Vec4 import Render.Samplers qualified as Samplers import Resource.Buffer qualified as Buffer@@ -21,10 +23,9 @@ import Resource.Image.Atlas qualified as Atlas import RIO.Vector.Storable qualified as Storable import Vulkan.Core10 qualified as Vk+import Vulkan.NamedType ((:::)) import Vulkan.Zero (Zero(..)) -type StorableAttrs = Storable.Vector InstanceAttrs- data InstanceAttrs = InstanceAttrs   { vertRect :: Vec4   , fragRect :: Vec4@@ -32,12 +33,15 @@   , tint    :: Vec4   , outline :: Vec4 +  , animation :: Vec4 -- direction xy, number of frames, speed++  , textureSize :: UVec2   , samplerId :: Int32   , textureId :: Int32-  , textureSize :: UVec2   }   deriving (Show, Generic) +-- XXX: okay, the layout matches instance GStorable InstanceAttrs  instance Zero InstanceAttrs where@@ -48,22 +52,30 @@     , tint    = 0     , outline = 0 +    , animation = 0++    , textureSize = 0     , samplerId = 0     , textureId = 0-    , textureSize = 0     } -vkInstanceAttrs :: [Vk.Format]-vkInstanceAttrs =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- Quad scale+offset-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- UV scale+offset-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- Tint-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- Outline (when enabled)+instance HasVkFormat InstanceAttrs where+  getVkFormat =+    [ Vk.FORMAT_R32G32B32A32_SFLOAT -- Quad scale+offset+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- UV scale+offset+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- Tint+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- Outline (when enabled) -  , Vk.FORMAT_R32G32_SINT -- Sampler + texture IDs-  , Vk.FORMAT_R32G32_UINT -- Texture size-  ]+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- Linear animation direction/duration, num frames, phase +    , Vk.FORMAT_R32G32_UINT -- Texture size+    , Vk.FORMAT_R32G32_SINT -- Sampler + texture IDs+    ]++instance HasVertexInputBindings InstanceAttrs where+  vertexInputBindings = [instanceFormat @InstanceAttrs]++type StorableAttrs = Storable.Vector InstanceAttrs type InstanceBuffer stage = Buffer.Allocated stage InstanceAttrs  fromTexture@@ -80,9 +92,11 @@     , tint    = 1     , outline = 0 +    , animation = 0++    , textureSize = 0     , samplerId = sampler     , textureId = texture-    , textureSize = 0     }  fromAtlas@@ -95,14 +109,16 @@ fromAtlas texture atlas scale atlasPos worldPos =   InstanceAttrs     { vertRect = Vec4.fromVec22 worldPos (tileSize * scale)-    , fragRect = Vec4.fromVec22 (atlasPos * uvScale) uvScale+    , fragRect = Vec4.fromVec22 ((atlasPos + tileMargins / tileSize) * uvScale) uvScale      , tint    = 1     , outline = 0 +    , animation = 0++    , textureSize = Atlas.sizePx atlas     , samplerId = Samplers.nearest Samplers.indices     , textureId = texture-    , textureSize = Atlas.sizePx atlas     }    where@@ -111,3 +127,25 @@     tileSize =       withUVec2 (Atlas.tileSizePx atlas) \tw th ->         vec2 (fromIntegral tw) (fromIntegral th)++    tileMargins =+      withUVec2 (Atlas.marginPx atlas) \mx my ->+        withVec2 atlasPos \px py ->+          vec2 (fromIntegral mx * px) (fromIntegral my * py)++-- | Simple animation controller with left-to-right linear cycle.+animate_+  :: "margin" ::: Float+  -> "num.frames" ::: Int+  -> "frame duration" ::: Float+  -> "phase" ::: Float+  -> InstanceAttrs+  -> InstanceAttrs+animate_ margin numFrames frameDuration phase attrs = attrs+  { animation =+        vec4+          (fromIntegral numFrames)+          frameDuration+          margin+          phase+  }
src/Render/Unlit/Sprite/Pipeline.hs view
@@ -17,7 +17,7 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag) import Render.DescSets.Set0 (Scene) import Render.Unlit.Sprite.Code qualified as Code@@ -34,7 +34,7 @@   => Vk.SampleCountFlagBits   -> Maybe Float   -> Bool-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample discardAlpha outline set0 = do@@ -46,13 +46,13 @@ config   :: Maybe Float   -> Bool-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> Config config discardAlpha outline (Tagged set0) =   Graphics.baseConfig     { Graphics.cStages         = stageSpirv     , Graphics.cDescLayouts    = Tagged @'[Scene] [set0]-    , Graphics.cVertexInput    = vertexInput+    , Graphics.cVertexInput    = Graphics.vertexInput @Pipeline     , Graphics.cDepthTest      = False     , Graphics.cDepthWrite     = False     , Graphics.cBlend          = True@@ -60,10 +60,6 @@     , Graphics.cSpecialization = specs     }   where-    vertexInput = Graphics.vertexInput-      [ (Vk.VERTEX_INPUT_RATE_INSTANCE, Model.vkInstanceAttrs)-      ]-     specs =       ( fromMaybe 0.0 discardAlpha       , outline
src/Render/Unlit/Textured/Model.hs view
@@ -1,113 +1,112 @@+{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}++{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE OverloadedRecordDot #-}+ module Render.Unlit.Textured.Model   ( Model+  , Vertex   , VertexAttrs-  , vkVertexAttrs -  , InstanceAttrs(..)-  , instanceAttrs--  , StorableAttrs-  , storableAttrs1+  , AttrsF(..)+  , Attrs+  , attrs -  , InstanceBuffers(..)+  , Stores+  , attrStores+  , stores1+  , Buffers    , TextureParams(..)-  , vkInstanceTexture -  , allocateInstancesWith-  , allocateInstancesCoherent-  , allocateInstancesCoherent_-  , updateCoherentResize_-  , Transform+  , ObserverCoherent   ) where  import RIO -import Foreign (Storable(..)) import Geomancy (Transform, Vec2, Vec4) import Geomancy.Vec3 qualified as Vec3 import RIO.Vector.Storable qualified as Storable-import UnliftIO.Resource (MonadResource, ReleaseKey, ResourceT, allocate) import Vulkan.Core10 qualified as Vk import Vulkan.NamedType ((:::)) import Vulkan.Zero (Zero(..))+import Geomancy.Gl.Block (Block)+import Geomancy.Gl.Block qualified as Block -import Engine.Vulkan.Types (HasVulkan)+import Engine.Types (HKD)+import Engine.Vulkan.Format (HasVkFormat(..))+import Engine.Vulkan.Pipeline.Graphics (HasVertexInputBindings(..), instanceFormat)+import Engine.Worker qualified as Worker import Resource.Buffer qualified as Buffer import Resource.Model qualified as Model+import Resource.Model.Observer qualified as Observer  type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  type VertexAttrs = "uv" ::: Vec2 -vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32_SFLOAT -- vTexCoord :: vec2-  ]---- | Data for a single element.-data InstanceAttrs = InstanceAttrs-  { textureParams :: TextureParams-  , transformMat4 :: Transform+data AttrsF f = Attrs+  { params     :: HKD f TextureParams+  , transforms :: HKD f Transform   }+  deriving (Generic) -instance Zero InstanceAttrs where-  zero = InstanceAttrs-    { textureParams = zero-    , transformMat4 = mempty+type Attrs = AttrsF Identity+deriving instance Show Attrs++instance HasVertexInputBindings Attrs where+  vertexInputBindings =+    [ instanceFormat @TextureParams+    , instanceFormat @Transform+    ]++type Stores = AttrsF Storable.Vector+deriving instance Show Stores++type Buffers = AttrsF (Buffer.Allocated 'Buffer.Coherent)+deriving instance Show Buffers+instance Observer.VertexBuffers Buffers+type ObserverCoherent = Worker.ObserverIO Buffers++instance Observer.UpdateCoherent Buffers Stores++instance Model.HasVertexBuffers Buffers where+  type VertexBuffersOf Buffers = Attrs++instance Zero Attrs where+  zero = Attrs+    { params = zero+    , transforms = mempty     } -instanceAttrs :: Int32 -> Int32 -> [Transform] -> InstanceAttrs-instanceAttrs samplerId textureId transforms = InstanceAttrs-  { textureParams = zero+attrs :: Int32 -> Int32 -> [Transform] -> Attrs+attrs samplerId textureId transforms = Attrs+  { params = zero       { tpSamplerId = samplerId       , tpTextureId = textureId       }-  , transformMat4 = mconcat transforms+  , transforms = mconcat transforms   } --- | Intermediate data to be shipped.-type StorableAttrs =-  ( Storable.Vector TextureParams-  , Storable.Vector Transform-  )+attrStores :: Foldable t => t Attrs -> Stores+attrStores source = Attrs+  { params = Storable.fromList $ map (.params) $ toList source+  , transforms = Storable.fromList $ map (.transforms) $ toList source+  } -storableAttrs1 :: Int32 -> Int32 -> [Transform] -> StorableAttrs-storableAttrs1 samplerId textureId transforms =-  ( Storable.singleton textureParams-  , Storable.singleton transformMat4-  )+stores1 :: Int32 -> Int32 -> [Transform] -> Stores+stores1 samplerId textureId transforms =+  Attrs+    { params = Storable.singleton attrs1.params+    , transforms = Storable.singleton attrs1.transforms+    }   where-    InstanceAttrs{..} = instanceAttrs+    attrs1 = attrs       samplerId       textureId       transforms --- | GPU-bound data.-data InstanceBuffers textureStage transformStage = InstanceBuffers-  { ibTexture   :: InstanceTexture textureStage-  , ibTransform :: InstanceTransform transformStage-  }--type InstanceTexture stage = Buffer.Allocated stage TextureParams--type InstanceTransform stage = Buffer.Allocated stage Transform--instance Model.HasVertexBuffers (InstanceBuffers textureStage transformStage) where-  type VertexBuffersOf (InstanceBuffers textureStage transformStage) = InstanceAttrs--  {-# INLINE getVertexBuffers #-}-  getVertexBuffers InstanceBuffers{..} =-    [ Buffer.aBuffer ibTexture-    , Buffer.aBuffer ibTransform-    ]--  {-# INLINE getInstanceCount #-}-  getInstanceCount InstanceBuffers{..} =-    min-      (Buffer.aUsed ibTexture)-      (Buffer.aUsed ibTransform)- data TextureParams = TextureParams   { tpScale     :: Vec2   , tpOffset    :: Vec2@@ -115,7 +114,8 @@   , tpSamplerId :: Int32   , tpTextureId :: Int32   }-  deriving (Show)+  deriving (Generic, Show, Block)+  deriving Storable via (Block.Packed TextureParams)  instance Zero TextureParams where   zero = TextureParams@@ -126,91 +126,9 @@     , tpTextureId = minBound     } -instance Storable TextureParams where-  alignment ~_ = 4--  sizeOf ~_ = 8 + 8 + 16 + 4 + 4--  poke ptr TextureParams{..} = do-    pokeByteOff ptr  0 tpScale-    pokeByteOff ptr  8 tpOffset-    pokeByteOff ptr 16 tpGamma-    pokeByteOff ptr 32 tpSamplerId-    pokeByteOff ptr 36 tpTextureId--  peek ptr = do-    tpScale     <- peekByteOff ptr  0-    tpOffset    <- peekByteOff ptr  8-    tpGamma     <- peekByteOff ptr 16-    tpSamplerId <- peekByteOff ptr 32-    tpTextureId <- peekByteOff ptr 36-    pure TextureParams{..}--vkInstanceTexture :: [Vk.Format]-vkInstanceTexture =-  [ Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureScaleOffset :: vec4-  , Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureGamma       :: vec4-  , Vk.FORMAT_R32G32_SINT         -- iTextureIds         :: ivec2-  ]--allocateInstancesWith-  :: ( MonadResource m-     , MonadUnliftIO m-     )-  => (Vk.BufferUsageFlagBits -> Int -> Storable.Vector TextureParams -> m (InstanceTexture texture))-  -> (Vk.BufferUsageFlagBits -> Int -> Storable.Vector Transform -> m (InstanceTransform transform))-  -> (forall stage a . Buffer.Allocated stage a -> m ())-  -> [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers texture transform)-allocateInstancesWith createTextures createTransforms bufferDestroy instances = do-  ul <- askUnliftIO-  allocate (create ul) (destroy ul)-  where-    textures   = Storable.fromList $ map textureParams instances-    transforms = Storable.fromList $ map transformMat4 instances-    numInstances = Storable.length textures--    create (UnliftIO ul) = ul do-      ibTexture   <- createTextures   Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances textures-      ibTransform <- createTransforms Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances transforms-      pure InstanceBuffers{..}--    destroy (UnliftIO ul) InstanceBuffers{..} = ul do-      bufferDestroy ibTexture-      bufferDestroy ibTransform--allocateInstancesCoherent-  :: ( MonadReader env m-     , HasVulkan env-     , MonadResource m-     , MonadUnliftIO m-     )-  => [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-allocateInstancesCoherent instances = do-  context <- ask-  allocateInstancesWith-    (Buffer.createCoherent context)-    (Buffer.createCoherent context)-    (Buffer.destroy context)-    instances--allocateInstancesCoherent_-  :: (HasVulkan env)-  => Int-  -> ResourceT (RIO env) (InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-allocateInstancesCoherent_ n =-  fmap snd $ allocateInstancesCoherent (replicate n zero)--updateCoherentResize_-  :: ( HasVulkan context-     , MonadUnliftIO m-     )-  => context-  -> InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent-  -> (Storable.Vector TextureParams, Storable.Vector Transform)-  -> m (InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-updateCoherentResize_ context InstanceBuffers{..} (textures, transforms) =-  InstanceBuffers-    <$> Buffer.updateCoherentResize_ context ibTexture textures-    <*> Buffer.updateCoherentResize_ context ibTransform transforms+instance HasVkFormat TextureParams where+  getVkFormat =+    [ Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureScaleOffset :: vec4+    , Vk.FORMAT_R32G32B32A32_SFLOAT -- iTextureGamma       :: vec4+    , Vk.FORMAT_R32G32_SINT         -- iTextureIds         :: ivec2+    ]
src/Render/Unlit/Textured/Pipeline.hs view
@@ -18,13 +18,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag)-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) import Render.Unlit.Textured.Code qualified as Code import Render.Unlit.Textured.Model qualified as Model -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.Attrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -33,7 +33,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 rp = do@@ -49,7 +49,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocateBlend multisample tset0 rp = do@@ -60,21 +60,14 @@     rp   pure p -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos -- vPosition-      , (Vk.VERTEX_INPUT_RATE_VERTEX,   Model.vkVertexAttrs)-      , (Vk.VERTEX_INPUT_RATE_INSTANCE, Model.vkInstanceTexture)-      , instanceTransform-      ] -configBlend :: Tagged Scene DsBindings -> Config+configBlend :: Tagged Scene DsLayoutBindings -> Config configBlend tset0 = (config tset0)   { Graphics.cBlend      = True   , Graphics.cDepthWrite = False
src/Render/Unlit/TileMap/Code.hs view
@@ -27,15 +27,19 @@     layout(location = 5) in vec2  iMapTextureSize;     layout(location = 6) in vec2  iTilesetTextureSize;     layout(location = 7) in vec2  iTileSize;+    layout(location = 8) in vec2  iTilesetOffset;+    layout(location = 9) in vec2  iTilesetBorder;      // transformMat-    layout(location = 8) in mat4 iModel;+    layout(location = 10) in mat4 iModel;      layout(location = 0)      out  vec2 fTexCoord;     layout(location = 1)      out  vec2 fPixCoord;     layout(location = 2) flat out ivec4 fTextureIds;-    layout(location = 3) flat out  vec2 fTilesetTextureSize;+    layout(location = 3) flat out  vec2 fTilesetTextureSizeInv;     layout(location = 4) flat out  vec2 fTileSize;+    layout(location = 5) flat out  vec2 fTilesetOffset;+    layout(location = 6) flat out  vec2 fTilesetBorder;      void main() {       vec4 fPosition = iModel * vec4(vPosition, 1.0);@@ -49,8 +53,10 @@       fTexCoord = fPixCoord / iMapTextureSize / iTileSize;        fTextureIds = iTextureIds;-      fTilesetTextureSize = iTilesetTextureSize;+      fTilesetTextureSizeInv = 1.0 / iTilesetTextureSize;       fTileSize = iTileSize;+      fTilesetOffset = iTilesetOffset * fTilesetTextureSizeInv;+      fTilesetBorder = iTilesetBorder * fTilesetTextureSizeInv;     }   |] @@ -68,13 +74,15 @@      // combined: tileset, tileset sampler, map, repeat     layout(location = 2) flat in ivec4 fTextureIds;-    layout(location = 3) flat in vec2 fTilesetTextureSize;+    layout(location = 3) flat in vec2 fTilesetTextureSizeInv;     layout(location = 4) flat in vec2 fTileSize;+    layout(location = 5) flat in vec2 fTilesetOffset;+    layout(location = 6) flat in vec2 fTilesetBorder;      layout(location = 0) out vec4 oColor;      int tilesetTextureIx = fTextureIds[0];-    int tilesetSamplerIx = fTextureIds[1];+    int tilesetSamplerIx = fTextureIds[1]; // XXX: can have repeat, but not mips     int mapTextureIx     = fTextureIds[2];     int repeatTiles      = fTextureIds[3]; @@ -86,24 +94,43 @@         discard;       } -      vec4 map = texture(+      vec4 map = textureLod(         sampler2D(           textures[nonuniformEXT(mapTextureIx)],           samplers[$samplerId]         ),-        fTexCoord+        fTexCoord,+        0       ); -      vec2 spriteOffset = floor(map.xy * 256.0) * fTileSize;+      vec2 tilePos = floor(map.xy * 256.0);+      vec2 spriteOffset = tilePos * fTileSize;+       vec2 spriteCoord = mod(fPixCoord, fTileSize);-      vec2 spriteUV = round(spriteOffset + spriteCoord) / fTilesetTextureSize;+      uint flags = uint(map.w * 256.0); -      oColor = texture(+      // XXX: Anti-diagonal flip first, to allow rotation with H/V flips+      if ((flags & 0x20) == 0x20)+        spriteCoord = spriteCoord.yx;+      if ((flags & 0x40) == 0x40)+        spriteCoord.x = fTileSize.x - spriteCoord.x;+      if ((flags & 0x80) == 0x80)+        spriteCoord.y = fTileSize.y - spriteCoord.y;++      vec2 tilesetPadding = fTilesetOffset + tilePos * fTilesetBorder;++      vec2 spriteUV =+        spriteOffset * fTilesetTextureSizeInv ++        spriteCoord * fTilesetTextureSizeInv ++        tilesetPadding;++      oColor = textureLod(         sampler2D(           textures[nonuniformEXT(tilesetTextureIx)],           samplers[nonuniformEXT(tilesetSamplerIx)]         ),-        spriteUV+        spriteUV,+        0       );     }   |]
src/Render/Unlit/TileMap/Model.hs view
@@ -1,92 +1,77 @@+{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}++{-# LANGUAGE DeriveAnyClass #-}+ module Render.Unlit.TileMap.Model   ( Model-  , VertexAttrs-  , vkVertexAttrs -  , InstanceAttrs(..)-  -- , instanceAttrs--  , StorableAttrs-  -- , storableAttrs1+    -- * Vertex data+  , Vertex+  , VertexAttrs -  , InstanceBuffers(..)+    -- * Instance data+  , AttrsF(..)+  , Attrs+  , Stores+  , Buffers    , TileMapParams(..)-  , vkInstanceTileMap -  , allocateInstancesWith-  , allocateInstancesCoherent-  , allocateInstancesCoherent_-  , updateCoherentResize_-  , Transform+  , ObserverCoherent   ) where  import RIO -import Foreign (Storable(..))+import Foreign.Storable.Generic (GStorable) import Geomancy (IVec4, Transform, Vec2) import Geomancy.Vec3 qualified as Vec3 import RIO.Vector.Storable qualified as Storable-import UnliftIO.Resource (MonadResource, ReleaseKey, ResourceT, allocate)-import Vulkan.Core10 qualified as Vk import Vulkan.NamedType ((:::)) import Vulkan.Zero (Zero(..)) -import Engine.Vulkan.Types (HasVulkan)+import Engine.Types (HKD)+import Engine.Vulkan.Format (HasVkFormat)+import Engine.Vulkan.Pipeline.Graphics (HasVertexInputBindings(..), instanceFormat)+import Engine.Worker qualified as Worker import Resource.Buffer qualified as Buffer import Resource.Model qualified as Model+import Resource.Model.Observer qualified as Observer +-- XXX: Can be a quad, full screen-triangle or fancy-shaped viewport. type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs+type Vertex = Model.Vertex3d VertexAttrs  type VertexAttrs = "uv" ::: Vec2 -vkVertexAttrs :: [Vk.Format]-vkVertexAttrs =-  [ Vk.FORMAT_R32G32_SFLOAT -- vTexCoord :: vec2-  ]---- | Data for a single element.-data InstanceAttrs = InstanceAttrs-  { tilemapParams :: TileMapParams-  , transformMat4 :: Transform+data AttrsF f = Attrs+  { params     :: HKD f TileMapParams+  , transforms :: HKD f Transform   }--instance Zero InstanceAttrs where-  zero = InstanceAttrs-    { tilemapParams = zero-    , transformMat4 = mempty-    }---- | Intermediate data to be shipped.-type StorableAttrs =-  ( Storable.Vector TileMapParams-  , Storable.Vector Transform-  )+  deriving (Generic) --- | GPU-bound data.-data InstanceBuffers tilemapStage transformStage = InstanceBuffers-  { ibTileMap   :: InstanceTileMap tilemapStage-  , ibTransform :: InstanceTransform transformStage-  }+type Attrs = AttrsF Identity+deriving instance Show Attrs+-- XXX: not correct, but shouldn't be needed+-- instance GStorable Attrs -type InstanceTileMap stage = Buffer.Allocated stage TileMapParams+instance HasVertexInputBindings Attrs where+  vertexInputBindings =+    [ instanceFormat @TileMapParams+    , instanceFormat @Transform+    ] -type InstanceTransform stage = Buffer.Allocated stage Transform+type Stores = AttrsF Storable.Vector+deriving instance Show Stores -instance Model.HasVertexBuffers (InstanceBuffers tilemapStage transformStage) where-  type VertexBuffersOf (InstanceBuffers tilemapStage transformStage) = InstanceAttrs+type Buffers = AttrsF (Buffer.Allocated 'Buffer.Coherent)+deriving instance Show Buffers+instance Observer.VertexBuffers Buffers+type ObserverCoherent = Worker.ObserverIO Buffers -  {-# INLINE getVertexBuffers #-}-  getVertexBuffers InstanceBuffers{..} =-    [ Buffer.aBuffer ibTileMap-    , Buffer.aBuffer ibTransform-    ]+instance Observer.UpdateCoherent Buffers Stores -  {-# INLINE getInstanceCount #-}-  getInstanceCount InstanceBuffers{..} =-    min-      (Buffer.aUsed ibTileMap)-      (Buffer.aUsed ibTransform)+instance Model.HasVertexBuffers Buffers where+  type VertexBuffersOf Buffers = Attrs  data TileMapParams = TileMapParams   { tmpTextureIds         :: IVec4@@ -95,9 +80,14 @@   , tmpMapTextureSize     :: Vec2   , tmpTilesetTextureSize :: Vec2   , tmpTileSize           :: Vec2+  , tmpTilesetOffset      :: Vec2+  , tmpTilesetBorder      :: Vec2   }-  deriving (Show)+  deriving (Generic, Show, HasVkFormat) +-- XXX: okay, the layout matches+instance GStorable TileMapParams+ instance Zero TileMapParams where   zero = TileMapParams     { tmpTextureIds         = 0@@ -106,98 +96,6 @@     , tmpMapTextureSize     = 1     , tmpTilesetTextureSize = 1     , tmpTileSize           = 1+    , tmpTilesetOffset      = 0+    , tmpTilesetBorder      = 0     }--instance Storable TileMapParams where-  alignment ~_ = 4--  sizeOf ~_ = 16 + 8 + 8 + 8 + 8 + 8--  poke ptr TileMapParams{..} = do-    pokeByteOff ptr  0 tmpTextureIds-    pokeByteOff ptr 16 tmpViewOffset-    pokeByteOff ptr 24 tmpViewportSize-    pokeByteOff ptr 32 tmpMapTextureSize-    pokeByteOff ptr 40 tmpTilesetTextureSize-    pokeByteOff ptr 48 tmpTileSize--  peek ptr = do-    tmpTextureIds         <- peekByteOff ptr  0-    tmpViewOffset         <- peekByteOff ptr 16-    tmpViewportSize       <- peekByteOff ptr 24-    tmpMapTextureSize     <- peekByteOff ptr 32-    tmpTilesetTextureSize <- peekByteOff ptr 48-    tmpTileSize           <- peekByteOff ptr 56-    pure TileMapParams{..}--vkInstanceTileMap :: [Vk.Format]-vkInstanceTileMap =-  [ Vk.FORMAT_R32G32B32A32_SINT -- tmpTextureIds         :: IVec4-  , Vk.FORMAT_R32G32_SFLOAT     -- tmpViewOffset         :: Vec2-  , Vk.FORMAT_R32G32_SFLOAT     -- tmpViewportSize       :: Vec2-  , Vk.FORMAT_R32G32_SFLOAT     -- tmpMapTextureSize     :: Vec2-  , Vk.FORMAT_R32G32_SFLOAT     -- tmpTilesetTextureSize :: Vec2-  , Vk.FORMAT_R32G32_SFLOAT     -- tmpTileSize           :: Vec2-  ]--allocateInstancesWith-  :: ( MonadResource m-     , MonadUnliftIO m-     )-  => (Vk.BufferUsageFlagBits -> Int -> Storable.Vector TileMapParams -> m (InstanceTileMap texture))-  -> (Vk.BufferUsageFlagBits -> Int -> Storable.Vector Transform -> m (InstanceTransform transform))-  -> (forall stage a . Buffer.Allocated stage a -> m ())-  -> [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers texture transform)-allocateInstancesWith createTextures createTransforms bufferDestroy instances = do-  ul <- askUnliftIO-  allocate (create ul) (destroy ul)-  where-    textures   = Storable.fromList $ map tilemapParams instances-    transforms = Storable.fromList $ map transformMat4 instances-    numInstances = Storable.length textures--    create (UnliftIO ul) = ul do-      ibTileMap   <- createTextures   Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances textures-      ibTransform <- createTransforms Vk.BUFFER_USAGE_VERTEX_BUFFER_BIT numInstances transforms-      pure InstanceBuffers{..}--    destroy (UnliftIO ul) InstanceBuffers{..} = ul do-      bufferDestroy ibTileMap-      bufferDestroy ibTransform--allocateInstancesCoherent-  :: ( MonadReader env m-     , HasVulkan env-     , MonadResource m-     , MonadUnliftIO m-     )-  => [InstanceAttrs]-  -> m (ReleaseKey, InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-allocateInstancesCoherent instances = do-  context <- ask-  allocateInstancesWith-    (Buffer.createCoherent context)-    (Buffer.createCoherent context)-    (Buffer.destroy context)-    instances--allocateInstancesCoherent_-  :: (HasVulkan env)-  => Int-  -> ResourceT (RIO env) (InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-allocateInstancesCoherent_ n =-  fmap snd $ allocateInstancesCoherent (replicate n zero)--updateCoherentResize_-  :: ( HasVulkan context-     , MonadUnliftIO m-     )-  => context-  -> InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent-  -> (Storable.Vector TileMapParams, Storable.Vector Transform)-  -> m (InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-updateCoherentResize_ context InstanceBuffers{..} (textures, transforms) =-  InstanceBuffers-    <$> Buffer.updateCoherentResize_ context ibTileMap textures-    <*> Buffer.updateCoherentResize_ context ibTransform transforms
src/Render/Unlit/TileMap/Pipeline.hs view
@@ -17,13 +17,13 @@ import Vulkan.Core10 qualified as Vk  import Engine.Vulkan.Pipeline.Graphics qualified as Graphics-import Engine.Vulkan.Types (HasVulkan, HasRenderPass(..), DsBindings)+import Engine.Vulkan.Types (DsLayoutBindings, HasVulkan, HasRenderPass(..)) import Render.Code (compileVert, compileFrag)-import Render.DescSets.Set0 (Scene, vertexPos, instanceTransform)+import Render.DescSets.Set0 (Scene) import Render.Unlit.TileMap.Code qualified as Code import Render.Unlit.TileMap.Model qualified as Model -type Pipeline = Graphics.Pipeline '[Scene] Model.VertexAttrs Model.InstanceAttrs+type Pipeline = Graphics.Pipeline '[Scene] Model.Vertex Model.Attrs type Config = Graphics.Configure Pipeline type instance Graphics.Specialization Pipeline = () @@ -32,7 +32,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocate multisample tset0 rp = do@@ -48,7 +48,7 @@      , HasRenderPass renderpass      )   => Vk.SampleCountFlagBits-  -> Tagged Scene DsBindings+  -> Tagged Scene DsLayoutBindings   -> renderpass   -> ResourceT (RIO env) Pipeline allocateBlend multisample tset0 rp = do@@ -59,21 +59,14 @@     rp   pure p -config :: Tagged Scene DsBindings -> Config+config :: Tagged Scene DsLayoutBindings -> Config config (Tagged set0) = Graphics.baseConfig   { Graphics.cDescLayouts  = Tagged @'[Scene] [set0]   , Graphics.cStages       = stageSpirv-  , Graphics.cVertexInput  = vertexInput+  , Graphics.cVertexInput  = Graphics.vertexInput @Pipeline   }-  where-    vertexInput = Graphics.vertexInput-      [ vertexPos-      , (Vk.VERTEX_INPUT_RATE_VERTEX,   Model.vkVertexAttrs)-      , (Vk.VERTEX_INPUT_RATE_INSTANCE, Model.vkInstanceTileMap)-      , instanceTransform-      ] -configBlend :: Tagged Scene DsBindings -> Config+configBlend :: Tagged Scene DsLayoutBindings -> Config configBlend tset0 = (config tset0)   { Graphics.cBlend      = True   , Graphics.cDepthWrite = False
src/Resource/Font.hs view
@@ -1,11 +1,9 @@ module Resource.Font   ( Config(..)-  , allocateCollection   , collectionTextures    , Font(..)-  , allocateFont-+  , allocate   ) where  import RIO@@ -19,8 +17,7 @@ import Resource.Font.EvanW qualified as EvanW import Resource.Source (Source) import Resource.Texture (Texture, Flat)-import Resource.Texture qualified as Texture-import Resource.Texture.Ktx1 qualified as Ktx1+import Resource.Texture.Ktx2 qualified as Ktx2  -- * General collection tools @@ -30,23 +27,6 @@   }   deriving (Show) -allocateCollection-  :: ( Traversable collection-     , MonadVulkan env m-     , HasLogFunc env-     , MonadThrow m-     , Resource.MonadResource m-     , HasCallStack-     )-  => Queues Vk.CommandPool-  -> collection Config-  -> m (Resource.ReleaseKey, collection Font)-allocateCollection pools collection = do-  collected <- for collection $-    withFrozenCallStack $ allocateFont pools-  key <- Resource.register $ traverse_ Resource.release $ fmap fst collected-  pure (key, fmap snd collected)- collectionTextures :: Foldable collection => collection Font -> Vector (Texture Flat) collectionTextures = Vector.fromList . map texture . toList @@ -57,7 +37,7 @@   , texture   :: Texture Flat   } -allocateFont+allocate   :: ( HasCallStack      , MonadVulkan env m      , HasLogFunc env@@ -66,18 +46,12 @@      )   => Queues Vk.CommandPool   -> Config-  -> m (Resource.ReleaseKey, Font)-allocateFont pools Config{..} = do-  context <- ask-+  -> m Font+allocate pools Config{..} = do   container <- withFrozenCallStack $     EvanW.load configContainer -  createTexture <- toIO $ withFrozenCallStack $-    Ktx1.load pools configTexture--  (textureKey, texture) <- Resource.allocate-    createTexture-    (Texture.destroy context)+  texture <- withFrozenCallStack $+    Ktx2.load pools configTexture -  pure (textureKey, Font{..})+  pure Font{..}
src/Stage/Loader/Render.hs view
@@ -46,7 +46,7 @@   usePass (Basic.rpForwardMsaa fRenderpass) imageIndex cb do     Swapchain.setDynamicFullscreen cb fSwapchainResources -    Set0.withBoundSet0 frSceneUi pWireframe cb do+    Set0.withBoundSet0 frSceneUi pUnlitTexturedBlend cb do       -- Render UI       Graphics.bind cb pUnlitTexturedBlend do         Draw.indexed cb (UI.quadUV ui) background
src/Stage/Loader/Scene.hs view
@@ -5,6 +5,8 @@  import RIO +import UnliftIO.Resource (MonadResource)+ import Engine.Camera qualified as Camera import Engine.Worker qualified as Worker import Render.DescSets.Set0 (Scene(..), emptyScene)@@ -12,7 +14,8 @@ type Process = Worker.Merge Scene  spawn-  :: ( MonadUnliftIO m+  :: ( MonadResource m+     , MonadUnliftIO m      , Worker.HasOutput projection      , Worker.GetOutput projection ~ Camera.Projection 'Camera.Orthographic      )
src/Stage/Loader/Setup.hs view
@@ -27,17 +27,17 @@ import Resource.CommandBuffer (withPools) import Resource.Font qualified as Font import Resource.Model qualified as Model+import Resource.Region qualified as Region import Resource.Source (Source)-import Resource.Texture qualified as Texture-import Resource.Texture.Ktx1 qualified as Ktx1+import Resource.Texture.Ktx2 qualified as Ktx2 import RIO.State (gets) import RIO.Vector.Partial ((!)) import UnliftIO.Resource qualified as Resource import Vulkan.Core10 qualified as Vk  import Stage.Loader.Render qualified as Render-import Stage.Loader.Types (FrameResources(..), RunState(..)) import Stage.Loader.Scene qualified as Scene+import Stage.Loader.Types (FrameResources(..), RunState(..)) import Stage.Loader.UI qualified as UI  bootstrap@@ -46,7 +46,7 @@   -> (Source, Source)   -> ((Text -> StageSetupRIO ()) -> StageSetupRIO loaded)   -> (loaded -> StackStage)-  -> ( (Setup Vector Vector loaded -> Engine.StackStage)+  -> ( Setup Vector Vector loaded -> Engine.StackStage      , Engine.StageSetupRIO (Setup Vector Vector loaded)      ) bootstrap titleMessage (smallFont, largeFont) (bgPath, spinnerPath) loadAction nextStage =@@ -55,15 +55,8 @@     action = withPools \pools -> do       logDebug "Bootstrapping loader" -      let-        fontConfigs = [smallFont, largeFont] :: Vector Font.Config-      (fontKey, fonts) <- Font.allocateCollection pools fontConfigs--      let-        texturePaths = [bgPath, spinnerPath] :: Vector Source-      (textureKey, textures) <- Texture.allocateCollectionWith-        (Ktx1.load pools)-        texturePaths+      fonts <- traverse (Font.allocate pools) [smallFont, largeFont]+      textures <- traverse (Ktx2.load pools) [bgPath, spinnerPath]        let         fontContainers = fmap Font.container fonts@@ -85,12 +78,6 @@           , largeFont = \fs -> fs ! 1           } -      loaderKey <- Resource.register $-        traverse_ @[] Resource.release-          [ fontKey-          , textureKey-          ]-       logDebug "Finished bootstrapping loader"       pure Setup{..} @@ -98,7 +85,6 @@   { loadAction :: (Text -> StageSetupRIO ()) -> StageSetupRIO loaded   , nextStage  :: loaded -> StackStage   , uiSettings :: UI.Settings textures fonts-  , loaderKey  :: Resource.ReleaseKey   }  stackStageBootstrap@@ -138,8 +124,7 @@      allocatePipelines swapchain rps = do       logDebug "Allocating loader pipelines"-      (_, samplers) <- Samplers.allocate-        (Swapchain.getAnisotropy swapchain)+      samplers <- Samplers.allocate (Swapchain.getAnisotropy swapchain)       Basic.allocatePipelines         (sceneBinds samplers)         (Swapchain.getMultisample swapchain)@@ -168,21 +153,18 @@   -> UI.Settings textures fonts   -> StageSetupRIO (Resource.ReleaseKey, RunState) initialRunState loadAction nextStage uiSettings =-  withPools \pools -> do-    (projectionKey, rsProjectionP) <- Worker.registered-      Camera.spawnOrthoPixelsCentered--    (sceneUiKey, rsSceneUiP) <- Worker.registered $-      Scene.spawn rsProjectionP+  withPools \pools -> Region.run do+    rsProjectionP <- Camera.spawnOrthoPixelsCentered -    context <- ask+    rsSceneUiP <- Scene.spawn rsProjectionP -    rsQuadUV <- Model.createStagedL context pools (Quad.toVertices Quad.texturedQuad) Nothing-    quadKey <- Resource.register $ Model.destroyIndexed context rsQuadUV+    rsQuadUV <- Model.createStagedL (Just "rsQuadUV") pools (Quad.toVertices Quad.texturedQuad) Nothing+    Model.registerIndexed_ rsQuadUV -    (screenKey, screenBoxP) <- Worker.registered Layout.trackScreen+    screenBoxP <- Layout.trackScreen -    (uiKey, rsUI) <- UI.spawn pools screenBoxP uiSettings+    rsUI <- Region.local $+      UI.spawn pools screenBoxP uiSettings      let       updateProgress text = do@@ -191,16 +173,7 @@           { Message.inputText = text           } -    releaseKeys <- Resource.register $-      traverse_ @[] Resource.release-        [ projectionKey-        , sceneUiKey-        , quadKey-        , screenKey-        , uiKey-        ]--    switcher <- async do+    switcher <- lift $ async do       loader <- async do         logDebug "Starting load action"         try (loadAction updateProgress) >>= \case@@ -229,7 +202,7 @@     -- XXX: propagate exceptions from loader threads     link switcher -    pure (releaseKeys, RunState{..})+    pure RunState{..}  initialFrameResources   :: (Traversable fonts, Traversable textures)
src/Stage/Loader/UI.hs view
@@ -15,7 +15,6 @@ import Control.Monad.Trans.Resource qualified as Resource import Geomancy (vec4) import Geomancy.Transform qualified as Transform-import RIO.Vector.Storable qualified as Storable import Vulkan.Core10 qualified as Vk  import Engine.Types qualified as Engine@@ -30,6 +29,8 @@ import Resource.Combined.Textures qualified as CombinedTextures import Resource.Font.EvanW qualified as EvanW import Resource.Model qualified as Model+import Resource.Model.Observer qualified as Observer+import Resource.Region qualified as Region import Resource.Texture (Texture, Flat)  data Settings fonts textures = Settings@@ -51,31 +52,24 @@   , progressInput :: Worker.Var Message.Input   , progressP     :: Message.Process -  , backgroundP :: Worker.Merge StorableAttrs-  , spinnerP    :: Worker.Merge StorableAttrs+  , backgroundP :: Worker.Merge UnlitTextured.Stores+  , spinnerP    :: Worker.Merge UnlitTextured.Stores    , quadUV :: UnlitTextured.Model 'Buffer.Staged   } -type StorableAttrs =-  ( Storable.Vector UnlitTextured.TextureParams-  , Storable.Vector UnlitTextured.Transform-  )- spawn   :: Queues Vk.CommandPool   -> Layout.BoxProcess   -> Settings fonts textures   -> Engine.StageRIO env (Resource.ReleaseKey, UI)-spawn pools screenBoxP Settings{..} = do+spawn pools screenBoxP Settings{..} = Region.run do   paddingVar <- Worker.newVar 16-  (screenPaddedKey, screenPaddedP) <- Worker.registered $-    Layout.padAbs screenBoxP paddingVar+  screenPaddedP <- Layout.padAbs screenBoxP paddingVar    -- Messages    sections <- Layout.splitsRelStatic Layout.sharePadsV screenPaddedP [2, 1, 1]-  sectionsKey <- Worker.registerCollection sections    (titleBoxP, subtitleBoxP, progressBoxP) <- case sections of     [titleBoxP, subtitleBoxP, progressBoxP] ->@@ -83,24 +77,20 @@     _ ->       error "assert: shares in Traversable preserve structure" -  (titleKey, titleP) <- Worker.registered $-    Worker.newVar title >>= Message.spawn titleBoxP-  (subtitleKey, subtitleP) <- Worker.registered $-    Worker.newVar subtitle >>= Message.spawn subtitleBoxP+  titleP <- Worker.newVar title >>= Message.spawn titleBoxP+  subtitleP <- Worker.newVar subtitle >>= Message.spawn subtitleBoxP    progressInput <- Worker.newVar progress-  (progressKey, progressP) <- Worker.registered $-    Message.spawn progressBoxP progressInput+  progressP <- Message.spawn progressBoxP progressInput    -- Splash -  (backgroundBoxKey, backgroundBoxP) <- Worker.registered $-    Layout.fitPlaceAbs Layout.Center 1.0 screenBoxP+  backgroundBoxP <- Layout.fitPlaceAbs Layout.Center 1.0 screenBoxP -  (backgroundKey, backgroundP) <- Worker.registered $+  backgroundP <-     Worker.spawnMerge1       ( \box ->-          UnlitTextured.storableAttrs1+          UnlitTextured.stores1               (Samplers.linear Samplers.indices)               backgroundIx               [Layout.boxTransformAbs box]@@ -109,20 +99,20 @@    -- Spinner -  (spinnerTransformTimeKey, spinnerTransformTimeP) <- Worker.registered $+  spinnerTransformTimeP <-     Worker.spawnTimed_ True 100 mempty do       t <- getMonotonicTime       pure $ Transform.rotateZ (realToFrac t) -  (spinnerTransformBoxKey, spinnerTransformBoxP) <- Worker.registered $+  spinnerTransformBoxP <-     Worker.spawnMerge1       (Layout.boxTransformAbs . snd . Layout.boxFitScale 64)       subtitleBoxP -  (spinnerKey, spinnerP) <- Worker.registered $+  spinnerP <-     Worker.spawnMerge2       ( \place turn ->-          UnlitTextured.storableAttrs1+          UnlitTextured.stores1               (Samplers.linear Samplers.indices)               spinnerIx               [turn, place]@@ -132,22 +122,14 @@    -- Models -  context <- ask-  quadUV <- Model.createStagedL context pools (Quad.toVertices Quad.texturedQuad) Nothing-  quadUVKey <- Resource.register $ Model.destroyIndexed context quadUV--  -- Cleanup--  key <- Resource.register $ traverse_ Resource.release-    [ screenPaddedKey-    , sectionsKey-    , titleKey, subtitleKey, progressKey-    , backgroundBoxKey, backgroundKey-    , spinnerTransformBoxKey, spinnerTransformTimeKey, spinnerKey-    , quadUVKey-    ]+  quadUV <- Model.createStagedL+    (Just "quadUV")+    pools+    (Quad.toVertices Quad.texturedQuad)+    Nothing+  Model.registerIndexed_ quadUV -  pure (key, UI{..})+  pure UI{..}   where     title = Message.Input       { inputText         = titleMessage@@ -187,8 +169,8 @@  data Observer = Observer   { messages   :: [Message.Observer]-  , background :: Worker.ObserverIO (UnlitTextured.InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)-  , spinner    :: Worker.ObserverIO (UnlitTextured.InstanceBuffers 'Buffer.Coherent 'Buffer.Coherent)+  , background :: UnlitTextured.ObserverCoherent+  , spinner    :: UnlitTextured.ObserverCoherent   }  newObserver :: UI -> ResourceT (Engine.StageRIO st) Observer@@ -200,12 +182,8 @@     , progressP     ] -  let-    newBufferObserver1 =-      UnlitTextured.allocateInstancesCoherent_ 1 >>= Worker.newObserverIO--  background <- newBufferObserver1-  spinner <- newBufferObserver1+  background <- Observer.newCoherent 1 "background"+  spinner <- Observer.newCoherent 1 "spinner"    pure Observer{..} @@ -218,10 +196,5 @@   traverse_ (uncurry Message.observe) $     zip [titleP, subtitleP, progressP] messages -  context <- ask--  Worker.observeIO_ backgroundP background $-    UnlitTextured.updateCoherentResize_ context--  Worker.observeIO_ spinnerP spinner $-    UnlitTextured.updateCoherentResize_ context+  Observer.observeCoherent backgroundP background+  Observer.observeCoherent spinnerP spinner