Save
This commit is contained in:
parent
b47b20023e
commit
bfed51f8d3
|
@ -13,6 +13,8 @@ documentation = "https://docs.rs/ash"
|
||||||
shared_library = "0.1.5"
|
shared_library = "0.1.5"
|
||||||
lazy_static = "0.2.1"
|
lazy_static = "0.2.1"
|
||||||
libc = "0.2.26"
|
libc = "0.2.26"
|
||||||
|
enumflags = "*"
|
||||||
|
enumflags_derive = "*"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate shared_library;
|
extern crate shared_library;
|
||||||
|
extern crate enumflags;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate enumflags_derive;
|
||||||
pub use instance::{DeviceError, Instance};
|
pub use instance::{DeviceError, Instance};
|
||||||
pub use device::Device;
|
pub use device::Device;
|
||||||
pub use entry::{Entry, InstanceError, LoadingError};
|
pub use entry::{Entry, InstanceError, LoadingError};
|
||||||
|
@ -15,6 +18,7 @@ pub mod vk;
|
||||||
pub mod extensions;
|
pub mod extensions;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
mod vk_test;
|
||||||
|
|
||||||
pub trait RawPtr<T> {
|
pub trait RawPtr<T> {
|
||||||
fn as_raw_ptr(&self) -> *const T;
|
fn as_raw_ptr(&self) -> *const T;
|
||||||
|
|
|
@ -4,13 +4,15 @@ version = "0.1.0"
|
||||||
authors = ["Maik Klein <maikklein@googlemail.com>"]
|
authors = ["Maik Klein <maikklein@googlemail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
vkxml = {git = "https://github.com/maikklein/vkxml"}
|
vkxml = {path = "/home/maik/projects/vkxml"}
|
||||||
|
#vkxml = {git = "https://github.com/maikklein/vkxml"}
|
||||||
heck = "0.3.0"
|
heck = "0.3.0"
|
||||||
|
proc-macro2 = "0.2.3"
|
||||||
|
|
||||||
[dependencies.quote]
|
[dependencies.quote]
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
||||||
[dependencies.syn]
|
[dependencies.syn]
|
||||||
vesion = "0.12.14"
|
version = "0.12.14"
|
||||||
features = ["full", "extra-traits"]
|
features = ["full", "extra-traits"]
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,84 @@
|
||||||
// #[macro_use]
|
// #[macro_use]
|
||||||
// extern crate serde_derive;
|
// extern crate serde_derive;
|
||||||
extern crate heck;
|
extern crate heck;
|
||||||
|
extern crate proc_macro2;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
pub extern crate vkxml;
|
pub extern crate vkxml;
|
||||||
|
|
||||||
|
use proc_macro2::Term;
|
||||||
use quote::Tokens;
|
use quote::Tokens;
|
||||||
use heck::{CamelCase, SnakeCase};
|
use heck::{CamelCase, ShoutySnakeCase, SnakeCase};
|
||||||
|
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
|
pub enum Constant {
|
||||||
|
Number(i32),
|
||||||
|
Hex(String),
|
||||||
|
BitPos(u32),
|
||||||
|
CExpr(vkxml::CExpression),
|
||||||
|
Text(String),
|
||||||
|
}
|
||||||
|
impl Constant {
|
||||||
|
pub fn value(&self) -> Option<i64> {
|
||||||
|
match *self {
|
||||||
|
Constant::Number(n) => Some(n as i64),
|
||||||
|
Constant::Hex(ref hex) => Some(hex.parse().expect("hex parse")),
|
||||||
|
Constant::BitPos(pos) => Some((1 << pos) as i64),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn to_tokens(&self) -> Tokens {
|
||||||
|
match *self {
|
||||||
|
Constant::Number(n) => {
|
||||||
|
let term = Term::intern(&n.to_string());
|
||||||
|
quote!{#term}
|
||||||
|
}
|
||||||
|
Constant::Hex(ref s) => {
|
||||||
|
let term = Term::intern(s);
|
||||||
|
quote!{#term}
|
||||||
|
}
|
||||||
|
Constant::Text(ref text) => {
|
||||||
|
quote!{#text}
|
||||||
|
}
|
||||||
|
Constant::CExpr(ref cexpr) => {
|
||||||
|
let rexpr = cexpr.replace("~", "!").replace("U", "u32");
|
||||||
|
let term = Term::intern(&rexpr);
|
||||||
|
quote!{#term}
|
||||||
|
}
|
||||||
|
Constant::BitPos(pos) => {
|
||||||
|
let value = 1 << pos;
|
||||||
|
let term = Term::intern(&format!("0b{:b}", value));
|
||||||
|
quote!{#term}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_constant(constant: &vkxml::Constant) -> Self {
|
||||||
|
let number = constant.number.map(|n| Constant::Number(n));
|
||||||
|
let hex = constant.hex.as_ref().map(|hex| Constant::Hex(hex.clone()));
|
||||||
|
let bitpos = constant.bitpos.map(|bit| Constant::BitPos(bit));
|
||||||
|
let expr = constant
|
||||||
|
.c_expression
|
||||||
|
.as_ref()
|
||||||
|
.map(|e| Constant::CExpr(e.clone()));
|
||||||
|
number.or(hex).or(bitpos).or(expr).expect("")
|
||||||
|
}
|
||||||
|
pub fn from_extension(extension: &vkxml::ExtensionConstant) -> Self {
|
||||||
|
let number = extension.number.map(|n| Constant::Number(n));
|
||||||
|
let hex = extension.hex.as_ref().map(|hex| Constant::Hex(hex.clone()));
|
||||||
|
let bitpos = extension.bitpos.map(|bit| Constant::BitPos(bit));
|
||||||
|
let expr = extension
|
||||||
|
.c_expression
|
||||||
|
.as_ref()
|
||||||
|
.map(|e| Constant::CExpr(e.clone()));
|
||||||
|
let text = extension.text.as_ref().map(|e| Constant::Text(e.clone()));
|
||||||
|
number.or(hex).or(bitpos).or(expr).or(text).expect("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ConstantExt {}
|
||||||
|
impl ConstantExt for vkxml::Constant {}
|
||||||
pub trait FeatureExt {
|
pub trait FeatureExt {
|
||||||
fn version_string(&self) -> String;
|
fn version_string(&self) -> String;
|
||||||
}
|
}
|
||||||
|
@ -252,19 +320,109 @@ pub fn generate_typedef(typedef: &vkxml::Typedef) -> Tokens {
|
||||||
let typedef_name = to_type_tokens(&typedef.name, None);
|
let typedef_name = to_type_tokens(&typedef.name, None);
|
||||||
let typedef_ty = to_type_tokens(&typedef.basetype, None);
|
let typedef_ty = to_type_tokens(&typedef.basetype, None);
|
||||||
quote!{
|
quote!{
|
||||||
type #typedef_name = #typedef_ty;
|
pub type #typedef_name = #typedef_ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_bitmask(bitmask: &vkxml::Bitmask) -> Tokens {
|
pub fn generate_bitmask(bitmask: &vkxml::Bitmask) -> Tokens {
|
||||||
println!("{:#?}", bitmask);
|
let name = &bitmask.name[2..];
|
||||||
let ident = Ident::from(&bitmask.name[2..]);
|
let name_without_flags = name.replace("Flags", "");
|
||||||
|
let ident = Ident::from(name);
|
||||||
|
let ident_without_flags = Ident::from(name_without_flags.as_str());
|
||||||
let type_token = to_type_tokens(&bitmask.basetype, None);
|
let type_token = to_type_tokens(&bitmask.basetype, None);
|
||||||
quote!{
|
quote!{
|
||||||
vk_bitflags_wrapped!(#ident, 0b0, #type_token);
|
pub type #ident = BitFlags<flags::#ident_without_flags>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_enumeration(_enum: &vkxml::EnumerationDeclaration) -> Tokens {
|
pub fn to_variant_ident(enum_name: &str, variant_name: &str) -> Ident {
|
||||||
quote!{}
|
let tag = ["AMD", "NN", "KHR", "NV", "EXT", "NVX", "KHX"]
|
||||||
|
.iter()
|
||||||
|
.filter_map(|tag| {
|
||||||
|
if enum_name.ends_with(tag) {
|
||||||
|
Some(tag)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.nth(0);
|
||||||
|
|
||||||
|
let name_without_tag = tag.map(|t| enum_name.replace(t, ""))
|
||||||
|
.unwrap_or(enum_name.into());
|
||||||
|
let variant_without_tag = tag.map(|t| variant_name.replace(t, ""))
|
||||||
|
.unwrap_or(variant_name.into());
|
||||||
|
let camel_case_name_enum = &name_without_tag.to_camel_case();
|
||||||
|
let name = variant_without_tag.to_camel_case()[2..].replace(camel_case_name_enum, "");
|
||||||
|
let is_digit = name.chars().nth(0).map(|c| c.is_digit(10)).unwrap_or(false);
|
||||||
|
if is_digit {
|
||||||
|
Ident::from(format!("Type{}", name).as_str())
|
||||||
|
} else {
|
||||||
|
Ident::from(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EnumType {
|
||||||
|
Bitflags(Tokens),
|
||||||
|
Enum(Tokens),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_enum(_enum: &vkxml::Enumeration) -> EnumType {
|
||||||
|
let name = &_enum.name[2..];
|
||||||
|
let _name = name.replace("FlagBits", "");
|
||||||
|
if name.contains("Bit") {
|
||||||
|
let variants = _enum.elements.iter().filter_map(|elem| {
|
||||||
|
let (variant_name, value) = match *elem {
|
||||||
|
vkxml::EnumerationElement::Enum(ref constant) => {
|
||||||
|
let c = Constant::from_constant(constant);
|
||||||
|
if c.value().map(|v| v == 0).unwrap_or(false) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
(constant.name.as_str(), c.to_tokens())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let variant_ident = to_variant_ident(&_name, variant_name);
|
||||||
|
Some(quote!{
|
||||||
|
#variant_ident = #value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let ident = Ident::from(_name.as_str());
|
||||||
|
let q = quote!{
|
||||||
|
#[derive(Copy, Clone, Debug, EnumFlags)]
|
||||||
|
pub enum #ident {
|
||||||
|
#(#variants,)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EnumType::Bitflags(q)
|
||||||
|
} else {
|
||||||
|
let variants = _enum.elements.iter().filter_map(|elem| {
|
||||||
|
let (variant_name, value) = match *elem {
|
||||||
|
vkxml::EnumerationElement::Enum(ref constant) => {
|
||||||
|
let c = Constant::from_constant(constant);
|
||||||
|
println!("value {:?}", c.value());
|
||||||
|
(constant.name.as_str(), c.to_tokens())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let variant_ident = to_variant_ident(&_name, variant_name);
|
||||||
|
Some(quote!{
|
||||||
|
#variant_ident = #value
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let ident = Ident::from(_name.as_str());
|
||||||
|
let q = quote!{
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum #ident {
|
||||||
|
#(#variants,)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EnumType::Enum(q)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn generate_struct(_struct: &vkxml::Struct) -> Tokens {
|
pub fn generate_struct(_struct: &vkxml::Struct) -> Tokens {
|
||||||
let name = Ident::from(&_struct.name[2..]);
|
let name = Ident::from(&_struct.name[2..]);
|
||||||
|
@ -292,7 +450,6 @@ pub fn generate_definition(definition: &vkxml::DefinitionsElement) -> Tokens {
|
||||||
match *definition {
|
match *definition {
|
||||||
vkxml::DefinitionsElement::Typedef(ref typedef) => generate_typedef(typedef),
|
vkxml::DefinitionsElement::Typedef(ref typedef) => generate_typedef(typedef),
|
||||||
vkxml::DefinitionsElement::Struct(ref _struct) => generate_struct(_struct),
|
vkxml::DefinitionsElement::Struct(ref _struct) => generate_struct(_struct),
|
||||||
vkxml::DefinitionsElement::Enumeration(ref _enum) => generate_enumeration(_enum),
|
|
||||||
vkxml::DefinitionsElement::Bitmask(ref mask) => generate_bitmask(mask),
|
vkxml::DefinitionsElement::Bitmask(ref mask) => generate_bitmask(mask),
|
||||||
_ => quote!{},
|
_ => quote!{},
|
||||||
}
|
}
|
||||||
|
@ -383,6 +540,42 @@ pub fn write_source_code(spec: &vkxml::Registry) {
|
||||||
.flat_map(|definitions| definitions.elements.iter().map(|definition| definition))
|
.flat_map(|definitions| definitions.elements.iter().map(|definition| definition))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let enums: Vec<&vkxml::Enumeration> = spec.elements
|
||||||
|
.iter()
|
||||||
|
.filter_map(|elem| match elem {
|
||||||
|
&vkxml::RegistryElement::Enums(ref enums) => Some(enums),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.flat_map(|enums| {
|
||||||
|
enums.elements.iter().filter_map(|_enum| match *_enum {
|
||||||
|
vkxml::EnumsElement::Enumeration(ref e) => Some(e),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let constants: Vec<&vkxml::Constant> = spec.elements
|
||||||
|
.iter()
|
||||||
|
.filter_map(|elem| match elem {
|
||||||
|
&vkxml::RegistryElement::Constants(ref constants) => Some(constants),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.flat_map(|constants| constants.elements.iter())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
//println!("{:#?}", constants);
|
||||||
|
|
||||||
|
let (enum_code, bitflags_code) = enums.into_iter().map(generate_enum).fold(
|
||||||
|
(Vec::new(), Vec::new()),
|
||||||
|
|mut acc, elem| {
|
||||||
|
match elem {
|
||||||
|
EnumType::Enum(token) => acc.0.push(token),
|
||||||
|
EnumType::Bitflags(token) => acc.1.push(token),
|
||||||
|
};
|
||||||
|
acc
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let definition_code: Vec<_> = definitions.into_iter().map(generate_definition).collect();
|
let definition_code: Vec<_> = definitions.into_iter().map(generate_definition).collect();
|
||||||
|
|
||||||
let feature_code: Vec<_> = features
|
let feature_code: Vec<_> = features
|
||||||
|
@ -394,11 +587,15 @@ pub fn write_source_code(spec: &vkxml::Registry) {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ext| generate_extension(ext, &commands))
|
.map(|ext| generate_extension(ext, &commands))
|
||||||
.collect();
|
.collect();
|
||||||
let mut file = File::create("vk_test.rs").expect("vk");
|
let mut file = File::create("../ash/src/vk_test.rs").expect("vk");
|
||||||
let source_code = quote!{
|
let source_code = quote!{
|
||||||
//#(#feature_code)*
|
//#(#feature_code)*
|
||||||
//#(#extension_code)*
|
//#(#extension_code)*
|
||||||
#(#definition_code)*
|
//#(#definition_code)*
|
||||||
|
//#(#enum_code)*
|
||||||
|
pub mod flags {
|
||||||
|
#(#bitflags_code)*
|
||||||
|
}
|
||||||
};
|
};
|
||||||
write!(&mut file, "{}", source_code);
|
write!(&mut file, "{}", source_code);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue