content: {-# language CPP #-}
  -- | = Name
  --
  -- VK_GOOGLE_display_timing - device extension
  --
  -- == VK_GOOGLE_display_timing
  --
  -- [__Name String__]
  --     @VK_GOOGLE_display_timing@
  --
  -- [__Extension Type__]
  --     Device extension
  --
  -- [__Registered Extension Number__]
  --     93
  --
  -- [__Revision__]
  --     1
  --
  -- [__Ratification Status__]
  --     Not ratified
  --
  -- [__Extension and Version Dependencies__]
  --     <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_KHR_swapchain VK_KHR_swapchain>
  --
  -- [__Contact__]
  --
  --     -   Ian Elliott
  --         <https://github.com/KhronosGroup/Vulkan-Docs/issues/new?body=[VK_GOOGLE_display_timing] @ianelliottus%0A*Here describe the issue or question you have about the VK_GOOGLE_display_timing extension* >
  --
  -- == Other Extension Metadata
  --
  -- [__Last Modified Date__]
  --     2017-02-14
  --
  -- [__IP Status__]
  --     No known IP claims.
  --
  -- [__Contributors__]
  --
  --     -   Ian Elliott, Google
  --
  --     -   Jesse Hall, Google
  --
  -- == Description
  --
  -- This device extension allows an application that uses the
  -- @VK_KHR_swapchain@ extension to obtain information about the
  -- presentation engine’s display, to obtain timing information about each
  -- present, and to schedule a present to happen no earlier than a desired
  -- time. An application can use this to minimize various visual anomalies
  -- (e.g. stuttering).
  --
  -- Traditional game and real-time animation applications need to correctly
  -- position their geometry for when the presentable image will be presented
  -- to the user. To accomplish this, applications need various timing
  -- information about the presentation engine’s display. They need to know
  -- when presentable images were actually presented, and when they could
  -- have been presented. Applications also need to tell the presentation
  -- engine to display an image no sooner than a given time. This allows the
  -- application to avoid stuttering, so the animation looks smooth to the
  -- user.
  --
  -- This extension treats variable-refresh-rate (VRR) displays as if they
  -- are fixed-refresh-rate (FRR) displays.
  --
  -- == New Commands
  --
  -- -   'getPastPresentationTimingGOOGLE'
  --
  -- -   'getRefreshCycleDurationGOOGLE'
  --
  -- == New Structures
  --
  -- -   'PastPresentationTimingGOOGLE'
  --
  -- -   'PresentTimeGOOGLE'
  --
  -- -   'RefreshCycleDurationGOOGLE'
  --
  -- -   Extending 'Vulkan.Extensions.VK_KHR_swapchain.PresentInfoKHR':
  --
  --     -   'PresentTimesInfoGOOGLE'
  --
  -- == New Enum Constants
  --
  -- -   'GOOGLE_DISPLAY_TIMING_EXTENSION_NAME'
  --
  -- -   'GOOGLE_DISPLAY_TIMING_SPEC_VERSION'
  --
  -- -   Extending 'Vulkan.Core10.Enums.StructureType.StructureType':
  --
  --     -   'Vulkan.Core10.Enums.StructureType.STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE'
  --
  -- == Examples
  --
  -- Note
  --
  -- The example code for the this extension (like the @VK_KHR_surface@ and
  -- @VK_GOOGLE_display_timing@ extensions) is contained in the cube demo
  -- that is shipped with the official Khronos SDK, and is being kept
  -- up-to-date in that location (see:
  -- <https://github.com/KhronosGroup/Vulkan-Tools/blob/master/cube/cube.c>
  -- ).
  --
  -- == Version History
  --
  -- -   Revision 1, 2017-02-14 (Ian Elliott)
  --
  --     -   Internal revisions
  --
  -- == See Also
  --
  -- 'PastPresentationTimingGOOGLE', 'PresentTimeGOOGLE',
  -- 'PresentTimesInfoGOOGLE', 'RefreshCycleDurationGOOGLE',
  -- 'getPastPresentationTimingGOOGLE', 'getRefreshCycleDurationGOOGLE'
  --
  -- == Document Notes
  --
  -- For more information, see the
  -- <https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VK_GOOGLE_display_timing Vulkan Specification>
  --
  -- This page is a generated document. Fixes and changes should be made to
  -- the generator scripts, not directly.
  module Vulkan.Extensions.VK_GOOGLE_display_timing  ( getRefreshCycleDurationGOOGLE
                                                     , getPastPresentationTimingGOOGLE
                                                     , RefreshCycleDurationGOOGLE(..)
                                                     , PastPresentationTimingGOOGLE(..)
                                                     , PresentTimesInfoGOOGLE(..)
                                                     , PresentTimeGOOGLE(..)
                                                     , GOOGLE_DISPLAY_TIMING_SPEC_VERSION
                                                     , pattern GOOGLE_DISPLAY_TIMING_SPEC_VERSION
                                                     , GOOGLE_DISPLAY_TIMING_EXTENSION_NAME
                                                     , pattern GOOGLE_DISPLAY_TIMING_EXTENSION_NAME
                                                     , SwapchainKHR(..)
                                                     ) where
  
  import Vulkan.Internal.Utils (traceAroundEvent)
  import Control.Exception.Base (bracket)
  import Control.Monad (unless)
  import Control.Monad.IO.Class (liftIO)
  import Foreign.Marshal.Alloc (allocaBytes)
  import Foreign.Marshal.Alloc (callocBytes)
  import Foreign.Marshal.Alloc (free)
  import GHC.Base (when)
  import GHC.IO (throwIO)
  import GHC.Ptr (nullFunPtr)
  import Foreign.Ptr (nullPtr)
  import Foreign.Ptr (plusPtr)
  import Control.Monad.Trans.Class (lift)
  import Control.Monad.Trans.Cont (evalContT)
  import Data.Vector (generateM)
  import qualified Data.Vector (imapM_)
  import qualified Data.Vector (length)
  import qualified Data.Vector (null)
  import Vulkan.CStruct (FromCStruct)
  import Vulkan.CStruct (FromCStruct(..))
  import Vulkan.CStruct (ToCStruct)
  import Vulkan.CStruct (ToCStruct(..))
  import Vulkan.Zero (Zero(..))
  import Control.Monad.IO.Class (MonadIO)
  import Data.String (IsString)
  import Data.Typeable (Typeable)
  import Foreign.Storable (Storable)
  import Foreign.Storable (Storable(peek))
  import Foreign.Storable (Storable(poke))
  import qualified Foreign.Storable (Storable(..))
  import GHC.Generics (Generic)
  import GHC.IO.Exception (IOErrorType(..))
  import GHC.IO.Exception (IOException(..))
  import Foreign.Ptr (FunPtr)
  import Foreign.Ptr (Ptr)
  import Data.Word (Word32)
  import Data.Word (Word64)
  import Data.Kind (Type)
  import Control.Monad.Trans.Cont (ContT(..))
  import Data.Vector (Vector)
  import Vulkan.CStruct.Utils (advancePtrBytes)
  import Vulkan.NamedType ((:::))
  import Vulkan.Core10.Handles (Device)
  import Vulkan.Core10.Handles (Device(..))
  import Vulkan.Core10.Handles (Device(Device))
  import Vulkan.Dynamic (DeviceCmds(pVkGetPastPresentationTimingGOOGLE))
  import Vulkan.Dynamic (DeviceCmds(pVkGetRefreshCycleDurationGOOGLE))
  import Vulkan.Core10.Handles (Device_T)
  import Vulkan.Core10.Enums.Result (Result)
  import Vulkan.Core10.Enums.Result (Result(..))
  import Vulkan.Core10.Enums.StructureType (StructureType)
  import Vulkan.Extensions.Handles (SwapchainKHR)
  import Vulkan.Extensions.Handles (SwapchainKHR(..))
  import Vulkan.Exception (VulkanException(..))
  import Vulkan.Core10.Enums.StructureType (StructureType(STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE))
  import Vulkan.Core10.Enums.Result (Result(SUCCESS))
  import Vulkan.Extensions.Handles (SwapchainKHR(..))
  foreign import ccall
  #if !defined(SAFE_FOREIGN_CALLS)
    unsafe
  #endif
    "dynamic" mkVkGetRefreshCycleDurationGOOGLE
    :: FunPtr (Ptr Device_T -> SwapchainKHR -> Ptr RefreshCycleDurationGOOGLE -> IO Result) -> Ptr Device_T -> SwapchainKHR -> Ptr RefreshCycleDurationGOOGLE -> IO Result
  
  -- | vkGetRefreshCycleDurationGOOGLE - Obtain the RC duration of the PE’s
  -- display
  --
  -- == Valid Usage (Implicit)
  --
  -- -   #VUID-vkGetRefreshCycleDurationGOOGLE-device-parameter# @device@
  --     /must/ be a valid 'Vulkan.Core10.Handles.Device' handle
  --
  -- -   #VUID-vkGetRefreshCycleDurationGOOGLE-swapchain-parameter#
  --     @swapchain@ /must/ be a valid
  --     'Vulkan.Extensions.Handles.SwapchainKHR' handle
  --
  -- -   #VUID-vkGetRefreshCycleDurationGOOGLE-pDisplayTimingProperties-parameter#
  --     @pDisplayTimingProperties@ /must/ be a valid pointer to a
  --     'RefreshCycleDurationGOOGLE' structure
  --
  -- -   #VUID-vkGetRefreshCycleDurationGOOGLE-swapchain-parent# @swapchain@
  --     /must/ have been created, allocated, or retrieved from @device@
  --
  -- == Host Synchronization
  --
  -- -   Host access to @swapchain@ /must/ be externally synchronized
  --
  -- == Return Codes
  --
  -- [<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#fundamentals-successcodes Success>]
  --
  --     -   'Vulkan.Core10.Enums.Result.SUCCESS'
  --
  -- [<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#fundamentals-errorcodes Failure>]
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_OUT_OF_HOST_MEMORY'
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_DEVICE_LOST'
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_SURFACE_LOST_KHR'
  --
  -- = See Also
  --
  -- <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_GOOGLE_display_timing VK_GOOGLE_display_timing>,
  -- 'Vulkan.Core10.Handles.Device', 'RefreshCycleDurationGOOGLE',
  -- 'Vulkan.Extensions.Handles.SwapchainKHR'
  getRefreshCycleDurationGOOGLE :: forall io
                                 . (MonadIO io)
                                => -- | @device@ is the device associated with @swapchain@.
                                   Device
                                -> -- | @swapchain@ is the swapchain to obtain the refresh duration for.
                                   SwapchainKHR
                                -> io (("displayTimingProperties" ::: RefreshCycleDurationGOOGLE))
  getRefreshCycleDurationGOOGLE device swapchain = liftIO . evalContT $ do
    let vkGetRefreshCycleDurationGOOGLEPtr = pVkGetRefreshCycleDurationGOOGLE (case device of Device{deviceCmds} -> deviceCmds)
    lift $ unless (vkGetRefreshCycleDurationGOOGLEPtr /= nullFunPtr) $
      throwIO $ IOError Nothing InvalidArgument "" "The function pointer for vkGetRefreshCycleDurationGOOGLE is null" Nothing Nothing
    let vkGetRefreshCycleDurationGOOGLE' = mkVkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLEPtr
    pPDisplayTimingProperties <- ContT (withZeroCStruct @RefreshCycleDurationGOOGLE)
    r <- lift $ traceAroundEvent "vkGetRefreshCycleDurationGOOGLE" (vkGetRefreshCycleDurationGOOGLE'
                                                                      (deviceHandle (device))
                                                                      (swapchain)
                                                                      (pPDisplayTimingProperties))
    lift $ when (r < SUCCESS) (throwIO (VulkanException r))
    pDisplayTimingProperties <- lift $ peekCStruct @RefreshCycleDurationGOOGLE pPDisplayTimingProperties
    pure $ (pDisplayTimingProperties)
  
  
  foreign import ccall
  #if !defined(SAFE_FOREIGN_CALLS)
    unsafe
  #endif
    "dynamic" mkVkGetPastPresentationTimingGOOGLE
    :: FunPtr (Ptr Device_T -> SwapchainKHR -> Ptr Word32 -> Ptr PastPresentationTimingGOOGLE -> IO Result) -> Ptr Device_T -> SwapchainKHR -> Ptr Word32 -> Ptr PastPresentationTimingGOOGLE -> IO Result
  
  -- | vkGetPastPresentationTimingGOOGLE - Obtain timing of a
  -- previously-presented image
  --
  -- = Description
  --
  -- If @pPresentationTimings@ is @NULL@, then the number of newly-available
  -- timing records for the given @swapchain@ is returned in
  -- @pPresentationTimingCount@. Otherwise, @pPresentationTimingCount@ /must/
  -- point to a variable set by the user to the number of elements in the
  -- @pPresentationTimings@ array, and on return the variable is overwritten
  -- with the number of structures actually written to
  -- @pPresentationTimings@. If the value of @pPresentationTimingCount@ is
  -- less than the number of newly-available timing records, at most
  -- @pPresentationTimingCount@ structures will be written, and
  -- 'Vulkan.Core10.Enums.Result.INCOMPLETE' will be returned instead of
  -- 'Vulkan.Core10.Enums.Result.SUCCESS', to indicate that not all the
  -- available timing records were returned.
  --
  -- == Valid Usage (Implicit)
  --
  -- -   #VUID-vkGetPastPresentationTimingGOOGLE-device-parameter# @device@
  --     /must/ be a valid 'Vulkan.Core10.Handles.Device' handle
  --
  -- -   #VUID-vkGetPastPresentationTimingGOOGLE-swapchain-parameter#
  --     @swapchain@ /must/ be a valid
  --     'Vulkan.Extensions.Handles.SwapchainKHR' handle
  --
  -- -   #VUID-vkGetPastPresentationTimingGOOGLE-pPresentationTimingCount-parameter#
  --     @pPresentationTimingCount@ /must/ be a valid pointer to a @uint32_t@
  --     value
  --
  -- -   #VUID-vkGetPastPresentationTimingGOOGLE-pPresentationTimings-parameter#
  --     If the value referenced by @pPresentationTimingCount@ is not @0@,
  --     and @pPresentationTimings@ is not @NULL@, @pPresentationTimings@
  --     /must/ be a valid pointer to an array of @pPresentationTimingCount@
  --     'PastPresentationTimingGOOGLE' structures
  --
  -- -   #VUID-vkGetPastPresentationTimingGOOGLE-swapchain-parent#
  --     @swapchain@ /must/ have been created, allocated, or retrieved from
  --     @device@
  --
  -- == Host Synchronization
  --
  -- -   Host access to @swapchain@ /must/ be externally synchronized
  --
  -- == Return Codes
  --
  -- [<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#fundamentals-successcodes Success>]
  --
  --     -   'Vulkan.Core10.Enums.Result.SUCCESS'
  --
  --     -   'Vulkan.Core10.Enums.Result.INCOMPLETE'
  --
  -- [<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#fundamentals-errorcodes Failure>]
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_OUT_OF_HOST_MEMORY'
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_DEVICE_LOST'
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_OUT_OF_DATE_KHR'
  --
  --     -   'Vulkan.Core10.Enums.Result.ERROR_SURFACE_LOST_KHR'
  --
  -- = See Also
  --
  -- <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_GOOGLE_display_timing VK_GOOGLE_display_timing>,
  -- 'Vulkan.Core10.Handles.Device', 'PastPresentationTimingGOOGLE',
  -- 'Vulkan.Extensions.Handles.SwapchainKHR'
  getPastPresentationTimingGOOGLE :: forall io
                                   . (MonadIO io)
                                  => -- | @device@ is the device associated with @swapchain@.
                                     Device
                                  -> -- | @swapchain@ is the swapchain to obtain presentation timing information
                                     -- duration for.
                                     SwapchainKHR
                                  -> io (Result, ("presentationTimings" ::: Vector PastPresentationTimingGOOGLE))
  getPastPresentationTimingGOOGLE device swapchain = liftIO . evalContT $ do
    let vkGetPastPresentationTimingGOOGLEPtr = pVkGetPastPresentationTimingGOOGLE (case device of Device{deviceCmds} -> deviceCmds)
    lift $ unless (vkGetPastPresentationTimingGOOGLEPtr /= nullFunPtr) $
      throwIO $ IOError Nothing InvalidArgument "" "The function pointer for vkGetPastPresentationTimingGOOGLE is null" Nothing Nothing
    let vkGetPastPresentationTimingGOOGLE' = mkVkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLEPtr
    let device' = deviceHandle (device)
    pPPresentationTimingCount <- ContT $ bracket (callocBytes @Word32 4) free
    r <- lift $ traceAroundEvent "vkGetPastPresentationTimingGOOGLE" (vkGetPastPresentationTimingGOOGLE'
                                                                        device'
                                                                        (swapchain)
                                                                        (pPPresentationTimingCount)
                                                                        (nullPtr))
    lift $ when (r < SUCCESS) (throwIO (VulkanException r))
    pPresentationTimingCount <- lift $ peek @Word32 pPPresentationTimingCount
    pPPresentationTimings <- ContT $ bracket (callocBytes @PastPresentationTimingGOOGLE ((fromIntegral (pPresentationTimingCount)) * 40)) free
    _ <- traverse (\i -> ContT $ pokeZeroCStruct (pPPresentationTimings `advancePtrBytes` (i * 40) :: Ptr PastPresentationTimingGOOGLE) . ($ ())) [0..(fromIntegral (pPresentationTimingCount)) - 1]
    r' <- lift $ traceAroundEvent "vkGetPastPresentationTimingGOOGLE" (vkGetPastPresentationTimingGOOGLE'
                                                                         device'
                                                                         (swapchain)
                                                                         (pPPresentationTimingCount)
                                                                         ((pPPresentationTimings)))
    lift $ when (r' < SUCCESS) (throwIO (VulkanException r'))
    pPresentationTimingCount' <- lift $ peek @Word32 pPPresentationTimingCount
    pPresentationTimings' <- lift $ generateM (fromIntegral (pPresentationTimingCount')) (\i -> peekCStruct @PastPresentationTimingGOOGLE (((pPPresentationTimings) `advancePtrBytes` (40 * (i)) :: Ptr PastPresentationTimingGOOGLE)))
    pure $ ((r'), pPresentationTimings')
  
  
  -- | VkRefreshCycleDurationGOOGLE - Structure containing the RC duration of a
  -- display
  --
  -- = See Also
  --
  -- <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_GOOGLE_display_timing VK_GOOGLE_display_timing>,
  -- 'getRefreshCycleDurationGOOGLE'
  data RefreshCycleDurationGOOGLE = RefreshCycleDurationGOOGLE
    { -- | @refreshDuration@ is the number of nanoseconds from the start of one
      -- refresh cycle to the next.
      refreshDuration :: Word64 }
    deriving (Typeable, Eq)
  #if defined(GENERIC_INSTANCES)
  deriving instance Generic (RefreshCycleDurationGOOGLE)
  #endif
  deriving instance Show RefreshCycleDurationGOOGLE
  
  instance ToCStruct RefreshCycleDurationGOOGLE where
    withCStruct x f = allocaBytes 8 $ \p -> pokeCStruct p x (f p)
    pokeCStruct p RefreshCycleDurationGOOGLE{..} f = do
      poke ((p `plusPtr` 0 :: Ptr Word64)) (refreshDuration)
      f
    cStructSize = 8
    cStructAlignment = 8
    pokeZeroCStruct p f = do
      poke ((p `plusPtr` 0 :: Ptr Word64)) (zero)
      f
  
  instance FromCStruct RefreshCycleDurationGOOGLE where
    peekCStruct p = do
      refreshDuration <- peek @Word64 ((p `plusPtr` 0 :: Ptr Word64))
      pure $ RefreshCycleDurationGOOGLE
               refreshDuration
  
  instance Storable RefreshCycleDurationGOOGLE where
    sizeOf ~_ = 8
    alignment ~_ = 8
    peek = peekCStruct
    poke ptr poked = pokeCStruct ptr poked (pure ())
  
  instance Zero RefreshCycleDurationGOOGLE where
    zero = RefreshCycleDurationGOOGLE
             zero
  
  
  -- | VkPastPresentationTimingGOOGLE - Structure containing timing information
  -- about a previously-presented image
  --
  -- = Description
  --
  -- The results for a given @swapchain@ and @presentID@ are only returned
  -- once from 'getPastPresentationTimingGOOGLE'.
  --
  -- The application /can/ use the 'PastPresentationTimingGOOGLE' values to
  -- occasionally adjust its timing. For example, if @actualPresentTime@ is
  -- later than expected (e.g. one @refreshDuration@ late), the application
  -- may increase its target IPD to a higher multiple of @refreshDuration@
  -- (e.g. decrease its frame rate from 60Hz to 30Hz). If @actualPresentTime@
  -- and @earliestPresentTime@ are consistently different, and if
  -- @presentMargin@ is consistently large enough, the application may
  -- decrease its target IPD to a smaller multiple of @refreshDuration@ (e.g.
  -- increase its frame rate from 30Hz to 60Hz). If @actualPresentTime@ and
  -- @earliestPresentTime@ are same, and if @presentMargin@ is consistently
  -- high, the application may delay the start of its input-render-present
  -- loop in order to decrease the latency between user input and the
  -- corresponding present (always leaving some margin in case a new image
  -- takes longer to render than the previous image). An application that
  -- desires its target IPD to always be the same as @refreshDuration@, can
  -- also adjust features until @actualPresentTime@ is never late and
  -- @presentMargin@ is satisfactory.
  --
  -- = See Also
  --
  -- <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_GOOGLE_display_timing VK_GOOGLE_display_timing>,
  -- 'getPastPresentationTimingGOOGLE'
  data PastPresentationTimingGOOGLE = PastPresentationTimingGOOGLE
    { -- | @presentID@ is an application-provided value that was given to a
      -- previous 'Vulkan.Extensions.VK_KHR_swapchain.queuePresentKHR' command
      -- via 'PresentTimeGOOGLE'::@presentID@ (see below). It /can/ be used to
      -- uniquely identify a previous present with the
      -- 'Vulkan.Extensions.VK_KHR_swapchain.queuePresentKHR' command.
      presentID :: Word32
    , -- | @desiredPresentTime@ is an application-provided value that was given to
      -- a previous 'Vulkan.Extensions.VK_KHR_swapchain.queuePresentKHR' command
      -- via 'PresentTimeGOOGLE'::@desiredPresentTime@. If non-zero, it was used
      -- by the application to indicate that an image not be presented any sooner
      -- than @desiredPresentTime@.
      desiredPresentTime :: Word64
    , -- | @actualPresentTime@ is the time when the image of the @swapchain@ was
      -- actually displayed.
      actualPresentTime :: Word64
    , -- | @earliestPresentTime@ is the time when the image of the @swapchain@
      -- could have been displayed. This /may/ differ from @actualPresentTime@ if
      -- the application requested that the image be presented no sooner than
      -- 'PresentTimeGOOGLE'::@desiredPresentTime@.
      earliestPresentTime :: Word64
    , -- | @presentMargin@ is an indication of how early the
      -- 'Vulkan.Extensions.VK_KHR_swapchain.queuePresentKHR' command was
      -- processed compared to how soon it needed to be processed, and still be
      -- presented at @earliestPresentTime@.
      presentMargin :: Word64
    }
    deriving (Typeable, Eq)
  #if defined(GENERIC_INSTANCES)
  deriving instance Generic (PastPresentationTimingGOOGLE)
  #endif
  deriving instance Show PastPresentationTimingGOOGLE
  
  instance ToCStruct PastPresentationTimingGOOGLE where
    withCStruct x f = allocaBytes 40 $ \p -> pokeCStruct p x (f p)
    pokeCStruct p PastPresentationTimingGOOGLE{..} f = do
      poke ((p `plusPtr` 0 :: Ptr Word32)) (presentID)
      poke ((p `plusPtr` 8 :: Ptr Word64)) (desiredPresentTime)
      poke ((p `plusPtr` 16 :: Ptr Word64)) (actualPresentTime)
      poke ((p `plusPtr` 24 :: Ptr Word64)) (earliestPresentTime)
      poke ((p `plusPtr` 32 :: Ptr Word64)) (presentMargin)
      f
    cStructSize = 40
    cStructAlignment = 8
    pokeZeroCStruct p f = do
      poke ((p `plusPtr` 0 :: Ptr Word32)) (zero)
      poke ((p `plusPtr` 8 :: Ptr Word64)) (zero)
      poke ((p `plusPtr` 16 :: Ptr Word64)) (zero)
      poke ((p `plusPtr` 24 :: Ptr Word64)) (zero)
      poke ((p `plusPtr` 32 :: Ptr Word64)) (zero)
      f
  
  instance FromCStruct PastPresentationTimingGOOGLE where
    peekCStruct p = do
      presentID <- peek @Word32 ((p `plusPtr` 0 :: Ptr Word32))
      desiredPresentTime <- peek @Word64 ((p `plusPtr` 8 :: Ptr Word64))
      actualPresentTime <- peek @Word64 ((p `plusPtr` 16 :: Ptr Word64))
      earliestPresentTime <- peek @Word64 ((p `plusPtr` 24 :: Ptr Word64))
      presentMargin <- peek @Word64 ((p `plusPtr` 32 :: Ptr Word64))
      pure $ PastPresentationTimingGOOGLE
               presentID
               desiredPresentTime
               actualPresentTime
               earliestPresentTime
               presentMargin
  
  instance Storable PastPresentationTimingGOOGLE where
    sizeOf ~_ = 40
    alignment ~_ = 8
    peek = peekCStruct
    poke ptr poked = pokeCStruct ptr poked (pure ())
  
  instance Zero PastPresentationTimingGOOGLE where
    zero = PastPresentationTimingGOOGLE
             zero
             zero
             zero
             zero
             zero
  
  
  -- | VkPresentTimesInfoGOOGLE - The earliest time each image should be
  -- presented
  --
  -- == Valid Usage
  --
  -- -   #VUID-VkPresentTimesInfoGOOGLE-swapchainCount-01247#
  --     @swapchainCount@ /must/ be the same value as
  --     'Vulkan.Extensions.VK_KHR_swapchain.PresentInfoKHR'::@swapchainCount@,
  --     where 'Vulkan.Extensions.VK_KHR_swapchain.PresentInfoKHR' is
  --     included in the @pNext@ chain of this 'PresentTimesInfoGOOGLE'
  --     structure
  --
  -- == Valid Usage (Implicit)
  --
  -- -   #VUID-VkPresentTimesInfoGOOGLE-sType-sType# @sType@ /must/ be
  --     'Vulkan.Core10.Enums.StructureType.STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE'
  --
  -- -   #VUID-VkPresentTimesInfoGOOGLE-pTimes-parameter# If @pTimes@ is not
  --     @NULL@, @pTimes@ /must/ be a valid pointer to an array of
  --     @swapchainCount@ 'PresentTimeGOOGLE' structures
  --
  -- -   #VUID-VkPresentTimesInfoGOOGLE-swapchainCount-arraylength#
  --     @swapchainCount@ /must/ be greater than @0@
  --
  -- = See Also
  --
  -- <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_GOOGLE_display_timing VK_GOOGLE_display_timing>,
  -- 'PresentTimeGOOGLE', 'Vulkan.Core10.Enums.StructureType.StructureType'
  data PresentTimesInfoGOOGLE = PresentTimesInfoGOOGLE
    { -- | @swapchainCount@ is the number of swapchains being presented to by this
      -- command.
      swapchainCount :: Word32
    , -- | @pTimes@ is @NULL@ or a pointer to an array of 'PresentTimeGOOGLE'
      -- elements with @swapchainCount@ entries. If not @NULL@, each element of
      -- @pTimes@ contains the earliest time to present the image corresponding
      -- to the entry in the
      -- 'Vulkan.Extensions.VK_KHR_swapchain.PresentInfoKHR'::@pImageIndices@
      -- array.
      times :: Vector PresentTimeGOOGLE
    }
    deriving (Typeable)
  #if defined(GENERIC_INSTANCES)
  deriving instance Generic (PresentTimesInfoGOOGLE)
  #endif
  deriving instance Show PresentTimesInfoGOOGLE
  
  instance ToCStruct PresentTimesInfoGOOGLE where
    withCStruct x f = allocaBytes 32 $ \p -> pokeCStruct p x (f p)
    pokeCStruct p PresentTimesInfoGOOGLE{..} f = evalContT $ do
      lift $ poke ((p `plusPtr` 0 :: Ptr StructureType)) (STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE)
      lift $ poke ((p `plusPtr` 8 :: Ptr (Ptr ()))) (nullPtr)
      let pTimesLength = Data.Vector.length $ (times)
      swapchainCount'' <- lift $ if (swapchainCount) == 0
        then pure $ fromIntegral pTimesLength
        else do
          unless (fromIntegral pTimesLength == (swapchainCount) || pTimesLength == 0) $
            throwIO $ IOError Nothing InvalidArgument "" "pTimes must be empty or have 'swapchainCount' elements" Nothing Nothing
          pure (swapchainCount)
      lift $ poke ((p `plusPtr` 16 :: Ptr Word32)) (swapchainCount'')
      pTimes'' <- if Data.Vector.null (times)
        then pure nullPtr
        else do
          pPTimes <- ContT $ allocaBytes @PresentTimeGOOGLE (((Data.Vector.length (times))) * 16)
          lift $ Data.Vector.imapM_ (\i e -> poke (pPTimes `plusPtr` (16 * (i)) :: Ptr PresentTimeGOOGLE) (e)) ((times))
          pure $ pPTimes
      lift $ poke ((p `plusPtr` 24 :: Ptr (Ptr PresentTimeGOOGLE))) pTimes''
      lift $ f
    cStructSize = 32
    cStructAlignment = 8
    pokeZeroCStruct p f = do
      poke ((p `plusPtr` 0 :: Ptr StructureType)) (STRUCTURE_TYPE_PRESENT_TIMES_INFO_GOOGLE)
      poke ((p `plusPtr` 8 :: Ptr (Ptr ()))) (nullPtr)
      f
  
  instance FromCStruct PresentTimesInfoGOOGLE where
    peekCStruct p = do
      swapchainCount <- peek @Word32 ((p `plusPtr` 16 :: Ptr Word32))
      pTimes <- peek @(Ptr PresentTimeGOOGLE) ((p `plusPtr` 24 :: Ptr (Ptr PresentTimeGOOGLE)))
      let pTimesLength = if pTimes == nullPtr then 0 else (fromIntegral swapchainCount)
      pTimes' <- generateM pTimesLength (\i -> peekCStruct @PresentTimeGOOGLE ((pTimes `advancePtrBytes` (16 * (i)) :: Ptr PresentTimeGOOGLE)))
      pure $ PresentTimesInfoGOOGLE
               swapchainCount pTimes'
  
  instance Zero PresentTimesInfoGOOGLE where
    zero = PresentTimesInfoGOOGLE
             zero
             mempty
  
  
  -- | VkPresentTimeGOOGLE - The earliest time image should be presented
  --
  -- = Description
  --
  -- > but does not need a specific pname:desiredPresentTime.
  --
  -- = See Also
  --
  -- <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#VK_GOOGLE_display_timing VK_GOOGLE_display_timing>,
  -- 'PresentTimesInfoGOOGLE'
  data PresentTimeGOOGLE = PresentTimeGOOGLE
    { -- | @presentID@ is an application-provided identification value, that /can/
      -- be used with the results of 'getPastPresentationTimingGOOGLE', in order
      -- to uniquely identify this present. In order to be useful to the
      -- application, it /should/ be unique within some period of time that is
      -- meaningful to the application.
      presentID :: Word32
    , -- | @desiredPresentTime@ specifies that the image given /should/ not be
      -- displayed to the user any earlier than this time. @desiredPresentTime@
      -- is a time in nanoseconds, relative to a monotonically-increasing clock
      -- (e.g. @CLOCK_MONOTONIC@ (see clock_gettime(2)) on Android and Linux). A
      -- value of zero specifies that the presentation engine /may/ display the
      -- image at any time. This is useful when the application desires to
      -- provide @presentID@,
      desiredPresentTime :: Word64
    }
    deriving (Typeable, Eq)
  #if defined(GENERIC_INSTANCES)
  deriving instance Generic (PresentTimeGOOGLE)
  #endif
  deriving instance Show PresentTimeGOOGLE
  
  instance ToCStruct PresentTimeGOOGLE where
    withCStruct x f = allocaBytes 16 $ \p -> pokeCStruct p x (f p)
    pokeCStruct p PresentTimeGOOGLE{..} f = do
      poke ((p `plusPtr` 0 :: Ptr Word32)) (presentID)
      poke ((p `plusPtr` 8 :: Ptr Word64)) (desiredPresentTime)
      f
    cStructSize = 16
    cStructAlignment = 8
    pokeZeroCStruct p f = do
      poke ((p `plusPtr` 0 :: Ptr Word32)) (zero)
      poke ((p `plusPtr` 8 :: Ptr Word64)) (zero)
      f
  
  instance FromCStruct PresentTimeGOOGLE where
    peekCStruct p = do
      presentID <- peek @Word32 ((p `plusPtr` 0 :: Ptr Word32))
      desiredPresentTime <- peek @Word64 ((p `plusPtr` 8 :: Ptr Word64))
      pure $ PresentTimeGOOGLE
               presentID desiredPresentTime
  
  instance Storable PresentTimeGOOGLE where
    sizeOf ~_ = 16
    alignment ~_ = 8
    peek = peekCStruct
    poke ptr poked = pokeCStruct ptr poked (pure ())
  
  instance Zero PresentTimeGOOGLE where
    zero = PresentTimeGOOGLE
             zero
             zero
  
  
  type GOOGLE_DISPLAY_TIMING_SPEC_VERSION = 1
  
  -- No documentation found for TopLevel "VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION"
  pattern GOOGLE_DISPLAY_TIMING_SPEC_VERSION :: forall a . Integral a => a
  pattern GOOGLE_DISPLAY_TIMING_SPEC_VERSION = 1
  
  
  type GOOGLE_DISPLAY_TIMING_EXTENSION_NAME = "VK_GOOGLE_display_timing"
  
  -- No documentation found for TopLevel "VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME"
  pattern GOOGLE_DISPLAY_TIMING_EXTENSION_NAME :: forall a . (Eq a, IsString a) => a
  pattern GOOGLE_DISPLAY_TIMING_EXTENSION_NAME = "VK_GOOGLE_display_timing"
  
  