Utilisation de DXCore pour énumérer des adaptateurs

DXCore est une API d’énumération d’adaptateur pour les appareils DirectX, de sorte que certaines de ses installations se chevauchent avec celles de DXGI.

DXCore permet l’exposition de nouveaux types d’appareils en mode utilisateur, comme MCDM (modèle de pilote de calcul Microsoft), à utiliser avec Direct3D 12, DirectML et Windows Machine Learning. DXCore, contrairement à DXGI, ne fournit aucune information sur la technologie ou les propriétés liées à l’affichage

Dans les sections suivantes, nous allons examiner les principales fonctionnalités de DXCore avec quelques exemples de code (écrits en C++/WinRT). Les exemples de code indiqués ci-dessous sont extraits de la liste de code source complète que vous pouvez trouver dans la rubrique Minimal DXCore application.

Créer une fabrique d’adaptateurs

Vous commencez l’énumération d’adaptateur DXCore en créant un objet de fabrique d’adaptateur, représenté par l’interface IDXCoreAdapterFactory . Pour créer une fabrique, incluez le dxcore.h fichier d’en-tête et appelez la fonction gratuite DXCoreCreateAdapterFactory .

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

Récupérer une liste d’adaptateurs

Contrairement à DXGI, une fabrique d’adaptateur DXCore nouvellement créée ne crée pas automatiquement un instantané de l’état de l’adaptateur du système. Au lieu de cela, DXCore crée cet instantané lorsque vous récupérez explicitement un objet de liste d’adaptateurs, représenté par l’interface IDXCoreAdapterList .

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

Sélectionner un adaptateur approprié dans la liste

Cette section montre comment, en fonction d’un objet de liste d’adaptateurs, vous pouvez trouver la première carte matérielle de la liste.

La méthode IDXCoreAdapterList::GetAdapterCount vous indique le nombre d’éléments de la liste et IDXCoreAdapterList::GetAdapter récupère une carte spécifique par index.

Vous pouvez ensuite interroger les propriétés de cet adaptateur en suivant ces étapes.

  • Tout d’abord, pour confirmer qu’il est valide de récupérer la valeur d’une propriété donnée pour cette carte sur cette version du système d’exploitation, vous appelez IDXCoreAdapter::IsPropertySupported. Transmettez une valeur de l’énumération DXCoreAdapterProperty pour identifier la propriété à laquelle vous interrogez.
  • Vérifiez éventuellement la taille de la valeur de propriété avec un appel à IDXCoreAdapter::GetPropertySize. Pour une propriété telle que DXCoreAdapterProperty::IsHardware, qui est un booléen simple, cette étape n’est pas nécessaire.
  • Enfin, récupérez la valeur de la propriété en appelant 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;
    }
}

Sélectionnez l’adaptateur préféré en triant une liste d’adaptateurs

Vous pouvez trier une liste d’adaptateurs DXCore en appelant la méthode IDXCoreAdapterList::Sort .

L’énumération DXCoreAdapterPreference définit les valeurs qui représentent des critères de tri. Transmettez un tableau de ces valeurs à Trier, puis lisez la première carte dans la liste triée résultante.

Pour déterminer si un type de tri sera compris par Sort, appelez d’abord 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;
}

Interroger et définir l’état de l’adaptateur (propriétés)

Vous pouvez récupérer et définir l’état d’un élément d’état spécifié d’un adaptateur en appelant les méthodes IDXCoreAdapter::QueryState et 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));
}

Dans la pratique, avant d’appeler QueryState et SetState, vous devez appeler IsQueryStateSupported pour confirmer que l’interrogation du type d’état est disponible pour cet adaptateur et ce système d’exploitation.

Actualisation de la liste des adaptateurs

Si une liste d’adaptateurs devient obsolète en raison de la modification des conditions système, elle sera marquée comme telle. Vous pouvez déterminer la fraîcheur d’une liste d’adaptateurs en interrogeant sa méthode IDXCoreAdapterList::IsStale .

Toutefois, vous pouvez vous abonner à des notifications pour des conditions telles que l’obsolescence. Pour ce faire, passez DXCoreNotificationType::AdapterListStale à IDXCoreAdapterFactory::RegisterEventNotification et stockez en toute sécurité le cookie retourné pour une utilisation ultérieure.

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

Vous pouvez ensuite générer un nouvel objet de liste d’adaptateurs actuel à partir de l’objet de fabrique que vous avez déjà. La gestion de ces conditions est essentielle à votre capacité à répondre en toute transparence aux événements tels que l’arrivée et la suppression de l’adaptateur (qu’il s’agisse d’un GPU ou d’un adaptateur de calcul spécialisé) et de modifier de manière appropriée les charges de travail en réponse.

Avant de détruire l’objet de liste d’adaptateurs, vous devez utiliser la valeur de cookie pour annuler l’inscription de cet objet à partir de notifications en appelant IDXCoreAdapterFactory::UnregisterEventNotification. Si vous n’êtes pas inscrit, une exception irrécupérable est levée lorsque la situation est détectée.

HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);

Afficher des informations

Notes

DXCore ne fournit pas d’informations d’affichage. Si nécessaire, vous devez utiliser la classe DisplayMonitor Windows Runtime pour récupérer ces informations. LuiD d’un adaptateur fournit un identificateur commun que vous pouvez utiliser pour mapper une carte DXCore aux informations DisplayMonitor.DisplayAdapterId. Pour obtenir le luiD d’un adaptateur, passez DXCoreAdapterProperty::InstanceLuid à la méthode IDXCoreAdapter::GetProperty .

Voir aussi