Remove pipeline layout parameter from pipeline creation

This commit is contained in:
Pierre Krieger 2016-10-16 20:31:49 +02:00
parent fe726b4e28
commit b9f4f8f2cf
4 changed files with 68 additions and 55 deletions

View File

@ -329,11 +329,6 @@ fn main() {
// attachments without any change. // attachments without any change.
blend: Blend::pass_through(), blend: Blend::pass_through(),
// Shaders can usually access resources such as images or buffers. This parameters is here
// to indicate the layout of the accessed resources, which is also called the *pipeline
// layout*. Here we don't access anything, so we just create an `EmptyPipeline` object.
layout: PipelineLayout::new(&device, EmptyPipelineDesc).unwrap(),
// We have to indicate which subpass of which render pass this pipeline is going to be used // We have to indicate which subpass of which render pass this pipeline is going to be used
// in. The pipeline will only be usable from this particular subpass. // in. The pipeline will only be usable from this particular subpass.
render_pass: Subpass::from(render_pass.clone(), 0).unwrap(), render_pass: Subpass::from(render_pass.clone(), 0).unwrap(),

View File

@ -91,6 +91,7 @@ pub fn write_descriptor_sets(doc: &parse::Spirv) -> String {
}).collect::<Vec<_>>().concat(); }).collect::<Vec<_>>().concat();
format!(r#" format!(r#"
#[derive(Debug, Clone)]
pub struct Layout(ShaderStages); pub struct Layout(ShaderStages);
#[allow(unsafe_code)] #[allow(unsafe_code)]

View File

@ -15,8 +15,8 @@ use std::sync::Arc;
use descriptor::PipelineLayoutRef; use descriptor::PipelineLayoutRef;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout; use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayout;
use descriptor::pipeline_layout::PipelineLayoutSys; use descriptor::pipeline_layout::PipelineLayoutSys;
use descriptor::pipeline_layout::PipelineLayoutDesc;
use descriptor::pipeline_layout::PipelineLayoutDescNames; use descriptor::pipeline_layout::PipelineLayoutDescNames;
use descriptor::pipeline_layout::PipelineLayoutSuperset; use descriptor::pipeline_layout::PipelineLayoutSuperset;
use pipeline::shader::ComputeShaderEntryPoint; use pipeline::shader::ComputeShaderEntryPoint;
@ -40,17 +40,18 @@ pub struct ComputePipeline<Pl> {
pipeline_layout: Pl, pipeline_layout: Pl,
} }
impl<Pl> ComputePipeline<Pl> { impl ComputePipeline<()> {
/// Builds a new `ComputePipeline`. /// Builds a new `ComputePipeline`.
pub fn new<Css, Csl>(device: &Arc<Device>, pipeline_layout: Pl, pub fn new<Css, Csl>(device: &Arc<Device>, shader: &ComputeShaderEntryPoint<Css, Csl>,
shader: &ComputeShaderEntryPoint<Css, Csl>, specialization: &Css) specialization: &Css)
-> Result<Arc<ComputePipeline<Pl>>, ComputePipelineCreationError> -> Result<Arc<ComputePipeline<PipelineLayout<Csl>>>, ComputePipelineCreationError>
where Pl: PipelineLayoutRef, where Csl: PipelineLayoutDescNames + Clone,
Csl: PipelineLayoutDesc,
Css: SpecializationConstants Css: SpecializationConstants
{ {
let vk = device.pointers(); let vk = device.pointers();
let pipeline_layout = shader.layout().clone().build(device).unwrap(); // TODO: error
// TODO: more details in the error // TODO: more details in the error
if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(), shader.layout()) { if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(), shader.layout()) {
return Err(ComputePipelineCreationError::IncompatiblePipelineLayout); return Err(ComputePipelineCreationError::IncompatiblePipelineLayout);
@ -101,7 +102,9 @@ impl<Pl> ComputePipeline<Pl> {
pipeline_layout: pipeline_layout, pipeline_layout: pipeline_layout,
})) }))
} }
}
impl<Pl> ComputePipeline<Pl> {
/// Returns the `Device` this compute pipeline was created with. /// Returns the `Device` this compute pipeline was created with.
#[inline] #[inline]
pub fn device(&self) -> &Arc<Device> { pub fn device(&self) -> &Arc<Device> {

View File

@ -18,8 +18,10 @@ use smallvec::SmallVec;
use device::Device; use device::Device;
use descriptor::PipelineLayoutRef; use descriptor::PipelineLayoutRef;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout; use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayout;
use descriptor::pipeline_layout::PipelineLayoutDesc; use descriptor::pipeline_layout::PipelineLayoutDesc;
use descriptor::pipeline_layout::PipelineLayoutDescNames; use descriptor::pipeline_layout::PipelineLayoutDescNames;
use descriptor::pipeline_layout::PipelineLayoutDescUnion;
use descriptor::pipeline_layout::PipelineLayoutSuperset; use descriptor::pipeline_layout::PipelineLayoutSuperset;
use descriptor::pipeline_layout::PipelineLayoutSys; use descriptor::pipeline_layout::PipelineLayoutSys;
use descriptor::pipeline_layout::EmptyPipelineDesc; use descriptor::pipeline_layout::EmptyPipelineDesc;
@ -61,7 +63,7 @@ mod tests;
/// Description of a `GraphicsPipeline`. /// Description of a `GraphicsPipeline`.
pub struct GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, pub struct GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo,
Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, L, Rp> Tel, Gs, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp>
{ {
/// Describes the layout of the vertex input. /// Describes the layout of the vertex input.
/// ///
@ -107,10 +109,6 @@ pub struct GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl,
/// the existing value in the attachments. /// the existing value in the attachments.
pub blend: Blend, pub blend: Blend,
/// Describes the list of descriptors and push constants that the various shaders are going to
/// use.
pub layout: L,
/// Which subpass of which render pass this pipeline will run on. It is an error to run a /// Which subpass of which render pass this pipeline will run on. It is an error to run a
/// graphics pipeline on a different subpass. /// graphics pipeline on a different subpass.
pub render_pass: Subpass<Rp>, pub render_pass: Subpass<Rp>,
@ -151,8 +149,8 @@ pub struct GraphicsPipeline<VertexDefinition, Layout, RenderP> {
num_viewports: u32, num_viewports: u32,
} }
impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp> impl<Vdef, Rp> GraphicsPipeline<Vdef, (), Rp>
where L: PipelineLayoutRef, Rp: RenderPass + RenderPassDesc where Rp: RenderPass + RenderPassDesc
{ {
/// Builds a new graphics pipeline object. /// Builds a new graphics pipeline object.
/// ///
@ -166,11 +164,11 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
(device: &Arc<Device>, (device: &Arc<Device>,
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, (), (), (), EmptyPipelineDesc, params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, (), (), (), EmptyPipelineDesc,
(), (), (), EmptyPipelineDesc, (), (), (), EmptyPipelineDesc, (), (), (), EmptyPipelineDesc, (), (), (), EmptyPipelineDesc,
Fs, Fi, Fo, Fl, L, Rp>) Fs, Fi, Fo, Fl, Rp>)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError> -> Result<Arc<GraphicsPipeline<Vdef, PipelineLayout<PipelineLayoutDescUnion<Vl, Fl>>, Rp>>, GraphicsPipelineCreationError>
where Vdef: VertexDefinition<Vi>, where Vdef: VertexDefinition<Vi>,
L: PipelineLayoutRef, Vl: PipelineLayoutDescNames + Clone,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDesc, Fl: PipelineLayoutDescNames + Clone,
Fi: ShaderInterfaceDefMatch<Vo>, Fi: ShaderInterfaceDefMatch<Vo>,
Fo: ShaderInterfaceDef, Fo: ShaderInterfaceDef,
Vo: ShaderInterfaceDef, Vo: ShaderInterfaceDef,
@ -180,9 +178,13 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err)); return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err));
} }
let pl = params.vertex_shader.layout().clone()
.union(params.fragment_shader.layout().clone())
.build(device).unwrap(); // TODO: error
GraphicsPipeline::new_inner::<_, _, _, _, (), (), (), EmptyPipelineDesc, (), (), (), GraphicsPipeline::new_inner::<_, _, _, _, (), (), (), EmptyPipelineDesc, (), (), (),
EmptyPipelineDesc, (), (), (), EmptyPipelineDesc, _, _, _, _> EmptyPipelineDesc, (), (), (), EmptyPipelineDesc, _, _, _, _>
(device, params) (device, params, pl)
} }
/// Builds a new graphics pipeline object with a geometry shader. /// Builds a new graphics pipeline object with a geometry shader.
@ -197,13 +199,12 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
(device: &Arc<Device>, (device: &Arc<Device>,
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, (), (), (), EmptyPipelineDesc, params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, (), (), (), EmptyPipelineDesc,
(), (), (), EmptyPipelineDesc, Gsp, Gi, Go, Gl, Fs, Fi, (), (), (), EmptyPipelineDesc, Gsp, Gi, Go, Gl, Fs, Fi,
Fo, Fl, L, Rp>) Fo, Fl, Rp>)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError> -> Result<Arc<GraphicsPipeline<Vdef, PipelineLayout<PipelineLayoutDescUnion<PipelineLayoutDescUnion<Vl, Fl>, Gl>>, Rp>>, GraphicsPipelineCreationError>
where Vdef: VertexDefinition<Vi>, where Vdef: VertexDefinition<Vi>,
L: PipelineLayoutRef, Vl: PipelineLayoutDescNames + Clone,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDescNames + Clone,
Fl: PipelineLayoutDesc, Gl: PipelineLayoutDescNames + Clone,
Gl: PipelineLayoutDesc,
Gi: ShaderInterfaceDefMatch<Vo>, Gi: ShaderInterfaceDefMatch<Vo>,
Vo: ShaderInterfaceDef, Vo: ShaderInterfaceDef,
Fi: ShaderInterfaceDefMatch<Go> + ShaderInterfaceDefMatch<Vo>, Fi: ShaderInterfaceDefMatch<Go> + ShaderInterfaceDefMatch<Vo>,
@ -225,7 +226,12 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
} }
} }
GraphicsPipeline::new_inner(device, params) let pl = params.vertex_shader.layout().clone()
.union(params.fragment_shader.layout().clone())
.union(params.geometry_shader.as_ref().unwrap().layout().clone()) // FIXME: unwrap()
.build(device).unwrap(); // TODO: error
GraphicsPipeline::new_inner(device, params, pl)
} }
/// Builds a new graphics pipeline object with tessellation shaders. /// Builds a new graphics pipeline object with tessellation shaders.
@ -242,14 +248,13 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
(device: &Arc<Device>, (device: &Arc<Device>,
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes,
Tei, Teo, Tel, (), (), (), EmptyPipelineDesc, Fs, Fi, Tei, Teo, Tel, (), (), (), EmptyPipelineDesc, Fs, Fi,
Fo, Fl, L, Rp>) Fo, Fl, Rp>)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError> -> Result<Arc<GraphicsPipeline<Vdef, PipelineLayout<PipelineLayoutDescUnion<PipelineLayoutDescUnion<PipelineLayoutDescUnion<Vl, Fl>, Tcl>, Tel>>, Rp>>, GraphicsPipelineCreationError>
where Vdef: VertexDefinition<Vi>, where Vdef: VertexDefinition<Vi>,
L: PipelineLayoutRef, Vl: PipelineLayoutDescNames + Clone,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDescNames + Clone,
Fl: PipelineLayoutDesc, Tcl: PipelineLayoutDescNames + Clone,
Tcl: PipelineLayoutDesc, Tel: PipelineLayoutDescNames + Clone,
Tel: PipelineLayoutDesc,
Tci: ShaderInterfaceDefMatch<Vo>, Tci: ShaderInterfaceDefMatch<Vo>,
Tei: ShaderInterfaceDefMatch<Tco>, Tei: ShaderInterfaceDefMatch<Tco>,
Vo: ShaderInterfaceDef, Vo: ShaderInterfaceDef,
@ -276,54 +281,63 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
} }
} }
GraphicsPipeline::new_inner(device, params) let pl = params.vertex_shader.layout().clone()
.union(params.fragment_shader.layout().clone())
.union(params.tessellation.as_ref().unwrap().tessellation_control_shader.layout().clone()) // FIXME: unwrap()
.union(params.tessellation.as_ref().unwrap().tessellation_evaluation_shader.layout().clone()) // FIXME: unwrap()
.build(device).unwrap(); // TODO: error
GraphicsPipeline::new_inner(device, params, pl)
}
} }
impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
where L: PipelineLayoutRef, Rp: RenderPass + RenderPassDesc
{
fn new_inner<'a, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs, fn new_inner<'a, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs,
Fi, Fo, Fl> Fi, Fo, Fl>
(device: &Arc<Device>, (device: &Arc<Device>,
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes, params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vo, Vl, Tcs, Tci, Tco, Tcl, Tes,
Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs, Fi, Fo, Fl, L, Tei, Teo, Tel, Gsp, Gi, Go, Gl, Fs, Fi, Fo, Fl, Rp>,
Rp>) pipeline_layout: L)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError> -> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError>
where Vdef: VertexDefinition<Vi>, where Vdef: VertexDefinition<Vi>,
Fo: ShaderInterfaceDef, Fo: ShaderInterfaceDef,
L: PipelineLayoutRef, Vl: PipelineLayoutDescNames,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDescNames,
Fl: PipelineLayoutDesc, Gl: PipelineLayoutDescNames,
Gl: PipelineLayoutDesc, Tcl: PipelineLayoutDescNames,
Tcl: PipelineLayoutDesc, Tel: PipelineLayoutDescNames,
Tel: PipelineLayoutDesc,
Rp: RenderPassSubpassInterface<Fo>, Rp: RenderPassSubpassInterface<Fo>,
{ {
let vk = device.pointers(); let vk = device.pointers();
// Checking that the pipeline layout matches the shader stages. // Checking that the pipeline layout matches the shader stages.
// TODO: more details in the errors // TODO: more details in the errors
if !PipelineLayoutSuperset::is_superset_of(params.layout.desc(), if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(),
params.vertex_shader.layout()) params.vertex_shader.layout())
{ {
return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout); return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout);
} }
if !PipelineLayoutSuperset::is_superset_of(params.layout.desc(), if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(),
params.fragment_shader.layout()) params.fragment_shader.layout())
{ {
return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout); return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout);
} }
if let Some(ref geometry_shader) = params.geometry_shader { if let Some(ref geometry_shader) = params.geometry_shader {
if !PipelineLayoutSuperset::is_superset_of(params.layout.desc(), if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(),
geometry_shader.layout()) geometry_shader.layout())
{ {
return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout); return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout);
} }
} }
if let Some(ref tess) = params.tessellation { if let Some(ref tess) = params.tessellation {
if !PipelineLayoutSuperset::is_superset_of(params.layout.desc(), if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(),
tess.tessellation_control_shader.layout()) tess.tessellation_control_shader.layout())
{ {
return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout); return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout);
} }
if !PipelineLayoutSuperset::is_superset_of(params.layout.desc(), if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(),
tess.tessellation_evaluation_shader.layout()) tess.tessellation_evaluation_shader.layout())
{ {
return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout); return Err(GraphicsPipelineCreationError::IncompatiblePipelineLayout);
@ -849,7 +863,7 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
pColorBlendState: &blend, pColorBlendState: &blend,
pDynamicState: dynamic_states.as_ref().map(|s| s as *const _) pDynamicState: dynamic_states.as_ref().map(|s| s as *const _)
.unwrap_or(ptr::null()), .unwrap_or(ptr::null()),
layout: PipelineLayoutRef::sys(&params.layout).internal_object(), layout: PipelineLayoutRef::sys(&pipeline_layout).internal_object(),
renderPass: params.render_pass.render_pass().inner().internal_object(), renderPass: params.render_pass.render_pass().inner().internal_object(),
subpass: params.render_pass.index(), subpass: params.render_pass.index(),
basePipelineHandle: 0, // TODO: basePipelineHandle: 0, // TODO:
@ -867,7 +881,7 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
Ok(Arc::new(GraphicsPipeline { Ok(Arc::new(GraphicsPipeline {
device: device.clone(), device: device.clone(),
pipeline: pipeline, pipeline: pipeline,
layout: params.layout, layout: pipeline_layout,
vertex_definition: params.vertex_input, vertex_definition: params.vertex_input,