keid-render-basic-0.1.3.0: src/Render/ForwardMsaa.hs
module Render.ForwardMsaa
( ForwardMsaa(..)
, allocateMsaa
, updateMsaa
, 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, newRefCounted, releaseRefCounted, resourceTRefCount)
import Engine.Vulkan.Types (HasVulkan(..), HasSwapchain(..), HasRenderPass(..), RenderPass(..), MonadVulkan)
import Render.Pass (usePass)
import Resource.Image (AllocatedImage)
import Resource.Image qualified as Image
-- * Simple MSAA-enabled pass
data ForwardMsaa = ForwardMsaa
{ fmRenderPass :: Vk.RenderPass
, fmColor :: AllocatedImage
, fmDepth :: AllocatedImage
, fmFrameBuffers :: Vector Vk.Framebuffer
, fmRenderArea :: Vk.Rect2D
, fmClear :: Vector Vk.ClearValue
, fmRelease :: RefCounted
}
instance HasRenderPass ForwardMsaa where
getRenderPass = fmRenderPass
getFramebuffers = fmFrameBuffers
getClearValues = fmClear
getRenderArea = fmRenderArea
instance RenderPass ForwardMsaa where
allocateRenderpass_ = allocateMsaa -- error "Thou shalt allocateMsaa instead"
updateRenderpass = updateMsaa
refcountRenderpass = resourceTRefCount . fmRelease
allocateMsaa
:: ( Resource.MonadResource m
, MonadVulkan env m
, HasLogFunc env
, HasSwapchain swapchain
)
=> swapchain
-> m ForwardMsaa
allocateMsaa swapchain = do
logDebug "Allocating ForwardMsaa resources"
(_rpKey, renderPass) <- allocateRenderPassMsaa swapchain
(refcounted, color, depth, framebuffers) <- allocateFramebufferMsaa swapchain renderPass
pure ForwardMsaa
{ fmRenderPass = renderPass
, fmRenderArea = fullSurface
, fmClear = clear
, fmColor = color
, fmDepth = depth
, fmFrameBuffers = framebuffers
, fmRelease = refcounted
}
where
fullSurface = Vk.Rect2D
{ Vk.offset = zero
, Vk.extent = getSurfaceExtent swapchain
}
clear = Vector.fromList
[ clearColor
, Vk.DepthStencil (Vk.ClearDepthStencilValue 1.0 0)
, clearColor
]
clearColor = Vk.Color zero
updateMsaa
:: ( Resource.MonadResource m
, MonadVulkan env m
, HasLogFunc env
, HasSwapchain swapchain
)
=> swapchain
-> ForwardMsaa
-> m ForwardMsaa
updateMsaa swapchain old@ForwardMsaa{fmRelease, fmRenderPass} = do
releaseRefCounted fmRelease
(refcounted, color, depth, framebuffers) <- allocateFramebufferMsaa swapchain fmRenderPass
pure old
{ fmColor = color
, fmDepth = depth
, fmFrameBuffers = framebuffers
, fmRelease = refcounted
, fmRenderArea = fullSurface
}
where
fullSurface = Vk.Rect2D
{ Vk.offset = zero
, Vk.extent = getSurfaceExtent swapchain
}
-- ** Render pass
allocateRenderPassMsaa
:: ( MonadVulkan env m
, Resource.MonadResource m
, HasSwapchain swapchain
)
=> swapchain
-> m (Resource.ReleaseKey, Vk.RenderPass)
allocateRenderPassMsaa swapchain = do
device <- asks getDevice
let
format = getSurfaceFormat swapchain
depthFormat = getDepthFormat swapchain
msaa = getMultisample swapchain
attachments =
[ color format msaa
, depth depthFormat msaa
, colorResolve format
]
res@(_key, object) <- Vk.withRenderPass device (createInfo attachments) Nothing Resource.allocate
Debug.nameObject device object "ForwardMSAA"
pure res
where
createInfo attachments = zero
{ Vk.attachments = Vector.fromList attachments
, Vk.subpasses = Vector.fromList [subpass]
, Vk.dependencies = Vector.fromList [colorDeps, depthDeps]
}
color format msaa = zero
{ Vk.format = format
, Vk.samples = msaa
, Vk.finalLayout = Vk.IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
, 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
}
depth format msaa = zero
{ Vk.format = format
, Vk.samples = msaa
, 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
, Vk.finalLayout = Vk.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
}
colorResolve format = zero
{ Vk.format = format
, Vk.samples = Vk.SAMPLE_COUNT_1_BIT
, Vk.finalLayout = Vk.IMAGE_LAYOUT_PRESENT_SRC_KHR
, Vk.loadOp = Vk.ATTACHMENT_LOAD_OP_DONT_CARE
}
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
}
, Vk.depthStencilAttachment = Just zero
{ 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
}
}
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
depthDeps = zero
{ Vk.srcSubpass = Vk.SUBPASS_EXTERNAL
, Vk.dstSubpass = 0
, Vk.srcStageMask = fragTests
, Vk.srcAccessMask = depthW
, Vk.dstStageMask = fragTests
, Vk.dstAccessMask = depthRW
}
where
fragTests =
Vk.PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT .|.
Vk.PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
depthW =
Vk.ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
depthRW =
Vk.ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT .|.
depthW
-- ** Framebuffer
type FramebuffersMsaa =
( RefCounted
, Image.AllocatedImage
, Image.AllocatedImage
, Vector Vk.Framebuffer
)
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)
(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)
perView <- Vector.iforM (getSwapchainViews swapchain) \ix colorResolve -> do
let
attachments = Vector.fromList
[ Image.aiImageView color
, Image.aiImageView depth
, colorResolve
]
fbCI = zero
{ Vk.renderPass = renderPass
, Vk.width = width
, Vk.height = height
, Vk.attachments = attachments
, Vk.layers = 1
}
device = getDevice context
res <- Vk.withFramebuffer device fbCI Nothing Resource.allocate
Debug.nameObject device (snd res) $
"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 (release, color, depth, framebuffers)