diff options
Diffstat (limited to 'src/pipeline/graphics_pipeline/mod.rs')
-rw-r--r-- | src/pipeline/graphics_pipeline/mod.rs | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/src/pipeline/graphics_pipeline/mod.rs b/src/pipeline/graphics_pipeline/mod.rs new file mode 100644 index 0000000..2082830 --- /dev/null +++ b/src/pipeline/graphics_pipeline/mod.rs @@ -0,0 +1,448 @@ +// Copyright (c) 2017 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +pub use self::builder::GraphicsPipelineBuilder; +pub use self::creation_error::GraphicsPipelineCreationError; +use crate::buffer::BufferAccess; +use crate::device::Device; +use crate::device::DeviceOwned; +use crate::pipeline::layout::PipelineLayout; +use crate::pipeline::shader::ShaderInterface; +use crate::pipeline::vertex::BufferlessDefinition; +use crate::pipeline::vertex::IncompatibleVertexDefinitionError; +use crate::pipeline::vertex::VertexDefinition; +use crate::pipeline::vertex::VertexInput; +use crate::pipeline::vertex::VertexSource; +use crate::render_pass::RenderPass; +use crate::render_pass::Subpass; +use crate::SafeDeref; +use crate::VulkanObject; +use std::fmt; +use std::hash::Hash; +use std::hash::Hasher; +use std::marker::PhantomData; +use std::ptr; +use std::sync::Arc; +use std::u32; + +mod builder; +mod creation_error; +// FIXME: restore +//mod tests; + +/// Defines how the implementation should perform a draw operation. +/// +/// This object contains the shaders and the various fixed states that describe how the +/// implementation should perform the various operations needed by a draw command. +pub struct GraphicsPipeline<VertexDefinition> { + inner: Inner, + layout: Arc<PipelineLayout>, + subpass: Subpass, + vertex_definition: VertexDefinition, + vertex_input: VertexInput, + + dynamic_line_width: bool, + dynamic_viewport: bool, + dynamic_scissor: bool, + dynamic_depth_bias: bool, + dynamic_depth_bounds: bool, + dynamic_stencil_compare_mask: bool, + dynamic_stencil_write_mask: bool, + dynamic_stencil_reference: bool, + dynamic_blend_constants: bool, + + num_viewports: u32, +} + +#[derive(PartialEq, Eq, Hash)] +struct Inner { + pipeline: ash::vk::Pipeline, + device: Arc<Device>, +} + +impl GraphicsPipeline<()> { + /// Starts the building process of a graphics pipeline. Returns a builder object that you can + /// fill with the various parameters. + pub fn start<'a>() -> GraphicsPipelineBuilder< + 'static, + 'static, + 'static, + 'static, + 'static, + BufferlessDefinition, + (), + (), + (), + (), + (), + > { + GraphicsPipelineBuilder::new() + } +} + +impl<Mv> GraphicsPipeline<Mv> { + /// Returns the vertex definition used in the constructor. + #[inline] + pub fn vertex_definition(&self) -> &Mv { + &self.vertex_definition + } + + /// Returns the device used to create this pipeline. + #[inline] + pub fn device(&self) -> &Arc<Device> { + &self.inner.device + } + + /// Returns the pass used in the constructor. + #[inline] + pub fn subpass(&self) -> Subpass { + self.subpass.clone() + } + + /// Returns the render pass used in the constructor. + #[inline] + pub fn render_pass(&self) -> &Arc<RenderPass> { + self.subpass.render_pass() + } + + /// Returns true if the line width used by this pipeline is dynamic. + #[inline] + pub fn has_dynamic_line_width(&self) -> bool { + self.dynamic_line_width + } + + /// Returns the number of viewports and scissors of this pipeline. + #[inline] + pub fn num_viewports(&self) -> u32 { + self.num_viewports + } + + /// Returns true if the viewports used by this pipeline are dynamic. + #[inline] + pub fn has_dynamic_viewports(&self) -> bool { + self.dynamic_viewport + } + + /// Returns true if the scissors used by this pipeline are dynamic. + #[inline] + pub fn has_dynamic_scissors(&self) -> bool { + self.dynamic_scissor + } + + /// Returns true if the depth bounds used by this pipeline are dynamic. + #[inline] + pub fn has_dynamic_depth_bounds(&self) -> bool { + self.dynamic_depth_bounds + } + + /// Returns true if the stencil compare masks used by this pipeline are dynamic. + #[inline] + pub fn has_dynamic_stencil_compare_mask(&self) -> bool { + self.dynamic_stencil_compare_mask + } + + /// Returns true if the stencil write masks used by this pipeline are dynamic. + #[inline] + pub fn has_dynamic_stencil_write_mask(&self) -> bool { + self.dynamic_stencil_write_mask + } + + /// Returns true if the stencil references used by this pipeline are dynamic. + #[inline] + pub fn has_dynamic_stencil_reference(&self) -> bool { + self.dynamic_stencil_reference + } +} + +unsafe impl<Mv> DeviceOwned for GraphicsPipeline<Mv> { + #[inline] + fn device(&self) -> &Arc<Device> { + &self.inner.device + } +} + +impl<Mv> fmt::Debug for GraphicsPipeline<Mv> { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(fmt, "<Vulkan graphics pipeline {:?}>", self.inner.pipeline) + } +} + +unsafe impl<Mv> VulkanObject for GraphicsPipeline<Mv> { + type Object = ash::vk::Pipeline; + + #[inline] + fn internal_object(&self) -> ash::vk::Pipeline { + self.inner.pipeline + } +} + +impl Drop for Inner { + #[inline] + fn drop(&mut self) { + unsafe { + let fns = self.device.fns(); + fns.v1_0 + .destroy_pipeline(self.device.internal_object(), self.pipeline, ptr::null()); + } + } +} + +/// Trait implemented on objects that reference a graphics pipeline. Can be made into a trait +/// object. +/// When using this trait `AutoCommandBufferBuilder::draw*` calls will need the buffers to be +/// wrapped in a `vec!()`. +pub unsafe trait GraphicsPipelineAbstract: + VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>> + DeviceOwned +{ + /// Returns an opaque object that represents the inside of the graphics pipeline. + fn inner(&self) -> GraphicsPipelineSys; + + /// Returns the pipeline layout used in the constructor. + fn layout(&self) -> &Arc<PipelineLayout>; + + /// Returns the subpass this graphics pipeline is rendering to. + fn subpass(&self) -> &Subpass; + + /// Returns the vertex input description of the graphics pipeline. + fn vertex_input(&self) -> &VertexInput; + + /// Returns true if the line width used by this pipeline is dynamic. + fn has_dynamic_line_width(&self) -> bool; + + /// Returns the number of viewports and scissors of this pipeline. + fn num_viewports(&self) -> u32; + + /// Returns true if the viewports used by this pipeline are dynamic. + fn has_dynamic_viewports(&self) -> bool; + + /// Returns true if the scissors used by this pipeline are dynamic. + fn has_dynamic_scissors(&self) -> bool; + + /// Returns true if the depth bounds used by this pipeline are dynamic. + fn has_dynamic_depth_bounds(&self) -> bool; + + /// Returns true if the stencil compare masks used by this pipeline are dynamic. + fn has_dynamic_stencil_compare_mask(&self) -> bool; + + /// Returns true if the stencil write masks used by this pipeline are dynamic. + fn has_dynamic_stencil_write_mask(&self) -> bool; + + /// Returns true if the stencil references used by this pipeline are dynamic. + fn has_dynamic_stencil_reference(&self) -> bool; +} + +unsafe impl<Mv> GraphicsPipelineAbstract for GraphicsPipeline<Mv> +where + Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>, +{ + #[inline] + fn inner(&self) -> GraphicsPipelineSys { + GraphicsPipelineSys(self.inner.pipeline, PhantomData) + } + + /// Returns the pipeline layout used in the constructor. + #[inline] + fn layout(&self) -> &Arc<PipelineLayout> { + &self.layout + } + + #[inline] + fn subpass(&self) -> &Subpass { + &self.subpass + } + + #[inline] + fn vertex_input(&self) -> &VertexInput { + &self.vertex_input + } + + #[inline] + fn has_dynamic_line_width(&self) -> bool { + self.dynamic_line_width + } + + #[inline] + fn num_viewports(&self) -> u32 { + self.num_viewports + } + + #[inline] + fn has_dynamic_viewports(&self) -> bool { + self.dynamic_viewport + } + + #[inline] + fn has_dynamic_scissors(&self) -> bool { + self.dynamic_scissor + } + + #[inline] + fn has_dynamic_depth_bounds(&self) -> bool { + self.dynamic_depth_bounds + } + + #[inline] + fn has_dynamic_stencil_compare_mask(&self) -> bool { + self.dynamic_stencil_compare_mask + } + + #[inline] + fn has_dynamic_stencil_write_mask(&self) -> bool { + self.dynamic_stencil_write_mask + } + + #[inline] + fn has_dynamic_stencil_reference(&self) -> bool { + self.dynamic_stencil_reference + } +} + +unsafe impl<T> GraphicsPipelineAbstract for T +where + T: SafeDeref, + T::Target: GraphicsPipelineAbstract, +{ + #[inline] + fn inner(&self) -> GraphicsPipelineSys { + GraphicsPipelineAbstract::inner(&**self) + } + + #[inline] + fn layout(&self) -> &Arc<PipelineLayout> { + (**self).layout() + } + + #[inline] + fn subpass(&self) -> &Subpass { + (**self).subpass() + } + + #[inline] + fn vertex_input(&self) -> &VertexInput { + (**self).vertex_input() + } + + #[inline] + fn has_dynamic_line_width(&self) -> bool { + (**self).has_dynamic_line_width() + } + + #[inline] + fn num_viewports(&self) -> u32 { + (**self).num_viewports() + } + + #[inline] + fn has_dynamic_viewports(&self) -> bool { + (**self).has_dynamic_viewports() + } + + #[inline] + fn has_dynamic_scissors(&self) -> bool { + (**self).has_dynamic_scissors() + } + + #[inline] + fn has_dynamic_depth_bounds(&self) -> bool { + (**self).has_dynamic_depth_bounds() + } + + #[inline] + fn has_dynamic_stencil_compare_mask(&self) -> bool { + (**self).has_dynamic_stencil_compare_mask() + } + + #[inline] + fn has_dynamic_stencil_write_mask(&self) -> bool { + (**self).has_dynamic_stencil_write_mask() + } + + #[inline] + fn has_dynamic_stencil_reference(&self) -> bool { + (**self).has_dynamic_stencil_reference() + } +} + +impl<Mv> PartialEq for GraphicsPipeline<Mv> +where + Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } +} + +impl<Mv> Eq for GraphicsPipeline<Mv> where Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>> +{} + +impl<Mv> Hash for GraphicsPipeline<Mv> +where + Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>, +{ + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + self.inner.hash(state); + } +} + +impl PartialEq for dyn GraphicsPipelineAbstract + Send + Sync { + #[inline] + fn eq(&self, other: &Self) -> bool { + GraphicsPipelineAbstract::inner(self).0 == GraphicsPipelineAbstract::inner(other).0 + && DeviceOwned::device(self) == DeviceOwned::device(other) + } +} + +impl Eq for dyn GraphicsPipelineAbstract + Send + Sync {} + +impl Hash for dyn GraphicsPipelineAbstract + Send + Sync { + #[inline] + fn hash<H: Hasher>(&self, state: &mut H) { + GraphicsPipelineAbstract::inner(self).0.hash(state); + DeviceOwned::device(self).hash(state); + } +} + +/// Opaque object that represents the inside of the graphics pipeline. +#[derive(Debug, Copy, Clone)] +pub struct GraphicsPipelineSys<'a>(ash::vk::Pipeline, PhantomData<&'a ()>); + +unsafe impl<'a> VulkanObject for GraphicsPipelineSys<'a> { + type Object = ash::vk::Pipeline; + + #[inline] + fn internal_object(&self) -> ash::vk::Pipeline { + self.0 + } +} + +unsafe impl<Mv> VertexDefinition for GraphicsPipeline<Mv> +where + Mv: VertexDefinition, +{ + #[inline] + fn definition( + &self, + interface: &ShaderInterface, + ) -> Result<VertexInput, IncompatibleVertexDefinitionError> { + self.vertex_definition.definition(interface) + } +} + +unsafe impl<Mv, S> VertexSource<S> for GraphicsPipeline<Mv> +where + Mv: VertexSource<S>, +{ + #[inline] + fn decode(&self, s: S) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize) { + self.vertex_definition.decode(s) + } +} |