use super::FabricClass;
use super::wgsl::{Detector, Mutant};
pub const SOURCE: &str = include_str!("lanes64.cl");
pub const IMPLEMENTATION: &str = "opencl-lanes64";
pub const HOST_LAYOUT: u32 = 1;
pub const GLOBAL_MAX: u64 = 1 << 20;
pub const BUILD_OPTIONS: &str = "-cl-std=CL1.2";
const DOMAIN_IMPLEMENTATION: &[u8] = b"wai:quantum-fabric-opencl\x01";
const DOMAIN_MEMBER: &[u8] = b"wai:quantum-fabric-opencl-member\x01";
fn hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect()
}
fn put(o: &mut Vec<u8>, bytes: &[u8]) {
o.extend_from_slice(&(bytes.len() as u64).to_be_bytes());
o.extend_from_slice(bytes);
}
pub fn implementation_id() -> String {
implementation_id_of(SOURCE)
}
pub fn implementation_id_of(source: &str) -> String {
let mut o = DOMAIN_IMPLEMENTATION.to_vec();
put(&mut o, source.as_bytes());
put(&mut o, BUILD_OPTIONS.as_bytes());
o.extend_from_slice(&HOST_LAYOUT.to_be_bytes());
format!("{IMPLEMENTATION}/{}", hex(&blake3::hash(&o).as_bytes()[..8]))
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum DeviceKind {
Gpu,
Cpu,
Accelerator,
}
impl DeviceKind {
fn name(self) -> &'static str {
match self {
DeviceKind::Gpu => "gpu",
DeviceKind::Cpu => "cpu",
DeviceKind::Accelerator => "accelerator",
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DeviceIdentity {
pub platform: String,
pub platform_version: String,
pub vendor: String,
pub name: String,
pub version: String,
pub driver: String,
pub kind: DeviceKind,
pub uuid: String,
pub compute_units: u32,
pub memory: u64,
}
impl DeviceIdentity {
pub fn class(&self) -> Option<FabricClass> {
match self.kind {
DeviceKind::Gpu => Some(FabricClass::Gpu),
DeviceKind::Cpu => Some(FabricClass::Cpu),
DeviceKind::Accelerator => None,
}
}
pub fn vendor_slug(&self) -> String {
let word = self.vendor.split_whitespace().find(|w| !w.eq_ignore_ascii_case("the")).unwrap_or("");
let slug: String = word.chars().take_while(|c| c.is_ascii_alphanumeric()).map(|c| c.to_ascii_lowercase()).collect();
if slug.is_empty() { "unknown".into() } else { slug }
}
pub fn member_id(&self) -> String {
let mut o = DOMAIN_MEMBER.to_vec();
for s in [&self.platform, &self.platform_version, &self.vendor, &self.name, &self.version, &self.driver] {
put(&mut o, s.as_bytes());
}
put(&mut o, self.kind.name().as_bytes());
put(&mut o, self.uuid.as_bytes());
o.extend_from_slice(&self.compute_units.to_be_bytes());
o.extend_from_slice(&self.memory.to_be_bytes());
format!("local/opencl-{}-{}", self.kind.name(), hex(&blake3::hash(&o).as_bytes()[..6]))
}
pub fn key(&self) -> String {
format!("opencl-{}-{}", self.kind.name(), self.vendor_slug())
}
}
pub const MUTANTS: [Mutant; 6] = [
Mutant { name: "O1", find: "((i64)a * (i64)b + ((i64)1 << 29)) >> 30;", replace: "((i64)a * (i64)b + ((i64)1 << 28)) >> 30;", detector: Detector::Probe },
Mutant { name: "O2", find: "((i64)a * (i64)b + ((i64)1 << 29)) >> 30;", replace: "((i64)a * (i64)b + ((i64)1 << 29)) >> 29;", detector: Detector::Probe },
Mutant { name: "O3", find: "u64 prod = (u64)((i64)c.x * (i64)c.y);", replace: "u64 prod = (u64)(uint)(c.x * c.y);", detector: Detector::Probe },
Mutant { name: "O4", find: "if ((i & (u64)ctrl) != (u64)ctrl) {", replace: "if ((i & (u64)ctrl) == (u64)ctrl) {", detector: Detector::Certificate },
Mutant { name: "O5", find: "fx(m2, a1.x) - fx(m3, a1.y);", replace: "fx(m2, a1.x) + fx(m3, a1.y);", detector: Detector::Certificate },
Mutant { name: "O6", find: "if (!(fits32(o0r) && fits32(o0i) && fits32(o1r) && fits32(o1i))) {", replace: "if (0) {", detector: Detector::Range },
];
pub fn mutate(m: &Mutant) -> String {
let n = SOURCE.matches(m.find).count();
assert_eq!(n, 1, "mutant {}: `{}` occurs {n} times in the kernel", m.name, m.find);
SOURCE.replacen(m.find, m.replace, 1)
}
#[cfg(test)]
mod tests {
use super::*;
fn identity() -> DeviceIdentity {
DeviceIdentity {
platform: "a platform".into(),
platform_version: "OpenCL 3.0".into(),
vendor: "Graphics Corporation".into(),
name: "a device".into(),
version: "OpenCL 3.0 CUDA".into(),
driver: "595.84".into(),
kind: DeviceKind::Gpu,
uuid: "00112233445566778899aabbccddeeff".into(),
compute_units: 20,
memory: 6 << 30,
}
}
#[test]
fn every_field_of_the_identity_is_in_the_member_id() {
let base = identity();
let id = base.member_id();
assert!(id.starts_with("local/opencl-gpu-") && id.len() == "local/opencl-gpu-".len() + 12, "{id}");
for other in ["local/cpu-x86_64", "local/cpu-aarch64", "local/gpu-cuda-ffffffffffff"] {
assert!(id.as_str() > other, "{id} sorts after {other}");
}
let cpu = DeviceIdentity { kind: DeviceKind::Cpu, ..identity() }.member_id();
assert!(cpu.as_str() > "local/cpu-x86_64", "a CPU device sorts after the CPU reference: {cpu}");
let variants = [
DeviceIdentity { platform: "another".into(), ..identity() },
DeviceIdentity { platform_version: "OpenCL 1.2".into(), ..identity() },
DeviceIdentity { vendor: "Cores(R) Corporation".into(), ..identity() },
DeviceIdentity { name: "another".into(), ..identity() },
DeviceIdentity { version: "OpenCL 1.2".into(), ..identity() },
DeviceIdentity { driver: "595.85".into(), ..identity() },
DeviceIdentity { kind: DeviceKind::Cpu, ..identity() },
DeviceIdentity { kind: DeviceKind::Accelerator, ..identity() },
DeviceIdentity { uuid: String::new(), ..identity() },
DeviceIdentity { compute_units: 21, ..identity() },
DeviceIdentity { memory: 8 << 30, ..identity() },
];
for v in variants {
assert_ne!(v.member_id(), id, "{v:?}");
}
assert_eq!(base.key(), "opencl-gpu-graphics");
assert_eq!(DeviceIdentity { vendor: "Cores(R) Corporation".into(), kind: DeviceKind::Cpu, ..identity() }.key(), "opencl-cpu-cores");
assert_eq!(DeviceIdentity { vendor: "The pocl project".into(), kind: DeviceKind::Cpu, ..identity() }.key(), "opencl-cpu-pocl");
assert_eq!(DeviceIdentity { vendor: String::new(), ..identity() }.key(), "opencl-gpu-unknown");
assert_eq!(base.class(), Some(FabricClass::Gpu));
assert_eq!(DeviceIdentity { kind: DeviceKind::Cpu, ..identity() }.class(), Some(FabricClass::Cpu));
assert_eq!(DeviceIdentity { kind: DeviceKind::Accelerator, ..identity() }.class(), None);
}
#[test]
fn the_implementation_id_follows_the_kernel_text() {
let id = implementation_id();
assert!(id.starts_with("opencl-lanes64/") && id.len() == "opencl-lanes64/".len() + 16, "{id}");
for m in &MUTANTS {
assert_ne!(implementation_id_of(&mutate(m)), id, "mutant {}", m.name);
}
}
#[test]
fn every_mutant_edits_the_kernel_once_and_names_distinct_edits() {
let mut seen = std::collections::BTreeSet::new();
for m in &MUTANTS {
let edited = mutate(m);
assert_ne!(edited, SOURCE, "mutant {} changes nothing", m.name);
assert!(seen.insert(edited), "mutant {} duplicates another", m.name);
}
for d in [Detector::Probe, Detector::Certificate, Detector::Range] {
assert!(MUTANTS.iter().any(|m| m.detector == d), "no mutant for {d:?}");
}
}
}