capi: extend config_struct macro to handle overrides
This commit is contained in:
parent
9b40c10466
commit
321e30a0f1
|
@ -146,29 +146,85 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! config_set_field {
|
macro_rules! config_set_field {
|
||||||
($options:ident.$field:ident <- $ptr:ident) => {
|
(@POINTER $options:ident.$field:ident <- $ptr:ident) => {
|
||||||
$options.$field = unsafe { ::std::ptr::addr_of!((*$ptr).$field).read() };
|
$options.$field = unsafe { ::std::ptr::addr_of!((*$ptr).$field).read() };
|
||||||
};
|
};
|
||||||
|
(@POINTER @NEGATIVE $options:ident.$field:ident <- $ptr:ident) => {
|
||||||
|
$options.$field = unsafe { !::std::ptr::addr_of!((*$ptr).$field).read() };
|
||||||
|
};
|
||||||
|
(@LITERAL $options:ident.$field:ident <- $value:literal) => {
|
||||||
|
$options.$field = $value;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! config_version_set {
|
macro_rules! config_version_set {
|
||||||
($version:literal => [$($field:ident),+ $(,)?] ($options:ident <- $ptr:ident)) => {
|
// "optimized" version for normal behaviour
|
||||||
let version = unsafe { ::std::ptr::addr_of!((*$ptr).version).read() };
|
(@ROOT $realver:ident $version:literal => [$($field:ident),+ $(,)?] ($options:ident <- $ptr:ident)) => {
|
||||||
#[allow(unused_comparisons)]
|
#[allow(unused_comparisons)]
|
||||||
if version >= $version {
|
if $realver >= $version {
|
||||||
$($crate::ctypes::config_set_field!($options.$field <- $ptr);)+
|
$($crate::ctypes::config_set_field!(@POINTER $options.$field <- $ptr);)+
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Repeater
|
||||||
|
(@ROOT $realver:ident $version:literal => [$($field:tt),+ $(,)?] ($options:ident <- $ptr:ident)) => {
|
||||||
|
$(crate::ctypes::config_version_set!(@SINGLE $realver $version => [$field] ($options <- $ptr));)+
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allow overriding default value with a literal for older versions
|
||||||
|
(@SINGLE $realver:ident $version:literal => [($field:ident: $value:literal)] ($options:ident <- $ptr:ident)) => {
|
||||||
|
#[allow(unused_comparisons)]
|
||||||
|
if $realver >= $version {
|
||||||
|
$crate::ctypes::config_set_field!(@LITERAL $options.$field <- $value);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allow negation of prior variables that is version dependent.
|
||||||
|
(@SINGLE $realver:ident $version:literal => [(!$field:ident)] ($options:ident <- $ptr:ident)) => {
|
||||||
|
#[allow(unused_comparisons)]
|
||||||
|
if $realver >= $version {
|
||||||
|
$crate::ctypes::config_set_field!(@POINTER @NEGATIVE $options.$field <- $ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(@SINGLE $realver:ident $version:literal => [$field:ident] ($options:ident <- $ptr:ident)) => {
|
||||||
|
#[allow(unused_comparisons)]
|
||||||
|
if $realver >= $version {
|
||||||
|
$crate::ctypes::config_set_field!(@POINTER $options.$field <- $ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro to declare a configuration struct, with options to change behaviour based on
|
||||||
|
/// API version.
|
||||||
|
///
|
||||||
|
/// For example following declaration does the following
|
||||||
|
///
|
||||||
|
/// * Declare `frames_in_flight`, `use_dynamic_rendering` for API version 0, with the following forward compatibility statements
|
||||||
|
/// * Inverts the behaviour of `use_dynamic_rendering` compared to API version 1.
|
||||||
|
/// * `disable_cache` is defaulted to `true` for API version 0, regardless of `Default::default`
|
||||||
|
/// but is not declared for API 0.
|
||||||
|
/// * Declare `use_dynamic_rendering` with normal behaviour, and `disable_cache` for API version 1.
|
||||||
|
/// * All fields that are undeclared inherit `Default::default`
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// config_struct! {
|
||||||
|
/// impl FilterChainOptions => filter_chain_vk_opt_t {
|
||||||
|
/// 0 => [frames_in_flight, (!use_dynamic_rendering), (disable_cache: true)];
|
||||||
|
/// 1 => [use_dynamic_rendering, disable_cache];
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
macro_rules! config_struct {
|
macro_rules! config_struct {
|
||||||
(impl $rust:ty => $capi:ty {$($version:literal => [$($field:ident),+ $(,)?]);+ $(;)?}) => {
|
(impl $rust:ty => $capi:ty {$($version:literal => [$($field:tt),+]);+ $(;)?}) => {
|
||||||
impl $crate::ctypes::FromUninit<$rust> for $capi {
|
impl $crate::ctypes::FromUninit<$rust> for $capi {
|
||||||
fn from_uninit(value: ::std::mem::MaybeUninit<Self>) -> $rust {
|
fn from_uninit(value: ::std::mem::MaybeUninit<Self>) -> $rust {
|
||||||
let ptr = value.as_ptr();
|
let ptr = value.as_ptr();
|
||||||
|
let version = unsafe { ::std::ptr::addr_of!((*ptr).version).read() };
|
||||||
|
|
||||||
let mut options = <$rust>::default();
|
let mut options = <$rust>::default();
|
||||||
$(
|
$(
|
||||||
$crate::ctypes::config_version_set!($version => [$($field),+] (options <- ptr));
|
$crate::ctypes::config_version_set!(@ROOT version $version => [$($field),+] (options <- ptr));
|
||||||
)+
|
)+
|
||||||
options
|
options
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue