1use core::num::{NonZeroU32, NonZeroU64, NonZeroUsize};
4
5use super::types::GpuDeviceProperties;
6use crate::law::{MemoryTier, TopologyEpoch};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct GpuTopology {
21 epoch: TopologyEpoch,
22 properties: GpuDeviceProperties,
23}
24
25impl GpuTopology {
26 #[must_use]
28 pub const fn from_provider(properties: GpuDeviceProperties) -> Self {
29 Self {
30 epoch: TopologyEpoch::INITIAL,
31 properties,
32 }
33 }
34
35 #[must_use]
37 #[inline]
38 pub const fn epoch(&self) -> TopologyEpoch {
39 self.epoch
40 }
41
42 #[must_use]
44 #[inline]
45 pub const fn compute_units(&self) -> Option<NonZeroU32> {
46 self.properties.compute_units
47 }
48
49 #[must_use]
51 #[inline]
52 pub const fn warp_width(&self) -> Option<NonZeroU32> {
53 self.properties.warp_width
54 }
55
56 #[must_use]
58 #[inline]
59 pub const fn max_threads_per_unit(&self) -> Option<NonZeroU32> {
60 self.properties.max_threads_per_unit
61 }
62
63 #[must_use]
66 #[inline]
67 pub const fn registers_per_unit(&self) -> Option<NonZeroU32> {
68 self.properties.registers_per_unit
69 }
70
71 #[must_use]
74 #[inline]
75 pub const fn shared_mem_per_unit_bytes(&self) -> Option<NonZeroUsize> {
76 self.properties.shared_mem_per_unit_bytes
77 }
78
79 #[must_use]
81 #[inline]
82 pub const fn l2_bytes(&self) -> Option<NonZeroUsize> {
83 self.properties.l2_bytes
84 }
85
86 #[must_use]
88 #[inline]
89 pub const fn memory_tier(&self) -> MemoryTier {
90 self.properties.memory_tier
91 }
92
93 #[must_use]
95 #[inline]
96 pub const fn memory_bytes(&self) -> Option<NonZeroU64> {
97 self.properties.memory_bytes
98 }
99
100 #[must_use]
104 #[inline]
105 pub const fn max_resident_warps(&self) -> Option<u64> {
106 match (
107 self.properties.compute_units,
108 self.properties.max_threads_per_unit,
109 self.properties.warp_width,
110 ) {
111 (Some(units), Some(threads), Some(width)) => {
112 Some((units.get() as u64) * (threads.get() as u64) / (width.get() as u64))
113 }
114 _ => None,
115 }
116 }
117}