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