|
| 1 | +// Copyright 2019 The Dawn Authors |
| 2 | +// Copyright 2022 The WebNN-native Authors |
| 3 | +// |
| 4 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +// you may not use this file except in compliance with the License. |
| 6 | +// You may obtain a copy of the License at |
| 7 | +// |
| 8 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +// |
| 10 | +// Unless required by applicable law or agreed to in writing, software |
| 11 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +// See the License for the specific language governing permissions and |
| 14 | +// limitations under the License. |
| 15 | + |
| 16 | +#include "webnn/native/dml/BackendDML.h" |
| 17 | + |
| 18 | +#include "webnn/native/Instance.h" |
| 19 | +#include "webnn/native/dml/ContextDML.h" |
| 20 | + |
| 21 | +namespace webnn::native::dml { |
| 22 | + |
| 23 | + Backend::Backend(InstanceBase* instance) |
| 24 | + : BackendConnection(instance, wnn::BackendType::DirectML) { |
| 25 | + } |
| 26 | + |
| 27 | + MaybeError Backend::Initialize() { |
| 28 | + return {}; |
| 29 | + } |
| 30 | + |
| 31 | + // An adapter called the "Microsoft Basic Render Driver" is always present. This adapter is a |
| 32 | + // render-only device that has no display outputs. |
| 33 | + inline bool IsSoftwareAdapter(IDXGIAdapter1* pAdapter) { |
| 34 | + DXGI_ADAPTER_DESC1 pDesc; |
| 35 | + pAdapter->GetDesc1(&pDesc); |
| 36 | + // See here for documentation on filtering WARP adapter: |
| 37 | + // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/d3d10-graphics-programming-guide-dxgi#new-info-about-enumerating-adapters-for-windows-8 |
| 38 | + return pDesc.Flags == DXGI_ADAPTER_FLAG_SOFTWARE || |
| 39 | + (pDesc.VendorId == 0x1414 && pDesc.DeviceId == 0x8c); |
| 40 | + } |
| 41 | + |
| 42 | + HRESULT EnumAdapter(DXGI_GPU_PREFERENCE gpuPreference, |
| 43 | + bool useGpu, |
| 44 | + ComPtr<IDXGIAdapter1> adapter) { |
| 45 | + ComPtr<IDXGIFactory6> dxgiFactory; |
| 46 | + WEBNN_RETURN_IF_FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory))); |
| 47 | + if (useGpu) { |
| 48 | + UINT adapterIndex = 0; |
| 49 | + while (dxgiFactory->EnumAdapterByGpuPreference(adapterIndex++, gpuPreference, |
| 50 | + IID_PPV_ARGS(&adapter)) != |
| 51 | + DXGI_ERROR_NOT_FOUND) { |
| 52 | + if (!IsSoftwareAdapter(adapter.Get())) { |
| 53 | + break; |
| 54 | + } |
| 55 | + } |
| 56 | + } else { |
| 57 | + WEBNN_RETURN_IF_FAILED(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(&adapter))); |
| 58 | + } |
| 59 | + return S_OK; |
| 60 | + } |
| 61 | + |
| 62 | + ContextBase* Backend::CreateContext(ContextOptions const* options) { |
| 63 | + wnn::DevicePreference devicePreference = options->devicePreference; |
| 64 | + bool useGpu = devicePreference == wnn::DevicePreference::Cpu ? false : true; |
| 65 | + DXGI_GPU_PREFERENCE gpuPreference = DXGI_GPU_PREFERENCE_UNSPECIFIED; |
| 66 | + wnn::PowerPreference powerPreference = options->powerPreference; |
| 67 | + switch (powerPreference) { |
| 68 | + case wnn::PowerPreference::High_performance: |
| 69 | + gpuPreference = DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE; |
| 70 | + break; |
| 71 | + case wnn::PowerPreference::Low_power: |
| 72 | + gpuPreference = DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_MINIMUM_POWER; |
| 73 | + break; |
| 74 | + default: |
| 75 | + break; |
| 76 | + } |
| 77 | + |
| 78 | + bool useDebugLayer = false; |
| 79 | +#ifdef _DEBUG |
| 80 | + useDebugLayer = true; |
| 81 | +#endif |
| 82 | + ComPtr<IDXGIAdapter1> adapter; |
| 83 | + if (FAILED(EnumAdapter(gpuPreference, useGpu, adapter))) { |
| 84 | + dawn::ErrorLog() << "Failed to enumerate adapters."; |
| 85 | + DAWN_ASSERT(0); |
| 86 | + } |
| 87 | + return Context::Create(adapter, useDebugLayer); |
| 88 | + } |
| 89 | + |
| 90 | + BackendConnection* Connect(InstanceBase* instance) { |
| 91 | + Backend* backend = new Backend(instance); |
| 92 | + |
| 93 | + if (instance->ConsumedError(backend->Initialize())) { |
| 94 | + delete backend; |
| 95 | + return nullptr; |
| 96 | + } |
| 97 | + |
| 98 | + return backend; |
| 99 | + } |
| 100 | + |
| 101 | +} // namespace webnn::native::dml |
0 commit comments