Skip to content

Commit

Permalink
Add partial support for khr_fragment_shading_rate (#2574)
Browse files Browse the repository at this point in the history
* support `khr_fragment_shading_rate`

* Add taskgraph `set_fragment_shading_rate`

* Add `set_fragment_shading_rate` validation

* Cleanup `FragmentShadingRateState` validation

* Consolidate fragment_shading_rate validation

* Add docs for `fragment_shading_rate`

* Update vulkano-taskgraph/src/command_buffer/commands/dynamic_state.rs

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>

* Format fragment_shading_rate validation messages

* Apply suggestions from code review

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>

---------

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>
  • Loading branch information
LDeakin and marc0246 authored Oct 19, 2024
1 parent dc61914 commit 6981040
Show file tree
Hide file tree
Showing 7 changed files with 443 additions and 5 deletions.
31 changes: 31 additions & 0 deletions vulkano-taskgraph/src/command_buffer/commands/dynamic_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use vulkano::{
pipeline::graphics::{
color_blend::LogicOp,
depth_stencil::{CompareOp, StencilFaces, StencilOp},
fragment_shading_rate::FragmentShadingRateCombinerOp,
input_assembly::PrimitiveTopology,
rasterization::{ConservativeRasterizationMode, CullMode, FrontFace},
vertex_input::{
Expand Down Expand Up @@ -772,4 +773,34 @@ impl RecordingCommandBuffer<'_> {

self
}

/// Sets the dynamic fragment shading rate for future draw calls.
pub unsafe fn set_fragment_shading_rate(
&mut self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> Result<&mut Self> {
unsafe { Ok(self.set_fragment_shading_rate_unchecked(fragment_size, combiner_ops)) }
}

pub unsafe fn set_fragment_shading_rate_unchecked(
&mut self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> &mut Self {
let fns = self.device().fns();
let fragment_size = vk::Extent2D {
width: fragment_size[0],
height: fragment_size[1],
};
let combiner_ops = [combiner_ops[0].into(), combiner_ops[1].into()];
unsafe {
(fns.khr_fragment_shading_rate
.cmd_set_fragment_shading_rate_khr)(
self.handle(), &fragment_size, &combiner_ops
)
}

self
}
}
4 changes: 3 additions & 1 deletion vulkano/src/command_buffer/auto/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{
graphics::{
color_blend::LogicOp,
depth_stencil::{CompareOp, StencilOps},
fragment_shading_rate::FragmentShadingRateState,
input_assembly::PrimitiveTopology,
rasterization::{
ConservativeRasterizationMode, CullMode, DepthBiasState, FrontFace, LineStipple,
Expand Down Expand Up @@ -1331,6 +1332,7 @@ pub(in crate::command_buffer) struct CommandBufferBuilderState {
pub(in crate::command_buffer) conservative_rasterization_mode:
Option<ConservativeRasterizationMode>,
pub(in crate::command_buffer) extra_primitive_overestimation_size: Option<f32>,
pub(in crate::command_buffer) fragment_shading_rate: Option<FragmentShadingRateState>,

// Active queries
pub(in crate::command_buffer) queries: HashMap<QueryType, QueryState>,
Expand Down Expand Up @@ -1362,7 +1364,7 @@ impl CommandBufferBuilderState {
DynamicState::DepthWriteEnable => self.depth_write_enable = None,
DynamicState::DiscardRectangle => self.discard_rectangle.clear(),
// DynamicState::ExclusiveScissor => todo!(),
// DynamicState::FragmentShadingRate => todo!(),
DynamicState::FragmentShadingRate => self.fragment_shading_rate = None,
DynamicState::FrontFace => self.front_face = None,
DynamicState::LineStipple => self.line_stipple = None,
DynamicState::LineWidth => self.line_width = None,
Expand Down
89 changes: 89 additions & 0 deletions vulkano/src/command_buffer/commands/dynamic_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
graphics::{
color_blend::LogicOp,
depth_stencil::{CompareOp, StencilFaces, StencilOp, StencilOps},
fragment_shading_rate::{FragmentShadingRateCombinerOp, FragmentShadingRateState},
input_assembly::PrimitiveTopology,
rasterization::{
ConservativeRasterizationMode, CullMode, DepthBiasState, FrontFace, LineStipple,
Expand Down Expand Up @@ -1280,6 +1281,54 @@ impl<L> RecordingCommandBuffer<L> {

self
}

/// Sets the dynamic fragment shading rate for future draw calls.
#[inline]
pub fn set_fragment_shading_rate(
&mut self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> Result<&mut Self, Box<ValidationError>> {
self.validate_set_fragment_shading_rate(fragment_size, combiner_ops)?;

unsafe { Ok(self.set_fragment_shading_rate_unchecked(fragment_size, combiner_ops)) }
}

fn validate_set_fragment_shading_rate(
&self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> Result<(), Box<ValidationError>> {
self.inner
.validate_set_fragment_shading_rate(fragment_size, combiner_ops)?;

self.validate_graphics_pipeline_fixed_state(DynamicState::FragmentShadingRate)?;

Ok(())
}

#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn set_fragment_shading_rate_unchecked(
&mut self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> &mut Self {
self.builder_state.fragment_shading_rate = Some(FragmentShadingRateState {
fragment_size,
combiner_ops,
..FragmentShadingRateState::default()
});

self.add_command(
"set_fragment_shading_rate",
Default::default(),
move |out: &mut RawRecordingCommandBuffer| {
out.set_fragment_shading_rate_unchecked(fragment_size, combiner_ops);
},
);

self
}
}

impl RawRecordingCommandBuffer {
Expand Down Expand Up @@ -3381,4 +3430,44 @@ impl RawRecordingCommandBuffer {

self
}

fn validate_set_fragment_shading_rate(
&self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> Result<(), Box<ValidationError>> {
FragmentShadingRateState {
fragment_size,
combiner_ops,
..FragmentShadingRateState::default()
}
.validate(self.device())?;

Ok(())
}

#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn set_fragment_shading_rate_unchecked(
&mut self,
fragment_size: [u32; 2],
combiner_ops: [FragmentShadingRateCombinerOp; 2],
) -> &mut Self {
let fns = self.device().fns();

let fragment_size = ash::vk::Extent2D {
width: fragment_size[0],
height: fragment_size[1],
};
let combiner_ops: [ash::vk::FragmentShadingRateCombinerOpKHR; 2] =
[combiner_ops[0].into(), combiner_ops[1].into()];

(fns.khr_fragment_shading_rate
.cmd_set_fragment_shading_rate_khr)(
self.handle(),
&fragment_size,
combiner_ops.as_ptr().cast(),
);

self
}
}
20 changes: 19 additions & 1 deletion vulkano/src/command_buffer/commands/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2633,7 +2633,25 @@ impl<L> RecordingCommandBuffer<L> {
}
}
// DynamicState::ExclusiveScissor => todo!(),
// DynamicState::FragmentShadingRate => todo!(),
DynamicState::FragmentShadingRate => {
if self.builder_state.fragment_shading_rate.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,
"VUID-vkCmdDrawIndexed-pipelineFragmentShadingRate-09238"
),
..Default::default()
}));
}
}
DynamicState::FrontFace => {
if self.builder_state.front_face.is_none() {
return Err(Box::new(ValidationError {
Expand Down
Loading

0 comments on commit 6981040

Please sign in to comment.