diff --git a/vulkano/src/pipeline/compute.rs b/vulkano/src/pipeline/compute.rs index 281aab9d2c..dce3aa7187 100644 --- a/vulkano/src/pipeline/compute.rs +++ b/vulkano/src/pipeline/compute.rs @@ -47,7 +47,10 @@ pub struct ComputePipeline { handle: ash::vk::Pipeline, device: InstanceOwnedDebugWrapper>, id: NonZeroU64, + + flags: PipelineCreateFlags, layout: DeviceOwnedDebugWrapper>, + 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 { 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 { &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, + /// 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>, + 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, diff --git a/vulkano/src/pipeline/graphics/mod.rs b/vulkano/src/pipeline/graphics/mod.rs index 19d0404122..5eb96fd892 100644 --- a/vulkano/src/pipeline/graphics/mod.rs +++ b/vulkano/src/pipeline/graphics/mod.rs @@ -125,6 +125,7 @@ pub struct GraphicsPipeline { device: InstanceOwnedDebugWrapper>, id: NonZeroU64, + flags: PipelineCreateFlags, // TODO: replace () with an object that describes the shaders in some way. shaders: HashMap, 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 { 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, + /// 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>, + /// 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 */ diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index ce10fcfe00..fa7999e871 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -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