Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support enumerating graphics adapters based on a given GPU preference #217

Merged
merged 1 commit into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions Python/src/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,22 @@
using namespace pydml;
using Microsoft::WRL::ComPtr;

Device::Device(bool useGpu, bool useDebugLayer) :
m_useGpu(useGpu)
// An adapter called the "Microsoft Basic Render Driver" is always present. This adapter is a render-only device that has no display outputs.
HRESULT IsWarpAdapter(IDXGIAdapter1* pAdapter, bool* isWarpAdapter)
{
DXGI_ADAPTER_DESC1 pDesc;
ReturnIfFailed(pAdapter->GetDesc1(&pDesc));
// see here for documentation on filtering WARP adapter:
// https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/d3d10-graphics-programming-guide-dxgi#new-info-about-enumerating-adapters-for-windows-8
auto isBasicRenderDriverVendorId = pDesc.VendorId == 0x1414;
auto isBasicRenderDriverDeviceId = pDesc.DeviceId == 0x8c;
auto isSoftwareAdapter = pDesc.Flags == DXGI_ADAPTER_FLAG_SOFTWARE;
*isWarpAdapter = isSoftwareAdapter || (isBasicRenderDriverVendorId && isBasicRenderDriverDeviceId);
return S_OK;
}

Device::Device(bool useGpu, bool useDebugLayer, DXGI_GPU_PREFERENCE gpuPreference) :
m_useGpu(useGpu), m_gpuPreference(gpuPreference)
{
//
// Create D3D12 resources
Expand All @@ -28,9 +42,26 @@ Device::Device(bool useGpu, bool useDebugLayer) :
}
}

ComPtr<IDXGIAdapter> dxgiAdapter;
ComPtr<IDXGIAdapter1> dxgiAdapter;
if (m_useGpu)
{
ComPtr<IDXGIFactory6> spFactory;
ReturnIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&spFactory)));
UINT i = 0;
while (spFactory->EnumAdapterByGpuPreference(i, m_gpuPreference, IID_PPV_ARGS(&dxgiAdapter)) != DXGI_ERROR_NOT_FOUND)
{
bool isWarpAdapter = false;
ReturnIfFailed(IsWarpAdapter(dxgiAdapter.Get(), &isWarpAdapter));
if (!isWarpAdapter)
{
break;
}
++i;
}
}

if ( !useGpu
|| FAILED(D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3d12Device))))
|| FAILED(D3D12CreateDevice(dxgiAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_d3d12Device))))
{
ComPtr<IDXGIFactory4> dxgiFactory;
ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)));
Expand Down
3 changes: 2 additions & 1 deletion Python/src/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace pydml
class Device
{
public:
explicit Device(bool useGpu = true, bool useDebugLayer = false);
explicit Device(bool useGpu = true, bool useDebugLayer = false, DXGI_GPU_PREFERENCE gpuPreference = DXGI_GPU_PREFERENCE_UNSPECIFIED);

std::vector<pydml::TensorData*> Compute(
IDMLCompiledOperator* op,
Expand Down Expand Up @@ -108,5 +108,6 @@ namespace pydml

bool m_useCpuCustomHeapResources = false;
bool m_useGpu = true;
DXGI_GPU_PREFERENCE m_gpuPreference;
};
}
1 change: 1 addition & 0 deletions Python/src/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

// ToDo: dxgi isn't available in WSL.
#include <dxgi1_5.h>
#include <dxgi1_6.h>
#include <dxgidebug.h>

#include <initguid.h>
Expand Down