Skip to main content

supasim_dev_utils/
lib.rs

1/* BEGIN LICENSE
2  SupaSim, a GPGPU and simulation toolkit.
3  Copyright (C) 2025 SupaMaggie70 (Magnus Larsson)
4
5
6  SupaSim is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License
8  as published by the Free Software Foundation; either version 3
9  of the License, or (at your option) any later version.
10
11  SupaSim is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15
16  You should have received a copy of the GNU General Public License
17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18END LICENSE */
19
20pub use paste;
21use std::fmt::Write;
22use tracing_subscriber::{
23    layer::{Context, SubscriberExt},
24    util::SubscriberInitExt,
25};
26
27pub struct EnterSpanPrinter;
28
29impl<S> tracing_subscriber::Layer<S> for EnterSpanPrinter
30where
31    S: tracing::Subscriber,
32    S: for<'a> tracing_subscriber::registry::LookupSpan<'a>,
33{
34    fn on_enter(&self, id: &tracing::Id, ctx: Context<'_, S>) {
35        if let Some(span_ref) = ctx.span(id) {
36            let name = span_ref.name();
37
38            // Get all field values as a string
39            let mut fields = String::new();
40            if let Some(ext) = span_ref
41                .extensions()
42                .get::<tracing_subscriber::fmt::FormattedFields<
43                    tracing_subscriber::fmt::format::DefaultFields,
44                >>()
45            {
46                write!(fields, "{ext}").ok();
47            }
48
49            println!("\t{name} [{fields}]");
50        }
51    }
52}
53pub fn setup_trace_printer() {
54    let _ = tracing_subscriber::registry()
55        .with(EnterSpanPrinter)
56        .with(tracing_subscriber::fmt::layer())
57        .try_init();
58}
59pub fn setup_trace_printer_if_env() {
60    if let Ok(a) = std::env::var("SUPASIM_LOG_FULL_TRACE")
61        && &a != "0"
62    {
63        setup_trace_printer();
64    }
65    let _ = env_logger::builder()
66        .filter_level(log::LevelFilter::Info)
67        .parse_default_env()
68        .try_init();
69}
70#[macro_export]
71macro_rules! all_backend_tests_inner {
72    ($func_name:ident, $backend_name:literal, $instance_create:block, $test_name:ident, $hal_backend: ident) => {
73        #[test]
74        pub fn $func_name() {
75            if std::env::var(concat!("SUPASIM_SKIP_BACKEND_", $backend_name))
76                .is_ok_and(|a| &a != "0" && &a != "false" && !a.is_empty())
77            {
78                return;
79            }
80            $crate::setup_trace_printer_if_env();
81            log::info!("{} test", $backend_name);
82            let instance = $instance_create;
83            let instance = instance.expect(&format!("Failed to create {} instance", $backend_name));
84            log::info!("Created {} instance", $backend_name);
85            $test_name::<hal::$hal_backend>(instance).unwrap();
86        }
87    };
88}
89#[macro_export]
90macro_rules! all_backend_tests {
91    ($test_name:ident) => {
92        $crate::paste::paste! {
93            $crate::all_backend_tests_inner!([<$test_name _dummy>], "DUMMY", {
94                hal::Dummy::create_instance()
95            }, $test_name, Dummy);
96
97            #[cfg(feature = "vulkan")]
98            $crate::all_backend_tests_inner!([<$test_name _vulkan>], "VULKAN", {
99                hal::Vulkan::create_instance(true)
100            }, $test_name, Vulkan);
101
102            #[cfg(all(feature = "metal", target_vendor = "apple"))]
103            $crate::all_backend_tests_inner!([<$test_name _metal>], "METAL", {
104                hal::Metal::create_instance()
105            }, $test_name, Metal);
106
107            #[cfg(feature = "wgpu")]
108            $crate::all_backend_tests_inner!([<$test_name _wgpu_vulkan>], "WGPU_VULKAN", {
109                hal::wgpu::Wgpu::create_instance(true, hal::wgpu::Backends::VULKAN, None)
110            }, $test_name, Wgpu);
111
112            #[cfg(all(feature = "wgpu", target_vendor = "apple"))]
113            $crate::all_backend_tests_inner!([<$test_name _wgpu_metal>], "WGPU_METAL", {
114                hal::wgpu::Wgpu::create_instance(true, hal::wgpu::Backends::METAL, None)
115            }, $test_name, Wgpu);
116
117            #[cfg(all(feature = "wgpu", target_os = "windows"))]
118            $crate::all_backend_tests_inner!([<$test_name _wgpu_dx12>], "WGPU_DX12", {
119                hal::wgpu::Wgpu::create_instance(true, hal::wgpu::Backends::DX12, None)
120            }, $test_name, Wgpu);
121        }
122    };
123}