Reads the same PDH counters as Task Manager (\GPU Engine(*)\Utilization Percentage, locale-independent via PdhAddEnglishCounterW), which cover graphics work under WDDM — games are caught without an exe list and the offender is named. Windows-only; a missing or failing counter disables the path with one log line. dwm (the desktop compositor) joins the default ignore list.
37 lines
1.0 KiB
Go
37 lines
1.0 KiB
Go
package game
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// errNotPrimed marks the first PDH sample after opening a query: rate-based
|
|
// counters (like engine utilization) need two collections before they
|
|
// return meaningful values.
|
|
var errNotPrimed = errors.New("GPU engine counter needs a second sample")
|
|
|
|
// parseGPUEngineInstance splits a PDH "GPU Engine" instance name —
|
|
// "pid_1234_luid_0x00000000_0x00011A2B_phys_0_eng_0_engtype_3D" — into PID
|
|
// and engine type ("3D", "Copy", "VideoDecode", ...). engType is empty when
|
|
// the name carries no engtype marker.
|
|
func parseGPUEngineInstance(name string) (pid int, engType string, ok bool) {
|
|
rest, found := strings.CutPrefix(name, "pid_")
|
|
if !found {
|
|
return 0, "", false
|
|
}
|
|
digits, rest, found := strings.Cut(rest, "_")
|
|
if !found {
|
|
return 0, "", false
|
|
}
|
|
pid, err := strconv.Atoi(digits)
|
|
if err != nil || pid < 0 {
|
|
return 0, "", false
|
|
}
|
|
const marker = "engtype_"
|
|
if i := strings.LastIndex(rest, marker); i >= 0 {
|
|
engType = rest[i+len(marker):]
|
|
}
|
|
return pid, engType, true
|
|
}
|