gfx_hal/pso/mod.rs
1//! Raw Pipeline State Objects
2//!
3//! This module contains items used to create and manage Pipelines.
4
5use crate::{device, pass, Backend};
6
7mod compute;
8mod descriptor;
9mod graphics;
10mod input_assembler;
11mod output_merger;
12mod specialization;
13
14pub use self::{
15 compute::*, descriptor::*, graphics::*, input_assembler::*, output_merger::*, specialization::*,
16};
17
18/// Error types happening upon PSO creation on the device side.
19#[derive(Clone, Debug, PartialEq, thiserror::Error)]
20pub enum CreationError {
21 /// Unknown other error.
22 #[error("Implementation specific error occurred")]
23 Other,
24 /// Shader module creation error.
25 #[error("{0:?} shader creation failed: {1:}")]
26 ShaderCreationError(ShaderStageFlags, String),
27 /// Unsupported pipeline on hardware or implementation. Example: mesh shaders on DirectX 11.
28 #[error("Pipeline kind is not supported")]
29 UnsupportedPipeline,
30 /// Invalid subpass (not part of renderpass).
31 #[error("Invalid subpass: {0:?}")]
32 InvalidSubpass(pass::SubpassId),
33 /// The shader is missing an entry point.
34 #[error("Invalid entry point: {0:}")]
35 MissingEntryPoint(String),
36 /// The specialization values are incorrect.
37 #[error("Specialization failed: {0:}")]
38 InvalidSpecialization(String),
39 /// Out of either host or device memory.
40 #[error(transparent)]
41 OutOfMemory(#[from] device::OutOfMemory),
42}
43
44bitflags!(
45 /// Stages of the logical pipeline.
46 ///
47 /// The pipeline is structured by the ordering of the flags.
48 /// Some stages are queue type dependent.
49 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
50 pub struct PipelineStage: u32 {
51 /// Beginning of the command queue.
52 const TOP_OF_PIPE = 0x1;
53 /// Indirect data consumption.
54 const DRAW_INDIRECT = 0x2;
55 /// Vertex data consumption.
56 const VERTEX_INPUT = 0x4;
57 /// Vertex shader execution.
58 const VERTEX_SHADER = 0x8;
59 /// Hull shader execution.
60 const HULL_SHADER = 0x10;
61 /// Domain shader execution.
62 const DOMAIN_SHADER = 0x20;
63 /// Geometry shader execution.
64 const GEOMETRY_SHADER = 0x40;
65 /// Fragment shader execution.
66 const FRAGMENT_SHADER = 0x80;
67 /// Stage of early depth and stencil test.
68 const EARLY_FRAGMENT_TESTS = 0x100;
69 /// Stage of late depth and stencil test.
70 const LATE_FRAGMENT_TESTS = 0x200;
71 /// Stage of final color value calculation.
72 const COLOR_ATTACHMENT_OUTPUT = 0x400;
73 /// Compute shader execution,
74 const COMPUTE_SHADER = 0x800;
75 /// Copy/Transfer command execution.
76 const TRANSFER = 0x1000;
77 /// End of the command queue.
78 const BOTTOM_OF_PIPE = 0x2000;
79 /// Read/Write access from host.
80 /// (Not a real pipeline stage)
81 const HOST = 0x4000;
82 /// Task shader stage.
83 const TASK_SHADER = 0x80000;
84 /// Mesh shader stage.
85 const MESH_SHADER = 0x100000;
86 }
87);
88
89bitflags!(
90 /// Combination of different shader pipeline stages.
91 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
92 #[derive(Default)]
93 pub struct ShaderStageFlags: u32 {
94 /// Vertex shader stage.
95 const VERTEX = 0x1;
96 /// Hull (tessellation) shader stage.
97 const HULL = 0x2;
98 /// Domain (tessellation) shader stage.
99 const DOMAIN = 0x4;
100 /// Geometry shader stage.
101 const GEOMETRY = 0x8;
102 /// Fragment shader stage.
103 const FRAGMENT = 0x10;
104 /// Compute shader stage.
105 const COMPUTE = 0x20;
106 /// Task shader stage.
107 const TASK = 0x40;
108 /// Mesh shader stage.
109 const MESH = 0x80;
110 /// All graphics pipeline shader stages.
111 const GRAPHICS = Self::VERTEX.bits | Self::HULL.bits |
112 Self::DOMAIN.bits | Self::GEOMETRY.bits | Self::FRAGMENT.bits;
113 /// All shader stages (matches Vulkan).
114 const ALL = 0x7FFFFFFF;
115 }
116);
117
118impl From<naga::ShaderStage> for ShaderStageFlags {
119 fn from(stage: naga::ShaderStage) -> Self {
120 use naga::ShaderStage as Ss;
121 match stage {
122 Ss::Vertex => Self::VERTEX,
123 Ss::Fragment => Self::FRAGMENT,
124 Ss::Compute => Self::COMPUTE,
125 }
126 }
127}
128
129/// Shader entry point.
130#[derive(Debug)]
131pub struct EntryPoint<'a, B: Backend> {
132 /// Entry point name.
133 pub entry: &'a str,
134 /// Reference to the shader module containing this entry point.
135 pub module: &'a B::ShaderModule,
136 /// Specialization constants to be used when creating the pipeline.
137 pub specialization: Specialization<'a>,
138}
139
140impl<'a, B: Backend> Clone for EntryPoint<'a, B> {
141 fn clone(&self) -> Self {
142 EntryPoint {
143 entry: self.entry,
144 module: self.module,
145 specialization: self.specialization.clone(),
146 }
147 }
148}
149
150bitflags!(
151 /// Pipeline creation flags.
152 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
153 pub struct PipelineCreationFlags: u32 {
154 /// Disable pipeline optimizations.
155 ///
156 /// May speedup pipeline creation.
157 const DISABLE_OPTIMIZATION = 0x1;
158 /// Allow derivatives (children) of the pipeline.
159 ///
160 /// Must be set when pipelines set the pipeline as base.
161 const ALLOW_DERIVATIVES = 0x2;
162 }
163);
164
165/// A reference to a parent pipeline. The assumption is that
166/// a parent and derivative/child pipeline have most settings
167/// in common, and one may be switched for another more quickly
168/// than entirely unrelated pipelines would be.
169#[derive(Debug)]
170pub enum BasePipeline<'a, P: 'a> {
171 /// Referencing an existing pipeline as parent.
172 Pipeline(&'a P),
173 /// A pipeline in the same create pipelines call.
174 ///
175 /// The index of the parent must be lower than the index of the child.
176 Index(usize),
177 /// No parent pipeline exists.
178 None,
179}
180
181/// Pipeline state which may be static or dynamic.
182#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
183#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
184pub enum State<T> {
185 /// Static state that cannot be altered.
186 Static(T),
187 /// Dynamic state set through a command buffer.
188 Dynamic,
189}
190
191impl<T> State<T> {
192 /// Returns the static value or a default.
193 pub fn static_or(self, default: T) -> T {
194 match self {
195 State::Static(v) => v,
196 State::Dynamic => default,
197 }
198 }
199
200 /// Whether the state is static.
201 pub fn is_static(self) -> bool {
202 match self {
203 State::Static(_) => true,
204 State::Dynamic => false,
205 }
206 }
207
208 /// Whether the state is dynamic.
209 pub fn is_dynamic(self) -> bool {
210 !self.is_static()
211 }
212}