D3DKMTQueryStatistics failure with D3DKMT_QUERYSTATISTICS_NODE


In our CCTV we have a module for hardware/software video decompression. It uses D3DKMTQueryStatistics for querying video decoder utilization on a particular graphics adapter with purpose for load balancing over several graphics adapters available on the system or CPU offloading when hardware is fully utilized.
Currently decode done via FFmpeg 4.2 + Direct3D 11 Video.

We use D3DKMTQueryStatistics as it is only known way for reading hardware video decoder engine running time. This always has no problem on Intel HD graphics. But on some systems we have found that calls for D3DKMTQueryStatistics fails with error STATUS_INVALID_PARAMETER when it is applied on NVIDIA adapter. On such systems utilities like Process Monitor or Process Hacker also fails to read utilization for GeForce.

Brief Details:

  1. Use IDXGIFactory1::EnumAdapters1 to get adapters in the system.
  2. Use IDXGIAdapter1::GetDesc1 to get adapter LUID
  3. Use D3DKMTQueryStatistics with D3DKMT_QUERYSTATISTICS_ADAPTER and LUID to get adapter’s NodeCount.
  4. Use D3DKMTOpenAdapterFromLuid to get adapter handle.
  5. Iterate over (nodeId: 0…NodeCount) and use D3DKMTQueryAdapterInfo(adapterHandle, node ) to find node with .EngineType == DXGK_ENGINE_TYPE_VIDEO_DECODE.
  6. Then call to D3DKMTQueryStatistics with D3DKMT_QUERYSTATISTICS_NODE and found decoder node id fails with NV card and success on Intel HD (both cards enabled).

The same card moved to another system with the same OS (for ex Windows 10 Pro) and identical NVIDIA drivers works as expected.
What kind of issue it can be, is it issue of our usage or drivers/configuration on particular systems or other?

Code samples
ULONG GetVideoDecoderNodeId(LUID adapterLuid)

	D3DKMT_OPENADAPTERFROMLUID openAdapterFromLuid{ adapterLuid };
	ResourceReleaser adapterReleaser([closeArg = D3DKMT_CLOSEADAPTER{ openAdapterFromLuid.hAdapter }]() { ::D3DKMTCloseAdapter(&closeArg); });

	D3DKMT_NODEMETADATA nodeMetadata{};
	D3DKMT_QUERYADAPTERINFO queryAdapterInfo{ openAdapterFromLuid.hAdapter, KMTQAITYPE_NODEMETADATA, &nodeMetadata, sizeof(nodeMetadata) };

	for (ULONG nodeId = 0; nodeId != adapterStatistics.QueryResult.AdapterInformation.NodeCount; ++nodeId)
		nodeMetadata.NodeOrdinalAndAdapterIndex = MAKELONG(nodeId, 0);
		if (nodeMetadata.NodeData.EngineType == DXGK_ENGINE_TYPE_VIDEO_DECODE)
			return nodeId;

	throw std::runtime_error("Adapter node with EngineType DXGK_ENGINE_TYPE_VIDEO_DECODE not found");

int64_t GetDecoderUsedTime(LUID adapterLuid)
	queryStats.AdapterLuid = adapterLuid;
	queryStats.QueryNode.NodeId = GetVideoDecoderNodeId(adapterLuid);
	return queryStats.QueryResult.NodeInformation.GlobalInformation.RunningTime.QuadPart;