keid-core-0.1.8.0: src/Render/Samplers.hs
module Render.Samplers
( Collection(..)
, allocate
, allocateFrom
, indices
, Params
, params
, createInfo
) where
import RIO
import Control.Monad.Trans.Resource (ResourceT)
import Control.Monad.Trans.Resource qualified as Resource
import GHC.Generics (Generic1)
import Vulkan.Core10 qualified as Vk
import Vulkan.NamedType ((:::))
import Vulkan.Zero (zero)
import Engine.Vulkan.Types (HasVulkan(..), MonadVulkan)
import Resource.Collection (Generically1(..))
import Resource.Collection qualified as Collection
import Vulkan.CStruct.Extends (PokeChain, Extendss)
data Collection a = Collection
{ linearMipRepeat :: a -- 0
, linearMip :: a -- 1
, linearRepeat :: a -- 2
, linear :: a -- 3
, nearestMipRepeat :: a -- 4
, nearestMip :: a -- 5
, nearestRepeat :: a -- 6
, nearest :: a -- 7
}
deriving stock (Show, Functor, Foldable, Traversable, Generic1)
deriving Applicative via Generically1 Collection
type Params = (Vk.Filter, "LOD clamp" ::: Float, Vk.SamplerAddressMode)
params :: Collection Params
params = Collection
{ linearMipRepeat = (Vk.FILTER_LINEAR, Vk.LOD_CLAMP_NONE, Vk.SAMPLER_ADDRESS_MODE_REPEAT) -- 0
, linearMip = (Vk.FILTER_LINEAR, Vk.LOD_CLAMP_NONE, Vk.SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) -- 1
, linearRepeat = (Vk.FILTER_LINEAR, 0, Vk.SAMPLER_ADDRESS_MODE_REPEAT) -- 2
, linear = (Vk.FILTER_LINEAR, 0, Vk.SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) -- 3
, nearestMipRepeat = (Vk.FILTER_NEAREST, Vk.LOD_CLAMP_NONE, Vk.SAMPLER_ADDRESS_MODE_REPEAT) -- 4
, nearestMip = (Vk.FILTER_NEAREST, Vk.LOD_CLAMP_NONE, Vk.SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) -- 5
, nearestRepeat = (Vk.FILTER_NEAREST, 0, Vk.SAMPLER_ADDRESS_MODE_REPEAT) -- 6
, nearest = (Vk.FILTER_NEAREST, 0, Vk.SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) -- 7
}
indices :: Collection Int32
indices = fmap fst $ Collection.enumerate params
allocate
:: MonadVulkan env io
=> "max anisotropy" ::: Float
-> ResourceT io (Collection Vk.Sampler)
allocate maxAnisotropy =
for params \p ->
allocateFrom maxAnisotropy p id
allocateFrom
:: ( PokeChain e
, Extendss Vk.SamplerCreateInfo e
, MonadVulkan env io
)
=> "max anisotropy" ::: Float
-> Params
-> (Vk.SamplerCreateInfo '[] -> Vk.SamplerCreateInfo e)
-> ResourceT io Vk.Sampler
allocateFrom maxAnisotropy (filt, mips, reps) f = do
device <- asks getDevice
sampler <- Vk.createSampler
device
(f $ createInfo maxAnisotropy filt mips reps)
Nothing
_key <- Resource.register $
Vk.destroySampler device sampler Nothing
pure sampler
createInfo
:: "max anisotropy" ::: Float
-> Vk.Filter
-> "max LoD" ::: Float
-> Vk.SamplerAddressMode
-> Vk.SamplerCreateInfo '[]
createInfo maxAnisotropy filt mips reps = zero
{ Vk.magFilter = filt
, Vk.minFilter = filt
, Vk.addressModeU = reps
, Vk.addressModeV = reps
, Vk.addressModeW = reps
, Vk.anisotropyEnable = maxAnisotropy > 1
, Vk.maxAnisotropy = maxAnisotropy
, Vk.borderColor = Vk.BORDER_COLOR_INT_OPAQUE_BLACK
, Vk.unnormalizedCoordinates = False
, Vk.compareEnable = False
, Vk.compareOp = Vk.COMPARE_OP_ALWAYS
, Vk.mipmapMode = Vk.SAMPLER_MIPMAP_MODE_LINEAR
, Vk.mipLodBias = 0
, Vk.minLod = 0
, Vk.maxLod = mips
}