{-# LANGUAGE OverloadedLists #-}

module Render.ShadowMap.RenderPass where

import RIO

import Control.Monad.Trans.Resource qualified as Resource
import Data.Vector qualified as Vector
import RIO.Vector.Partial ((!))
import Vulkan.Core10 qualified as Vk
import Vulkan.Core11.Promoted_From_VK_KHR_multiview qualified as Khr
import Vulkan.NamedType ((:::))
import Vulkan.Utils.Debug qualified as Debug
import Vulkan.Zero (zero)
import Vulkan.CStruct.Extends (pattern (:&), pattern (::&))

import Engine.Types.RefCounted (RefCounted, newRefCounted, resourceTRefCount)
import Engine.Vulkan.Types (HasVulkan(..), HasSwapchain(..), HasRenderPass(..), RenderPass(..), MonadVulkan)
import Resource.Image (AllocatedImage)
import Resource.Image qualified as Image

-- * Depth-only pass for shadowmapping pipelines

data ShadowMap = ShadowMap
  { ShadowMap -> RenderPass
smRenderPass  :: Vk.RenderPass
  , ShadowMap -> AllocatedImage
smDepthImage  :: AllocatedImage
  , ShadowMap -> Framebuffer
smFrameBuffer :: Vk.Framebuffer
  , ShadowMap -> Rect2D
smRenderArea  :: Vk.Rect2D
  , ShadowMap -> Extent2D
smExtent      :: Vk.Extent2D
  , ShadowMap -> Word32
smLayerCount  :: Word32
  , ShadowMap -> Vector ClearValue
smClear       :: Vector Vk.ClearValue
  , ShadowMap -> RefCounted
smRelease     :: RefCounted
  }

instance HasRenderPass ShadowMap where
  getRenderPass :: ShadowMap -> RenderPass
getRenderPass   = ShadowMap -> RenderPass
smRenderPass
  getFramebuffers :: ShadowMap -> Vector Framebuffer
getFramebuffers = Int -> Framebuffer -> Vector Framebuffer
forall a. Int -> a -> Vector a
Vector.replicate Int
10 (Framebuffer -> Vector Framebuffer)
-> (ShadowMap -> Framebuffer) -> ShadowMap -> Vector Framebuffer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShadowMap -> Framebuffer
smFrameBuffer
  getClearValues :: ShadowMap -> Vector ClearValue
getClearValues  = ShadowMap -> Vector ClearValue
smClear
  getRenderArea :: ShadowMap -> Rect2D
getRenderArea   = ShadowMap -> Rect2D
smRenderArea

instance RenderPass ShadowMap where
  allocateRenderpass_ :: context -> ResourceT (RIO env) ShadowMap
allocateRenderpass_ = [Char] -> context -> ResourceT (RIO env) ShadowMap
forall a. HasCallStack => [Char] -> a
error [Char]
"Don't allocate ShadowMap via class"
  updateRenderpass :: context -> ShadowMap -> RIO env ShadowMap
updateRenderpass    = [Char] -> context -> ShadowMap -> RIO env ShadowMap
forall a. HasCallStack => [Char] -> a
error [Char]
"Don't recreate ShadowMap on resize"
  refcountRenderpass :: ShadowMap -> RIO env ()
refcountRenderpass  = RefCounted -> RIO env ()
forall (f :: * -> *). MonadResource f => RefCounted -> f ()
resourceTRefCount (RefCounted -> RIO env ())
-> (ShadowMap -> RefCounted) -> ShadowMap -> RIO env ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShadowMap -> RefCounted
smRelease

allocate
  :: ( Resource.MonadResource m
     , MonadVulkan env m
     , HasLogFunc env
     , HasSwapchain context
     )
  => context
  -> Word32
  -> "light count" ::: Word32
  -> m ShadowMap
allocate :: context -> Word32 -> Word32 -> m ShadowMap
allocate context
context Word32
mapSize Word32
layerCount = do
  Utf8Builder -> m ()
forall (m :: * -> *) env.
(MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack) =>
Utf8Builder -> m ()
logDebug Utf8Builder
"Allocating ShadowMap resources"
  (ReleaseKey
_rpKey, RenderPass
renderPass) <- context -> Word32 -> Word32 -> m (ReleaseKey, RenderPass)
forall env (m :: * -> *) context.
(MonadVulkan env m, MonadResource m, HasSwapchain context) =>
context -> Word32 -> Word32 -> m (ReleaseKey, RenderPass)
allocateRenderPass context
context (Word32
2 Word32 -> Word32 -> Word32
forall a b. (Num a, Integral b) => a -> b -> a
^ Word32
layerCount Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
1) Word32
0
  (RefCounted
refcounted, AllocatedImage
depthImage, Framebuffer
framebuffer) <- context
-> Extent2D
-> Word32
-> RenderPass
-> m (RefCounted, AllocatedImage, Framebuffer)
forall (m :: * -> *) env context.
(MonadResource m, MonadVulkan env m, HasLogFunc env,
 HasSwapchain context) =>
context
-> Extent2D
-> Word32
-> RenderPass
-> m (RefCounted, AllocatedImage, Framebuffer)
allocateFramebuffer context
context Extent2D
extent Word32
layerCount RenderPass
renderPass

  pure ShadowMap :: RenderPass
-> AllocatedImage
-> Framebuffer
-> Rect2D
-> Extent2D
-> Word32
-> Vector ClearValue
-> RefCounted
-> ShadowMap
ShadowMap
    { $sel:smRenderPass:ShadowMap :: RenderPass
smRenderPass  = RenderPass
renderPass
    , $sel:smExtent:ShadowMap :: Extent2D
smExtent      = Extent2D
extent
    , $sel:smLayerCount:ShadowMap :: Word32
smLayerCount  = Word32
layerCount
    , $sel:smRenderArea:ShadowMap :: Rect2D
smRenderArea  = Rect2D
fullSurface
    , $sel:smClear:ShadowMap :: Vector ClearValue
smClear       = Vector ClearValue
clear
    , $sel:smDepthImage:ShadowMap :: AllocatedImage
smDepthImage  = AllocatedImage
depthImage
    , $sel:smFrameBuffer:ShadowMap :: Framebuffer
smFrameBuffer = Framebuffer
framebuffer
    , $sel:smRelease:ShadowMap :: RefCounted
smRelease     = RefCounted
refcounted
    }
  where
    extent :: Extent2D
extent = Extent2D :: Word32 -> Word32 -> Extent2D
Vk.Extent2D{$sel:width:Extent2D :: Word32
width=Word32
mapSize, $sel:height:Extent2D :: Word32
height=Word32
mapSize}

    fullSurface :: Rect2D
fullSurface = Rect2D :: Offset2D -> Extent2D -> Rect2D
Vk.Rect2D
      { $sel:offset:Rect2D :: Offset2D
Vk.offset = Offset2D
forall a. Zero a => a
zero
      , $sel:extent:Rect2D :: Extent2D
Vk.extent = Extent2D
extent
      }

    clear :: Vector ClearValue
clear = [ClearValue] -> Vector ClearValue
forall a. [a] -> Vector a
Vector.fromList
      [ ClearDepthStencilValue -> ClearValue
Vk.DepthStencil (Float -> Word32 -> ClearDepthStencilValue
Vk.ClearDepthStencilValue Float
1.0 Word32
0)
      ]

-- ** Render pass

allocateRenderPass
  :: ( MonadVulkan env m
     , Resource.MonadResource m
     , HasSwapchain context
     )
  => context
  -> Word32
  -> Word32
  -> m (Resource.ReleaseKey, Vk.RenderPass)
allocateRenderPass :: context -> Word32 -> Word32 -> m (ReleaseKey, RenderPass)
allocateRenderPass context
context Word32
viewMask Word32
correlationMask = do
  Device
device <- (env -> Device) -> m Device
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks env -> Device
forall a. HasVulkan a => a -> Device
getDevice
  let depthFormat :: Format
depthFormat = context -> Format
forall a. HasSwapchain a => a -> Format
getDepthFormat context
context

  res :: (ReleaseKey, RenderPass)
res@(ReleaseKey
_key, RenderPass
object) <- Device
-> RenderPassCreateInfo '[RenderPassMultiviewCreateInfo]
-> Maybe AllocationCallbacks
-> (IO RenderPass
    -> (RenderPass -> IO ()) -> m (ReleaseKey, RenderPass))
-> m (ReleaseKey, RenderPass)
forall (a :: [*]) (io :: * -> *) r.
(Extendss RenderPassCreateInfo a, PokeChain a, MonadIO io) =>
Device
-> RenderPassCreateInfo a
-> Maybe AllocationCallbacks
-> (io RenderPass -> (RenderPass -> io ()) -> r)
-> r
Vk.withRenderPass Device
device (Format -> RenderPassCreateInfo '[RenderPassMultiviewCreateInfo]
createInfo Format
depthFormat) Maybe AllocationCallbacks
forall a. Maybe a
Nothing IO RenderPass
-> (RenderPass -> IO ()) -> m (ReleaseKey, RenderPass)
forall (m :: * -> *) a.
MonadResource m =>
IO a -> (a -> IO ()) -> m (ReleaseKey, a)
Resource.allocate
  Device -> RenderPass -> ByteString -> m ()
forall a (m :: * -> *).
(HasObjectType a, MonadIO m) =>
Device -> a -> ByteString -> m ()
Debug.nameObject Device
device RenderPass
object ByteString
"ShadowMap.RP"
  pure (ReleaseKey, RenderPass)
res
  where
    createInfo :: Format -> RenderPassCreateInfo '[RenderPassMultiviewCreateInfo]
createInfo Format
depthFormat =
      RenderPassCreateInfo '[]
forall a. Zero a => a
zero
        { $sel:attachments:RenderPassCreateInfo :: Vector AttachmentDescription
Vk.attachments  = [AttachmentDescription] -> Vector AttachmentDescription
forall a. [a] -> Vector a
Vector.fromList [Format -> AttachmentDescription
depth Format
depthFormat]
        , $sel:subpasses:RenderPassCreateInfo :: Vector SubpassDescription
Vk.subpasses    = [SubpassDescription] -> Vector SubpassDescription
forall a. [a] -> Vector a
Vector.fromList [Item [SubpassDescription]
SubpassDescription
subpass]
        , $sel:dependencies:RenderPassCreateInfo :: Vector SubpassDependency
Vk.dependencies = [SubpassDependency] -> Vector SubpassDependency
forall a. [a] -> Vector a
Vector.fromList [Item [SubpassDependency]
SubpassDependency
pre, Item [SubpassDependency]
SubpassDependency
post]
        }
      RenderPassCreateInfo '[]
-> Chain '[RenderPassMultiviewCreateInfo]
-> RenderPassCreateInfo '[RenderPassMultiviewCreateInfo]
forall (a :: [*] -> *) (es :: [*]) (es' :: [*]).
Extensible a =>
a es' -> Chain es -> a es
::& RenderPassMultiviewCreateInfo :: Vector Word32
-> Vector Int32 -> Vector Word32 -> RenderPassMultiviewCreateInfo
Khr.RenderPassMultiviewCreateInfo
        { $sel:viewMasks:RenderPassMultiviewCreateInfo :: Vector Word32
Khr.viewMasks        = [Word32
Item (Vector Word32)
viewMask]
        , $sel:viewOffsets:RenderPassMultiviewCreateInfo :: Vector Int32
Khr.viewOffsets      = []
        , $sel:correlationMasks:RenderPassMultiviewCreateInfo :: Vector Word32
Khr.correlationMasks = [Word32
Item (Vector Word32)
correlationMask]
        }
      RenderPassMultiviewCreateInfo
-> Chain '[] -> Chain '[RenderPassMultiviewCreateInfo]
forall e (es :: [*]). e -> Chain es -> Chain (e : es)
:& ()

    depth :: Format -> AttachmentDescription
depth Format
depthFormat = AttachmentDescription
forall a. Zero a => a
zero
      { $sel:format:AttachmentDescription :: Format
Vk.format         = Format
depthFormat
      , $sel:samples:AttachmentDescription :: SampleCountFlagBits
Vk.samples        = SampleCountFlagBits
Vk.SAMPLE_COUNT_1_BIT
      , $sel:loadOp:AttachmentDescription :: AttachmentLoadOp
Vk.loadOp         = AttachmentLoadOp
Vk.ATTACHMENT_LOAD_OP_CLEAR
      , $sel:storeOp:AttachmentDescription :: AttachmentStoreOp
Vk.storeOp        = AttachmentStoreOp
Vk.ATTACHMENT_STORE_OP_STORE
      , $sel:stencilLoadOp:AttachmentDescription :: AttachmentLoadOp
Vk.stencilLoadOp  = AttachmentLoadOp
Vk.ATTACHMENT_LOAD_OP_DONT_CARE
      , $sel:stencilStoreOp:AttachmentDescription :: AttachmentStoreOp
Vk.stencilStoreOp = AttachmentStoreOp
Vk.ATTACHMENT_STORE_OP_DONT_CARE
      , $sel:initialLayout:AttachmentDescription :: ImageLayout
Vk.initialLayout  = ImageLayout
Vk.IMAGE_LAYOUT_UNDEFINED
      , $sel:finalLayout:AttachmentDescription :: ImageLayout
Vk.finalLayout    = ImageLayout
Vk.IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
      }

    subpass :: SubpassDescription
subpass = SubpassDescription
forall a. Zero a => a
zero
      { $sel:pipelineBindPoint:SubpassDescription :: PipelineBindPoint
Vk.pipelineBindPoint = PipelineBindPoint
Vk.PIPELINE_BIND_POINT_GRAPHICS
      , $sel:depthStencilAttachment:SubpassDescription :: Maybe AttachmentReference
Vk.depthStencilAttachment = AttachmentReference -> Maybe AttachmentReference
forall a. a -> Maybe a
Just AttachmentReference
forall a. Zero a => a
zero
          { $sel:attachment:AttachmentReference :: Word32
Vk.attachment = Word32
0
          , $sel:layout:AttachmentReference :: ImageLayout
Vk.layout     = ImageLayout
Vk.IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
          }
      }

    pre :: SubpassDependency
pre = SubpassDependency
forall a. Zero a => a
zero
      { $sel:dependencyFlags:SubpassDependency :: DependencyFlags
Vk.dependencyFlags = DependencyFlags
Vk.DEPENDENCY_BY_REGION_BIT

      , $sel:srcSubpass:SubpassDependency :: Word32
Vk.srcSubpass      = Word32
Vk.SUBPASS_EXTERNAL
      , $sel:srcStageMask:SubpassDependency :: PipelineStageFlags
Vk.srcStageMask    = PipelineStageFlags
Vk.PIPELINE_STAGE_FRAGMENT_SHADER_BIT
      , $sel:srcAccessMask:SubpassDependency :: AccessFlags
Vk.srcAccessMask   = AccessFlags
Vk.ACCESS_SHADER_READ_BIT

      , $sel:dstSubpass:SubpassDependency :: Word32
Vk.dstSubpass      = Word32
0
      , $sel:dstStageMask:SubpassDependency :: PipelineStageFlags
Vk.dstStageMask    = PipelineStageFlags
Vk.PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
      , $sel:dstAccessMask:SubpassDependency :: AccessFlags
Vk.dstAccessMask   = AccessFlags
Vk.ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
      }

    post :: SubpassDependency
post = SubpassDependency
forall a. Zero a => a
zero
      { $sel:dependencyFlags:SubpassDependency :: DependencyFlags
Vk.dependencyFlags = DependencyFlags
Vk.DEPENDENCY_BY_REGION_BIT

      , $sel:srcSubpass:SubpassDependency :: Word32
Vk.srcSubpass      = Word32
0
      , $sel:srcStageMask:SubpassDependency :: PipelineStageFlags
Vk.srcStageMask    = PipelineStageFlags
Vk.PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
      , $sel:srcAccessMask:SubpassDependency :: AccessFlags
Vk.srcAccessMask   = AccessFlags
Vk.ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT

      , $sel:dstSubpass:SubpassDependency :: Word32
Vk.dstSubpass      = Word32
Vk.SUBPASS_EXTERNAL
      , $sel:dstStageMask:SubpassDependency :: PipelineStageFlags
Vk.dstStageMask    = PipelineStageFlags
Vk.PIPELINE_STAGE_FRAGMENT_SHADER_BIT
      , $sel:dstAccessMask:SubpassDependency :: AccessFlags
Vk.dstAccessMask   = AccessFlags
Vk.ACCESS_SHADER_READ_BIT
      }

-- ** Framebuffer

type Framebuffers =
  ( RefCounted
  , Image.AllocatedImage
  , Vk.Framebuffer
  )

allocateFramebuffer
  :: ( Resource.MonadResource m
     , MonadVulkan env m
     , HasLogFunc env
     , HasSwapchain context
     )
  => context
  -> Vk.Extent2D
  -> Word32
  -> Vk.RenderPass
  -> m Framebuffers
allocateFramebuffer :: context
-> Extent2D
-> Word32
-> RenderPass
-> m (RefCounted, AllocatedImage, Framebuffer)
allocateFramebuffer context
context Extent2D
extent Word32
layerCount RenderPass
renderPass = do
  Device
device <- (env -> Device) -> m Device
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks env -> Device
forall a. HasVulkan a => a -> Device
getDevice
  (env, context)
context' <- (env -> (env, context)) -> m (env, context)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (, context
context)
  let Vk.Extent2D{Word32
width :: Word32
$sel:width:Extent2D :: Extent2D -> Word32
width, Word32
height :: Word32
$sel:height:Extent2D :: Extent2D -> Word32
height} = Extent2D
extent

  (ReleaseKey
depthKey, AllocatedImage
depth) <- IO AllocatedImage
-> (AllocatedImage -> IO ()) -> m (ReleaseKey, AllocatedImage)
forall (m :: * -> *) a.
MonadResource m =>
IO a -> (a -> IO ()) -> m (ReleaseKey, a)
Resource.allocate
    ((env, context)
-> Extent2D
-> ("shadowmap layers" ::: Maybe Word32)
-> IO AllocatedImage
forall (io :: * -> *) context.
(MonadIO io, HasVulkan context, HasSwapchain context) =>
context
-> Extent2D
-> ("shadowmap layers" ::: Maybe Word32)
-> io AllocatedImage
Image.createDepthResource (env, context)
context' Extent2D
extent (("shadowmap layers" ::: Maybe Word32) -> IO AllocatedImage)
-> ("shadowmap layers" ::: Maybe Word32) -> IO AllocatedImage
forall a b. (a -> b) -> a -> b
$ Word32 -> "shadowmap layers" ::: Maybe Word32
forall a. a -> Maybe a
Just Word32
layerCount)
    ((env, context) -> AllocatedImage -> IO ()
forall (io :: * -> *) context.
(MonadIO io, HasVulkan context) =>
context -> AllocatedImage -> io ()
Image.destroyAllocatedImage (env, context)
context')

  let
    attachments :: Vector ImageView
attachments = [ImageView] -> Vector ImageView
forall a. [a] -> Vector a
Vector.fromList
      [ AllocatedImage -> ImageView
Image.aiImageView AllocatedImage
depth
      ]

    {- XXX:
      If the render pass uses multiview, then layers must be one and each attachment
      requires a number of layers that is greater than the maximum bit index set in
      the view mask in the subpasses in which it is used.
    -}
    fbNumLayers :: Word32
fbNumLayers = Word32
1

    fbCI :: FramebufferCreateInfo '[]
fbCI = FramebufferCreateInfo '[]
forall a. Zero a => a
zero
      { $sel:renderPass:FramebufferCreateInfo :: RenderPass
Vk.renderPass  = RenderPass
renderPass
      , $sel:width:FramebufferCreateInfo :: Word32
Vk.width       = Word32
width
      , $sel:height:FramebufferCreateInfo :: Word32
Vk.height      = Word32
height
      , $sel:attachments:FramebufferCreateInfo :: Vector ImageView
Vk.attachments = Vector ImageView
attachments
      , $sel:layers:FramebufferCreateInfo :: Word32
Vk.layers      = Word32
fbNumLayers
      }
  (ReleaseKey
framebufferKey, Framebuffer
framebuffer) <- Device
-> FramebufferCreateInfo '[]
-> Maybe AllocationCallbacks
-> (IO Framebuffer
    -> (Framebuffer -> IO ()) -> m (ReleaseKey, Framebuffer))
-> m (ReleaseKey, Framebuffer)
forall (a :: [*]) (io :: * -> *) r.
(Extendss FramebufferCreateInfo a, PokeChain a, MonadIO io) =>
Device
-> FramebufferCreateInfo a
-> Maybe AllocationCallbacks
-> (io Framebuffer -> (Framebuffer -> io ()) -> r)
-> r
Vk.withFramebuffer Device
device FramebufferCreateInfo '[]
fbCI Maybe AllocationCallbacks
forall a. Maybe a
Nothing IO Framebuffer
-> (Framebuffer -> IO ()) -> m (ReleaseKey, Framebuffer)
forall (m :: * -> *) a.
MonadResource m =>
IO a -> (a -> IO ()) -> m (ReleaseKey, a)
Resource.allocate
  Device -> Framebuffer -> ByteString -> m ()
forall a (m :: * -> *).
(HasObjectType a, MonadIO m) =>
Device -> a -> ByteString -> m ()
Debug.nameObject Device
device Framebuffer
framebuffer ByteString
"ShadowMap.FB"

  IO ()
releaseDebug <- m () -> m (IO ())
forall (m :: * -> *) a. MonadUnliftIO m => m a -> m (IO a)
toIO (m () -> m (IO ())) -> m () -> m (IO ())
forall a b. (a -> b) -> a -> b
$ Utf8Builder -> m ()
forall (m :: * -> *) env.
(MonadIO m, MonadReader env m, HasLogFunc env, HasCallStack) =>
Utf8Builder -> m ()
logDebug Utf8Builder
"Releasing ShadowMap resources"
  RefCounted
release <- IO () -> m RefCounted
forall (m :: * -> *). MonadIO m => IO () -> m RefCounted
newRefCounted do
    IO ()
releaseDebug
    ReleaseKey -> IO ()
forall (m :: * -> *). MonadIO m => ReleaseKey -> m ()
Resource.release ReleaseKey
depthKey
    ReleaseKey -> IO ()
forall (m :: * -> *). MonadIO m => ReleaseKey -> m ()
Resource.release ReleaseKey
framebufferKey

  pure (RefCounted
release, AllocatedImage
depth, Framebuffer
framebuffer)

usePass :: (MonadIO io, HasRenderPass a) => a -> Word32 -> Vk.CommandBuffer -> io r -> io r
usePass :: a -> Word32 -> CommandBuffer -> io r -> io r
usePass a
render Word32
imageIndex CommandBuffer
cb =
  CommandBuffer
-> RenderPassBeginInfo '[] -> SubpassContents -> io r -> io r
forall (a :: [*]) (io :: * -> *) r.
(Extendss RenderPassBeginInfo a, PokeChain a, MonadIO io) =>
CommandBuffer
-> RenderPassBeginInfo a -> SubpassContents -> io r -> io r
Vk.cmdUseRenderPass
    CommandBuffer
cb
    (a -> Word32 -> RenderPassBeginInfo '[]
forall a. HasRenderPass a => a -> Word32 -> RenderPassBeginInfo '[]
beginInfo a
render Word32
imageIndex)
    SubpassContents
Vk.SUBPASS_CONTENTS_INLINE

beginInfo :: HasRenderPass a => a -> Word32 -> Vk.RenderPassBeginInfo '[]
beginInfo :: a -> Word32 -> RenderPassBeginInfo '[]
beginInfo a
rp Word32
imageIndex = RenderPassBeginInfo '[]
forall a. Zero a => a
zero
  { $sel:renderPass:RenderPassBeginInfo :: RenderPass
Vk.renderPass  = a -> RenderPass
forall a. HasRenderPass a => a -> RenderPass
getRenderPass a
rp
  , $sel:framebuffer:RenderPassBeginInfo :: Framebuffer
Vk.framebuffer = a -> Vector Framebuffer
forall a. HasRenderPass a => a -> Vector Framebuffer
getFramebuffers a
rp Vector Framebuffer -> Int -> Framebuffer
forall (v :: * -> *) a. Vector v a => v a -> Int -> a
! Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
imageIndex -- XXX: we only have one
  , $sel:renderArea:RenderPassBeginInfo :: Rect2D
Vk.renderArea  = a -> Rect2D
forall a. HasRenderPass a => a -> Rect2D
getRenderArea a
rp
  , $sel:clearValues:RenderPassBeginInfo :: Vector ClearValue
Vk.clearValues = a -> Vector ClearValue
forall a. HasRenderPass a => a -> Vector ClearValue
getClearValues a
rp
  }