blob: 2082830fe58d4f3e2f0eb72bff6de0564f8a45dc [file] [log] [blame]
// 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)
}
}