in Tools/WinMLRunner/src/LearningModelDeviceHelper.cpp [31:240]
void PopulateLearningModelDeviceList(CommandLineArgs& args, std::vector<LearningModelDeviceWithMetadata>& deviceList)
{
std::vector<DeviceType> deviceTypes = args.FetchDeviceTypes();
std::vector<DeviceCreationLocation> deviceCreationLocations = args.FetchDeviceCreationLocations();
for (auto deviceType : deviceTypes)
{
for (auto deviceCreationLocation : deviceCreationLocations)
{
try
{
#ifdef DXCORE_SUPPORTED_BUILD
const std::wstring& adapterName = args.GetGPUAdapterName();
#endif
if (deviceCreationLocation == DeviceCreationLocation::UserD3DDevice && deviceType != DeviceType::CPU)
{
// Enumerate Adapters to pick the requested one.
com_ptr<IDXGIFactory6> factory;
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory6), factory.put_void());
THROW_IF_FAILED(hr);
com_ptr<IDXGIAdapter> adapter;
switch (deviceType)
{
case DeviceType::DefaultGPU:
hr = factory->EnumAdapterByGpuPreference(0, DXGI_GPU_PREFERENCE_UNSPECIFIED,
__uuidof(IDXGIAdapter), adapter.put_void());
break;
case DeviceType::MinPowerGPU:
hr = factory->EnumAdapterByGpuPreference(0, DXGI_GPU_PREFERENCE_MINIMUM_POWER,
__uuidof(IDXGIAdapter), adapter.put_void());
break;
case DeviceType::HighPerfGPU:
hr = factory->EnumAdapterByGpuPreference(0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
__uuidof(IDXGIAdapter), adapter.put_void());
break;
default:
throw hresult(E_INVALIDARG);
}
THROW_IF_FAILED(hr);
// Creating the device on the client and using it to create the video frame and initialize the
// session makes sure that everything is on the same device. This usually avoids an expensive
// cross-device and cross-videoframe copy via the VideoFrame pipeline.
com_ptr<ID3D11Device> d3d11Device;
hr = D3D11CreateDevice(adapter.get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr,
D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION,
d3d11Device.put(), nullptr, nullptr);
THROW_IF_FAILED(hr);
com_ptr<IDXGIDevice> dxgiDevice;
hr = d3d11Device->QueryInterface(__uuidof(IDXGIDevice), dxgiDevice.put_void());
THROW_IF_FAILED(hr);
com_ptr<IInspectable> inspectableDevice;
hr = CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.get(), inspectableDevice.put());
THROW_IF_FAILED(hr);
LearningModelDeviceWithMetadata learningModelDeviceWithMetadata =
{
LearningModelDevice::CreateFromDirect3D11Device(inspectableDevice.as<IDirect3DDevice>()),
deviceType,
deviceCreationLocation
};
OutputHelper::PrintLearningModelDevice(learningModelDeviceWithMetadata);
deviceList.push_back(learningModelDeviceWithMetadata);
}
#ifdef DXCORE_SUPPORTED_BUILD
else if ((TypeHelper::GetWinmlDeviceKind(deviceType) != LearningModelDeviceKind::Cpu) &&
!adapterName.empty())
{
com_ptr<IDXCoreAdapterFactory> spFactory;
THROW_IF_FAILED(DXCoreCreateAdapterFactory(IID_PPV_ARGS(spFactory.put())));
com_ptr<IDXCoreAdapterList> spAdapterList;
const GUID dxGUIDs[] = { DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE };
THROW_IF_FAILED(
spFactory->CreateAdapterList(ARRAYSIZE(dxGUIDs), dxGUIDs, IID_PPV_ARGS(spAdapterList.put())));
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string adapterNameStr = converter.to_bytes(adapterName);
com_ptr<IDXCoreAdapter> spAdapter = nullptr;
com_ptr<IDXCoreAdapter> currAdapter = nullptr;
bool chosenAdapterFound = false;
printf("Printing available adapters..\n");
for (UINT i = 0; i < spAdapterList->GetAdapterCount(); i++)
{
THROW_IF_FAILED(spAdapterList->GetAdapter(i, currAdapter.put()));
// If the adapter is a software adapter then don't consider it for index selection
bool isHardware;
size_t driverDescriptionSize;
THROW_IF_FAILED(currAdapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription,
&driverDescriptionSize));
CHAR* driverDescription = new CHAR[driverDescriptionSize];
THROW_IF_FAILED(currAdapter->GetProperty(DXCoreAdapterProperty::IsHardware, &isHardware));
THROW_IF_FAILED(currAdapter->GetProperty(DXCoreAdapterProperty::DriverDescription,
driverDescriptionSize, driverDescription));
if (isHardware)
{
printf("Description: %s\n", driverDescription);
}
if (!adapterName.empty() && !chosenAdapterFound)
{
std::string driverDescriptionStr = std::string(driverDescription);
std::transform(driverDescriptionStr.begin(), driverDescriptionStr.end(),
driverDescriptionStr.begin(), ::tolower);
std::transform(adapterNameStr.begin(), adapterNameStr.end(), adapterNameStr.begin(),
::tolower);
if (strstr(driverDescriptionStr.c_str(), adapterNameStr.c_str()))
{
chosenAdapterFound = true;
spAdapter = currAdapter;
}
}
currAdapter = nullptr;
delete driverDescription;
}
if (spAdapter == nullptr)
{
throw hresult_invalid_argument(L"ERROR: No matching adapter with given adapter name: " +
adapterName);
}
size_t driverDescriptionSize;
THROW_IF_FAILED(
spAdapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription, &driverDescriptionSize));
CHAR* driverDescription = new CHAR[driverDescriptionSize];
spAdapter->GetProperty(DXCoreAdapterProperty::DriverDescription, driverDescriptionSize,
driverDescription);
printf("Using adapter : %s\n", driverDescription);
delete driverDescription;
IUnknown* pAdapter = spAdapter.get();
com_ptr<IDXGIAdapter> spDxgiAdapter;
D3D_FEATURE_LEVEL d3dFeatureLevel = D3D_FEATURE_LEVEL_1_0_CORE;
D3D12_COMMAND_LIST_TYPE commandQueueType = D3D12_COMMAND_LIST_TYPE_COMPUTE;
// Check if adapter selected has DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS attribute selected. If
// so, then GPU was selected that has D3D12 and D3D11 capabilities. It would be the most stable
// to use DXGI to enumerate GPU and use D3D_FEATURE_LEVEL_11_0 so that image tensorization for
// video frames would be able to happen on the GPU.
if (spAdapter->IsAttributeSupported(DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS))
{
d3dFeatureLevel = D3D_FEATURE_LEVEL::D3D_FEATURE_LEVEL_11_0;
com_ptr<IDXGIFactory4> dxgiFactory4;
HRESULT hr;
try
{
hr = CreateDXGIFactory2SEH(dxgiFactory4.put_void());
}
catch (...)
{
hr = E_FAIL;
}
if (hr == S_OK)
{
// If DXGI factory creation was successful then get the IDXGIAdapter from the LUID
// acquired from the selectedAdapter
std::cout << "Using DXGI for adapter creation.." << std::endl;
LUID adapterLuid;
THROW_IF_FAILED(spAdapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, &adapterLuid));
THROW_IF_FAILED(dxgiFactory4->EnumAdapterByLuid(adapterLuid, __uuidof(IDXGIAdapter),
spDxgiAdapter.put_void()));
pAdapter = spDxgiAdapter.get();
}
}
// create D3D12Device
com_ptr<ID3D12Device> d3d12Device;
THROW_IF_FAILED(
D3D12CreateDevice(pAdapter, d3dFeatureLevel, __uuidof(ID3D12Device), d3d12Device.put_void()));
// create D3D12 command queue from device
com_ptr<ID3D12CommandQueue> d3d12CommandQueue;
D3D12_COMMAND_QUEUE_DESC commandQueueDesc = {};
commandQueueDesc.Type = commandQueueType;
THROW_IF_FAILED(d3d12Device->CreateCommandQueue(&commandQueueDesc, __uuidof(ID3D12CommandQueue),
d3d12CommandQueue.put_void()));
// create LearningModelDevice from command queue
auto factory = get_activation_factory<LearningModelDevice, ILearningModelDeviceFactoryNative>();
com_ptr<::IUnknown> spUnkLearningModelDevice;
THROW_IF_FAILED(
factory->CreateFromD3D12CommandQueue(d3d12CommandQueue.get(), spUnkLearningModelDevice.put()));
deviceList.push_back({
spUnkLearningModelDevice.as<LearningModelDevice>(),
deviceType,
deviceCreationLocation
});
}
#endif
else
{
LearningModelDeviceWithMetadata learningModelDeviceWithMetadata =
{
LearningModelDevice( TypeHelper::GetWinmlDeviceKind(deviceType)),
deviceType,
deviceCreationLocation
};
OutputHelper::PrintLearningModelDevice(learningModelDeviceWithMetadata);
deviceList.push_back(learningModelDeviceWithMetadata);
}
}
catch (...)
{
printf("Creating LearningModelDevice failed!");
throw;
}
}
}
}