PresentMon
PresentMon copied to clipboard
Enable Adapter Utilization API provided by Microsoft
Auto-migrated from intel-sandbox/applications.graphics.presentmonservice/issues/325
Original creation by markgalvan-intel on 2023-10-03 14:17:07+00:00
Link to HSDES: https://hsdes.intel.com/appstore/article/#/22014192522 Link to DxCore Adapter Utilization spec: https://github.com/intel-innersource/drivers.gpu.mirrors.cga-exchange.docs/blob/master/dxcore/Adapter%20Utilization%20IHV%20Spec.md
API provides adapter agnostic API to numerous Graphics HW telemetries. They include:
- Physical Adapter Count
- Adapter Engine Count
- Adapter Engine Name
- Adapter Engine Running Time
- Adapter Memory Usage
- Adapter Temperature
and more
[!NOTE] Comment by markgalvan-intel at 2024-02-09 17:19:40+00:00
Started inspection of DXCore API. Created a comparison of what we currently have vs. what the new DXCore API provides. Started rough draft of design. Will add to this issue as design becomes more concrete.
Added comparison chart to issue. Added initial class design for DxCoreTelemetry.
Original Estimated Time: 5 days Time Spent: 1.0 days
Day 1:
- Review of new DxCore API telemetry additions
- Initial DxCore class design
Day 2:
- Adding DXCoreTelemetry skeleton code into current PresentMonService code.
- Research of general DxCore programming guide to understand how it fits into PresentMonService code
[!NOTE] Comment by markgalvan-intel at 2024-02-09 18:45:49+00:00
| DXCore API | Description | Current PM2 Support | Notes |
|---|---|---|---|
| PhysicalAdapterCount | Returns the number of physical adapters in this logical adapter. Can be greater in Linked display adapter (LDA) configurations. | Yes | Currently we iterate through provider APIs and determine which API returns something valid. We track the number of adapters found and the name of each one. This is then made available to the client via the named pipe interface. |
| AdapterEngineCount | This query takes physical adapter index as input, and outputs the count of engines on the physical adapter. | No | |
| AdapterEngineName | This query takes physical adapter index and engine ID as input, and outputs engine type. | Not Sure | Is this the adapter name? |
| AdapterEngineRunningTimeMicroseconds | This query takes engine ID and physical adapter index as input, and outputs engine running time as output. API callers can calculate the usage of any engine by dividing the difference in running times of two calls by the actual time elapsed between the two calls. | Not Sure | Is this GPU Utilization? |
| AdapterMemoryUsageBytes | This query takes physical adapter index and Dedicated vs. Shared as input, and outputs the Committed and Resident Memory Dedicated or Shared portions of GPU Memory respectively. | Yes | We don't have dedicated vs. shared |
| AdapterTemperatureCelsius | This query takes physical adapter index as input, and outputs current GPU temperature as a float in degrees Celsius. | Yes | |
| AdapterEngineRunningTimeByProcessMicroseconds | This query takes engine ID, physical adapter index, and Process Handle as input, and outputs engine running time as output. | No | If this is GPU Utilization would neat to show utilization per process |
| AdapterMemoryUsageByProcessBytes | This query takes engine ID, physical adapter index, and Process Handle as input, and outputs Committed and Resident Memory on Dedicated or Shared portions of GPU memory, respectively. | No | Again neat to show memory usage per process |
| AdapterInUseProcessCount | This query return the number of processes using an adapter. It returns a value of uint32_t through outputBuffer. | No | How would we display this information? Is it something we continually output? |
| AdapterInUseProcessSet | This query takes a pre-allocated array from the app and returns a set of PIDs currently using the current adapter, in addition to array size. | No | How would we display this information? Is it something we continually output? |
| AdapterEngineFrequencyHertz | This query will return the clock frequency of a given engine on a physical adapter in hertz. | Yes | In addition to current frequency displays max frequency and maximum overclocked frequency |
| AdapterMemoryFrequencyHertz | This query will return the clock frequency of an adapter's memory in hertz. | Yes |
[!NOTE] Comment by markgalvan-intel at 2024-02-09 22:51:13+00:00
DxCoreTelemetryInfo Structure
struct DxCoreTelemetryInfo
{
uint32_t memoryUsageCommittedBytes;
uint32_t memoryUsageResidentBytes;
double gpuTemperatureCelsius;
double gpuUtilization;
double gpuUtilizationByProcess;
double gpuMemoryUsageByProcessBytes;
uint64_t gpuFrequencyHertz;
uint64_t gpuMaxFrequencyHertz;
uint64_t gpuMaxOverclockedFrequencyHertz;
uint64_t gpuMemoryFrequencyHertz;
};
DxCoreTelemetry Class
Description
The DxCoreTelemetry class is used to sample GPU performance data through DXCore and it's QueryState and GetProperty APIs.
Methods
Sample() -> bool
Samples all GPU performance data available through DXCore and stores in a circular buffer for later retrieval
Return Value: bool if the Sample was successful or not
GetClosest(qpc: uint64_t) -> std::optional<DxCoreTelemetryInfo>
Use the passed qpc find and return the closest GPU performance data with the closest QPC
Parameters:
qpc: QPC to look for in GPU performance data circular buffer
Return Value: If found, the GPU performance data gathered during data sampling
GetPhysicalAdapterCount() -> uint32_t
Return the number of physical adapters on system
Return Value: Physical adapter count
GetAdapterEngineCount(physicalAdapterIndex: uint32_t ) -> uint32_t
Return the number of engines on the physical adapter
Parameters:
physicalAdapterIndex: physical adapter index
Return Value: Adapter engine count
GetAdapterEngineName(physicalAdapterIndex: uint32_t, adapterEngineIndex: uint32_t) -> std::string
Returns adapter engine name based on the physical adapter index and engine index.
Parameters:
physicalAdapterIndex: physical adapter index- 'engineId': engine ID
Return Value: Engine name associated with the passed in physical adapter index and engine id
StartTrackingProcess(process: HANDLE) -> void
Start tracking GPU performance data on passed in process
Parameters:
process: handle of process to track. ( We get handle using OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, …) is this okay?)
Return Value: None
StopTrackingProcess(process: HANDLE) -> void
Stop tracking GPU performance data on passed in process
Parameters:
process: handle of process to track. ( We get handle using OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, …) is this okay?)
Return Value: None
Members
history: std::map<HANDLE,TelemetryHistory<DxCoreTelemetryInfo>- Map of handles used to track the GPU Performance data.