nvml_wrapper/vgpu.rs
1use std::{ffi::CStr, os::raw::c_uint};
2
3use ffi::bindings::{
4 nvmlVgpuCapability_t, nvmlVgpuTypeId_t, NVML_DEVICE_NAME_BUFFER_SIZE,
5 NVML_GRID_LICENSE_BUFFER_SIZE,
6};
7use static_assertions::assert_impl_all;
8
9use crate::{
10 error::{nvml_sym, nvml_try, NvmlError},
11 Device,
12};
13
14pub struct VgpuType<'dev> {
15 id: nvmlVgpuTypeId_t,
16 device: &'dev Device<'dev>,
17}
18
19assert_impl_all!(VgpuType: Send, Sync);
20
21impl<'dev> VgpuType<'dev> {
22 /// Create a new vGPU type wrapper.
23 ///
24 /// You probably don't need to use this yourself, but rather through
25 /// [`Device::vgpu_supported_types`] and [`Device::vgpu_creatable_types`].
26 pub fn new(device: &'dev Device, id: nvmlVgpuTypeId_t) -> Self {
27 Self { id, device }
28 }
29
30 /// Access the `Device` this struct belongs to.
31 ///
32 pub fn device(&self) -> &'dev Device<'_> {
33 self.device
34 }
35
36 /// Get the underlying vGPU type id.
37 pub fn id(&self) -> nvmlVgpuTypeId_t {
38 self.id
39 }
40
41 /// Retrieve the class of the vGPU type.
42 ///
43 /// # Errors
44 ///
45 /// * `Uninitialized`, if the library has not been successfully initialized
46 /// * `InvalidArg`, if this `Device` is invalid
47 /// * `Unknown`, on any unexpected error
48 ///
49 /// # Device support
50 ///
51 /// Kepler or newer fully supported devices.
52 #[doc(alias = "nvmlVgpuTypeGetClass")]
53 pub fn class_name(&self) -> Result<String, NvmlError> {
54 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetClass.as_ref())?;
55
56 unsafe {
57 let mut size = NVML_DEVICE_NAME_BUFFER_SIZE;
58 let mut buffer = vec![0; size as usize];
59
60 nvml_try(sym(self.id, buffer.as_mut_ptr(), &mut size))?;
61
62 let version_raw = CStr::from_ptr(buffer.as_ptr());
63 Ok(version_raw.to_str()?.into())
64 }
65 }
66
67 /// Retrieve license requirements for a vGPU type.
68 ///
69 /// The license type and version required to run the specified vGPU type is returned as an
70 /// alphanumeric string, in the form "\<license name\>,\<version\>", for example
71 /// "GRID-Virtual-PC,2.0". If a vGPU is runnable with* more than one type of license, the
72 /// licenses are delimited by a semicolon, for example
73 /// "GRID-Virtual-PC,2.0;GRID-Virtual-WS,2.0;GRID-Virtual-WS-Ext,2.0".
74 ///
75 /// # Errors
76 ///
77 /// * `Uninitialized`, if the library has not been successfully initialized
78 /// * `InsufficientSize`, if the passed-in `size` is 0 (must be > 0)
79 /// * `InvalidArg`, if this `Device` is invalid
80 /// * `Unknown`, on any unexpected error
81 ///
82 /// # Device support
83 ///
84 /// Kepler or newer fully supported devices.
85 #[doc(alias = "nvmlVgpuTypeGetLicense")]
86 pub fn license(&self) -> Result<String, NvmlError> {
87 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetLicense.as_ref())?;
88
89 unsafe {
90 let mut buffer = vec![0; NVML_GRID_LICENSE_BUFFER_SIZE as usize];
91
92 nvml_try(sym(self.id, buffer.as_mut_ptr(), buffer.len() as u32))?;
93
94 let version_raw = CStr::from_ptr(buffer.as_ptr());
95 Ok(version_raw.to_str()?.into())
96 }
97 }
98
99 /// Retrieve the name of the vGPU type.
100 ///
101 /// The name is an alphanumeric string that denotes a particular vGPU, e.g. GRID M60-2Q.
102 ///
103 /// # Errors
104 ///
105 /// * `Uninitialized`, if the library has not been successfully initialized
106 /// * `InvalidArg`, if this `Device` is invalid
107 /// * `Unknown`, on any unexpected error
108 ///
109 /// # Device support
110 ///
111 /// Kepler or newer fully supported devices.
112 #[doc(alias = "nvmlVgpuTypeGetName")]
113 pub fn name(&self) -> Result<String, NvmlError> {
114 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetName.as_ref())?;
115
116 unsafe {
117 let mut size = NVML_DEVICE_NAME_BUFFER_SIZE;
118 let mut buffer = vec![0; size as usize];
119
120 nvml_try(sym(self.id, buffer.as_mut_ptr(), &mut size))?;
121
122 let version_raw = CStr::from_ptr(buffer.as_ptr());
123 Ok(version_raw.to_str()?.into())
124 }
125 }
126
127 /// Retrieve the requested capability for a given vGPU type. Refer to the
128 /// `nvmlVgpuCapability_t` structure for the specific capabilities that can be
129 /// queried.
130 ///
131 /// # Errors
132 ///
133 /// * `Uninitialized`, if the library has not been successfully initialized
134 /// * `InvalidArg`, if this `Device` is invalid
135 /// * `Unknown`, on any unexpected error
136 ///
137 /// # Device Support
138 ///
139 /// Maxwell or newer fully supported devices.
140 #[doc(alias = "nvmlVgpuTypeGetCapabilities")]
141 pub fn capabilities(&self, capability: nvmlVgpuCapability_t) -> Result<bool, NvmlError> {
142 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetCapabilities.as_ref())?;
143
144 let mut result: c_uint = 0;
145 unsafe {
146 nvml_try(sym(self.id, capability, &mut result))?;
147 }
148 Ok(result != 0)
149 }
150
151 /// Retrieve the device ID of the vGPU type.
152 ///
153 /// # Errors
154 ///
155 /// * `Uninitialized`, if the library has not been successfully initialized
156 /// * `InvalidArg`, if this `Device` is invalid
157 /// * `Unknown`, on any unexpected error
158 ///
159 /// # Device Support
160 ///
161 /// Kepler or newer fully supported devices.
162 #[doc(alias = "nvmlVgpuTypeGetDeviceID")]
163 pub fn device_id(&self) -> Result<(u64, u64), NvmlError> {
164 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetDeviceID.as_ref())?;
165
166 let (mut device_id, mut subsystem_id) = (0, 0);
167 unsafe {
168 nvml_try(sym(self.id, &mut device_id, &mut subsystem_id))?;
169 }
170 Ok((device_id, subsystem_id))
171 }
172
173 /// Retrieve the static frame rate limit value of the vGPU type.
174 ///
175 /// # Errors
176 ///
177 /// * `Uninitialized`, if the library has not been successfully initialized
178 /// * `NotSupported`, if frame rate limiter is turned off for the vGPU type
179 /// * `InvalidArg`, if this `Device` is invalid
180 /// * `Unknown`, on any unexpected error
181 ///
182 /// # Device Support
183 ///
184 /// Kepler or newer fully supported devices.
185 #[doc(alias = "nvmlVgpuTypeGetFrameRateLimit")]
186 pub fn frame_rate_limit(&self) -> Result<u32, NvmlError> {
187 let sym = nvml_sym(
188 self.device
189 .nvml()
190 .lib
191 .nvmlVgpuTypeGetFrameRateLimit
192 .as_ref(),
193 )?;
194
195 let mut limit = 0;
196 unsafe {
197 nvml_try(sym(self.id, &mut limit))?;
198 }
199 Ok(limit)
200 }
201
202 /// Retrieve the vGPU framebuffer size in bytes.
203 ///
204 /// # Errors
205 ///
206 /// * `Uninitialized`, if the library has not been successfully initialized
207 /// * `InvalidArg`, if this `Device` is invalid
208 /// * `Unknown`, on any unexpected error
209 ///
210 /// # Device Support
211 ///
212 /// Kepler or newer fully supported devices.
213 #[doc(alias = "nvmlVgpuTypeGetFramebufferSize")]
214 pub fn framebuffer_size(&self) -> Result<u64, NvmlError> {
215 let sym = nvml_sym(
216 self.device
217 .nvml()
218 .lib
219 .nvmlVgpuTypeGetFramebufferSize
220 .as_ref(),
221 )?;
222
223 let mut size = 0;
224 unsafe {
225 nvml_try(sym(self.id, &mut size))?;
226 }
227 Ok(size)
228 }
229
230 /// Retrieve the GPU Instance Profile ID for the vGPU type. The API will return a valid GPU
231 /// Instance Profile ID for the MIG capable vGPU types, else
232 /// [`crate::ffi::bindings::INVALID_GPU_INSTANCE_PROFILE_ID`] is returned.
233 ///
234 /// # Errors
235 ///
236 /// * `Uninitialized`, if the library has not been successfully initialized
237 /// * `InvalidArg`, if this `Device` is invalid
238 /// * `Unknown`, on any unexpected error
239 ///
240 /// # Device Support
241 ///
242 /// Kepler or newer fully supported devices.
243 #[doc(alias = "nvmlVgpuTypeGetGpuInstanceProfileId")]
244 pub fn instance_profile_id(&self) -> Result<u32, NvmlError> {
245 let sym = nvml_sym(
246 self.device
247 .nvml()
248 .lib
249 .nvmlVgpuTypeGetGpuInstanceProfileId
250 .as_ref(),
251 )?;
252
253 let mut profile_id = 0;
254 unsafe {
255 nvml_try(sym(self.id, &mut profile_id))?;
256 }
257 Ok(profile_id)
258 }
259
260 /// Retrieve the maximum number of vGPU instances creatable on a device for the vGPU type.
261 ///
262 /// # Errors
263 ///
264 /// * `Uninitialized`, if the library has not been successfully initialized
265 /// * `InvalidArg`, if this `Device` is invalid
266 /// * `Unknown`, on any unexpected error
267 ///
268 /// # Device Support
269 ///
270 /// Kepler or newer fully supported devices.
271 #[doc(alias = "nvmlVgpuTypeGetMaxInstances")]
272 pub fn max_instances(&self) -> Result<u32, NvmlError> {
273 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetMaxInstances.as_ref())?;
274
275 let mut max = 0;
276 unsafe {
277 nvml_try(sym(self.device.handle(), self.id, &mut max))?;
278 }
279 Ok(max)
280 }
281
282 /// Retrieve the maximum number of vGPU instances supported per VM for the vGPU type.
283 ///
284 /// # Errors
285 ///
286 /// * `Uninitialized`, if the library has not been successfully initialized
287 /// * `InvalidArg`, if this `Device` is invalid
288 /// * `Unknown`, on any unexpected error
289 ///
290 /// # Device Support
291 ///
292 /// Kepler or newer fully supported devices.
293 #[doc(alias = "nvmlVgpuTypeGetMaxInstancesPerVm")]
294 pub fn max_instances_per_vm(&self) -> Result<u32, NvmlError> {
295 let sym = nvml_sym(
296 self.device
297 .nvml()
298 .lib
299 .nvmlVgpuTypeGetMaxInstancesPerVm
300 .as_ref(),
301 )?;
302
303 let mut max = 0;
304 unsafe {
305 nvml_try(sym(self.id, &mut max))?;
306 }
307 Ok(max)
308 }
309
310 /// Retrieve count of vGPU's supported display heads.
311 ///
312 /// # Errors
313 ///
314 /// * `Uninitialized`, if the library has not been successfully initialized
315 /// * `InvalidArg`, if this `Device` is invalid
316 /// * `Unknown`, on any unexpected error
317 ///
318 /// # Device Support
319 ///
320 /// Kepler or newer fully supported devices.
321 #[doc(alias = "nvmlVgpuTypeGetNumDisplayHeads")]
322 pub fn num_display_heads(&self) -> Result<u32, NvmlError> {
323 let sym = nvml_sym(
324 self.device
325 .nvml()
326 .lib
327 .nvmlVgpuTypeGetNumDisplayHeads
328 .as_ref(),
329 )?;
330
331 let mut heads = 0;
332 unsafe {
333 nvml_try(sym(self.id, &mut heads))?;
334 }
335 Ok(heads)
336 }
337
338 /// Retrieve vGPU display head's maximum supported resolution.
339 ///
340 /// The `display_head` argument specifies the 0-based display index, the
341 /// maximum being what [`VgpuType::num_display_heads`] returns.
342 ///
343 /// # Errors
344 ///
345 /// * `Uninitialized`, if the library has not been successfully initialized
346 /// * `InvalidArg`, if this `Device` is invalid
347 /// * `Unknown`, on any unexpected error
348 ///
349 /// # Device Support
350 ///
351 /// Kepler or newer fully supported devices.
352 #[doc(alias = "nvmlVgpuTypeGetResolution")]
353 pub fn resolution(&self, display_head: u32) -> Result<(u32, u32), NvmlError> {
354 let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetResolution.as_ref())?;
355
356 let (mut x, mut y) = (0, 0);
357 unsafe {
358 nvml_try(sym(self.id, display_head, &mut x, &mut y))?;
359 }
360 Ok((x, y))
361 }
362}