use std::fmt;
use std::str::FromStr;
use crate::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ComputeCapability {
pub major: u32,
pub minor: u32,
}
impl ComputeCapability {
pub const fn new(major: u32, minor: u32) -> Self {
Self { major, minor }
}
pub const fn at_least(self, other: Self) -> bool {
self.major > other.major || self.major == other.major && self.minor >= other.minor
}
}
impl fmt::Display for ComputeCapability {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum PtxTier {
Sm75,
Sm80,
Sm90,
Sm120,
}
impl PtxTier {
pub const BASELINE: Self = Self::Sm75;
pub const ALL: &'static [Self] = &[Self::Sm75, Self::Sm80, Self::Sm90, Self::Sm120];
pub(crate) const COUNT: usize = Self::ALL.len();
pub const fn name(self) -> &'static str {
match self {
Self::Sm75 => "sm75",
Self::Sm80 => "sm80",
Self::Sm90 => "sm90",
Self::Sm120 => "sm120",
}
}
pub const fn min_capability(self) -> ComputeCapability {
match self {
Self::Sm75 => ComputeCapability::new(7, 5),
Self::Sm80 => ComputeCapability::new(8, 0),
Self::Sm90 => ComputeCapability::new(9, 0),
Self::Sm120 => ComputeCapability::new(12, 0),
}
}
pub(crate) const fn index(self) -> usize {
match self {
Self::Sm75 => 0,
Self::Sm80 => 1,
Self::Sm90 => 2,
Self::Sm120 => 3,
}
}
}
impl fmt::Display for PtxTier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
impl FromStr for PtxTier {
type Err = Error;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let value = value.trim();
Self::ALL
.iter()
.copied()
.find(|tier| tier.name() == value)
.ok_or_else(|| Error::InvalidPtxTier {
value: value.to_string(),
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct TierSet(u32);
impl TierSet {
pub const EMPTY: Self = Self(0);
pub const fn of(tiers: &[PtxTier]) -> Self {
let mut set = Self::EMPTY;
let mut index = 0;
while index < tiers.len() {
set = set.with(tiers[index]);
index += 1;
}
set
}
pub const fn with(self, tier: PtxTier) -> Self {
Self(self.0 | 1 << tier.index())
}
pub const fn with_if(self, tier: PtxTier, enabled: bool) -> Self {
if enabled { self.with(tier) } else { self }
}
pub const fn contains(self, tier: PtxTier) -> bool {
self.0 & 1 << tier.index() != 0
}
pub fn iter(self) -> impl Iterator<Item = PtxTier> {
PtxTier::ALL
.iter()
.copied()
.filter(move |tier| self.contains(*tier))
}
}