Add support for pipeline derivatives (#2299)

* Add support for pipeline derivatives

* Doc derp

* Formatting

---------

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>
This commit is contained in:
Rua 2023-08-24 02:02:09 +02:00 committed by GitHub
parent a99aa95e61
commit 15665c3437
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 17 deletions

View File

@ -47,7 +47,10 @@ pub struct ComputePipeline {
handle: ash::vk::Pipeline,
device: InstanceOwnedDebugWrapper<Arc<Device>>,
id: NonZeroU64,
flags: PipelineCreateFlags,
layout: DeviceOwnedDebugWrapper<Arc<PipelineLayout>>,
descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>,
num_used_descriptor_sets: u32,
}
@ -90,6 +93,7 @@ impl ComputePipeline {
flags,
ref stage,
ref layout,
ref base_pipeline,
_ne: _,
} = &create_info;
@ -166,8 +170,10 @@ impl ComputePipeline {
flags: flags.into(),
stage: stage_vk,
layout: layout.handle(),
base_pipeline_handle: ash::vk::Pipeline::null(),
base_pipeline_index: 0,
base_pipeline_handle: base_pipeline
.as_ref()
.map_or(ash::vk::Pipeline::null(), VulkanObject::handle),
base_pipeline_index: -1,
..Default::default()
};
@ -203,9 +209,10 @@ impl ComputePipeline {
create_info: ComputePipelineCreateInfo,
) -> Arc<ComputePipeline> {
let ComputePipelineCreateInfo {
flags: _,
flags,
stage,
layout,
base_pipeline: _,
_ne: _,
} = create_info;
@ -227,17 +234,26 @@ impl ComputePipeline {
handle,
device: InstanceOwnedDebugWrapper(device),
id: Self::next_id(),
flags,
layout: DeviceOwnedDebugWrapper(layout),
descriptor_binding_requirements,
num_used_descriptor_sets,
})
}
/// Returns the `Device` this compute pipeline was created with.
/// Returns the `Device` that the pipeline was created with.
#[inline]
pub fn device(&self) -> &Arc<Device> {
&self.device
}
/// Returns the flags that the pipeline was created with.
#[inline]
pub fn flags(&self) -> PipelineCreateFlags {
self.flags
}
}
impl Pipeline for ComputePipeline {
@ -310,6 +326,15 @@ pub struct ComputePipelineCreateInfo {
/// There is no default value.
pub layout: Arc<PipelineLayout>,
/// The pipeline to use as a base when creating this pipeline.
///
/// If this is `Some`, then `flags` must contain [`PipelineCreateFlags::DERIVATIVE`],
/// and the `flags` of the provided pipeline must contain
/// [`PipelineCreateFlags::ALLOW_DERIVATIVES`].
///
/// The default value is `None`.
pub base_pipeline: Option<Arc<ComputePipeline>>,
pub _ne: crate::NonExhaustive,
}
@ -321,6 +346,7 @@ impl ComputePipelineCreateInfo {
flags: PipelineCreateFlags::empty(),
stage,
layout,
base_pipeline: None,
_ne: crate::NonExhaustive(()),
}
}
@ -330,6 +356,7 @@ impl ComputePipelineCreateInfo {
flags,
ref stage,
ref layout,
ref base_pipeline,
_ne: _,
} = self;
@ -342,6 +369,37 @@ impl ComputePipelineCreateInfo {
.validate(device)
.map_err(|err| err.add_context("stage"))?;
if flags.intersects(PipelineCreateFlags::DERIVATIVE) {
let base_pipeline = base_pipeline.as_ref().ok_or_else(|| {
Box::new(ValidationError {
problem: "`flags` contains `PipelineCreateFlags::DERIVATIVE`, but \
`base_pipeline` is `None`"
.into(),
vuids: &["VUID-VkComputePipelineCreateInfo-flags-07984"],
..Default::default()
})
})?;
if !base_pipeline
.flags()
.intersects(PipelineCreateFlags::ALLOW_DERIVATIVES)
{
return Err(Box::new(ValidationError {
context: "base_pipeline.flags()".into(),
problem: "does not contain `PipelineCreateFlags::ALLOW_DERIVATIVES`".into(),
vuids: &["VUID-vkCreateComputePipelines-flags-00696"],
..Default::default()
}));
}
} else if base_pipeline.is_some() {
return Err(Box::new(ValidationError {
problem: "`flags` does not contain `PipelineCreateFlags::DERIVATIVE`, but \
`base_pipeline` is `Some`"
.into(),
..Default::default()
}));
}
let &PipelineShaderStageCreateInfo {
flags: _,
ref entry_point,

View File

@ -125,6 +125,7 @@ pub struct GraphicsPipeline {
device: InstanceOwnedDebugWrapper<Arc<Device>>,
id: NonZeroU64,
flags: PipelineCreateFlags,
// TODO: replace () with an object that describes the shaders in some way.
shaders: HashMap<ShaderStage, ()>,
descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>,
@ -190,7 +191,8 @@ impl GraphicsPipeline {
ref color_blend_state,
ref layout,
subpass: ref render_pass,
ref subpass,
ref base_pipeline,
ref discard_rectangle_state,
_ne: _,
@ -1003,7 +1005,7 @@ impl GraphicsPipeline {
}
}
let render_pass = render_pass.as_ref().unwrap();
let render_pass = subpass.as_ref().unwrap();
let mut render_pass_vk = ash::vk::RenderPass::null();
let mut subpass_vk = 0;
let mut color_attachment_formats_vk: SmallVec<[_; 4]> = SmallVec::new();
@ -1124,8 +1126,10 @@ impl GraphicsPipeline {
layout: layout.handle(),
render_pass: render_pass_vk,
subpass: subpass_vk,
base_pipeline_handle: ash::vk::Pipeline::null(), // TODO:
base_pipeline_index: -1, // TODO:
base_pipeline_handle: base_pipeline
.as_ref()
.map_or(ash::vk::Pipeline::null(), VulkanObject::handle),
base_pipeline_index: -1,
..Default::default()
};
@ -1184,7 +1188,7 @@ impl GraphicsPipeline {
create_info: GraphicsPipelineCreateInfo,
) -> Arc<Self> {
let GraphicsPipelineCreateInfo {
flags: _,
flags,
stages,
vertex_input_state,
@ -1197,7 +1201,8 @@ impl GraphicsPipeline {
color_blend_state,
layout,
subpass: render_pass,
subpass,
base_pipeline: _,
discard_rectangle_state,
@ -1597,6 +1602,7 @@ impl GraphicsPipeline {
device: InstanceOwnedDebugWrapper(device),
id: Self::next_id(),
flags,
shaders,
descriptor_binding_requirements,
num_used_descriptor_sets,
@ -1611,7 +1617,7 @@ impl GraphicsPipeline {
depth_stencil_state,
color_blend_state,
layout: DeviceOwnedDebugWrapper(layout),
subpass: render_pass.unwrap(),
subpass: subpass.unwrap(),
dynamic_state,
discard_rectangle_state,
@ -1624,6 +1630,12 @@ impl GraphicsPipeline {
&self.device
}
/// Returns the flags that the pipeline was created with.
#[inline]
pub fn flags(&self) -> PipelineCreateFlags {
self.flags
}
/// Returns information about a particular shader.
///
/// `None` is returned if the pipeline does not contain this shader.
@ -1863,6 +1875,15 @@ pub struct GraphicsPipelineCreateInfo {
/// The default value is `None`.
pub subpass: Option<PipelineSubpassType>,
/// The pipeline to use as a base when creating this pipeline.
///
/// If this is `Some`, then `flags` must contain [`PipelineCreateFlags::DERIVATIVE`],
/// and the `flags` of the provided pipeline must contain
/// [`PipelineCreateFlags::ALLOW_DERIVATIVES`].
///
/// The default value is `None`.
pub base_pipeline: Option<Arc<GraphicsPipeline>>,
/// The discard rectangle state.
///
/// This state is always used if it is provided.
@ -1890,6 +1911,7 @@ impl GraphicsPipelineCreateInfo {
color_blend_state: None,
layout,
subpass: None,
base_pipeline: None,
discard_rectangle_state: None,
_ne: crate::NonExhaustive(()),
}
@ -1911,6 +1933,7 @@ impl GraphicsPipelineCreateInfo {
ref layout,
ref subpass,
ref base_pipeline,
ref discard_rectangle_state,
_ne: _,
@ -1921,6 +1944,37 @@ impl GraphicsPipelineCreateInfo {
.set_vuids(&["VUID-VkGraphicsPipelineCreateInfo-flags-parameter"])
})?;
if flags.intersects(PipelineCreateFlags::DERIVATIVE) {
let base_pipeline = base_pipeline.as_ref().ok_or_else(|| {
Box::new(ValidationError {
problem: "`flags` contains `PipelineCreateFlags::DERIVATIVE`, but \
`base_pipeline` is `None`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-flags-07984"],
..Default::default()
})
})?;
if !base_pipeline
.flags()
.intersects(PipelineCreateFlags::ALLOW_DERIVATIVES)
{
return Err(Box::new(ValidationError {
context: "base_pipeline.flags()".into(),
problem: "does not contain `PipelineCreateFlags::ALLOW_DERIVATIVES`".into(),
vuids: &["VUID-vkCreateGraphicsPipelines-flags-00721"],
..Default::default()
}));
}
} else if base_pipeline.is_some() {
return Err(Box::new(ValidationError {
problem: "`flags` does not contain `PipelineCreateFlags::DERIVATIVE`, but \
`base_pipeline` is `Some`"
.into(),
..Default::default()
}));
}
/*
Gather shader stages
*/

View File

@ -92,13 +92,11 @@ vulkan_bitflags! {
/// The pipeline will not be optimized.
DISABLE_OPTIMIZATION = DISABLE_OPTIMIZATION,
/* TODO: enable
// TODO: document
ALLOW_DERIVATIVES = ALLOW_DERIVATIVES,*/
/// Derivative pipelines can be created using this pipeline as a base.
ALLOW_DERIVATIVES = ALLOW_DERIVATIVES,
/* TODO: enable
// TODO: document
DERIVATIVE = DERIVATIVE,*/
/// Create the pipeline by deriving from a base pipeline.
DERIVATIVE = DERIVATIVE,
/* TODO: enable
// TODO: document