1 // Copyright (c) 2016 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 crate::RequiresOneOf;
11 use bytemuck::cast_slice;
12 use std::{
13     error::Error,
14     fmt::{Display, Error as FmtError, Formatter},
15 };
16 
17 /// Properties of an extension in the loader or a physical device.
18 #[derive(Clone, Debug)]
19 pub struct ExtensionProperties {
20     /// The name of the extension.
21     pub extension_name: String,
22 
23     /// The version of the extension.
24     pub spec_version: u32,
25 }
26 
27 impl From<ash::vk::ExtensionProperties> for ExtensionProperties {
28     #[inline]
from(val: ash::vk::ExtensionProperties) -> Self29     fn from(val: ash::vk::ExtensionProperties) -> Self {
30         Self {
31             extension_name: {
32                 let bytes = cast_slice(val.extension_name.as_slice());
33                 let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
34                 String::from_utf8_lossy(&bytes[0..end]).into()
35             },
36             spec_version: val.spec_version,
37         }
38     }
39 }
40 
41 /// An error that can happen when enabling an extension on an instance or device.
42 #[derive(Clone, Copy, Debug)]
43 pub struct ExtensionRestrictionError {
44     /// The extension in question.
45     pub extension: &'static str,
46     /// The restriction that was not met.
47     pub restriction: ExtensionRestriction,
48 }
49 
50 impl Error for ExtensionRestrictionError {}
51 
52 impl Display for ExtensionRestrictionError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>53     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
54         write!(
55             f,
56             "a restriction for the extension {} was not met: {}",
57             self.extension, self.restriction,
58         )
59     }
60 }
61 
62 #[derive(Clone, Copy, Debug)]
63 pub enum ExtensionRestriction {
64     /// Not supported by the loader or physical device.
65     NotSupported,
66     /// Required to be enabled by the physical device.
67     RequiredIfSupported,
68     /// Requires one of the following.
69     Requires(RequiresOneOf),
70     /// Requires a device extension to be disabled.
71     ConflictsDeviceExtension(&'static str),
72 }
73 
74 impl Display for ExtensionRestriction {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>75     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
76         match *self {
77             ExtensionRestriction::NotSupported => {
78                 write!(f, "not supported by the loader or physical device")
79             }
80             ExtensionRestriction::RequiredIfSupported => {
81                 write!(f, "required to be enabled by the physical device")
82             }
83             ExtensionRestriction::Requires(requires) => {
84                 if requires.len() > 1 {
85                     write!(f, "requires one of: {}", requires)
86                 } else {
87                     write!(f, "requires: {}", requires)
88                 }
89             }
90             ExtensionRestriction::ConflictsDeviceExtension(ext) => {
91                 write!(f, "requires device extension {} to be disabled", ext)
92             }
93         }
94     }
95 }
96