Skip to content

Commit 64b2556

Browse files
authored
generator: Replace Extends{Root} with Extends<Root> trait (#971)
generator: Replace `Extends{Root}` with `StructExtends<Root>` generic Instead of emitting a new `trait` for every `Root` struct that is being implemented by one or more "child" structs (those that have `Root` in their `structextends`), create one trait that takes the root struct as a generic parameter, and implement that directly instead. This not only saves on having to define the `trait` for every `Root` struct but also paves the way towards providing default trait implementations for any pair of root and child struct, such as the `p_next` builder methods.
1 parent 98e5db8 commit 64b2556

File tree

9 files changed

+1850
-1969
lines changed

9 files changed

+1850
-1969
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
The expected length of this array can be queried with the respective `*_len()` variant of these functions.
2929
- `push_next()` has been renamed to `extend()` and marked as `unsafe`. Users are encouraged to call `push()` for singular structs instead. (#909)
3030
- Changed and renamed `RawPtr::as_raw_ptr(&self)` trait function to a by-value `RawPtr::to_raw_ptr(self)` function. (#965)
31+
- All `Extends{Root}` traits have been replaced with a single `Extends<Root>` trait using generics. (#971)
3132

3233
### Removed
3334

ash/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ rust-version = "1.69.0"
2424
[dependencies]
2525
libloading = { version = "0.8", optional = true }
2626

27+
[dev-dependencies]
28+
trybuild = "1.0"
29+
2730
[features]
2831
default = ["loaded", "debug", "std"]
2932
# Link the Vulkan loader at compile time.

ash/src/extensions/khr/acceleration_structure.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ impl crate::khr::acceleration_structure::Device {
263263
max_primitive_counts: &[u32],
264264
size_info: &mut vk::AccelerationStructureBuildSizesInfoKHR<'_>,
265265
) {
266-
assert_eq!(max_primitive_counts.len(), build_info.geometry_count as _);
266+
assert_eq!(
267+
max_primitive_counts.len(),
268+
build_info.geometry_count as usize
269+
);
267270

268271
(self.fp.get_acceleration_structure_build_sizes_khr)(
269272
self.handle,

ash/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,3 +268,9 @@ where
268268
}
269269
}
270270
}
271+
272+
#[test]
273+
fn trybuild() {
274+
let t = trybuild::TestCases::new();
275+
t.compile_fail("tests/fail/long_lived_root_struct_borrow.rs");
276+
}

ash/src/vk.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,21 @@ pub trait Handle: Sized {
5050
}
5151

5252
/// Structures implementing this trait are layout-compatible with [`BaseInStructure`] and
53-
/// [`BaseOutStructure`]. Such structures have an `s_type` field indicating its type, which
54-
/// must always match the value of [`TaggedStructure::STRUCTURE_TYPE`].
53+
/// [`BaseOutStructure`]. Such structures have an `s_type` field indicating its type, which must
54+
/// always match the value of [`TaggedStructure::STRUCTURE_TYPE`].
5555
pub unsafe trait TaggedStructure {
5656
const STRUCTURE_TYPE: StructureType;
5757
}
5858

59+
/// Implemented for every structure that extends base structure `B`. Concretely that means struct
60+
/// `B` is listed in its array of [`structextends` in the Vulkan registry][1].
61+
///
62+
/// Similar to [`TaggedStructure`], all `unsafe` implementers of this trait must guarantee that
63+
/// their structure is layout-compatible [`BaseInStructure`] and [`BaseOutStructure`].
64+
///
65+
/// [1]: https://registry.khronos.org/vulkan/specs/latest/styleguide.html#extensions-interactions
66+
pub unsafe trait Extends<B> {}
67+
5968
/// Iterates through the pointer chain. Includes the item that is passed into the function.
6069
/// Stops at the last [`BaseOutStructure`] that has a null [`BaseOutStructure::p_next`] field.
6170
pub(crate) unsafe fn ptr_chain_iter<T: ?Sized>(
@@ -222,6 +231,62 @@ mod tests {
222231
assert_eq!(chain, chain2);
223232
}
224233

234+
#[test]
235+
#[should_panic]
236+
fn disallow_nested_ptr_chains() {
237+
let mut generated_commands =
238+
vk::PhysicalDeviceDeviceGeneratedCommandsFeaturesEXT::default();
239+
let mut private_data = vk::PhysicalDevicePrivateDataFeatures {
240+
p_next: <*mut _>::cast(&mut generated_commands),
241+
..Default::default()
242+
};
243+
let _device_create_info = vk::DeviceCreateInfo::default().push(&mut private_data);
244+
}
245+
246+
#[test]
247+
fn test_nested_ptr_chains() {
248+
let mut generated_commands =
249+
vk::PhysicalDeviceDeviceGeneratedCommandsFeaturesEXT::default();
250+
let mut private_data = vk::PhysicalDevicePrivateDataFeatures {
251+
p_next: <*mut _>::cast(&mut generated_commands),
252+
..Default::default()
253+
};
254+
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::default();
255+
let mut corner = vk::PhysicalDeviceCornerSampledImageFeaturesNV::default();
256+
let chain = alloc::vec![
257+
<*mut _>::cast(&mut private_data),
258+
<*mut _>::cast(&mut generated_commands),
259+
<*mut _>::cast(&mut variable_pointers),
260+
<*mut _>::cast(&mut corner),
261+
];
262+
let mut device_create_info = vk::DeviceCreateInfo::default()
263+
.push(&mut corner)
264+
.push(&mut variable_pointers);
265+
// Insert private_data->generated_commands into the chain, such that generate_commands->variable_pointers->corner:
266+
device_create_info = unsafe { device_create_info.extend(&mut private_data) };
267+
let chain2: Vec<*mut vk::BaseOutStructure<'_>> = unsafe {
268+
vk::ptr_chain_iter(&mut device_create_info)
269+
.skip(1)
270+
.collect()
271+
};
272+
assert_eq!(chain, chain2);
273+
}
274+
275+
#[test]
276+
fn test_dynamic_add_to_ptr_chain() {
277+
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::default();
278+
let variable_pointers: &mut dyn vk::Extends<vk::DeviceCreateInfo<'_>> =
279+
&mut variable_pointers;
280+
let chain = alloc::vec![<*mut _>::cast(variable_pointers)];
281+
let mut device_create_info = vk::DeviceCreateInfo::default().push(variable_pointers);
282+
let chain2: Vec<*mut vk::BaseOutStructure<'_>> = unsafe {
283+
vk::ptr_chain_iter(&mut device_create_info)
284+
.skip(1)
285+
.collect()
286+
};
287+
assert_eq!(chain, chain2);
288+
}
289+
225290
#[test]
226291
fn test_debug_flags() {
227292
assert_eq!(

0 commit comments

Comments
 (0)