D3D12: Dynamically load D3D12, DXGI and D3DCompiler
Linking against their .lib makes loading Dawn fail on systems that don't have the DLLs. This happens for example on Windows7 that doesn't have d3d12.dll. Instead we dynamically load functions pointers from these DLLs at d3d12::Device startup. Change-Id: I4d01a12d0f91bec45bf125450d2c08aaa9ff9fac
This commit is contained in:
parent
748a5d5b28
commit
d8597b2e1f
9
BUILD.gn
9
BUILD.gn
|
@ -389,12 +389,7 @@ source_set("libdawn_native_sources") {
|
|||
]
|
||||
|
||||
if (dawn_enable_d3d12) {
|
||||
libs += [
|
||||
"d3d12.lib",
|
||||
"dxgi.lib",
|
||||
"dxguid.lib",
|
||||
"d3dcompiler.lib",
|
||||
]
|
||||
libs += [ "dxguid.lib" ]
|
||||
sources += [
|
||||
"src/dawn_native/d3d12/BindGroupD3D12.cpp",
|
||||
"src/dawn_native/d3d12/BindGroupD3D12.h",
|
||||
|
@ -423,6 +418,8 @@ source_set("libdawn_native_sources") {
|
|||
"src/dawn_native/d3d12/NativeSwapChainImplD3D12.h",
|
||||
"src/dawn_native/d3d12/PipelineLayoutD3D12.cpp",
|
||||
"src/dawn_native/d3d12/PipelineLayoutD3D12.h",
|
||||
"src/dawn_native/d3d12/PlatformFunctions.cpp",
|
||||
"src/dawn_native/d3d12/PlatformFunctions.h",
|
||||
"src/dawn_native/d3d12/QueueD3D12.cpp",
|
||||
"src/dawn_native/d3d12/QueueD3D12.h",
|
||||
"src/dawn_native/d3d12/RenderPassDescriptorD3D12.cpp",
|
||||
|
|
|
@ -225,6 +225,8 @@ if (DAWN_ENABLE_D3D12)
|
|||
${D3D12_DIR}/NativeSwapChainImplD3D12.h
|
||||
${D3D12_DIR}/PipelineLayoutD3D12.cpp
|
||||
${D3D12_DIR}/PipelineLayoutD3D12.h
|
||||
${D3D12_DIR}/PlatformFunctions.cpp
|
||||
${D3D12_DIR}/PlatformFunctions.h
|
||||
${D3D12_DIR}/QueueD3D12.cpp
|
||||
${D3D12_DIR}/QueueD3D12.h
|
||||
${D3D12_DIR}/RenderPassDescriptorD3D12.cpp
|
||||
|
|
|
@ -17,10 +17,9 @@
|
|||
#include "common/Assert.h"
|
||||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
|
||||
#include "dawn_native/d3d12/PlatformFunctions.h"
|
||||
#include "dawn_native/d3d12/ShaderModuleD3D12.h"
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
||||
ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
|
||||
|
@ -40,9 +39,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
ComPtr<ID3DBlob> compiledShader;
|
||||
ComPtr<ID3DBlob> errors;
|
||||
|
||||
if (FAILED(D3DCompile(hlslSource.c_str(), hlslSource.length(), nullptr, nullptr, nullptr,
|
||||
entryPoint.c_str(), "cs_5_1", compileFlags, 0, &compiledShader,
|
||||
&errors))) {
|
||||
const PlatformFunctions* functions = ToBackend(builder->GetDevice())->GetFunctions();
|
||||
if (FAILED(functions->d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr, nullptr,
|
||||
nullptr, entryPoint.c_str(), "cs_5_1", compileFlags, 0,
|
||||
&compiledShader, &errors))) {
|
||||
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
|
||||
ASSERT(false);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "dawn_native/d3d12/InputStateD3D12.h"
|
||||
#include "dawn_native/d3d12/NativeSwapChainImplD3D12.h"
|
||||
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
|
||||
#include "dawn_native/d3d12/PlatformFunctions.h"
|
||||
#include "dawn_native/d3d12/QueueD3D12.h"
|
||||
#include "dawn_native/d3d12/RenderPassDescriptorD3D12.h"
|
||||
#include "dawn_native/d3d12/RenderPipelineD3D12.h"
|
||||
|
@ -66,7 +67,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
|
||||
namespace {
|
||||
ComPtr<IDXGIFactory4> CreateFactory() {
|
||||
ComPtr<IDXGIFactory4> CreateFactory(const PlatformFunctions* functions) {
|
||||
ComPtr<IDXGIFactory4> factory;
|
||||
|
||||
uint32_t dxgiFactoryFlags = 0;
|
||||
|
@ -74,7 +75,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
// Enable the debug layer (requires the Graphics Tools "optional feature").
|
||||
{
|
||||
ComPtr<ID3D12Debug> debugController;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
if (SUCCEEDED(functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
debugController->EnableDebugLayer();
|
||||
|
||||
// Enable additional debug layers.
|
||||
|
@ -82,18 +83,19 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
|
||||
ComPtr<IDXGIDebug1> dxgiDebug;
|
||||
if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) {
|
||||
if (SUCCEEDED(functions->dxgiGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) {
|
||||
dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL,
|
||||
DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL));
|
||||
}
|
||||
}
|
||||
#endif // defined(DAWN_ENABLE_ASSERTS)
|
||||
|
||||
ASSERT_SUCCESS(CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
|
||||
ASSERT_SUCCESS(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
|
||||
return factory;
|
||||
}
|
||||
|
||||
ComPtr<IDXGIAdapter1> GetHardwareAdapter(ComPtr<IDXGIFactory4> factory) {
|
||||
ComPtr<IDXGIAdapter1> GetHardwareAdapter(ComPtr<IDXGIFactory4> factory,
|
||||
const PlatformFunctions* functions) {
|
||||
for (uint32_t adapterIndex = 0;; ++adapterIndex) {
|
||||
IDXGIAdapter1* adapter = nullptr;
|
||||
if (factory->EnumAdapters1(adapterIndex, &adapter) == DXGI_ERROR_NOT_FOUND) {
|
||||
|
@ -102,8 +104,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the actual
|
||||
// device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
|
||||
_uuidof(ID3D12Device), nullptr))) {
|
||||
if (SUCCEEDED(functions->d3d12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
|
||||
_uuidof(ID3D12Device), nullptr))) {
|
||||
return adapter;
|
||||
}
|
||||
adapter->Release();
|
||||
|
@ -114,15 +116,22 @@ namespace dawn_native { namespace d3d12 {
|
|||
} // anonymous namespace
|
||||
|
||||
Device::Device() {
|
||||
mFunctions = new PlatformFunctions();
|
||||
|
||||
{
|
||||
MaybeError status = mFunctions->LoadFunctions();
|
||||
ASSERT(status.IsSuccess());
|
||||
}
|
||||
|
||||
// Create the connection to DXGI and the D3D12 device
|
||||
mFactory = CreateFactory();
|
||||
mFactory = CreateFactory(mFunctions);
|
||||
ASSERT(mFactory.Get() != nullptr);
|
||||
|
||||
mHardwareAdapter = GetHardwareAdapter(mFactory);
|
||||
mHardwareAdapter = GetHardwareAdapter(mFactory, mFunctions);
|
||||
ASSERT(mHardwareAdapter.Get() != nullptr);
|
||||
|
||||
ASSERT_SUCCESS(D3D12CreateDevice(mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&mD3d12Device)));
|
||||
ASSERT_SUCCESS(mFunctions->d3d12CreateDevice(mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&mD3d12Device)));
|
||||
|
||||
// Create device-global objects
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
|
@ -157,6 +166,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
delete mMapRequestTracker;
|
||||
delete mResourceAllocator;
|
||||
delete mResourceUploader;
|
||||
delete mFunctions;
|
||||
}
|
||||
|
||||
ComPtr<IDXGIFactory4> Device::GetFactory() {
|
||||
|
@ -175,6 +185,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
return mDescriptorHeapAllocator;
|
||||
}
|
||||
|
||||
const PlatformFunctions* Device::GetFunctions() {
|
||||
return mFunctions;
|
||||
}
|
||||
|
||||
MapRequestTracker* Device::GetMapRequestTracker() const {
|
||||
return mMapRequestTracker;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
class CommandAllocatorManager;
|
||||
class DescriptorHeapAllocator;
|
||||
class MapRequestTracker;
|
||||
class PlatformFunctions;
|
||||
class ResourceAllocator;
|
||||
class ResourceUploader;
|
||||
|
||||
|
@ -59,6 +60,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
DescriptorHeapAllocator* GetDescriptorHeapAllocator();
|
||||
MapRequestTracker* GetMapRequestTracker() const;
|
||||
const PlatformFunctions* GetFunctions();
|
||||
ResourceAllocator* GetResourceAllocator();
|
||||
ResourceUploader* GetResourceUploader();
|
||||
|
||||
|
@ -97,6 +99,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
CommandAllocatorManager* mCommandAllocatorManager = nullptr;
|
||||
DescriptorHeapAllocator* mDescriptorHeapAllocator = nullptr;
|
||||
MapRequestTracker* mMapRequestTracker = nullptr;
|
||||
PlatformFunctions* mFunctions = nullptr;
|
||||
ResourceAllocator* mResourceAllocator = nullptr;
|
||||
ResourceUploader* mResourceUploader = nullptr;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "common/BitSetIterator.h"
|
||||
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
|
||||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||
#include "dawn_native/d3d12/PlatformFunctions.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
|
@ -92,7 +93,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
ComPtr<ID3DBlob> signature;
|
||||
ComPtr<ID3DBlob> error;
|
||||
ASSERT_SUCCESS(D3D12SerializeRootSignature(
|
||||
ASSERT_SUCCESS(device->GetFunctions()->d3d12SerializeRootSignature(
|
||||
&rootSignatureDescriptor, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
|
||||
ASSERT_SUCCESS(device->GetD3D12Device()->CreateRootSignature(
|
||||
0, signature->GetBufferPointer(), signature->GetBufferSize(),
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2018 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/PlatformFunctions.h"
|
||||
|
||||
#include "common/DynamicLib.h"
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
||||
PlatformFunctions::PlatformFunctions() {
|
||||
}
|
||||
PlatformFunctions::~PlatformFunctions() {
|
||||
}
|
||||
|
||||
MaybeError PlatformFunctions::LoadFunctions() {
|
||||
DAWN_TRY(LoadD3D12());
|
||||
DAWN_TRY(LoadDXGI());
|
||||
DAWN_TRY(LoadD3DCompiler());
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError PlatformFunctions::LoadD3D12() {
|
||||
std::string error;
|
||||
if (!mD3D12Lib.Open("d3d12.dll", &error) ||
|
||||
!mD3D12Lib.GetProc(&d3d12CreateDevice, "D3D12CreateDevice", &error) ||
|
||||
!mD3D12Lib.GetProc(&d3d12GetDebugInterface, "D3D12GetDebugInterface", &error) ||
|
||||
!mD3D12Lib.GetProc(&d3d12SerializeRootSignature, "D3D12SerializeRootSignature",
|
||||
&error) ||
|
||||
!mD3D12Lib.GetProc(&d3d12CreateRootSignatureDeserializer,
|
||||
"D3D12CreateRootSignatureDeserializer", &error) ||
|
||||
!mD3D12Lib.GetProc(&d3d12SerializeVersionedRootSignature,
|
||||
"D3D12SerializeVersionedRootSignature", &error) ||
|
||||
!mD3D12Lib.GetProc(&d3d12CreateVersionedRootSignatureDeserializer,
|
||||
"D3D12CreateVersionedRootSignatureDeserializer", &error)) {
|
||||
DAWN_RETURN_ERROR(error.c_str());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError PlatformFunctions::LoadDXGI() {
|
||||
std::string error;
|
||||
if (!mDXGILib.Open("dxgi.dll", &error) ||
|
||||
!mDXGILib.GetProc(&dxgiGetDebugInterface1, "DXGIGetDebugInterface1", &error) ||
|
||||
!mDXGILib.GetProc(&createDxgiFactory2, "CreateDXGIFactory2", &error)) {
|
||||
DAWN_RETURN_ERROR(error.c_str());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
MaybeError PlatformFunctions::LoadD3DCompiler() {
|
||||
std::string error;
|
||||
if (!mD3DCompilerLib.Open("d3dcompiler_47.dll", &error) ||
|
||||
!mD3DCompilerLib.GetProc(&d3dCompile, "D3DCompile", &error)) {
|
||||
DAWN_RETURN_ERROR(error.c_str());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
#ifndef DAWNNATIVE_D3D12_PLATFORMFUNCTIONS_H_
|
||||
#define DAWNNATIVE_D3D12_PLATFORMFUNCTIONS_H_
|
||||
|
||||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
|
||||
#include "common/DynamicLib.h"
|
||||
#include "dawn_native/Error.h"
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
class DynamicLib;
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
||||
// Loads the functions required from the platform dynamically so that we don't need to rely on
|
||||
// them being present in the system. For example linking against d3d12.lib would prevent
|
||||
// dawn_native from loading on Windows 7 system where d3d12.dll doesn't exist.
|
||||
class PlatformFunctions {
|
||||
public:
|
||||
PlatformFunctions();
|
||||
~PlatformFunctions();
|
||||
|
||||
MaybeError LoadFunctions();
|
||||
|
||||
// Functions from d3d12.dll
|
||||
PFN_D3D12_CREATE_DEVICE d3d12CreateDevice = nullptr;
|
||||
PFN_D3D12_GET_DEBUG_INTERFACE d3d12GetDebugInterface = nullptr;
|
||||
|
||||
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d12SerializeRootSignature = nullptr;
|
||||
PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER d3d12CreateRootSignatureDeserializer = nullptr;
|
||||
PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d12SerializeVersionedRootSignature = nullptr;
|
||||
PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER
|
||||
d3d12CreateVersionedRootSignatureDeserializer = nullptr;
|
||||
|
||||
// Functions from dxgi.dll
|
||||
using PFN_DXGI_GET_DEBUG_INTERFACE1 = HRESULT(WINAPI*)(UINT Flags,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void** pDebug);
|
||||
PFN_DXGI_GET_DEBUG_INTERFACE1 dxgiGetDebugInterface1 = nullptr;
|
||||
|
||||
using PFN_CREATE_DXGI_FACTORY2 = HRESULT(WINAPI*)(UINT Flags,
|
||||
REFIID riid,
|
||||
_COM_Outptr_ void** ppFactory);
|
||||
PFN_CREATE_DXGI_FACTORY2 createDxgiFactory2 = nullptr;
|
||||
|
||||
// Functions from d3d3compiler.dll
|
||||
pD3DCompile d3dCompile = nullptr;
|
||||
|
||||
private:
|
||||
MaybeError LoadD3D12();
|
||||
MaybeError LoadDXGI();
|
||||
MaybeError LoadD3DCompiler();
|
||||
|
||||
DynamicLib mD3D12Lib;
|
||||
DynamicLib mDXGILib;
|
||||
DynamicLib mD3DCompilerLib;
|
||||
};
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
||||
#endif // DAWNNATIVE_VULKAN_VULKANFUNCTIONS_H_
|
|
@ -20,6 +20,7 @@
|
|||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||
#include "dawn_native/d3d12/InputStateD3D12.h"
|
||||
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
|
||||
#include "dawn_native/d3d12/PlatformFunctions.h"
|
||||
#include "dawn_native/d3d12/ShaderModuleD3D12.h"
|
||||
#include "dawn_native/d3d12/TextureD3D12.h"
|
||||
|
||||
|
@ -101,9 +102,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
break;
|
||||
}
|
||||
|
||||
if (FAILED(D3DCompile(hlslSource.c_str(), hlslSource.length(), nullptr, nullptr,
|
||||
nullptr, entryPoint.c_str(), compileTarget, compileFlags, 0,
|
||||
&compiledShader[stage], &errors))) {
|
||||
const PlatformFunctions* functions = ToBackend(builder->GetDevice())->GetFunctions();
|
||||
if (FAILED(functions->d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr,
|
||||
nullptr, nullptr, entryPoint.c_str(), compileTarget,
|
||||
compileFlags, 0, &compiledShader[stage], &errors))) {
|
||||
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
|
||||
ASSERT(false);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue