1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
//! Generates multiple fragments per framebuffer pixel when rasterizing. This can be used for
//! anti-aliasing.
use crate::device::Device;
use crate::image::SampleCount;
use crate::pipeline::graphics::GraphicsPipelineCreationError;
use crate::pipeline::DynamicState;
use crate::render_pass::Subpass;
use fnv::FnvHashMap;
use std::ptr;
// TODO: handle some weird behaviors with non-floating-point targets
/// State of the multisampling.
#[derive(Copy, Clone, Debug)]
pub struct MultisampleState {
/*
TODO: enable
/// The number of rasterization samples to take per pixel. The GPU will pick this many different
/// locations within each pixel and assign to each of these locations a different depth value.
/// The depth and stencil test will then be run for each sample.
pub rasterization_samples: SampleCount,
*/
/// Controls the proportion (between 0.0 and 1.0) of the samples that will be run through the
/// fragment shader.
///
/// If the value is 1.0, then all sub-pixel samples will run
/// through the shader and get a different value. If the value is 0.5, about half of the samples
/// will run through the shader and the other half will get their values from the ones which
/// went through the shader.
///
/// If set to `Some`, the [`sample_rate_shading`](crate::device::Features::sample_rate_shading)
/// feature must be enabled on the device.
pub sample_shading: Option<f32>,
/*
TODO: enable
pub sample_mask: Option<[u32; 2]>, // 64 bits for needed for 64 SampleCount
*/
/// Controls whether the alpha value of the fragment will be used in an implementation-defined
/// way to determine which samples get disabled or not. For example if the alpha value is 0.5,
/// then about half of the samples will be discarded. If you render to a multisample image, this
/// means that the color will end up being mixed with whatever color was underneath, which gives
/// the same effect as alpha blending.
pub alpha_to_coverage_enable: bool,
/// Controls whether the alpha value of all the samples will be forced to 1.0 (or the
/// maximum possible value) after the effects of `alpha_to_coverage` have been applied.
///
/// If set to `true`, the [`alpha_to_one`](crate::device::Features::alpha_to_one)
/// feature must be enabled on the device.
pub alpha_to_one_enable: bool,
}
impl MultisampleState {
/// Creates a `MultisampleState` with multisampling disabled.
#[inline]
pub fn new() -> MultisampleState {
MultisampleState {
//rasterization_samples: 1,
sample_shading: None,
//sample_mask: [0xffffffff; 4],
alpha_to_coverage_enable: false,
alpha_to_one_enable: false,
}
}
pub(crate) fn to_vulkan(
&self,
device: &Device,
dynamic_state_modes: &mut FnvHashMap<DynamicState, bool>,
subpass: &Subpass,
) -> Result<ash::vk::PipelineMultisampleStateCreateInfo, GraphicsPipelineCreationError> {
let rasterization_samples = subpass.num_samples().unwrap_or(SampleCount::Sample1).into();
let (sample_shading_enable, min_sample_shading) =
if let Some(min_sample_shading) = self.sample_shading {
if !device.enabled_features().sample_rate_shading {
return Err(GraphicsPipelineCreationError::FeatureNotEnabled {
feature: "sample_rate_shading",
reason: "MultisampleState::sample_shading was Some",
});
}
assert!(min_sample_shading >= 0.0 && min_sample_shading <= 1.0); // TODO: return error?
(ash::vk::TRUE, min_sample_shading)
} else {
(ash::vk::FALSE, 0.0)
};
let alpha_to_one_enable = {
if self.alpha_to_one_enable {
if !device.enabled_features().alpha_to_one {
return Err(GraphicsPipelineCreationError::FeatureNotEnabled {
feature: "alpha_to_one",
reason: "MultisampleState::alpha_to_one was true",
});
}
}
self.alpha_to_one_enable as ash::vk::Bool32
};
Ok(ash::vk::PipelineMultisampleStateCreateInfo {
flags: ash::vk::PipelineMultisampleStateCreateFlags::empty(),
rasterization_samples,
sample_shading_enable,
min_sample_shading,
p_sample_mask: ptr::null(),
alpha_to_coverage_enable: self.alpha_to_coverage_enable as ash::vk::Bool32,
alpha_to_one_enable,
..Default::default()
})
}
}
impl Default for MultisampleState {
/// Returns [`MultisampleState::new()`].
#[inline]
fn default() -> Self {
Self::new()
}
}