rusticl/platform: advertise all extensions supported by all devices

There is a spec issue about this to clarify this behavior, but the current
wording can be interpreted that the platform always lists all extensions
supported by all drivers.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33667>
This commit is contained in:
Karol Herbst 2025-01-24 22:04:38 +01:00 committed by Marge Bot
parent ed77f67e44
commit 0fd70ee9de
4 changed files with 59 additions and 32 deletions

View file

@ -15,9 +15,9 @@ unsafe impl CLInfo<cl_platform_info> for cl_platform_id {
fn query(&self, q: cl_platform_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
self.get_ref()?;
match q {
CL_PLATFORM_EXTENSIONS => v.write::<&str>(PLATFORM_EXTENSION_STR),
CL_PLATFORM_EXTENSIONS => v.write::<&str>(&Platform::get().extension_string),
CL_PLATFORM_EXTENSIONS_WITH_VERSION => {
v.write::<&[cl_name_version]>(&PLATFORM_EXTENSIONS)
v.write::<&[cl_name_version]>(&Platform::get().extensions)
}
CL_PLATFORM_HOST_TIMER_RESOLUTION => v.write::<cl_ulong>(1),
CL_PLATFORM_ICD_SUFFIX_KHR => v.write::<&CStr>(c"MESA"),

View file

@ -608,7 +608,7 @@ impl Device {
fn fill_extensions(&mut self) {
let mut exts_str: Vec<String> = Vec::new();
let mut exts = PLATFORM_EXTENSIONS.to_vec();
let mut exts = Vec::new();
let mut feats = Vec::new();
let mut spirv_exts = Vec::new();
let mut add_ext = |major, minor, patch, ext: &str| {
@ -623,18 +623,26 @@ impl Device {
};
// add extensions all drivers support for now
add_ext(1, 0, 0, "cl_khr_byte_addressable_store");
add_ext(1, 0, 0, "cl_khr_create_command_queue");
add_ext(1, 0, 0, "cl_khr_expect_assume");
add_ext(1, 0, 0, "cl_khr_extended_versioning");
add_ext(1, 0, 0, "cl_khr_global_int32_base_atomics");
add_ext(1, 0, 0, "cl_khr_global_int32_extended_atomics");
add_ext(1, 0, 0, "cl_khr_il_program");
add_ext(1, 0, 0, "cl_khr_local_int32_base_atomics");
add_ext(1, 0, 0, "cl_khr_local_int32_extended_atomics");
add_ext(2, 0, 0, "cl_khr_integer_dot_product");
add_ext(1, 0, 0, "cl_khr_spirv_no_integer_wrap_decoration");
add_ext(1, 0, 0, "cl_khr_suggested_local_work_size");
add_feat(2, 0, 0, "__opencl_c_integer_dot_product_input_4x8bit");
add_feat(
2,
0,
0,
"__opencl_c_integer_dot_product_input_4x8bit_packed",
);
add_feat(2, 0, 0, "__opencl_c_integer_dot_product_input_4x8bit");
add_ext(1, 0, 0, "cl_khr_local_int32_base_atomics");
add_ext(1, 0, 0, "cl_khr_local_int32_extended_atomics");
add_spirv(c"SPV_KHR_expect_assume");
add_spirv(c"SPV_KHR_float_controls");
@ -715,7 +723,7 @@ impl Device {
self.extensions = exts;
self.clc_features = feats;
self.extension_string = format!("{} {}", PLATFORM_EXTENSION_STR, exts_str.join(" "));
self.extension_string = exts_str.join(" ");
self.spirv_extensions = spirv_exts;
}

View file

@ -4,6 +4,7 @@ use crate::core::device::*;
use crate::core::version::*;
use mesa_rust_gen::*;
use mesa_rust_util::string::char_arr_to_cstr;
use rusticl_opencl_gen::*;
use std::env;
@ -19,6 +20,8 @@ pub const MAX_PIXEL_SIZE_BYTES: u64 = 4 * 4;
pub struct Platform {
dispatch: &'static cl_icd_dispatch,
pub devs: Vec<Device>,
pub extension_string: String,
pub extensions: Vec<cl_name_version>,
}
pub enum PerfDebugLevel {
@ -48,34 +51,11 @@ pub struct PlatformFeatures {
static PLATFORM_ENV_ONCE: Once = Once::new();
static PLATFORM_ONCE: Once = Once::new();
macro_rules! gen_cl_exts {
(@COUNT $e:expr) => { 1 };
(@COUNT $e:expr, $($es:expr),+) => { 1 + gen_cl_exts!(@COUNT $($es),*) };
(@CONCAT $e:tt) => { $e };
(@CONCAT $e:tt, $($es:tt),+) => { concat!($e, ' ', gen_cl_exts!(@CONCAT $($es),*)) };
([$(($major:expr, $minor:expr, $patch:expr, $ext:tt)$(,)?)+]) => {
pub static PLATFORM_EXTENSION_STR: &str = concat!(gen_cl_exts!(@CONCAT $($ext),*));
pub static PLATFORM_EXTENSIONS: [cl_name_version; gen_cl_exts!(@COUNT $($ext),*)] = [
$(mk_cl_version_ext($major, $minor, $patch, $ext)),+
];
}
}
gen_cl_exts!([
(1, 0, 0, "cl_khr_byte_addressable_store"),
(1, 0, 0, "cl_khr_create_command_queue"),
(1, 0, 0, "cl_khr_expect_assume"),
(1, 0, 0, "cl_khr_extended_versioning"),
(1, 0, 0, "cl_khr_icd"),
(1, 0, 0, "cl_khr_il_program"),
(1, 0, 0, "cl_khr_spirv_no_integer_wrap_decoration"),
(1, 0, 0, "cl_khr_suggested_local_work_size"),
]);
static mut PLATFORM: Platform = Platform {
dispatch: &DISPATCH,
devs: Vec::new(),
extension_string: String::new(),
extensions: Vec::new(),
};
static mut PLATFORM_DBG: PlatformDebug = PlatformDebug {
allow_invalid_spirv: false,
@ -162,6 +142,38 @@ impl Platform {
}
self.devs = Device::all();
let mut exts_str: Vec<&str> = Vec::new();
let mut add_ext = |major, minor, patch, ext: &'static str| {
self.extensions
.push(mk_cl_version_ext(major, minor, patch, ext));
exts_str.push(ext);
};
// Add all platform extensions we don't expect devices to advertise.
add_ext(1, 0, 0, "cl_khr_icd");
let mut exts;
if let Some((first, rest)) = self.devs.split_first() {
exts = first.extensions.clone();
for dev in rest {
// This isn't fast, but the lists are small, so it doesn't really matter.
exts.retain(|ext| dev.extensions.contains(ext));
}
// Now that we found all extensions supported by all devices, we push them to the
// platform.
for ext in &exts {
exts_str.push(
// SAFETY: ext.name contains a nul terminated string.
unsafe { char_arr_to_cstr(&ext.name) }.to_str().unwrap(),
);
self.extensions.push(*ext);
}
}
self.extension_string = exts_str.join(" ");
}
pub fn init_once() {

View file

@ -11,3 +11,10 @@ pub fn c_string_to_string(cstr: *const c_char) -> String {
assert!(res.is_ok());
String::from(res.unwrap_or(""))
}
/// # Safety
///
/// Same as [`CStr::from_ptr`]
pub unsafe fn char_arr_to_cstr(c_str: &[c_char]) -> &CStr {
unsafe { CStr::from_ptr(c_str.as_ptr()) }
}