library/src/AdapterEnumeration.cpp (122 lines of code) (raw):

#include "AdapterEnumeration.h" #include "ErrorHandling.h" #include "ObjectHelpers.h" #include <Windows.Devices.Display.Core.Interop.h> AdapterEnumeration::AdapterEnumeration() { // Create our DXCore adapter factory auto error = CheckHresult(DXCoreCreateAdapterFactory(this->adapterFactory.put())); if (error) { throw error.Wrap(L"DXCoreCreateAdapterFactory failed"); } } void AdapterEnumeration::EnumerateAdapters(const DeviceFilter& filter, bool includeIntegrated, bool includeDetachable) { // Log our enumeration parameters LOG( L"Enumerating DirectX adapters using parameters: {{ filter:{}, includeIntegrated:{}, includeDetachable:{} }}", DeviceFilterName(filter), includeIntegrated, includeDetachable ); // Clear our adapter lists and our set of unique adapters this->adapterLists.clear(); this->uniqueAdapters.clear(); #define ENUMERATE_ADAPTERS(attribute)\ {\ GUID attributes[]{ attribute };\ this->adapterLists.push_back(nullptr); \ auto error = CheckHresult(this->adapterFactory->CreateAdapterList(_countof(attributes), attributes, this->adapterLists.back().put()));\ if (error) { \ throw error.Wrap(L"IDXCoreAdapterFactory::CreateAdapterList() failed for attribute " + wstring(L#attribute));\ }\ } // Enumerate adapters that support Direct3D 11 if (filter != DeviceFilter::ComputeOnly && filter != DeviceFilter::DisplayAndCompute) { ENUMERATE_ADAPTERS(DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS); } // Enumerate adapters that support Direct3D 12 if (filter != DeviceFilter::ComputeOnly) { ENUMERATE_ADAPTERS(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS); } // Enumerate adapters that support Direct3D 12 Core if (filter != DeviceFilter::DisplayOnly) { ENUMERATE_ADAPTERS(DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE); } #undef ENUMERATE_ADAPTERS // Process each of the enumerated adapters and apply our filtering criteria for (auto const& adapters : this->adapterLists) { const uint32_t count = adapters->GetAdapterCount(); for (uint32_t index = 0; index < count; ++index) { // Extract the details for the current adapter com_ptr<IDXCoreAdapter> adapter; auto error = CheckHresult(adapters->GetAdapter(index, adapter.put())); if (error) { throw error.Wrap(L"IDXCoreAdapterList::GetAdapter() failed for index " + std::to_wstring(index)); } Adapter details = this->ExtractAdapterDetails(adapter); // Ignore software devices if (!details.IsHardware) { continue; } // If the adapter does not match our filter mode then ignore it if ((filter == DeviceFilter::DisplayOnly && details.SupportsCompute) || (filter == DeviceFilter::ComputeOnly && details.SupportsDisplay) || (filter == DeviceFilter::DisplayAndCompute && (!details.SupportsDisplay || !details.SupportsCompute))) { continue; } // If the adapter is integrated and we are not including integrated devices then ignore it if (details.IsIntegrated && !includeIntegrated) { continue; } // If the adapter is detachable and we are not including detachable devices then ignore it if (details.IsDetachable && !includeDetachable) { continue; } // Add the adapter to our set of unique adapters this->uniqueAdapters.insert(std::make_pair(details.InstanceLuid, details)); } } // Log the list of unique adapter LUIDs LOG(L"Enumerated DirectX adapters with LUIDs: {}", FMT(ObjectHelpers::GetMappingKeys(this->uniqueAdapters))); } const map<int64_t, Adapter>& AdapterEnumeration::GetUniqueAdapters() const { return this->uniqueAdapters; } bool AdapterEnumeration::IsStale() const { // If we have not yet performed enumeration then report that our data is stale if (this->adapterLists.empty()) { LOG(L"No adapter lists yet, need to perform enumeration"); return true; } // If any of our adapter lists are stale then our data is stale for (auto const& list : this->adapterLists) { if (list->IsStale()) { LOG(L"Found stale adapter list"); return true; } } return false; } Adapter AdapterEnumeration::ExtractAdapterDetails(const com_ptr<IDXCoreAdapter>& adapter) const { Adapter details; DeviceDiscoveryError error; // Extract the adapter LUID and convert it to an int64_t LUID instanceLuid; error = CheckHresult(adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, &instanceLuid)); if (error) { throw error.Wrap(L"IDXCoreAdapter::GetProperty() failed for property InstanceLuid"); } details.InstanceLuid = Int64FromLuid(instanceLuid); // Extract the PnP hardware ID information error = CheckHresult(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, &details.HardwareID)); if (error) { throw error.Wrap(L"IDXCoreAdapter::GetProperty() failed for property HardwareID"); } // Extract the boolean specifying whether the adapter is a hardware device error = CheckHresult(adapter->GetProperty(DXCoreAdapterProperty::IsHardware, &details.IsHardware)); if (error) { throw error.Wrap(L"IDXCoreAdapter::GetProperty() failed for property IsHardware"); } // Extract the boolean specifying whether the adapter is an integrated GPU error = CheckHresult(adapter->GetProperty(DXCoreAdapterProperty::IsIntegrated, &details.IsIntegrated)); if (error) { throw error.Wrap(L"IDXCoreAdapter::GetProperty() failed for property IsIntegrated"); } // Extract the boolean specifying whether the adapter is detachable error = CheckHresult(adapter->GetProperty(DXCoreAdapterProperty::IsDetachable, &details.IsDetachable)); if (error) { throw error.Wrap(L"IDXCoreAdapter::GetProperty() failed for property IsDetachable"); } // Determine whether the adapter supports display details.SupportsDisplay = adapter->IsAttributeSupported(DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS) || adapter->IsAttributeSupported(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS); // Determine whether the adapter supports compute details.SupportsCompute = adapter->IsAttributeSupported(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS); return details; }