mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
Make specialization constants work (#780)
* Add new template parameters for GraphicsPipelineBuilder * Add support for the specialization constants in build() * Fix SpecializationConstants fields being private * Fix lifetime problem in SpecializationConstants::descriptors() * Run rustfmt on builder.rs
This commit is contained in:
parent
a54281f8ec
commit
2cbdb288d4
@ -122,17 +122,19 @@ impl Default for SpecializationConstants {{
|
|||||||
|
|
||||||
unsafe impl SpecConstsTrait for SpecializationConstants {{
|
unsafe impl SpecConstsTrait for SpecializationConstants {{
|
||||||
fn descriptors() -> &'static [SpecializationMapEntry] {{
|
fn descriptors() -> &'static [SpecializationMapEntry] {{
|
||||||
&[
|
static DESCRIPTORS: [SpecializationMapEntry; {num_map_entries}] = [
|
||||||
{map_entries}
|
{map_entries}
|
||||||
]
|
];
|
||||||
|
&DESCRIPTORS
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
"#,
|
"#,
|
||||||
struct_def = spec_consts.iter().map(|c| format!("{}: {}", c.name, c.rust_ty))
|
struct_def = spec_consts.iter().map(|c| format!("pub {}: {}", c.name, c.rust_ty))
|
||||||
.collect::<Vec<_>>().join(", "),
|
.collect::<Vec<_>>().join(", "),
|
||||||
def_vals = spec_consts.iter().map(|c| format!("{}: {}", c.name, c.default_value))
|
def_vals = spec_consts.iter().map(|c| format!("{}: {}", c.name, c.default_value))
|
||||||
.collect::<Vec<_>>().join(", "),
|
.collect::<Vec<_>>().join(", "),
|
||||||
|
num_map_entries = map_entries.len(),
|
||||||
map_entries = map_entries.join(", ")
|
map_entries = map_entries.join(", ")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ use pipeline::depth_stencil::Compare;
|
|||||||
use pipeline::depth_stencil::DepthBounds;
|
use pipeline::depth_stencil::DepthBounds;
|
||||||
use pipeline::depth_stencil::DepthStencil;
|
use pipeline::depth_stencil::DepthStencil;
|
||||||
use pipeline::graphics_pipeline::GraphicsPipeline;
|
use pipeline::graphics_pipeline::GraphicsPipeline;
|
||||||
use pipeline::graphics_pipeline::Inner as GraphicsPipelineInner;
|
|
||||||
use pipeline::graphics_pipeline::GraphicsPipelineCreationError;
|
use pipeline::graphics_pipeline::GraphicsPipelineCreationError;
|
||||||
|
use pipeline::graphics_pipeline::Inner as GraphicsPipelineInner;
|
||||||
use pipeline::input_assembly::InputAssembly;
|
use pipeline::input_assembly::InputAssembly;
|
||||||
use pipeline::input_assembly::PrimitiveTopology;
|
use pipeline::input_assembly::PrimitiveTopology;
|
||||||
use pipeline::multisample::Multisample;
|
use pipeline::multisample::Multisample;
|
||||||
@ -43,6 +43,7 @@ use pipeline::shader::EmptyEntryPointDummy;
|
|||||||
use pipeline::shader::GraphicsEntryPointAbstract;
|
use pipeline::shader::GraphicsEntryPointAbstract;
|
||||||
use pipeline::shader::GraphicsShaderType;
|
use pipeline::shader::GraphicsShaderType;
|
||||||
use pipeline::shader::ShaderInterfaceDefMatch;
|
use pipeline::shader::ShaderInterfaceDefMatch;
|
||||||
|
use pipeline::shader::SpecializationConstants;
|
||||||
use pipeline::vertex::SingleBufferDefinition;
|
use pipeline::vertex::SingleBufferDefinition;
|
||||||
use pipeline::vertex::VertexDefinition;
|
use pipeline::vertex::VertexDefinition;
|
||||||
use pipeline::viewport::Scissor;
|
use pipeline::viewport::Scissor;
|
||||||
@ -58,24 +59,16 @@ use vk;
|
|||||||
|
|
||||||
/// Prototype for a `GraphicsPipeline`.
|
/// Prototype for a `GraphicsPipeline`.
|
||||||
// TODO: we can optimize this by filling directly the raw vk structs
|
// TODO: we can optimize this by filling directly the raw vk structs
|
||||||
pub struct GraphicsPipelineBuilder<
|
pub struct GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp> {
|
||||||
Vdef,
|
|
||||||
Vs,
|
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp>
|
|
||||||
{
|
|
||||||
vertex_input: Vdef,
|
vertex_input: Vdef,
|
||||||
vertex_shader: Option<Vs>,
|
vertex_shader: Option<(Vs, Vss)>,
|
||||||
input_assembly: InputAssembly,
|
input_assembly: InputAssembly,
|
||||||
tessellation: Option<TessInfo<Tcs, Tes>>,
|
tessellation: Option<TessInfo<Tcs, Tcss, Tes, Tess>>,
|
||||||
geometry_shader: Option<Gs>,
|
geometry_shader: Option<(Gs, Gss)>,
|
||||||
viewport: Option<ViewportsState>,
|
viewport: Option<ViewportsState>,
|
||||||
raster: Rasterization,
|
raster: Rasterization,
|
||||||
multisample: Multisample,
|
multisample: Multisample,
|
||||||
fragment_shader: Option<Fs>,
|
fragment_shader: Option<(Fs, Fss)>,
|
||||||
depth_stencil: DepthStencil,
|
depth_stencil: DepthStencil,
|
||||||
blend: Blend,
|
blend: Blend,
|
||||||
render_pass: Option<Subpass<Rp>>,
|
render_pass: Option<Subpass<Rp>>,
|
||||||
@ -83,18 +76,24 @@ pub struct GraphicsPipelineBuilder<
|
|||||||
|
|
||||||
// Additional parameters if tessellation is used.
|
// Additional parameters if tessellation is used.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct TessInfo<Tcs, Tes> {
|
struct TessInfo<Tcs, Tcss, Tes, Tess> {
|
||||||
tessellation_control_shader: Tcs,
|
tessellation_control_shader: (Tcs, Tcss),
|
||||||
tessellation_evaluation_shader: Tes,
|
tessellation_evaluation_shader: (Tes, Tess),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GraphicsPipelineBuilder<SingleBufferDefinition<()>,
|
impl
|
||||||
EmptyEntryPointDummy,
|
GraphicsPipelineBuilder<SingleBufferDefinition<()>,
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy,
|
||||||
EmptyEntryPointDummy,
|
(),
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy,
|
||||||
EmptyEntryPointDummy,
|
(),
|
||||||
()> {
|
EmptyEntryPointDummy,
|
||||||
|
(),
|
||||||
|
EmptyEntryPointDummy,
|
||||||
|
(),
|
||||||
|
EmptyEntryPointDummy,
|
||||||
|
(),
|
||||||
|
()> {
|
||||||
/// Builds a new empty builder.
|
/// Builds a new empty builder.
|
||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
@ -114,26 +113,19 @@ impl GraphicsPipelineBuilder<SingleBufferDefinition<()>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Vdef,
|
impl<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp>
|
||||||
Vs,
|
GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp>
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp>
|
|
||||||
GraphicsPipelineBuilder<Vdef,
|
|
||||||
Vs,
|
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp>
|
|
||||||
where Vdef: VertexDefinition<Vs::InputDefinition>,
|
where Vdef: VertexDefinition<Vs::InputDefinition>,
|
||||||
Vs: GraphicsEntryPointAbstract,
|
Vs: GraphicsEntryPointAbstract,
|
||||||
Fs: GraphicsEntryPointAbstract,
|
Fs: GraphicsEntryPointAbstract,
|
||||||
Gs: GraphicsEntryPointAbstract,
|
Gs: GraphicsEntryPointAbstract,
|
||||||
Tcs: GraphicsEntryPointAbstract,
|
Tcs: GraphicsEntryPointAbstract,
|
||||||
Tes: GraphicsEntryPointAbstract,
|
Tes: GraphicsEntryPointAbstract,
|
||||||
|
Vss: SpecializationConstants,
|
||||||
|
Tcss: SpecializationConstants,
|
||||||
|
Tess: SpecializationConstants,
|
||||||
|
Gss: SpecializationConstants,
|
||||||
|
Fss: SpecializationConstants,
|
||||||
Vs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
Vs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
||||||
Fs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
Fs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
||||||
Tcs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
Tcs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
||||||
@ -141,10 +133,11 @@ impl<Vdef,
|
|||||||
Gs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
Gs::PipelineLayout: Clone + 'static + Send + Sync, // TODO: shouldn't be required
|
||||||
Tcs::InputDefinition: ShaderInterfaceDefMatch<Vs::OutputDefinition>,
|
Tcs::InputDefinition: ShaderInterfaceDefMatch<Vs::OutputDefinition>,
|
||||||
Tes::InputDefinition: ShaderInterfaceDefMatch<Tcs::OutputDefinition>,
|
Tes::InputDefinition: ShaderInterfaceDefMatch<Tcs::OutputDefinition>,
|
||||||
Gs::InputDefinition: ShaderInterfaceDefMatch<Tes::OutputDefinition> + ShaderInterfaceDefMatch<Vs::OutputDefinition>,
|
Gs::InputDefinition: ShaderInterfaceDefMatch<Tes::OutputDefinition>
|
||||||
|
+ ShaderInterfaceDefMatch<Vs::OutputDefinition>,
|
||||||
Fs::InputDefinition: ShaderInterfaceDefMatch<Gs::OutputDefinition>
|
Fs::InputDefinition: ShaderInterfaceDefMatch<Gs::OutputDefinition>
|
||||||
+ ShaderInterfaceDefMatch<Tes::OutputDefinition>
|
+ ShaderInterfaceDefMatch<Tes::OutputDefinition>
|
||||||
+ ShaderInterfaceDefMatch<Vs::OutputDefinition>,
|
+ ShaderInterfaceDefMatch<Vs::OutputDefinition>,
|
||||||
Rp: RenderPassAbstract + RenderPassSubpassInterface<Fs::OutputDefinition>
|
Rp: RenderPassAbstract + RenderPassSubpassInterface<Fs::OutputDefinition>
|
||||||
{
|
{
|
||||||
/// Builds the graphics pipeline.
|
/// Builds the graphics pipeline.
|
||||||
@ -161,126 +154,165 @@ impl<Vdef,
|
|||||||
if let Some(ref tess) = self.tessellation {
|
if let Some(ref tess) = self.tessellation {
|
||||||
if let Some(ref gs) = self.geometry_shader {
|
if let Some(ref gs) = self.geometry_shader {
|
||||||
if let Err(err) = tess.tessellation_control_shader
|
if let Err(err) = tess.tessellation_control_shader
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(self.vertex_shader.as_ref().unwrap().output())
|
.matches(self.vertex_shader.as_ref().unwrap().0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err));
|
||||||
}
|
}
|
||||||
if let Err(err) = tess.tessellation_evaluation_shader
|
if let Err(err) = tess.tessellation_evaluation_shader
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(tess.tessellation_control_shader.output())
|
.matches(tess.tessellation_control_shader.0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err));
|
||||||
}
|
}
|
||||||
if let Err(err) = gs.input()
|
if let Err(err) = gs.0
|
||||||
.matches(tess.tessellation_evaluation_shader.output())
|
.input()
|
||||||
|
.matches(tess.tessellation_evaluation_shader.0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::TessEvalGeometryStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::TessEvalGeometryStagesMismatch(err));
|
||||||
}
|
}
|
||||||
if let Err(err) = self.fragment_shader.as_ref().unwrap().input().matches(gs.output()) {
|
if let Err(err) = self.fragment_shader
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.input()
|
||||||
|
.matches(gs.0.output())
|
||||||
|
{
|
||||||
return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline_layout = Box::new(self.vertex_shader.as_ref().unwrap().layout().clone()
|
pipeline_layout = Box::new(self.vertex_shader.as_ref().unwrap().0.layout().clone()
|
||||||
.union(self.fragment_shader.as_ref().unwrap().layout().clone())
|
.union(self.fragment_shader.as_ref().unwrap().0.layout().clone())
|
||||||
.union(self.tessellation.as_ref().unwrap().tessellation_control_shader.layout().clone()) // FIXME: unwrap()
|
.union(self.tessellation.as_ref().unwrap().tessellation_control_shader.0.layout().clone()) // FIXME: unwrap()
|
||||||
.union(self.tessellation.as_ref().unwrap().tessellation_evaluation_shader.layout().clone()) // FIXME: unwrap()
|
.union(self.tessellation.as_ref().unwrap().tessellation_evaluation_shader.0.layout().clone()) // FIXME: unwrap()
|
||||||
.union(self.geometry_shader.as_ref().unwrap().layout().clone()) // FIXME: unwrap()
|
.union(self.geometry_shader.as_ref().unwrap().0.layout().clone()) // FIXME: unwrap()
|
||||||
.build(device.clone()).unwrap()) as Box<_>; // TODO: error
|
.build(device.clone()).unwrap()) as Box<_>; // TODO: error
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if let Err(err) = tess.tessellation_control_shader
|
if let Err(err) = tess.tessellation_control_shader
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(self.vertex_shader.as_ref().unwrap().output())
|
.matches(self.vertex_shader.as_ref().unwrap().0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::VertexTessControlStagesMismatch(err));
|
||||||
}
|
}
|
||||||
if let Err(err) = tess.tessellation_evaluation_shader
|
if let Err(err) = tess.tessellation_evaluation_shader
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(tess.tessellation_control_shader.output())
|
.matches(tess.tessellation_control_shader.0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::TessControlTessEvalStagesMismatch(err));
|
||||||
}
|
}
|
||||||
if let Err(err) = self
|
if let Err(err) = self.fragment_shader
|
||||||
.fragment_shader
|
.as_ref()
|
||||||
.as_ref().unwrap()
|
.unwrap()
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(tess.tessellation_evaluation_shader.output())
|
.matches(tess.tessellation_evaluation_shader.0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::TessEvalFragmentStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::TessEvalFragmentStagesMismatch(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline_layout = Box::new(self.vertex_shader.as_ref().unwrap().layout().clone()
|
pipeline_layout = Box::new(self.vertex_shader.as_ref().unwrap().0.layout().clone()
|
||||||
.union(self.fragment_shader.as_ref().unwrap().layout().clone())
|
.union(self.fragment_shader.as_ref().unwrap().0.layout().clone())
|
||||||
.union(self.tessellation.as_ref().unwrap().tessellation_control_shader.layout().clone()) // FIXME: unwrap()
|
.union(self.tessellation.as_ref().unwrap().tessellation_control_shader.0.layout().clone()) // FIXME: unwrap()
|
||||||
.union(self.tessellation.as_ref().unwrap().tessellation_evaluation_shader.layout().clone()) // FIXME: unwrap()
|
.union(self.tessellation.as_ref().unwrap().tessellation_evaluation_shader.0.layout().clone()) // FIXME: unwrap()
|
||||||
.build(device.clone()).unwrap()) as Box<_>; // TODO: error
|
.build(device.clone()).unwrap()) as Box<_>; // TODO: error
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if let Some(ref geometry_shader) = self.geometry_shader {
|
if let Some(ref geometry_shader) = self.geometry_shader {
|
||||||
if let Err(err) = geometry_shader
|
if let Err(err) = geometry_shader
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(self.vertex_shader.as_ref().unwrap().output())
|
.matches(self.vertex_shader.as_ref().unwrap().0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::VertexGeometryStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::VertexGeometryStagesMismatch(err));
|
||||||
}
|
}
|
||||||
if let Err(err) = self
|
if let Err(err) = self.fragment_shader
|
||||||
.fragment_shader
|
.as_ref()
|
||||||
.as_ref().unwrap()
|
.unwrap()
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(geometry_shader.output())
|
.matches(geometry_shader.0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::GeometryFragmentStagesMismatch(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline_layout = Box::new(self.vertex_shader.as_ref().unwrap().layout().clone()
|
pipeline_layout = Box::new(self.vertex_shader.as_ref().unwrap().0.layout().clone()
|
||||||
.union(self.fragment_shader.as_ref().unwrap().layout().clone())
|
.union(self.fragment_shader.as_ref().unwrap().0.layout().clone())
|
||||||
.union(self.geometry_shader.as_ref().unwrap().layout().clone()) // FIXME: unwrap()
|
.union(self.geometry_shader.as_ref().unwrap().0.layout().clone()) // FIXME: unwrap()
|
||||||
.build(device.clone()).unwrap()) as Box<_>; // TODO: error
|
.build(device.clone()).unwrap()) as Box<_>; // TODO: error
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if let Err(err) = self
|
if let Err(err) = self.fragment_shader
|
||||||
.fragment_shader
|
.as_ref()
|
||||||
.as_ref().unwrap()
|
.unwrap()
|
||||||
|
.0
|
||||||
.input()
|
.input()
|
||||||
.matches(self.vertex_shader.as_ref().unwrap().output())
|
.matches(self.vertex_shader.as_ref().unwrap().0.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err));
|
return Err(GraphicsPipelineCreationError::VertexFragmentStagesMismatch(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline_layout = Box::new(self
|
pipeline_layout =
|
||||||
.vertex_shader
|
Box::new(self.vertex_shader
|
||||||
.as_ref().unwrap()
|
.as_ref()
|
||||||
.layout()
|
.unwrap()
|
||||||
.clone()
|
.0
|
||||||
.union(self.fragment_shader.as_ref().unwrap().layout().clone())
|
.layout()
|
||||||
.build(device.clone())
|
.clone()
|
||||||
.unwrap()) as Box<_>; // TODO: error
|
.union(self.fragment_shader.as_ref().unwrap().0.layout().clone())
|
||||||
|
.build(device.clone())
|
||||||
|
.unwrap()) as Box<_>; // TODO: error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
||||||
self.vertex_shader.as_ref().unwrap().layout())?;
|
self.vertex_shader
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.layout())?;
|
||||||
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
||||||
self.fragment_shader.as_ref().unwrap().layout())?;
|
self.fragment_shader
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.layout())?;
|
||||||
if let Some(ref geometry_shader) = self.geometry_shader {
|
if let Some(ref geometry_shader) = self.geometry_shader {
|
||||||
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout, geometry_shader.layout())?;
|
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
||||||
|
geometry_shader.0.layout())?;
|
||||||
}
|
}
|
||||||
if let Some(ref tess) = self.tessellation {
|
if let Some(ref tess) = self.tessellation {
|
||||||
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
||||||
tess.tessellation_control_shader.layout())?;
|
tess.tessellation_control_shader
|
||||||
|
.0
|
||||||
|
.layout())?;
|
||||||
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
PipelineLayoutSuperset::ensure_superset_of(&pipeline_layout,
|
||||||
tess.tessellation_evaluation_shader
|
tess.tessellation_evaluation_shader
|
||||||
|
.0
|
||||||
.layout())?;
|
.layout())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the subpass can accept the output of the fragment shader.
|
// Check that the subpass can accept the output of the fragment shader.
|
||||||
if !RenderPassSubpassInterface::is_compatible_with(&self.render_pass.as_ref().unwrap().render_pass(),
|
if !RenderPassSubpassInterface::is_compatible_with(&self.render_pass
|
||||||
self.render_pass.as_ref().unwrap().index(),
|
.as_ref()
|
||||||
self.fragment_shader.as_ref().unwrap().output())
|
.unwrap()
|
||||||
|
.render_pass(),
|
||||||
|
self.render_pass
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.index(),
|
||||||
|
self.fragment_shader
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.output())
|
||||||
{
|
{
|
||||||
return Err(GraphicsPipelineCreationError::FragmentShaderRenderPassIncompatible);
|
return Err(GraphicsPipelineCreationError::FragmentShaderRenderPassIncompatible);
|
||||||
}
|
}
|
||||||
@ -288,11 +320,70 @@ impl<Vdef,
|
|||||||
// Will contain the list of dynamic states. Filled throughout this function.
|
// Will contain the list of dynamic states. Filled throughout this function.
|
||||||
let mut dynamic_states: SmallVec<[vk::DynamicState; 8]> = SmallVec::new();
|
let mut dynamic_states: SmallVec<[vk::DynamicState; 8]> = SmallVec::new();
|
||||||
|
|
||||||
|
// Creating the specialization constants of the various stages.
|
||||||
|
let vertex_shader_specialization = {
|
||||||
|
let spec_descriptors = Vss::descriptors();
|
||||||
|
let constants = &self.vertex_shader.as_ref().unwrap().1;
|
||||||
|
vk::SpecializationInfo {
|
||||||
|
mapEntryCount: spec_descriptors.len() as u32,
|
||||||
|
pMapEntries: spec_descriptors.as_ptr() as *const _,
|
||||||
|
dataSize: mem::size_of_val(constants),
|
||||||
|
pData: constants as *const Vss as *const _,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tess_shader_specialization = if let Some(ref tess) = self.tessellation {
|
||||||
|
let tcs_spec = {
|
||||||
|
let spec_descriptors = Tcss::descriptors();
|
||||||
|
let constants = &tess.tessellation_control_shader.1;
|
||||||
|
vk::SpecializationInfo {
|
||||||
|
mapEntryCount: spec_descriptors.len() as u32,
|
||||||
|
pMapEntries: spec_descriptors.as_ptr() as *const _,
|
||||||
|
dataSize: mem::size_of_val(constants),
|
||||||
|
pData: constants as *const Tcss as *const _,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tes_spec = {
|
||||||
|
let spec_descriptors = Tess::descriptors();
|
||||||
|
let constants = &tess.tessellation_evaluation_shader.1;
|
||||||
|
vk::SpecializationInfo {
|
||||||
|
mapEntryCount: spec_descriptors.len() as u32,
|
||||||
|
pMapEntries: spec_descriptors.as_ptr() as *const _,
|
||||||
|
dataSize: mem::size_of_val(constants),
|
||||||
|
pData: constants as *const Tess as *const _,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some((tcs_spec, tes_spec))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let geometry_shader_specialization = if let Some(ref gs) = self.geometry_shader {
|
||||||
|
let spec_descriptors = Gss::descriptors();
|
||||||
|
let constants = &gs.1;
|
||||||
|
Some(vk::SpecializationInfo {
|
||||||
|
mapEntryCount: spec_descriptors.len() as u32,
|
||||||
|
pMapEntries: spec_descriptors.as_ptr() as *const _,
|
||||||
|
dataSize: mem::size_of_val(constants),
|
||||||
|
pData: constants as *const Gss as *const _,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let fragment_shader_specialization = {
|
||||||
|
let spec_descriptors = Fss::descriptors();
|
||||||
|
let constants = &self.fragment_shader.as_ref().unwrap().1;
|
||||||
|
vk::SpecializationInfo {
|
||||||
|
mapEntryCount: spec_descriptors.len() as u32,
|
||||||
|
pMapEntries: spec_descriptors.as_ptr() as *const _,
|
||||||
|
dataSize: mem::size_of_val(constants),
|
||||||
|
pData: constants as *const Fss as *const _,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// List of shader stages.
|
// List of shader stages.
|
||||||
let stages = {
|
let stages = {
|
||||||
let mut stages = SmallVec::<[_; 5]>::new();
|
let mut stages = SmallVec::<[_; 5]>::new();
|
||||||
|
|
||||||
match self.vertex_shader.as_ref().unwrap().ty() {
|
match self.vertex_shader.as_ref().unwrap().0.ty() {
|
||||||
GraphicsShaderType::Vertex => {},
|
GraphicsShaderType::Vertex => {},
|
||||||
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
||||||
};
|
};
|
||||||
@ -302,12 +393,17 @@ impl<Vdef,
|
|||||||
pNext: ptr::null(),
|
pNext: ptr::null(),
|
||||||
flags: 0, // reserved
|
flags: 0, // reserved
|
||||||
stage: vk::SHADER_STAGE_VERTEX_BIT,
|
stage: vk::SHADER_STAGE_VERTEX_BIT,
|
||||||
module: self.vertex_shader.as_ref().unwrap().module().internal_object(),
|
module: self.vertex_shader
|
||||||
pName: self.vertex_shader.as_ref().unwrap().name().as_ptr(),
|
.as_ref()
|
||||||
pSpecializationInfo: ptr::null(), // TODO:
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.module()
|
||||||
|
.internal_object(),
|
||||||
|
pName: self.vertex_shader.as_ref().unwrap().0.name().as_ptr(),
|
||||||
|
pSpecializationInfo: &vertex_shader_specialization as *const _,
|
||||||
});
|
});
|
||||||
|
|
||||||
match self.fragment_shader.as_ref().unwrap().ty() {
|
match self.fragment_shader.as_ref().unwrap().0.ty() {
|
||||||
GraphicsShaderType::Fragment => {},
|
GraphicsShaderType::Fragment => {},
|
||||||
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
||||||
};
|
};
|
||||||
@ -317,9 +413,14 @@ impl<Vdef,
|
|||||||
pNext: ptr::null(),
|
pNext: ptr::null(),
|
||||||
flags: 0, // reserved
|
flags: 0, // reserved
|
||||||
stage: vk::SHADER_STAGE_FRAGMENT_BIT,
|
stage: vk::SHADER_STAGE_FRAGMENT_BIT,
|
||||||
module: self.fragment_shader.as_ref().unwrap().module().internal_object(),
|
module: self.fragment_shader
|
||||||
pName: self.fragment_shader.as_ref().unwrap().name().as_ptr(),
|
.as_ref()
|
||||||
pSpecializationInfo: ptr::null(), // TODO:
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.module()
|
||||||
|
.internal_object(),
|
||||||
|
pName: self.fragment_shader.as_ref().unwrap().0.name().as_ptr(),
|
||||||
|
pSpecializationInfo: &fragment_shader_specialization as *const _,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(ref gs) = self.geometry_shader {
|
if let Some(ref gs) = self.geometry_shader {
|
||||||
@ -332,9 +433,12 @@ impl<Vdef,
|
|||||||
pNext: ptr::null(),
|
pNext: ptr::null(),
|
||||||
flags: 0, // reserved
|
flags: 0, // reserved
|
||||||
stage: vk::SHADER_STAGE_GEOMETRY_BIT,
|
stage: vk::SHADER_STAGE_GEOMETRY_BIT,
|
||||||
module: gs.module().internal_object(),
|
module: gs.0.module().internal_object(),
|
||||||
pName: gs.name().as_ptr(),
|
pName: gs.0.name().as_ptr(),
|
||||||
pSpecializationInfo: ptr::null(), // TODO:
|
pSpecializationInfo: geometry_shader_specialization
|
||||||
|
.as_ref()
|
||||||
|
.unwrap() as
|
||||||
|
*const _,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,12 +449,12 @@ impl<Vdef,
|
|||||||
return Err(GraphicsPipelineCreationError::TessellationShaderFeatureNotEnabled);
|
return Err(GraphicsPipelineCreationError::TessellationShaderFeatureNotEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
match tess.tessellation_control_shader.ty() {
|
match tess.tessellation_control_shader.0.ty() {
|
||||||
GraphicsShaderType::TessellationControl => {},
|
GraphicsShaderType::TessellationControl => {},
|
||||||
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
||||||
};
|
};
|
||||||
|
|
||||||
match tess.tessellation_evaluation_shader.ty() {
|
match tess.tessellation_evaluation_shader.0.ty() {
|
||||||
GraphicsShaderType::TessellationControl => {},
|
GraphicsShaderType::TessellationControl => {},
|
||||||
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
_ => return Err(GraphicsPipelineCreationError::WrongShaderType),
|
||||||
};
|
};
|
||||||
@ -360,9 +464,16 @@ impl<Vdef,
|
|||||||
pNext: ptr::null(),
|
pNext: ptr::null(),
|
||||||
flags: 0, // reserved
|
flags: 0, // reserved
|
||||||
stage: vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT,
|
stage: vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT,
|
||||||
module: tess.tessellation_control_shader.module().internal_object(),
|
module: tess.tessellation_control_shader
|
||||||
pName: tess.tessellation_control_shader.name().as_ptr(),
|
.0
|
||||||
pSpecializationInfo: ptr::null(), // TODO:
|
.module()
|
||||||
|
.internal_object(),
|
||||||
|
pName: tess.tessellation_control_shader.0.name().as_ptr(),
|
||||||
|
pSpecializationInfo: &tess_shader_specialization
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.0 as
|
||||||
|
*const _,
|
||||||
});
|
});
|
||||||
|
|
||||||
stages.push(vk::PipelineShaderStageCreateInfo {
|
stages.push(vk::PipelineShaderStageCreateInfo {
|
||||||
@ -371,10 +482,15 @@ impl<Vdef,
|
|||||||
flags: 0, // reserved
|
flags: 0, // reserved
|
||||||
stage: vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
|
stage: vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
|
||||||
module: tess.tessellation_evaluation_shader
|
module: tess.tessellation_evaluation_shader
|
||||||
|
.0
|
||||||
.module()
|
.module()
|
||||||
.internal_object(),
|
.internal_object(),
|
||||||
pName: tess.tessellation_evaluation_shader.name().as_ptr(),
|
pName: tess.tessellation_evaluation_shader.0.name().as_ptr(),
|
||||||
pSpecializationInfo: ptr::null(), // TODO:
|
pSpecializationInfo: &tess_shader_specialization
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.1 as
|
||||||
|
*const _,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,9 +500,8 @@ impl<Vdef,
|
|||||||
// Vertex bindings.
|
// Vertex bindings.
|
||||||
let (binding_descriptions, attribute_descriptions) = {
|
let (binding_descriptions, attribute_descriptions) = {
|
||||||
let (buffers_iter, attribs_iter) =
|
let (buffers_iter, attribs_iter) =
|
||||||
self
|
self.vertex_input
|
||||||
.vertex_input
|
.definition(self.vertex_shader.as_ref().unwrap().0.input())?;
|
||||||
.definition(self.vertex_shader.as_ref().unwrap().input())?;
|
|
||||||
|
|
||||||
let mut binding_descriptions = SmallVec::<[_; 8]>::new();
|
let mut binding_descriptions = SmallVec::<[_; 8]>::new();
|
||||||
for (num, stride, rate) in buffers_iter {
|
for (num, stride, rate) in buffers_iter {
|
||||||
@ -494,7 +609,7 @@ impl<Vdef,
|
|||||||
|
|
||||||
// TODO: should check from the tess eval shader instead of the input assembly
|
// TODO: should check from the tess eval shader instead of the input assembly
|
||||||
if let Some(ref gs) = self.geometry_shader {
|
if let Some(ref gs) = self.geometry_shader {
|
||||||
match gs.ty() {
|
match gs.0.ty() {
|
||||||
GraphicsShaderType::Geometry(primitives) => {
|
GraphicsShaderType::Geometry(primitives) => {
|
||||||
if !primitives.matches(self.input_assembly.topology) {
|
if !primitives.matches(self.input_assembly.topology) {
|
||||||
return Err(GraphicsPipelineCreationError::TopologyNotMatchingGeometryShader);
|
return Err(GraphicsPipelineCreationError::TopologyNotMatchingGeometryShader);
|
||||||
@ -760,7 +875,9 @@ impl<Vdef,
|
|||||||
_ => return Err(GraphicsPipelineCreationError::WrongStencilState),
|
_ => return Err(GraphicsPipelineCreationError::WrongStencilState),
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.depth_stencil.depth_write && !self.render_pass.as_ref().unwrap().has_writable_depth() {
|
if self.depth_stencil.depth_write &&
|
||||||
|
!self.render_pass.as_ref().unwrap().has_writable_depth()
|
||||||
|
{
|
||||||
return Err(GraphicsPipelineCreationError::NoDepthAttachment);
|
return Err(GraphicsPipelineCreationError::NoDepthAttachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,13 +926,11 @@ impl<Vdef,
|
|||||||
passOp: self.depth_stencil.stencil_front.pass_op as u32,
|
passOp: self.depth_stencil.stencil_front.pass_op as u32,
|
||||||
depthFailOp: self.depth_stencil.stencil_front.depth_fail_op as u32,
|
depthFailOp: self.depth_stencil.stencil_front.depth_fail_op as u32,
|
||||||
compareOp: self.depth_stencil.stencil_front.compare as u32,
|
compareOp: self.depth_stencil.stencil_front.compare as u32,
|
||||||
compareMask: self
|
compareMask: self.depth_stencil
|
||||||
.depth_stencil
|
|
||||||
.stencil_front
|
.stencil_front
|
||||||
.compare_mask
|
.compare_mask
|
||||||
.unwrap_or(u32::MAX),
|
.unwrap_or(u32::MAX),
|
||||||
writeMask: self
|
writeMask: self.depth_stencil
|
||||||
.depth_stencil
|
|
||||||
.stencil_front
|
.stencil_front
|
||||||
.write_mask
|
.write_mask
|
||||||
.unwrap_or(u32::MAX),
|
.unwrap_or(u32::MAX),
|
||||||
@ -826,13 +941,11 @@ impl<Vdef,
|
|||||||
passOp: self.depth_stencil.stencil_back.pass_op as u32,
|
passOp: self.depth_stencil.stencil_back.pass_op as u32,
|
||||||
depthFailOp: self.depth_stencil.stencil_back.depth_fail_op as u32,
|
depthFailOp: self.depth_stencil.stencil_back.depth_fail_op as u32,
|
||||||
compareOp: self.depth_stencil.stencil_back.compare as u32,
|
compareOp: self.depth_stencil.stencil_back.compare as u32,
|
||||||
compareMask: self
|
compareMask: self.depth_stencil
|
||||||
.depth_stencil
|
|
||||||
.stencil_back
|
.stencil_back
|
||||||
.compare_mask
|
.compare_mask
|
||||||
.unwrap_or(u32::MAX),
|
.unwrap_or(u32::MAX),
|
||||||
writeMask: self
|
writeMask: self.depth_stencil
|
||||||
.depth_stencil
|
|
||||||
.stencil_back
|
.stencil_back
|
||||||
.write_mask
|
.write_mask
|
||||||
.unwrap_or(u32::MAX),
|
.unwrap_or(u32::MAX),
|
||||||
@ -848,7 +961,9 @@ impl<Vdef,
|
|||||||
|
|
||||||
match self.blend.attachments {
|
match self.blend.attachments {
|
||||||
AttachmentsBlend::Collective(blend) => {
|
AttachmentsBlend::Collective(blend) => {
|
||||||
(0 .. num_atch).map(|_| blend.clone().into_vulkan_state()).collect()
|
(0 .. num_atch)
|
||||||
|
.map(|_| blend.clone().into_vulkan_state())
|
||||||
|
.collect()
|
||||||
},
|
},
|
||||||
AttachmentsBlend::Individual(blend) => {
|
AttachmentsBlend::Individual(blend) => {
|
||||||
if blend.len() != num_atch as usize {
|
if blend.len() != num_atch as usize {
|
||||||
@ -859,7 +974,10 @@ impl<Vdef,
|
|||||||
return Err(GraphicsPipelineCreationError::IndependentBlendFeatureNotEnabled);
|
return Err(GraphicsPipelineCreationError::IndependentBlendFeatureNotEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
blend.iter().map(|b| b.clone().into_vulkan_state()).collect()
|
blend
|
||||||
|
.iter()
|
||||||
|
.map(|b| b.clone().into_vulkan_state())
|
||||||
|
.collect()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -922,7 +1040,12 @@ impl<Vdef,
|
|||||||
.map(|s| s as *const _)
|
.map(|s| s as *const _)
|
||||||
.unwrap_or(ptr::null()),
|
.unwrap_or(ptr::null()),
|
||||||
layout: PipelineLayoutAbstract::sys(&pipeline_layout).internal_object(),
|
layout: PipelineLayoutAbstract::sys(&pipeline_layout).internal_object(),
|
||||||
renderPass: self.render_pass.as_ref().unwrap().render_pass().inner().internal_object(),
|
renderPass: self.render_pass
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.render_pass()
|
||||||
|
.inner()
|
||||||
|
.internal_object(),
|
||||||
subpass: self.render_pass.as_ref().unwrap().index(),
|
subpass: self.render_pass.as_ref().unwrap().index(),
|
||||||
basePipelineHandle: 0, // TODO:
|
basePipelineHandle: 0, // TODO:
|
||||||
basePipelineIndex: -1, // TODO:
|
basePipelineIndex: -1, // TODO:
|
||||||
@ -941,64 +1064,43 @@ impl<Vdef,
|
|||||||
let (render_pass, render_pass_subpass) = self.render_pass.take().unwrap().into();
|
let (render_pass, render_pass_subpass) = self.render_pass.take().unwrap().into();
|
||||||
|
|
||||||
Ok(GraphicsPipeline {
|
Ok(GraphicsPipeline {
|
||||||
inner: GraphicsPipelineInner {
|
inner: GraphicsPipelineInner {
|
||||||
device: device.clone(),
|
device: device.clone(),
|
||||||
pipeline: pipeline,
|
pipeline: pipeline,
|
||||||
},
|
},
|
||||||
layout: pipeline_layout,
|
layout: pipeline_layout,
|
||||||
|
|
||||||
vertex_definition: self.vertex_input,
|
vertex_definition: self.vertex_input,
|
||||||
|
|
||||||
render_pass: render_pass,
|
render_pass: render_pass,
|
||||||
render_pass_subpass: render_pass_subpass,
|
render_pass_subpass: render_pass_subpass,
|
||||||
|
|
||||||
dynamic_line_width: self.raster.line_width.is_none(),
|
dynamic_line_width: self.raster.line_width.is_none(),
|
||||||
dynamic_viewport: self.viewport.as_ref().unwrap().dynamic_viewports(),
|
dynamic_viewport: self.viewport.as_ref().unwrap().dynamic_viewports(),
|
||||||
dynamic_scissor: self.viewport.as_ref().unwrap().dynamic_scissors(),
|
dynamic_scissor: self.viewport.as_ref().unwrap().dynamic_scissors(),
|
||||||
dynamic_depth_bias: self.raster.depth_bias.is_dynamic(),
|
dynamic_depth_bias: self.raster.depth_bias.is_dynamic(),
|
||||||
dynamic_depth_bounds: self.depth_stencil.depth_bounds_test.is_dynamic(),
|
dynamic_depth_bounds: self.depth_stencil.depth_bounds_test.is_dynamic(),
|
||||||
dynamic_stencil_compare_mask: self
|
dynamic_stencil_compare_mask: self.depth_stencil.stencil_back.compare_mask.is_none(),
|
||||||
.depth_stencil
|
dynamic_stencil_write_mask: self.depth_stencil.stencil_back.write_mask.is_none(),
|
||||||
.stencil_back
|
dynamic_stencil_reference: self.depth_stencil.stencil_back.reference.is_none(),
|
||||||
.compare_mask
|
dynamic_blend_constants: self.blend.blend_constants.is_none(),
|
||||||
.is_none(),
|
|
||||||
dynamic_stencil_write_mask: self.depth_stencil.stencil_back.write_mask.is_none(),
|
|
||||||
dynamic_stencil_reference: self.depth_stencil.stencil_back.reference.is_none(),
|
|
||||||
dynamic_blend_constants: self.blend.blend_constants.is_none(),
|
|
||||||
|
|
||||||
num_viewports: self.viewport.as_ref().unwrap().num_viewports(),
|
num_viewports: self.viewport.as_ref().unwrap().num_viewports(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add build_with_cache method
|
// TODO: add build_with_cache method
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Vdef,
|
impl<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp>
|
||||||
Vs,
|
GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp> {
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp>
|
|
||||||
GraphicsPipelineBuilder<Vdef,
|
|
||||||
Vs,
|
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp> {
|
|
||||||
// TODO: add pipeline derivate system
|
// TODO: add pipeline derivate system
|
||||||
|
|
||||||
/// Sets the vertex input.
|
/// Sets the vertex input.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn vertex_input<T>(self, vertex_input: T)
|
pub fn vertex_input<T>(
|
||||||
-> GraphicsPipelineBuilder<T,
|
self, vertex_input: T)
|
||||||
Vs,
|
-> GraphicsPipelineBuilder<T, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp> {
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp> {
|
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
vertex_input: vertex_input,
|
vertex_input: vertex_input,
|
||||||
vertex_shader: self.vertex_shader,
|
vertex_shader: self.vertex_shader,
|
||||||
@ -1023,10 +1125,15 @@ impl<Vdef,
|
|||||||
pub fn vertex_input_single_buffer<V>(self)
|
pub fn vertex_input_single_buffer<V>(self)
|
||||||
-> GraphicsPipelineBuilder<SingleBufferDefinition<V>,
|
-> GraphicsPipelineBuilder<SingleBufferDefinition<V>,
|
||||||
Vs,
|
Vs,
|
||||||
|
Vss,
|
||||||
Tcs,
|
Tcs,
|
||||||
|
Tcss,
|
||||||
Tes,
|
Tes,
|
||||||
|
Tess,
|
||||||
Gs,
|
Gs,
|
||||||
|
Gss,
|
||||||
Fs,
|
Fs,
|
||||||
|
Fss,
|
||||||
Rp> {
|
Rp> {
|
||||||
self.vertex_input(SingleBufferDefinition::<V>::new())
|
self.vertex_input(SingleBufferDefinition::<V>::new())
|
||||||
}
|
}
|
||||||
@ -1034,21 +1141,15 @@ impl<Vdef,
|
|||||||
/// Sets the vertex shader to use.
|
/// Sets the vertex shader to use.
|
||||||
// TODO: correct specialization constants
|
// TODO: correct specialization constants
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn vertex_shader<Vs2>(self,
|
pub fn vertex_shader<Vs2, Vss2>(
|
||||||
shader: Vs2,
|
self, shader: Vs2, specialization_constants: Vss2)
|
||||||
specialization_constants: ())
|
-> GraphicsPipelineBuilder<Vdef, Vs2, Vss2, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp>
|
||||||
-> GraphicsPipelineBuilder<Vdef,
|
where Vs2: GraphicsEntryPointAbstract<SpecializationConstants = Vss2>,
|
||||||
Vs2,
|
Vss2: SpecializationConstants
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp>
|
|
||||||
where Vs2: GraphicsEntryPointAbstract<SpecializationConstants = ()>,
|
|
||||||
{
|
{
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
vertex_input: self.vertex_input,
|
vertex_input: self.vertex_input,
|
||||||
vertex_shader: Some(shader),
|
vertex_shader: Some((shader, specialization_constants)),
|
||||||
input_assembly: self.input_assembly,
|
input_assembly: self.input_assembly,
|
||||||
tessellation: self.tessellation,
|
tessellation: self.tessellation,
|
||||||
geometry_shader: self.geometry_shader,
|
geometry_shader: self.geometry_shader,
|
||||||
@ -1179,22 +1280,27 @@ impl<Vdef,
|
|||||||
/// Sets the tessellation shaders to use.
|
/// Sets the tessellation shaders to use.
|
||||||
// TODO: correct specialization constants
|
// TODO: correct specialization constants
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn tessellation_shaders<Tcs2, Tes2>(self,
|
pub fn tessellation_shaders<Tcs2, Tcss2, Tes2, Tess2>(
|
||||||
tessellation_control_shader: Tcs2,
|
self, tessellation_control_shader: Tcs2,
|
||||||
tessellation_control_shader_spec_constants: (),
|
tessellation_control_shader_spec_constants: Tcss2, tessellation_evaluation_shader: Tes2,
|
||||||
tessellation_evaluation_shader: Tes2,
|
tessellation_evaluation_shader_spec_constants: Tess2)
|
||||||
tessellation_evaluation_shader_spec_constants: ())
|
-> GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs2, Tcss2, Tes2, Tess2, Gs, Gss, Fs, Fss, Rp>
|
||||||
-> GraphicsPipelineBuilder<Vdef, Vs, Tcs2, Tes2, Gs, Fs, Rp>
|
where Tcs2: GraphicsEntryPointAbstract<SpecializationConstants = Tcss2>,
|
||||||
where Tcs2: GraphicsEntryPointAbstract<SpecializationConstants = ()>,
|
Tes2: GraphicsEntryPointAbstract<SpecializationConstants = Tess2>,
|
||||||
Tes2: GraphicsEntryPointAbstract<SpecializationConstants = ()>,
|
Tcss2: SpecializationConstants,
|
||||||
|
Tess2: SpecializationConstants
|
||||||
{
|
{
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
vertex_input: self.vertex_input,
|
vertex_input: self.vertex_input,
|
||||||
vertex_shader: self.vertex_shader,
|
vertex_shader: self.vertex_shader,
|
||||||
input_assembly: self.input_assembly,
|
input_assembly: self.input_assembly,
|
||||||
tessellation: Some(TessInfo {
|
tessellation: Some(TessInfo {
|
||||||
tessellation_control_shader: tessellation_control_shader,
|
tessellation_control_shader:
|
||||||
tessellation_evaluation_shader: tessellation_evaluation_shader,
|
(tessellation_control_shader,
|
||||||
|
tessellation_control_shader_spec_constants),
|
||||||
|
tessellation_evaluation_shader:
|
||||||
|
(tessellation_evaluation_shader,
|
||||||
|
tessellation_evaluation_shader_spec_constants),
|
||||||
}),
|
}),
|
||||||
geometry_shader: self.geometry_shader,
|
geometry_shader: self.geometry_shader,
|
||||||
viewport: self.viewport,
|
viewport: self.viewport,
|
||||||
@ -1217,24 +1323,18 @@ impl<Vdef,
|
|||||||
/// Sets the geometry shader to use.
|
/// Sets the geometry shader to use.
|
||||||
// TODO: correct specialization constants
|
// TODO: correct specialization constants
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn geometry_shader<Gs2>(self,
|
pub fn geometry_shader<Gs2, Gss2>(
|
||||||
shader: Gs2,
|
self, shader: Gs2, specialization_constants: Gss2)
|
||||||
specialization_constants: ())
|
-> GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs2, Gss2, Fs, Fss, Rp>
|
||||||
-> GraphicsPipelineBuilder<Vdef,
|
where Gs2: GraphicsEntryPointAbstract<SpecializationConstants = Gss2>,
|
||||||
Vs,
|
Gss2: SpecializationConstants
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs2,
|
|
||||||
Fs,
|
|
||||||
Rp>
|
|
||||||
where Gs2: GraphicsEntryPointAbstract<SpecializationConstants = ()>,
|
|
||||||
{
|
{
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
vertex_input: self.vertex_input,
|
vertex_input: self.vertex_input,
|
||||||
vertex_shader: self.vertex_shader,
|
vertex_shader: self.vertex_shader,
|
||||||
input_assembly: self.input_assembly,
|
input_assembly: self.input_assembly,
|
||||||
tessellation: self.tessellation,
|
tessellation: self.tessellation,
|
||||||
geometry_shader: Some(shader),
|
geometry_shader: Some((shader, specialization_constants)),
|
||||||
viewport: self.viewport,
|
viewport: self.viewport,
|
||||||
raster: self.raster,
|
raster: self.raster,
|
||||||
multisample: self.multisample,
|
multisample: self.multisample,
|
||||||
@ -1425,17 +1525,11 @@ impl<Vdef,
|
|||||||
/// The fragment shader is run once for each pixel that is covered by each primitive.
|
/// The fragment shader is run once for each pixel that is covered by each primitive.
|
||||||
// TODO: correct specialization constants
|
// TODO: correct specialization constants
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fragment_shader<Fs2>(self,
|
pub fn fragment_shader<Fs2, Fss2>(
|
||||||
shader: Fs2,
|
self, shader: Fs2, specialization_constants: Fss2)
|
||||||
specialization_constants: ())
|
-> GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs2, Fss2, Rp>
|
||||||
-> GraphicsPipelineBuilder<Vdef,
|
where Fs2: GraphicsEntryPointAbstract<SpecializationConstants = Fss2>,
|
||||||
Vs,
|
Fss2: SpecializationConstants
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs2,
|
|
||||||
Rp>
|
|
||||||
where Fs2: GraphicsEntryPointAbstract<SpecializationConstants = ()>,
|
|
||||||
{
|
{
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
vertex_input: self.vertex_input,
|
vertex_input: self.vertex_input,
|
||||||
@ -1446,7 +1540,7 @@ impl<Vdef,
|
|||||||
viewport: self.viewport,
|
viewport: self.viewport,
|
||||||
raster: self.raster,
|
raster: self.raster,
|
||||||
multisample: self.multisample,
|
multisample: self.multisample,
|
||||||
fragment_shader: Some(shader),
|
fragment_shader: Some((shader, specialization_constants)),
|
||||||
depth_stencil: self.depth_stencil,
|
depth_stencil: self.depth_stencil,
|
||||||
blend: self.blend,
|
blend: self.blend,
|
||||||
render_pass: self.render_pass,
|
render_pass: self.render_pass,
|
||||||
@ -1549,14 +1643,9 @@ impl<Vdef,
|
|||||||
|
|
||||||
/// Sets the render pass subpass to use.
|
/// Sets the render pass subpass to use.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn render_pass<Rp2>(self, subpass: Subpass<Rp2>)
|
pub fn render_pass<Rp2>(
|
||||||
-> GraphicsPipelineBuilder<Vdef,
|
self, subpass: Subpass<Rp2>)
|
||||||
Vs,
|
-> GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp2> {
|
||||||
Tcs,
|
|
||||||
Tes,
|
|
||||||
Gs,
|
|
||||||
Fs,
|
|
||||||
Rp2> {
|
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
vertex_input: self.vertex_input,
|
vertex_input: self.vertex_input,
|
||||||
vertex_shader: self.vertex_shader,
|
vertex_shader: self.vertex_shader,
|
||||||
@ -1574,9 +1663,20 @@ impl<Vdef,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Vdef, Vs, Tcs, Tes, Gs, Fs, Rp> Clone for
|
impl<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp> Clone
|
||||||
GraphicsPipelineBuilder<Vdef, Vs, Tcs, Tes, Gs, Fs, Rp>
|
for GraphicsPipelineBuilder<Vdef, Vs, Vss, Tcs, Tcss, Tes, Tess, Gs, Gss, Fs, Fss, Rp>
|
||||||
where Vdef: Clone, Vs: Clone, Tcs: Clone, Tes: Clone, Gs: Clone, Fs: Clone, Rp: Clone
|
where Vdef: Clone,
|
||||||
|
Vs: Clone,
|
||||||
|
Vss: Clone,
|
||||||
|
Tcs: Clone,
|
||||||
|
Tcss: Clone,
|
||||||
|
Tes: Clone,
|
||||||
|
Tess: Clone,
|
||||||
|
Gs: Clone,
|
||||||
|
Gss: Clone,
|
||||||
|
Fs: Clone,
|
||||||
|
Fss: Clone,
|
||||||
|
Rp: Clone
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
GraphicsPipelineBuilder {
|
GraphicsPipelineBuilder {
|
||||||
|
@ -84,11 +84,11 @@ impl GraphicsPipeline<(), (), ()> {
|
|||||||
/// fill with the various parameters.
|
/// fill with the various parameters.
|
||||||
pub fn start<'a>()
|
pub fn start<'a>()
|
||||||
-> GraphicsPipelineBuilder<SingleBufferDefinition<()>,
|
-> GraphicsPipelineBuilder<SingleBufferDefinition<()>,
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy, (),
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy, (),
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy, (),
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy, (),
|
||||||
EmptyEntryPointDummy,
|
EmptyEntryPointDummy, (),
|
||||||
()>
|
()>
|
||||||
{
|
{
|
||||||
GraphicsPipelineBuilder::new()
|
GraphicsPipelineBuilder::new()
|
||||||
|
Loading…
Reference in New Issue
Block a user