Skip to content

Commit

Permalink
Create and initialize Device object: the first PR for rewriting DML b…
Browse files Browse the repository at this point in the history
…ackend
  • Loading branch information
mingmingtasd committed Aug 23, 2022
1 parent 294de6b commit aab6d9b
Show file tree
Hide file tree
Showing 8 changed files with 436 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/webnn/native/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,19 @@ source_set("sources") {
}
}

if (webnn_enable_dml) {
sources += [
"dml/BackendDML.cpp",
"dml/BackendDML.h",
"dml/ContextDML.cpp",
"dml/ContextDML.h",
"dml/GraphDML.cpp",
"dml/GraphDML.h",
"dml/CommandRecorderDML.cpp",
"dml/CommandRecorderDML.h",
]
}

if (webnn_enable_dmlx) {
if (webnn_enable_gpu_buffer == false) {
sources += [
Expand Down
143 changes: 143 additions & 0 deletions src/webnn/native/dml/BackendDML.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2019 The Dawn Authors
// Copyright 2022 The WebNN-native Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "webnn/native/dml/BackendDML.h"

#include "webnn/native/Instance.h"
#include "webnn/native/dml/ContextDML.h"

namespace webnn::native::dml {
HRESULT Backend::EnumAdapter(DXGI_GPU_PREFERENCE gpuPreference) {
Adapter adapter;
ComPtr<IDXGIFactory6> dxgiFactory;
WEBNN_RETURN_IF_FAILED(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)));
UINT adapterIndex = 0;
while (dxgiFactory->EnumAdapterByGpuPreference(adapterIndex++, gpuPreference,
IID_PPV_ARGS(&adapter.adapter)) !=
DXGI_ERROR_NOT_FOUND) {
DXGI_ADAPTER_DESC1 pDesc;
adapter.adapter->GetDesc1(&pDesc);
// An adapter called the "Microsoft Basic Render Driver" is always present.
// This adapter is a render-only device that has no display outputs. 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
bool isSoftwareAdapter = pDesc.Flags == DXGI_ADAPTER_FLAG_SOFTWARE ||
(pDesc.VendorId == 0x1414 && pDesc.DeviceId == 0x8c);
if (!isSoftwareAdapter) {
break;
}
}

// Create the D3D device.
WEBNN_RETURN_IF_FAILED(D3D12CreateDevice(adapter.adapter.Get(), D3D_FEATURE_LEVEL_11_0,
IID_PPV_ARGS(&adapter.D3D12Device)));

// Create the DirectML device.
ComPtr<ID3D12DebugDevice> debugDevice;
if (mUseDebugLayer && SUCCEEDED(adapter.D3D12Device.As(&debugDevice))) {
WEBNN_RETURN_IF_FAILED(DMLCreateDevice(adapter.D3D12Device.Get(),
DML_CREATE_DEVICE_FLAG_DEBUG,
IID_PPV_ARGS(&adapter.DMLDevice)));
} else {
WEBNN_RETURN_IF_FAILED(DMLCreateDevice(adapter.D3D12Device.Get(),
DML_CREATE_DEVICE_FLAG_NONE,
IID_PPV_ARGS(&adapter.DMLDevice)));
}

D3D12_COMMAND_QUEUE_DESC commandQueueDesc{};
commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
WEBNN_RETURN_IF_FAILED(adapter.D3D12Device->CreateCommandQueue(
&commandQueueDesc, IID_PPV_ARGS(&adapter.commandQueue)));
if (adapter.adapter) {
mAdapters[gpuPreference] = adapter;
}
return S_OK;
}

Backend::Backend(InstanceBase* instance)
: BackendConnection(instance, wnn::BackendType::DirectML) {
}

MaybeError Backend::Initialize() {
mUseDebugLayer = false;
#ifdef _DEBUG
mUseDebugLayer = true;
#endif
if (mUseDebugLayer) {
ComPtr<ID3D12Debug> debug;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug)))) {
debug->EnableDebugLayer();
}
}

ComPtr<IDXGIAdapter1> adapter;
EnumAdapter(DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_UNSPECIFIED);
EnumAdapter(DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE);
EnumAdapter(DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_MINIMUM_POWER);
return {};
}

ContextBase* Backend::CreateContext(ContextOptions const* options) {
wnn::DevicePreference devicePreference =
options == nullptr ? wnn::DevicePreference::Default : options->devicePreference;
bool useGpu = devicePreference == wnn::DevicePreference::Cpu ? false : true;
if (!useGpu) {
dawn::ErrorLog() << "Only support to create Context with Gpu.";
return nullptr;
}

Adapter adapter;
wnn::PowerPreference powerPreference =
options == nullptr ? wnn::PowerPreference::Default : options->powerPreference;
switch (powerPreference) {
case wnn::PowerPreference::High_performance:
if (mAdapters.find(DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE) !=
mAdapters.end()) {
adapter = mAdapters[DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE];
}
break;
case wnn::PowerPreference::Low_power:
if (mAdapters.find(DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_MINIMUM_POWER) !=
mAdapters.end()) {
adapter = mAdapters[DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_MINIMUM_POWER];
}
break;
default:
if (mAdapters.find(DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_UNSPECIFIED) !=
mAdapters.end()) {
adapter = mAdapters[DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_UNSPECIFIED];
} else {
dawn::ErrorLog() << "Failed to create the context with none adapter.";
return nullptr;
}
break;
}

return Context::Create(adapter.DMLDevice, adapter.D3D12Device, adapter.commandQueue);
}

BackendConnection* Connect(InstanceBase* instance) {
Backend* backend = new Backend(instance);

if (instance->ConsumedError(backend->Initialize())) {
delete backend;
return nullptr;
}

return backend;
}

} // namespace webnn::native::dml
49 changes: 49 additions & 0 deletions src/webnn/native/dml/BackendDML.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2019 The Dawn Authors
// Copyright 2022 The WebNN-native Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef WEBNN_NATIVE_DML_BACKEND_DML_H_
#define WEBNN_NATIVE_DML_BACKEND_DML_H_

#include <map>

#include "dml_platform.h"
#include "webnn/native/BackendConnection.h"
#include "webnn/native/Context.h"

namespace webnn::native::dml {

struct Adapter {
ComPtr<IDMLDevice> DMLDevice;
ComPtr<ID3D12Device> D3D12Device;
ComPtr<ID3D12CommandQueue> commandQueue;
ComPtr<IDXGIAdapter1> adapter;
};

class Backend : public BackendConnection {
public:
Backend(InstanceBase* instance);

HRESULT EnumAdapter(DXGI_GPU_PREFERENCE gpuPreference);
MaybeError Initialize();
ContextBase* CreateContext(ContextOptions const* options = nullptr) override;

private:
std::map<DXGI_GPU_PREFERENCE, Adapter> mAdapters;
bool mUseDebugLayer;
};

} // namespace webnn::native::dml

#endif // WEBNN_NATIVE_DML_BACKEND_DML_H_
55 changes: 55 additions & 0 deletions src/webnn/native/dml/ContextDML.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2022 The WebNN-native Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "webnn/native/dml/ContextDML.h"

#include "webnn/native/dml/GraphDML.h"

namespace webnn::native::dml {

HRESULT Context::Initialize() {
WEBNN_RETURN_IF_FAILED(mCommandRecorder.D3D12Device->CreateCommandAllocator(
D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&mCommandRecorder.commandAllocator)));
WEBNN_RETURN_IF_FAILED(mCommandRecorder.D3D12Device->CreateCommandList(
0, D3D12_COMMAND_LIST_TYPE_DIRECT, mCommandRecorder.commandAllocator.Get(), nullptr,
IID_PPV_ARGS(&mCommandRecorder.commandList)));
return S_OK;
};

// static
ContextBase* Context::Create(ComPtr<IDMLDevice> DMLDevice,
ComPtr<ID3D12Device> D3D12Device,
ComPtr<ID3D12CommandQueue> commandQueue) {
Context* context = new Context(DMLDevice, D3D12Device, commandQueue);
if (FAILED(context->Initialize())) {
dawn::ErrorLog() << "Failed to initialize Device.";
delete context;
return nullptr;
}
return context;
}

Context::Context(ComPtr<IDMLDevice> DMLDevice,
ComPtr<ID3D12Device> D3D12Device,
ComPtr<ID3D12CommandQueue> commandQueue) {
mCommandRecorder.DMLDevice = DMLDevice;
mCommandRecorder.D3D12Device = D3D12Device;
mCommandRecorder.commandQueue = commandQueue;
}

GraphBase* Context::CreateGraphImpl() {
return new Graph(this);
}

} // namespace webnn::native::dml
47 changes: 47 additions & 0 deletions src/webnn/native/dml/ContextDML.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2022 The WebNN-native Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef WEBNN_NATIVE_DML_CONTEXT_DML_H_
#define WEBNN_NATIVE_DML_CONTEXT_DML_H_

#include "webnn/native/Context.h"

#include "common/Log.h"
#include "CommandRecorderDML.h"
#include "dml_platform.h"
#include "webnn/native/Graph.h"

namespace webnn::native::dml {

class Context : public ContextBase {
public:
static ContextBase* Create(ComPtr<IDMLDevice> DMLDevice,
ComPtr<ID3D12Device> D3D12Device,
ComPtr<ID3D12CommandQueue> commandQueue);
~Context() override = default;

private:
Context(ComPtr<IDMLDevice> DMLDevice,
ComPtr<ID3D12Device> D3D12Device,
ComPtr<ID3D12CommandQueue> commandQueue);
HRESULT Initialize();

GraphBase* CreateGraphImpl() override;

CommandRecorder mCommandRecorder;
};

} // namespace webnn::native::dml

#endif // WEBNN_NATIVE_DML_CONTEXT_DML_H_
33 changes: 33 additions & 0 deletions src/webnn/native/dml/GraphDML.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2022 The WebNN-native Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "webnn/native/dml/GraphDML.h"

#include "webnn/native/NamedInputs.h"
#include "webnn/native/NamedOutputs.h"

namespace webnn::native ::dml {

Graph::Graph(Context* context) : GraphBase(context) {
}

MaybeError Graph::CompileImpl() {
return {};
}

MaybeError Graph::ComputeImpl(NamedInputsBase* inputs, NamedOutputsBase* outputs) {
return {};
}

} // namespace webnn::native::dml
Loading

0 comments on commit aab6d9b

Please sign in to comment.