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 .