Skip to main content

nvml_wrapper/
vgpu.rs

1use std::{
2    ffi::CStr,
3    os::raw::{c_char, c_uint},
4};
5
6use ffi::bindings::{
7    nvmlEnableState_enum_NVML_FEATURE_ENABLED, nvmlEncoderSessionInfo_t, nvmlFBCSessionInfo_t,
8    nvmlFBCStats_t, nvmlVgpuCapability_t, nvmlVgpuInstance_t, nvmlVgpuLicenseInfo_st,
9    nvmlVgpuMetadata_t, nvmlVgpuPlacementId_t, nvmlVgpuRuntimeState_t, nvmlVgpuTypeBar1Info_v1_t,
10    nvmlVgpuTypeId_t, nvmlVgpuVmIdType_NVML_VGPU_VM_ID_DOMAIN_ID,
11    nvmlVgpuVmIdType_NVML_VGPU_VM_ID_UUID, NVML_DEVICE_NAME_BUFFER_SIZE,
12    NVML_DEVICE_UUID_BUFFER_SIZE, NVML_GRID_LICENSE_BUFFER_SIZE,
13    NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE,
14};
15use static_assertions::assert_impl_all;
16
17use crate::{
18    enum_wrappers::vgpu::VmId,
19    error::{nvml_sym, nvml_try, nvml_try_count, NvmlError},
20    struct_wrappers::{
21        device::{EncoderSessionInfo, FbcSessionInfo, FbcStats},
22        vgpu::{Bar1Info, VgpuLicenseInfo, VgpuMetadata, VgpuPlacementId, VgpuRuntimeState},
23    },
24    structs::device::EncoderStats,
25    Device,
26};
27
28#[derive(Debug)]
29pub struct VgpuType<'dev> {
30    id: nvmlVgpuTypeId_t,
31    device: &'dev Device<'dev>,
32}
33
34assert_impl_all!(VgpuType: Send, Sync);
35
36impl<'dev> VgpuType<'dev> {
37    /// Create a new vGPU type wrapper.
38    ///
39    /// You probably don't need to use this yourself, but rather through
40    /// [`Device::vgpu_supported_types`] and [`Device::vgpu_creatable_types`].
41    pub fn new(device: &'dev Device, id: nvmlVgpuTypeId_t) -> Self {
42        Self { id, device }
43    }
44
45    /// Access the `Device` this struct belongs to.
46    ///
47    pub fn device(&self) -> &'dev Device<'_> {
48        self.device
49    }
50
51    /// Get the underlying vGPU type id.
52    pub fn id(&self) -> nvmlVgpuTypeId_t {
53        self.id
54    }
55
56    /// Retrieve the class of the vGPU type.
57    ///
58    /// # Errors
59    ///
60    /// * `Uninitialized`, if the library has not been successfully initialized
61    /// * `InvalidArg`, if this `Device` is invalid
62    /// * `Unknown`, on any unexpected error
63    ///
64    /// # Device support
65    ///
66    /// Kepler or newer fully supported devices.
67    #[doc(alias = "nvmlVgpuTypeGetClass")]
68    pub fn class_name(&self) -> Result<String, NvmlError> {
69        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetClass.as_ref())?;
70
71        unsafe {
72            let mut size = NVML_DEVICE_NAME_BUFFER_SIZE;
73            let mut buffer = vec![0; size as usize];
74
75            nvml_try(sym(self.id, buffer.as_mut_ptr(), &mut size))?;
76
77            let version_raw = CStr::from_ptr(buffer.as_ptr());
78            Ok(version_raw.to_str()?.into())
79        }
80    }
81
82    /// Retrieve license requirements for a vGPU type.
83    ///
84    /// The license type and version required to run the specified vGPU type is returned as an
85    /// alphanumeric string, in the form "\<license name\>,\<version\>", for example
86    /// "GRID-Virtual-PC,2.0". If a vGPU is runnable with* more than one type of license, the
87    /// licenses are delimited by a semicolon, for example
88    /// "GRID-Virtual-PC,2.0;GRID-Virtual-WS,2.0;GRID-Virtual-WS-Ext,2.0".
89    ///
90    /// # Errors
91    ///
92    /// * `Uninitialized`, if the library has not been successfully initialized
93    /// * `InsufficientSize`, if the passed-in `size` is 0 (must be > 0)
94    /// * `InvalidArg`, if this `Device` is invalid
95    /// * `Unknown`, on any unexpected error
96    ///
97    /// # Device support
98    ///
99    /// Kepler or newer fully supported devices.
100    #[doc(alias = "nvmlVgpuTypeGetLicense")]
101    pub fn license(&self) -> Result<String, NvmlError> {
102        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetLicense.as_ref())?;
103
104        unsafe {
105            let mut buffer = vec![0; NVML_GRID_LICENSE_BUFFER_SIZE as usize];
106
107            nvml_try(sym(self.id, buffer.as_mut_ptr(), buffer.len() as u32))?;
108
109            let version_raw = CStr::from_ptr(buffer.as_ptr());
110            Ok(version_raw.to_str()?.into())
111        }
112    }
113
114    /// Retrieve the name of the vGPU type.
115    ///
116    /// The name is an alphanumeric string that denotes a particular vGPU, e.g. GRID M60-2Q.
117    ///
118    /// # Errors
119    ///
120    /// * `Uninitialized`, if the library has not been successfully initialized
121    /// * `InvalidArg`, if this `Device` is invalid
122    /// * `Unknown`, on any unexpected error
123    ///
124    /// # Device support
125    ///
126    /// Kepler or newer fully supported devices.
127    #[doc(alias = "nvmlVgpuTypeGetName")]
128    pub fn name(&self) -> Result<String, NvmlError> {
129        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetName.as_ref())?;
130
131        unsafe {
132            let mut size = NVML_DEVICE_NAME_BUFFER_SIZE;
133            let mut buffer = vec![0; size as usize];
134
135            nvml_try(sym(self.id, buffer.as_mut_ptr(), &mut size))?;
136
137            let version_raw = CStr::from_ptr(buffer.as_ptr());
138            Ok(version_raw.to_str()?.into())
139        }
140    }
141
142    /// Retrieve the requested capability for a given vGPU type. Refer to the
143    /// `nvmlVgpuCapability_t` structure for the specific capabilities that can be
144    /// queried.
145    ///
146    /// # Errors
147    ///
148    /// * `Uninitialized`, if the library has not been successfully initialized
149    /// * `InvalidArg`, if this `Device` is invalid
150    /// * `Unknown`, on any unexpected error
151    ///
152    /// # Device Support
153    ///
154    /// Maxwell or newer fully supported devices.
155    #[doc(alias = "nvmlVgpuTypeGetCapabilities")]
156    pub fn capabilities(&self, capability: nvmlVgpuCapability_t) -> Result<bool, NvmlError> {
157        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetCapabilities.as_ref())?;
158
159        let mut result: c_uint = 0;
160        unsafe {
161            nvml_try(sym(self.id, capability, &mut result))?;
162        }
163        Ok(result != 0)
164    }
165
166    /// Retrieve the device ID of the vGPU type.
167    ///
168    /// # Errors
169    ///
170    /// * `Uninitialized`, if the library has not been successfully initialized
171    /// * `InvalidArg`, if this `Device` is invalid
172    /// * `Unknown`, on any unexpected error
173    ///
174    /// # Device Support
175    ///
176    /// Kepler or newer fully supported devices.
177    #[doc(alias = "nvmlVgpuTypeGetDeviceID")]
178    pub fn device_id(&self) -> Result<(u64, u64), NvmlError> {
179        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetDeviceID.as_ref())?;
180
181        let (mut device_id, mut subsystem_id) = (0, 0);
182        unsafe {
183            nvml_try(sym(self.id, &mut device_id, &mut subsystem_id))?;
184        }
185        Ok((device_id, subsystem_id))
186    }
187
188    /// Retrieve the static frame rate limit value of the vGPU type.
189    ///
190    /// # Errors
191    ///
192    /// * `Uninitialized`, if the library has not been successfully initialized
193    /// * `NotSupported`, if frame rate limiter is turned off for the vGPU type
194    /// * `InvalidArg`, if this `Device` is invalid
195    /// * `Unknown`, on any unexpected error
196    ///
197    /// # Device Support
198    ///
199    /// Kepler or newer fully supported devices.
200    #[doc(alias = "nvmlVgpuTypeGetFrameRateLimit")]
201    pub fn frame_rate_limit(&self) -> Result<u32, NvmlError> {
202        let sym = nvml_sym(
203            self.device
204                .nvml()
205                .lib
206                .nvmlVgpuTypeGetFrameRateLimit
207                .as_ref(),
208        )?;
209
210        let mut limit = 0;
211        unsafe {
212            nvml_try(sym(self.id, &mut limit))?;
213        }
214        Ok(limit)
215    }
216
217    /// Retrieve the vGPU framebuffer size in bytes.
218    ///
219    /// # Errors
220    ///
221    /// * `Uninitialized`, if the library has not been successfully initialized
222    /// * `InvalidArg`, if this `Device` is invalid
223    /// * `Unknown`, on any unexpected error
224    ///
225    /// # Device Support
226    ///
227    /// Kepler or newer fully supported devices.
228    #[doc(alias = "nvmlVgpuTypeGetFramebufferSize")]
229    pub fn framebuffer_size(&self) -> Result<u64, NvmlError> {
230        let sym = nvml_sym(
231            self.device
232                .nvml()
233                .lib
234                .nvmlVgpuTypeGetFramebufferSize
235                .as_ref(),
236        )?;
237
238        let mut size = 0;
239        unsafe {
240            nvml_try(sym(self.id, &mut size))?;
241        }
242        Ok(size)
243    }
244
245    /// Retrieve the GPU Instance Profile ID for the vGPU type. The API will return a valid GPU
246    /// Instance Profile ID for the MIG capable vGPU types, else
247    /// [`crate::ffi::bindings::INVALID_GPU_INSTANCE_PROFILE_ID`] is returned.
248    ///
249    /// # Errors
250    ///
251    /// * `Uninitialized`, if the library has not been successfully initialized
252    /// * `InvalidArg`, if this `Device` is invalid
253    /// * `Unknown`, on any unexpected error
254    ///
255    /// # Device Support
256    ///
257    /// Kepler or newer fully supported devices.
258    #[doc(alias = "nvmlVgpuTypeGetGpuInstanceProfileId")]
259    pub fn instance_profile_id(&self) -> Result<u32, NvmlError> {
260        let sym = nvml_sym(
261            self.device
262                .nvml()
263                .lib
264                .nvmlVgpuTypeGetGpuInstanceProfileId
265                .as_ref(),
266        )?;
267
268        let mut profile_id = 0;
269        unsafe {
270            nvml_try(sym(self.id, &mut profile_id))?;
271        }
272        Ok(profile_id)
273    }
274
275    /// Retrieve the maximum number of vGPU instances creatable on a device for the vGPU type.
276    ///
277    /// # Errors
278    ///
279    /// * `Uninitialized`, if the library has not been successfully initialized
280    /// * `InvalidArg`, if this `Device` is invalid
281    /// * `Unknown`, on any unexpected error
282    ///
283    /// # Device Support
284    ///
285    /// Kepler or newer fully supported devices.
286    #[doc(alias = "nvmlVgpuTypeGetMaxInstances")]
287    pub fn max_instances(&self) -> Result<u32, NvmlError> {
288        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetMaxInstances.as_ref())?;
289
290        let mut max = 0;
291        unsafe {
292            nvml_try(sym(self.device.handle(), self.id, &mut max))?;
293        }
294        Ok(max)
295    }
296
297    /// Retrieve the maximum number of vGPU instances supported per VM for the vGPU type.
298    ///
299    /// # Errors
300    ///
301    /// * `Uninitialized`, if the library has not been successfully initialized
302    /// * `InvalidArg`, if this `Device` is invalid
303    /// * `Unknown`, on any unexpected error
304    ///
305    /// # Device Support
306    ///
307    /// Kepler or newer fully supported devices.
308    #[doc(alias = "nvmlVgpuTypeGetMaxInstancesPerVm")]
309    pub fn max_instances_per_vm(&self) -> Result<u32, NvmlError> {
310        let sym = nvml_sym(
311            self.device
312                .nvml()
313                .lib
314                .nvmlVgpuTypeGetMaxInstancesPerVm
315                .as_ref(),
316        )?;
317
318        let mut max = 0;
319        unsafe {
320            nvml_try(sym(self.id, &mut max))?;
321        }
322        Ok(max)
323    }
324
325    /// Retrieve count of vGPU's supported display heads.
326    ///
327    /// # Errors
328    ///
329    /// * `Uninitialized`, if the library has not been successfully initialized
330    /// * `InvalidArg`, if this `Device` is invalid
331    /// * `Unknown`, on any unexpected error
332    ///
333    /// # Device Support
334    ///
335    /// Kepler or newer fully supported devices.
336    #[doc(alias = "nvmlVgpuTypeGetNumDisplayHeads")]
337    pub fn num_display_heads(&self) -> Result<u32, NvmlError> {
338        let sym = nvml_sym(
339            self.device
340                .nvml()
341                .lib
342                .nvmlVgpuTypeGetNumDisplayHeads
343                .as_ref(),
344        )?;
345
346        let mut heads = 0;
347        unsafe {
348            nvml_try(sym(self.id, &mut heads))?;
349        }
350        Ok(heads)
351    }
352
353    /// Retrieve vGPU display head's maximum supported resolution.
354    ///
355    /// The `display_head` argument specifies the 0-based display index, the
356    /// maximum being what [`VgpuType::num_display_heads`] returns.
357    ///
358    /// # Errors
359    ///
360    /// * `Uninitialized`, if the library has not been successfully initialized
361    /// * `InvalidArg`, if this `Device` is invalid
362    /// * `Unknown`, on any unexpected error
363    ///
364    /// # Device Support
365    ///
366    /// Kepler or newer fully supported devices.
367    #[doc(alias = "nvmlVgpuTypeGetResolution")]
368    pub fn resolution(&self, display_head: u32) -> Result<(u32, u32), NvmlError> {
369        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetResolution.as_ref())?;
370
371        let (mut x, mut y) = (0, 0);
372        unsafe {
373            nvml_try(sym(self.id, display_head, &mut x, &mut y))?;
374        }
375        Ok((x, y))
376    }
377
378    /// Retrieve the BAR1 info for given vGPU type.
379    ///
380    /// # Errors
381    ///
382    /// * `Uninitialized`, if the library has not been successfully initialized
383    ///
384    /// # Platform Support
385    ///
386    /// For Maxwell or newer fully supported devices.
387    #[doc(alias = "nvmlVgpuTypeGetBAR1Info")]
388    pub fn bar1_info(&self) -> Result<Bar1Info, NvmlError> {
389        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetBAR1Info.as_ref())?;
390        let mut info: nvmlVgpuTypeBar1Info_v1_t;
391        unsafe {
392            info = std::mem::zeroed();
393            nvml_try(sym(self.id, &mut info))?;
394        }
395        Ok(info.into())
396    }
397
398    /// Retrieve the static framebuffer reservation of the vGPU type in bytes
399    ///
400    /// # Errors
401    ///
402    /// * `Uninitialized`, if the library has not been successfully initialized
403    ///
404    #[doc(alias = "nvmlVgpuTypeGetFbReservation")]
405    pub fn fb_reservation(&self) -> Result<u64, NvmlError> {
406        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetFbReservation.as_ref())?;
407        let mut res = 0;
408        unsafe {
409            nvml_try(sym(self.id, &mut res))?;
410        }
411        Ok(res)
412    }
413
414    /// Retrieve the static GSP heap size of the vGPU type in bytes
415    ///
416    /// # Errors
417    ///
418    /// * `Uninitialized`, if the library has not been successfully initialized
419    #[doc(alias = "nvmlVgpuTypeGetGspHeapSize")]
420    pub fn gsp_heap_size(&self) -> Result<u64, NvmlError> {
421        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuTypeGetGspHeapSize.as_ref())?;
422        let mut res = 0;
423        unsafe {
424            nvml_try(sym(self.id, &mut res))?;
425        }
426        Ok(res)
427    }
428}
429
430pub struct VgpuInstance<'dev> {
431    pub(crate) instance: nvmlVgpuInstance_t,
432    device: &'dev Device<'dev>,
433}
434
435assert_impl_all!(VgpuInstance: Send, Sync);
436
437impl<'dev> VgpuInstance<'dev> {
438    /// Create a new vGPU instance wrapper from a raw vGPU instance ID.
439    ///
440    /// You probably don't need to use this yourself, but rather through
441    /// `Device::active_vgpus` (Linux only).
442    pub fn new(instance: nvmlVgpuInstance_t, device: &'dev Device<'dev>) -> Self {
443        Self { instance, device }
444    }
445
446    /// Retrieve the VM ID associated with a vGPU instance.
447    ///
448    /// The VM ID is returned as a string, not exceeding 80 characters in length (including the NUL
449    /// terminator). See nvmlConstants::NVML_DEVICE_UUID_BUFFER_SIZE.
450    ///
451    /// The format of the VM ID varies by platform, and is indicated by the type identifier returned
452    /// in vmIdType.
453    ///
454    /// # Errors
455    ///
456    /// * `Uninitialized` if the library has not been successfully initialized
457    /// * `NotFound` if self does not match a valid active vGPU instance on the system
458    /// * `Unknown` on any unexpected error
459    ///
460    /// # Platform Support
461    ///
462    /// For Kepler or newer fully supported devices.
463    #[doc(alias = "nvmlVgpuInstanceGetVmID")]
464    pub fn vm_id(&self) -> Result<VmId, NvmlError> {
465        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetVmID.as_ref())?;
466        let mut s = [0; NVML_DEVICE_UUID_BUFFER_SIZE as usize];
467        let mut id_type = 0;
468        let id = unsafe {
469            nvml_try(sym(
470                self.instance,
471                s.as_mut_ptr(),
472                NVML_DEVICE_UUID_BUFFER_SIZE,
473                &mut id_type,
474            ))?;
475            CStr::from_ptr(s.as_ptr())
476        };
477
478        let id = id.to_str()?.to_string();
479        Ok(match id_type {
480            nvmlVgpuVmIdType_NVML_VGPU_VM_ID_DOMAIN_ID => VmId::Domain(id),
481            nvmlVgpuVmIdType_NVML_VGPU_VM_ID_UUID => VmId::Uuid(id),
482            _ => return Err(NvmlError::Unknown),
483        })
484    }
485
486    /// Retrieve the framebuffer usage in bytes.
487    ///
488    /// Framebuffer usage is the amount of vGPU framebuffer memory that is currently in use by the VM
489    ///
490    /// # Errors
491    ///
492    /// * `Uninitialized`, if the library has not been successfully initialized
493    /// * `InvalidArg` if self is invalid
494    /// * `NotFound` if self does not match a valid active vGPU instance on the system
495    /// * `Unknown`, on any unexpected error
496    ///
497    /// # Platform Support
498    ///
499    /// For Kepler or newer fully supported devices.
500    #[doc(alias = "nvmlVgpuInstanceGetFbUsage")]
501    pub fn fb_usage(&self) -> Result<u64, NvmlError> {
502        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetFbUsage.as_ref())?;
503        let mut usage = 0;
504        unsafe {
505            nvml_try(sym(self.instance, &mut usage))?;
506        }
507        Ok(usage)
508    }
509
510    /// Retrieve the vGPU type of a vGPU instance
511    ///
512    /// Returns the vGPU type ID of vgpu assigned to the vGPU instance.
513    ///
514    /// # Errors
515    ///
516    /// * `Uninitialized`, if the library has not been successfully initialized
517    /// * `InvalidArg` if self is invalid
518    /// * `NotFound` if self does not match a valid active vGPU instance on the system
519    /// * `Unknown`, on any unexpected error
520    ///
521    /// # Platform Support
522    ///
523    /// For Maxwell or newer fully supported devices
524    #[doc(alias = "nvmlVgpuInstanceGetType")]
525    pub fn instance_type(&self) -> Result<VgpuType<'dev>, NvmlError> {
526        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetType.as_ref())?;
527        let mut raw_type = 0;
528        unsafe {
529            nvml_try(sym(self.instance, &mut raw_type))?;
530        }
531        Ok(VgpuType::new(self.device, raw_type))
532    }
533
534    /// Get the list of process ids running on this vGPU instance for stats purpose
535    ///
536    /// see [`crate::device::Device::vgpu_accounting_pids`] for details
537    #[doc(alias = "nvmlVgpuInstanceGetAccountingPids")]
538    pub fn accounting_pids(&self) -> Result<Vec<u32>, NvmlError> {
539        self.device.vgpu_accounting_pids(self.instance)
540    }
541
542    /// Clears accounting information of the vGPU instance that have already terminated.
543    ///
544    /// # Errors
545    ///
546    /// * `Uninitialized`, if the library has not been successfully initialized
547    /// * `NoPermission`, if the user doesn't have permission to perform this operation
548    /// * `NotSupported`, if the vGPU doesn't support this feature or accounting mode is disabled
549    ///
550    /// # Platform Support
551    ///
552    /// For Maxwell or newer fully supported devices. Requires root/admin permissions.
553    #[doc(alias = "nvmlVgpuInstanceClearAccountingPids")]
554    pub fn clear_accounting_pids(&self) -> Result<(), NvmlError> {
555        let sym = nvml_sym(
556            self.device
557                .nvml()
558                .lib
559                .nvmlVgpuInstanceClearAccountingPids
560                .as_ref(),
561        )?;
562        unsafe { nvml_try(sym(self.instance)) }
563    }
564
565    /// Queries the state of per process accounting mode on vGPU.
566    ///
567    /// # Errors
568    ///
569    /// * `Uninitialized`, if the library has not been successfully initialized
570    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
571    /// * `NotSupported`, if the vGPU doesn't support this feature or accounting mode is disabled
572    /// * `DriverNotLoaded`, driver is not running on the vGPU instance
573    ///
574    /// # Platform Support
575    ///
576    /// For Maxwell or newer fully supported devices.
577    #[doc(alias = "nvmlVgpuInstanceGetAccountingMode")]
578    pub fn accounting_mode(&self) -> Result<bool, NvmlError> {
579        let sym = nvml_sym(
580            self.device
581                .nvml()
582                .lib
583                .nvmlVgpuInstanceGetAccountingMode
584                .as_ref(),
585        )?;
586        let mut mode = 0;
587        unsafe {
588            nvml_try(sym(self.instance, &mut mode))?;
589        }
590        Ok(mode == nvmlEnableState_enum_NVML_FEATURE_ENABLED)
591    }
592
593    /// Retrieve the current ECC mode of vGPU instance.
594    ///
595    /// # Errors
596    ///
597    /// * `Uninitialized`, if the library has not been successfully initialized
598    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
599    /// * `NotSupported`, if the vGPU doesn't support this feature or accounting mode is disabled
600    #[doc(alias = "nvmlVgpuInstanceGetEccMode")]
601    pub fn ecc_mode(&self) -> Result<bool, NvmlError> {
602        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetEccMode.as_ref())?;
603        let mut mode = 0;
604        unsafe {
605            nvml_try(sym(self.instance, &mut mode))?;
606        }
607        Ok(mode == nvmlEnableState_enum_NVML_FEATURE_ENABLED)
608    }
609
610    /// Retrieve the encoder capacity of a vGPU instance, as a percentage of maximum encoder
611    /// capacity with valid values in the range 0-100.
612    ///
613    /// # Errors
614    ///
615    /// * `Uninitialized`, if the library has not been successfully initialized
616    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
617    ///
618    /// # Platform Support
619    ///
620    /// For Maxwell or newer fully supported devices.
621    #[doc(alias = "nvmlVgpuInstanceGetEncoderCapacity")]
622    pub fn encoder_capacity(&self) -> Result<u32, NvmlError> {
623        let sym = nvml_sym(
624            self.device
625                .nvml()
626                .lib
627                .nvmlVgpuInstanceGetEncoderCapacity
628                .as_ref(),
629        )?;
630        let mut cap = 0;
631        unsafe {
632            nvml_try(sym(self.instance, &mut cap))?;
633        }
634        Ok(cap)
635    }
636
637    /// Retrieves information about all active encoder sessions on a vGPU Instance.
638    ///
639    /// # Errors
640    ///
641    /// * `Uninitialized`, if the library has not been successfully initialized
642    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
643    ///
644    /// # Platform Support
645    ///
646    /// For Maxwell or newer fully supported devices.
647    #[doc(alias = "nvmlVgpuInstanceGetEncoderSessions")]
648    pub fn encoder_sessions(&self) -> Result<Vec<EncoderSessionInfo>, NvmlError> {
649        let sym = nvml_sym(
650            self.device
651                .nvml()
652                .lib
653                .nvmlVgpuInstanceGetEncoderSessions
654                .as_ref(),
655        )?;
656        let mut count = self.encoder_session_count()?;
657        let mut raw_sessions: Vec<nvmlEncoderSessionInfo_t>;
658        unsafe {
659            raw_sessions = vec![std::mem::zeroed(); count as usize];
660            nvml_try(sym(self.instance, &mut count, raw_sessions.as_mut_ptr()))?;
661        };
662        raw_sessions
663            .into_iter()
664            .map(EncoderSessionInfo::try_from)
665            .collect()
666    }
667
668    /// Retrieves the current encoder statistics of a vGPU Instance
669    ///
670    /// # Errors
671    ///
672    /// * `Uninitialized`, if the library has not been successfully initialized
673    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
674    ///
675    /// # Platform Support
676    ///
677    /// For Maxwell or newer fully supported devices.
678    #[doc(alias = "nvmlVgpuInstanceGetEncoderStats")]
679    pub fn encoder_stats(&self) -> Result<EncoderStats, NvmlError> {
680        let sym = nvml_sym(
681            self.device
682                .nvml()
683                .lib
684                .nvmlVgpuInstanceGetEncoderStats
685                .as_ref(),
686        )?;
687        let mut session_count = self.encoder_session_count()?;
688        let mut average_fps = 0;
689        let mut average_latency = 0;
690        unsafe {
691            nvml_try(sym(
692                self.instance,
693                &mut session_count,
694                &mut average_fps,
695                &mut average_latency,
696            ))?;
697        };
698        Ok(EncoderStats {
699            session_count,
700            average_fps,
701            average_latency,
702        })
703    }
704
705    /// Retrieves information about active frame buffer capture sessions on a vGPU Instance.
706    ///
707    /// > hResolution, vResolution, averageFPS and averageLatency data for a FBC session
708    /// > returned in sessionInfo may be zero if there are no new frames captured since the
709    /// > session started.
710    ///
711    /// # Errors
712    ///
713    /// * `Uninitialized`, if the library has not been successfully initialized
714    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
715    ///
716    /// # Platform Support
717    ///
718    /// For Maxwell or newer fully supported devices.
719    #[doc(alias = "nvmlVgpuInstanceGetFBCSessions")]
720    pub fn fbc_sessions(&self) -> Result<Vec<FbcSessionInfo>, NvmlError> {
721        let sym = nvml_sym(
722            self.device
723                .nvml()
724                .lib
725                .nvmlVgpuInstanceGetFBCSessions
726                .as_ref(),
727        )?;
728        let mut session_count = 0;
729        let mut info: Vec<nvmlFBCSessionInfo_t>;
730        unsafe {
731            nvml_try_count(sym(self.instance, &mut session_count, std::ptr::null_mut()))?;
732            if session_count == 0 {
733                return Ok(Vec::new());
734            }
735            info = vec![std::mem::zeroed(); session_count as usize];
736            nvml_try(sym(self.instance, &mut session_count, info.as_mut_ptr()))?;
737        };
738        info.into_iter().map(FbcSessionInfo::try_from).collect()
739    }
740
741    /// Retrieves the active frame buffer capture sessions statistics of a vGPU Instance
742    ///
743    /// # Errors
744    ///
745    /// * `Uninitialized`, if the library has not been successfully initialized
746    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
747    ///
748    /// # Platform Support
749    ///
750    /// For Maxwell or newer fully supported devices.
751    #[doc(alias = "nvmlVgpuInstanceGetFBCStats")]
752    pub fn fbc_stats(&self) -> Result<FbcStats, NvmlError> {
753        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetFBCStats.as_ref())?;
754        unsafe {
755            let mut info: nvmlFBCStats_t = std::mem::zeroed();
756            nvml_try(sym(self.instance, &mut info))?;
757            Ok(FbcStats::from(info))
758        }
759    }
760
761    /// Retrieve the frame rate limit set for the vGPU instance.
762    ///
763    /// Returns the value of the frame rate limit set for the vGPU instance
764    ///
765    /// # Errors
766    ///
767    /// * `Uninitialized`, if the library has not been successfully initialized
768    /// * `NotSupported`, if frame rate limiter is turned off for the vGPU type
769    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
770    ///
771    /// # Platform Support
772    ///
773    /// For Kepler or newer fully supported devices.
774    #[doc(alias = "nvmlVgpuInstanceGetFrameRateLimit")]
775    pub fn frame_rate_limit(&self) -> Result<u32, NvmlError> {
776        let sym = nvml_sym(
777            self.device
778                .nvml()
779                .lib
780                .nvmlVgpuInstanceGetFrameRateLimit
781                .as_ref(),
782        )?;
783        let mut limit = 0;
784        unsafe {
785            nvml_try(sym(self.instance, &mut limit))?;
786        };
787        Ok(limit)
788    }
789
790    /// Retrieve the GPU Instance ID for the given vGPU Instance. The API will return a valid GPU
791    /// Instance ID for MIG backed vGPU Instance, else INVALID_GPU_INSTANCE_ID is returned.
792    ///
793    /// # Errors
794    ///
795    /// * `Uninitialized`, if the library has not been successfully initialized
796    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
797    ///
798    /// # Platform Support
799    ///
800    /// For Kepler or newer fully supported devices.
801    #[doc(alias = "nvmlVgpuInstanceGetGpuInstanceId")]
802    pub fn gpu_instance_id(&self) -> Result<u32, NvmlError> {
803        let sym = nvml_sym(
804            self.device
805                .nvml()
806                .lib
807                .nvmlVgpuInstanceGetGpuInstanceId
808                .as_ref(),
809        )?;
810        let mut id = 0;
811        unsafe {
812            nvml_try(sym(self.instance, &mut id))?;
813        };
814        Ok(id)
815    }
816
817    /// Retrieves the PCI Id of the given vGPU Instance i.e. the PCI Id of the GPU as seen inside
818    /// the VM.
819    ///
820    /// The vGPU PCI id is returned as "00000000:00:00.0" if NVIDIA driver is not installed on the
821    /// vGPU instance.
822    ///
823    /// # Errors
824    ///
825    /// * `Uninitialized`, if the library has not been successfully initialized
826    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
827    /// * `DriverNotLoaded`, driver is not running on the vGPU instance
828    #[doc(alias = "nvmlVgpuInstanceGetGpuPciId")]
829    pub fn gpu_pci_id(&self) -> Result<String, NvmlError> {
830        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetGpuPciId.as_ref())?;
831        let mut buffer: Vec<c_char>;
832        let mut count = 0;
833        let raw_id = unsafe {
834            nvml_try_count(sym(self.instance, [0; 1].as_mut_ptr(), &mut count))?;
835            if count == 0 {
836                return Ok(String::new());
837            }
838            buffer = vec![0; count as usize];
839            nvml_try(sym(self.instance, buffer.as_mut_ptr(), &mut count))?;
840            CStr::from_ptr(buffer.as_ptr())
841        };
842        Ok(raw_id.to_str()?.to_string())
843    }
844
845    /// Query the license information of the vGPU instance.
846    ///
847    /// # Errors
848    ///
849    /// * `Uninitialized`, if the library has not been successfully initialized
850    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
851    /// * `DriverNotLoaded`, driver is not running on the vGPU instance
852    #[cfg(feature = "legacy-functions")]
853    #[doc(alias = "nvmlVgpuInstanceGetLicenseInfo")]
854    pub fn license_info(&self) -> Result<VgpuLicenseInfo, NvmlError> {
855        let sym = nvml_sym(
856            self.device
857                .nvml()
858                .lib
859                .nvmlVgpuInstanceGetLicenseInfo
860                .as_ref(),
861        )?;
862        let mut info: nvmlVgpuLicenseInfo_st;
863
864        unsafe {
865            info = std::mem::zeroed();
866            nvml_try(sym(self.instance, &mut info))?;
867        };
868        Ok(VgpuLicenseInfo::from(info))
869    }
870
871    /// Query the license information of the vGPU instance.
872    ///
873    /// # Errors
874    ///
875    /// * `Uninitialized`, if the library has not been successfully initialized
876    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
877    /// * `DriverNotLoaded`, driver is not running on the vGPU instance
878    ///
879    /// # Platform Support
880    ///
881    /// For Maxwell or newer fully supported devices.
882    #[doc(alias = "nvmlVgpuInstanceGetLicenseInfo_v2")]
883    pub fn license_info_v2(&self) -> Result<VgpuLicenseInfo, NvmlError> {
884        let sym = nvml_sym(
885            self.device
886                .nvml()
887                .lib
888                .nvmlVgpuInstanceGetLicenseInfo_v2
889                .as_ref(),
890        )?;
891        let mut info: nvmlVgpuLicenseInfo_st;
892
893        unsafe {
894            info = std::mem::zeroed();
895            nvml_try(sym(self.instance, &mut info))?;
896        };
897        Ok(VgpuLicenseInfo::from(info))
898    }
899
900    /// Retrieve the MDEV UUID of a vGPU instance.
901    ///
902    /// The MDEV UUID is a globally unique identifier of the mdev device assigned to the VM, and is
903    /// returned as a 5-part hexadecimal string, not exceeding 80 characters in length (including
904    /// the NULL terminator). MDEV UUID is displayed only on KVM platform.
905    /// See nvmlConstants::NVML_DEVICE_UUID_BUFFER_SIZE.
906    ///
907    /// # Errors
908    ///
909    /// * `Uninitialized`, if the library has not been successfully initialized
910    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
911    /// * `NotSupported`, on any hypervisor other than KVM
912    ///
913    /// # Platform Support
914    ///
915    /// For Maxwell or newer fully supported devices.
916    #[doc(alias = "nvmlVgpuInstanceGetMdevUUID")]
917    pub fn mdev_uuid(&self) -> Result<String, NvmlError> {
918        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetMdevUUID.as_ref())?;
919        let mut buffer: [c_char; NVML_DEVICE_UUID_BUFFER_SIZE as usize] =
920            [0; NVML_DEVICE_UUID_BUFFER_SIZE as usize];
921
922        unsafe {
923            nvml_try(sym(
924                self.instance,
925                buffer.as_mut_ptr(),
926                NVML_DEVICE_UUID_BUFFER_SIZE,
927            ))?;
928            let raw_id = CStr::from_ptr(buffer.as_ptr());
929            Ok(raw_id.to_str()?.to_string())
930        }
931    }
932
933    /// Returns vGPU metadata structure for a running vGPU. The structure contains information
934    /// about the vGPU and its associated VM such as the currently installed NVIDIA guest driver
935    /// version, together with host driver version and an opaque data section containing internal
936    /// state.
937    ///
938    /// May be called at any time for a vGPU instance. Some fields in the returned structure are
939    /// dependent on information obtained from the guest VM, which may not yet have reached a state
940    /// where that information is available.
941    ///
942    /// # Errors
943    ///
944    /// * `Uninitialized`, if the library has not been successfully initialized
945    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
946    ///
947    /// # Platform Support
948    ///
949    ///
950    #[doc(alias = "nvmlVgpuInstanceGetMetadata")]
951    pub fn metadata(&self) -> Result<VgpuMetadata, NvmlError> {
952        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetMetadata.as_ref())?;
953        let mut byte_size = 0;
954        unsafe {
955            nvml_try_count(sym(self.instance, std::ptr::null_mut(), &mut byte_size))?;
956            // The metadata is one variable-length structure: a fixed header
957            // followed by an opaque payload. Over-allocate in whole
958            // `nvmlVgpuMetadata_t`s so the buffer stays correctly aligned.
959            let struct_size = std::mem::size_of::<nvmlVgpuMetadata_t>();
960            let count = ((byte_size as usize + struct_size - 1) / struct_size).max(1);
961            let mut buffer: Vec<nvmlVgpuMetadata_t> = vec![std::mem::zeroed(); count];
962            let mut byte_size = (count * struct_size) as c_uint;
963            nvml_try(sym(self.instance, buffer.as_mut_ptr(), &mut byte_size))?;
964            VgpuMetadata::try_from(buffer[0])
965        }
966    }
967
968    /// Query the placement ID of active vGPU instance.
969    ///
970    /// When in vGPU heterogeneous mode, this function returns a valid placement ID as
971    /// [`VgpuPlacementId::id`], [`VgpuPlacementId::version`] is the version number
972    /// # Errors
973    ///
974    /// * `Uninitialized`, if the library has not been successfully initialized
975    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
976    #[doc(alias = "nvmlVgpuInstanceGetPlacementId")]
977    pub fn placement_id(&self) -> Result<VgpuPlacementId, NvmlError> {
978        let sym = nvml_sym(
979            self.device
980                .nvml()
981                .lib
982                .nvmlVgpuInstanceGetPlacementId
983                .as_ref(),
984        )?;
985        let mut raw_placement_id: nvmlVgpuPlacementId_t;
986        unsafe {
987            raw_placement_id = std::mem::zeroed();
988            nvml_try(sym(self.instance, &mut raw_placement_id))?;
989        }
990        Ok(raw_placement_id.into())
991    }
992
993    /// Retrieve the currently used runtime state size of the vGPU instance
994    ///
995    /// This size represents the maximum in-memory data size utilized by a vGPU instance during
996    /// standard operation. This measurement is exclusive of frame buffer (FB) data size assigned
997    /// to the vGPU instance.
998    ///
999    /// # Errors
1000    ///
1001    /// * `Uninitialized`, if the library has not been successfully initialized
1002    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
1003    ///
1004    /// # Platform Support
1005    ///
1006    /// For Maxwell or newer fully supported devices.
1007    #[doc(alias = "nvmlVgpuInstanceGetRuntimeStateSize")]
1008    pub fn runtime_state_size(&self) -> Result<VgpuRuntimeState, NvmlError> {
1009        let sym = nvml_sym(
1010            self.device
1011                .nvml()
1012                .lib
1013                .nvmlVgpuInstanceGetRuntimeStateSize
1014                .as_ref(),
1015        )?;
1016        let mut raw_state: nvmlVgpuRuntimeState_t;
1017        unsafe {
1018            raw_state = std::mem::zeroed();
1019            nvml_try(sym(self.instance, &mut raw_state))?;
1020        }
1021        Ok(raw_state.into())
1022    }
1023
1024    /// Retrieve the UUID of a vGPU instance.
1025    ///
1026    /// The UUID is a globally unique identifier associated with the vGPU, and is returned as a 5-part hexadecimal string
1027    ///
1028    /// # Errors
1029    ///
1030    /// * `Uninitialized`, if the library has not been successfully initialized
1031    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
1032    ///
1033    /// # Platform Support
1034    ///
1035    /// For Kepler or newer fully supported devices.
1036    #[doc(alias = "nvmlVgpuInstanceGetUUID")]
1037    pub fn uuid(&self) -> Result<String, NvmlError> {
1038        let sym = nvml_sym(self.device.nvml().lib.nvmlVgpuInstanceGetUUID.as_ref())?;
1039        let mut buffer: [c_char; NVML_DEVICE_UUID_BUFFER_SIZE as usize] =
1040            [0; NVML_DEVICE_UUID_BUFFER_SIZE as usize];
1041
1042        unsafe {
1043            nvml_try(sym(
1044                self.instance,
1045                buffer.as_mut_ptr(),
1046                NVML_DEVICE_UUID_BUFFER_SIZE,
1047            ))?;
1048            let raw_id = CStr::from_ptr(buffer.as_ptr());
1049            Ok(raw_id.to_str()?.to_string())
1050        }
1051    }
1052
1053    /// Retrieve the NVIDIA driver version installed in the VM associated with a vGPU.
1054    ///
1055    /// The version is returned as an alphanumeric string in the caller-supplied buffer version.
1056    /// This may be called at any time for a vGPU instance.
1057    ///
1058    /// The guest VM driver version is returned as "Not Available" if no NVIDIA driver is installed
1059    /// in the VM, or the VM has not yet booted to the point where the NVIDIA driver is loaded and
1060    /// initialized.
1061    ///
1062    /// # Errors
1063    ///
1064    /// * `Uninitialized`, if the library has not been successfully initialized
1065    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
1066    ///
1067    /// # Platform Support
1068    ///
1069    /// For Kepler or newer fully supported devices.
1070    #[doc(alias = "nvmlVgpuInstanceGetVmDriverVersion")]
1071    pub fn driver_version(&self) -> Result<String, NvmlError> {
1072        let sym = nvml_sym(
1073            self.device
1074                .nvml()
1075                .lib
1076                .nvmlVgpuInstanceGetVmDriverVersion
1077                .as_ref(),
1078        )?;
1079        let mut buffer: [c_char; NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE as usize] =
1080            [0; NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE as usize];
1081
1082        unsafe {
1083            nvml_try(sym(
1084                self.instance,
1085                buffer.as_mut_ptr(),
1086                NVML_SYSTEM_NVML_VERSION_BUFFER_SIZE,
1087            ))?;
1088            let raw_id = CStr::from_ptr(buffer.as_ptr());
1089            Ok(raw_id.to_str()?.to_string())
1090        }
1091    }
1092    /// Set the encoder capacity of a vGPU instance, as a percentage of maximum encoder capacity with valid values in the range 0-100.
1093    ///
1094    /// # Errors
1095    ///
1096    /// * `Uninitialized`, if the library has not been successfully initialized
1097    /// * `NotFound`, if the vGPU does not match a valid active vGPU instance on the system
1098    ///
1099    /// # Platform Support
1100    ///
1101    /// For Maxwell or newer fully supported devices.
1102    #[doc(alias = "nvmlVgpuInstanceSetEncoderCapacity")]
1103    pub fn set_encoder_capacity(&self, capacity: u32) -> Result<(), NvmlError> {
1104        let sym = nvml_sym(
1105            self.device
1106                .nvml()
1107                .lib
1108                .nvmlVgpuInstanceSetEncoderCapacity
1109                .as_ref(),
1110        )?;
1111
1112        unsafe {
1113            nvml_try(sym(self.instance, capacity))?;
1114        }
1115        Ok(())
1116    }
1117
1118    fn encoder_session_count(&self) -> Result<u32, NvmlError> {
1119        let sym = nvml_sym(
1120            self.device
1121                .nvml()
1122                .lib
1123                .nvmlVgpuInstanceGetEncoderSessions
1124                .as_ref(),
1125        )?;
1126        let mut count = 0;
1127        unsafe {
1128            nvml_try_count(sym(self.instance, &mut count, std::ptr::null_mut()))?;
1129        };
1130        Ok(count)
1131    }
1132}
1133
1134impl<'dev> std::fmt::Debug for VgpuInstance<'dev> {
1135    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1136        f.debug_struct("VgpuInstance")
1137            .field("instance", &self.instance)
1138            .finish_non_exhaustive()
1139    }
1140}
1141
1142#[cfg(test)]
1143mod tests {
1144    use super::*;
1145
1146    use crate::test_utils::*;
1147
1148    #[test]
1149    fn vgpu_type_class_name() {
1150        let nvml = nvml();
1151        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).class_name());
1152    }
1153
1154    #[test]
1155    fn vgpu_type_license() {
1156        let nvml = nvml();
1157        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).license());
1158    }
1159
1160    #[test]
1161    fn vgpu_type_name() {
1162        let nvml = nvml();
1163        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).name());
1164    }
1165
1166    #[test]
1167    fn vgpu_type_device_id() {
1168        let nvml = nvml();
1169        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).device_id());
1170    }
1171
1172    #[test]
1173    fn vgpu_type_frame_rate_limit() {
1174        let nvml = nvml();
1175        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).frame_rate_limit());
1176    }
1177
1178    #[test]
1179    fn vgpu_type_framebuffer_size() {
1180        let nvml = nvml();
1181        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).framebuffer_size());
1182    }
1183
1184    #[test]
1185    fn vgpu_type_instance_profile_id() {
1186        let nvml = nvml();
1187        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).instance_profile_id());
1188    }
1189
1190    #[test]
1191    fn vgpu_type_max_instances() {
1192        let nvml = nvml();
1193        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).max_instances());
1194    }
1195
1196    #[test]
1197    fn vgpu_type_max_instances_per_vm() {
1198        let nvml = nvml();
1199        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).max_instances_per_vm());
1200    }
1201
1202    #[test]
1203    fn vgpu_type_num_display_heads() {
1204        let nvml = nvml();
1205        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).num_display_heads());
1206    }
1207
1208    #[test]
1209    fn vgpu_type_resolution() {
1210        let nvml = nvml();
1211        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).resolution(1));
1212    }
1213
1214    #[test]
1215    fn vgpu_type_get_bar1_info() {
1216        let nvml = nvml();
1217        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).bar1_info());
1218    }
1219
1220    #[test]
1221    fn vgpu_type_get_fb_reservation() {
1222        let nvml = nvml();
1223        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).fb_reservation());
1224    }
1225
1226    #[test]
1227    fn vgpu_type_get_gsp_heap_size() {
1228        let nvml = nvml();
1229        test_with_device(1, &nvml, |dev| VgpuType::new(dev, 1).gsp_heap_size());
1230    }
1231
1232    #[test]
1233    fn vgpu_instance_get_vm_id() {
1234        let nvml = nvml();
1235        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).vm_id());
1236    }
1237
1238    #[test]
1239    fn vgpu_instance_get_fb_usage() {
1240        let nvml = nvml();
1241        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).fb_usage());
1242    }
1243
1244    #[test]
1245    fn vgpu_instance_get_instance_type() {
1246        let nvml = nvml();
1247        test_with_device(1, &nvml, |dev| {
1248            Ok(VgpuInstance::new(1, dev).instance_type()?.id)
1249        });
1250    }
1251
1252    #[test]
1253    fn vgpu_instance_accounting_pids() {
1254        let nvml = nvml();
1255        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).accounting_pids());
1256    }
1257
1258    #[test]
1259    fn vgpu_instance_clear_accounting_pids() {
1260        let nvml = nvml();
1261        test_with_device(1, &nvml, |dev| {
1262            VgpuInstance::new(1, dev).clear_accounting_pids()
1263        });
1264    }
1265
1266    #[test]
1267    fn vgpu_instance_get_accounting_mode() {
1268        let nvml = nvml();
1269        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).accounting_mode());
1270    }
1271
1272    #[test]
1273    fn vgpu_instance_get_ecc_mode() {
1274        let nvml = nvml();
1275        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).ecc_mode());
1276    }
1277
1278    #[test]
1279    fn vgpu_instance_get_encoder_capacity() {
1280        let nvml = nvml();
1281        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).encoder_capacity());
1282    }
1283
1284    #[test]
1285    fn vgpu_instance_get_encoder_sessions() {
1286        let nvml = nvml();
1287        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).encoder_sessions());
1288    }
1289
1290    #[test]
1291    fn vgpu_instance_get_encoder_stats() {
1292        let nvml = nvml();
1293        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).encoder_stats());
1294    }
1295
1296    #[test]
1297    fn vgpu_instance_get_fbc_sessions() {
1298        let nvml = nvml();
1299        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).fbc_sessions());
1300    }
1301
1302    #[test]
1303    fn vgpu_instance_get_fbc_stats() {
1304        let nvml = nvml();
1305        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).fbc_stats());
1306    }
1307
1308    #[test]
1309    fn vgpu_instance_get_frame_rate_limit() {
1310        let nvml = nvml();
1311        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).frame_rate_limit());
1312    }
1313
1314    #[test]
1315    fn vgpu_instance_get_gpu_instance_id() {
1316        let nvml = nvml();
1317        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).gpu_instance_id());
1318    }
1319
1320    #[test]
1321    fn vgpu_instance_get_gpu_pci_id() {
1322        let nvml = nvml();
1323        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).gpu_pci_id());
1324    }
1325
1326    #[test]
1327    #[cfg(feature = "legacy-functions")]
1328    fn vgpu_instance_get_license_info() {
1329        let nvml = nvml();
1330        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).license_info());
1331    }
1332
1333    #[test]
1334    fn vgpu_instance_get_license_info_v2() {
1335        let nvml = nvml();
1336        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).license_info_v2());
1337    }
1338
1339    #[test]
1340    fn vgpu_instance_get_mdev_uuid() {
1341        let nvml = nvml();
1342        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).mdev_uuid());
1343    }
1344
1345    #[test]
1346    fn vgpu_instance_get_metadata() {
1347        let nvml = nvml();
1348        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).metadata());
1349    }
1350
1351    #[test]
1352    fn vgpu_instance_get_placement_id() {
1353        let nvml = nvml();
1354        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).placement_id());
1355    }
1356
1357    #[test]
1358    fn vgpu_instance_get_runtime_state_size() {
1359        let nvml = nvml();
1360        test_with_device(1, &nvml, |dev| {
1361            VgpuInstance::new(1, dev).runtime_state_size()
1362        });
1363    }
1364
1365    #[test]
1366    fn vgpu_instance_get_uuid() {
1367        let nvml = nvml();
1368        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).uuid());
1369    }
1370
1371    #[test]
1372    fn vgpu_instance_get_driver_version() {
1373        let nvml = nvml();
1374        test_with_device(1, &nvml, |dev| VgpuInstance::new(1, dev).driver_version());
1375    }
1376
1377    #[test]
1378    fn vgpu_instance_set_encoder_capacity() {
1379        let nvml = nvml();
1380        test_with_device(1, &nvml, |dev| {
1381            VgpuInstance::new(1, dev).set_encoder_capacity(50)
1382        });
1383    }
1384}