• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::api::icd::CLResult;
2 use crate::api::icd::DISPATCH;
3 use crate::core::device::*;
4 use crate::core::version::*;
5 
6 use mesa_rust_gen::*;
7 use rusticl_opencl_gen::*;
8 
9 use std::env;
10 use std::sync::Once;
11 
12 #[repr(C)]
13 pub struct Platform {
14     dispatch: &'static cl_icd_dispatch,
15     pub devs: Vec<Device>,
16 }
17 
18 pub struct PlatformDebug {
19     pub allow_invalid_spirv: bool,
20     pub clc: bool,
21     pub program: bool,
22     pub sync_every_event: bool,
23     pub validate_spirv: bool,
24 }
25 
26 pub struct PlatformFeatures {
27     pub fp16: bool,
28     pub fp64: bool,
29 }
30 
31 static PLATFORM_ENV_ONCE: Once = Once::new();
32 static PLATFORM_ONCE: Once = Once::new();
33 
34 macro_rules! gen_cl_exts {
35     (@COUNT $e:expr) => { 1 };
36     (@COUNT $e:expr, $($es:expr),+) => { 1 + gen_cl_exts!(@COUNT $($es),*) };
37 
38     (@CONCAT $e:tt) => { $e };
39     (@CONCAT $e:tt, $($es:tt),+) => { concat!($e, ' ', gen_cl_exts!(@CONCAT $($es),*)) };
40 
41     ([$(($major:expr, $minor:expr, $patch:expr, $ext:tt)$(,)?)+]) => {
42         pub static PLATFORM_EXTENSION_STR: &str = concat!(gen_cl_exts!(@CONCAT $($ext),*));
43         pub static PLATFORM_EXTENSIONS: [cl_name_version; gen_cl_exts!(@COUNT $($ext),*)] = [
44             $(mk_cl_version_ext($major, $minor, $patch, $ext)),+
45         ];
46     }
47 }
48 gen_cl_exts!([
49     (1, 0, 0, "cl_khr_byte_addressable_store"),
50     (1, 0, 0, "cl_khr_create_command_queue"),
51     (1, 0, 0, "cl_khr_expect_assume"),
52     (1, 0, 0, "cl_khr_extended_versioning"),
53     (1, 0, 0, "cl_khr_icd"),
54     (1, 0, 0, "cl_khr_il_program"),
55     (1, 0, 0, "cl_khr_spirv_no_integer_wrap_decoration"),
56 ]);
57 
58 static mut PLATFORM: Platform = Platform {
59     dispatch: &DISPATCH,
60     devs: Vec::new(),
61 };
62 static mut PLATFORM_DBG: PlatformDebug = PlatformDebug {
63     allow_invalid_spirv: false,
64     clc: false,
65     program: false,
66     sync_every_event: false,
67     validate_spirv: false,
68 };
69 static mut PLATFORM_FEATURES: PlatformFeatures = PlatformFeatures {
70     fp16: false,
71     fp64: false,
72 };
73 
load_env()74 fn load_env() {
75     let debug = unsafe { &mut PLATFORM_DBG };
76     if let Ok(debug_flags) = env::var("RUSTICL_DEBUG") {
77         for flag in debug_flags.split(',') {
78             match flag {
79                 "allow_invalid_spirv" => debug.allow_invalid_spirv = true,
80                 "clc" => debug.clc = true,
81                 "program" => debug.program = true,
82                 "sync" => debug.sync_every_event = true,
83                 "validate" => debug.validate_spirv = true,
84                 "" => (),
85                 _ => eprintln!("Unknown RUSTICL_DEBUG flag found: {}", flag),
86             }
87         }
88     }
89 
90     let features = unsafe { &mut PLATFORM_FEATURES };
91     if let Ok(feature_flags) = env::var("RUSTICL_FEATURES") {
92         for flag in feature_flags.split(',') {
93             match flag {
94                 "fp16" => features.fp16 = true,
95                 "fp64" => features.fp64 = true,
96                 "" => (),
97                 _ => eprintln!("Unknown RUSTICL_FEATURES flag found: {}", flag),
98             }
99         }
100     }
101 }
102 
103 impl Platform {
as_ptr(&self) -> cl_platform_id104     pub fn as_ptr(&self) -> cl_platform_id {
105         (self as *const Self) as cl_platform_id
106     }
107 
get() -> &'static Self108     pub fn get() -> &'static Self {
109         debug_assert!(PLATFORM_ONCE.is_completed());
110         // SAFETY: no mut references exist at this point
111         unsafe { &PLATFORM }
112     }
113 
dbg() -> &'static PlatformDebug114     pub fn dbg() -> &'static PlatformDebug {
115         debug_assert!(PLATFORM_ENV_ONCE.is_completed());
116         unsafe { &PLATFORM_DBG }
117     }
118 
features() -> &'static PlatformFeatures119     pub fn features() -> &'static PlatformFeatures {
120         debug_assert!(PLATFORM_ENV_ONCE.is_completed());
121         unsafe { &PLATFORM_FEATURES }
122     }
123 
init(&mut self)124     fn init(&mut self) {
125         unsafe {
126             glsl_type_singleton_init_or_ref();
127         }
128 
129         self.devs = Device::all().collect();
130     }
131 
init_once()132     pub fn init_once() {
133         PLATFORM_ENV_ONCE.call_once(load_env);
134         // SAFETY: no concurrent static mut access due to std::Once
135         PLATFORM_ONCE.call_once(|| unsafe { PLATFORM.init() });
136     }
137 }
138 
139 impl Drop for Platform {
drop(&mut self)140     fn drop(&mut self) {
141         unsafe {
142             glsl_type_singleton_decref();
143         }
144     }
145 }
146 
147 pub trait GetPlatformRef {
get_ref(&self) -> CLResult<&'static Platform>148     fn get_ref(&self) -> CLResult<&'static Platform>;
149 }
150 
151 impl GetPlatformRef for cl_platform_id {
get_ref(&self) -> CLResult<&'static Platform>152     fn get_ref(&self) -> CLResult<&'static Platform> {
153         if !self.is_null() && *self == Platform::get().as_ptr() {
154             Ok(Platform::get())
155         } else {
156             Err(CL_INVALID_PLATFORM)
157         }
158     }
159 }
160