• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "dawn_native/d3d12/BackendD3D12.h"
16 
17 #include "dawn_native/D3D12Backend.h"
18 #include "dawn_native/Instance.h"
19 #include "dawn_native/d3d12/AdapterD3D12.h"
20 #include "dawn_native/d3d12/D3D12Error.h"
21 #include "dawn_native/d3d12/PlatformFunctions.h"
22 
23 namespace dawn_native { namespace d3d12 {
24 
25     namespace {
26 
CreateFactory(const PlatformFunctions * functions,BackendValidationLevel validationLevel,bool beginCaptureOnStartup)27         ResultOrError<ComPtr<IDXGIFactory4>> CreateFactory(const PlatformFunctions* functions,
28                                                            BackendValidationLevel validationLevel,
29                                                            bool beginCaptureOnStartup) {
30             ComPtr<IDXGIFactory4> factory;
31 
32             uint32_t dxgiFactoryFlags = 0;
33 
34             // Enable the debug layer (requires the Graphics Tools "optional feature").
35             {
36                 if (validationLevel != BackendValidationLevel::Disabled) {
37                     ComPtr<ID3D12Debug3> debugController;
38                     if (SUCCEEDED(
39                             functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
40                         ASSERT(debugController != nullptr);
41                         debugController->EnableDebugLayer();
42                         if (validationLevel == BackendValidationLevel::Full) {
43                             debugController->SetEnableGPUBasedValidation(true);
44                         }
45 
46                         // Enable additional debug layers.
47                         dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
48                     }
49                 }
50 
51                 if (beginCaptureOnStartup) {
52                     ComPtr<IDXGraphicsAnalysis> graphicsAnalysis;
53                     if (functions->dxgiGetDebugInterface1 != nullptr &&
54                         SUCCEEDED(functions->dxgiGetDebugInterface1(
55                             0, IID_PPV_ARGS(&graphicsAnalysis)))) {
56                         graphicsAnalysis->BeginCapture();
57                     }
58                 }
59             }
60 
61             if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) {
62                 return DAWN_INTERNAL_ERROR("Failed to create a DXGI factory");
63             }
64 
65             ASSERT(factory != nullptr);
66             return std::move(factory);
67         }
68 
CreateAdapterFromIDXGIAdapter(Backend * backend,ComPtr<IDXGIAdapter> dxgiAdapter)69         ResultOrError<std::unique_ptr<AdapterBase>> CreateAdapterFromIDXGIAdapter(
70             Backend* backend,
71             ComPtr<IDXGIAdapter> dxgiAdapter) {
72             ComPtr<IDXGIAdapter3> dxgiAdapter3;
73             DAWN_TRY(CheckHRESULT(dxgiAdapter.As(&dxgiAdapter3), "DXGIAdapter retrieval"));
74             std::unique_ptr<Adapter> adapter =
75                 std::make_unique<Adapter>(backend, std::move(dxgiAdapter3));
76             DAWN_TRY(adapter->Initialize());
77 
78             return {std::move(adapter)};
79         }
80 
81     }  // anonymous namespace
82 
Backend(InstanceBase * instance)83     Backend::Backend(InstanceBase* instance)
84         : BackendConnection(instance, wgpu::BackendType::D3D12) {
85     }
86 
Initialize()87     MaybeError Backend::Initialize() {
88         mFunctions = std::make_unique<PlatformFunctions>();
89         DAWN_TRY(mFunctions->LoadFunctions());
90 
91         const auto instance = GetInstance();
92 
93         DAWN_TRY_ASSIGN(mFactory,
94                         CreateFactory(mFunctions.get(), instance->GetBackendValidationLevel(),
95                                       instance->IsBeginCaptureOnStartupEnabled()));
96 
97         return {};
98     }
99 
GetFactory() const100     ComPtr<IDXGIFactory4> Backend::GetFactory() const {
101         return mFactory;
102     }
103 
EnsureDxcLibrary()104     MaybeError Backend::EnsureDxcLibrary() {
105         if (mDxcLibrary == nullptr) {
106             DAWN_TRY(CheckHRESULT(
107                 mFunctions->dxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&mDxcLibrary)),
108                 "DXC create library"));
109             ASSERT(mDxcLibrary != nullptr);
110         }
111         return {};
112     }
113 
EnsureDxcCompiler()114     MaybeError Backend::EnsureDxcCompiler() {
115         if (mDxcCompiler == nullptr) {
116             DAWN_TRY(CheckHRESULT(
117                 mFunctions->dxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&mDxcCompiler)),
118                 "DXC create compiler"));
119             ASSERT(mDxcCompiler != nullptr);
120         }
121         return {};
122     }
123 
EnsureDxcValidator()124     MaybeError Backend::EnsureDxcValidator() {
125         if (mDxcValidator == nullptr) {
126             DAWN_TRY(CheckHRESULT(
127                 mFunctions->dxcCreateInstance(CLSID_DxcValidator, IID_PPV_ARGS(&mDxcValidator)),
128                 "DXC create validator"));
129             ASSERT(mDxcValidator != nullptr);
130         }
131         return {};
132     }
133 
GetDxcLibrary() const134     ComPtr<IDxcLibrary> Backend::GetDxcLibrary() const {
135         ASSERT(mDxcLibrary != nullptr);
136         return mDxcLibrary;
137     }
138 
GetDxcCompiler() const139     ComPtr<IDxcCompiler> Backend::GetDxcCompiler() const {
140         ASSERT(mDxcCompiler != nullptr);
141         return mDxcCompiler;
142     }
143 
GetDxcValidator() const144     ComPtr<IDxcValidator> Backend::GetDxcValidator() const {
145         ASSERT(mDxcValidator != nullptr);
146         return mDxcValidator;
147     }
148 
GetFunctions() const149     const PlatformFunctions* Backend::GetFunctions() const {
150         return mFunctions.get();
151     }
152 
DiscoverDefaultAdapters()153     std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
154         AdapterDiscoveryOptions options;
155         auto result = DiscoverAdapters(&options);
156         if (result.IsError()) {
157             GetInstance()->ConsumedError(result.AcquireError());
158             return {};
159         }
160         return result.AcquireSuccess();
161     }
162 
DiscoverAdapters(const AdapterDiscoveryOptionsBase * optionsBase)163     ResultOrError<std::vector<std::unique_ptr<AdapterBase>>> Backend::DiscoverAdapters(
164         const AdapterDiscoveryOptionsBase* optionsBase) {
165         ASSERT(optionsBase->backendType == WGPUBackendType_D3D12);
166         const AdapterDiscoveryOptions* options =
167             static_cast<const AdapterDiscoveryOptions*>(optionsBase);
168 
169         std::vector<std::unique_ptr<AdapterBase>> adapters;
170         if (options->dxgiAdapter != nullptr) {
171             // |dxgiAdapter| was provided. Discover just that adapter.
172             std::unique_ptr<AdapterBase> adapter;
173             DAWN_TRY_ASSIGN(adapter, CreateAdapterFromIDXGIAdapter(this, options->dxgiAdapter));
174             adapters.push_back(std::move(adapter));
175             return std::move(adapters);
176         }
177 
178         // Enumerate and discover all available adapters.
179         for (uint32_t adapterIndex = 0;; ++adapterIndex) {
180             ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
181             if (mFactory->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
182                 break;  // No more adapters to enumerate.
183             }
184 
185             ASSERT(dxgiAdapter != nullptr);
186             ResultOrError<std::unique_ptr<AdapterBase>> adapter =
187                 CreateAdapterFromIDXGIAdapter(this, dxgiAdapter);
188             if (adapter.IsError()) {
189                 GetInstance()->ConsumedError(adapter.AcquireError());
190                 continue;
191             }
192 
193             adapters.push_back(std::move(adapter.AcquireSuccess()));
194         }
195 
196         return adapters;
197     }
198 
Connect(InstanceBase * instance)199     BackendConnection* Connect(InstanceBase* instance) {
200         Backend* backend = new Backend(instance);
201 
202         if (instance->ConsumedError(backend->Initialize())) {
203             delete backend;
204             return nullptr;
205         }
206 
207         return backend;
208     }
209 
210 }}  // namespace dawn_native::d3d12
211