@@ -134,45 +134,69 @@ bool gpuinfo_fix_dynamic_info_from_process_info(struct list_head *devices) {
134134 unsigned reportedGpuRate = dynamic_info -> gpu_util_rate ;
135135 RESET_GPUINFO_DYNAMIC (dynamic_info , gpu_util_rate );
136136
137- // AMDGPU does not provide encode and decode utilization through the DRM sensor info.
138- // Update them here since per-process sysfs exposes this information.
139- bool needGpuEncode = !GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , encoder_rate );
140- bool needGpuDecode = !GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , decoder_rate );
137+ // For encode/decode, save vendor-reported values and reset, then re-aggregate
138+ // from per-process info (same pattern as gpu_util_rate). This ensures GPUs that
139+ // set a baseline (e.g., AMDGPU sets 0) show 0% when idle, while GPUs that never
140+ // set encoder_rate/decoder_rate still show null.
141+ bool validReportedEncoderRate = GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , encoder_rate );
142+ unsigned reportedEncoderRate = dynamic_info -> encoder_rate ;
143+ if (validReportedEncoderRate )
144+ RESET_GPUINFO_DYNAMIC (dynamic_info , encoder_rate );
145+
146+ bool validReportedDecoderRate = GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , decoder_rate );
147+ unsigned reportedDecoderRate = dynamic_info -> decoder_rate ;
148+ if (validReportedDecoderRate )
149+ RESET_GPUINFO_DYNAMIC (dynamic_info , decoder_rate );
150+
141151 bool needGPUMemory = !GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , used_memory ) &&
142152 GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , total_memory );
143- if (needGpuRate || needGpuEncode || needGpuDecode || needGPUMemory ) {
144- for (unsigned processIdx = 0 ; processIdx < device -> processes_count ; ++ processIdx ) {
145- struct gpu_process * process_info = & device -> processes [processIdx ];
146- if (needGpuRate && GPUINFO_PROCESS_FIELD_VALID (process_info , gpu_usage )) {
147- if (GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , gpu_util_rate )) {
148- dynamic_info -> gpu_util_rate = MYMIN (100 , dynamic_info -> gpu_util_rate + process_info -> gpu_usage );
149- } else {
150- SET_GPUINFO_DYNAMIC (dynamic_info , gpu_util_rate , MYMIN (100 , process_info -> gpu_usage ));
151- }
153+ for (unsigned processIdx = 0 ; processIdx < device -> processes_count ; ++ processIdx ) {
154+ struct gpu_process * process_info = & device -> processes [processIdx ];
155+ if (needGpuRate && GPUINFO_PROCESS_FIELD_VALID (process_info , gpu_usage )) {
156+ if (GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , gpu_util_rate )) {
157+ dynamic_info -> gpu_util_rate = MYMIN (100 , dynamic_info -> gpu_util_rate + process_info -> gpu_usage );
158+ } else {
159+ SET_GPUINFO_DYNAMIC (dynamic_info , gpu_util_rate , MYMIN (100 , process_info -> gpu_usage ));
152160 }
153- if ( needGpuEncode && GPUINFO_PROCESS_FIELD_VALID ( process_info , encode_usage )) {
154- if (GPUINFO_DYNAMIC_FIELD_VALID ( dynamic_info , encoder_rate )) {
155- dynamic_info -> encoder_rate = MYMIN ( 100 , dynamic_info -> encoder_rate + process_info -> encode_usage );
156- } else {
157- SET_GPUINFO_DYNAMIC ( dynamic_info , encoder_rate , MYMIN ( 100 , process_info -> encode_usage ));
158- }
161+ }
162+ if (GPUINFO_PROCESS_FIELD_VALID ( process_info , encode_usage )) {
163+ if ( GPUINFO_DYNAMIC_FIELD_VALID ( dynamic_info , encoder_rate )) {
164+ dynamic_info -> encoder_rate = MYMIN ( 100 , dynamic_info -> encoder_rate + process_info -> encode_usage );
165+ } else {
166+ SET_GPUINFO_DYNAMIC ( dynamic_info , encoder_rate , MYMIN ( 100 , process_info -> encode_usage ));
159167 }
160- if ( needGpuDecode && GPUINFO_PROCESS_FIELD_VALID ( process_info , decode_usage )) {
161- if (GPUINFO_DYNAMIC_FIELD_VALID ( dynamic_info , decoder_rate )) {
162- dynamic_info -> decoder_rate = MYMIN ( 100 , dynamic_info -> decoder_rate + process_info -> decode_usage );
163- } else {
164- SET_GPUINFO_DYNAMIC ( dynamic_info , decoder_rate , MYMIN ( 100 , process_info -> decode_usage ));
165- }
168+ }
169+ if (GPUINFO_PROCESS_FIELD_VALID ( process_info , decode_usage )) {
170+ if ( GPUINFO_DYNAMIC_FIELD_VALID ( dynamic_info , decoder_rate )) {
171+ dynamic_info -> decoder_rate = MYMIN ( 100 , dynamic_info -> decoder_rate + process_info -> decode_usage );
172+ } else {
173+ SET_GPUINFO_DYNAMIC ( dynamic_info , decoder_rate , MYMIN ( 100 , process_info -> decode_usage ));
166174 }
167- if ( needGPUMemory && GPUINFO_PROCESS_FIELD_VALID ( process_info , gpu_memory_usage )) {
168- if ( GPUINFO_DYNAMIC_FIELD_VALID ( dynamic_info , used_memory )) {
169- dynamic_info -> used_memory += dynamic_info -> used_memory + process_info -> gpu_memory_usage ;
170- } else {
171- SET_GPUINFO_DYNAMIC ( dynamic_info , used_memory , process_info -> gpu_memory_usage );
172- }
175+ }
176+ if ( needGPUMemory && GPUINFO_PROCESS_FIELD_VALID ( process_info , gpu_memory_usage )) {
177+ if ( GPUINFO_DYNAMIC_FIELD_VALID ( dynamic_info , used_memory )) {
178+ dynamic_info -> used_memory += dynamic_info -> used_memory + process_info -> gpu_memory_usage ;
179+ } else {
180+ SET_GPUINFO_DYNAMIC ( dynamic_info , used_memory , process_info -> gpu_memory_usage );
173181 }
174182 }
175183 }
184+ // Restore vendor-reported encoder/decoder rate if process aggregation didn't produce a value,
185+ // or use the max of vendor-reported and process-aggregated
186+ if (validReportedEncoderRate ) {
187+ if (!GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , encoder_rate )) {
188+ SET_GPUINFO_DYNAMIC (dynamic_info , encoder_rate , reportedEncoderRate );
189+ } else if (dynamic_info -> encoder_rate < reportedEncoderRate ) {
190+ dynamic_info -> encoder_rate = reportedEncoderRate ;
191+ }
192+ }
193+ if (validReportedDecoderRate ) {
194+ if (!GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , decoder_rate )) {
195+ SET_GPUINFO_DYNAMIC (dynamic_info , decoder_rate , reportedDecoderRate );
196+ } else if (dynamic_info -> decoder_rate < reportedDecoderRate ) {
197+ dynamic_info -> decoder_rate = reportedDecoderRate ;
198+ }
199+ }
176200 // Sanitize what we got from processes: we can't have more than the total!
177201 if (needGPUMemory && GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , used_memory ) &&
178202 GPUINFO_DYNAMIC_FIELD_VALID (dynamic_info , total_memory ) &&
@@ -394,13 +418,14 @@ void gpuinfo_refresh_utilisation_rate(struct gpu_info *gpu_info) {
394418 return ;
395419
396420 if (IS_VALID (gpuinfo_engine_count_valid , gpu_info -> static_info .valid ))
397- ec = gpu_info -> static_info .engine_count ;
421+ ec = gpu_info -> static_info .engine_count ;
398422 else
399- ec = 1 ;
423+ ec = 1 ;
400424
401425 avg_delta_secs = ((double )total_delta / gpu_info -> processes_count ) / 1000000000.0 ;
402426 max_freq_hz = gpu_info -> dynamic_info .gpu_clock_speed_max * 1000000 ;
403- utilisation_rate = (unsigned int )((((double )gfx_total_process_cycles ) / (((double )max_freq_hz ) * avg_delta_secs * ec )) * 100 );
427+ utilisation_rate =
428+ (unsigned int )((((double )gfx_total_process_cycles ) / (((double )max_freq_hz ) * avg_delta_secs * ec )) * 100 );
404429 utilisation_rate = utilisation_rate > 100 ? 100 : utilisation_rate ;
405430
406431 SET_GPUINFO_DYNAMIC (& gpu_info -> dynamic_info , gpu_util_rate , utilisation_rate );
0 commit comments