Implement push_next

This commit is contained in:
Maik Klein 2019-02-26 20:54:48 +01:00
parent c46a41e1d2
commit 4f7ca180f6
3 changed files with 84 additions and 43 deletions

View file

@ -28,11 +28,10 @@ impl RayTracing {
pdevice: vk::PhysicalDevice, pdevice: vk::PhysicalDevice,
) -> vk::PhysicalDeviceRayTracingPropertiesNV { ) -> vk::PhysicalDeviceRayTracingPropertiesNV {
let mut props_rt = vk::PhysicalDeviceRayTracingPropertiesNV::default(); let mut props_rt = vk::PhysicalDeviceRayTracingPropertiesNV::default();
let mut props = vk::PhysicalDeviceProperties2::builder() {
.next(&mut props_rt) let mut props = vk::PhysicalDeviceProperties2::builder().push_next(&mut props_rt);
.build(); instance.get_physical_device_properties2(pdevice, &mut props);
}
instance.get_physical_device_properties2(pdevice, &mut props);
props_rt props_rt
} }

View file

@ -3,13 +3,13 @@ extern crate ash;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
extern crate winapi; extern crate winapi;
extern crate winit;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
extern crate cocoa; extern crate cocoa;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
extern crate metal_rs as metal; extern crate metal_rs as metal;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
extern crate objc; extern crate objc;
extern crate winit;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use cocoa::appkit::{NSView, NSWindow}; use cocoa::appkit::{NSView, NSWindow};
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -406,19 +406,21 @@ impl ExampleBase {
.queue_priorities(&priorities) .queue_priorities(&priorities)
.build()]; .build()];
let mut variable_pointers = let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder()
vk::PhysicalDeviceVariablePointerFeatures::builder().variable_pointers(true).build(); .variable_pointers(true)
.build();
let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder() let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder()
.corner_sampled_image(true).build(); .corner_sampled_image(true)
.build();
let mut device_create_info = vk::DeviceCreateInfo::builder() let mut device_create_info = vk::DeviceCreateInfo::builder()
.next(&mut corner) .push_next(&mut corner)
.next(&mut variable_pointers) .push_next(&mut variable_pointers)
.queue_create_infos(&queue_info) .queue_create_infos(&queue_info)
.enabled_extension_names(&device_extension_names_raw) .enabled_extension_names(&device_extension_names_raw)
.enabled_features(&features) .enabled_features(&features)
.build(); .build();
for ptr in vk::ptr_chain_iter(&mut device_create_info){ for ptr in vk::ptr_chain_iter(&mut device_create_info) {
println!("{:?}", ptr); println!("{:?}", ptr);
} }
println!("--"); println!("--");

View file

@ -1378,7 +1378,10 @@ pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Opt
Some(q) Some(q)
} }
pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> { pub fn derive_setters(
_struct: &vkxml::Struct,
root_create_info_names: &HashSet<String>,
) -> Option<Tokens> {
if &_struct.name == "VkBaseInStructure" || &_struct.name == "VkBaseOutStructure" { if &_struct.name == "VkBaseInStructure" || &_struct.name == "VkBaseOutStructure" {
return None; return None;
} }
@ -1578,31 +1581,26 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
}) })
}); });
let mut nexts = Vec::new();
let extends_name = name_to_tokens(&format!("Extends{}", name)); let extends_name = name_to_tokens(&format!("Extends{}", name));
if let Some(extends) = &_struct.extends {
for target in extends.split(',') {
let target = match target {
// https://github.com/KhronosGroup/Vulkan-Docs/pull/870
"VkPhysicalDeviceProperties" => "VkPhysicalDeviceProperties2",
x => x,
};
let target_ident = name_to_tokens(&format!("Extends{}", name_to_tokens(target)));
nexts.push(quote! {
unsafe impl #target_ident for #name {}
});
}
}
let next_function = if has_next { let next_extends = _struct.extends.as_ref().map(|extends| {
let extends = extends
.split(',')
.find(|extend| root_create_info_names.contains(&extend.to_string()))
.expect("Should have a root create info");
name_to_tokens(&format!("Extends{}", name_to_tokens(&extends)))
});
// We only implement a next methods for root create infos
let next_function = if has_next && next_extends.is_none() {
quote! { quote! {
pub fn next<T: #extends_name>(mut self, next: &'a mut T) -> #name_builder<'a> { /// Prepend
pub fn push_next<T: #extends_name>(mut self, next: &'a mut T) -> #name_builder<'a> {
unsafe{ unsafe{
let last_extension = ptr_chain_iter(&mut self.inner) let next_ptr: *mut BaseOutStructure = ::std::mem::transmute(next);
.last() (*next_ptr).p_next = self.inner.p_next as _;
.expect("Initial ptr was null"); self.inner.p_next = next_ptr as _;
// Append the extension at the end
(*last_extension).p_next = next as *mut T as *mut _;
} }
self self
} }
@ -1611,7 +1609,9 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
quote! {} quote! {}
}; };
let next_trait = if has_next { // Root create infos come with their own trait that structs that extends this create info will
// implement
let next_trait = if has_next && _struct.extends.is_none() {
quote! { quote! {
pub unsafe trait #extends_name {} pub unsafe trait #extends_name {}
} }
@ -1619,6 +1619,15 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
quote! {} quote! {}
}; };
// If the struct extends something we need to implement the root create info trait.
let impl_extend_trait = if let Some(next_extends) = next_extends {
quote! {
unsafe impl #next_extends for #name {}
}
} else {
quote! {}
};
let q = quote! { let q = quote! {
impl #name { impl #name {
pub fn builder<'a>() -> #name_builder<'a> { pub fn builder<'a>() -> #name_builder<'a> {
@ -1634,11 +1643,10 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
marker: ::std::marker::PhantomData<&'a ()>, marker: ::std::marker::PhantomData<&'a ()>,
} }
#impl_extend_trait
#next_trait #next_trait
#(#nexts)*
impl<'a> ::std::ops::Deref for #name_builder<'a> { impl<'a> ::std::ops::Deref for #name_builder<'a> {
type Target = #name; type Target = #name;
@ -1646,6 +1654,7 @@ pub fn derive_setters(_struct: &vkxml::Struct) -> Option<Tokens> {
&self.inner &self.inner
} }
} }
impl<'a> ::std::ops::DerefMut for #name_builder<'a> { impl<'a> ::std::ops::DerefMut for #name_builder<'a> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner &mut self.inner
@ -1676,7 +1685,11 @@ pub fn manual_derives(_struct: &vkxml::Struct) -> Tokens {
_ => quote! {}, _ => quote! {},
} }
} }
pub fn generate_struct(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Tokens { pub fn generate_struct(
_struct: &vkxml::Struct,
root_create_info_names: &HashSet<String>,
union_types: &HashSet<&str>,
) -> Tokens {
let name = name_to_tokens(&_struct.name); let name = name_to_tokens(&_struct.name);
let members = _struct.elements.iter().filter_map(|elem| match *elem { let members = _struct.elements.iter().filter_map(|elem| match *elem {
vkxml::StructElement::Member(ref field) => Some(field), vkxml::StructElement::Member(ref field) => Some(field),
@ -1691,7 +1704,7 @@ pub fn generate_struct(_struct: &vkxml::Struct, union_types: &HashSet<&str>) ->
let debug_tokens = derive_debug(_struct, union_types); let debug_tokens = derive_debug(_struct, union_types);
let default_tokens = derive_default(_struct); let default_tokens = derive_default(_struct);
let setter_tokens = derive_setters(_struct); let setter_tokens = derive_setters(_struct, root_create_info_names);
let manual_derive_tokens = manual_derives(_struct); let manual_derive_tokens = manual_derives(_struct);
let dbg_str = if debug_tokens.is_none() { let dbg_str = if debug_tokens.is_none() {
quote!(Debug,) quote!(Debug,)
@ -1777,16 +1790,35 @@ fn generate_union(union: &vkxml::Union) -> Tokens {
} }
} }
} }
pub fn root_create_info_names(definitions: &[&vkxml::DefinitionsElement]) -> HashSet<String> {
definitions
.iter()
.filter_map(|definition| match *definition {
vkxml::DefinitionsElement::Struct(ref _struct) => {
let is_root_create_info = _struct.extends.is_none();
if is_root_create_info {
Some(_struct.name.clone())
} else {
None
}
}
_ => None,
})
.collect()
}
pub fn generate_definition( pub fn generate_definition(
definition: &vkxml::DefinitionsElement, definition: &vkxml::DefinitionsElement,
union_types: &HashSet<&str>, union_types: &HashSet<&str>,
root_create_info_names: &HashSet<String>,
bitflags_cache: &mut HashSet<Ident>, bitflags_cache: &mut HashSet<Ident>,
) -> Option<Tokens> { ) -> Option<Tokens> {
match *definition { match *definition {
vkxml::DefinitionsElement::Typedef(ref typedef) => Some(generate_typedef(typedef)), vkxml::DefinitionsElement::Typedef(ref typedef) => Some(generate_typedef(typedef)),
vkxml::DefinitionsElement::Struct(ref _struct) => { vkxml::DefinitionsElement::Struct(ref _struct) => Some(generate_struct(
Some(generate_struct(_struct, union_types)) _struct,
} root_create_info_names,
union_types,
)),
vkxml::DefinitionsElement::Bitmask(ref mask) => generate_bitmask(mask, bitflags_cache), vkxml::DefinitionsElement::Bitmask(ref mask) => generate_bitmask(mask, bitflags_cache),
vkxml::DefinitionsElement::Handle(ref handle) => generate_handle(handle), vkxml::DefinitionsElement::Handle(ref handle) => generate_handle(handle),
vkxml::DefinitionsElement::FuncPtr(ref fp) => Some(generate_funcptr(fp)), vkxml::DefinitionsElement::FuncPtr(ref fp) => Some(generate_funcptr(fp)),
@ -2124,9 +2156,17 @@ pub fn write_source_code(path: &Path) {
}) })
.collect::<HashSet<&str>>(); .collect::<HashSet<&str>>();
let root_create_info_names = root_create_info_names(&definitions);
let definition_code: Vec<_> = definitions let definition_code: Vec<_> = definitions
.into_iter() .into_iter()
.filter_map(|def| generate_definition(def, &union_types, &mut bitflags_cache)) .filter_map(|def| {
generate_definition(
def,
&union_types,
&root_create_info_names,
&mut bitflags_cache,
)
})
.collect(); .collect();
let feature_code: Vec<_> = features let feature_code: Vec<_> = features