Skip to content

Commit 28ffd5e

Browse files
committed
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 8b0d4c5 commit 28ffd5e

File tree

9 files changed

+3564
-2120
lines changed

9 files changed

+3564
-2120
lines changed

Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2626
- `get_pipeline_executable_statistics()`.
2727
The expected length of this array can be queried with the respective `*_len()` variant of these functions.
2828
- `push_next()` has been renamed to `extend()` and marked as `unsafe`. Users are encouraged to call `push()` for singular structs instead. (#909)
29+
- All `Extends{Root}` traits have been replaced with a single `Extends<Root>` trait using generics. (#971)
2930

3031
### Removed
3132

ash/Cargo.toml

+3
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

+4-1
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

+6
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,9 @@ where
255255
}
256256
}
257257
}
258+
259+
#[test]
260+
fn trybuild() {
261+
let t = trybuild::TestCases::new();
262+
t.compile_fail("tests/fail/long_lived_root_struct_borrow.rs");
263+
}

ash/src/vk.rs

+65
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ 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 [`vk::BaseInStructure`] and [`vk::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)