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