Merge #196
196: Rewrite builder in the readme r=MaikKlein a=MaikKlein Co-authored-by: Maik Klein <maikklein@googlemail.com> Co-authored-by: Benjamin Saunders <ben.e.saunders@gmail.com>
This commit is contained in:
commit
775a7d035d
3 changed files with 1267 additions and 6 deletions
43
README.md
43
README.md
|
@ -72,15 +72,46 @@ let desc_alloc_info = vk::DescriptorSetAllocateInfo {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
### Builder pattern
|
### Builder pattern
|
||||||
|
|
||||||
```Rust
|
```Rust
|
||||||
let pipeline_vertex_input_state_create_info = vk::PipelineVertexInputStateCreateInfo::builder()
|
// We lose all lifetime information when we call `.build()`. Be carefull!
|
||||||
.vertex_binding_descriptions(&Vertex::binding_descriptions())
|
let queue_info = [vk::DeviceQueueCreateInfo::builder()
|
||||||
.vertex_attribute_descriptions(&Vertex::attribute_descriptions()).build();
|
.queue_family_index(queue_family_index)
|
||||||
|
.queue_priorities(&priorities)
|
||||||
|
.build()];
|
||||||
|
|
||||||
|
// We don't need to call build here because builders implement `Deref`.
|
||||||
|
let device_create_info = vk::DeviceCreateInfo::builder()
|
||||||
|
.queue_create_infos(&queue_info)
|
||||||
|
.enabled_extension_names(&device_extension_names_raw)
|
||||||
|
.enabled_features(&features);
|
||||||
|
|
||||||
|
let device: Device = instance
|
||||||
|
.create_device(pdevice, &device_create_info, None)
|
||||||
|
.unwrap();
|
||||||
```
|
```
|
||||||
|
|
||||||
Builders implement `Deref` targeting their corresponding Vulkan struct, so references to builders can be passed directly
|
Builders have an explicit lifetime, and are marked as `#[repr(transparent)]`.
|
||||||
to Vulkan functions. This is encouraged as doing so allows Rust to check the lifetimes of captured objects are valid,
|
```Rust
|
||||||
whereas calling `build` discards lifetime information, making inadvertent use-after-free errors more likely.
|
#[repr(transparent)]
|
||||||
|
pub struct DeviceCreateInfoBuilder<'a> {
|
||||||
|
inner: DeviceCreateInfo,
|
||||||
|
marker: ::std::marker::PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
impl<'a> DeviceCreateInfoBuilder<'a> {
|
||||||
|
//...
|
||||||
|
pub fn queue_create_infos(
|
||||||
|
mut self,
|
||||||
|
queue_create_infos: &'a [DeviceQueueCreateInfo],
|
||||||
|
) -> DeviceCreateInfoBuilder<'a> {...}
|
||||||
|
//...
|
||||||
|
```
|
||||||
|
|
||||||
|
Every reference has to live as long as the builder itself. Builders implement `Deref` targeting their corresponding Vulkan struct, so references to builders can be passed directly
|
||||||
|
to Vulkan functions.
|
||||||
|
|
||||||
|
Calling `.build()` will **discard** that lifetime because Vulkan structs use raw pointers internally. This should be avoided as much as possible because this can easily lead to dangling pointers. If `.build()` has to be called, it should be called as late as possible. [Lifetimes of temporaries](https://doc.rust-lang.org/reference/expressions.html#temporary-lifetimes) are extended to the enclosing statement, ensuring they are valid for the duration of a Vulkan call occurring in the same statement.
|
||||||
|
|
||||||
|
|
||||||
### Pointer chains
|
### Pointer chains
|
||||||
|
|
||||||
|
|
1227
ash/src/vk.rs
1227
ash/src/vk.rs
File diff suppressed because it is too large
Load diff
|
@ -1726,6 +1726,9 @@ pub fn derive_setters(
|
||||||
|
|
||||||
#next_function
|
#next_function
|
||||||
|
|
||||||
|
/// Calling build will **discard** all the lifetime information. Only call this if
|
||||||
|
/// necessary! Builders implement `Deref` targeting their corresponding Vulkan struct,
|
||||||
|
/// so references to builders can be passed directly to Vulkan functions.
|
||||||
pub fn build(self) -> #name {
|
pub fn build(self) -> #name {
|
||||||
self.inner
|
self.inner
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue