Uso de DXCore para enumerar adaptadores

DXCore es una API de enumeración de adaptadores para dispositivos DirectX, por lo que algunas de sus instalaciones se superponen con las de DXGI.

DXCore permite la exposición de nuevos tipos de dispositivo al modo de usuario, como MCDM (modelo de controlador de proceso de Microsoft), para su uso con Direct3D 12, DirectML y Windows Machine Learning. DXCore, a diferencia de DXGI, no proporciona ninguna información sobre la tecnología o las propiedades relacionadas con la pantalla.

En las secciones siguientes, echaremos un vistazo a las características principales de DXCore con algunos ejemplos de código (escritos en C++/WinRT). Los ejemplos de código que se muestran a continuación se extraen de la lista de código fuente completa que puede encontrar en el tema Aplicación Minimal DXCore.

Creación de un generador de adaptadores

Para comenzar la enumeración del adaptador DXCore, cree un objeto de fábrica de adaptadores, representado por la interfaz IDXCoreAdapterFactory . Para crear un generador, incluya el archivo de dxcore.h encabezado y llame a la función gratuita DXCoreCreateAdapterFactory .

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

Recuperar una lista de adaptadores

A diferencia de DXGI, una fábrica de adaptadores DXCore recién creada no crea automáticamente una instantánea del estado del adaptador del sistema. En su lugar, DXCore crea esa instantánea cuando se recupera explícitamente un objeto de lista de adaptadores, representado por la interfaz IDXCoreAdapterList .

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

Seleccionar un adaptador adecuado en la lista

En esta sección se muestra cómo, dado un objeto de lista de adaptadores, podría encontrar el primer adaptador de hardware en la lista.

El método IDXCoreAdapterList::GetAdapterCount indica el número de elementos de la lista y IDXCoreAdapterList::GetAdapter recupera un adaptador específico por índice.

Después, puede consultar las propiedades de ese adaptador siguiendo estos pasos.

  • En primer lugar, para confirmar que es válido recuperar el valor de una propiedad determinada para este adaptador en esta versión del sistema operativo, llame a IDXCoreAdapter::IsPropertySupported. Pase un valor de la enumeración DXCoreAdapterProperty para identificar qué propiedad está consultando.
  • Opcionalmente, confirme el tamaño del valor de propiedad con una llamada a IDXCoreAdapter::GetPropertySize. Para una propiedad como DXCoreAdapterProperty::IsHardware, que es un booleano simple, este paso no es necesario.
  • Y, por último, recupere el valor de la propiedad llamando a 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;
    }
}

Seleccionar el adaptador preferido ordenando una lista de adaptadores

Puede ordenar una lista de adaptadores DXCore llamando al método IDXCoreAdapterList::Sort .

La enumeración DXCoreAdapterPreference define valores que representan criterios de ordenación. Pase una matriz de esos valores a Sort y, a continuación, lea el primer adaptador de la lista ordenada resultante.

Para determinar si un tipo de ordenación va a entenderse por Sort, primero llame a 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;
}

Consulta y establecimiento del estado del adaptador (propiedades)

Puede recuperar y establecer el estado de un elemento de estado especificado de un adaptador llamando a los métodos 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));
}

En la práctica, antes de llamar a QueryState y SetState, debe llamar a IsQueryStateSupported para confirmar que la consulta del tipo de estado está disponible para este adaptador y sistema operativo (SO).

Actualización de la lista de adaptadores

Si una lista de adaptadores queda obsoleta debido a las condiciones del sistema cambiantes, se marcará como tal. Puede determinar la actualización de una lista de adaptadores sondeando su método IDXCoreAdapterList::IsStale .

Sin embargo, más convenientemente, puede suscribirse a notificaciones para condiciones como obsolescencia. Para ello, pase DXCoreNotificationType::AdapterListStale a IDXCoreAdapterFactory::RegisterEventNotification y almacene de forma segura la cookie devuelta para su uso posterior.

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

A continuación, puede generar un nuevo objeto de lista de adaptadores actual a partir del objeto de fábrica que ya tiene. El control de estas condiciones es fundamental para su capacidad de responder sin problemas a eventos como la llegada y eliminación del adaptador (ya sea una GPU o un adaptador de proceso especializado) y para desplazar correctamente las cargas de trabajo en respuesta.

Antes de destruir el objeto de lista de adaptadores, debe usar el valor de cookie para anular el registro de ese objeto de las notificaciones mediante una llamada a IDXCoreAdapterFactory::UnregisterEventNotification. Si no anula el registro, se genera una excepción irrecuperable cuando se detecta la situación.

HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);

Mostrar información

Nota

DXCore no proporciona ninguna información de visualización. Cuando sea necesario, debe usar la clase Windows Runtime DisplayMonitor para recuperar esta información. El LUID de un adaptador proporciona un identificador común que puedes usar para asignar un adaptador DXCore a la información de DisplayMonitor.DisplayAdapterId . Para obtener el LUID de un adaptador, pase DXCoreAdapterProperty::InstanceLuid al método IDXCoreAdapter::GetProperty .

Consulte también