1 // Copyright (c) 2017 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use super::vertex_input::IncompatibleVertexDefinitionError;
11 use crate::{
12     descriptor_set::layout::DescriptorSetLayoutCreationError,
13     format::{Format, NumericType},
14     pipeline::layout::{PipelineLayoutCreationError, PipelineLayoutSupersetError},
15     shader::{ShaderInterfaceMismatchError, ShaderScalarType},
16     OomError, RequirementNotMet, RequiresOneOf, VulkanError,
17 };
18 use std::{
19     error::Error,
20     fmt::{Display, Error as FmtError, Formatter},
21 };
22 
23 /// Error that can happen when creating a graphics pipeline.
24 #[derive(Clone, Debug, PartialEq, Eq)]
25 pub enum GraphicsPipelineCreationError {
26     RequirementNotMet {
27         required_for: &'static str,
28         requires_one_of: RequiresOneOf,
29     },
30 
31     /// A color attachment has a format that does not support blending.
32     ColorAttachmentFormatBlendNotSupported { attachment_index: u32 },
33 
34     /// A color attachment has a format that does not support that usage.
35     ColorAttachmentFormatUsageNotSupported { attachment_index: u32 },
36 
37     /// The depth attachment has a format that does not support that usage.
38     DepthAttachmentFormatUsageNotSupported,
39 
40     /// The depth and stencil attachments have different formats.
41     DepthStencilAttachmentFormatMismatch,
42 
43     /// The output of the fragment shader is not compatible with what the render pass subpass
44     /// expects.
45     FragmentShaderRenderPassIncompatible,
46 
47     /// The pipeline layout is not compatible with what the shaders expect.
48     IncompatiblePipelineLayout(PipelineLayoutSupersetError),
49 
50     /// The provided specialization constants are not compatible with what the shader expects.
51     IncompatibleSpecializationConstants,
52 
53     /// The vertex definition is not compatible with the input of the vertex shader.
54     IncompatibleVertexDefinition(IncompatibleVertexDefinitionError),
55 
56     /// Tried to use a patch list without a tessellation shader, or a non-patch-list with a
57     /// tessellation shader.
58     InvalidPrimitiveTopology,
59 
60     /// `patch_control_points` was not greater than 0 and less than or equal to the `max_tessellation_patch_size` limit.
61     InvalidNumPatchControlPoints,
62 
63     /// The maximum number of discard rectangles has been exceeded.
64     MaxDiscardRectanglesExceeded {
65         /// Maximum allowed value.
66         max: u32,
67         /// Value that was passed.
68         obtained: u32,
69     },
70 
71     /// The `max_multiview_view_count` limit has been exceeded.
72     MaxMultiviewViewCountExceeded { view_count: u32, max: u32 },
73 
74     /// The maximum value for the instance rate divisor has been exceeded.
75     MaxVertexAttribDivisorExceeded {
76         /// Index of the faulty binding.
77         binding: u32,
78         /// Maximum allowed value.
79         max: u32,
80         /// Value that was passed.
81         obtained: u32,
82     },
83 
84     /// The maximum number of vertex attributes has been exceeded.
85     MaxVertexInputAttributesExceeded {
86         /// Maximum allowed value.
87         max: u32,
88         /// Value that was passed.
89         obtained: usize,
90     },
91 
92     /// The maximum offset for a vertex attribute has been exceeded. This means that your vertex
93     /// struct is too large.
94     MaxVertexInputAttributeOffsetExceeded {
95         /// Maximum allowed value.
96         max: u32,
97         /// Value that was passed.
98         obtained: u32,
99     },
100 
101     /// The maximum number of vertex sources has been exceeded.
102     MaxVertexInputBindingsExceeded {
103         /// Maximum allowed value.
104         max: u32,
105         /// Value that was passed.
106         obtained: u32,
107     },
108 
109     /// The maximum stride value for vertex input (ie. the distance between two vertex elements)
110     /// has been exceeded.
111     MaxVertexInputBindingStrideExceeded {
112         /// Index of the faulty binding.
113         binding: u32,
114         /// Maximum allowed value.
115         max: u32,
116         /// Value that was passed.
117         obtained: u32,
118     },
119 
120     /// The maximum number of viewports has been exceeded.
121     MaxViewportsExceeded {
122         /// Maximum allowed value.
123         max: u32,
124         /// Value that was passed.
125         obtained: u32,
126     },
127 
128     /// The `min_vertex_input_binding_stride_alignment` limit was exceeded.
129     MinVertexInputBindingStrideAlignmentExceeded {
130         /// Index of the faulty binding.
131         binding: u32,
132         /// Maximum allowed value.
133         max: u32,
134         /// Value that was passed.
135         obtained: u32,
136     },
137 
138     /// The maximum dimensions of viewports has been exceeded.
139     MaxViewportDimensionsExceeded,
140 
141     /// The number of attachments specified in the blending does not match the number of
142     /// attachments in the subpass.
143     MismatchBlendingAttachmentsCount,
144 
145     /// The provided `rasterization_samples` does not match the number of samples of the render
146     /// subpass.
147     MultisampleRasterizationSamplesMismatch,
148 
149     /// The depth test requires a depth attachment but render pass has no depth attachment, or
150     /// depth writing is enabled and the depth attachment is read-only.
151     NoDepthAttachment,
152 
153     /// The stencil test requires a stencil attachment but render pass has no stencil attachment, or
154     /// stencil writing is enabled and the stencil attachment is read-only.
155     NoStencilAttachment,
156 
157     /// Not enough memory.
158     OomError(OomError),
159 
160     /// Error while creating a descriptor set layout object.
161     DescriptorSetLayoutCreationError(DescriptorSetLayoutCreationError),
162 
163     /// Error while creating the pipeline layout object.
164     PipelineLayoutCreationError(PipelineLayoutCreationError),
165 
166     /// The output interface of one shader and the input interface of the next shader do not match.
167     ShaderStagesMismatch(ShaderInterfaceMismatchError),
168 
169     /// The stencil attachment has a format that does not support that usage.
170     StencilAttachmentFormatUsageNotSupported,
171 
172     /// The [`strict_lines`](crate::device::Properties::strict_lines) device property was `false`.
173     StrictLinesNotSupported,
174 
175     /// The primitives topology does not match what the geometry shader expects.
176     TopologyNotMatchingGeometryShader,
177 
178     /// The type of the shader input variable at the given location is not compatible with the
179     /// format of the corresponding vertex input attribute.
180     VertexInputAttributeIncompatibleFormat {
181         location: u32,
182         shader_type: ShaderScalarType,
183         attribute_type: NumericType,
184     },
185 
186     /// The location provided is assigned, but expected to unassigned due to the format of the
187     /// prior location.
188     VertexInputAttributeInvalidAssignedLocation { location: u32 },
189 
190     /// The binding number specified by a vertex input attribute does not exist in the provided list
191     /// of binding descriptions.
192     VertexInputAttributeInvalidBinding { location: u32, binding: u32 },
193 
194     /// The vertex shader expects an input variable at the given location, but no vertex input
195     /// attribute exists for that location.
196     VertexInputAttributeMissing { location: u32 },
197 
198     /// The format specified by a vertex input attribute is not supported for vertex buffers.
199     VertexInputAttributeUnsupportedFormat { location: u32, format: Format },
200 
201     /// The minimum or maximum bounds of viewports have been exceeded.
202     ViewportBoundsExceeded,
203 
204     /// The wrong type of shader has been passed.
205     ///
206     /// For example you passed a vertex shader as the fragment shader.
207     WrongShaderType,
208 
209     /// The requested stencil test is invalid.
210     WrongStencilState,
211 }
212 
213 impl Error for GraphicsPipelineCreationError {
source(&self) -> Option<&(dyn Error + 'static)>214     fn source(&self) -> Option<&(dyn Error + 'static)> {
215         match self {
216             Self::OomError(err) => Some(err),
217             Self::PipelineLayoutCreationError(err) => Some(err),
218             Self::IncompatiblePipelineLayout(err) => Some(err),
219             Self::ShaderStagesMismatch(err) => Some(err),
220             Self::IncompatibleVertexDefinition(err) => Some(err),
221             _ => None,
222         }
223     }
224 }
225 
226 impl Display for GraphicsPipelineCreationError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>227     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
228         match self {
229             Self::RequirementNotMet {
230                 required_for,
231                 requires_one_of,
232             } => write!(
233                 f,
234                 "a requirement was not met for: {}; requires one of: {}",
235                 required_for, requires_one_of,
236             ),
237             Self::ColorAttachmentFormatBlendNotSupported { attachment_index } => write!(
238                 f,
239                 "color attachment {} has a format that does not support blending",
240                 attachment_index,
241             ),
242             Self::ColorAttachmentFormatUsageNotSupported { attachment_index } => write!(
243                 f,
244                 "color attachment {} has a format that does not support that usage",
245                 attachment_index,
246             ),
247             Self::DepthAttachmentFormatUsageNotSupported => write!(
248                 f,
249                 "the depth attachment has a format that does not support that usage",
250             ),
251             Self::DepthStencilAttachmentFormatMismatch => write!(
252                 f,
253                 "the depth and stencil attachments have different formats",
254             ),
255             Self::FragmentShaderRenderPassIncompatible => write!(
256                 f,
257                 "the output of the fragment shader is not compatible with what the render pass \
258                 subpass expects",
259             ),
260             Self::IncompatiblePipelineLayout(_) => write!(
261                 f,
262                 "the pipeline layout is not compatible with what the shaders expect",
263             ),
264             Self::IncompatibleSpecializationConstants => write!(
265                 f,
266                 "the provided specialization constants are not compatible with what the shader \
267                 expects",
268             ),
269             Self::IncompatibleVertexDefinition(_) => write!(
270                 f,
271                 "the vertex definition is not compatible with the input of the vertex shader",
272             ),
273             Self::InvalidPrimitiveTopology => write!(
274                 f,
275                 "trying to use a patch list without a tessellation shader, or a non-patch-list \
276                 with a tessellation shader",
277             ),
278             Self::InvalidNumPatchControlPoints => write!(
279                 f,
280                 "patch_control_points was not greater than 0 and less than or equal to the \
281                 max_tessellation_patch_size limit",
282             ),
283             Self::MaxDiscardRectanglesExceeded { .. } => write!(
284                 f,
285                 "the maximum number of discard rectangles has been exceeded",
286             ),
287             Self::MaxMultiviewViewCountExceeded { .. } => {
288                 write!(f, "the `max_multiview_view_count` limit has been exceeded")
289             }
290             Self::MaxVertexAttribDivisorExceeded { .. } => write!(
291                 f,
292                 "the maximum value for the instance rate divisor has been exceeded",
293             ),
294             Self::MaxVertexInputAttributesExceeded { .. } => write!(
295                 f,
296                 "the maximum number of vertex attributes has been exceeded",
297             ),
298             Self::MaxVertexInputAttributeOffsetExceeded { .. } => write!(
299                 f,
300                 "the maximum offset for a vertex attribute has been exceeded",
301             ),
302             Self::MaxVertexInputBindingsExceeded { .. } => {
303                 write!(f, "the maximum number of vertex sources has been exceeded")
304             }
305             Self::MaxVertexInputBindingStrideExceeded { .. } => write!(
306                 f,
307                 "the maximum stride value for vertex input (ie. the distance between two vertex \
308                 elements) has been exceeded",
309             ),
310             Self::MaxViewportsExceeded { .. } => {
311                 write!(f, "the maximum number of viewports has been exceeded")
312             }
313             Self::MaxViewportDimensionsExceeded => {
314                 write!(f, "the maximum dimensions of viewports has been exceeded")
315             }
316             Self::MinVertexInputBindingStrideAlignmentExceeded { .. } => write!(
317                 f,
318                 "the `min_vertex_input_binding_stride_alignment` limit has been exceeded",
319             ),
320             Self::MismatchBlendingAttachmentsCount => write!(
321                 f,
322                 "the number of attachments specified in the blending does not match the number of \
323                 attachments in the subpass",
324             ),
325             Self::MultisampleRasterizationSamplesMismatch => write!(
326                 f,
327                 "the provided `rasterization_samples` does not match the number of samples of the \
328                 render subpass",
329             ),
330             Self::NoDepthAttachment => write!(
331                 f,
332                 "the depth attachment of the render pass does not match the depth test",
333             ),
334             Self::NoStencilAttachment => write!(
335                 f,
336                 "the stencil attachment of the render pass does not match the stencil test",
337             ),
338             Self::OomError(_) => write!(f, "not enough memory available"),
339             Self::DescriptorSetLayoutCreationError(_) => {
340                 write!(f, "error while creating a descriptor set layout object")
341             }
342             Self::PipelineLayoutCreationError(_) => {
343                 write!(f, "error while creating the pipeline layout object")
344             }
345             Self::ShaderStagesMismatch(_) => write!(
346                 f,
347                 "the output interface of one shader and the input interface of the next shader do \
348                 not match",
349             ),
350             Self::StencilAttachmentFormatUsageNotSupported => write!(
351                 f,
352                 "the stencil attachment has a format that does not support that usage",
353             ),
354             Self::StrictLinesNotSupported => {
355                 write!(f, "the strict_lines device property was false")
356             }
357             Self::TopologyNotMatchingGeometryShader => write!(
358                 f,
359                 "the primitives topology does not match what the geometry shader expects",
360             ),
361             Self::VertexInputAttributeIncompatibleFormat {
362                 location,
363                 shader_type,
364                 attribute_type,
365             } => write!(
366                 f,
367                 "the type of the shader input variable at location {} ({:?}) is not compatible \
368                 with the format of the corresponding vertex input attribute ({:?})",
369                 location, shader_type, attribute_type,
370             ),
371             Self::VertexInputAttributeInvalidAssignedLocation { location } => write!(
372                 f,
373                 "input attribute location {} is expected to be unassigned due to the format of the prior location",
374                 location,
375             ),
376             Self::VertexInputAttributeInvalidBinding { location, binding } => write!(
377                 f,
378                 "the binding number {} specified by vertex input attribute location {} does not \
379                 exist in the provided list of binding descriptions",
380                 binding, location,
381             ),
382             Self::VertexInputAttributeMissing { location } => write!(
383                 f,
384                 "the vertex shader expects an input variable at location {}, but no vertex input \
385                 attribute exists for that location",
386                 location,
387             ),
388             Self::VertexInputAttributeUnsupportedFormat { location, format } => write!(
389                 f,
390                 "the format {:?} specified by vertex input attribute location {} is not supported \
391                 for vertex buffers",
392                 format, location,
393             ),
394             Self::ViewportBoundsExceeded => write!(
395                 f,
396                 "the minimum or maximum bounds of viewports have been exceeded",
397             ),
398             Self::WrongShaderType => write!(f, "the wrong type of shader has been passed"),
399             Self::WrongStencilState => write!(f, "the requested stencil test is invalid"),
400         }
401     }
402 }
403 
404 impl From<OomError> for GraphicsPipelineCreationError {
from(err: OomError) -> GraphicsPipelineCreationError405     fn from(err: OomError) -> GraphicsPipelineCreationError {
406         Self::OomError(err)
407     }
408 }
409 
410 impl From<DescriptorSetLayoutCreationError> for GraphicsPipelineCreationError {
from(err: DescriptorSetLayoutCreationError) -> Self411     fn from(err: DescriptorSetLayoutCreationError) -> Self {
412         Self::DescriptorSetLayoutCreationError(err)
413     }
414 }
415 
416 impl From<PipelineLayoutCreationError> for GraphicsPipelineCreationError {
from(err: PipelineLayoutCreationError) -> Self417     fn from(err: PipelineLayoutCreationError) -> Self {
418         Self::PipelineLayoutCreationError(err)
419     }
420 }
421 
422 impl From<PipelineLayoutSupersetError> for GraphicsPipelineCreationError {
from(err: PipelineLayoutSupersetError) -> Self423     fn from(err: PipelineLayoutSupersetError) -> Self {
424         Self::IncompatiblePipelineLayout(err)
425     }
426 }
427 
428 impl From<IncompatibleVertexDefinitionError> for GraphicsPipelineCreationError {
from(err: IncompatibleVertexDefinitionError) -> Self429     fn from(err: IncompatibleVertexDefinitionError) -> Self {
430         Self::IncompatibleVertexDefinition(err)
431     }
432 }
433 
434 impl From<VulkanError> for GraphicsPipelineCreationError {
from(err: VulkanError) -> Self435     fn from(err: VulkanError) -> Self {
436         match err {
437             err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
438             err @ VulkanError::OutOfDeviceMemory => Self::OomError(OomError::from(err)),
439             _ => panic!("unexpected error: {:?}", err),
440         }
441     }
442 }
443 
444 impl From<RequirementNotMet> for GraphicsPipelineCreationError {
from(err: RequirementNotMet) -> Self445     fn from(err: RequirementNotMet) -> Self {
446         Self::RequirementNotMet {
447             required_for: err.required_for,
448             requires_one_of: err.requires_one_of,
449         }
450     }
451 }
452