From 4752fcdcf2733e393410001fbfc9a5a3ec5179ee Mon Sep 17 00:00:00 2001 From: aiwhskruht <217834908+aiwhskruht@users.noreply.github.com> Date: Tue, 2 Sep 2025 08:57:54 -0700 Subject: [PATCH] Api traits test code (#487) Add initial templated API test support. This needs to be improved to use an attribute macro, but that will require some major surgery :( --- Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 1 + cuda_macros/src/lib.rs | 39 +++++++++++++++++++++++++++++++++++++- cuda_tests/Cargo.toml | 16 ++++++++++++++++ cuda_tests/src/cuda/mod.rs | 8 ++++++++ cuda_tests/src/lib.rs | 24 +++++++++++++++++++++++ zluda/Cargo.toml | 1 + zluda/src/cuda_impl/mod.rs | 1 - zluda/src/cuda_impl/rt.rs | 2 -- zluda/src/lib.rs | 3 +++ zluda/src/tests/mod.rs | 8 ++++++++ 11 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 cuda_tests/Cargo.toml create mode 100644 cuda_tests/src/cuda/mod.rs create mode 100644 cuda_tests/src/lib.rs delete mode 100644 zluda/src/cuda_impl/mod.rs delete mode 100644 zluda/src/cuda_impl/rt.rs create mode 100644 zluda/src/tests/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 26efea5..c0efe2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,6 +447,21 @@ dependencies = [ "syn 2.0.89", ] +[[package]] +name = "cuda_tests" +version = "0.0.0" +dependencies = [ + "cuda_macros", + "cuda_types", + "dtor 0.0.6", + "lazy_static", + "lz4-sys", + "num_enum", + "paste", + "rustc-hash 1.1.0", + "tempfile", +] + [[package]] name = "cuda_types" version = "0.0.0" @@ -3714,6 +3729,7 @@ dependencies = [ "blake3", "comgr", "cuda_macros", + "cuda_tests", "cuda_types", "dark_api", "dtor 0.0.7", diff --git a/Cargo.toml b/Cargo.toml index 9415c8f..db4f75b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "comgr", "cuda_macros", "cuda_types", + "cuda_tests", "dark_api", "detours-sys", "ext/amd_comgr-sys", diff --git a/cuda_macros/src/lib.rs b/cuda_macros/src/lib.rs index 83baa64..58b4d0f 100644 --- a/cuda_macros/src/lib.rs +++ b/cuda_macros/src/lib.rs @@ -10,7 +10,7 @@ use syn::punctuated::Punctuated; use syn::visit_mut::VisitMut; use syn::{ bracketed, parse_macro_input, File, ForeignItem, ForeignItemFn, Ident, Item, Path, Signature, - Token, + Token, token }; const CUDA_RS: &'static str = include_str! {"cuda.rs"}; @@ -308,3 +308,40 @@ fn join( } } + +#[proc_macro] +pub fn generate_api_macro(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as ApiMacroInput); + let ApiMacroInput(_, trait_name, _, type_name, _, macro_name) = input; + let expanded = quote! { + struct #type_name; + macro_rules! #macro_name { + ($($abi:literal fn $fn_name:ident( $( $arg_id:ident : $arg_type:ty ),* ) -> $ret_type:ty;)*) => { + impl #trait_name for #type_name { + fn new() -> Self { Self } + $( + #[inline(always)] + fn $fn_name(&self, $( $arg_id : $arg_type ),* ) -> $ret_type { + unsafe { super::$fn_name( $( $arg_id ),* ) } + } + )* + } + }; + } + }; + TokenStream::from(expanded) +} +#[allow(dead_code)] +struct ApiMacroInput(token::Impl, Path, token::For, Path, token::Use, Ident); +impl syn::parse::Parse for ApiMacroInput { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + Ok(ApiMacroInput( + input.parse()?, // impl + input.parse()?, // trait + input.parse()?, // for + input.parse()?, // type + input.parse()?, // using + input.parse()? // macro + )) + } +} diff --git a/cuda_tests/Cargo.toml b/cuda_tests/Cargo.toml new file mode 100644 index 0000000..2ff6700 --- /dev/null +++ b/cuda_tests/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "cuda_tests" +version = "0.0.0" +authors = ["Andrzej Janik "] +edition = "2021" + +[dependencies] +cuda_types = { path = "../cuda_types" } +cuda_macros = { path = "../cuda_macros" } +lazy_static = "1.4" +num_enum = "0.4" +lz4-sys = "1.9" +tempfile = "3" +paste = "1.0" +rustc-hash = "1.1" +dtor = "0.0.6" diff --git a/cuda_tests/src/cuda/mod.rs b/cuda_tests/src/cuda/mod.rs new file mode 100644 index 0000000..a512158 --- /dev/null +++ b/cuda_tests/src/cuda/mod.rs @@ -0,0 +1,8 @@ +use crate::api_trait; +use cuda_types::cuda::*; + +cuda_macros::cuda_function_declarations!(api_trait); + +pub unsafe fn init_check(api: T) { + assert_eq!(api.cuInit(0), CUresult::SUCCESS); +} diff --git a/cuda_tests/src/lib.rs b/cuda_tests/src/lib.rs new file mode 100644 index 0000000..5141eb3 --- /dev/null +++ b/cuda_tests/src/lib.rs @@ -0,0 +1,24 @@ +#[macro_export] +macro_rules! api_trait { + ($($abi:literal fn $fn_name:ident( $($arg_id:ident : $arg_type:ty),* ) -> $ret_type:ty;)*) => { + pub trait Api { + fn new() -> Self; + $(fn $fn_name(&self, $( $arg_id : $arg_type ),* ) -> $ret_type;)* + } + }; +} + +#[macro_export] +macro_rules! api_test { + ($func:ident, $type:ty) => { + paste::paste! { + #[test] + #[allow(non_snake_case)] + fn [<$func _test>]() { + unsafe { $func::<$type>(<$type>::new()) } + } + } + }; +} + +pub mod cuda; diff --git a/zluda/Cargo.toml b/zluda/Cargo.toml index 144f9a3..923227d 100644 --- a/zluda/Cargo.toml +++ b/zluda/Cargo.toml @@ -27,6 +27,7 @@ zluda_common = { path = "../zluda_common" } blake3 = "1.8.2" serde = "1.0.219" serde_json = "1.0.142" +cuda_tests = { path = "../cuda_tests" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["heapapi", "std"] } diff --git a/zluda/src/cuda_impl/mod.rs b/zluda/src/cuda_impl/mod.rs deleted file mode 100644 index 63b9049..0000000 --- a/zluda/src/cuda_impl/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod rt; \ No newline at end of file diff --git a/zluda/src/cuda_impl/rt.rs b/zluda/src/cuda_impl/rt.rs deleted file mode 100644 index 3931bc3..0000000 --- a/zluda/src/cuda_impl/rt.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub enum ContextState {} -pub enum ContextStateManager {} diff --git a/zluda/src/lib.rs b/zluda/src/lib.rs index 2c6e2cd..e9559e8 100644 --- a/zluda/src/lib.rs +++ b/zluda/src/lib.rs @@ -160,3 +160,6 @@ cuda_macros::cuda_function_declarations!( ], implemented_in_function <= [cuLaunchKernel,] ); + +#[cfg(test)] +mod tests; diff --git a/zluda/src/tests/mod.rs b/zluda/src/tests/mod.rs new file mode 100644 index 0000000..3f32c70 --- /dev/null +++ b/zluda/src/tests/mod.rs @@ -0,0 +1,8 @@ +use cuda_macros::generate_api_macro; +use cuda_tests::api_test; +use cuda_tests::cuda::*; + +generate_api_macro!(impl cuda_tests::cuda::Api for TestApi use implemented_test); +cuda_macros::cuda_function_declarations!(implemented_test); + +api_test!(init_check, TestApi);