wgpu-hs-0.1.0.0: src-internal/WGPU/Internal/Pipeline.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
-- |
-- Module : WGPU.Internal.Pipeline
-- Description : Pipelines.
module WGPU.Internal.Pipeline
( -- * Types
PipelineLayout (..),
PipelineLayoutDescriptor (..),
VertexFormat (..),
VertexAttribute (..),
InputStepMode (..),
VertexBufferLayout (..),
VertexState (..),
PrimitiveTopology (..),
IndexFormat (..),
FrontFace (..),
CullMode (..),
PrimitiveState (..),
StencilOperation (..),
StencilFaceState (..),
StencilState (..),
DepthBiasState (..),
DepthStencilState (..),
MultisampleState (..),
BlendFactor (..),
BlendOperation (..),
BlendComponent (..),
BlendState (..),
ColorWriteMask (..),
ColorTargetState (..),
FragmentState (..),
RenderPipelineDescriptor (..),
-- * Functions
createPipelineLayout,
createRenderPipeline,
colorWriteMaskAll,
)
where
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Cont (evalContT)
import Data.Bits ((.|.))
import Data.Default (Default, def)
import Data.Int (Int32)
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Vector as Vector
import Data.Word (Word32, Word64, Word8)
import Foreign (nullPtr)
import Foreign.C (CFloat (CFloat))
import WGPU.Internal.Binding (BindGroupLayout)
import WGPU.Internal.Device (Device, deviceInst, wgpuDevice)
import WGPU.Internal.Instance (Instance, wgpuHsInstance)
import WGPU.Internal.Memory (ToRaw, raw, rawArrayPtr, rawPtr, showWithPtr)
import WGPU.Internal.Multipurpose (CompareFunction)
import WGPU.Internal.RenderPass (RenderPipeline (RenderPipeline))
import WGPU.Internal.SMaybe (SMaybe (SJust, SNothing))
import WGPU.Internal.Shader (ShaderEntryPoint, ShaderModule)
import WGPU.Internal.Texture (TextureFormat)
import WGPU.Raw.Generated.Enum.WGPUBlendFactor (WGPUBlendFactor)
import qualified WGPU.Raw.Generated.Enum.WGPUBlendFactor as WGPUBlendFactor
import WGPU.Raw.Generated.Enum.WGPUBlendOperation (WGPUBlendOperation)
import qualified WGPU.Raw.Generated.Enum.WGPUBlendOperation as WGPUBlendOperation
import WGPU.Raw.Generated.Enum.WGPUColorWriteMask (WGPUColorWriteMask (WGPUColorWriteMask))
import qualified WGPU.Raw.Generated.Enum.WGPUColorWriteMask as WGPUColorWriteMask
import WGPU.Raw.Generated.Enum.WGPUCullMode (WGPUCullMode)
import qualified WGPU.Raw.Generated.Enum.WGPUCullMode as WGPUCullMode
import WGPU.Raw.Generated.Enum.WGPUFrontFace (WGPUFrontFace)
import qualified WGPU.Raw.Generated.Enum.WGPUFrontFace as WGPUFrontFace
import WGPU.Raw.Generated.Enum.WGPUIndexFormat (WGPUIndexFormat)
import qualified WGPU.Raw.Generated.Enum.WGPUIndexFormat as WGPUIndexFormat
import WGPU.Raw.Generated.Enum.WGPUInputStepMode (WGPUInputStepMode)
import qualified WGPU.Raw.Generated.Enum.WGPUInputStepMode as WGPUInputStepMode
import WGPU.Raw.Generated.Enum.WGPUPrimitiveTopology (WGPUPrimitiveTopology)
import qualified WGPU.Raw.Generated.Enum.WGPUPrimitiveTopology as WGPUPrimitiveTopology
import WGPU.Raw.Generated.Enum.WGPUStencilOperation (WGPUStencilOperation)
import qualified WGPU.Raw.Generated.Enum.WGPUStencilOperation as WGPUStencilOperation
import WGPU.Raw.Generated.Enum.WGPUVertexFormat (WGPUVertexFormat)
import qualified WGPU.Raw.Generated.Enum.WGPUVertexFormat as WGPUVertexFormat
import qualified WGPU.Raw.Generated.Fun as RawFun
import WGPU.Raw.Generated.Struct.WGPUBlendComponent (WGPUBlendComponent)
import qualified WGPU.Raw.Generated.Struct.WGPUBlendComponent as WGPUBlendComponent
import WGPU.Raw.Generated.Struct.WGPUBlendState (WGPUBlendState)
import qualified WGPU.Raw.Generated.Struct.WGPUBlendState as WGPUBlendState
import WGPU.Raw.Generated.Struct.WGPUColorTargetState (WGPUColorTargetState)
import qualified WGPU.Raw.Generated.Struct.WGPUColorTargetState as WGPUColorTargetState
import WGPU.Raw.Generated.Struct.WGPUDepthStencilState (WGPUDepthStencilState)
import qualified WGPU.Raw.Generated.Struct.WGPUDepthStencilState as WGPUDepthStencilState
import WGPU.Raw.Generated.Struct.WGPUFragmentState (WGPUFragmentState)
import qualified WGPU.Raw.Generated.Struct.WGPUFragmentState as WGPUFragmentState
import WGPU.Raw.Generated.Struct.WGPUMultisampleState (WGPUMultisampleState)
import qualified WGPU.Raw.Generated.Struct.WGPUMultisampleState as WGPUMultisampleState
import WGPU.Raw.Generated.Struct.WGPUPipelineLayoutDescriptor (WGPUPipelineLayoutDescriptor)
import qualified WGPU.Raw.Generated.Struct.WGPUPipelineLayoutDescriptor as WGPUPipelineLayoutDescriptor
import WGPU.Raw.Generated.Struct.WGPUPrimitiveState (WGPUPrimitiveState)
import qualified WGPU.Raw.Generated.Struct.WGPUPrimitiveState as WGPUPrimitiveState
import WGPU.Raw.Generated.Struct.WGPURenderPipelineDescriptor (WGPURenderPipelineDescriptor)
import qualified WGPU.Raw.Generated.Struct.WGPURenderPipelineDescriptor as WGPURenderPipelineDescriptor
import WGPU.Raw.Generated.Struct.WGPUStencilFaceState (WGPUStencilFaceState)
import qualified WGPU.Raw.Generated.Struct.WGPUStencilFaceState as WGPUStencilFaceState
import WGPU.Raw.Generated.Struct.WGPUVertexAttribute (WGPUVertexAttribute)
import qualified WGPU.Raw.Generated.Struct.WGPUVertexAttribute as WGPUVertexAttribute
import WGPU.Raw.Generated.Struct.WGPUVertexBufferLayout (WGPUVertexBufferLayout)
import qualified WGPU.Raw.Generated.Struct.WGPUVertexBufferLayout as WGPUVertexBufferLayout
import WGPU.Raw.Generated.Struct.WGPUVertexState (WGPUVertexState)
import qualified WGPU.Raw.Generated.Struct.WGPUVertexState as WGPUVertexState
import WGPU.Raw.Types (WGPUPipelineLayout (WGPUPipelineLayout))
import Prelude hiding (compare)
-------------------------------------------------------------------------------
newtype PipelineLayout = PipelineLayout {wgpuPipelineLayout :: WGPUPipelineLayout}
instance Show PipelineLayout where
show p =
let PipelineLayout (WGPUPipelineLayout ptr) = p
in showWithPtr "PipelineLayout" ptr
instance Eq PipelineLayout where
(==) p1 p2 =
let PipelineLayout (WGPUPipelineLayout p1_ptr) = p1
PipelineLayout (WGPUPipelineLayout p2_ptr) = p2
in p1_ptr == p2_ptr
instance ToRaw PipelineLayout WGPUPipelineLayout where
raw = pure . wgpuPipelineLayout
-------------------------------------------------------------------------------
-- | Describes a pipeline layout.
data PipelineLayoutDescriptor = PipelineLayoutDescriptor
{ -- | Debug label of the pipeline layout.
pipelineLabel :: !Text,
-- | Bind groups that this pipeline uses.
bindGroupLayouts :: !(Vector BindGroupLayout)
}
deriving (Eq, Show)
instance ToRaw PipelineLayoutDescriptor WGPUPipelineLayoutDescriptor where
raw PipelineLayoutDescriptor {..} = do
label_ptr <- rawPtr pipelineLabel
bindGroupLayouts_ptr <- rawArrayPtr bindGroupLayouts
pure
WGPUPipelineLayoutDescriptor.WGPUPipelineLayoutDescriptor
{ nextInChain = nullPtr,
label = label_ptr,
bindGroupLayoutCount = fromIntegral . Vector.length $ bindGroupLayouts,
bindGroupLayouts = bindGroupLayouts_ptr
}
-------------------------------------------------------------------------------
-- | Create a pipeline layout.
createPipelineLayout ::
-- | The device for which the pipeline layout will be created.
Device ->
-- | Descriptor of the pipeline.
PipelineLayoutDescriptor ->
IO PipelineLayout
createPipelineLayout device pdl = evalContT $ do
let inst = deviceInst device
pipelineLayoutDescriptor_ptr <- rawPtr pdl
rawPipelineLayout <-
liftIO $
RawFun.wgpuDeviceCreatePipelineLayout
(wgpuHsInstance inst)
(wgpuDevice device)
pipelineLayoutDescriptor_ptr
pure (PipelineLayout rawPipelineLayout)
-------------------------------------------------------------------------------
-- | Vertex format for a vertex attribute.
data VertexFormat
= VertexFormatUint8x2
| VertexFormatUint8x4
| VertexFormatSint8x2
| VertexFormatSint8x4
| VertexFormatUnorm8x2
| VertexFormatUnorm8x4
| VertexFormatSnorm8x2
| VertexFormatSnorm8x4
| VertexFormatUint16x2
| VertexFormatUint16x4
| VertexFormatSint16x2
| VertexFormatSint16x4
| VertexFormatUnorm16x2
| VertexFormatUnorm16x4
| VertexFormatSnorm16x2
| VertexFormatSnorm16x4
| VertexFormatFloat16x2
| VertexFormatFloat16x4
| VertexFormatFloat32
| VertexFormatFloat32x2
| VertexFormatFloat32x3
| VertexFormatFloat32x4
| VertexFormatUint32
| VertexFormatUint32x2
| VertexFormatUint32x3
| VertexFormatUint32x4
| VertexFormatSint32
| VertexFormatSint32x2
| VertexFormatSint32x3
| VertexFormatSint32x4
deriving (Eq, Show)
-- | Convert a 'VertexFormat' to its raw representation.
instance ToRaw VertexFormat WGPUVertexFormat where
raw vf =
pure $
case vf of
VertexFormatUint8x2 -> WGPUVertexFormat.Uint8x2
VertexFormatUint8x4 -> WGPUVertexFormat.Uint8x4
VertexFormatSint8x2 -> WGPUVertexFormat.Sint8x2
VertexFormatSint8x4 -> WGPUVertexFormat.Sint8x4
VertexFormatUnorm8x2 -> WGPUVertexFormat.Unorm8x2
VertexFormatUnorm8x4 -> WGPUVertexFormat.Unorm8x4
VertexFormatSnorm8x2 -> WGPUVertexFormat.Snorm8x2
VertexFormatSnorm8x4 -> WGPUVertexFormat.Snorm8x4
VertexFormatUint16x2 -> WGPUVertexFormat.Uint16x2
VertexFormatUint16x4 -> WGPUVertexFormat.Uint16x4
VertexFormatSint16x2 -> WGPUVertexFormat.Sint16x2
VertexFormatSint16x4 -> WGPUVertexFormat.Sint16x4
VertexFormatUnorm16x2 -> WGPUVertexFormat.Unorm16x2
VertexFormatUnorm16x4 -> WGPUVertexFormat.Unorm16x4
VertexFormatSnorm16x2 -> WGPUVertexFormat.Snorm16x2
VertexFormatSnorm16x4 -> WGPUVertexFormat.Snorm16x4
VertexFormatFloat16x2 -> WGPUVertexFormat.Float16x2
VertexFormatFloat16x4 -> WGPUVertexFormat.Float16x4
VertexFormatFloat32 -> WGPUVertexFormat.Float32
VertexFormatFloat32x2 -> WGPUVertexFormat.Float32x2
VertexFormatFloat32x3 -> WGPUVertexFormat.Float32x3
VertexFormatFloat32x4 -> WGPUVertexFormat.Float32x4
VertexFormatUint32 -> WGPUVertexFormat.Uint32
VertexFormatUint32x2 -> WGPUVertexFormat.Uint32x2
VertexFormatUint32x3 -> WGPUVertexFormat.Uint32x3
VertexFormatUint32x4 -> WGPUVertexFormat.Uint32x4
VertexFormatSint32 -> WGPUVertexFormat.Sint32
VertexFormatSint32x2 -> WGPUVertexFormat.Sint32x2
VertexFormatSint32x3 -> WGPUVertexFormat.Sint32x3
VertexFormatSint32x4 -> WGPUVertexFormat.Sint32x4
-------------------------------------------------------------------------------
-- | Vertex inputs (attributes) to shaders.
data VertexAttribute = VertexAttribute
{ -- | Format of the input.
vertexFormat :: VertexFormat,
-- | Byte offset of the start of the input.
offset :: Word64,
-- | Location for this input. Must match the location in the shader.
shaderLocation :: Word32
}
deriving (Eq, Show)
instance ToRaw VertexAttribute WGPUVertexAttribute where
raw VertexAttribute {..} = do
n_format <- raw vertexFormat
pure
WGPUVertexAttribute.WGPUVertexAttribute
{ format = n_format,
offset = offset,
shaderLocation = shaderLocation
}
-------------------------------------------------------------------------------
-- | Determines when vertex data is advanced.
data InputStepMode
= -- | Input data is advanced every vertex.
InputStepModeVertex
| -- | Input data is advanced every instance.
InputStepModeInstance
deriving (Eq, Show)
-- | Convert an 'InputStepMode' to its raw value.
instance ToRaw InputStepMode WGPUInputStepMode where
raw ism =
pure $
case ism of
InputStepModeVertex -> WGPUInputStepMode.Vertex
InputStepModeInstance -> WGPUInputStepMode.Instance
-------------------------------------------------------------------------------
-- | Describes how a vertex buffer is interpreted.
data VertexBufferLayout = VertexBufferLayout
{ -- | The stride, in bytes, between elements of the buffer.
arrayStride :: !Word64,
-- | How often the vertex buffer is stepped forward (per vertex or
-- per instance).
stepMode :: !InputStepMode,
-- | List of attributes that comprise a single vertex.
attributes :: !(Vector VertexAttribute)
}
deriving (Eq, Show)
instance ToRaw VertexBufferLayout WGPUVertexBufferLayout where
raw VertexBufferLayout {..} = do
n_stepMode <- raw stepMode
attributes_ptr <- rawArrayPtr attributes
pure
WGPUVertexBufferLayout.WGPUVertexBufferLayout
{ arrayStride = arrayStride,
stepMode = n_stepMode,
attributeCount = fromIntegral . length $ attributes,
attributes = attributes_ptr
}
-------------------------------------------------------------------------------
-- | Describes the vertex process in a render pipeline.
data VertexState = VertexState
{ -- | The compiled shader module for this stage.
vertexShaderModule :: !ShaderModule,
-- | The name of the entry point in the compiled shader. There must be a
-- function that returns @void@ with this name in the shader.
vertexEntryPoint :: !ShaderEntryPoint,
-- | The format of any vertex buffers used with this pipeline.
buffers :: !(Vector VertexBufferLayout)
}
deriving (Eq, Show)
instance ToRaw VertexState WGPUVertexState where
raw VertexState {..} = do
n_shaderModule <- raw vertexShaderModule
entryPoint_ptr <- rawPtr vertexEntryPoint
buffers_ptr <- rawArrayPtr buffers
pure
WGPUVertexState.WGPUVertexState
{ nextInChain = nullPtr,
shaderModule = n_shaderModule,
entryPoint = entryPoint_ptr,
bufferCount = fromIntegral . length $ buffers,
buffers = buffers_ptr
}
-------------------------------------------------------------------------------
-- | Primitive type out of which an input mesh is composed.
data PrimitiveTopology
= PrimitiveTopologyPointList
| PrimitiveTopologyLineList
| PrimitiveTopologyLineStrip
| PrimitiveTopologyTriangleList
| PrimitiveTopologyTriangleStrip
deriving (Eq, Show)
instance Default PrimitiveTopology where def = PrimitiveTopologyTriangleList
-- | Convert a 'PrimitiveTopology' to its raw value.
instance ToRaw PrimitiveTopology WGPUPrimitiveTopology where
raw pt =
pure $
case pt of
PrimitiveTopologyPointList -> WGPUPrimitiveTopology.PointList
PrimitiveTopologyLineList -> WGPUPrimitiveTopology.LineList
PrimitiveTopologyLineStrip -> WGPUPrimitiveTopology.LineStrip
PrimitiveTopologyTriangleList -> WGPUPrimitiveTopology.TriangleList
PrimitiveTopologyTriangleStrip -> WGPUPrimitiveTopology.TriangleStrip
-------------------------------------------------------------------------------
-- | Format of indices used within a pipeline.
data IndexFormat
= -- | Indices are 16-bit unsigned integers ('Word16')
IndexFormatUint16
| -- | Indices are 32-bit unsigned integers ('Word32')
IndexFormatUint32
deriving (Eq, Show)
-- | Convert an 'IndexFormat' to its raw value.
instance ToRaw IndexFormat WGPUIndexFormat where
raw idxFmt =
pure $
case idxFmt of
IndexFormatUint16 -> WGPUIndexFormat.Uint16
IndexFormatUint32 -> WGPUIndexFormat.Uint32
-------------------------------------------------------------------------------
-- | Winding order which classifies the "front" face.
data FrontFace
= -- | Triangles with counter-clockwise vertices are the front face.
FrontFaceCCW
| -- | Triangles with clockwise vertices are the front face.
FrontFaceCW
deriving (Eq, Show)
instance Default FrontFace where def = FrontFaceCCW
-- | Convert a 'FrontFace' to its raw value.
instance ToRaw FrontFace WGPUFrontFace where
raw ff =
pure $
case ff of
FrontFaceCCW -> WGPUFrontFace.CCW
FrontFaceCW -> WGPUFrontFace.CW
-------------------------------------------------------------------------------
-- | Whether to cull the face of a vertex.
data CullMode
= -- | Cull the front face.
CullModeFront
| -- | Cull the back face.
CullModeBack
| -- | Do not cull either face.
CullModeNone
deriving (Eq, Show)
instance Default CullMode where def = CullModeNone
-- | Convert a 'CullMode' to its raw value.
instance ToRaw CullMode WGPUCullMode where
raw cm =
pure $
case cm of
CullModeFront -> WGPUCullMode.Front
CullModeBack -> WGPUCullMode.Back
CullModeNone -> WGPUCullMode.None
-------------------------------------------------------------------------------
-- | Describes the state of primitive assembly and rasterization in a render
-- pipeline.
--
-- Differences between this and the Rust API:
-- - no `clamp_depth` member
-- - no `polygon_mode` member
-- - no `conservative` member
data PrimitiveState = PrimitiveState
{ -- | The primitive topology used to interpret vertices.
topology :: !PrimitiveTopology,
-- | When drawing strip topologies with indices, this is the required
-- format for the index buffer. This has no effect for non-indexed or
-- non-strip draws.
stripIndexFormat :: !(SMaybe IndexFormat),
-- | The face to consider the front for the purpose of culling and
-- stencil operations.
frontFace :: !FrontFace,
-- | The face culling mode.
cullMode :: !CullMode
}
deriving (Eq, Show)
instance Default PrimitiveState where
def =
PrimitiveState
{ topology = def,
stripIndexFormat = SNothing,
frontFace = def,
cullMode = def
}
instance ToRaw PrimitiveState WGPUPrimitiveState where
raw PrimitiveState {..} = do
n_topology <- raw topology
n_stripIndexFormat <-
case stripIndexFormat of
SNothing -> pure WGPUIndexFormat.Undefined
SJust sif -> raw sif
n_frontFace <- raw frontFace
n_cullMode <- raw cullMode
pure
WGPUPrimitiveState.WGPUPrimitiveState
{ nextInChain = nullPtr,
topology = n_topology,
stripIndexFormat = n_stripIndexFormat,
frontFace = n_frontFace,
cullMode = n_cullMode
}
-------------------------------------------------------------------------------
-- | Operation to perform on a stencil value.
data StencilOperation
= StencilOperationKeep
| StencilOperationZero
| StencilOperationReplace
| StencilOperationInvert
| StencilOperationIncrementClamp
| StencilOperationDecrementClamp
| StencilOperationIncrementWrap
| StencilOperationDecrementWrap
deriving (Eq, Show)
-- | Convert a 'StencilOperation' to its raw value.
instance ToRaw StencilOperation WGPUStencilOperation where
raw so =
pure $
case so of
StencilOperationKeep -> WGPUStencilOperation.Keep
StencilOperationZero -> WGPUStencilOperation.Zero
StencilOperationReplace -> WGPUStencilOperation.Replace
StencilOperationInvert -> WGPUStencilOperation.Invert
StencilOperationIncrementClamp -> WGPUStencilOperation.IncrementClamp
StencilOperationDecrementClamp -> WGPUStencilOperation.DecrementClamp
StencilOperationIncrementWrap -> WGPUStencilOperation.IncrementWrap
StencilOperationDecrementWrap -> WGPUStencilOperation.DecrementWrap
-------------------------------------------------------------------------------
-- | Describes stencil state in a render pipeline.
data StencilFaceState = StencilFaceState
{ compare :: !CompareFunction,
failOp :: !StencilOperation,
depthFailOp :: !StencilOperation,
passOp :: !StencilOperation
}
deriving (Eq, Show)
instance ToRaw StencilFaceState WGPUStencilFaceState where
raw StencilFaceState {..} = do
n_compare <- raw compare
n_failOp <- raw failOp
n_depthFailOp <- raw depthFailOp
n_passOp <- raw passOp
pure
WGPUStencilFaceState.WGPUStencilFaceState
{ compare = n_compare,
failOp = n_failOp,
depthFailOp = n_depthFailOp,
passOp = n_passOp
}
-------------------------------------------------------------------------------
-- | State of the stencil operation (fixed pipeline stage).
data StencilState = StencilState
{ -- | Front face mode.
front :: !StencilFaceState,
-- | Back face mode.
back :: !StencilFaceState,
-- | Stencil values are AND-ed with this mask when reading and writing from
-- the stencil buffer.
readMask :: !Word8,
-- | Stencil values are AND-ed with this mask when writing to the stencil
-- buffer.
writeMask :: !Word8
}
deriving (Eq, Show)
-------------------------------------------------------------------------------
-- | Describes the biasing setting for the depth target.
data DepthBiasState = DepthBiasState
{ -- Constant depth biasing factor, in basic units of the depth format.
constant :: !Int32,
-- | Slope depth biasing factor.
slopeScale :: !Float,
-- | Depth bias clamp value (absolute).
clamp :: !Float
}
deriving (Eq, Show)
-------------------------------------------------------------------------------
-- | Describes the depth / stencil state of a render pipeline.
data DepthStencilState = DepthStencilState
{ -- | Format of the depth/stencil buffer. This must be a special depth
-- format, and must match the format of the depth/stencil attachment in
-- the command encoder.
depthStencilTextureFormat :: !TextureFormat,
-- | If disabled, depth will not be written to.
depthWriteEnabled :: !Bool,
-- | Comparison function used to compare depth values in the depth test.
depthCompare :: !CompareFunction,
-- | Stencil state.
stencil :: !StencilState,
-- | Depth bias state.
bias :: !DepthBiasState
}
deriving (Eq, Show)
instance ToRaw DepthStencilState WGPUDepthStencilState where
raw DepthStencilState {..} = do
n_format <- raw depthStencilTextureFormat
n_depthWriteEnabled <- raw depthWriteEnabled
n_depthCompare <- raw depthCompare
n_stencilFront <- raw . front $ stencil
n_stencilBack <- raw . back $ stencil
pure
WGPUDepthStencilState.WGPUDepthStencilState
{ nextInChain = nullPtr,
format = n_format,
depthWriteEnabled = n_depthWriteEnabled,
depthCompare = n_depthCompare,
stencilFront = n_stencilFront,
stencilBack = n_stencilBack,
stencilReadMask = fromIntegral . readMask $ stencil,
stencilWriteMask = fromIntegral $ writeMask (stencil :: StencilState),
depthBias = constant bias,
depthBiasSlopeScale = CFloat (slopeScale bias),
depthBiasClamp = CFloat (clamp bias)
}
-------------------------------------------------------------------------------
-- | Describes the multi-sampling state of a render pipeline.
data MultisampleState = MultisampleState
{ -- | Number of samples calculated per pixel (for MSAA). For
-- non-multisampled textures, this should be 1.
count :: Word32,
-- | Bitmask that restricts the samples of a pixel modified by this
-- pipeline. All samples can be enabled by using
-- @0XFFFFFFFF@ (ie. zero complement).
mask :: Word32,
-- | When enabled, produces another sample mask per pixel based on the
-- alpha output value, and that is AND-ed with the sample mask and the
-- primitive coverage to restrict the set of samples affected by a
-- primitive.
alphaToCoverageEnabled :: Bool
}
deriving (Eq, Show)
instance ToRaw MultisampleState WGPUMultisampleState where
raw MultisampleState {..} = do
n_alphaToCoverageEnabled <- raw alphaToCoverageEnabled
pure
WGPUMultisampleState.WGPUMultisampleState
{ nextInChain = nullPtr,
count = count,
mask = mask,
alphaToCoverageEnabled = n_alphaToCoverageEnabled
}
-------------------------------------------------------------------------------
-- | Alpha blend factor.
data BlendFactor
= BlendFactorZero
| BlendFactorOne
| BlendFactorSrc
| BlendFactorOneMinusSrc
| BlendFactorSrcAlpha
| BlendFactorOneMinusSrcAlpha
| BlendFactorDst
| BlendFactorOneMinusDst
| BlendFactorDstAlpha
| BlendFactorOneMinusDstAlpha
| BlendFactorSrcAlphaSaturated
| BlendFactorConstant
| BlendFactorOneMinusConstant
deriving (Eq, Show)
-- | Convert a 'BlendFactor' to its raw value.
instance ToRaw BlendFactor WGPUBlendFactor where
raw bf =
pure $
case bf of
BlendFactorZero -> WGPUBlendFactor.Zero
BlendFactorOne -> WGPUBlendFactor.One
BlendFactorSrc -> WGPUBlendFactor.Src
BlendFactorOneMinusSrc -> WGPUBlendFactor.OneMinusSrc
BlendFactorSrcAlpha -> WGPUBlendFactor.SrcAlpha
BlendFactorOneMinusSrcAlpha -> WGPUBlendFactor.OneMinusSrcAlpha
BlendFactorDst -> WGPUBlendFactor.Dst
BlendFactorOneMinusDst -> WGPUBlendFactor.OneMinusDst
BlendFactorDstAlpha -> WGPUBlendFactor.DstAlpha
BlendFactorOneMinusDstAlpha -> WGPUBlendFactor.OneMinusDstAlpha
BlendFactorSrcAlphaSaturated -> WGPUBlendFactor.SrcAlphaSaturated
BlendFactorConstant -> WGPUBlendFactor.Constant
BlendFactorOneMinusConstant -> WGPUBlendFactor.OneMinusConstant
-------------------------------------------------------------------------------
-- | Alpha blending operation.
data BlendOperation
= BlendOperationAdd
| BlendOperationSubtract
| BlendOperationReverseSubtract
| BlendOperationMin
| BlendOperationMax
deriving (Eq, Show)
-- | Convert a 'BlendOperation' to its raw value.
instance ToRaw BlendOperation WGPUBlendOperation where
raw bo =
pure $
case bo of
BlendOperationAdd -> WGPUBlendOperation.Add
BlendOperationSubtract -> WGPUBlendOperation.Subtract
BlendOperationReverseSubtract -> WGPUBlendOperation.ReverseSubtract
BlendOperationMin -> WGPUBlendOperation.Min
BlendOperationMax -> WGPUBlendOperation.Max
-------------------------------------------------------------------------------
-- | Describes the blend component of a pipeline.
data BlendComponent = BlendComponent
{ -- | Multiplier for the source, which is produced by the fragment shader.
srcFactor :: !BlendFactor,
-- | Multiplier for the destination, which is stored in the target.
dstFactor :: !BlendFactor,
-- | Binary operation applied to the source and destination, multiplied by
-- their respective factors.
operation :: !BlendOperation
}
deriving (Eq, Show)
instance Default BlendComponent where
def =
BlendComponent
{ srcFactor = BlendFactorOne,
dstFactor = BlendFactorZero,
operation = BlendOperationAdd
}
instance ToRaw BlendComponent WGPUBlendComponent where
raw BlendComponent {..} = do
n_srcFactor <- raw srcFactor
n_dstFactor <- raw dstFactor
n_operation <- raw operation
pure
WGPUBlendComponent.WGPUBlendComponent
{ srcFactor = n_srcFactor,
dstFactor = n_dstFactor,
operation = n_operation
}
-------------------------------------------------------------------------------
-- | Describes the blend state of a render pipeline.
data BlendState = BlendState
{ -- | Color equation.
blendColor :: !BlendComponent,
-- | Alpha equation.
blendAlpha :: !BlendComponent
}
deriving (Eq, Show)
instance ToRaw BlendState WGPUBlendState where
raw BlendState {..} = do
n_color <- raw blendColor
n_alpha <- raw blendAlpha
pure
WGPUBlendState.WGPUBlendState
{ color = n_color,
alpha = n_alpha
}
-------------------------------------------------------------------------------
-- | Describes which color channels are written.
data ColorWriteMask = ColorWriteMask
{ maskRed :: !Bool,
maskGreen :: !Bool,
maskBlue :: !Bool,
maskAlpha :: !Bool
}
deriving (Eq, Show)
-- | A 'ColorWriteMask' that writes all colors and the alpha value.
colorWriteMaskAll :: ColorWriteMask
colorWriteMaskAll = ColorWriteMask True True True True
instance ToRaw ColorWriteMask WGPUColorWriteMask where
raw ColorWriteMask {..} =
pure $
WGPUColorWriteMask
( (if maskRed then WGPUColorWriteMask.Red else 0)
.|. (if maskGreen then WGPUColorWriteMask.Green else 0)
.|. (if maskBlue then WGPUColorWriteMask.Blue else 0)
.|. (if maskAlpha then WGPUColorWriteMask.Alpha else 0)
)
-------------------------------------------------------------------------------
-- | Describes the color state of a render pipeline.
data ColorTargetState = ColorTargetState
{ -- | The texture format of the image that this pipeline will render to.
-- Must match the format of the corresponding color attachment in the
-- command encoder.
colorTextureFormat :: !TextureFormat,
-- | The blending that is used for this pipeline.
blend :: !(SMaybe BlendState),
-- | Mask which enables or disables writes to different color/alpha
-- channels.
colorWriteMask :: !ColorWriteMask
}
deriving (Eq, Show)
instance ToRaw ColorTargetState WGPUColorTargetState where
raw ColorTargetState {..} = do
n_format <- raw colorTextureFormat
blend_ptr <-
case blend of
SNothing -> pure nullPtr
SJust x -> rawPtr x
WGPUColorWriteMask n_writeMask <- raw colorWriteMask
pure
WGPUColorTargetState.WGPUColorTargetState
{ nextInChain = nullPtr,
format = n_format,
blend = blend_ptr,
writeMask = n_writeMask
}
-------------------------------------------------------------------------------
-- | Describes the fragment processing in a render pipeline.
data FragmentState = FragmentState
{ -- | The compiled shader module for this stage.
fragmentShaderModule :: !ShaderModule,
-- | The entry point in the compiled shader. There must be a function that
-- returns @void@ with this name in the shader.
fragmentEntryPoint :: !ShaderEntryPoint,
-- | The color state of the render targets.
targets :: !(Vector ColorTargetState)
}
deriving (Eq, Show)
instance ToRaw FragmentState WGPUFragmentState where
raw FragmentState {..} = do
n_shaderModule <- raw fragmentShaderModule
entryPoint_ptr <- rawPtr fragmentEntryPoint
targets_ptr <- rawArrayPtr targets
pure
WGPUFragmentState.WGPUFragmentState
{ nextInChain = nullPtr,
shaderModule = n_shaderModule,
entryPoint = entryPoint_ptr,
targetCount = fromIntegral . length $ targets,
targets = targets_ptr
}
-------------------------------------------------------------------------------
-- | Describes a render (graphics) pipeline.
data RenderPipelineDescriptor = RenderPipelineDescriptor
{ -- | Debug label of the pipeline.
renderPipelineLabel :: !Text,
-- | The layout of bind groups for this pipeline.
layout :: !(SMaybe PipelineLayout),
-- | Vertex state.
vertex :: !VertexState,
-- | Primitive state.
primitive :: !PrimitiveState,
-- | Depth stencil state.
depthStencil :: !(SMaybe DepthStencilState),
-- | Multisample state.
multisample :: !MultisampleState,
-- | Fragment state.
fragment :: !(SMaybe FragmentState)
}
deriving (Eq, Show)
instance ToRaw RenderPipelineDescriptor WGPURenderPipelineDescriptor where
raw RenderPipelineDescriptor {..} = do
label_ptr <- rawPtr renderPipelineLabel
n_layout <-
case layout of
SNothing -> pure (WGPUPipelineLayout nullPtr)
SJust x -> raw x
n_vertex <- raw vertex
n_primitive <- raw primitive
n_depthStencil <-
case depthStencil of
SNothing -> pure nullPtr
SJust x -> rawPtr x
n_multisample <- raw multisample
n_fragment <-
case fragment of
SNothing -> pure nullPtr
SJust x -> rawPtr x
pure
WGPURenderPipelineDescriptor.WGPURenderPipelineDescriptor
{ nextInChain = nullPtr,
label = label_ptr,
layout = n_layout,
vertex = n_vertex,
primitive = n_primitive,
depthStencil = n_depthStencil,
multisample = n_multisample,
fragment = n_fragment
}
createRenderPipeline ::
Device ->
RenderPipelineDescriptor ->
IO RenderPipeline
createRenderPipeline device rpd = evalContT $ do
let inst :: Instance
inst = deviceInst device
renderPipelineDescriptor_ptr <- rawPtr rpd
renderPipelineRaw <-
liftIO $
RawFun.wgpuDeviceCreateRenderPipeline
(wgpuHsInstance inst)
(wgpuDevice device)
renderPipelineDescriptor_ptr
pure (RenderPipeline renderPipelineRaw)