Перечисление адаптеров с использованием DXCore
DXCore — это API перечисления адаптеров для устройств DirectX, поэтому некоторые из его возможностей перекрываются с api DXGI.
DXCore позволяет использовать новые типы устройств в пользовательском режиме, например MCDM (модель драйвера вычислений Майкрософт), для использования с Direct3D 12, DirectML и Windows Машинное обучение. DXCore, в отличие от DXGI, не предоставляет никаких сведений о технологии или свойствах, связанных с отображением
В следующих нескольких разделах мы рассмотрим основные функции DXCore с некоторыми примерами кода (написанными на C++/WinRT). Приведенные ниже примеры кода извлекаются из полного описания исходного кода, который можно найти в разделе "Минимальное приложение DXCore".
Создание фабрики адаптеров
Перечисление адаптера DXCore начинается путем создания объекта фабрики адаптеров, представленного интерфейсом IDXCoreAdapterFactory . Чтобы создать фабрику, включите файл заголовка dxcore.h
и вызовите бесплатную функцию DXCoreCreateAdapterFactory .
#include <dxcore.h>
...
winrt::com_ptr<IDXCoreAdapterFactory> adapterFactory;
winrt::check_hresult(::DXCoreCreateAdapterFactory(adapterFactory.put()));
Получение списка адаптеров
В отличие от DXGI, только что созданная фабрика адаптеров DXCore не создает моментальный снимок состояния адаптера системы. Вместо этого DXCore создает этот моментальный снимок при явном извлечении объекта списка адаптеров, который представлен интерфейсом IDXCoreAdapterList .
winrt::com_ptr<IDXCoreAdapterList> d3D12CoreComputeAdapters;
GUID attributes[]{ DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE };
winrt::check_hresult(
adapterFactory->CreateAdapterList(_countof(attributes),
attributes,
d3D12CoreComputeAdapters.put()));
Выбор подходящего адаптера из списка
В этом разделе показано, как, учитывая объект списка адаптеров, можно найти первый аппаратный адаптер в списке.
Метод IDXCoreAdapterList::GetAdapterCount сообщает количество элементов в списке, а IDXCoreAdapterList::GetAdapter извлекает определенный адаптер по индексу.
Затем можно запросить свойства этого адаптера, выполнив следующие действия.
- Во-первых, чтобы убедиться, что это допустимо для получения значения заданного свойства для этого адаптера в этой версии операционной системы, вызывается IDXCoreAdapter::IsPropertySupported. Передайте значение перечисления DXCoreAdapterProperty , чтобы определить, о каком свойстве вы запрашиваете.
- При необходимости подтвердите размер значения свойства с помощью вызова IDXCoreAdapter::GetPropertySize. Для свойства, такого как DXCoreAdapterProperty::IsHardware, которое является простым логическим, этот шаг не требуется.
- Наконец, получите значение свойства, вызвав 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;
}
}
Выбор предпочтительного адаптера путем сортировки списка адаптеров
Список адаптеров DXCore можно отсортировать, вызвав метод IDXCoreAdapterList::Sort .
Перечисление DXCoreAdapterPreference определяет значения, представляющие критерии сортировки. Передайте массив этих значений в "Сортировку", а затем считывает первый адаптер в результирующем отсортированный список.
Чтобы определить, будет ли тип сортировки понят с помощью Sort, сначала вызовите 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;
}
Запрос и задание состояния адаптера (свойства)
Вы можете получить и задать состояние указанного элемента состояния адаптера, вызвав методы IDXCoreAdapter::QueryState и 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));
}
На практике перед вызовом QueryState и SetState следует вызвать IsQueryStateSupported , чтобы убедиться, что запрос типа состояния доступен для этого адаптера и операционной системы (ОС).
Актуальность списка адаптеров
Если список адаптеров становится устаревшим из-за изменения условий системы, он будет помечен как таковой. Вы можете определить актуальность списка адаптеров, опрашивая его метод IDXCoreAdapterList::IsStale .
Более удобно, однако, вы можете подписаться на уведомления для таких условий, как устаревание. Для этого передайте DXCoreNotificationType::AdapterListStale в IDXCoreAdapterFactory::RegisterEventNotification и безопасно сохраните возвращенный файл cookie для последующего использования.
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)
{
...
}
Затем можно создать новый текущий объект списка адаптеров из уже имеющегося объекта фабрики. Обработка этих условий крайне важна для вашей способности легко реагировать на такие события, как прибытие и удаление адаптера (будь то GPU или специализированный вычислительный адаптер), а также для соответствующей смены рабочих нагрузок в ответ.
Перед уничтожением объекта списка адаптеров необходимо использовать значение cookie для отмены регистрации этого объекта из уведомлений путем вызова IDXCoreAdapterFactory::UnregisterEventNotification. Если вы не отмените регистрацию, при обнаружении ситуации возникает неустранимое исключение.
HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);
Отображение сведений
Примечание
DXCore не предоставляет никаких отображаемых сведений. При необходимости для получения этих сведений следует использовать класс среда выполнения Windows DisplayMonitor. LUID адаптера предоставляет общий идентификатор, который можно использовать для сопоставления адаптера DXCore с данными DisplayMonitor.DisplayAdapterId. Чтобы получить LUID адаптера, передайте DXCoreAdapterProperty::InstanceLuid в метод IDXCoreAdapter::GetProperty .