Verwenden von DXCore zum Auflisten von Adaptern
DXCore ist eine Adapterenumerations-API für DirectX-Geräte, sodass sich einige seiner Funktionen mit denen von DXGI überschneiden.
DXCore ermöglicht die Gefährdung neuer Gerätetypen für den Benutzermodus, z. B. MCDM (Microsoft Compute Driver Model), für die Verwendung mit Direct3D 12, DirectMLund Windows Machine Learning. DXCore stellt im Gegensatz zu DXGI keine Informationen zu anzeigebezogenen Technologien oder Eigenschaften zur Verfügung.
In den nächsten Abschnitten werfen wir einen Blick auf die Hauptfunktionen von DXCore mit einigen Codebeispielen (geschrieben in C++/WinRT). Die unten gezeigten Codebeispiele stammen aus der vollständigen Quellcodeauflistung, die Sie im Thema Minimale DXCore-Anwendung finden.
Erstellen einer Adapter-Factory
Sie beginnen mit der DXCore-Adapterenumeration, indem Sie ein Adapterfactoryobjekt erstellen, das durch die IDXCoreAdapterFactory-Schnittstelle dargestellt wird. Um eine Factory zu erstellen, schließen Sie die dxcore.h Headerdatei ein, und rufen Sie die kostenlose DXCoreCreateAdapterFactory-Funktion auf.
#include <dxcore.h>
...
winrt::com_ptr<IDXCoreAdapterFactory> adapterFactory;
winrt::check_hresult(::DXCoreCreateAdapterFactory(adapterFactory.put()));
Abrufen einer Adapterliste
Im Gegensatz zu DXGI erstellt eine neu erstellte DXCore-Adapter-Factory nicht automatisch eine Momentaufnahme des Adapterzustands des Systems. Stattdessen erstellt DXCore diese Momentaufnahme, wenn Sie explizit ein Adapterlistenobjekt abrufen, das durch die IDXCoreAdapterList-Schnittstelle dargestellt wird.
winrt::com_ptr<IDXCoreAdapterList> d3D12CoreComputeAdapters;
GUID attributes[]{ DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE };
winrt::check_hresult(
adapterFactory->CreateAdapterList(_countof(attributes),
attributes,
d3D12CoreComputeAdapters.put()));
Auswählen eines geeigneten Adapters aus der Liste
In diesem Abschnitt wird veranschaulicht, wie Sie bei einem Adapterlistenobjekt den ersten Hardwareadapter in der Liste finden können.
Die IDXCoreAdapterList::GetAdapterCount-Methode gibt die Anzahl der Elemente in der Liste an, und IDXCoreAdapterList::GetAdapter ruft einen bestimmten Adapter nach Index ab.
Sie können dann die Eigenschaften dieses Adapters abfragen, indem Sie die folgenden Schritte ausführen.
- Um zunächst zu bestätigen, dass es gültig ist, den Wert einer bestimmten Eigenschaft für diesen Adapter auf dieser Betriebssystemversion abzurufen, rufen Sie IDXCoreAdapter::IsPropertySupported auf. Übergeben Sie einen Wert der DXCoreAdapterProperty-Enumeration, um zu identifizieren, welche Eigenschaft Sie abfragen.
- Bestätigen Sie optional die Größe des Eigenschaftswerts mit einem Aufruf von IDXCoreAdapter::GetPropertySize. Für eine Eigenschaft wie DXCoreAdapterProperty::IsHardware, bei der es sich um einen einfachen booleschen Wert handelt, ist dieser Schritt nicht erforderlich.
- Rufen Sie schließlich den Wert der Eigenschaft ab, indem Sie IDXCoreAdapter::GetProperty aufrufen.
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;
}
}
Auswählen des bevorzugten Adapters durch Sortieren einer Adapterliste
Sie können eine DXCore-Adapterliste sortieren, indem Sie die IDXCoreAdapterList::Sort-Methode aufrufen.
Die DXCoreAdapterPreference-Enumeration definiert Werte, die Sortierkriterien darstellen. Übergeben Sie ein Array dieser Werte an Sort, und lesen Sie dann den ersten Adapter in der resultierenden sortierten Liste aus.
Um zu bestimmen, ob ein Sortiertyp von Sort verstanden wird, rufen Sie zunächst IDXCoreAdapterList::IsAdapterPreferenceSupported auf.
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;
}
Abfragen und Festlegen des Adapterzustands (Eigenschaften)
Sie können den Zustand eines angegebenen Zustandselements eines Adapters abrufen und festlegen, indem Sie die Methoden IDXCoreAdapter::QueryState und IDXCoreAdapter::SetState aufrufen.
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));
}
In der Praxis sollten Sie vor dem Aufrufen von QueryState und SetState IsQueryStateSupported aufrufen, um zu bestätigen, dass das Abfragen der Zustandsart für diesen Adapter und das Betriebssystem verfügbar ist.
Aktualität der Adapterliste
Sollte eine Adapterliste aufgrund von sich ändernden Systembedingungen veraltet sein, wird sie als solche gekennzeichnet. Sie können die Aktualität einer Adapterliste ermitteln, indem Sie die IDXCoreAdapterList::IsStale-Methode abruft.
Bequemer können Sie jedoch Benachrichtigungen für Bedingungen wie Veralten abonnieren. Übergeben Sie dazu DXCoreNotificationType::AdapterListFactory::RegisterEventNotification an IDXCoreAdapterFactory::RegisterEventNotification,und speichern Sie das zurückgegebene Cookie zur späteren Verwendung sicher.
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)
{
...
}
Sie können dann ein neues, aktuelles Adapterlistenobjekt aus dem Factoryobjekt generieren, das Sie bereits haben. Der Umgang mit diesen Bedingungen ist entscheidend für Ihre Fähigkeit, nahtlos auf Ereignisse wie das Ein- und Entfernen von Adaptern zu reagieren (unabhängig davon, ob es sich um eine GPU oder einen spezialisierten Computeadapter handelt) und workloads entsprechend zu verschieben.
Bevor Sie das Adapterlistenobjekt zerstören, müssen Sie den Cookiewert verwenden, um die Registrierung dieses Objekts bei Benachrichtigungen durch Aufrufen von IDXCoreAdapterFactory::UnregisterEventNotification zu aufheben. Wenn Sie die Registrierung nicht aufheben, wird eine schwerwiegende Ausnahme ausgelöst, wenn die Situation erkannt wird.
HRESULT hr = factory->UnregisterEventNotification(m_eventCookie);
Anzeigen von Informationen
Hinweis
DXCore selbst stellt keine Anzeigeinformationen zur Verfügung. Verwenden Sie bei Bedarf die klasse Windows Runtime DisplayMonitor, um diese Informationen abzurufen. Die LUID eines Adapters stellt einen allgemeinen Bezeichner zum Zuordnen eines DXCore-Adapters zu DisplayMonitor.DisplayAdapterId-Informationen zur Verfügung. Um die LUID eines Adapters zu erhalten, übergeben Sie DXCoreAdapterProperty::InstanceLuid an die IDXCoreAdapter::GetProperty-Methode.