use core::num::{NonZeroU32, NonZeroU64, NonZeroUsize};
use super::types::GpuDeviceProperties;
use crate::law::{MemoryTier, TopologyEpoch};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GpuTopology {
epoch: TopologyEpoch,
properties: GpuDeviceProperties,
}
impl GpuTopology {
#[must_use]
pub const fn from_provider(properties: GpuDeviceProperties) -> Self {
Self {
epoch: TopologyEpoch::INITIAL,
properties,
}
}
#[must_use]
#[inline]
pub const fn epoch(&self) -> TopologyEpoch {
self.epoch
}
#[must_use]
#[inline]
pub const fn compute_units(&self) -> Option<NonZeroU32> {
self.properties.compute_units
}
#[must_use]
#[inline]
pub const fn warp_width(&self) -> Option<NonZeroU32> {
self.properties.warp_width
}
#[must_use]
#[inline]
pub const fn max_threads_per_unit(&self) -> Option<NonZeroU32> {
self.properties.max_threads_per_unit
}
#[must_use]
#[inline]
pub const fn registers_per_unit(&self) -> Option<NonZeroU32> {
self.properties.registers_per_unit
}
#[must_use]
#[inline]
pub const fn shared_mem_per_unit_bytes(&self) -> Option<NonZeroUsize> {
self.properties.shared_mem_per_unit_bytes
}
#[must_use]
#[inline]
pub const fn l2_bytes(&self) -> Option<NonZeroUsize> {
self.properties.l2_bytes
}
#[must_use]
#[inline]
pub const fn memory_tier(&self) -> MemoryTier {
self.properties.memory_tier
}
#[must_use]
#[inline]
pub const fn memory_bytes(&self) -> Option<NonZeroU64> {
self.properties.memory_bytes
}
#[must_use]
#[inline]
pub const fn max_resident_warps(&self) -> Option<u64> {
match (
self.properties.compute_units,
self.properties.max_threads_per_unit,
self.properties.warp_width,
) {
(Some(units), Some(threads), Some(width)) => {
Some((units.get() as u64) * (threads.get() as u64) / (width.get() as u64))
}
_ => None,
}
}
}