| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Vulkan.Utils.Frame
Description
Per-frame state and the recycling-Frame loop. Each frame owns a binary
image-available semaphore and a command pool — those are RecycledResources
that get handed back to a channel in VulkanContext once the frame's GPU work
has completed. (The present-wait/render-finished semaphore is per swapchain
image, on the Swapchain, because it is only safe to
reuse once its image is re-acquired — not when the frame's render finishes.)
The host-side timeline semaphore (fHostTimeline) lives across frames:
each frame increments it to its own fIndex on the GPU, and the host
waits on it inside the spawned wait-and-recycle thread.
This module requires Vulkan 1.2-level timeline-semaphore support. See
frameInstanceRequirements / frameDeviceRequirements for the
extension/feature requirements to merge into your boot sequence.
Synopsis
- data Frame = Frame {
- fIndex :: Word64
- fSwapchain :: Swapchain
- fRecycled :: RecycledResources
- fHostTimeline :: Semaphore
- fGPUWork :: IORef [(Semaphore, Word64)]
- fResources :: (ReleaseKey, InternalState)
- initialFrame :: MonadResource m => VulkanContext -> Swapchain -> m Frame
- advanceFrame :: MonadResource m => VulkanContext -> Swapchain -> Frame -> m Frame
- runFrame :: VulkanContext -> Frame -> ResourceT IO a -> IO a
- recordCommands :: (MonadResource m, MonadFail m) => VulkanContext -> Frame -> (CommandBuffer -> m ()) -> m CommandBuffer
- queueSubmitFrame :: MonadIO m => VulkanContext -> Frame -> Word32 -> Vector CommandBuffer -> m ()
- acquireFrameImage :: MonadIO m => VulkanContext -> Frame -> m (Result, Word32)
- presentFrameImage :: MonadIO m => VulkanContext -> Frame -> Result -> Word32 -> m ()
- drainFrames :: VulkanContext -> Frame -> IO ()
- allocateTimelineSemaphore :: MonadResource m => Device -> Word64 -> m (ReleaseKey, Semaphore)
- frameInstanceRequirements :: [InstanceRequirement]
- frameDeviceRequirements :: [DeviceRequirement]
Documentation
Constructors
| Frame | |
Fields
| |
initialFrame :: MonadResource m => VulkanContext -> Swapchain -> m Frame Source #
Build the initial frame with one spare RecycledResources seeded
into the recycle channel. That, plus the set attached to this frame,
caps max-in-flight at 2 (CPU recording + GPU executing the previous).
Arguments
| :: MonadResource m | |
| => VulkanContext | |
| -> Swapchain | Same as old, or freshly recreated |
| -> Frame | The just-finished frame |
| -> m Frame |
Build the next frame, taking one set of recycled resources from the bin.
Caller passes the (possibly-recreated) Swapchain.
runFrame :: VulkanContext -> Frame -> ResourceT IO a -> IO a Source #
Run a per-frame action against this frame's per-frame ResourceT scope, then asynchronously wait for the GPU work and recycle. The wait/recycle runs in a forked thread so the next frame can begin recording immediately.
Anything allocated inside action is freed when the frame retires.
recordCommands :: (MonadResource m, MonadFail m) => VulkanContext -> Frame -> (CommandBuffer -> m ()) -> m CommandBuffer Source #
Allocate a primary command buffer from this frame's recycled command pool,
begin it with COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, run the caller's
recording action, end recording, and return the buffer ready to hand to
queueSubmitFrame.
For a non-standard begin shape (secondary level, different usage flags,
inheritance info) call withCommandBuffers and useCommandBuffer
directly.
Arguments
| :: MonadIO m | |
| => VulkanContext | |
| -> Frame | |
| -> Word32 | Acquired image index (from |
| -> Vector CommandBuffer | |
| -> m () |
Submit a per-frame command buffer batch and record the timeline-wait bookkeeping the host wait thread will block on.
Builds the standard frame submit from context/frame: waits on the frame's
image-available semaphore at COLOR_ATTACHMENT_OUTPUT, signals the
swapchain's per-image render-finished semaphore (at imageIndex) plus its
timeline value, and submits on the graphics queue.
For a non-standard submit shape (multiple submit infos, different wait
stage, extra signals), call queueSubmit directly and append
(fHostTimeline f, fIndex f) to fGPUWork f.
acquireFrameImage :: MonadIO m => VulkanContext -> Frame -> m (Result, Word32) Source #
Acquire the next swapchain image for this frame, signalling the frame's image-available semaphore on completion.
The acquire result is returned alongside the image index so the caller can
thread it into presentFrameImage, which honours SUBOPTIMAL_KHR from
either side by raising ERROR_OUT_OF_DATE_KHR to drive a swapchain
recreation. Timeouts and unexpected results are also translated to
ERROR_OUT_OF_DATE_KHR — the main loop's swapchain-recreation path is the
right place to recover.
presentFrameImage :: MonadIO m => VulkanContext -> Frame -> Result -> Word32 -> m () Source #
Present this frame's acquired image, waiting on the swapchain's per-image
render-finished semaphore (at imageIndex). Presents on the graphics queue
(qGraphics . vcQueues).
If either the prior acquire (passed in) or this present reports
SUBOPTIMAL_KHR, raises ERROR_OUT_OF_DATE_KHR so the main loop
recreates the swapchain.
drainFrames :: VulkanContext -> Frame -> IO () Source #
Shutdown drain: spawn the unrendered current frame's wait/recycle thread,
then block on the recycle channel until both this frame's and the previous
in-flight frame's deposits have arrived. After this returns, every forked
wait thread has run its per-frame cleanup, so the outer ResourceT is safe
to tear down GPU resources.
Assumes max-in-flight is 2 (see initialFrame).
allocateTimelineSemaphore :: MonadResource m => Device -> Word64 -> m (ReleaseKey, Semaphore) Source #
Allocate a timeline semaphore initialised to the given value.
frameInstanceRequirements :: [InstanceRequirement] Source #
Instance-level requirements for the recycling Frame machinery. Merge
with your application's other InstanceRequirements at instance creation.
Required because checking PhysicalDeviceTimelineSemaphoreFeatures at
physical-device pick time goes through VkPhysicalDeviceFeatures2, which
needs either Vulkan 1.1+ or this extension.
frameDeviceRequirements :: [DeviceRequirement] Source #
The device-level requirements needed by runFrame queueSubmitFrame
allocateTimelineSemaphore. Merge into your other DeviceRequirements when
calling allocateDeviceFromRequirements.