使用 DXCore 枚举适配器

DXCore 是适用于 DirectX 设备的适配器枚举 API,因此其某些功能与 DXGI 的功能重叠。

DXCore 允许将新设备类型公开到用户模式,例如 MCDM (Microsoft 计算驱动程序模型) ,以便与 Direct3D 12DirectMLWindows 机器学习一起使用。 DXCore 与 DXGI 不同,不提供与显示相关的技术或属性的任何信息

在接下来的几个部分中,我们将介绍 DXCore 的main功能,以及 (用 C++/WinRT) 编写的一些代码示例。 下面所示的代码示例摘自可在 最小 DXCore 应用程序主题中找到的完整源代码列表。

创建适配器工厂

通过创建适配器工厂对象开始 DXCore 适配器枚举,该对象由 IDXCoreAdapterFactory 接口表示。 若要创建工厂,请 dxcore.h 包含 头文件,并调用 DXCoreCreateAdapterFactory free 函数。

#include <dxcore.h>
...
winrt::com_ptr<IDXCoreAdapterFactory> adapterFactory;
winrt::check_hresult(::DXCoreCreateAdapterFactory(adapterFactory.put()));

检索适配器列表

与 DXGI 不同,新创建的 DXCore 适配器工厂不会自动创建系统的适配器状态快照。 相反,当显式检索由 IDXCoreAdapterList 接口表示的适配器列表对象时,DXCore 会创建快照。

winrt::com_ptr<IDXCoreAdapterList> d3D12CoreComputeAdapters;
GUID attributes[]{ DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE };
winrt::check_hresult(
    adapterFactory->CreateAdapterList(_countof(attributes),
        attributes,
        d3D12CoreComputeAdapters.put()));

从列表中选择适当的适配器

本部分演示如何在给定适配器列表对象的情况下在列表中找到第一个硬件适配器。

IDXCoreAdapterList::GetAdapterCount 方法告知列表中的元素数,IDXCoreAdapterList::GetAdapter 按索引检索特定适配器。

然后,可以按照以下步骤查询该适配器的属性。

winrt::com_ptr<IDXCoreAdapter> preferredAdapter;

const uint32_t count{ d3D12CoreComputeAdapters->GetAdapterCount() };

for (uint32_t i = 0; i < count; ++i)
{
    winrt::com_ptr<IDXCoreAdapter> candidateAdapter;
    winrt::check_hresult(
        d3D12CoreComputeAdapters->GetAdapter(i, candidateAdapter.put()));

    bool isHardware{ false };
    winrt::check_hresult(candidateAdapter->GetProperty(
        DXCoreAdapterProperty::IsHardware,
        &isHardware));

    if (isHardware)
    {
        // Choose the first hardware adapter, and stop looping.
        preferredAdapter = candidateAdapter;
        break;
    }

    // Otherwise, ensure that (as long as there are *any* adapters) we'll
    // at least choose one.
    if (!preferredAdapter)
    {
        preferredAdapter = candidateAdapter;
    }
}

通过对适配器列表进行排序来选择首选适配器

可以通过调用 IDXCoreAdapterList::Sort 方法对 DXCore 适配器列表进行排序

DXCoreAdapterPreference 枚举定义表示排序条件的值。 将这些值的数组传递给 Sort,然后读取生成的排序列表中的第一个适配器。

若要确定排序类型是否将由 Sort 理解,请先调用 IDXCoreAdapterList::IsAdapterPreferenceSupported

winrt::com_ptr<IDXCoreAdapter> TryFindHardwareHighPerformanceGraphicsAdapter()
{
    // You begin DXCore adapter enumeration by creating an adapter factory.
    winrt::com_ptr<IDXCoreAdapterFactory> adapterFactory;
    winrt::check_hresult(::DXCoreCreateAdapterFactory(adapterFactory.put()));

    // From the factory, retrieve a list of all the Direct3D 12 Graphics adapters.
    winrt::com_ptr<IDXCoreAdapterList> d3D12GraphicsAdapters;
    GUID attributes[]{ DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS };
    winrt::check_hresult(
        adapterFactory->CreateAdapterList(_countof(attributes),
            attributes,
            d3D12GraphicsAdapters.put()));

    DXCoreAdapterPreference sortPreferences[]{
        DXCoreAdapterPreference::Hardware, DXCoreAdapterPreference::HighPerformance };

    // Ask the OS to sort for the highest performance hardware adapter.
    winrt::check_hresult(d3D12GraphicsAdapters->Sort(_countof(sortPreferences), sortPreferences));

    winrt::com_ptr<IDXCoreAdapter> preferredAdapter;

    if (d3D12GraphicsAdapters->GetAdapterCount() > 0)
    {
        winrt::check_hresult(d3D12GraphicsAdapters->GetAdapter(0, preferredAdapter.put()));
    }

    return preferredAdapter;
}

查询和设置适配器状态 (属性)

可以通过调用 IDXCoreAdapter::QueryState 和 IDXCoreAdapter::SetState 方法检索和设置适配器的指定状态项的状态。

void SetDesiredMemoryReservation(winrt::com_ptr<IDXCoreAdapter> const& adapter, uint64_t reservation)
{
    DXCoreAdapterMemoryBudgetNodeSegmentGroup nodeSegmentGroup{};
    nodeSegmentGroup.nodeIndex = 0;
    nodeSegmentGroup.segmentGroup = DXCoreSegmentGroup::Local;

    DXCoreAdapterMemoryBudget memoryBudget{};
    winrt::check_hresult(adapter->QueryState(
        DXCoreAdapterState::AdapterMemoryBudget,
        &nodeSegmentGroup,
        &memoryBudget));

    // Clamp the reservation to what's available.
    reservation = std::min<uint64_t>(reservation, memoryBudget.availableForReservation);

    winrt::check_hresult(adapter->SetState(
        DXCoreAdapterState::AdapterMemoryBudget,
        &nodeSegmentGroup,
        &reservation));
}

在实践中,在调用 QueryStateSetState 之前,应调用 IsQueryStateSupported 以确认查询状态类型是否可用于此适配器和操作系统 (操作系统) 。

适配器列表新鲜度

如果适配器列表由于系统条件的变化而过时,则会将其标记为“ 。 可以通过轮询适配器列表的 IDXCoreAdapterList::IsStale 方法来确定适配器列表的新鲜度。

不过,对于过期等情况,可以更方便地订阅通知。 为此,请将 DXCoreNotificationType::AdapterListStale 传递给 IDXCoreAdapterFactory::RegisterEventNotification,并安全地存储返回的 Cookie 供以后使用。

uint32_t m_eventCookie = 0;
...
winrt::check_hresult(factory->RegisterEventNotification(
    m_adapters.get(),
    DXCoreNotificationType::AdapterListStale,
    OnAdapterListStale,
    this,
    &m_eventCookie));
...
static void WINAPI OnAdapterListStale(
    DXCoreNotificationType notificationType,
    IUnknown* staleObject,
    void* context)
{
    ...
}

然后,可以从已有的工厂对象生成新的当前适配器列表对象。 处理这些条件对于无缝响应事件(例如适配器到达和删除 (无论是 GPU 还是专用计算适配器) )以及适当转移工作负载以做出响应的能力至关重要。

在销毁适配器列表对象之前,必须使用 cookie 值通过调用 IDXCoreAdapterFactory::UnregisterEventNotification 从通知中注销该对象。 如果不注销,则在检测到这种情况时会引发致命异常。

HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);

显示信息

注意

DXCore 本身不提供任何显示信息。 如有必要,应使用 Windows 运行时 DisplayMonitor 类来检索此信息。 适配器的 LUID 提供一个通用标识符,可用于将 DXCore 适配器映射到 DisplayMonitor.DisplayAdapterId 信息。 若要获取适配器的 LUID,请将 DXCoreAdapterProperty::InstanceLuid 传递给 IDXCoreAdapter::GetProperty 方法。

请参阅