use crate::{
macros::{vulkan_bitflags, vulkan_enum},
pipeline::StateMode,
};
#[derive(Clone, Debug)]
pub struct ColorBlendState {
pub logic_op: Option<StateMode<LogicOp>>,
pub attachments: Vec<ColorBlendAttachmentState>,
pub blend_constants: StateMode<[f32; 4]>,
}
impl ColorBlendState {
#[inline]
pub fn new(num: u32) -> Self {
Self {
logic_op: None,
attachments: (0..num)
.map(|_| ColorBlendAttachmentState {
blend: None,
color_write_mask: ColorComponents::all(),
color_write_enable: StateMode::Fixed(true),
})
.collect(),
blend_constants: StateMode::Fixed([0.0, 0.0, 0.0, 0.0]),
}
}
#[inline]
pub fn logic_op(mut self, logic_op: LogicOp) -> Self {
self.logic_op = Some(StateMode::Fixed(logic_op));
self
}
#[inline]
pub fn logic_op_dynamic(mut self) -> Self {
self.logic_op = Some(StateMode::Dynamic);
self
}
#[inline]
pub fn blend(mut self, blend: AttachmentBlend) -> Self {
self.attachments
.iter_mut()
.for_each(|attachment_state| attachment_state.blend = Some(blend));
self
}
#[inline]
pub fn blend_alpha(mut self) -> Self {
self.attachments
.iter_mut()
.for_each(|attachment_state| attachment_state.blend = Some(AttachmentBlend::alpha()));
self
}
#[inline]
pub fn blend_additive(mut self) -> Self {
self.attachments.iter_mut().for_each(|attachment_state| {
attachment_state.blend = Some(AttachmentBlend::additive())
});
self
}
#[inline]
pub fn color_write_mask(mut self, color_write_mask: ColorComponents) -> Self {
self.attachments
.iter_mut()
.for_each(|attachment_state| attachment_state.color_write_mask = color_write_mask);
self
}
#[inline]
pub fn blend_constants(mut self, constants: [f32; 4]) -> Self {
self.blend_constants = StateMode::Fixed(constants);
self
}
#[inline]
pub fn blend_constants_dynamic(mut self) -> Self {
self.blend_constants = StateMode::Dynamic;
self
}
}
impl Default for ColorBlendState {
#[inline]
fn default() -> Self {
Self::new(1)
}
}
vulkan_enum! {
#[non_exhaustive]
LogicOp = LogicOp(i32);
Clear = CLEAR,
And = AND,
AndReverse = AND_REVERSE,
Copy = COPY,
AndInverted = AND_INVERTED,
Noop = NO_OP,
Xor = XOR,
Or = OR,
Nor = NOR,
Equivalent = EQUIVALENT,
Invert = INVERT,
OrReverse = OR_REVERSE,
CopyInverted = COPY_INVERTED,
OrInverted = OR_INVERTED,
Nand = NAND,
Set = SET,
}
impl Default for LogicOp {
#[inline]
fn default() -> LogicOp {
LogicOp::Noop
}
}
#[derive(Clone, Debug)]
pub struct ColorBlendAttachmentState {
pub blend: Option<AttachmentBlend>,
pub color_write_mask: ColorComponents,
pub color_write_enable: StateMode<bool>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AttachmentBlend {
pub color_op: BlendOp,
pub color_source: BlendFactor,
pub color_destination: BlendFactor,
pub alpha_op: BlendOp,
pub alpha_source: BlendFactor,
pub alpha_destination: BlendFactor,
}
impl AttachmentBlend {
#[inline]
pub fn ignore_source() -> Self {
Self {
color_op: BlendOp::Add,
color_source: BlendFactor::Zero,
color_destination: BlendFactor::DstColor,
alpha_op: BlendOp::Add,
alpha_source: BlendFactor::Zero,
alpha_destination: BlendFactor::DstColor,
}
}
#[inline]
pub fn alpha() -> Self {
Self {
color_op: BlendOp::Add,
color_source: BlendFactor::SrcAlpha,
color_destination: BlendFactor::OneMinusSrcAlpha,
alpha_op: BlendOp::Add,
alpha_source: BlendFactor::SrcAlpha,
alpha_destination: BlendFactor::OneMinusSrcAlpha,
}
}
#[inline]
pub fn additive() -> Self {
Self {
color_op: BlendOp::Add,
color_source: BlendFactor::One,
color_destination: BlendFactor::One,
alpha_op: BlendOp::Max,
alpha_source: BlendFactor::One,
alpha_destination: BlendFactor::One,
}
}
}
impl From<AttachmentBlend> for ash::vk::PipelineColorBlendAttachmentState {
#[inline]
fn from(val: AttachmentBlend) -> Self {
ash::vk::PipelineColorBlendAttachmentState {
blend_enable: ash::vk::TRUE,
src_color_blend_factor: val.color_source.into(),
dst_color_blend_factor: val.color_destination.into(),
color_blend_op: val.color_op.into(),
src_alpha_blend_factor: val.alpha_source.into(),
dst_alpha_blend_factor: val.alpha_destination.into(),
alpha_blend_op: val.alpha_op.into(),
color_write_mask: ash::vk::ColorComponentFlags::empty(), }
}
}
vulkan_enum! {
#[non_exhaustive]
BlendFactor = BlendFactor(i32);
Zero = ZERO,
One = ONE,
SrcColor = SRC_COLOR,
OneMinusSrcColor = ONE_MINUS_SRC_COLOR,
DstColor = DST_COLOR,
OneMinusDstColor = ONE_MINUS_DST_COLOR,
SrcAlpha = SRC_ALPHA,
OneMinusSrcAlpha = ONE_MINUS_SRC_ALPHA,
DstAlpha = DST_ALPHA,
OneMinusDstAlpha = ONE_MINUS_DST_ALPHA,
ConstantColor = CONSTANT_COLOR,
OneMinusConstantColor = ONE_MINUS_CONSTANT_COLOR,
ConstantAlpha = CONSTANT_ALPHA,
OneMinusConstantAlpha = ONE_MINUS_CONSTANT_ALPHA,
SrcAlphaSaturate = SRC_ALPHA_SATURATE,
Src1Color = SRC1_COLOR,
OneMinusSrc1Color = ONE_MINUS_SRC1_COLOR,
Src1Alpha = SRC1_ALPHA,
OneMinusSrc1Alpha = ONE_MINUS_SRC1_ALPHA,
}
vulkan_enum! {
#[non_exhaustive]
BlendOp = BlendOp(i32);
Add = ADD,
Subtract = SUBTRACT,
ReverseSubtract = REVERSE_SUBTRACT,
Min = MIN,
Max = MAX,
}
vulkan_bitflags! {
ColorComponents = ColorComponentFlags(u32);
r = R,
g = G,
b = B,
a = A,
}