aboutsummaryrefslogtreecommitdiff
path: root/autogen/extensions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'autogen/extensions.rs')
-rw-r--r--autogen/extensions.rs399
1 files changed, 399 insertions, 0 deletions
diff --git a/autogen/extensions.rs b/autogen/extensions.rs
new file mode 100644
index 0000000..b303da1
--- /dev/null
+++ b/autogen/extensions.rs
@@ -0,0 +1,399 @@
+// Copyright (c) 2021 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.
+
+use heck::SnakeCase;
+use indexmap::IndexMap;
+use std::io::Write;
+use vk_parse::Extension;
+
+// This is not included in vk.xml, so it's added here manually
+fn required_if_supported(name: &str) -> bool {
+ match name {
+ "VK_KHR_portability_subset" => true,
+ _ => false,
+ }
+}
+
+fn conflicts_extensions(name: &str) -> &'static [&'static str] {
+ match name {
+ "VK_KHR_buffer_device_address" => &["VK_EXT_buffer_device_address"],
+ "VK_EXT_buffer_device_address" => &["VK_KHR_buffer_device_address"],
+ _ => &[],
+ }
+}
+
+pub fn write<W: Write>(writer: &mut W, extensions: &IndexMap<&str, &Extension>) {
+ write_device_extensions(writer, make_vulkano_extensions("device", &extensions));
+ write!(writer, "\n\n").unwrap();
+ write_instance_extensions(writer, make_vulkano_extensions("instance", &extensions));
+}
+
+#[derive(Clone, Debug)]
+struct VulkanoExtension {
+ member: String,
+ raw: String,
+ requires_core: (u16, u16),
+ requires_device_extensions: Vec<String>,
+ requires_instance_extensions: Vec<String>,
+ required_if_supported: bool,
+ conflicts_device_extensions: Vec<String>,
+ status: Option<ExtensionStatus>,
+}
+
+#[derive(Clone, Debug)]
+enum Replacement {
+ Core((u16, u16)),
+ DeviceExtension(String),
+ InstanceExtension(String),
+}
+
+#[derive(Clone, Debug)]
+enum ExtensionStatus {
+ Promoted(Replacement),
+ Deprecated(Option<Replacement>),
+}
+
+fn make_vulkano_extensions(
+ ty: &str,
+ extensions: &IndexMap<&str, &Extension>,
+) -> Vec<VulkanoExtension> {
+ extensions
+ .values()
+ .filter(|ext| ext.ext_type.as_ref().unwrap() == ty)
+ .map(|ext| {
+ let raw = ext.name.to_owned();
+ let member = raw.strip_prefix("VK_").unwrap().to_snake_case();
+ let (major, minor) = ext
+ .requires_core
+ .as_ref()
+ .map(|s| s.as_str())
+ .unwrap_or("1.0")
+ .split_once('.')
+ .unwrap();
+ let requires_extensions: Vec<_> = ext
+ .requires
+ .as_ref()
+ .map(|s| s.split(',').collect())
+ .unwrap_or_default();
+ let conflicts_extensions = conflicts_extensions(&ext.name);
+
+ VulkanoExtension {
+ member: member.clone(),
+ raw,
+ requires_core: (major.parse().unwrap(), minor.parse().unwrap()),
+ requires_device_extensions: requires_extensions
+ .iter()
+ .filter(|&&vk_name| extensions[vk_name].ext_type.as_ref().unwrap() == "device")
+ .map(|vk_name| vk_name.strip_prefix("VK_").unwrap().to_snake_case())
+ .collect(),
+ requires_instance_extensions: requires_extensions
+ .iter()
+ .filter(|&&vk_name| {
+ extensions[vk_name].ext_type.as_ref().unwrap() == "instance"
+ })
+ .map(|vk_name| vk_name.strip_prefix("VK_").unwrap().to_snake_case())
+ .collect(),
+ required_if_supported: required_if_supported(ext.name.as_str()),
+ conflicts_device_extensions: conflicts_extensions
+ .iter()
+ .filter(|&&vk_name| extensions[vk_name].ext_type.as_ref().unwrap() == "device")
+ .map(|vk_name| vk_name.strip_prefix("VK_").unwrap().to_snake_case())
+ .collect(),
+ status: ext
+ .promotedto
+ .as_ref()
+ .map(|s| s.as_str())
+ .and_then(|pr| {
+ if let Some(version) = pr.strip_prefix("VK_VERSION_") {
+ let (major, minor) = version.split_once('_').unwrap();
+ Some(ExtensionStatus::Promoted(Replacement::Core((
+ major.parse().unwrap(),
+ minor.parse().unwrap(),
+ ))))
+ } else {
+ let member = pr.strip_prefix("VK_").unwrap().to_snake_case();
+ match extensions[pr].ext_type.as_ref().unwrap().as_str() {
+ "device" => Some(ExtensionStatus::Promoted(
+ Replacement::DeviceExtension(member),
+ )),
+ "instance" => Some(ExtensionStatus::Promoted(
+ Replacement::InstanceExtension(member),
+ )),
+ _ => unreachable!(),
+ }
+ }
+ })
+ .or_else(|| {
+ ext.deprecatedby
+ .as_ref()
+ .map(|s| s.as_str())
+ .and_then(|depr| {
+ if depr.is_empty() {
+ Some(ExtensionStatus::Deprecated(None))
+ } else if let Some(version) = depr.strip_prefix("VK_VERSION_") {
+ let (major, minor) = version.split_once('_').unwrap();
+ Some(ExtensionStatus::Deprecated(Some(Replacement::Core((
+ major.parse().unwrap(),
+ minor.parse().unwrap(),
+ )))))
+ } else {
+ let member = depr.strip_prefix("VK_").unwrap().to_snake_case();
+ match extensions[depr].ext_type.as_ref().unwrap().as_str() {
+ "device" => Some(ExtensionStatus::Deprecated(Some(
+ Replacement::DeviceExtension(member),
+ ))),
+ "instance" => Some(ExtensionStatus::Deprecated(Some(
+ Replacement::InstanceExtension(member),
+ ))),
+ _ => unreachable!(),
+ }
+ }
+ })
+ }),
+ }
+ })
+ .collect()
+}
+
+fn write_device_extensions<W, I>(writer: &mut W, extensions: I)
+where
+ W: Write,
+ I: IntoIterator<Item = VulkanoExtension>,
+{
+ write!(writer, "crate::device::extensions::device_extensions! {{").unwrap();
+ for ext in extensions {
+ write!(writer, "\n\t{} => {{", ext.member).unwrap();
+ write_doc(writer, &ext);
+ write!(writer, "\n\t\traw: b\"{}\",", ext.raw).unwrap();
+ write!(
+ writer,
+ "\n\t\trequires_core: crate::Version::V{}_{},",
+ ext.requires_core.0, ext.requires_core.1
+ )
+ .unwrap();
+ write!(
+ writer,
+ "\n\t\trequires_device_extensions: [{}],",
+ ext.requires_device_extensions.join(", ")
+ )
+ .unwrap();
+ write!(
+ writer,
+ "\n\t\trequires_instance_extensions: [{}],",
+ ext.requires_instance_extensions.join(", ")
+ )
+ .unwrap();
+ write!(
+ writer,
+ "\n\t\trequired_if_supported: {},",
+ ext.required_if_supported
+ )
+ .unwrap();
+ write!(
+ writer,
+ "\n\t\tconflicts_device_extensions: [{}],",
+ ext.conflicts_device_extensions.join(", ")
+ )
+ .unwrap();
+
+ /*if let Some(promoted_to_core) = ext.promoted_to_core {
+ write!(
+ writer,
+ "\n\t\tpromoted_to_core: Some(Version::V{}_{}),",
+ promoted_to_core.0, promoted_to_core.1
+ )
+ .unwrap();
+ } else {
+ write!(writer, "\n\t\tpromoted_to_core: None,",).unwrap();
+ }*/
+
+ write!(writer, "\n\t}},").unwrap();
+ }
+ write!(writer, "\n}}").unwrap();
+}
+
+fn write_instance_extensions<W, I>(writer: &mut W, extensions: I)
+where
+ W: Write,
+ I: IntoIterator<Item = VulkanoExtension>,
+{
+ write!(
+ writer,
+ "crate::instance::extensions::instance_extensions! {{"
+ )
+ .unwrap();
+ for ext in extensions {
+ write!(writer, "\n\t{} => {{", ext.member).unwrap();
+ write_doc(writer, &ext);
+ write!(writer, "\n\t\traw: b\"{}\",", ext.raw).unwrap();
+ write!(
+ writer,
+ "\n\t\trequires_core: crate::Version::V{}_{},",
+ ext.requires_core.0, ext.requires_core.1
+ )
+ .unwrap();
+ write!(
+ writer,
+ "\n\t\trequires_instance_extensions: [{}],",
+ ext.requires_instance_extensions.join(", ")
+ )
+ .unwrap();
+
+ /*if let Some(promoted_to_core) = ext.promoted_to_core {
+ write!(
+ writer,
+ "\n\t\tpromoted_to_core: Some(crate::Version::V{}_{}),",
+ promoted_to_core.0, promoted_to_core.1
+ )
+ .unwrap();
+ } else {
+ write!(writer, "\n\t\tpromoted_to_core: None,",).unwrap();
+ }*/
+
+ write!(writer, "\n\t}},").unwrap();
+ }
+ write!(writer, "\n}}").unwrap();
+}
+
+fn write_doc<W>(writer: &mut W, ext: &VulkanoExtension)
+where
+ W: Write,
+{
+ write!(writer, "\n\t\tdoc: \"\n\t\t\t- [Vulkan documentation](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/{}.html)", ext.raw).unwrap();
+
+ if ext.requires_core != (1, 0) {
+ write!(
+ writer,
+ "\n\t\t\t- Requires Vulkan {}.{}",
+ ext.requires_core.0, ext.requires_core.1
+ )
+ .unwrap();
+ }
+
+ if !ext.requires_device_extensions.is_empty() {
+ let links: Vec<_> = ext
+ .requires_device_extensions
+ .iter()
+ .map(|ext| format!("[`{}`](crate::device::DeviceExtensions::{0})", ext))
+ .collect();
+ write!(
+ writer,
+ "\n\t\t\t- Requires device extension{}: {}",
+ if ext.requires_device_extensions.len() > 1 {
+ "s"
+ } else {
+ ""
+ },
+ links.join(", ")
+ )
+ .unwrap();
+ }
+
+ if !ext.requires_instance_extensions.is_empty() {
+ let links: Vec<_> = ext
+ .requires_instance_extensions
+ .iter()
+ .map(|ext| format!("[`{}`](crate::instance::InstanceExtensions::{0})", ext))
+ .collect();
+ write!(
+ writer,
+ "\n\t\t\t- Requires instance extension{}: {}",
+ if ext.requires_instance_extensions.len() > 1 {
+ "s"
+ } else {
+ ""
+ },
+ links.join(", ")
+ )
+ .unwrap();
+ }
+
+ if ext.required_if_supported {
+ write!(
+ writer,
+ "\n\t\t\t- Must be enabled if it is supported by the physical device",
+ )
+ .unwrap();
+ }
+
+ if !ext.conflicts_device_extensions.is_empty() {
+ let links: Vec<_> = ext
+ .conflicts_device_extensions
+ .iter()
+ .map(|ext| format!("[`{}`](crate::device::DeviceExtensions::{0})", ext))
+ .collect();
+ write!(
+ writer,
+ "\n\t\t\t- Conflicts with device extension{}: {}",
+ if ext.conflicts_device_extensions.len() > 1 {
+ "s"
+ } else {
+ ""
+ },
+ links.join(", ")
+ )
+ .unwrap();
+ }
+
+ if let Some(status) = ext.status.as_ref() {
+ match status {
+ ExtensionStatus::Promoted(replacement) => {
+ write!(writer, "\n\t\t\t- Promoted to ",).unwrap();
+
+ match replacement {
+ Replacement::Core(version) => {
+ write!(writer, "Vulkan {}.{}", version.0, version.1).unwrap();
+ }
+ Replacement::DeviceExtension(ext) => {
+ write!(writer, "[`{}`](crate::device::DeviceExtensions::{0})", ext)
+ .unwrap();
+ }
+ Replacement::InstanceExtension(ext) => {
+ write!(
+ writer,
+ "[`{}`](crate::instance::InstanceExtensions::{0})",
+ ext
+ )
+ .unwrap();
+ }
+ }
+ }
+ ExtensionStatus::Deprecated(replacement) => {
+ write!(writer, "\n\t\t\t- Deprecated ",).unwrap();
+
+ match replacement {
+ Some(Replacement::Core(version)) => {
+ write!(writer, "by Vulkan {}.{}", version.0, version.1).unwrap();
+ }
+ Some(Replacement::DeviceExtension(ext)) => {
+ write!(
+ writer,
+ "by [`{}`](crate::device::DeviceExtensions::{0})",
+ ext
+ )
+ .unwrap();
+ }
+ Some(Replacement::InstanceExtension(ext)) => {
+ write!(
+ writer,
+ "by [`{}`](crate::instance::InstanceExtensions::{0})",
+ ext
+ )
+ .unwrap();
+ }
+ None => {
+ write!(writer, "without a replacement").unwrap();
+ }
+ }
+ }
+ }
+ }
+
+ write!(writer, "\n\t\t\",").unwrap();
+}