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