{-# LANGUAGE OverloadedLists #-}

{-| The Vulkan-1.3-core "always-on" dynamic state: the set of pipeline state
that can be made dynamic without any vendor or experimental extension, so a
single pipeline object serves every combination instead of permuting into one
'Vk.Pipeline' per variation. See 'Vulkan.Utils.RenderPass.allocatePipeline'
and 'Vulkan.Utils.DynamicRendering.allocatePipeline'.

Because these states are declared dynamic, the matching @cmdSet*@ MUST be issued
before each draw (an unset dynamic state is undefined behaviour). The
'DynamicState' record carries the whole set with safe defaults; amend it with
the per-frame situation (the swapchain extent via 'dynamicStateFor') and emit
the lot in one go with 'applyDynamicStates' over 'allDynamicStates'.

Defaults mirror Vulkan's zero-initialized values, deviating only where a
non-zero is required for validity ('lineWidth' @= 1@) or to match the pipeline's
baked topology class ('topology' @= TRIANGLE_LIST@). They are feature-free
(no @wideLines@, no @depthBounds@) and valid with a colour-only attachment (all
depth/stencil tests disabled).
-}
module Vulkan.Utils.DynamicState
  ( -- * The dynamic-state record
    DynamicState (..)
  , defaultDynamicState
  , dynamicStateFor

    -- * Applying it
  , applyDynamicStates

    -- * The state set (pipeline @dynamicStates@ ⇆ apply, single source of truth)
  , allDynamicStates
  , depthOnlyDynamicStates
  , defaultDynamicStatesFor
  , minimalDynamicStates
  , noDynamicStates
  , preRasterizationStates
  , fragmentTestStates
  , fragmentOutputStates

    -- * Whole-extent viewport/scissor
  , fullViewport
  , fullScissor
  ) where

import Control.Monad.IO.Class (MonadIO)
import Data.Foldable (traverse_)
import Data.Vector (Vector)
import qualified Data.Vector as V
import Data.Word (Word32)
import qualified Vulkan.Core10 as Rect2D (Rect2D (..))
import qualified Vulkan.Core10 as Viewport (Viewport (..))
import qualified Vulkan.Core10 as Vk
import qualified Vulkan.Core13 as Vk
import Vulkan.Zero (zero)

-- | A viewport covering the whole extent, with depth range @0@ to @1@.
fullViewport :: Vk.Extent2D -> Vk.Viewport
fullViewport :: Extent2D -> Viewport
fullViewport (Vk.Extent2D Word32
w Word32
h) =
  Viewport
forall a. Zero a => a
zero
    { Viewport.width = realToFrac w
    , Viewport.height = realToFrac h
    , Viewport.maxDepth = 1
    }

-- | A scissor rectangle covering the whole extent (offset at the origin).
fullScissor :: Vk.Extent2D -> Vk.Rect2D
fullScissor :: Extent2D -> Rect2D
fullScissor Extent2D
extent = Rect2D
forall a. Zero a => a
zero{Rect2D.extent = extent}

----------------------------------------------------------------
-- The record
----------------------------------------------------------------

{- | Every Vulkan-1.3-core always-on dynamic state, as plain values. Field types
match the @cmdSet*@ argument shapes. The stencil ops apply to
@STENCIL_FACE_FRONT_AND_BACK@.
-}
data DynamicState = DynamicState
  { -- Pre-rasterization
    DynamicState -> Vector Viewport
viewports :: Vector Vk.Viewport
  , DynamicState -> Vector Rect2D
scissors :: Vector Vk.Rect2D
  , DynamicState -> PrimitiveTopology
topology :: Vk.PrimitiveTopology
  , DynamicState -> Bool
primitiveRestart :: Bool
  , DynamicState -> CullModeFlags
cullMode :: Vk.CullModeFlags
  , DynamicState -> FrontFace
frontFace :: Vk.FrontFace
  , DynamicState -> Bool
rasterizerDiscard :: Bool
  , DynamicState -> Float
lineWidth :: Float
  -- ^ @/= 1@ requires the @wideLines@ feature.
  , DynamicState -> Bool
depthBiasEnable :: Bool
  , DynamicState -> (Float, Float, Float)
depthBias :: (Float, Float, Float)
  -- ^ @(constantFactor, clamp, slopeFactor)@.
  , -- Fragment-shader depth/stencil tests
    DynamicState -> Bool
depthTest :: Bool
  , DynamicState -> Bool
depthWrite :: Bool
  , DynamicState -> CompareOp
depthCompareOp :: Vk.CompareOp
  , DynamicState -> Bool
depthBoundsTest :: Bool
  -- ^ Requires the @depthBounds@ feature.
  , DynamicState -> (Float, Float)
depthBounds :: (Float, Float)
  -- ^ @(min, max)@.
  , DynamicState -> Bool
stencilTest :: Bool
  , DynamicState -> StencilOp
stencilFailOp :: Vk.StencilOp
  , DynamicState -> StencilOp
stencilPassOp :: Vk.StencilOp
  , DynamicState -> StencilOp
stencilDepthFailOp :: Vk.StencilOp
  , DynamicState -> CompareOp
stencilCompareOp :: Vk.CompareOp
  , DynamicState -> Word32
stencilCompareMask :: Word32
  , DynamicState -> Word32
stencilWriteMask :: Word32
  , DynamicState -> Word32
stencilReference :: Word32
  , -- Fragment-output
    DynamicState -> (Float, Float, Float, Float)
blendConstants :: (Float, Float, Float, Float)
  }

{- | Safe, feature-free defaults (see module header). 'viewports' and 'scissors'
are empty — supply them with 'dynamicStateFor' or by record update before
applying.
-}
defaultDynamicState :: DynamicState
defaultDynamicState :: DynamicState
defaultDynamicState =
  DynamicState
    { viewports :: Vector Viewport
viewports = Vector Viewport
forall a. Vector a
V.empty
    , scissors :: Vector Rect2D
scissors = Vector Rect2D
forall a. Vector a
V.empty
    , topology :: PrimitiveTopology
topology = PrimitiveTopology
Vk.PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
    , primitiveRestart :: Bool
primitiveRestart = Bool
False
    , cullMode :: CullModeFlags
cullMode = CullModeFlags
Vk.CULL_MODE_NONE
    , frontFace :: FrontFace
frontFace = FrontFace
Vk.FRONT_FACE_COUNTER_CLOCKWISE
    , rasterizerDiscard :: Bool
rasterizerDiscard = Bool
False
    , lineWidth :: Float
lineWidth = Float
1
    , depthBiasEnable :: Bool
depthBiasEnable = Bool
False
    , depthBias :: (Float, Float, Float)
depthBias = (Float
0, Float
0, Float
0)
    , depthTest :: Bool
depthTest = Bool
False
    , depthWrite :: Bool
depthWrite = Bool
False
    , depthCompareOp :: CompareOp
depthCompareOp = CompareOp
Vk.COMPARE_OP_NEVER
    , depthBoundsTest :: Bool
depthBoundsTest = Bool
False
    , depthBounds :: (Float, Float)
depthBounds = (Float
0, Float
0)
    , stencilTest :: Bool
stencilTest = Bool
False
    , stencilFailOp :: StencilOp
stencilFailOp = StencilOp
Vk.STENCIL_OP_KEEP
    , stencilPassOp :: StencilOp
stencilPassOp = StencilOp
Vk.STENCIL_OP_KEEP
    , stencilDepthFailOp :: StencilOp
stencilDepthFailOp = StencilOp
Vk.STENCIL_OP_KEEP
    , stencilCompareOp :: CompareOp
stencilCompareOp = CompareOp
Vk.COMPARE_OP_NEVER
    , stencilCompareMask :: Word32
stencilCompareMask = Word32
0
    , stencilWriteMask :: Word32
stencilWriteMask = Word32
0
    , stencilReference :: Word32
stencilReference = Word32
0
    , blendConstants :: (Float, Float, Float, Float)
blendConstants = (Float
0, Float
0, Float
0, Float
0)
    }

{- | 'defaultDynamicState' with the whole-extent viewport and scissor filled in.
The common entry point; amend further by record update, e.g.

@
'applyDynamicStates' 'allDynamicStates' cb ('dynamicStateFor' ext){ 'cullMode' = Vk.CULL_MODE_BACK_BIT }
@
-}
dynamicStateFor :: Vk.Extent2D -> DynamicState
dynamicStateFor :: Extent2D -> DynamicState
dynamicStateFor Extent2D
ext =
  DynamicState
defaultDynamicState
    { viewports = V.singleton (fullViewport ext)
    , scissors = V.singleton (fullScissor ext)
    }

----------------------------------------------------------------
-- The state set (single source of truth)
----------------------------------------------------------------

preRasterizationStates :: Vector Vk.DynamicState
preRasterizationStates :: Vector DynamicState
preRasterizationStates =
  [ Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_VIEWPORT_WITH_COUNT
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_SCISSOR_WITH_COUNT
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_PRIMITIVE_TOPOLOGY
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_CULL_MODE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_FRONT_FACE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_LINE_WIDTH
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_BIAS_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_BIAS
  ]

-- | Fragment-shader depth/stencil dynamic states.
fragmentTestStates :: Vector Vk.DynamicState
fragmentTestStates :: Vector DynamicState
fragmentTestStates =
  [ Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_TEST_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_WRITE_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_COMPARE_OP
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_DEPTH_BOUNDS
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_STENCIL_TEST_ENABLE
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_STENCIL_OP
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_STENCIL_COMPARE_MASK
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_STENCIL_WRITE_MASK
  , Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_STENCIL_REFERENCE
  ]

fragmentOutputStates :: Vector Vk.DynamicState
fragmentOutputStates :: Vector DynamicState
fragmentOutputStates = [Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_BLEND_CONSTANTS]

{- | The whole always-on set: pass this (or 'Nothing', which resolves to it) to a
full-dynamic pipeline builder, and feed the same set to 'applyDynamicStates' so
the pipeline's @dynamicStates@ and the per-frame applies stay in lockstep.
-}
allDynamicStates :: Vector Vk.DynamicState
allDynamicStates :: Vector DynamicState
allDynamicStates =
  Vector DynamicState
preRasterizationStates Vector DynamicState -> Vector DynamicState -> Vector DynamicState
forall a. Semigroup a => a -> a -> a
<> Vector DynamicState
fragmentTestStates Vector DynamicState -> Vector DynamicState -> Vector DynamicState
forall a. Semigroup a => a -> a -> a
<> Vector DynamicState
fragmentOutputStates

{- | The set for a depth-only pipeline (no colour attachment): everything in
'allDynamicStates' except 'fragmentOutputStates' ('Vk.DYNAMIC_STATE_BLEND_CONSTANTS'),
which has no colour attachment to act on. Pair it with a depth-only pipeline and
feed the same set to 'applyDynamicStates'.
-}
depthOnlyDynamicStates :: Vector Vk.DynamicState
depthOnlyDynamicStates :: Vector DynamicState
depthOnlyDynamicStates = Vector DynamicState
preRasterizationStates Vector DynamicState -> Vector DynamicState -> Vector DynamicState
forall a. Semigroup a => a -> a -> a
<> Vector DynamicState
fragmentTestStates

{- | The default dynamic-state set for an attachment shape: 'allDynamicStates' when
there is at least one colour attachment, otherwise 'depthOnlyDynamicStates'. The
default a pipeline builder resolves @Nothing@ to.
-}
defaultDynamicStatesFor
  :: Bool
  -- ^ Whether the pipeline has any colour attachment.
  -> Vector Vk.DynamicState
defaultDynamicStatesFor :: Bool -> Vector DynamicState
defaultDynamicStatesFor Bool
hasColor
  | Bool
hasColor = Vector DynamicState
allDynamicStates
  | Bool
otherwise = Vector DynamicState
depthOnlyDynamicStates

{- | Just the (fixed-count) viewport and scissor. For pipelines that want only
those dynamic and set them with 'Vk.cmdSetViewport' / 'Vk.cmdSetScissor' (not the
with-count variants 'applyDynamicStates' issues for 'allDynamicStates').
-}
minimalDynamicStates :: Vector Vk.DynamicState
minimalDynamicStates :: Vector DynamicState
minimalDynamicStates =
  [Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_VIEWPORT, Item (Vector DynamicState)
DynamicState
Vk.DYNAMIC_STATE_SCISSOR]

{- | Declare /nothing/ dynamic: every state is baked into the pipeline, so no
@cmdSet*@ need be issued (skip 'applyDynamicStates' entirely). Pass it where a
builder takes @Maybe (Vector Vk.DynamicState)@.

The pipeline must then carry a complete static state — crucially a baked viewport
and scissor — so this suits a builder that bakes those (typically a fixed-size
offscreen target). The colour-pipeline builders here instead leave viewport and
scissor dynamic, so they pair with 'Nothing' / 'allDynamicStates', not this.
-}
noDynamicStates :: Maybe (Vector Vk.DynamicState)
noDynamicStates :: Maybe (Vector DynamicState)
noDynamicStates = Vector DynamicState -> Maybe (Vector DynamicState)
forall a. a -> Maybe a
Just Vector DynamicState
forall a. Vector a
V.empty

----------------------------------------------------------------
-- Applying
----------------------------------------------------------------

{- | Issue the @cmdSet*@ for exactly the given states, pulling values from the
record. Use the same set passed to the pipeline builder for exact lockstep.
States not modelled by 'DynamicState' are skipped (the caller must set those
themselves).
-}
applyDynamicStates
  :: (MonadIO m) => Vector Vk.DynamicState -> Vk.CommandBuffer -> DynamicState -> m ()
applyDynamicStates :: forall (m :: * -> *).
MonadIO m =>
Vector DynamicState -> CommandBuffer -> DynamicState -> m ()
applyDynamicStates Vector DynamicState
states CommandBuffer
cb DynamicState
s = (DynamicState -> m ()) -> Vector DynamicState -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ DynamicState -> m ()
go Vector DynamicState
states
  where
    DynamicState{Bool
Float
Word32
(Float, Float)
(Float, Float, Float)
(Float, Float, Float, Float)
Vector Rect2D
Vector Viewport
CompareOp
CullModeFlags
FrontFace
PrimitiveTopology
StencilOp
lineWidth :: DynamicState -> Float
topology :: DynamicState -> PrimitiveTopology
viewports :: DynamicState -> Vector Viewport
scissors :: DynamicState -> Vector Rect2D
primitiveRestart :: DynamicState -> Bool
cullMode :: DynamicState -> CullModeFlags
frontFace :: DynamicState -> FrontFace
rasterizerDiscard :: DynamicState -> Bool
depthBiasEnable :: DynamicState -> Bool
depthBias :: DynamicState -> (Float, Float, Float)
depthTest :: DynamicState -> Bool
depthWrite :: DynamicState -> Bool
depthCompareOp :: DynamicState -> CompareOp
depthBoundsTest :: DynamicState -> Bool
depthBounds :: DynamicState -> (Float, Float)
stencilTest :: DynamicState -> Bool
stencilFailOp :: DynamicState -> StencilOp
stencilPassOp :: DynamicState -> StencilOp
stencilDepthFailOp :: DynamicState -> StencilOp
stencilCompareOp :: DynamicState -> CompareOp
stencilCompareMask :: DynamicState -> Word32
stencilWriteMask :: DynamicState -> Word32
stencilReference :: DynamicState -> Word32
blendConstants :: DynamicState -> (Float, Float, Float, Float)
viewports :: Vector Viewport
scissors :: Vector Rect2D
topology :: PrimitiveTopology
primitiveRestart :: Bool
cullMode :: CullModeFlags
frontFace :: FrontFace
rasterizerDiscard :: Bool
lineWidth :: Float
depthBiasEnable :: Bool
depthBias :: (Float, Float, Float)
depthTest :: Bool
depthWrite :: Bool
depthCompareOp :: CompareOp
depthBoundsTest :: Bool
depthBounds :: (Float, Float)
stencilTest :: Bool
stencilFailOp :: StencilOp
stencilPassOp :: StencilOp
stencilDepthFailOp :: StencilOp
stencilCompareOp :: CompareOp
stencilCompareMask :: Word32
stencilWriteMask :: Word32
stencilReference :: Word32
blendConstants :: (Float, Float, Float, Float)
..} = DynamicState
s
    bothFaces :: StencilFaceFlagBits
bothFaces = StencilFaceFlagBits
Vk.STENCIL_FACE_FRONT_AND_BACK
    (Float
biasConstant, Float
biasClamp, Float
biasSlope) = (Float, Float, Float)
depthBias
    (Float
minBound', Float
maxBound') = (Float, Float)
depthBounds
    go :: DynamicState -> m ()
go = \case
      DynamicState
Vk.DYNAMIC_STATE_VIEWPORT_WITH_COUNT -> CommandBuffer -> Vector Viewport -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> Vector Viewport -> io ()
Vk.cmdSetViewportWithCount CommandBuffer
cb Vector Viewport
viewports
      DynamicState
Vk.DYNAMIC_STATE_SCISSOR_WITH_COUNT -> CommandBuffer -> Vector Rect2D -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> Vector Rect2D -> io ()
Vk.cmdSetScissorWithCount CommandBuffer
cb Vector Rect2D
scissors
      DynamicState
Vk.DYNAMIC_STATE_PRIMITIVE_TOPOLOGY -> CommandBuffer -> PrimitiveTopology -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> PrimitiveTopology -> io ()
Vk.cmdSetPrimitiveTopology CommandBuffer
cb PrimitiveTopology
topology
      DynamicState
Vk.DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetPrimitiveRestartEnable CommandBuffer
cb Bool
primitiveRestart
      DynamicState
Vk.DYNAMIC_STATE_CULL_MODE -> CommandBuffer -> CullModeFlags -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> CullModeFlags -> io ()
Vk.cmdSetCullMode CommandBuffer
cb CullModeFlags
cullMode
      DynamicState
Vk.DYNAMIC_STATE_FRONT_FACE -> CommandBuffer -> FrontFace -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> FrontFace -> io ()
Vk.cmdSetFrontFace CommandBuffer
cb FrontFace
frontFace
      DynamicState
Vk.DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetRasterizerDiscardEnable CommandBuffer
cb Bool
rasterizerDiscard
      DynamicState
Vk.DYNAMIC_STATE_LINE_WIDTH -> CommandBuffer -> Float -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> Float -> io ()
Vk.cmdSetLineWidth CommandBuffer
cb Float
lineWidth
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_BIAS_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetDepthBiasEnable CommandBuffer
cb Bool
depthBiasEnable
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_BIAS -> CommandBuffer -> Float -> Float -> Float -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> Float -> Float -> Float -> io ()
Vk.cmdSetDepthBias CommandBuffer
cb Float
biasConstant Float
biasClamp Float
biasSlope
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_TEST_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetDepthTestEnable CommandBuffer
cb Bool
depthTest
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_WRITE_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetDepthWriteEnable CommandBuffer
cb Bool
depthWrite
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_COMPARE_OP -> CommandBuffer -> CompareOp -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> CompareOp -> io ()
Vk.cmdSetDepthCompareOp CommandBuffer
cb CompareOp
depthCompareOp
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetDepthBoundsTestEnable CommandBuffer
cb Bool
depthBoundsTest
      DynamicState
Vk.DYNAMIC_STATE_DEPTH_BOUNDS -> CommandBuffer -> Float -> Float -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> Float -> Float -> io ()
Vk.cmdSetDepthBounds CommandBuffer
cb Float
minBound' Float
maxBound'
      DynamicState
Vk.DYNAMIC_STATE_STENCIL_TEST_ENABLE -> CommandBuffer -> Bool -> m ()
forall (io :: * -> *). MonadIO io => CommandBuffer -> Bool -> io ()
Vk.cmdSetStencilTestEnable CommandBuffer
cb Bool
stencilTest
      DynamicState
Vk.DYNAMIC_STATE_STENCIL_OP ->
        CommandBuffer
-> StencilFaceFlagBits
-> StencilOp
-> StencilOp
-> StencilOp
-> CompareOp
-> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer
-> StencilFaceFlagBits
-> StencilOp
-> StencilOp
-> StencilOp
-> CompareOp
-> io ()
Vk.cmdSetStencilOp CommandBuffer
cb StencilFaceFlagBits
bothFaces StencilOp
stencilFailOp StencilOp
stencilPassOp StencilOp
stencilDepthFailOp CompareOp
stencilCompareOp
      DynamicState
Vk.DYNAMIC_STATE_STENCIL_COMPARE_MASK -> CommandBuffer -> StencilFaceFlagBits -> Word32 -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> StencilFaceFlagBits -> Word32 -> io ()
Vk.cmdSetStencilCompareMask CommandBuffer
cb StencilFaceFlagBits
bothFaces Word32
stencilCompareMask
      DynamicState
Vk.DYNAMIC_STATE_STENCIL_WRITE_MASK -> CommandBuffer -> StencilFaceFlagBits -> Word32 -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> StencilFaceFlagBits -> Word32 -> io ()
Vk.cmdSetStencilWriteMask CommandBuffer
cb StencilFaceFlagBits
bothFaces Word32
stencilWriteMask
      DynamicState
Vk.DYNAMIC_STATE_STENCIL_REFERENCE -> CommandBuffer -> StencilFaceFlagBits -> Word32 -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> StencilFaceFlagBits -> Word32 -> io ()
Vk.cmdSetStencilReference CommandBuffer
cb StencilFaceFlagBits
bothFaces Word32
stencilReference
      DynamicState
Vk.DYNAMIC_STATE_BLEND_CONSTANTS -> CommandBuffer -> (Float, Float, Float, Float) -> m ()
forall (io :: * -> *).
MonadIO io =>
CommandBuffer -> (Float, Float, Float, Float) -> io ()
Vk.cmdSetBlendConstants CommandBuffer
cb (Float, Float, Float, Float)
blendConstants
      DynamicState
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()