@@ -56,6 +56,15 @@ pub unsafe trait TaggedStructure {
56
56
const STRUCTURE_TYPE : StructureType ;
57
57
}
58
58
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
+
59
68
/// Iterates through the pointer chain. Includes the item that is passed into the function.
60
69
/// Stops at the last [`BaseOutStructure`] that has a null [`BaseOutStructure::p_next`] field.
61
70
pub ( crate ) unsafe fn ptr_chain_iter < T : ?Sized > (
@@ -222,6 +231,62 @@ mod tests {
222
231
assert_eq ! ( chain, chain2) ;
223
232
}
224
233
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
+
225
290
#[ test]
226
291
fn test_debug_flags ( ) {
227
292
assert_eq ! (
0 commit comments