744: Add `backends!` and `backends_map!` macros to code duplication r=kvark a=Kimundi

**Description**
The source code is doing a lot of things duplicated for each backend, which leads to code duplication and harder to read code.
This PR attempts to improve the situation by introducing a `backends!` and `backends_map!` for doing the code duplication automatically.

**Testing**
The macro have unit tests for checking that they work correctly.



Co-authored-by: Marvin Löbel <loebel.marvin@gmail.com>
This commit is contained in:
bors[bot] 2020-06-22 23:52:54 +00:00 committed by GitHub
commit 29e286bdc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 523 additions and 323 deletions

View File

@ -2734,17 +2734,20 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
use crate::backend;
let mut callbacks = Vec::new();
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
self.poll_devices::<backend::Vulkan>(force_wait, &mut callbacks);
#[cfg(windows)]
self.poll_devices::<backend::Dx11>(force_wait, &mut callbacks);
#[cfg(windows)]
self.poll_devices::<backend::Dx12>(force_wait, &mut callbacks);
#[cfg(any(target_os = "ios", target_os = "macos"))]
self.poll_devices::<backend::Metal>(force_wait, &mut callbacks);
backends! {
#[vulkan] {
self.poll_devices::<backend::Vulkan>(force_wait, &mut callbacks);
}
#[metal] {
self.poll_devices::<backend::Metal>(force_wait, &mut callbacks);
}
#[dx12] {
self.poll_devices::<backend::Dx12>(force_wait, &mut callbacks);
}
#[dx11] {
self.poll_devices::<backend::Dx11>(force_wait, &mut callbacks);
}
}
fire_map_callbacks(callbacks);
}

View File

@ -553,18 +553,17 @@ pub struct Hubs<F: GlobalIdentityHandlerFactory> {
impl<F: GlobalIdentityHandlerFactory> Hubs<F> {
fn new(factory: &F) -> Self {
Hubs {
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
vulkan: Hub::new(factory),
#[cfg(any(target_os = "ios", target_os = "macos"))]
metal: Hub::new(factory),
#[cfg(windows)]
dx12: Hub::new(factory),
#[cfg(windows)]
dx11: Hub::new(factory),
backends! {
Hubs {
#[vulkan]
vulkan: Hub::new(factory),
#[metal]
metal: Hub::new(factory),
#[dx12]
dx12: Hub::new(factory),
#[dx11]
dx11: Hub::new(factory),
}
}
}
}
@ -592,18 +591,23 @@ impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
if !thread::panicking() {
log::info!("Dropping Global");
let mut surface_guard = self.surfaces.data.write();
// destroy hubs
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
self.hubs.vulkan.clear(&mut *surface_guard);
#[cfg(any(target_os = "ios", target_os = "macos"))]
self.hubs.metal.clear(&mut *surface_guard);
#[cfg(windows)]
self.hubs.dx12.clear(&mut *surface_guard);
#[cfg(windows)]
self.hubs.dx11.clear(&mut *surface_guard);
backends! {
#[vulkan] {
self.hubs.vulkan.clear(&mut *surface_guard);
}
#[metal] {
self.hubs.metal.clear(&mut *surface_guard);
}
#[dx12] {
self.hubs.dx12.clear(&mut *surface_guard);
}
#[dx11] {
self.hubs.dx11.clear(&mut *surface_guard);
}
}
// destroy surfaces
for (_, (surface, _)) in surface_guard.map.drain() {
self.instance.destroy_surface(surface);

View File

@ -59,61 +59,45 @@ pub struct Instance {
impl Instance {
pub fn new(name: &str, version: u32, backends: BackendBit) -> Self {
Instance {
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
vulkan: if backends.contains(Backend::Vulkan.into()) {
gfx_backend_vulkan::Instance::create(name, version).ok()
} else {
None
},
#[cfg(any(target_os = "ios", target_os = "macos"))]
metal: if backends.contains(Backend::Metal.into()) {
Some(gfx_backend_metal::Instance::create(name, version).unwrap())
} else {
None
},
#[cfg(windows)]
dx12: if backends.contains(Backend::Dx12.into()) {
gfx_backend_dx12::Instance::create(name, version).ok()
} else {
None
},
#[cfg(windows)]
dx11: if backends.contains(Backend::Dx11.into()) {
Some(gfx_backend_dx11::Instance::create(name, version).unwrap())
} else {
None
},
backends_map! {
let map = |(backend, backend_create)| {
if backends.contains(backend.into()) {
backend_create(name, version).ok()
} else {
None
}
};
Instance {
#[vulkan]
vulkan: map((Backend::Vulkan, gfx_backend_vulkan::Instance::create)),
#[metal]
metal: map((Backend::Metal, gfx_backend_metal::Instance::create)),
#[dx12]
dx12: map((Backend::Dx12, gfx_backend_dx12::Instance::create)),
#[dx11]
dx11: map((Backend::Dx11, gfx_backend_dx11::Instance::create)),
}
}
}
pub(crate) fn destroy_surface(&mut self, surface: Surface) {
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
unsafe {
if let Some(suf) = surface.vulkan {
self.vulkan.as_mut().unwrap().destroy_surface(suf);
}
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
unsafe {
if let Some(suf) = surface.metal {
self.metal.as_mut().unwrap().destroy_surface(suf);
}
}
#[cfg(windows)]
unsafe {
if let Some(suf) = surface.dx12 {
self.dx12.as_mut().unwrap().destroy_surface(suf);
}
if let Some(suf) = surface.dx11 {
self.dx11.as_mut().unwrap().destroy_surface(suf);
}
backends_map! {
let map = |(surface_backend, self_backend)| {
unsafe {
if let Some(suf) = surface_backend {
self_backend.as_mut().unwrap().destroy_surface(suf);
}
}
};
#[vulkan]
map((surface.vulkan, &mut self.vulkan)),
#[metal]
map((surface.metal, &mut self.metal)),
#[dx12]
map((surface.dx12, &mut self.dx12)),
#[dx11]
map((surface.dx11, &mut self.dx11)),
}
}
}
@ -300,35 +284,23 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
span!(_guard, INFO, "Instance::create_surface");
let surface = unsafe {
Surface {
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
vulkan: self
.instance
.vulkan
backends_map! {
let map = |inst| {
inst
.as_ref()
.and_then(|inst| inst.create_surface(handle).ok()),
#[cfg(any(target_os = "ios", target_os = "macos"))]
metal: self
.instance
.metal
.as_ref()
.and_then(|inst| inst.create_surface(handle).ok()),
#[cfg(windows)]
dx12: self
.instance
.dx12
.as_ref()
.and_then(|inst| inst.create_surface(handle).ok()),
#[cfg(windows)]
dx11: self
.instance
.dx11
.as_ref()
.and_then(|inst| inst.create_surface(handle).ok()),
.and_then(|inst| inst.create_surface(handle).ok())
};
Surface {
#[vulkan]
vulkan: map(&self.instance.vulkan),
#[metal]
metal: map(&self.instance.metal),
#[dx12]
dx12: map(&self.instance.dx12),
#[dx11]
dx11: map(&self.instance.dx11),
}
}
};
@ -347,69 +319,31 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut token = Token::root();
let mut adapters = Vec::new();
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
{
if let Some(ref inst) = instance.vulkan {
if let Some(id_vulkan) = inputs.find(Backend::Vulkan) {
for raw in inst.enumerate_adapters() {
let adapter = Adapter::new(raw, unsafe_extensions);
log::info!("Adapter Vulkan {:?}", adapter.raw.info);
adapters.push(backend::Vulkan::hub(self).adapters.register_identity(
id_vulkan.clone(),
adapter,
&mut token,
));
backends_map! {
let map = |(instance_field, backend, backend_info, backend_hub)| {
if let Some(inst) = instance_field {
if let Some(id_backend) = inputs.find(backend) {
for raw in inst.enumerate_adapters() {
let adapter = Adapter::new(raw, unsafe_extensions);
log::info!("Adapter {} {:?}", backend_info, adapter.raw.info);
adapters.push(backend_hub(self).adapters.register_identity(
id_backend.clone(),
adapter,
&mut token,
));
}
}
}
}
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
{
if let Some(ref inst) = instance.metal {
if let Some(id_metal) = inputs.find(Backend::Metal) {
for raw in inst.enumerate_adapters() {
let adapter = Adapter::new(raw, unsafe_extensions);
log::info!("Adapter Metal {:?}", adapter.raw.info);
adapters.push(backend::Metal::hub(self).adapters.register_identity(
id_metal.clone(),
adapter,
&mut token,
));
}
}
}
}
#[cfg(windows)]
{
if let Some(ref inst) = instance.dx12 {
if let Some(id_dx12) = inputs.find(Backend::Dx12) {
for raw in inst.enumerate_adapters() {
let adapter = Adapter::new(raw, unsafe_extensions);
log::info!("Adapter Dx12 {:?}", adapter.raw.info);
adapters.push(backend::Dx12::hub(self).adapters.register_identity(
id_dx12.clone(),
adapter,
&mut token,
));
}
}
}
if let Some(ref inst) = instance.dx11 {
if let Some(id_dx11) = inputs.find(Backend::Dx11) {
for raw in inst.enumerate_adapters() {
let adapter = Adapter::new(raw, unsafe_extensions);
log::info!("Adapter Dx11 {:?}", adapter.raw.info);
adapters.push(backend::Dx11::hub(self).adapters.register_identity(
id_dx11.clone(),
adapter,
&mut token,
));
}
}
}
};
#[vulkan]
map((&instance.vulkan, Backend::Vulkan, "Vulkan", backend::Vulkan::hub)),
#[metal]
map((&instance.metal, Backend::Metal, "Metal", backend::Metal::hub)),
#[dx12]
map((&instance.dx12, Backend::Dx12, "Dx12", backend::Dx12::hub)),
#[dx11]
map((&instance.dx11, Backend::Dx11, "Dx11", backend::Dx11::hub)),
}
adapters
@ -429,98 +363,62 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let compatible_surface = desc.compatible_surface.map(|id| &surface_guard[id]);
let mut device_types = Vec::new();
let id_vulkan = inputs.find(Backend::Vulkan);
let id_metal = inputs.find(Backend::Metal);
let id_dx12 = inputs.find(Backend::Dx12);
let id_dx11 = inputs.find(Backend::Dx11);
let mut id_vulkan = inputs.find(Backend::Vulkan);
let mut id_metal = inputs.find(Backend::Metal);
let mut id_dx12 = inputs.find(Backend::Dx12);
let mut id_dx11 = inputs.find(Backend::Dx11);
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
let mut adapters_vk = match instance.vulkan {
Some(ref inst) if id_vulkan.is_some() => {
let mut adapters = inst.enumerate_adapters();
if let Some(&Surface {
vulkan: Some(ref surface),
..
}) = compatible_surface
{
adapters.retain(|a| {
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.supports_queue_family(qf))
});
backends_map! {
let map = |(instance_backend, id_backend, surface_backend)| {
match instance_backend {
Some(ref inst) if id_backend.is_some() => {
let mut adapters = inst.enumerate_adapters();
if let Some(surface_backend) = compatible_surface.and_then(surface_backend) {
adapters.retain(|a| {
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface_backend.supports_queue_family(qf))
});
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
_ => Vec::new(),
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
_ => Vec::new(),
};
#[cfg(any(target_os = "ios", target_os = "macos"))]
let mut adapters_mtl = match instance.metal {
Some(ref inst) if id_metal.is_some() => {
let mut adapters = inst.enumerate_adapters();
if let Some(&Surface {
metal: Some(ref surface),
..
}) = compatible_surface
{
adapters.retain(|a| {
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.supports_queue_family(qf))
});
};
// NB: The internal function definitions are a workaround for Rust
// being weird with lifetimes for closure literals...
#[vulkan]
let adapters_vk = map((&instance.vulkan, &id_vulkan, {
fn surface_vulkan(surf: &Surface) -> Option<&GfxSurface<backend::Vulkan>> {
surf.vulkan.as_ref()
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
_ => Vec::new(),
};
#[cfg(windows)]
let mut adapters_dx12 = match instance.dx12 {
Some(ref inst) if id_dx12.is_some() => {
let mut adapters = inst.enumerate_adapters();
if let Some(&Surface {
dx12: Some(ref surface),
..
}) = compatible_surface
{
adapters.retain(|a| {
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.supports_queue_family(qf))
});
surface_vulkan
}));
#[metal]
let adapters_mtl = map((&instance.metal, &id_metal, {
fn surface_metal(surf: &Surface) -> Option<&GfxSurface<backend::Metal>> {
surf.metal.as_ref()
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
_ => Vec::new(),
};
#[cfg(windows)]
let mut adapters_dx11 = match instance.dx11 {
Some(ref inst) if id_dx11.is_some() => {
let mut adapters = inst.enumerate_adapters();
if let Some(&Surface {
dx11: Some(ref surface),
..
}) = compatible_surface
{
adapters.retain(|a| {
a.queue_families
.iter()
.find(|qf| qf.queue_type().supports_graphics())
.map_or(false, |qf| surface.supports_queue_family(qf))
});
surface_metal
}));
#[dx12]
let adapters_dx12 = map((&instance.dx12, &id_dx12, {
fn surface_dx12(surf: &Surface) -> Option<&GfxSurface<backend::Dx12>> {
surf.dx12.as_ref()
}
device_types.extend(adapters.iter().map(|ad| ad.info.device_type.clone()));
adapters
}
_ => Vec::new(),
};
surface_dx12
}));
#[dx11]
let adapters_dx11 = map((&instance.dx11, &id_dx11, {
fn surface_dx11(surf: &Surface) -> Option<&GfxSurface<backend::Dx11>> {
surf.dx11.as_ref()
}
surface_dx11
}));
}
if device_types.is_empty() {
log::warn!("No adapters are available!");
@ -563,64 +461,39 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
let mut selected = preferred_gpu.unwrap_or(0);
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
{
if selected < adapters_vk.len() {
let adapter = Adapter::new(adapters_vk.swap_remove(selected), unsafe_extensions);
log::info!("Adapter Vulkan {:?}", adapter.raw.info);
let id = backend::Vulkan::hub(self).adapters.register_identity(
id_vulkan.unwrap(),
adapter,
&mut token,
);
return Some(id);
}
selected -= adapters_vk.len();
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
{
if selected < adapters_mtl.len() {
let adapter = Adapter::new(adapters_mtl.swap_remove(selected), unsafe_extensions);
log::info!("Adapter Metal {:?}", adapter.raw.info);
let id = backend::Metal::hub(self).adapters.register_identity(
id_metal.unwrap(),
adapter,
&mut token,
);
return Some(id);
}
selected -= adapters_mtl.len();
}
#[cfg(windows)]
{
if selected < adapters_dx12.len() {
let adapter = Adapter::new(adapters_dx12.swap_remove(selected), unsafe_extensions);
log::info!("Adapter Dx12 {:?}", adapter.raw.info);
let id = backend::Dx12::hub(self).adapters.register_identity(
id_dx12.unwrap(),
adapter,
&mut token,
);
return Some(id);
}
selected -= adapters_dx12.len();
if selected < adapters_dx11.len() {
let adapter = Adapter::new(adapters_dx11.swap_remove(selected), unsafe_extensions);
log::info!("Adapter Dx11 {:?}", adapter.raw.info);
let id = backend::Dx11::hub(self).adapters.register_identity(
id_dx11.unwrap(),
adapter,
&mut token,
);
return Some(id);
}
selected -= adapters_dx11.len();
backends_map! {
let map = |(info_adapter, id_backend, mut adapters_backend, backend_hub)| {
if selected < adapters_backend.len() {
let adapter = Adapter::new(adapters_backend.swap_remove(selected), unsafe_extensions);
log::info!("Adapter {} {:?}", info_adapter, adapter.raw.info);
let id = backend_hub(self).adapters.register_identity(
id_backend.take().unwrap(),
adapter,
&mut token,
);
return Some(id);
}
selected -= adapters_backend.len();
};
#[vulkan]
map(("Vulkan", &mut id_vulkan, adapters_vk, backend::Vulkan::hub)),
#[metal]
map(("Metal", &mut id_metal, adapters_mtl, backend::Metal::hub)),
#[dx12]
map(("Dx12", &mut id_dx12, adapters_dx12, backend::Dx12::hub)),
#[dx11]
map(("Dx11", &mut id_dx11, adapters_dx11, backend::Dx11::hub)),
}
let _ = (selected, id_vulkan, id_metal, id_dx12, id_dx11);
let _ = (
selected,
id_vulkan.take(),
id_metal.take(),
id_dx12.take(),
id_dx11.take(),
);
log::warn!("Some adapters are present, but enumerating them failed!");
None
}

View File

@ -9,19 +9,23 @@
unused_qualifications
)]
#[macro_use]
mod macros;
pub mod backend {
#[cfg(windows)]
pub use gfx_backend_dx11::Backend as Dx11;
#[cfg(windows)]
pub use gfx_backend_dx12::Backend as Dx12;
pub use gfx_backend_empty::Backend as Empty;
#[cfg(any(target_os = "ios", target_os = "macos"))]
pub use gfx_backend_metal::Backend as Metal;
#[cfg(any(
not(any(target_os = "ios", target_os = "macos")),
feature = "gfx-backend-vulkan"
))]
pub use gfx_backend_vulkan::Backend as Vulkan;
#[cfg(any(target_os = "ios", target_os = "macos"))]
pub use gfx_backend_metal::Backend as Metal;
#[cfg(windows)]
pub use gfx_backend_dx12::Backend as Dx12;
#[cfg(windows)]
pub use gfx_backend_dx11::Backend as Dx11;
}
pub mod binding_model;

316
wgpu-core/src/macros.rs Normal file
View File

@ -0,0 +1,316 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
macro_rules! backends {
// one let statement per backend
(
#[vulkan] let $vk_field:pat = $vk_expr:expr;
#[metal] let $mtl_field:pat = $mtl_expr:expr;
#[dx12] let $dx12_field:pat = $dx12_expr:expr;
#[dx11] let $dx11_field:pat = $dx11_expr:expr;
) => {
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
let $vk_field = $vk_expr;
#[cfg(any(target_os = "ios", target_os = "macos"))]
let $mtl_field = $mtl_expr;
#[cfg(windows)]
let $dx12_field = $dx12_expr;
#[cfg(windows)]
let $dx11_field = $dx11_expr;
};
// one block statement per backend
(
#[vulkan] $vk_block:block
#[metal] $mtl_block:block
#[dx12] $dx12_block:block
#[dx11] $dx11_block:block
) => {
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
$vk_block
#[cfg(any(target_os = "ios", target_os = "macos"))]
$mtl_block
#[cfg(windows)]
$dx12_block
#[cfg(windows)]
$dx11_block
};
// a struct constructor with one field per backend
(
$Struct:path {
#[vulkan] $vk_field:ident: $vk_expr:expr,
#[metal] $mtl_field:ident: $mtl_expr:expr,
#[dx12] $dx12_field:ident: $dx12_expr:expr,
#[dx11] $dx11_field:ident: $dx11_expr:expr,
}
) => {{
$Struct {
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
$vk_field: $vk_expr,
#[cfg(any(target_os = "ios", target_os = "macos"))]
$mtl_field: $mtl_expr,
#[cfg(windows)]
$dx12_field: $dx12_expr,
#[cfg(windows)]
$dx11_field: $dx11_expr,
}
}};
}
macro_rules! backends_map {
// one let statement per backend with mapped data
(
let map = |$backend:pat| $map:block;
$(
#[$backend_attr:ident] let $pat:pat = map($expr:expr);
)*
) => {
backends! {
$(
#[$backend_attr]
let $pat = {
let $backend = $expr;
$map
};
)*
}
};
// one block statement per backend with mapped data
(
let map = |$backend:pat| $map:block;
$(
#[$backend_attr:ident] map($expr:expr),
)*
) => {
backends! {
$(
#[$backend_attr]
{
let $backend = $expr;
$map
}
)*
}
};
// a struct constructor with one field per backend with mapped data
(
let map = |$backend:pat| $map:block;
$Struct:path {
$(
#[$backend_attr:ident] $ident:ident : map($expr:expr),
)*
}
) => {
backends! {
$Struct {
$(
#[$backend_attr]
$ident: {
let $backend = $expr;
$map
},
)*
}
}
};
}
#[test]
fn test_backend_macro() {
struct Foo {
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
vulkan: u32,
#[cfg(any(target_os = "ios", target_os = "macos"))]
metal: u32,
#[cfg(windows)]
dx12: u32,
#[cfg(windows)]
dx11: u32,
}
// test struct construction
let test_foo: Foo = backends_map! {
let map = |init| { init - 100 };
Foo {
#[vulkan] vulkan: map(101),
#[metal] metal: map(102),
#[dx12] dx12: map(103),
#[dx11] dx11: map(104),
}
};
let mut vec = Vec::new();
// test basic statement-per-backend
backends_map! {
let map = |(id, chr)| {
vec.push((id, chr));
};
#[vulkan]
map((test_foo.vulkan, 'a')),
#[metal]
map((test_foo.metal, 'b')),
#[dx12]
map((test_foo.dx12, 'c')),
#[dx11]
map((test_foo.dx11, 'd')),
}
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
assert!(vec.contains(&(1, 'a')));
#[cfg(any(target_os = "ios", target_os = "macos"))]
assert!(vec.contains(&(2, 'b')));
#[cfg(windows)]
assert!(vec.contains(&(3, 'c')));
#[cfg(windows)]
assert!(vec.contains(&(4, 'd')));
// test complex statement-per-backend
backends_map! {
let map = |(id, pred, code)| {
if pred(id) {
code();
}
};
#[vulkan]
map((test_foo.vulkan, |v| v == 1, || println!("vulkan"))),
#[metal]
map((test_foo.metal, |v| v == 2, || println!("metal"))),
#[dx12]
map((test_foo.dx12, |v| v == 3, || println!("dx12"))),
#[dx11]
map((test_foo.dx11, |v| v == 4, || println!("dx11"))),
}
// test struct construction 2
let test_foo_2: Foo = backends! {
Foo {
#[vulkan]
vulkan: 1,
#[metal]
metal: 2,
#[dx12]
dx12: 3,
#[dx11]
dx11: 4,
}
};
backends! {
#[vulkan]
let var_vulkan = test_foo_2.vulkan;
#[metal]
let var_metal = test_foo_2.metal;
#[dx12]
let var_dx12 = test_foo_2.dx12;
#[dx11]
let var_dx11 = test_foo_2.dx11;
}
backends_map! {
let map = |(id, chr, var)| { (chr, id, var) };
#[vulkan]
let var_vulkan = map((test_foo_2.vulkan, 'a', var_vulkan));
#[metal]
let var_metal = map((test_foo_2.metal, 'b', var_metal));
#[dx12]
let var_dx12 = map((test_foo_2.dx12, 'c', var_dx12));
#[dx11]
let var_dx11 = map((test_foo_2.dx11, 'd', var_dx11));
}
backends! {
#[vulkan]
{
println!("backend int: {:?}", var_vulkan);
}
#[metal]
{
println!("backend int: {:?}", var_metal);
}
#[dx12]
{
println!("backend int: {:?}", var_dx12);
}
#[dx11]
{
println!("backend int: {:?}", var_dx11);
}
}
#[cfg(any(
windows,
all(unix, not(any(target_os = "ios", target_os = "macos"))),
feature = "gfx-backend-vulkan",
))]
let _ = var_vulkan;
#[cfg(any(target_os = "ios", target_os = "macos"))]
let _ = var_metal;
#[cfg(windows)]
let _ = var_dx12;
#[cfg(windows)]
let _ = var_dx11;
}