Verwenden von DXCore zum Auflisten von Adaptern

DXCore ist eine Adapterenumerations-API für DirectX-Geräte, sodass sich einige ihrer Funktionen mit denen von DXGI überschneiden.

DXCore ermöglicht die Offenlegung neuer Gerätetypen im Benutzermodus, z. B. MCDM (Microsoft Compute Driver Model), für die Verwendung mit Direct3D 12, DirectML und Windows Machine Learning. DXCore stellt im Gegensatz zu DXGI keine Informationen zu anzeigebezogenen Technologien oder Eigenschaften bereit.

In den nächsten Abschnitten werfen wir einen Blick auf die Standard Features von DXCore mit einigen Codebeispielen (geschrieben in C++/WinRT). Die unten gezeigten Codebeispiele werden aus dem vollständigen Quellcodeeintrag extrahiert, den Sie im Thema Minimale DXCore-Anwendung finden.

Erstellen einer Adapterfactory

Sie beginnen mit der DXCore-Adapterenumeration, indem Sie ein Adapterfactoryobjekt erstellen, das durch die IDXCoreAdapterFactory-Schnittstelle dargestellt wird. Um eine Factory zu erstellen, schließen Sie die dxcore.h Headerdatei ein, und rufen Sie die kostenlose DXCoreCreateAdapterFactory-Funktion auf.

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

Abrufen einer Adapterliste

Im Gegensatz zu DXGI erstellt eine neu erstellte DXCore-Adapterfactory nicht automatisch eine Momentaufnahme des Adapterstatus des Systems. Stattdessen erstellt DXCore diese Momentaufnahme, wenn Sie explizit ein Adapterlistenobjekt abrufen, das durch die IDXCoreAdapterList-Schnittstelle dargestellt wird.

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

Auswählen eines geeigneten Adapters aus der Liste

In diesem Abschnitt wird veranschaulicht, wie Sie bei einem Adapterlistenobjekt den ersten Hardwareadapter in der Liste finden können.

Die IDXCoreAdapterList::GetAdapterCount-Methode gibt die Anzahl der Elemente in der Liste an, und IDXCoreAdapterList::GetAdapter ruft einen bestimmten Adapter nach Index ab.

Sie können dann die Eigenschaften dieses Adapters abfragen, indem Sie die folgenden Schritte ausführen.

  • Um zu bestätigen, dass es gültig ist, den Wert einer bestimmten Eigenschaft für diesen Adapter unter dieser Betriebssystemversion abzurufen, rufen Sie IDXCoreAdapter::IsPropertySupported auf. Übergeben Sie einen Wert der DXCoreAdapterProperty-Enumeration , um zu identifizieren, welche Eigenschaft Sie abfragen.
  • Bestätigen Sie optional die Größe des Eigenschaftswerts mit einem Aufruf von IDXCoreAdapter::GetPropertySize. Für eine Eigenschaft wie DXCoreAdapterProperty::IsHardware, bei der es sich um einen einfachen booleschen Wert handelt, ist dieser Schritt nicht erforderlich.
  • Rufen Sie schließlich den Wert der Eigenschaft ab, indem Sie IDXCoreAdapter::GetProperty aufrufen.
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;
    }
}

Wählen Sie den bevorzugten Adapter aus, indem Sie eine Adapterliste sortieren.

Sie können eine DXCore-Adapterliste sortieren, indem Sie die IDXCoreAdapterList::Sort-Methode aufrufen.

Die DXCoreAdapterPreference-Enumeration definiert Werte, die Sortierkriterien darstellen. Übergeben Sie ein Array dieser Werte an Sort, und lesen Sie dann den ersten Adapter in der resultierenden sortierten Liste aus.

Um zu bestimmen, ob ein Sortiertyp von Sort verstanden wird, rufen Sie zunächst IDXCoreAdapterList::IsAdapterPreferenceSupported auf.

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;
}

Abfragen und Festlegen des Adapterzustands (Eigenschaften)

Sie können den Zustand eines angegebenen Zustandselements eines Adapters abrufen und festlegen, indem Sie die Methoden IDXCoreAdapter::QueryState und IDXCoreAdapter::SetState aufrufen.

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));
}

In der Praxis sollten Sie vor dem Aufrufen von QueryState und SetStateIsQueryStateSupported aufrufen, um zu bestätigen, dass die Abfrage der Zustandsart für diesen Adapter und das Betriebssystem verfügbar ist.

Aktualität der Adapterliste

Sollte eine Adapterliste aufgrund sich ändernder Systembedingungen veraltet sein, wird sie als solche gekennzeichnet. Sie können die Aktualität einer Adapterliste ermitteln, indem Sie die IDXCoreAdapterList::IsStale-Methode abfragen.

Bequemer können Sie jedoch Benachrichtigungen für Bedingungen wie Veraltung abonnieren. Übergeben Sie dazu DXCoreNotificationType::AdapterListStale an IDXCoreAdapterFactory::RegisterEventNotification, und speichern Sie das zurückgegebene Cookie zur späteren Verwendung sicher.

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)
{
    ...
}

Anschließend können Sie aus dem bereits vorhandenen Factoryobjekt ein neues aktuelles Adapterlistenobjekt generieren. Die Behandlung dieser Bedingungen ist entscheidend für Ihre Fähigkeit, nahtlos auf Ereignisse wie das Eintreffen und Entfernen des Adapters zu reagieren (unabhängig davon, ob es sich um eine GPU oder einen spezialisierten Computeadapter handelt) und workloads entsprechend zu verschieben.

Bevor Sie das Adapterlistenobjekt zerstören, müssen Sie den Cookiewert verwenden, um die Registrierung dieses Objekts in Benachrichtigungen aufzuheben, indem Sie IDXCoreAdapterFactory::UnregisterEventNotification aufrufen. Wenn Sie die Registrierung nicht aufheben, wird eine schwerwiegende Ausnahme ausgelöst, wenn die Situation erkannt wird.

HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);

Anzeigen von Informationen

Hinweis

DXCore stellt selbst keine Anzeigeinformationen bereit. Wenn erforderlich, sollten Sie die Windows-Runtime DisplayMonitor-Klasse verwenden, um diese Informationen abzurufen. Die LUID eines Adapters stellt einen allgemeinen Bezeichner bereit, den Sie zum Zuordnen eines DXCore-Adapters zu DisplayMonitor.DisplayAdapterId-Informationen verwenden können. Um die LUID eines Adapters abzurufen, übergeben Sie DXCoreAdapterProperty::InstanceLuid an die IDXCoreAdapter::GetProperty-Methode .

Siehe auch