Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Implement extension chaining #183

Merged
merged 21 commits into from
Mar 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ Builders implement `Deref` targeting their corresponding Vulkan struct, so refer
to Vulkan functions. This is encouraged as doing so allows Rust to check the lifetimes of captured objects are valid,
whereas calling `build` discards lifetime information, making inadvertent use-after-free errors more likely.

### Pointer chains

```Rust
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder();
let mut corner =
vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder();
;
let mut device_create_info = vk::DeviceCreateInfo::builder()
.push_next(&mut corner)
.push_next(&mut variable_pointers);
```

Pointer chains in builders differ from raw Vulkan. Instead of chaining every struct manually, you instead use `.push_next` on the struct that you are going to pass into the function. Those structs then get *pepended* into the chain.

`push_next` is also type checked, you can only add valid structs to the chain. Both the structs and the builders can be passed into `push_next`. Only builders for structs that can be passed into functions will implement a `push_next`.


### Flags and constants as associated constants

```Rust
Expand Down
12 changes: 10 additions & 2 deletions ash/src/extensions/experimental/amd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,11 +657,19 @@ impl<'a> ::std::ops::Deref for PhysicalDeviceWaveLimitPropertiesAmdBuilder<'a> {
}
}
impl<'a> PhysicalDeviceWaveLimitPropertiesAmdBuilder<'a> {
pub fn next<T>(mut self, next: &'a mut T) -> PhysicalDeviceWaveLimitPropertiesAmdBuilder<'a>
pub fn push_next<T>(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about where this definition is coming from. It's missing the chain support added to the generated version. I guess it's hand-written? Is that necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is handwritten. I am not sure what we should do about it. Maybe we should remove all the builder stuff because it will probably get out of date anyway?

I am going to update it anyway.

Everything in experimental won't adhere to semver, so we can remove some parts in the future. I probably should document that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, then, but why isn't this generated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is not included in the vk.xml. That is why it is inside the experimental module. @msiglreith basically reversed the API :). This will be deleted when it is officially included in the vk.xml.

mut self,
next: &'a mut T,
) -> PhysicalDeviceWaveLimitPropertiesAmdBuilder<'a>
where
T: ExtendsPhysicalDeviceWaveLimitPropertiesAmd,
{
self.inner.p_next = next as *mut T as *mut c_void;
unsafe {
let next_ptr = next as *mut T as *mut BaseOutStructure;
let last_next = ptr_chain_iter(next).last().unwrap();
(*last_next).p_next = self.inner.p_next as _;
self.inner.p_next = next_ptr as _;
}
self
}
pub fn build(self) -> PhysicalDeviceWaveLimitPropertiesAmd {
Expand Down
9 changes: 4 additions & 5 deletions ash/src/extensions/nv/ray_tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ impl RayTracing {
pdevice: vk::PhysicalDevice,
) -> vk::PhysicalDeviceRayTracingPropertiesNV {
let mut props_rt = vk::PhysicalDeviceRayTracingPropertiesNV::default();
let mut props = vk::PhysicalDeviceProperties2::builder()
.next(&mut props_rt)
.build();

instance.get_physical_device_properties2(pdevice, &mut props);
{
let mut props = vk::PhysicalDeviceProperties2::builder().push_next(&mut props_rt);
instance.get_physical_device_properties2(pdevice, &mut props);
}
props_rt
}

Expand Down
24 changes: 24 additions & 0 deletions ash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,27 @@ impl<'r, T> RawPtr<T> for Option<&'r T> {
}
}
}

#[cfg(test)]
mod tests {
use super::vk;
#[test]
fn test_ptr_chains() {
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder();
let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::builder();
let chain = vec![
&variable_pointers as *const _ as usize,
&corner as *const _ as usize,
];
let mut device_create_info = vk::DeviceCreateInfo::builder()
.push_next(&mut corner)
.push_next(&mut variable_pointers);
let chain2: Vec<usize> = unsafe {
vk::ptr_chain_iter(&mut device_create_info)
.skip(1)
.map(|ptr| ptr as usize)
.collect()
};
assert_eq!(chain, chain2);
}
}
Loading