diff options
author | Kaiyi Li <kaiyili@google.com> | 2023-08-03 22:20:57 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-08-03 22:20:57 +0000 |
commit | 308c941f21a4d9a4bf66f64c811b91237922c2e6 (patch) | |
tree | f204b748c5dd920d6176f3d0e10b820dafbb5784 /src/pipeline/graphics/mod.rs | |
parent | 45f20af9022b6c3786a61123a169bb355053ee5a (diff) | |
parent | 0f5fd0001fdc80b81802004262fdf62405329a3c (diff) | |
download | vulkano-308c941f21a4d9a4bf66f64c811b91237922c2e6.tar.gz |
Upgrade vulkano to 0.33.0 am: cfa3173d1d am: 6fb41c608d am: 570756a047 am: 0f5fd0001f
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/vulkano/+/2690275
Change-Id: Ib65dfbc52fe90e151ca7e4ec13ff1af8e498a582
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'src/pipeline/graphics/mod.rs')
-rw-r--r-- | src/pipeline/graphics/mod.rs | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/src/pipeline/graphics/mod.rs b/src/pipeline/graphics/mod.rs new file mode 100644 index 0000000..a85e8b5 --- /dev/null +++ b/src/pipeline/graphics/mod.rs @@ -0,0 +1,302 @@ +// 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. + +//! A pipeline that performs graphics processing operations. +//! +//! Unlike a compute pipeline, which performs general-purpose work, a graphics pipeline is geared +//! specifically towards doing graphical processing. To that end, it consists of several shaders, +//! with additional state and glue logic in between. +//! +//! A graphics pipeline performs many separate steps, that execute more or less in sequence. +//! Due to the parallel nature of a GPU, no strict ordering guarantees may exist. +//! +//! 1. Vertex input and assembly: vertex input data is read from data buffers and then assembled +//! into primitives (points, lines, triangles etc.). +//! 2. Vertex shader invocations: the vertex data of each primitive is fed as input to the vertex +//! shader, which performs transformations on the data and generates new data as output. +//! 3. (Optional) Tessellation: primitives are subdivided by the operations of two shaders, the +//! tessellation control and tessellation evaluation shaders. The control shader produces the +//! tessellation level to apply for the primitive, while the evaluation shader postprocesses the +//! newly created vertices. +//! 4. (Optional) Geometry shading: whole primitives are fed as input and processed into a new set +//! of output primitives. +//! 5. Vertex post-processing, including: +//! - Clipping primitives to the view frustum and user-defined clipping planes. +//! - Perspective division. +//! - Viewport mapping. +//! 6. Rasterization: converting primitives into a two-dimensional representation. Primitives may be +//! discarded depending on their orientation, and are then converted into a collection of +//! fragments that are processed further. +//! 7. Fragment operations. These include invocations of the fragment shader, which generates the +//! values to be written to the color attachment. Various testing and discarding operations can +//! be performed both before and after the fragment shader ("early" and "late" fragment tests), +//! including: +//! - Discard rectangle test +//! - Scissor test +//! - Sample mask test +//! - Depth bounds test +//! - Stencil test +//! - Depth test +//! 8. Color attachment output: the final pixel data is written to a framebuffer. Blending and +//! logical operations can be applied to combine incoming pixel data with data already present +//! in the framebuffer. +//! +//! A graphics pipeline contains many configuration options, which are grouped into collections of +//! "state". Often, these directly correspond to one or more steps in the graphics pipeline. Each +//! state collection has a dedicated submodule. +//! +//! Once a graphics pipeline has been created, you can execute it by first *binding* it in a command +//! buffer, binding the necessary vertex buffers, binding any descriptor sets, setting push +//! constants, and setting any dynamic state that the pipeline may need. Then you issue a `draw` +//! command. + +pub use self::{builder::GraphicsPipelineBuilder, creation_error::GraphicsPipelineCreationError}; +use self::{ + color_blend::ColorBlendState, depth_stencil::DepthStencilState, + discard_rectangle::DiscardRectangleState, input_assembly::InputAssemblyState, + multisample::MultisampleState, rasterization::RasterizationState, + render_pass::PipelineRenderPassType, tessellation::TessellationState, + vertex_input::VertexInputState, viewport::ViewportState, +}; +use super::{DynamicState, Pipeline, PipelineBindPoint, PipelineLayout}; +use crate::{ + device::{Device, DeviceOwned}, + macros::impl_id_counter, + shader::{DescriptorBindingRequirements, FragmentTestsStages, ShaderStage}, + VulkanObject, +}; +use ahash::HashMap; +use std::{ + fmt::{Debug, Error as FmtError, Formatter}, + num::NonZeroU64, + ptr, + sync::Arc, +}; + +mod builder; +pub mod color_blend; +mod creation_error; +pub mod depth_stencil; +pub mod discard_rectangle; +pub mod input_assembly; +pub mod multisample; +pub mod rasterization; +pub mod render_pass; +pub mod tessellation; +pub mod vertex_input; +pub mod viewport; +// 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 { + handle: ash::vk::Pipeline, + device: Arc<Device>, + id: NonZeroU64, + layout: Arc<PipelineLayout>, + render_pass: PipelineRenderPassType, + + // TODO: replace () with an object that describes the shaders in some way. + shaders: HashMap<ShaderStage, ()>, + descriptor_binding_requirements: HashMap<(u32, u32), DescriptorBindingRequirements>, + num_used_descriptor_sets: u32, + fragment_tests_stages: Option<FragmentTestsStages>, + + vertex_input_state: VertexInputState, + input_assembly_state: InputAssemblyState, + tessellation_state: Option<TessellationState>, + viewport_state: Option<ViewportState>, + discard_rectangle_state: Option<DiscardRectangleState>, + rasterization_state: RasterizationState, + multisample_state: Option<MultisampleState>, + depth_stencil_state: Option<DepthStencilState>, + color_blend_state: Option<ColorBlendState>, + dynamic_state: HashMap<DynamicState, bool>, +} + +impl GraphicsPipeline { + /// Starts the building process of a graphics pipeline. Returns a builder object that you can + /// fill with the various parameters. + #[inline] + pub fn start() -> GraphicsPipelineBuilder< + 'static, + 'static, + 'static, + 'static, + 'static, + VertexInputState, + (), + (), + (), + (), + (), + > { + GraphicsPipelineBuilder::new() + } + + /// Returns the device used to create this pipeline. + #[inline] + pub fn device(&self) -> &Arc<Device> { + &self.device + } + + /// Returns the render pass this graphics pipeline is rendering to. + #[inline] + pub fn render_pass(&self) -> &PipelineRenderPassType { + &self.render_pass + } + + /// Returns information about a particular shader. + /// + /// `None` is returned if the pipeline does not contain this shader. + /// + /// Compatibility note: `()` is temporary, it will be replaced with something else in the + /// future. + // TODO: ^ implement and make this public + #[inline] + pub(crate) fn shader(&self, stage: ShaderStage) -> Option<()> { + self.shaders.get(&stage).copied() + } + + /// Returns the vertex input state used to create this pipeline. + #[inline] + pub fn vertex_input_state(&self) -> &VertexInputState { + &self.vertex_input_state + } + + /// Returns the input assembly state used to create this pipeline. + #[inline] + pub fn input_assembly_state(&self) -> &InputAssemblyState { + &self.input_assembly_state + } + + /// Returns the tessellation state used to create this pipeline. + #[inline] + pub fn tessellation_state(&self) -> Option<&TessellationState> { + self.tessellation_state.as_ref() + } + + /// Returns the viewport state used to create this pipeline. + #[inline] + pub fn viewport_state(&self) -> Option<&ViewportState> { + self.viewport_state.as_ref() + } + + /// Returns the discard rectangle state used to create this pipeline. + #[inline] + pub fn discard_rectangle_state(&self) -> Option<&DiscardRectangleState> { + self.discard_rectangle_state.as_ref() + } + + /// Returns the rasterization state used to create this pipeline. + #[inline] + pub fn rasterization_state(&self) -> &RasterizationState { + &self.rasterization_state + } + + /// Returns the multisample state used to create this pipeline. + #[inline] + pub fn multisample_state(&self) -> Option<&MultisampleState> { + self.multisample_state.as_ref() + } + + /// Returns the depth/stencil state used to create this pipeline. + #[inline] + pub fn depth_stencil_state(&self) -> Option<&DepthStencilState> { + self.depth_stencil_state.as_ref() + } + + /// Returns the color blend state used to create this pipeline. + #[inline] + pub fn color_blend_state(&self) -> Option<&ColorBlendState> { + self.color_blend_state.as_ref() + } + + /// Returns whether a particular state is must be dynamically set. + /// + /// `None` is returned if the pipeline does not contain this state. Previously set dynamic + /// state is not disturbed when binding it. + #[inline] + pub fn dynamic_state(&self, state: DynamicState) -> Option<bool> { + self.dynamic_state.get(&state).copied() + } + + /// Returns all potentially dynamic states in the pipeline, and whether they are dynamic or not. + #[inline] + pub fn dynamic_states(&self) -> impl ExactSizeIterator<Item = (DynamicState, bool)> + '_ { + self.dynamic_state.iter().map(|(k, v)| (*k, *v)) + } + + /// If the pipeline has a fragment shader, returns the fragment tests stages used. + #[inline] + pub fn fragment_tests_stages(&self) -> Option<FragmentTestsStages> { + self.fragment_tests_stages + } +} + +impl Pipeline for GraphicsPipeline { + #[inline] + fn bind_point(&self) -> PipelineBindPoint { + PipelineBindPoint::Graphics + } + + #[inline] + fn layout(&self) -> &Arc<PipelineLayout> { + &self.layout + } + + #[inline] + fn num_used_descriptor_sets(&self) -> u32 { + self.num_used_descriptor_sets + } + + #[inline] + fn descriptor_binding_requirements( + &self, + ) -> &HashMap<(u32, u32), DescriptorBindingRequirements> { + &self.descriptor_binding_requirements + } +} + +unsafe impl DeviceOwned for GraphicsPipeline { + #[inline] + fn device(&self) -> &Arc<Device> { + &self.device + } +} + +impl Debug for GraphicsPipeline { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!(f, "<Vulkan graphics pipeline {:?}>", self.handle) + } +} + +unsafe impl VulkanObject for GraphicsPipeline { + type Handle = ash::vk::Pipeline; + + #[inline] + fn handle(&self) -> Self::Handle { + self.handle + } +} + +impl Drop for GraphicsPipeline { + #[inline] + fn drop(&mut self) { + unsafe { + let fns = self.device.fns(); + (fns.v1_0.destroy_pipeline)(self.device.handle(), self.handle, ptr::null()); + } + } +} + +impl_id_counter!(GraphicsPipeline); |