// Copyright 2019 The Dawn 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 "dawn_native/d3d12/BackendD3D12.h" #include "dawn_native/D3D12Backend.h" #include "dawn_native/Instance.h" #include "dawn_native/d3d12/AdapterD3D12.h" #include "dawn_native/d3d12/D3D12Error.h" #include "dawn_native/d3d12/PlatformFunctions.h" namespace dawn_native { namespace d3d12 { namespace { ResultOrError> CreateFactory(const PlatformFunctions* functions, BackendValidationLevel validationLevel, bool beginCaptureOnStartup) { ComPtr factory; uint32_t dxgiFactoryFlags = 0; // Enable the debug layer (requires the Graphics Tools "optional feature"). { if (validationLevel != BackendValidationLevel::Disabled) { ComPtr debugController; if (SUCCEEDED( functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { ASSERT(debugController != nullptr); debugController->EnableDebugLayer(); if (validationLevel == BackendValidationLevel::Full) { debugController->SetEnableGPUBasedValidation(true); } // Enable additional debug layers. dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; } } if (beginCaptureOnStartup) { ComPtr graphicsAnalysis; if (functions->dxgiGetDebugInterface1 != nullptr && SUCCEEDED(functions->dxgiGetDebugInterface1( 0, IID_PPV_ARGS(&graphicsAnalysis)))) { graphicsAnalysis->BeginCapture(); } } } if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) { return DAWN_INTERNAL_ERROR("Failed to create a DXGI factory"); } ASSERT(factory != nullptr); return std::move(factory); } ResultOrError> CreateAdapterFromIDXGIAdapter( Backend* backend, ComPtr dxgiAdapter) { ComPtr dxgiAdapter3; DAWN_TRY(CheckHRESULT(dxgiAdapter.As(&dxgiAdapter3), "DXGIAdapter retrieval")); std::unique_ptr adapter = std::make_unique(backend, std::move(dxgiAdapter3)); DAWN_TRY(adapter->Initialize()); return {std::move(adapter)}; } } // anonymous namespace Backend::Backend(InstanceBase* instance) : BackendConnection(instance, wgpu::BackendType::D3D12) { } MaybeError Backend::Initialize() { mFunctions = std::make_unique(); DAWN_TRY(mFunctions->LoadFunctions()); const auto instance = GetInstance(); DAWN_TRY_ASSIGN(mFactory, CreateFactory(mFunctions.get(), instance->GetBackendValidationLevel(), instance->IsBeginCaptureOnStartupEnabled())); return {}; } ComPtr Backend::GetFactory() const { return mFactory; } MaybeError Backend::EnsureDxcLibrary() { if (mDxcLibrary == nullptr) { DAWN_TRY(CheckHRESULT( mFunctions->dxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&mDxcLibrary)), "DXC create library")); ASSERT(mDxcLibrary != nullptr); } return {}; } MaybeError Backend::EnsureDxcCompiler() { if (mDxcCompiler == nullptr) { DAWN_TRY(CheckHRESULT( mFunctions->dxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&mDxcCompiler)), "DXC create compiler")); ASSERT(mDxcCompiler != nullptr); } return {}; } MaybeError Backend::EnsureDxcValidator() { if (mDxcValidator == nullptr) { DAWN_TRY(CheckHRESULT( mFunctions->dxcCreateInstance(CLSID_DxcValidator, IID_PPV_ARGS(&mDxcValidator)), "DXC create validator")); ASSERT(mDxcValidator != nullptr); } return {}; } ComPtr Backend::GetDxcLibrary() const { ASSERT(mDxcLibrary != nullptr); return mDxcLibrary; } ComPtr Backend::GetDxcCompiler() const { ASSERT(mDxcCompiler != nullptr); return mDxcCompiler; } ComPtr Backend::GetDxcValidator() const { ASSERT(mDxcValidator != nullptr); return mDxcValidator; } const PlatformFunctions* Backend::GetFunctions() const { return mFunctions.get(); } std::vector> Backend::DiscoverDefaultAdapters() { std::vector> adapters; for (uint32_t adapterIndex = 0;; ++adapterIndex) { ComPtr dxgiAdapter = nullptr; if (mFactory->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) { break; // No more adapters to enumerate. } ASSERT(dxgiAdapter != nullptr); ResultOrError> adapter = CreateAdapterFromIDXGIAdapter(this, dxgiAdapter); if (adapter.IsError()) { GetInstance()->ConsumedError(adapter.AcquireError()); continue; } adapters.push_back(std::move(adapter.AcquireSuccess())); } return adapters; } ResultOrError>> Backend::DiscoverAdapters( const AdapterDiscoveryOptionsBase* optionsBase) { ASSERT(optionsBase->backendType == WGPUBackendType_D3D12); const AdapterDiscoveryOptions* options = static_cast(optionsBase); ASSERT(options->dxgiAdapter != nullptr); std::unique_ptr adapter; DAWN_TRY_ASSIGN(adapter, CreateAdapterFromIDXGIAdapter(this, options->dxgiAdapter)); std::vector> adapters; adapters.push_back(std::move(adapter)); return std::move(adapters); } BackendConnection* Connect(InstanceBase* instance) { Backend* backend = new Backend(instance); if (instance->ConsumedError(backend->Initialize())) { delete backend; return nullptr; } return backend; } }} // namespace dawn_native::d3d12