枚举 GPU 引擎功能

从 Windows 8.1 开始,显示微型端口驱动程序必须实现 DxgkDdiGetNodeMetadata 函数,该函数用于查询 GPU 节点的引擎功能。

此信息有助于评估工作负载在节点之间的计划和分布方式,并提高调试应用程序的能力。

引擎功能 设备驱动程序接口 (DDI)

此接口提供指定 GPU 节点的引擎功能:

指向 DxgkDdiGetNodeMetadata 函数的指针由 DRIVER_INITIALIZATION_DATA 结构的 DxgkDdiGetNodeMetadata 成员提供。

GPU 节点体系结构

系统上的每个显示适配器都有许多不同的引擎可用于计划任务。 每个引擎只分配给一个节点,但如果该节点与多个适配器相关联,则每个节点可能包含多个引擎,例如在链接的显示适配器 (LDA) 配置中,其中多个物理 GPU 链接到形成单个、更快的虚拟 GPU。

显示 GPU 引擎和节点体系结构的示意图。

不同的节点表示 GPU 的非对称处理核心,而每个节点中的引擎表示跨适配器的对称处理核心。 也就是说,三维节点在多个适配器上只包含相同的三维引擎,并且永远不会包含不同的引擎类型。

由于引擎始终按引擎类型分组到节点中,因此可以根据指定的节点查询引擎类型信息。 DXGK_ENGINE_TYPE 枚举中 列出了显示微型端口驱动程序可以指定的引擎类型。

节点元数据函数的示例实现

此代码演示显示微型端口驱动程序如何实现 可由 DxgkDdiGetNodeMetadata 函数返回的某些引擎类型。

NTSTATUS
IHVGetNodeDescription(
        IN_CONST_HANDLE                     hAdapter,
        UINT                                NodeOrdinal,
        OUT_PDXGKARG_GETNODEMETADATA        pGetNodeMetadata
        )
{
    DDI_FUNCTION();
    PAGED_CODE();

    if(NULL == pGetNodeMetadata)
    {
        return STATUS_INVALID_PARAMETER;
    }

    CAdapter *pAdapter = GetAdapterFromHandle(hAdapter);

    //Invalid handle
    if(NULL == pAdapter)
    {
        return STATUS_INVALID_PARAMETER;
    }

    //Node ordinal is out of bounds. Required to return
    //STATUS_INVALID_PARAMETER
    if(NodeOrdinal >= pAdapter->GetNumNodes())
    {
        return STATUS_INVALID_PARAMETER;
    }

    switch(pAdapter->GetEngineType(NodeOrdinal))
    {
        //This is the adapter's 3-D engine. This engine handles a large number
        //of different workloads, but it also handles the adapter's 3-D 
        //workloads. Therefore the 3-D capability is what must be exposed.
        case GPU_ENGINE_3D:
        {
            pGetNodeMetadata->EngineType = DXGK_ENGINE_TYPE_3D;
            break;
        }

        //This is the adapter's video decoding engine
        case GPU_ENGINE_VIDEO_DECODE:
        {
            pGetNodeMetadata->EngineType = DXGK_ENGINE_TYPE_VIDEO_DECODE;
            break;
        }

        //This engine is proprietary and contains no functionality that
        //fits the DXGK_ENGINE_TYPE enumeration
        case GPU_ENGINE_PROPRIETARY_ENGINE_1:
        {
            pGetNodeMetadata->EngineType = DXGK_ENGINE_TYPE_OTHER;

            //Copy over friendly name associated with this engine
            SetFriendlyNameForEngine(pGetNodeMetadata->FriendlyName,
                                     DXGK_MAX_METADATA_NAME_LENGTH,
                                     PROPRIETARY_ENGINE_1_NAME);
            break;
        }
    }

    return STATUS_SUCCESS;
}