mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
support for ext_conservative_rasterization
(#2508)
* disabled bad validation code * conservative rasterization * validation for conservative_rasterization * rebuild * extra_primitive_overestimation_size dynamic state * safety fixed * set builder state * formatted * unfixed fake bug fix * actually unfixed fake bug fix * fixed bad formatting * deleted duplicate todo * command buffer documentation * formatted * add vuid Co-authored-by: Rua <ruawhitepaw@gmail.com> * add vuid Co-authored-by: Rua <ruawhitepaw@gmail.com> * more validation * Update vulkano/src/pipeline/graphics/mod.rs Co-authored-by: Rua <ruawhitepaw@gmail.com> * Update vulkano/src/pipeline/graphics/mod.rs Co-authored-by: Rua <ruawhitepaw@gmail.com> * Update vulkano/src/pipeline/graphics/mod.rs Co-authored-by: Rua <ruawhitepaw@gmail.com> * Update vulkano/src/pipeline/graphics/mod.rs Co-authored-by: Rua <ruawhitepaw@gmail.com> * put in block * add todo * fixed clippy * removed redundant checks --------- Co-authored-by: Rua <ruawhitepaw@gmail.com>
This commit is contained in:
parent
78f3f9f508
commit
5dab2df966
@ -18,6 +18,7 @@ use crate::{
|
||||
pipeline::{
|
||||
graphics::{
|
||||
color_blend::LogicOp,
|
||||
conservative_rasterization::ConservativeRasterizationMode,
|
||||
depth_stencil::{CompareOp, StencilOps},
|
||||
input_assembly::PrimitiveTopology,
|
||||
rasterization::{CullMode, DepthBiasState, FrontFace, LineStipple},
|
||||
@ -1207,6 +1208,9 @@ pub(in crate::command_buffer) struct CommandBufferBuilderState {
|
||||
pub(in crate::command_buffer) vertex_input: Option<VertexInputState>,
|
||||
pub(in crate::command_buffer) viewport: HashMap<u32, Viewport>,
|
||||
pub(in crate::command_buffer) viewport_with_count: Option<SmallVec<[Viewport; 2]>>,
|
||||
pub(in crate::command_buffer) conservative_rasterization_mode:
|
||||
Option<ConservativeRasterizationMode>,
|
||||
pub(in crate::command_buffer) extra_primitive_overestimation_size: Option<f32>,
|
||||
|
||||
// Active queries
|
||||
pub(in crate::command_buffer) queries: HashMap<QueryType, QueryState>,
|
||||
@ -1275,25 +1279,28 @@ impl CommandBufferBuilderState {
|
||||
// DynamicState::ColorBlendEquation => todo!(),
|
||||
// DynamicState::ColorWriteMask => todo!(),
|
||||
// DynamicState::RasterizationStream => todo!(),
|
||||
// DynamicState::ConservativeRasterizationMode => todo!(),
|
||||
// DynamicState::ExtraPrimitiveOverestimationSize => todo!(),
|
||||
// DynamicState::DepthClipEnable => todo!(),
|
||||
// DynamicState::SampleLocationsEnable => todo!(),
|
||||
// DynamicState::ColorBlendAdvanced => todo!(),
|
||||
// DynamicState::ProvokingVertexMode => todo!(),
|
||||
// DynamicState::LineRasterizationMode => todo!(),
|
||||
// DynamicState::LineStippleEnable => todo!(),
|
||||
// DynamicState::DepthClipNegativeOneToOne => todo!(),
|
||||
// DynamicState::ViewportWScalingEnable => todo!(),
|
||||
// DynamicState::ViewportSwizzle => todo!(),
|
||||
// DynamicState::CoverageToColorEnable => todo!(),
|
||||
// DynamicState::CoverageToColorLocation => todo!(),
|
||||
// DynamicState::CoverageModulationMode => todo!(),
|
||||
// DynamicState::CoverageModulationTableEnable => todo!(),
|
||||
// DynamicState::CoverageModulationTable => todo!(),
|
||||
// DynamicState::ShadingRateImageEnable => todo!(),
|
||||
// DynamicState::RepresentativeFragmentTestEnable => todo!(),
|
||||
// DynamicState::CoverageReductionMode => todo!(),
|
||||
DynamicState::ConservativeRasterizationMode => {
|
||||
self.conservative_rasterization_mode = None
|
||||
}
|
||||
DynamicState::ExtraPrimitiveOverestimationSize => {
|
||||
self.extra_primitive_overestimation_size = None
|
||||
} /* DynamicState::DepthClipEnable => todo!(),
|
||||
* DynamicState::SampleLocationsEnable => todo!(),
|
||||
* DynamicState::ColorBlendAdvanced => todo!(),
|
||||
* DynamicState::ProvokingVertexMode => todo!(),
|
||||
* DynamicState::LineRasterizationMode => todo!(),
|
||||
* DynamicState::LineStippleEnable => todo!(),
|
||||
* DynamicState::DepthClipNegativeOneToOne => todo!(),
|
||||
* DynamicState::ViewportWScalingEnable => todo!(),
|
||||
* DynamicState::ViewportSwizzle => todo!(),
|
||||
* DynamicState::CoverageToColorEnable => todo!(),
|
||||
* DynamicState::CoverageToColorLocation => todo!(),
|
||||
* DynamicState::CoverageModulationMode => todo!(),
|
||||
* DynamicState::CoverageModulationTableEnable => todo!(),
|
||||
* DynamicState::CoverageModulationTable => todo!(),
|
||||
* DynamicState::ShadingRateImageEnable => todo!(),
|
||||
* DynamicState::RepresentativeFragmentTestEnable => todo!(),
|
||||
* DynamicState::CoverageReductionMode => todo!(), */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
pipeline::{
|
||||
graphics::{
|
||||
color_blend::LogicOp,
|
||||
conservative_rasterization::ConservativeRasterizationMode,
|
||||
depth_stencil::{CompareOp, StencilFaces, StencilOp, StencilOps},
|
||||
input_assembly::PrimitiveTopology,
|
||||
rasterization::{CullMode, DepthBiasState, FrontFace, LineStipple},
|
||||
@ -1196,6 +1197,91 @@ impl RecordingCommandBuffer {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the dynamic conservative rasterization mode for future draw calls.
|
||||
#[inline]
|
||||
pub fn set_conservative_rasterization_mode(
|
||||
&mut self,
|
||||
conservative_rasterization_mode: ConservativeRasterizationMode,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_set_conservative_rasterization_mode()?;
|
||||
|
||||
unsafe {
|
||||
Ok(self.set_conservative_rasterization_mode_unchecked(conservative_rasterization_mode))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_set_conservative_rasterization_mode(&self) -> Result<(), Box<ValidationError>> {
|
||||
self.inner.validate_set_conservative_rasterization_mode()?;
|
||||
|
||||
self.validate_graphics_pipeline_fixed_state(DynamicState::ConservativeRasterizationMode)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn set_conservative_rasterization_mode_unchecked(
|
||||
&mut self,
|
||||
conservative_rasterization_mode: ConservativeRasterizationMode,
|
||||
) -> &mut Self {
|
||||
self.builder_state.conservative_rasterization_mode = Some(conservative_rasterization_mode);
|
||||
|
||||
self.add_command(
|
||||
"set_conservative_rasterization_mode",
|
||||
Default::default(),
|
||||
move |out: &mut RawRecordingCommandBuffer| {
|
||||
out.set_conservative_rasterization_mode_unchecked(conservative_rasterization_mode);
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the dynamic extra primitive overestimation size for future draw calls.
|
||||
#[inline]
|
||||
pub fn set_extra_primitive_overestimation_size(
|
||||
&mut self,
|
||||
extra_primitive_overestimation_size: f32,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_set_extra_primitive_overestimation_size()?;
|
||||
|
||||
unsafe {
|
||||
Ok(self.set_extra_primitive_overestimation_size_unchecked(
|
||||
extra_primitive_overestimation_size,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_set_extra_primitive_overestimation_size(&self) -> Result<(), Box<ValidationError>> {
|
||||
self.inner.validate_set_conservative_rasterization_mode()?;
|
||||
|
||||
self.validate_graphics_pipeline_fixed_state(
|
||||
DynamicState::ExtraPrimitiveOverestimationSize,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn set_extra_primitive_overestimation_size_unchecked(
|
||||
&mut self,
|
||||
extra_primitive_overestimation_size: f32,
|
||||
) -> &mut Self {
|
||||
self.builder_state.extra_primitive_overestimation_size =
|
||||
Some(extra_primitive_overestimation_size);
|
||||
|
||||
self.add_command(
|
||||
"set_extra_primitive_overestimation_size",
|
||||
Default::default(),
|
||||
move |out: &mut RawRecordingCommandBuffer| {
|
||||
out.set_extra_primitive_overestimation_size_unchecked(
|
||||
extra_primitive_overestimation_size,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RawRecordingCommandBuffer {
|
||||
@ -3186,4 +3272,144 @@ impl RawRecordingCommandBuffer {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_conservative_rasterization_mode(
|
||||
&mut self,
|
||||
conservative_rasterization_mode: ConservativeRasterizationMode,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_set_conservative_rasterization_mode()?;
|
||||
|
||||
Ok(self.set_conservative_rasterization_mode_unchecked(conservative_rasterization_mode))
|
||||
}
|
||||
|
||||
fn validate_set_conservative_rasterization_mode(&self) -> Result<(), Box<ValidationError>> {
|
||||
if !(self
|
||||
.device()
|
||||
.enabled_features()
|
||||
.extended_dynamic_state3_conservative_rasterization_mode)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[
|
||||
RequiresAllOf(&[Requires::DeviceFeature(
|
||||
"extended_dynamic_state3_conservative_rasterization_mode",
|
||||
)]),
|
||||
RequiresAllOf(&[Requires::DeviceFeature("shader_object")]),
|
||||
]),
|
||||
vuids: &["VUID-vkCmdSetConservativeRasterizationModeEXT-None-09423"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "the queue family of the command buffer does not support \
|
||||
graphics operations"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdSetConservativeRasterizationModeEXT-commandBuffer-cmdpool"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn set_conservative_rasterization_mode_unchecked(
|
||||
&mut self,
|
||||
conservative_rasterization_mode: ConservativeRasterizationMode,
|
||||
) -> &mut Self {
|
||||
let fns = self.device().fns();
|
||||
(fns.ext_extended_dynamic_state3
|
||||
.cmd_set_conservative_rasterization_mode_ext)(
|
||||
self.handle(),
|
||||
conservative_rasterization_mode.into(),
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set_extra_primitive_overestimation_size(
|
||||
&mut self,
|
||||
extra_primitive_overestimation_size: f32,
|
||||
) -> Result<&mut Self, Box<ValidationError>> {
|
||||
self.validate_set_extra_primitive_overestimation_size(extra_primitive_overestimation_size)?;
|
||||
|
||||
Ok(self
|
||||
.set_extra_primitive_overestimation_size_unchecked(extra_primitive_overestimation_size))
|
||||
}
|
||||
|
||||
fn validate_set_extra_primitive_overestimation_size(
|
||||
&self,
|
||||
extra_primitive_overestimation_size: f32,
|
||||
) -> Result<(), Box<ValidationError>> {
|
||||
let properties = self.device().physical_device().properties();
|
||||
|
||||
if !(self
|
||||
.device()
|
||||
.enabled_features()
|
||||
.extended_dynamic_state3_extra_primitive_overestimation_size)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[
|
||||
RequiresAllOf(&[Requires::DeviceFeature(
|
||||
"extended_dynamic_state3_extra_primitive_overestimation_size",
|
||||
)]),
|
||||
RequiresAllOf(&[Requires::DeviceFeature("shader_object")]),
|
||||
]),
|
||||
vuids: &["VUID-vkCmdSetExtraPrimitiveOverestimationSizeEXT-None-09423"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if !self
|
||||
.queue_family_properties()
|
||||
.queue_flags
|
||||
.intersects(QueueFlags::GRAPHICS)
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "the queue family of the command buffer does not support \
|
||||
graphics operations"
|
||||
.into(),
|
||||
vuids: &["VUID-vkCmdSetExtraPrimitiveOverestimationSizeEXT-commandBuffer-cmdpool"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
if extra_primitive_overestimation_size < 0.0
|
||||
|| extra_primitive_overestimation_size
|
||||
> properties.max_extra_primitive_overestimation_size.unwrap()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "overestimation size".into(),
|
||||
problem: "the overestimation size is not in the range of 0.0 to `max_extra_primitive_overestimation_size` inclusive".into(),
|
||||
vuids: &[
|
||||
"VUID-vkCmdSetExtraPrimitiveOverestimationSizeEXT-extraPrimitiveOverestimationSize-07428",
|
||||
],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn set_extra_primitive_overestimation_size_unchecked(
|
||||
&mut self,
|
||||
extra_primitive_overestimation_size: f32,
|
||||
) -> &mut Self {
|
||||
let fns = self.device().fns();
|
||||
(fns.ext_extended_dynamic_state3
|
||||
.cmd_set_extra_primitive_overestimation_size_ext)(
|
||||
self.handle(),
|
||||
extra_primitive_overestimation_size,
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -3219,6 +3219,43 @@ impl RecordingCommandBuffer {
|
||||
// the viewportCount parameter of
|
||||
// vkCmdSetViewportWithCountEXT must be 1
|
||||
}
|
||||
DynamicState::ConservativeRasterizationMode => {
|
||||
if self.builder_state.conservative_rasterization_mode.is_none() {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: format!(
|
||||
"the currently bound graphics pipeline requires the \
|
||||
`DynamicState::{:?}` dynamic state, but \
|
||||
this state was either not set, or it was overwritten by a \
|
||||
more recent `bind_pipeline_graphics` command",
|
||||
dynamic_state
|
||||
)
|
||||
.into(),
|
||||
vuids: vuids!(vuid_type, "None-07631"),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
// TODO: VUID-vkCmdDraw-conservativePointAndLineRasterization-07499
|
||||
}
|
||||
DynamicState::ExtraPrimitiveOverestimationSize => {
|
||||
if self
|
||||
.builder_state
|
||||
.extra_primitive_overestimation_size
|
||||
.is_none()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: format!(
|
||||
"the currently bound graphics pipeline requires the \
|
||||
`DynamicState::{:?}` dynamic state, but \
|
||||
this state was either not set, or it was overwritten by a \
|
||||
more recent `bind_pipeline_graphics` command",
|
||||
dynamic_state
|
||||
)
|
||||
.into(),
|
||||
vuids: vuids!(vuid_type, "None-07632"),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
90
vulkano/src/pipeline/graphics/conservative_rasterization.rs
Normal file
90
vulkano/src/pipeline/graphics/conservative_rasterization.rs
Normal file
@ -0,0 +1,90 @@
|
||||
//! A mode of rasterization where the edges of primitives are modified so that fragments are
|
||||
//! generated if the edge of a primitive touches any part of a pixel, or if a pixel is fully
|
||||
//! covered by a primitive.
|
||||
use crate::{device::Device, macros::vulkan_enum, ValidationError};
|
||||
|
||||
/// The state in a graphics pipeline describing how the conservative rasterization mode should
|
||||
/// behave.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ConservativeRasterizationState {
|
||||
/// Sets the conservative rasterization mode.
|
||||
///
|
||||
/// The default value is [`ConservativeRasterizationMode::Disabled`].
|
||||
pub mode: ConservativeRasterizationMode,
|
||||
|
||||
/// The extra size in pixels to increase the generating primitive during conservative
|
||||
/// rasterization. If the mode is set to anything other than
|
||||
/// [`ConservativeRasterizationMode::Overestimate`] this value is ignored.
|
||||
///
|
||||
/// The default value is 0.0.
|
||||
pub overestimation_size: f32,
|
||||
|
||||
pub _ne: crate::NonExhaustive,
|
||||
}
|
||||
|
||||
impl Default for ConservativeRasterizationState {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
mode: ConservativeRasterizationMode::Disabled,
|
||||
overestimation_size: 0.0,
|
||||
_ne: crate::NonExhaustive(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConservativeRasterizationState {
|
||||
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
|
||||
let &Self {
|
||||
mode,
|
||||
overestimation_size,
|
||||
_ne: _,
|
||||
} = self;
|
||||
|
||||
let properties = device.physical_device().properties();
|
||||
|
||||
mode.validate_device(device).map_err(|err| {
|
||||
err.add_context("mode").set_vuids(&[
|
||||
"VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-conservativeRasterizationMode-parameter",
|
||||
])
|
||||
})?;
|
||||
|
||||
if overestimation_size < 0.0
|
||||
|| overestimation_size > properties.max_extra_primitive_overestimation_size.unwrap()
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "overestimation size".into(),
|
||||
problem: "the overestimation size is not in the range of 0.0 to `max_extra_primitive_overestimation_size` inclusive".into(),
|
||||
vuids: &[
|
||||
"VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-extraPrimitiveOverestimationSize-01769",
|
||||
],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
#[non_exhaustive]
|
||||
|
||||
/// Describes how fragments will be generated based on how much is covered by a primitive.
|
||||
ConservativeRasterizationMode = ConservativeRasterizationModeEXT(i32);
|
||||
|
||||
/// Conservative rasterization is disabled and rasterization proceeds as normal.
|
||||
Disabled = DISABLED,
|
||||
|
||||
/// Fragments will be generated if any part of a primitive touches a pixel.
|
||||
Overestimate = OVERESTIMATE,
|
||||
|
||||
/// Fragments will be generated only if a primitive completely covers a pixel.
|
||||
Underestimate = UNDERESTIMATE,
|
||||
}
|
||||
|
||||
impl Default for ConservativeRasterizationMode {
|
||||
#[inline]
|
||||
fn default() -> ConservativeRasterizationMode {
|
||||
ConservativeRasterizationMode::Disabled
|
||||
}
|
||||
}
|
@ -79,6 +79,7 @@
|
||||
|
||||
use self::{
|
||||
color_blend::ColorBlendState,
|
||||
conservative_rasterization::ConservativeRasterizationMode,
|
||||
depth_stencil::{DepthState, DepthStencilState},
|
||||
discard_rectangle::DiscardRectangleState,
|
||||
input_assembly::{InputAssemblyState, PrimitiveTopology},
|
||||
@ -104,6 +105,7 @@ use crate::{
|
||||
macros::impl_id_counter,
|
||||
pipeline::graphics::{
|
||||
color_blend::ColorBlendAttachmentState,
|
||||
conservative_rasterization::ConservativeRasterizationState,
|
||||
depth_stencil::{StencilOpState, StencilState},
|
||||
rasterization::{CullMode, DepthBiasState},
|
||||
subpass::PipelineRenderingCreateInfo,
|
||||
@ -126,6 +128,7 @@ use std::{
|
||||
};
|
||||
|
||||
pub mod color_blend;
|
||||
pub mod conservative_rasterization;
|
||||
pub mod depth_stencil;
|
||||
pub mod discard_rectangle;
|
||||
pub mod input_assembly;
|
||||
@ -163,6 +166,7 @@ pub struct GraphicsPipeline {
|
||||
subpass: PipelineSubpassType,
|
||||
|
||||
discard_rectangle_state: Option<DiscardRectangleState>,
|
||||
conservative_rasterization_state: Option<ConservativeRasterizationState>,
|
||||
|
||||
descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>,
|
||||
num_used_descriptor_sets: u32,
|
||||
@ -222,6 +226,7 @@ impl GraphicsPipeline {
|
||||
ref base_pipeline,
|
||||
|
||||
ref discard_rectangle_state,
|
||||
ref conservative_rasterization_state,
|
||||
_ne: _,
|
||||
} = &create_info;
|
||||
|
||||
@ -818,6 +823,25 @@ impl GraphicsPipeline {
|
||||
);
|
||||
}
|
||||
|
||||
let mut conservative_rasterization_state_vk = None;
|
||||
|
||||
if let Some(conservative_rasterization_state) = conservative_rasterization_state {
|
||||
let ConservativeRasterizationState {
|
||||
mode,
|
||||
overestimation_size,
|
||||
_ne: _,
|
||||
} = conservative_rasterization_state;
|
||||
|
||||
let _ = conservative_rasterization_state_vk.insert(
|
||||
ash::vk::PipelineRasterizationConservativeStateCreateInfoEXT {
|
||||
flags: ash::vk::PipelineRasterizationConservativeStateCreateFlagsEXT::empty(),
|
||||
conservative_rasterization_mode: (*mode).into(),
|
||||
extra_primitive_overestimation_size: *overestimation_size,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Create
|
||||
*/
|
||||
@ -877,6 +901,11 @@ impl GraphicsPipeline {
|
||||
create_info_vk.p_next = info as *const _ as *const _;
|
||||
}
|
||||
|
||||
if let Some(info) = conservative_rasterization_state_vk.as_mut() {
|
||||
info.p_next = create_info_vk.p_next;
|
||||
create_info_vk.p_next = info as *const _ as *const _;
|
||||
}
|
||||
|
||||
if let Some(info) = rendering_create_info_vk.as_mut() {
|
||||
info.p_next = create_info_vk.p_next;
|
||||
create_info_vk.p_next = info as *const _ as *const _;
|
||||
@ -945,6 +974,7 @@ impl GraphicsPipeline {
|
||||
base_pipeline: _,
|
||||
|
||||
discard_rectangle_state,
|
||||
conservative_rasterization_state,
|
||||
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
@ -1081,6 +1111,13 @@ impl GraphicsPipeline {
|
||||
fixed_state.extend([DynamicState::DiscardRectangle]);
|
||||
}
|
||||
|
||||
if conservative_rasterization_state.is_some() {
|
||||
fixed_state.extend([
|
||||
DynamicState::ConservativeRasterizationMode,
|
||||
DynamicState::ExtraPrimitiveOverestimationSize,
|
||||
]);
|
||||
}
|
||||
|
||||
fixed_state.retain(|state| !dynamic_state.contains(state));
|
||||
|
||||
Arc::new(Self {
|
||||
@ -1104,6 +1141,7 @@ impl GraphicsPipeline {
|
||||
subpass: subpass.unwrap(),
|
||||
|
||||
discard_rectangle_state,
|
||||
conservative_rasterization_state,
|
||||
|
||||
descriptor_binding_requirements,
|
||||
num_used_descriptor_sets,
|
||||
@ -1203,6 +1241,12 @@ impl GraphicsPipeline {
|
||||
self.discard_rectangle_state.as_ref()
|
||||
}
|
||||
|
||||
/// Returns the conservative rasterization state used to create this pipeline.
|
||||
#[inline]
|
||||
pub fn conservative_rasterization_state(&self) -> Option<&ConservativeRasterizationState> {
|
||||
self.conservative_rasterization_state.as_ref()
|
||||
}
|
||||
|
||||
/// If the pipeline has a fragment shader, returns the fragment tests stages used.
|
||||
#[inline]
|
||||
pub fn fragment_tests_stages(&self) -> Option<FragmentTestsStages> {
|
||||
@ -1395,6 +1439,11 @@ pub struct GraphicsPipelineCreateInfo {
|
||||
/// The default value is `None`.
|
||||
pub discard_rectangle_state: Option<DiscardRectangleState>,
|
||||
|
||||
/// The conservative rasterization state.
|
||||
///
|
||||
/// The default value is `None`.
|
||||
pub conservative_rasterization_state: Option<ConservativeRasterizationState>,
|
||||
|
||||
pub _ne: crate::NonExhaustive,
|
||||
}
|
||||
|
||||
@ -1421,6 +1470,7 @@ impl GraphicsPipelineCreateInfo {
|
||||
base_pipeline: None,
|
||||
|
||||
discard_rectangle_state: None,
|
||||
conservative_rasterization_state: None,
|
||||
_ne: crate::NonExhaustive(()),
|
||||
}
|
||||
}
|
||||
@ -1445,6 +1495,7 @@ impl GraphicsPipelineCreateInfo {
|
||||
ref base_pipeline,
|
||||
|
||||
ref discard_rectangle_state,
|
||||
ref conservative_rasterization_state,
|
||||
_ne: _,
|
||||
} = self;
|
||||
|
||||
@ -2155,6 +2206,23 @@ impl GraphicsPipelineCreateInfo {
|
||||
.map_err(|err| err.add_context("discard_rectangle_state"))?;
|
||||
}
|
||||
|
||||
if let Some(conservative_rasterization_state) = conservative_rasterization_state {
|
||||
if !device.enabled_extensions().ext_conservative_rasterization {
|
||||
return Err(Box::new(ValidationError {
|
||||
context: "conservative_rasterization_state".into(),
|
||||
problem: "is `Some`".into(),
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
|
||||
"ext_conservative_rasterization",
|
||||
)])]),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
conservative_rasterization_state
|
||||
.validate(device)
|
||||
.map_err(|err| err.add_context("conservative_rasterization_state"))?;
|
||||
}
|
||||
|
||||
for dynamic_state in dynamic_state.iter().copied() {
|
||||
dynamic_state.validate_device(device).map_err(|err| {
|
||||
err.add_context("dynamic_state")
|
||||
@ -2505,6 +2573,107 @@ impl GraphicsPipelineCreateInfo {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(conservative_rasterization_state) = conservative_rasterization_state {
|
||||
let properties = device.physical_device().properties();
|
||||
|
||||
if matches!(
|
||||
conservative_rasterization_state.mode,
|
||||
ConservativeRasterizationMode::Disabled
|
||||
) && !properties
|
||||
.conservative_point_and_line_rasterization
|
||||
.unwrap_or(false)
|
||||
{
|
||||
if let (None, Some(input_assembly_state)) = (geometry_stage, input_assembly_state) {
|
||||
if matches!(
|
||||
input_assembly_state.topology,
|
||||
PrimitiveTopology::PointList
|
||||
| PrimitiveTopology::LineList
|
||||
| PrimitiveTopology::LineStrip
|
||||
) && (!dynamic_state.contains(&DynamicState::PrimitiveTopology)
|
||||
|| match device
|
||||
.physical_device()
|
||||
.properties()
|
||||
.dynamic_primitive_topology_unrestricted
|
||||
{
|
||||
Some(b) => !b,
|
||||
None => false,
|
||||
})
|
||||
{
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "`input_assembly_state.topology` is not compatible with the \
|
||||
conservative rasterization mode"
|
||||
.into(),
|
||||
vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-08892"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(geometry_stage), Some(_)) = (geometry_stage, input_assembly_state) {
|
||||
let spirv = geometry_stage.entry_point.module().spirv();
|
||||
let entry_point_function = spirv.function(geometry_stage.entry_point.id());
|
||||
|
||||
let invalid_output =
|
||||
entry_point_function
|
||||
.execution_modes()
|
||||
.iter()
|
||||
.any(|instruction| {
|
||||
matches!(
|
||||
instruction,
|
||||
Instruction::ExecutionMode {
|
||||
mode: ExecutionMode::OutputPoints
|
||||
| ExecutionMode::OutputLineStrip,
|
||||
..
|
||||
},
|
||||
)
|
||||
});
|
||||
|
||||
if invalid_output {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "the output topology of the geometry shader is not compatible with the \
|
||||
conservative rasterization mode"
|
||||
.into(),
|
||||
vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-06760"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mesh_stage) = mesh_stage {
|
||||
let spirv = mesh_stage.entry_point.module().spirv();
|
||||
let entry_point_function = spirv.function(mesh_stage.entry_point.id());
|
||||
|
||||
let mut invalid_output = false;
|
||||
|
||||
for instruction in entry_point_function.execution_modes() {
|
||||
if let Instruction::ExecutionMode { mode, .. } = *instruction {
|
||||
match mode {
|
||||
ExecutionMode::OutputPoints => {
|
||||
invalid_output = true;
|
||||
break;
|
||||
}
|
||||
ExecutionMode::OutputLineStrip => {
|
||||
invalid_output = true;
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if invalid_output {
|
||||
return Err(Box::new(ValidationError {
|
||||
problem: "the output topology of the mesh shader is not compatible with the \
|
||||
conservative rasterization mode"
|
||||
.into(),
|
||||
vuids: &["VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-06761"],
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let (Some(fragment_stage), Some(color_blend_state), Some(subpass)) =
|
||||
(fragment_stage, color_blend_state, subpass)
|
||||
{
|
||||
|
@ -730,19 +730,25 @@ vulkan_enum! {
|
||||
RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]),
|
||||
]), */
|
||||
|
||||
/* TODO: enable
|
||||
// TODO: document
|
||||
/// The value of
|
||||
/// [`ConservativeRasterizationState::mode`](crate::pipeline::graphics::conservative_rasterization::ConservativeRasterizationState::mode)
|
||||
///
|
||||
/// Set with
|
||||
/// [`set_conservative_rasterization_mode`](crate::command_buffer::RecordingCommandBuffer::set_conservative_rasterization_mode).
|
||||
ConservativeRasterizationMode = CONSERVATIVE_RASTERIZATION_MODE_EXT
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]),
|
||||
]), */
|
||||
]),
|
||||
|
||||
/* TODO: enable
|
||||
// TODO: document
|
||||
/// The value of
|
||||
/// [`ConservativeRasterizationState::overestimation_size`](crate::pipeline::graphics::conservative_rasterization::ConservativeRasterizationState::overestimation_size)
|
||||
///
|
||||
/// Set with
|
||||
/// [`set_extra_primitive_overestimation_size`](crate::command_buffer::RecordingCommandBuffer::set_extra_primitive_overestimation_size).
|
||||
ExtraPrimitiveOverestimationSize = EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT
|
||||
RequiresOneOf([
|
||||
RequiresAllOf([DeviceExtension(ext_extended_dynamic_state3)]),
|
||||
]), */
|
||||
]),
|
||||
|
||||
/* TODO: enable
|
||||
// TODO: document
|
||||
|
Loading…
Reference in New Issue
Block a user