mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
feat: proper vram size and usage reporting on intel (#442)
* chore: add vangogh test data * feat: proper intel vram reporting * feat: vendor all header files
This commit is contained in:
3916
lact-daemon/include/drm/i915_drm.h
Normal file
3916
lact-daemon/include/drm/i915_drm.h
Normal file
File diff suppressed because it is too large
Load Diff
341
lact-daemon/include/drm/intel_bufmgr.h
Normal file
341
lact-daemon/include/drm/intel_bufmgr.h
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright © 2008-2012 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file intel_bufmgr.h
|
||||
*
|
||||
* Public definitions of Intel-specific bufmgr functions.
|
||||
*/
|
||||
|
||||
#ifndef INTEL_BUFMGR_H
|
||||
#define INTEL_BUFMGR_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct drm_clip_rect;
|
||||
|
||||
typedef struct _drm_intel_bufmgr drm_intel_bufmgr;
|
||||
typedef struct _drm_intel_context drm_intel_context;
|
||||
typedef struct _drm_intel_bo drm_intel_bo;
|
||||
|
||||
struct _drm_intel_bo {
|
||||
/**
|
||||
* Size in bytes of the buffer object.
|
||||
*
|
||||
* The size may be larger than the size originally requested for the
|
||||
* allocation, such as being aligned to page size.
|
||||
*/
|
||||
unsigned long size;
|
||||
|
||||
/**
|
||||
* Alignment requirement for object
|
||||
*
|
||||
* Used for GTT mapping & pinning the object.
|
||||
*/
|
||||
unsigned long align;
|
||||
|
||||
/**
|
||||
* Deprecated field containing (possibly the low 32-bits of) the last
|
||||
* seen virtual card address. Use offset64 instead.
|
||||
*/
|
||||
unsigned long offset;
|
||||
|
||||
/**
|
||||
* Virtual address for accessing the buffer data. Only valid while
|
||||
* mapped.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
void *virt;
|
||||
#else
|
||||
void *virtual;
|
||||
#endif
|
||||
|
||||
/** Buffer manager context associated with this buffer object */
|
||||
drm_intel_bufmgr *bufmgr;
|
||||
|
||||
/**
|
||||
* MM-specific handle for accessing object
|
||||
*/
|
||||
int handle;
|
||||
|
||||
/**
|
||||
* Last seen card virtual address (offset from the beginning of the
|
||||
* aperture) for the object. This should be used to fill relocation
|
||||
* entries when calling drm_intel_bo_emit_reloc()
|
||||
*/
|
||||
uint64_t offset64;
|
||||
};
|
||||
|
||||
enum aub_dump_bmp_format {
|
||||
AUB_DUMP_BMP_FORMAT_8BIT = 1,
|
||||
AUB_DUMP_BMP_FORMAT_ARGB_4444 = 4,
|
||||
AUB_DUMP_BMP_FORMAT_ARGB_0888 = 6,
|
||||
AUB_DUMP_BMP_FORMAT_ARGB_8888 = 7,
|
||||
};
|
||||
|
||||
typedef struct _drm_intel_aub_annotation {
|
||||
uint32_t type;
|
||||
uint32_t subtype;
|
||||
uint32_t ending_offset;
|
||||
} drm_intel_aub_annotation;
|
||||
|
||||
#define BO_ALLOC_FOR_RENDER (1<<0)
|
||||
|
||||
drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
|
||||
unsigned long size, unsigned int alignment);
|
||||
drm_intel_bo *drm_intel_bo_alloc_for_render(drm_intel_bufmgr *bufmgr,
|
||||
const char *name,
|
||||
unsigned long size,
|
||||
unsigned int alignment);
|
||||
drm_intel_bo *drm_intel_bo_alloc_userptr(drm_intel_bufmgr *bufmgr,
|
||||
const char *name,
|
||||
void *addr, uint32_t tiling_mode,
|
||||
uint32_t stride, unsigned long size,
|
||||
unsigned long flags);
|
||||
drm_intel_bo *drm_intel_bo_alloc_tiled(drm_intel_bufmgr *bufmgr,
|
||||
const char *name,
|
||||
int x, int y, int cpp,
|
||||
uint32_t *tiling_mode,
|
||||
unsigned long *pitch,
|
||||
unsigned long flags);
|
||||
void drm_intel_bo_reference(drm_intel_bo *bo);
|
||||
void drm_intel_bo_unreference(drm_intel_bo *bo);
|
||||
int drm_intel_bo_map(drm_intel_bo *bo, int write_enable);
|
||||
int drm_intel_bo_unmap(drm_intel_bo *bo);
|
||||
|
||||
int drm_intel_bo_subdata(drm_intel_bo *bo, unsigned long offset,
|
||||
unsigned long size, const void *data);
|
||||
int drm_intel_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
|
||||
unsigned long size, void *data);
|
||||
void drm_intel_bo_wait_rendering(drm_intel_bo *bo);
|
||||
|
||||
void drm_intel_bufmgr_set_debug(drm_intel_bufmgr *bufmgr, int enable_debug);
|
||||
void drm_intel_bufmgr_destroy(drm_intel_bufmgr *bufmgr);
|
||||
int drm_intel_bo_exec(drm_intel_bo *bo, int used,
|
||||
struct drm_clip_rect *cliprects, int num_cliprects, int DR4);
|
||||
int drm_intel_bo_mrb_exec(drm_intel_bo *bo, int used,
|
||||
struct drm_clip_rect *cliprects, int num_cliprects, int DR4,
|
||||
unsigned int flags);
|
||||
int drm_intel_bufmgr_check_aperture_space(drm_intel_bo ** bo_array, int count);
|
||||
|
||||
int drm_intel_bo_emit_reloc(drm_intel_bo *bo, uint32_t offset,
|
||||
drm_intel_bo *target_bo, uint32_t target_offset,
|
||||
uint32_t read_domains, uint32_t write_domain);
|
||||
int drm_intel_bo_emit_reloc_fence(drm_intel_bo *bo, uint32_t offset,
|
||||
drm_intel_bo *target_bo,
|
||||
uint32_t target_offset,
|
||||
uint32_t read_domains, uint32_t write_domain);
|
||||
int drm_intel_bo_pin(drm_intel_bo *bo, uint32_t alignment);
|
||||
int drm_intel_bo_unpin(drm_intel_bo *bo);
|
||||
int drm_intel_bo_set_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
|
||||
uint32_t stride);
|
||||
int drm_intel_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
|
||||
uint32_t * swizzle_mode);
|
||||
int drm_intel_bo_flink(drm_intel_bo *bo, uint32_t * name);
|
||||
int drm_intel_bo_busy(drm_intel_bo *bo);
|
||||
int drm_intel_bo_madvise(drm_intel_bo *bo, int madv);
|
||||
int drm_intel_bo_use_48b_address_range(drm_intel_bo *bo, uint32_t enable);
|
||||
int drm_intel_bo_set_softpin_offset(drm_intel_bo *bo, uint64_t offset);
|
||||
|
||||
int drm_intel_bo_disable_reuse(drm_intel_bo *bo);
|
||||
int drm_intel_bo_is_reusable(drm_intel_bo *bo);
|
||||
int drm_intel_bo_references(drm_intel_bo *bo, drm_intel_bo *target_bo);
|
||||
|
||||
/* drm_intel_bufmgr_gem.c */
|
||||
drm_intel_bufmgr *drm_intel_bufmgr_gem_init(int fd, int batch_size);
|
||||
drm_intel_bo *drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
|
||||
const char *name,
|
||||
unsigned int handle);
|
||||
void drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr);
|
||||
void drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr);
|
||||
void drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr,
|
||||
int limit);
|
||||
int drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo);
|
||||
int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo);
|
||||
int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo);
|
||||
|
||||
#define HAVE_DRM_INTEL_GEM_BO_DISABLE_IMPLICIT_SYNC 1
|
||||
int drm_intel_bufmgr_gem_can_disable_implicit_sync(drm_intel_bufmgr *bufmgr);
|
||||
void drm_intel_gem_bo_disable_implicit_sync(drm_intel_bo *bo);
|
||||
void drm_intel_gem_bo_enable_implicit_sync(drm_intel_bo *bo);
|
||||
|
||||
void *drm_intel_gem_bo_map__cpu(drm_intel_bo *bo);
|
||||
void *drm_intel_gem_bo_map__gtt(drm_intel_bo *bo);
|
||||
void *drm_intel_gem_bo_map__wc(drm_intel_bo *bo);
|
||||
|
||||
int drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo);
|
||||
void drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start);
|
||||
void drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable);
|
||||
|
||||
void
|
||||
drm_intel_bufmgr_gem_set_aub_filename(drm_intel_bufmgr *bufmgr,
|
||||
const char *filename);
|
||||
void drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable);
|
||||
void drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
|
||||
int x1, int y1, int width, int height,
|
||||
enum aub_dump_bmp_format format,
|
||||
int pitch, int offset);
|
||||
void
|
||||
drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
|
||||
drm_intel_aub_annotation *annotations,
|
||||
unsigned count);
|
||||
|
||||
int drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id);
|
||||
|
||||
int drm_intel_get_aperture_sizes(int fd, size_t *mappable, size_t *total);
|
||||
int drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr);
|
||||
int drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns);
|
||||
|
||||
drm_intel_context *drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr);
|
||||
int drm_intel_gem_context_get_id(drm_intel_context *ctx,
|
||||
uint32_t *ctx_id);
|
||||
void drm_intel_gem_context_destroy(drm_intel_context *ctx);
|
||||
int drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
|
||||
int used, unsigned int flags);
|
||||
int drm_intel_gem_bo_fence_exec(drm_intel_bo *bo,
|
||||
drm_intel_context *ctx,
|
||||
int used,
|
||||
int in_fence,
|
||||
int *out_fence,
|
||||
unsigned int flags);
|
||||
|
||||
int drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd);
|
||||
drm_intel_bo *drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr,
|
||||
int prime_fd, int size);
|
||||
|
||||
/* drm_intel_bufmgr_fake.c */
|
||||
drm_intel_bufmgr *drm_intel_bufmgr_fake_init(int fd,
|
||||
unsigned long low_offset,
|
||||
void *low_virtual,
|
||||
unsigned long size,
|
||||
volatile unsigned int
|
||||
*last_dispatch);
|
||||
void drm_intel_bufmgr_fake_set_last_dispatch(drm_intel_bufmgr *bufmgr,
|
||||
volatile unsigned int
|
||||
*last_dispatch);
|
||||
void drm_intel_bufmgr_fake_set_exec_callback(drm_intel_bufmgr *bufmgr,
|
||||
int (*exec) (drm_intel_bo *bo,
|
||||
unsigned int used,
|
||||
void *priv),
|
||||
void *priv);
|
||||
void drm_intel_bufmgr_fake_set_fence_callback(drm_intel_bufmgr *bufmgr,
|
||||
unsigned int (*emit) (void *priv),
|
||||
void (*wait) (unsigned int fence,
|
||||
void *priv),
|
||||
void *priv);
|
||||
drm_intel_bo *drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr,
|
||||
const char *name,
|
||||
unsigned long offset,
|
||||
unsigned long size, void *virt);
|
||||
void drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo,
|
||||
void (*invalidate_cb) (drm_intel_bo
|
||||
* bo,
|
||||
void *ptr),
|
||||
void *ptr);
|
||||
|
||||
void drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr);
|
||||
void drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr);
|
||||
|
||||
struct drm_intel_decode *drm_intel_decode_context_alloc(uint32_t devid);
|
||||
void drm_intel_decode_context_free(struct drm_intel_decode *ctx);
|
||||
void drm_intel_decode_set_batch_pointer(struct drm_intel_decode *ctx,
|
||||
void *data, uint32_t hw_offset,
|
||||
int count);
|
||||
void drm_intel_decode_set_dump_past_end(struct drm_intel_decode *ctx,
|
||||
int dump_past_end);
|
||||
void drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx,
|
||||
uint32_t head, uint32_t tail);
|
||||
void drm_intel_decode_set_output_file(struct drm_intel_decode *ctx, FILE *out);
|
||||
void drm_intel_decode(struct drm_intel_decode *ctx);
|
||||
|
||||
int drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
|
||||
uint32_t offset,
|
||||
uint64_t *result);
|
||||
|
||||
int drm_intel_get_reset_stats(drm_intel_context *ctx,
|
||||
uint32_t *reset_count,
|
||||
uint32_t *active,
|
||||
uint32_t *pending);
|
||||
|
||||
int drm_intel_get_subslice_total(int fd, unsigned int *subslice_total);
|
||||
int drm_intel_get_eu_total(int fd, unsigned int *eu_total);
|
||||
|
||||
int drm_intel_get_pooled_eu(int fd);
|
||||
int drm_intel_get_min_eu_in_pool(int fd);
|
||||
|
||||
/** @{ Compatibility defines to keep old code building despite the symbol rename
|
||||
* from dri_* to drm_intel_*
|
||||
*/
|
||||
#define dri_bo drm_intel_bo
|
||||
#define dri_bufmgr drm_intel_bufmgr
|
||||
#define dri_bo_alloc drm_intel_bo_alloc
|
||||
#define dri_bo_reference drm_intel_bo_reference
|
||||
#define dri_bo_unreference drm_intel_bo_unreference
|
||||
#define dri_bo_map drm_intel_bo_map
|
||||
#define dri_bo_unmap drm_intel_bo_unmap
|
||||
#define dri_bo_subdata drm_intel_bo_subdata
|
||||
#define dri_bo_get_subdata drm_intel_bo_get_subdata
|
||||
#define dri_bo_wait_rendering drm_intel_bo_wait_rendering
|
||||
#define dri_bufmgr_set_debug drm_intel_bufmgr_set_debug
|
||||
#define dri_bufmgr_destroy drm_intel_bufmgr_destroy
|
||||
#define dri_bo_exec drm_intel_bo_exec
|
||||
#define dri_bufmgr_check_aperture_space drm_intel_bufmgr_check_aperture_space
|
||||
#define dri_bo_emit_reloc(reloc_bo, read, write, target_offset, \
|
||||
reloc_offset, target_bo) \
|
||||
drm_intel_bo_emit_reloc(reloc_bo, reloc_offset, \
|
||||
target_bo, target_offset, \
|
||||
read, write);
|
||||
#define dri_bo_pin drm_intel_bo_pin
|
||||
#define dri_bo_unpin drm_intel_bo_unpin
|
||||
#define dri_bo_get_tiling drm_intel_bo_get_tiling
|
||||
#define dri_bo_set_tiling(bo, mode) drm_intel_bo_set_tiling(bo, mode, 0)
|
||||
#define dri_bo_flink drm_intel_bo_flink
|
||||
#define intel_bufmgr_gem_init drm_intel_bufmgr_gem_init
|
||||
#define intel_bo_gem_create_from_name drm_intel_bo_gem_create_from_name
|
||||
#define intel_bufmgr_gem_enable_reuse drm_intel_bufmgr_gem_enable_reuse
|
||||
#define intel_bufmgr_fake_init drm_intel_bufmgr_fake_init
|
||||
#define intel_bufmgr_fake_set_last_dispatch drm_intel_bufmgr_fake_set_last_dispatch
|
||||
#define intel_bufmgr_fake_set_exec_callback drm_intel_bufmgr_fake_set_exec_callback
|
||||
#define intel_bufmgr_fake_set_fence_callback drm_intel_bufmgr_fake_set_fence_callback
|
||||
#define intel_bo_fake_alloc_static drm_intel_bo_fake_alloc_static
|
||||
#define intel_bo_fake_disable_backing_store drm_intel_bo_fake_disable_backing_store
|
||||
#define intel_bufmgr_fake_contended_lock_take drm_intel_bufmgr_fake_contended_lock_take
|
||||
#define intel_bufmgr_fake_evict_all drm_intel_bufmgr_fake_evict_all
|
||||
|
||||
/** @{ */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INTEL_BUFMGR_H */
|
||||
@@ -1,2 +1,3 @@
|
||||
#include "drm/i915_drm.h"
|
||||
#include "drm/intel_bufmgr.h"
|
||||
#include "drm/xe_drm.h"
|
||||
#include <libdrm/intel_bufmgr.h>
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
mod drm;
|
||||
|
||||
use super::{CommonControllerInfo, GpuController};
|
||||
use crate::{bindings::intel::IntelDrm, config, server::vulkan::get_vulkan_info};
|
||||
use crate::{
|
||||
bindings::intel::{
|
||||
drm_i915_gem_memory_class_I915_MEMORY_CLASS_DEVICE,
|
||||
drm_xe_memory_class_DRM_XE_MEM_REGION_CLASS_VRAM, IntelDrm,
|
||||
},
|
||||
config,
|
||||
server::vulkan::get_vulkan_info,
|
||||
};
|
||||
use amdgpu_sysfs::{gpu_handle::power_profile_mode::PowerProfileModesTable, hw_mon::Temperature};
|
||||
use anyhow::{anyhow, Context};
|
||||
use futures::future::LocalBoxFuture;
|
||||
@@ -116,200 +125,7 @@ impl IntelGpuController {
|
||||
|
||||
Ok(controller)
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuController for IntelGpuController {
|
||||
fn controller_info(&self) -> &CommonControllerInfo {
|
||||
&self.common
|
||||
}
|
||||
|
||||
fn get_info(&self) -> DeviceInfo {
|
||||
let vulkan_info = match get_vulkan_info(&self.common.pci_info) {
|
||||
Ok(info) => Some(info),
|
||||
Err(err) => {
|
||||
warn!("could not load vulkan info: {err}");
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let drm_info = DrmInfo {
|
||||
intel: match self.driver_type {
|
||||
DriverType::I915 => self.get_drm_info_i915(),
|
||||
DriverType::Xe => self.get_drm_info_xe(),
|
||||
},
|
||||
vram_clock_ratio: 1.0,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
DeviceInfo {
|
||||
pci_info: Some(self.common.pci_info.clone()),
|
||||
vulkan_info,
|
||||
driver: self.common.driver.clone(),
|
||||
vbios_version: None,
|
||||
link_info: LinkInfo::default(),
|
||||
drm_info: Some(drm_info),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||
fn apply_config<'a>(
|
||||
&'a self,
|
||||
config: &'a config::Gpu,
|
||||
) -> LocalBoxFuture<'a, anyhow::Result<()>> {
|
||||
Box::pin(async {
|
||||
if let Some(max_clock) = config.clocks_configuration.max_core_clock {
|
||||
self.write_freq(FrequencyType::Max, max_clock)
|
||||
.context("Could not set max clock")?;
|
||||
}
|
||||
|
||||
if let Some(min_clock) = config.clocks_configuration.min_core_clock {
|
||||
self.write_freq(FrequencyType::Min, min_clock)
|
||||
.context("Could not set min clock")?;
|
||||
}
|
||||
|
||||
if let Some(cap) = config.power_cap {
|
||||
self.write_hwmon_file("power", "_max", &((cap * 1_000_000.0) as u64).to_string())
|
||||
.context("Could not set power cap")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn get_stats(&self, _gpu_config: Option<&config::Gpu>) -> DeviceStats {
|
||||
let current_gfxclk = self.read_freq(FrequencyType::Cur);
|
||||
let gpu_clockspeed = self
|
||||
.read_freq(FrequencyType::Act)
|
||||
.filter(|value| *value != 0)
|
||||
.or(current_gfxclk);
|
||||
|
||||
let clockspeed = ClockspeedStats {
|
||||
gpu_clockspeed,
|
||||
current_gfxclk,
|
||||
vram_clockspeed: None,
|
||||
};
|
||||
|
||||
let cap_current = self
|
||||
.read_hwmon_file("power", "_max")
|
||||
.map(|value: f64| value / 1_000_000.0)
|
||||
.map(|cap| if cap == 0.0 { 100.0 } else { cap }); // Placeholder max value
|
||||
|
||||
let power = PowerStats {
|
||||
average: None,
|
||||
current: self.get_power_usage(),
|
||||
cap_current,
|
||||
cap_min: Some(0.0),
|
||||
cap_max: self
|
||||
.read_hwmon_file::<f64>("power", "_rated_max")
|
||||
.filter(|max| *max != 0.0)
|
||||
.map(|cap| cap / 1_000_000.0)
|
||||
.or_else(|| cap_current.map(|current| current * 2.0)),
|
||||
cap_default: self.initial_power_cap,
|
||||
};
|
||||
|
||||
let voltage = VoltageStats {
|
||||
gpu: self.read_hwmon_file("in", "_input"),
|
||||
northbridge: None,
|
||||
};
|
||||
|
||||
let vram = VramStats {
|
||||
total: self
|
||||
.drm_try_2(IntelDrm::drm_intel_get_aperture_sizes)
|
||||
.map(|(_, total)| total as u64),
|
||||
used: None,
|
||||
};
|
||||
|
||||
let fan = FanStats {
|
||||
speed_current: self.read_hwmon_file("fan", "_input"),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
DeviceStats {
|
||||
clockspeed,
|
||||
vram,
|
||||
busy_percent: self.get_busy_percent(),
|
||||
power,
|
||||
temps: self.get_temperatures(),
|
||||
voltage,
|
||||
throttle_info: self.get_throttle_info(),
|
||||
fan,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_clocks_info(&self) -> anyhow::Result<ClocksInfo> {
|
||||
let clocks_table = IntelClocksTable {
|
||||
gt_freq: self
|
||||
.read_freq(FrequencyType::Min)
|
||||
.zip(self.read_freq(FrequencyType::Max)),
|
||||
rp0_freq: self.read_freq(FrequencyType::Rp0),
|
||||
rpe_freq: self.read_freq(FrequencyType::Rpe),
|
||||
rpn_freq: self.read_freq(FrequencyType::Rpn),
|
||||
};
|
||||
|
||||
let table = if clocks_table == IntelClocksTable::default() {
|
||||
None
|
||||
} else {
|
||||
Some(ClocksTable::Intel(clocks_table))
|
||||
};
|
||||
|
||||
Ok(ClocksInfo {
|
||||
table,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn get_power_states(&self, _gpu_config: Option<&config::Gpu>) -> PowerStates {
|
||||
let core = [
|
||||
FrequencyType::Rpn,
|
||||
FrequencyType::Rpe,
|
||||
FrequencyType::Rp0,
|
||||
FrequencyType::Boost,
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|freq_type| {
|
||||
let value = self.read_freq(freq_type)?;
|
||||
Some(PowerState {
|
||||
enabled: true,
|
||||
min_value: None,
|
||||
value,
|
||||
index: None,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
PowerStates { core, vram: vec![] }
|
||||
}
|
||||
|
||||
fn reset_pmfw_settings(&self) {}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn cleanup_clocks(&self) -> anyhow::Result<()> {
|
||||
if let Some(rp0) = self.read_freq(FrequencyType::Rp0) {
|
||||
if let Err(err) = self.write_freq(FrequencyType::Max, rp0 as i32) {
|
||||
warn!("could not reset max clock: {err:#}");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(rpn) = self.read_freq(FrequencyType::Rpn) {
|
||||
if let Err(err) = self.write_freq(FrequencyType::Min, rpn as i32) {
|
||||
warn!("could not reset min clock: {err:#}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_power_profile_modes(&self) -> anyhow::Result<PowerProfileModesTable> {
|
||||
Err(anyhow!("Not supported"))
|
||||
}
|
||||
|
||||
fn vbios_dump(&self) -> anyhow::Result<Vec<u8>> {
|
||||
Err(anyhow!("Not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntelGpuController {
|
||||
#[allow(clippy::unused_self)]
|
||||
fn debugfs_path(&self) -> PathBuf {
|
||||
#[cfg(test)]
|
||||
@@ -436,26 +252,6 @@ impl IntelGpuController {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, allow(unreachable_code, unused_variables))]
|
||||
fn drm_try_2<T: Default, O: Default>(
|
||||
&self,
|
||||
f: unsafe fn(&IntelDrm, c_int, *mut T, *mut O) -> c_int,
|
||||
) -> Option<(T, O)> {
|
||||
#[cfg(test)]
|
||||
return None;
|
||||
|
||||
unsafe {
|
||||
let mut a = T::default();
|
||||
let mut b = O::default();
|
||||
let result = f(&self.drm, self.drm_file.as_raw_fd(), &mut a, &mut b);
|
||||
if result == 0 {
|
||||
Some((a, b))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(
|
||||
clippy::cast_precision_loss,
|
||||
clippy::cast_sign_loss,
|
||||
@@ -624,6 +420,250 @@ impl IntelGpuController {
|
||||
}
|
||||
Some(reasons)
|
||||
}
|
||||
|
||||
fn get_vram_stats(&self) -> VramStats {
|
||||
let mut total = None;
|
||||
let mut used = None;
|
||||
|
||||
match self.driver_type {
|
||||
DriverType::I915 => {
|
||||
if let Ok(Some(query)) = drm::i915::query_memory_regions(&self.drm_file) {
|
||||
let mut i915_total = 0;
|
||||
let mut i915_unallocated = 0;
|
||||
|
||||
unsafe {
|
||||
let regions = query.regions.as_slice(query.num_regions as usize);
|
||||
for region_info in regions {
|
||||
if u32::from(region_info.region.memory_class)
|
||||
== drm_i915_gem_memory_class_I915_MEMORY_CLASS_DEVICE
|
||||
{
|
||||
i915_total += region_info.probed_size;
|
||||
i915_unallocated += region_info.unallocated_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if i915_total > 0 {
|
||||
total = Some(i915_total);
|
||||
}
|
||||
if i915_total > 0 {
|
||||
used = Some(i915_total - i915_unallocated);
|
||||
}
|
||||
}
|
||||
}
|
||||
DriverType::Xe => {
|
||||
if let Ok(Some(query)) = drm::xe::query_mem_regions(&self.drm_file) {
|
||||
let mut xe_total = 0;
|
||||
let mut xe_used = 0;
|
||||
|
||||
unsafe {
|
||||
let regions = query.mem_regions.as_slice(query.num_mem_regions as usize);
|
||||
for region_info in regions {
|
||||
if u32::from(region_info.mem_class)
|
||||
== drm_xe_memory_class_DRM_XE_MEM_REGION_CLASS_VRAM
|
||||
{
|
||||
xe_total += region_info.total_size;
|
||||
xe_used += region_info.used;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if xe_used > 0 {
|
||||
total = Some(xe_total);
|
||||
}
|
||||
if xe_used > 0 {
|
||||
used = Some(xe_used);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VramStats { total, used }
|
||||
}
|
||||
}
|
||||
|
||||
impl GpuController for IntelGpuController {
|
||||
fn controller_info(&self) -> &CommonControllerInfo {
|
||||
&self.common
|
||||
}
|
||||
|
||||
fn get_info(&self) -> DeviceInfo {
|
||||
let vulkan_info = match get_vulkan_info(&self.common.pci_info) {
|
||||
Ok(info) => Some(info),
|
||||
Err(err) => {
|
||||
warn!("could not load vulkan info: {err}");
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let drm_info = DrmInfo {
|
||||
intel: match self.driver_type {
|
||||
DriverType::I915 => self.get_drm_info_i915(),
|
||||
DriverType::Xe => self.get_drm_info_xe(),
|
||||
},
|
||||
vram_clock_ratio: 1.0,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
DeviceInfo {
|
||||
pci_info: Some(self.common.pci_info.clone()),
|
||||
vulkan_info,
|
||||
driver: self.common.driver.clone(),
|
||||
vbios_version: None,
|
||||
link_info: LinkInfo::default(),
|
||||
drm_info: Some(drm_info),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||
fn apply_config<'a>(
|
||||
&'a self,
|
||||
config: &'a config::Gpu,
|
||||
) -> LocalBoxFuture<'a, anyhow::Result<()>> {
|
||||
Box::pin(async {
|
||||
if let Some(max_clock) = config.clocks_configuration.max_core_clock {
|
||||
self.write_freq(FrequencyType::Max, max_clock)
|
||||
.context("Could not set max clock")?;
|
||||
}
|
||||
|
||||
if let Some(min_clock) = config.clocks_configuration.min_core_clock {
|
||||
self.write_freq(FrequencyType::Min, min_clock)
|
||||
.context("Could not set min clock")?;
|
||||
}
|
||||
|
||||
if let Some(cap) = config.power_cap {
|
||||
self.write_hwmon_file("power", "_max", &((cap * 1_000_000.0) as u64).to_string())
|
||||
.context("Could not set power cap")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn get_stats(&self, _gpu_config: Option<&config::Gpu>) -> DeviceStats {
|
||||
let current_gfxclk = self.read_freq(FrequencyType::Cur);
|
||||
let gpu_clockspeed = self
|
||||
.read_freq(FrequencyType::Act)
|
||||
.filter(|value| *value != 0)
|
||||
.or(current_gfxclk);
|
||||
|
||||
let clockspeed = ClockspeedStats {
|
||||
gpu_clockspeed,
|
||||
current_gfxclk,
|
||||
vram_clockspeed: None,
|
||||
};
|
||||
|
||||
let cap_current = self
|
||||
.read_hwmon_file("power", "_max")
|
||||
.map(|value: f64| value / 1_000_000.0)
|
||||
.map(|cap| if cap == 0.0 { 100.0 } else { cap }); // Placeholder max value
|
||||
|
||||
let power = PowerStats {
|
||||
average: None,
|
||||
current: self.get_power_usage(),
|
||||
cap_current,
|
||||
cap_min: Some(0.0),
|
||||
cap_max: self
|
||||
.read_hwmon_file::<f64>("power", "_rated_max")
|
||||
.filter(|max| *max != 0.0)
|
||||
.map(|cap| cap / 1_000_000.0)
|
||||
.or_else(|| cap_current.map(|current| current * 2.0)),
|
||||
cap_default: self.initial_power_cap,
|
||||
};
|
||||
|
||||
let voltage = VoltageStats {
|
||||
gpu: self.read_hwmon_file("in", "_input"),
|
||||
northbridge: None,
|
||||
};
|
||||
|
||||
let fan = FanStats {
|
||||
speed_current: self.read_hwmon_file("fan", "_input"),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
DeviceStats {
|
||||
clockspeed,
|
||||
vram: self.get_vram_stats(),
|
||||
busy_percent: self.get_busy_percent(),
|
||||
power,
|
||||
temps: self.get_temperatures(),
|
||||
voltage,
|
||||
throttle_info: self.get_throttle_info(),
|
||||
fan,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_clocks_info(&self) -> anyhow::Result<ClocksInfo> {
|
||||
let clocks_table = IntelClocksTable {
|
||||
gt_freq: self
|
||||
.read_freq(FrequencyType::Min)
|
||||
.zip(self.read_freq(FrequencyType::Max)),
|
||||
rp0_freq: self.read_freq(FrequencyType::Rp0),
|
||||
rpe_freq: self.read_freq(FrequencyType::Rpe),
|
||||
rpn_freq: self.read_freq(FrequencyType::Rpn),
|
||||
};
|
||||
|
||||
let table = if clocks_table == IntelClocksTable::default() {
|
||||
None
|
||||
} else {
|
||||
Some(ClocksTable::Intel(clocks_table))
|
||||
};
|
||||
|
||||
Ok(ClocksInfo {
|
||||
table,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn get_power_states(&self, _gpu_config: Option<&config::Gpu>) -> PowerStates {
|
||||
let core = [
|
||||
FrequencyType::Rpn,
|
||||
FrequencyType::Rpe,
|
||||
FrequencyType::Rp0,
|
||||
FrequencyType::Boost,
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|freq_type| {
|
||||
let value = self.read_freq(freq_type)?;
|
||||
Some(PowerState {
|
||||
enabled: true,
|
||||
min_value: None,
|
||||
value,
|
||||
index: None,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
PowerStates { core, vram: vec![] }
|
||||
}
|
||||
|
||||
fn reset_pmfw_settings(&self) {}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
fn cleanup_clocks(&self) -> anyhow::Result<()> {
|
||||
if let Some(rp0) = self.read_freq(FrequencyType::Rp0) {
|
||||
if let Err(err) = self.write_freq(FrequencyType::Max, rp0 as i32) {
|
||||
warn!("could not reset max clock: {err:#}");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(rpn) = self.read_freq(FrequencyType::Rpn) {
|
||||
if let Err(err) = self.write_freq(FrequencyType::Min, rpn as i32) {
|
||||
warn!("could not reset min clock: {err:#}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_power_profile_modes(&self) -> anyhow::Result<PowerProfileModesTable> {
|
||||
Err(anyhow!("Not supported"))
|
||||
}
|
||||
|
||||
fn vbios_dump(&self) -> anyhow::Result<Vec<u8>> {
|
||||
Err(anyhow!("Not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
||||
25
lact-daemon/src/server/gpu_controller/intel/drm.rs
Normal file
25
lact-daemon/src/server/gpu_controller/intel/drm.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
pub mod i915;
|
||||
pub mod xe;
|
||||
|
||||
use std::{alloc, ops::Deref};
|
||||
|
||||
pub struct DrmBox<T> {
|
||||
data: *const T,
|
||||
layout: alloc::Layout,
|
||||
}
|
||||
|
||||
impl<T> Deref for DrmBox<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &(*self.data) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for DrmBox<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
alloc::dealloc(self.data as *mut u8, self.layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
60
lact-daemon/src/server/gpu_controller/intel/drm/i915.rs
Normal file
60
lact-daemon/src/server/gpu_controller/intel/drm/i915.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
#![allow(
|
||||
clippy::cast_lossless,
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_sign_loss
|
||||
)]
|
||||
use super::DrmBox;
|
||||
use crate::bindings::intel::drm_i915_query_item;
|
||||
use crate::bindings::intel::{
|
||||
drm_i915_query, drm_i915_query_memory_regions, DRM_COMMAND_BASE, DRM_I915_QUERY_MEMORY_REGIONS,
|
||||
DRM_IOCTL_BASE,
|
||||
};
|
||||
use nix::{errno::Errno, ioctl_readwrite};
|
||||
use std::{alloc, fs::File, mem, os::fd::AsRawFd, ptr};
|
||||
|
||||
const DRM_I915_QUERY: u32 = 0x39;
|
||||
|
||||
ioctl_readwrite!(
|
||||
i915_query,
|
||||
DRM_IOCTL_BASE,
|
||||
DRM_COMMAND_BASE + DRM_I915_QUERY,
|
||||
drm_i915_query
|
||||
);
|
||||
|
||||
unsafe fn query_item<T>(fd: i32, query_id: u32) -> Result<Option<DrmBox<T>>, Errno> {
|
||||
let mut query_item = drm_i915_query_item {
|
||||
query_id: query_id as u64,
|
||||
length: 0,
|
||||
flags: 0,
|
||||
data_ptr: 0,
|
||||
};
|
||||
|
||||
let mut query = drm_i915_query {
|
||||
num_items: 1,
|
||||
flags: 0,
|
||||
items_ptr: ptr::from_ref(&query_item) as u64,
|
||||
};
|
||||
|
||||
i915_query(fd, &mut query)?;
|
||||
|
||||
if query_item.length <= 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let layout =
|
||||
alloc::Layout::from_size_align(query_item.length as usize, mem::align_of::<T>()).unwrap();
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let data = alloc::alloc_zeroed(layout) as *const T;
|
||||
|
||||
query_item.data_ptr = data as u64;
|
||||
|
||||
i915_query(fd, &mut query)?;
|
||||
|
||||
Ok(Some(DrmBox { data, layout }))
|
||||
}
|
||||
|
||||
pub fn query_memory_regions(
|
||||
fd: &File,
|
||||
) -> Result<Option<DrmBox<drm_i915_query_memory_regions>>, Errno> {
|
||||
unsafe { query_item(fd.as_raw_fd(), DRM_I915_QUERY_MEMORY_REGIONS) }
|
||||
}
|
||||
44
lact-daemon/src/server/gpu_controller/intel/drm/xe.rs
Normal file
44
lact-daemon/src/server/gpu_controller/intel/drm/xe.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
use crate::bindings::intel::{
|
||||
drm_xe_device_query, drm_xe_query_mem_regions, DRM_COMMAND_BASE, DRM_IOCTL_BASE,
|
||||
DRM_XE_DEVICE_QUERY, DRM_XE_DEVICE_QUERY_MEM_REGIONS,
|
||||
};
|
||||
use nix::{errno::Errno, ioctl_readwrite};
|
||||
use std::{alloc, fs::File, mem, os::fd::AsRawFd};
|
||||
|
||||
use super::DrmBox;
|
||||
|
||||
ioctl_readwrite!(
|
||||
xe_device_query,
|
||||
DRM_IOCTL_BASE,
|
||||
DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY,
|
||||
drm_xe_device_query
|
||||
);
|
||||
|
||||
unsafe fn query_item<T>(fd: i32, query_id: u32) -> Result<Option<DrmBox<T>>, Errno> {
|
||||
let mut query = drm_xe_device_query {
|
||||
query: query_id,
|
||||
size: 0,
|
||||
data: 0,
|
||||
extensions: 0,
|
||||
reserved: [0, 0],
|
||||
};
|
||||
xe_device_query(fd, &mut query)?;
|
||||
|
||||
if query.size == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let layout = alloc::Layout::from_size_align(query.size as usize, mem::align_of::<T>()).unwrap();
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let data = alloc::alloc_zeroed(layout) as *const T;
|
||||
|
||||
query.data = data as u64;
|
||||
|
||||
xe_device_query(fd, &mut query)?;
|
||||
|
||||
Ok(Some(DrmBox { data, layout }))
|
||||
}
|
||||
|
||||
pub fn query_mem_regions(fd: &File) -> Result<Option<DrmBox<drm_xe_query_mem_regions>>, Errno> {
|
||||
unsafe { query_item(fd.as_raw_fd(), DRM_XE_DEVICE_QUERY_MEM_REGIONS) }
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
8.0 GT/s PCIe
|
||||
@@ -0,0 +1 @@
|
||||
16
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
200000000
|
||||
@@ -0,0 +1 @@
|
||||
sclk
|
||||
@@ -0,0 +1 @@
|
||||
15
|
||||
@@ -0,0 +1 @@
|
||||
vddgfx
|
||||
@@ -0,0 +1 @@
|
||||
669
|
||||
@@ -0,0 +1 @@
|
||||
vddnb
|
||||
@@ -0,0 +1 @@
|
||||
amdgpu
|
||||
@@ -0,0 +1 @@
|
||||
3218000
|
||||
@@ -0,0 +1 @@
|
||||
15000000
|
||||
@@ -0,0 +1 @@
|
||||
15000000
|
||||
@@ -0,0 +1 @@
|
||||
29000000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
4057000
|
||||
@@ -0,0 +1 @@
|
||||
slowPPT
|
||||
@@ -0,0 +1 @@
|
||||
3040000
|
||||
@@ -0,0 +1 @@
|
||||
15000000
|
||||
@@ -0,0 +1 @@
|
||||
15000000
|
||||
@@ -0,0 +1 @@
|
||||
30000000
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
fastPPT
|
||||
@@ -0,0 +1 @@
|
||||
56000
|
||||
@@ -0,0 +1 @@
|
||||
edge
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,4 @@
|
||||
0: 400Mhz
|
||||
1: 600Mhz
|
||||
2: 687Mhz *
|
||||
3: 687Mhz *
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
0: 200Mhz *
|
||||
1: 1100Mhz
|
||||
2: 1600Mhz
|
||||
@@ -0,0 +1,4 @@
|
||||
0: 400Mhz *
|
||||
1: 600Mhz
|
||||
2: 800Mhz
|
||||
3: 1000Mhz
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
states: 1
|
||||
0 default
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
1 3D_FULL_SCREEN
|
||||
3 VIDEO
|
||||
4 VR
|
||||
5 COMPUTE
|
||||
6 CUSTOM
|
||||
8 CAPPED
|
||||
9 UNCAPPED
|
||||
@@ -0,0 +1,6 @@
|
||||
DRIVER=amdgpu
|
||||
PCI_CLASS=30000
|
||||
PCI_ID=1002:163F
|
||||
PCI_SUBSYS_ID=1002:0123
|
||||
PCI_SLOT_NAME=0000:04:00.0
|
||||
MODALIAS=pci:v00001002d0000163Fsv00001002sd00000123bc03sc00i00
|
||||
@@ -0,0 +1 @@
|
||||
113-AMDAerithJ-005
|
||||
@@ -0,0 +1 @@
|
||||
0x1002
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
source: lact-daemon/src/tests/mod.rs
|
||||
expression: device_info
|
||||
---
|
||||
{
|
||||
"clocks_info": null,
|
||||
"info": {
|
||||
"driver": "amdgpu",
|
||||
"link_info": {
|
||||
"current_speed": "8.0 GT/s PCIe",
|
||||
"current_width": "16"
|
||||
},
|
||||
"pci_info": {
|
||||
"device_pci_info": {
|
||||
"model": "VanGogh [AMD Custom GPU 0405]",
|
||||
"model_id": "163F",
|
||||
"vendor": "Advanced Micro Devices, Inc. [AMD/ATI]",
|
||||
"vendor_id": "1002"
|
||||
},
|
||||
"subsystem_pci_info": {
|
||||
"model_id": "0123",
|
||||
"vendor": "Advanced Micro Devices, Inc. [AMD/ATI]",
|
||||
"vendor_id": "1002"
|
||||
}
|
||||
},
|
||||
"vbios_version": "113-AMDAerithJ-005",
|
||||
"vulkan_info": {
|
||||
"api_version": "",
|
||||
"device_name": "",
|
||||
"driver": {
|
||||
"version": 0
|
||||
},
|
||||
"enabled_layers": [],
|
||||
"extensions": {},
|
||||
"features": {}
|
||||
}
|
||||
},
|
||||
"pci_info": {
|
||||
"device_pci_info": {
|
||||
"model": "VanGogh [AMD Custom GPU 0405]",
|
||||
"model_id": "163F",
|
||||
"vendor": "Advanced Micro Devices, Inc. [AMD/ATI]",
|
||||
"vendor_id": "1002"
|
||||
},
|
||||
"subsystem_pci_info": {
|
||||
"model_id": "0123",
|
||||
"vendor": "Advanced Micro Devices, Inc. [AMD/ATI]",
|
||||
"vendor_id": "1002"
|
||||
}
|
||||
},
|
||||
"power_profile_modes": null,
|
||||
"power_states": {
|
||||
"core": [
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 0,
|
||||
"value": 200
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 1,
|
||||
"value": 1100
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 2,
|
||||
"value": 1600
|
||||
}
|
||||
],
|
||||
"vram": [
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 0,
|
||||
"value": 400
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 1,
|
||||
"value": 600
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 2,
|
||||
"value": 687
|
||||
},
|
||||
{
|
||||
"enabled": true,
|
||||
"index": 3,
|
||||
"value": 687
|
||||
}
|
||||
]
|
||||
},
|
||||
"stats": {
|
||||
"busy_percent": 0,
|
||||
"clockspeed": {
|
||||
"gpu_clockspeed": 200
|
||||
},
|
||||
"core_power_state": 0,
|
||||
"fan": {
|
||||
"control_enabled": false,
|
||||
"pmfw_info": {}
|
||||
},
|
||||
"power": {
|
||||
"average": 3.218,
|
||||
"cap_current": 15.0,
|
||||
"cap_default": 15.0,
|
||||
"cap_max": 29.0,
|
||||
"cap_min": 0.0,
|
||||
"current": 4.057
|
||||
},
|
||||
"temps": {
|
||||
"edge": {
|
||||
"crit": null,
|
||||
"crit_hyst": null,
|
||||
"current": 56.0
|
||||
}
|
||||
},
|
||||
"voltage": {
|
||||
"gpu": 15,
|
||||
"northbridge": 669
|
||||
},
|
||||
"vram": {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user