packages feed

vulkan-utils-spirv-0.1.0.0: src/Vulkan/Utils/SpirV/DeviceAddress.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}

{-| A 64-bit buffer device address — a GPU pointer to a @buffer_reference@ /
@PhysicalStorageBuffer@ block.

A @buffer_reference@ member of a shader block is stored as an 8-byte address, not
the pointee inline, so reflection-driven codegen maps it to a 'DeviceAddress'
field. The phantom @a@ records the pointee's generated record type (e.g.
@DeviceAddress Node@), purely for documentation and type-safety at the call site;
the runtime representation is just the 'Word64' address.

The 'Graphics.Gl.Block.Block' instance lays it out as a single 8-byte scalar
(alignment 8) under both std140 and std430 — matching @VkDeviceAddress@ — so a
generated record carrying one gets the right offsets via @deriving Storable via
(Std430 …)@.
-}
module Vulkan.Utils.SpirV.DeviceAddress
  ( DeviceAddress (..)
  ) where

import Data.Word (Word64)
import Foreign.Ptr.Diff (peekDiffOff, pokeDiffOff)
import Foreign.Storable (Storable)
import Graphics.Gl.Block (Block (..))

-- | A device address pointing at a @buffer_reference@ block of type @a@.
newtype DeviceAddress a = DeviceAddress Word64
  deriving stock (Eq, Ord, Show)
  deriving newtype (Storable)

{- | One 8-byte scalar (alignment 8) under both layouts; mirrors the @Double@
scalar instance gl-block ships, since @a@ is phantom.
-}
instance Block (DeviceAddress a) where
  type PackedSize (DeviceAddress a) = 8
  alignment140 _ = 8
  sizeOf140 = sizeOfPacked
  alignment430 = alignment140
  sizeOf430 = sizeOf140
  isStruct _ = False
  read140 = peekDiffOff
  write140 = pokeDiffOff
  read430 = read140
  write430 = write140
  readPacked = read140
  writePacked = write140