Compartilhar via


Usar DXCore para enumerar adaptadores

DXCore é uma API de enumeração de adaptador para dispositivos DirectX, portanto, algumas de suas instalações se sobrepõem às do DXGI.

O DXCore permite a exposição de novos tipos de dispositivo ao modo de usuário, como MCDM (Modelo de Driver de Computação da Microsoft), para uso com Direct3D 12, DirectML e Windows Machine Learning. O DXCore, ao contrário do DXGI, não fornece nenhuma informação sobre a tecnologia ou as propriedades relacionadas à exibição

Nas próximas seções, vamos dar uma olhada nos recursos de main do DXCore com alguns exemplos de código (escritos em C++/WinRT). Os exemplos de código mostrados abaixo são extraídos da listagem completa do código-fonte que você pode encontrar no tópico Aplicativo DXCore Mínimo.

Criar uma fábrica de adaptadores

Você inicia a enumeração do adaptador DXCore criando um objeto de fábrica do adaptador, que é representado pela interface IDXCoreAdapterFactory . Para criar uma fábrica, inclua o dxcore.h arquivo de cabeçalho e chame a função livre DXCoreCreateAdapterFactory .

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

Recuperar uma lista de adaptadores

Ao contrário do DXGI, uma fábrica de adaptadores DXCore recém-criada não cria automaticamente uma instantâneo do estado do adaptador do sistema. Em vez disso, o DXCore cria esse instantâneo quando você recupera explicitamente um objeto de lista de adaptadores, que é representado pela 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()));

Selecione um adaptador apropriado na lista

Esta seção demonstra como, dado um objeto de lista de adaptadores, você pode encontrar o primeiro adaptador de hardware na lista.

O método IDXCoreAdapterList::GetAdapterCount informa o número de elementos na lista e IDXCoreAdapterList::GetAdapter recupera um adaptador específico por índice.

Em seguida, você pode consultar as propriedades desse adaptador seguindo estas etapas.

  • Primeiro, para confirmar que é válido recuperar o valor de uma determinada propriedade para esse adaptador nesta versão do sistema operacional, chame IDXCoreAdapter::IsPropertySupported. Passe um valor da enumeração DXCoreAdapterProperty para identificar qual propriedade você está consultando.
  • Opcionalmente, confirme o tamanho do valor da propriedade com uma chamada para IDXCoreAdapter::GetPropertySize. Para uma propriedade como DXCoreAdapterProperty::IsHardware, que é um booliano simples, essa etapa não é necessária.
  • E, por fim, recupere o valor da propriedade chamando 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;
    }
}

Selecione o adaptador preferencial classificando uma lista de adaptadores

Você pode classificar uma lista de adaptadores DXCore chamando o método IDXCoreAdapterList::Sort .

A enumeração DXCoreAdapterPreference define valores que representam critérios de classificação. Passe uma matriz desses valores para Classificar e, em seguida, leia o primeiro adaptador na lista classificada resultante.

Para determinar se um tipo de classificação será compreendido por Sort, primeira chamada 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;
}

Consultar e definir o estado do adaptador (propriedades)

Você pode recuperar e definir o estado de um item de estado especificado de um adaptador chamando os 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));
}

Na prática, antes de chamar QueryState e SetState, você deve chamar IsQueryStateSupported para confirmar se a consulta do tipo de estado está disponível para esse adaptador e sistema operacional (SO).

Atualização da lista de adaptadores

Se uma lista de adaptadores ficar obsoleta devido à alteração das condições do sistema, ela será marcada como tal. Você pode determinar o frescor de uma lista de adaptadores sondando seu método IDXCoreAdapterList::IsStale .

Mais convenientemente, porém, você pode assinar notificações para condições como desatualização. Para fazer isso, passe DXCoreNotificationType::AdapterListStale para IDXCoreAdapterFactory::RegisterEventNotification e armazene com segurança o cookie retornado para 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)
{
    ...
}

Em seguida, você pode gerar um novo objeto de lista de adaptadores, atual, do objeto de fábrica que você já tem. Lidar com essas condições é essencial para sua capacidade de responder perfeitamente a eventos como chegada e remoção do adaptador (seja uma GPU ou um adaptador de computação especializado) e para deslocar adequadamente cargas de trabalho em resposta.

Antes de destruir o objeto de lista de adaptadores, você deve usar o valor do cookie para cancelar o registro desse objeto de notificações chamando IDXCoreAdapterFactory::UnregisterEventNotification. Se você não cancelar o registro, uma exceção fatal será gerada quando a situação for detectada.

HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);

Exibir informações

Observação

O DXCore em si não fornece nenhuma informação de exibição. Quando necessário, você deve usar a classe Windows Runtime DisplayMonitor para recuperar essas informações. O LUID de um adaptador fornece um identificador comum que você pode usar para mapear um adaptador DXCore para as informações de DisplayMonitor.DisplayAdapterId . Para obter o LUID de um adaptador, passe DXCoreAdapterProperty::InstanceLuid para o método IDXCoreAdapter::GetProperty .

Confira também