Uso di DXCore per enumerare gli adapter

DXCore è un'API di enumerazione adapter per i dispositivi DirectX, quindi alcune delle sue strutture si sovrappongono a quelle di DXGI.

DXCore consente l'esposizione di nuovi tipi di dispositivi alla modalità utente, ad esempio MCDM (Microsoft Compute Driver Model), per l'uso con Direct3D 12, DirectML e Windows Machine Learning. DXCore, a differenza di DXGI, non fornisce informazioni sulla tecnologia o sulle proprietà correlate allo schermo

Nelle sezioni successive verranno esaminate le funzionalità principali di DXCore con alcuni esempi di codice (scritti in C++/WinRT). Gli esempi di codice illustrati di seguito sono estratti dall'elenco completo del codice sorgente che è possibile trovare nell'argomento Applicazione DXCore minima.

Creare una factory di adattatori

Per iniziare l'enumerazione dell'adattatore DXCore, creare un oggetto factory dell'adattatore, rappresentato dall'interfaccia IDXCoreAdapterFactory . Per creare una factory, includere il dxcore.h file di intestazione e chiamare la funzione libera DXCoreCreateAdapterFactory .

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

Recuperare un elenco di adattatori

A differenza di DXGI, una nuova factory di adattatori DXCore non crea automaticamente uno snapshot dello stato dell'adattatore del sistema. DXCore crea invece lo snapshot quando si recupera in modo esplicito un oggetto elenco di adattatori, rappresentato dall'interfaccia IDXCoreAdapterList .

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

Selezionare un adattatore appropriato dall'elenco

In questa sezione viene illustrato come, dato un oggetto elenco di adattatori, è possibile trovare la prima scheda hardware nell'elenco.

Il metodo IDXCoreAdapterList::GetAdapterCount indica il numero di elementi nell'elenco e IDXCoreAdapterList::GetAdapter recupera un adattatore specifico per indice.

È quindi possibile eseguire una query sulle proprietà dell'adattatore seguendo questa procedura.

  • Prima di tutto, per verificare che sia valido recuperare il valore di una determinata proprietà per questa scheda in questa versione del sistema operativo, chiamare IDXCoreAdapter::IsPropertySupported. Passare un valore dell'enumerazione DXCoreAdapterProperty per identificare la proprietà su cui si esegue una query.
  • Facoltativamente, verificare le dimensioni del valore della proprietà con una chiamata a IDXCoreAdapter::GetPropertySize. Per una proprietà come DXCoreAdapterProperty::IsHardware, che è un semplice booleano, questo passaggio non è necessario.
  • Infine, recuperare il valore della proprietà chiamando IDXCoreAdapter::GetProperty.
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;
    }
}

Selezionare l'adattatore preferito ordinando un elenco di adattatori

È possibile ordinare un elenco di adattatori DXCore chiamando il metodo IDXCoreAdapterList::Sort .

L'enumerazione DXCoreAdapterPreference definisce i valori che rappresentano i criteri di ordinamento. Passare una matrice di tali valori a Ordina e quindi leggere la prima scheda nell'elenco ordinato risultante.

Per determinare se un tipo di ordinamento verrà compreso in Sort, chiamare prima 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;
}

Eseguire query e impostare lo stato dell'adattatore (proprietà)

È possibile recuperare e impostare lo stato di un elemento di stato specificato di un adattatore chiamando i metodi IDXCoreAdapter::QueryState e 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));
}

In pratica, prima di chiamare QueryState e SetState, è necessario chiamare IsQueryStateSupported per verificare che l'esecuzione di query sul tipo di stato sia disponibile per questa scheda e il sistema operativo.

Aggiornamento dell'elenco degli adattatori

Se un elenco di adattatori diventa obsoleto a causa della modifica delle condizioni di sistema, verrà contrassegnato come tale. È possibile determinare la freschezza di un elenco di adattatori eseguendo il polling del relativo metodo IDXCoreAdapterList::IsStale .

Più convenientemente, tuttavia, è possibile sottoscrivere le notifiche per condizioni come la decadimento. A tale scopo, passare DXCoreNotificationType::AdapterListStale a IDXCoreAdapterFactory::RegisterEventNotification e archiviare in modo sicuro il cookie restituito per usarlo in un secondo momento.

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

È quindi possibile generare un nuovo oggetto elenco di adattatori corrente dall'oggetto factory già presente. La gestione di queste condizioni è fondamentale per la possibilità di rispondere senza problemi a eventi come l'arrivo e la rimozione delle schede (che si tratti di una GPU o di una scheda di calcolo specializzata) e di spostare in modo appropriato i carichi di lavoro in risposta.

Prima di eliminare definitivamente l'oggetto elenco di adattatori, è necessario utilizzare il valore del cookie per annullare la registrazione dell'oggetto dalle notifiche chiamando IDXCoreAdapterFactory::UnregisterEventNotification. Se non si annulla la registrazione, viene generata un'eccezione irreversibile quando viene rilevata la situazione.

HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);

Visualizzare le informazioni

Nota

DXCore non fornisce informazioni di visualizzazione. Se necessario, è necessario usare la classe Windows Runtime DisplayMonitor per recuperare queste informazioni. Il LUID di un adattatore fornisce un identificatore comune che è possibile usare per eseguire il mapping di una scheda DXCore alle informazioni displayMonitor.DisplayAdapterId. Per ottenere il LUID di un adattatore, passare DXCoreAdapterProperty::InstanceLuid al metodo IDXCoreAdapter::GetProperty .

Vedi anche