Fix incorrect generation of commands with aliases (#279)
* Fix incorrect generation of commands with aliases * Use alias name instead of the actual cmd name
This commit is contained in:
parent
c32f0dd739
commit
af6acb93e5
3 changed files with 2203 additions and 304 deletions
2402
ash/src/vk.rs
2402
ash/src/vk.rs
File diff suppressed because it is too large
Load diff
|
@ -10,7 +10,7 @@ vkxml = "0.3"
|
|||
nom = "4.0"
|
||||
heck = "0.3"
|
||||
proc-macro2 = "0.2"
|
||||
itertools = "0.7"
|
||||
itertools = "0.9"
|
||||
|
||||
[dependencies.quote]
|
||||
version = "0.4.2"
|
||||
|
|
|
@ -723,10 +723,26 @@ pub type CommandMap<'a> = HashMap<vkxml::Identifier, &'a vkxml::Command>;
|
|||
fn generate_function_pointers<'a>(
|
||||
ident: Ident,
|
||||
commands: &[&'a vkxml::Command],
|
||||
aliases: &HashMap<String, String, impl BuildHasher>,
|
||||
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||
) -> quote::Tokens {
|
||||
// We filter commands so that we don't have duplicates
|
||||
let commands: Vec<_> = commands
|
||||
// Commands can have duplicates inside them because they are declared per features. But we only
|
||||
// really want to generate one function pointer.
|
||||
let commands = {
|
||||
let mut cache = HashSet::new();
|
||||
let mut cmd_vec: Vec<&vkxml::Command> = Vec::new();
|
||||
for cmd in commands {
|
||||
let name = cmd.name.as_str();
|
||||
if !cache.contains(name) {
|
||||
cmd_vec.push(cmd);
|
||||
cache.insert(name);
|
||||
}
|
||||
}
|
||||
cmd_vec
|
||||
};
|
||||
// PFN function pointers are global and can not have duplicates. This can happen because there
|
||||
// are aliases to commands
|
||||
let commands_pfn: Vec<_> = commands
|
||||
.iter()
|
||||
.filter(|cmd| {
|
||||
let ident = cmd.name.as_str();
|
||||
|
@ -738,14 +754,29 @@ fn generate_function_pointers<'a>(
|
|||
}
|
||||
})
|
||||
.collect();
|
||||
let names: Vec<_> = commands.iter().map(|cmd| cmd.command_ident()).collect();
|
||||
|
||||
let function_name_raw = |name: &str| -> String {
|
||||
if let Some(alias_name) = aliases.get(name) {
|
||||
alias_name.to_string()
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
};
|
||||
let function_name = |name: &str| -> Ident {
|
||||
let fn_name = function_name_raw(&name);
|
||||
Ident::from(fn_name[2..].to_snake_case().as_str())
|
||||
};
|
||||
let names: Vec<_> = commands
|
||||
.iter()
|
||||
.map(|cmd| function_name(&cmd.name))
|
||||
.collect();
|
||||
let names_ref = &names;
|
||||
let names_ref1 = &names;
|
||||
let names_ref2 = &names;
|
||||
let names_ref3 = &names;
|
||||
let raw_names: Vec<_> = commands
|
||||
.iter()
|
||||
.map(|cmd| Ident::from(cmd.name.as_str()))
|
||||
.map(|cmd| Ident::from(function_name_raw(cmd.name.as_str()).as_str()))
|
||||
.collect();
|
||||
let raw_names_ref = &raw_names;
|
||||
let names_left = &names;
|
||||
|
@ -809,7 +840,7 @@ fn generate_function_pointers<'a>(
|
|||
.collect();
|
||||
let return_types_ref = &return_types;
|
||||
|
||||
let pfn_names: Vec<_> = commands
|
||||
let pfn_names: Vec<_> = commands_pfn
|
||||
.iter()
|
||||
.map(|cmd| Ident::from(format!("PFN_{}", cmd.name.as_str())))
|
||||
.collect();
|
||||
|
@ -985,24 +1016,38 @@ pub fn generate_extension_commands<'a>(
|
|||
extension_name: &str,
|
||||
items: &[vk_parse::ExtensionChild],
|
||||
cmd_map: &CommandMap<'a>,
|
||||
cmd_aliases: &HashMap<String, String, impl BuildHasher>,
|
||||
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||
) -> Tokens {
|
||||
let commands = items
|
||||
let mut commands = Vec::new();
|
||||
let mut aliases = HashMap::new();
|
||||
items
|
||||
.iter()
|
||||
.filter_map(|ext_item| match ext_item {
|
||||
vk_parse::ExtensionChild::Require { items, .. } => {
|
||||
Some(items.iter().filter_map(|item| match item {
|
||||
vk_parse::InterfaceItem::Command { ref name, .. } => cmd_map.get(name).copied(),
|
||||
vk_parse::InterfaceItem::Command { ref name, .. } => Some(name),
|
||||
_ => None,
|
||||
}))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.flat_map(|iter| iter)
|
||||
.collect_vec();
|
||||
.flatten()
|
||||
.for_each(|name| {
|
||||
if let Some(cmd) = cmd_map.get(name).copied() {
|
||||
commands.push(cmd);
|
||||
} else if let Some(cmd) = cmd_aliases
|
||||
.get(name)
|
||||
.and_then(|alias_name| cmd_map.get(alias_name).copied())
|
||||
{
|
||||
aliases.insert(cmd.name.clone(), name.to_string());
|
||||
commands.push(cmd);
|
||||
}
|
||||
});
|
||||
|
||||
let name = format!("{}Fn", extension_name.to_camel_case());
|
||||
let ident = Ident::from(&name[2..]);
|
||||
let fp = generate_function_pointers(ident, &commands, fn_cache);
|
||||
let fp = generate_function_pointers(ident, &commands, &aliases, fn_cache);
|
||||
let byte_name = format!("{}\0", extension_name);
|
||||
|
||||
let byte_name_ident =
|
||||
|
@ -1024,6 +1069,7 @@ pub fn generate_extension<'a>(
|
|||
cmd_map: &CommandMap<'a>,
|
||||
const_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||
cmd_aliases: &HashMap<String, String, impl BuildHasher>,
|
||||
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||
) -> Option<quote::Tokens> {
|
||||
// Okay this is a little bit odd. We need to generate all extensions, even disabled ones,
|
||||
|
@ -1039,7 +1085,13 @@ pub fn generate_extension<'a>(
|
|||
const_cache,
|
||||
const_values,
|
||||
);
|
||||
let fp = generate_extension_commands(&extension.name, &extension.children, cmd_map, fn_cache);
|
||||
let fp = generate_extension_commands(
|
||||
&extension.name,
|
||||
&extension.children,
|
||||
cmd_map,
|
||||
cmd_aliases,
|
||||
fn_cache,
|
||||
);
|
||||
let q = quote! {
|
||||
#fp
|
||||
#extension_tokens
|
||||
|
@ -1972,23 +2024,31 @@ pub fn generate_feature<'a>(
|
|||
);
|
||||
let version = feature.version_string();
|
||||
let static_fn = if feature.is_version(1, 0) {
|
||||
generate_function_pointers(Ident::from("StaticFn"), &static_commands, fn_cache)
|
||||
generate_function_pointers(
|
||||
Ident::from("StaticFn"),
|
||||
&static_commands,
|
||||
&HashMap::new(),
|
||||
fn_cache,
|
||||
)
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
let entry = generate_function_pointers(
|
||||
Ident::from(format!("EntryFnV{}", version).as_str()),
|
||||
&entry_commands,
|
||||
&HashMap::new(),
|
||||
fn_cache,
|
||||
);
|
||||
let instance = generate_function_pointers(
|
||||
Ident::from(format!("InstanceFnV{}", version).as_str()),
|
||||
&instance_commands,
|
||||
&HashMap::new(),
|
||||
fn_cache,
|
||||
);
|
||||
let device = generate_function_pointers(
|
||||
Ident::from(format!("DeviceFnV{}", version).as_str()),
|
||||
&device_commands,
|
||||
&HashMap::new(),
|
||||
fn_cache,
|
||||
);
|
||||
quote! {
|
||||
|
@ -2154,6 +2214,24 @@ pub fn write_source_code(path: &Path) {
|
|||
.collect();
|
||||
|
||||
let spec = vk_parse::parse_file_as_vkxml(path);
|
||||
let cmd_aliases: HashMap<String, String> = spec2
|
||||
.0
|
||||
.iter()
|
||||
.filter_map(|item| match item {
|
||||
vk_parse::RegistryChild::Commands(cmds) => {
|
||||
let cmd_tuple_iter = cmds.children.iter().filter_map(|cmd| match cmd {
|
||||
vk_parse::Command::Alias { name, alias } => {
|
||||
Some((name.to_string(), alias.to_string()))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
Some(cmd_tuple_iter)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let commands: HashMap<vkxml::Identifier, &vkxml::Command> = spec
|
||||
.elements
|
||||
.iter()
|
||||
|
@ -2238,6 +2316,7 @@ pub fn write_source_code(path: &Path) {
|
|||
&commands,
|
||||
&mut const_cache,
|
||||
&mut const_values,
|
||||
&cmd_aliases,
|
||||
&mut fn_cache,
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue