Progress on creating the d3d12 renderer
This commit is contained in:
@@ -70,7 +70,7 @@
|
|||||||
<SubSystem>
|
<SubSystem>
|
||||||
</SubSystem>
|
</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>ws2_32.lib;dxguid.lib;d3d12.lib;dxgi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ws2_32.lib;d3d12.lib;dxgi.lib;dxguid.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>
|
<AdditionalDependencies>
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>ws2_32.lib;dxguid.lib;d3d12.lib;dxgi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>ws2_32.lib;d3d12.lib;dxgi.lib;dxguid.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -14,6 +14,12 @@
|
|||||||
#define UNICODE
|
#define UNICODE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Only Supports Win10 and greater
|
||||||
|
#undef WINVER
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0A00
|
||||||
|
#define WINVER _WIN32_WINNT
|
||||||
|
|
||||||
#define NOIME
|
#define NOIME
|
||||||
#define NOWINRES
|
#define NOWINRES
|
||||||
#define NOGDICAPMASKS
|
#define NOGDICAPMASKS
|
||||||
|
|||||||
@@ -1,27 +1,43 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <core/Common/NonNullPtr.h>
|
||||||
|
#include <Core/Memory/Allocator.h>
|
||||||
|
#include <DX12Utils.h>
|
||||||
#include <Graphics/D3D12/DX12Includes.h>
|
#include <Graphics/D3D12/DX12Includes.h>
|
||||||
#include <Graphics/GraphicsDevice.h>
|
#include <Graphics/GraphicsDevice.h>
|
||||||
|
|
||||||
|
// TODO : Use LoadLibrary and not link to the lib. Allows failing earlier if Dx12 is not installed for some reason
|
||||||
|
// + Will load the dll when needed
|
||||||
|
// This will prevent us from using IID_ variables as they are defined in dxguid.lib
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
// TODO : Use LoadLibrary and not link to the lib. Allows failing earlier if Dx12 is not installed for some reason
|
struct D3D12Renderer : GPURenderer
|
||||||
// + Will load the dll when needed
|
{
|
||||||
// This will prevent us from using IID_ variables as they are defined in dxguid.lib
|
IDXGIFactory4* DXGIFactory;
|
||||||
|
IDXGIAdapter1* DXGIAdapter;
|
||||||
|
|
||||||
|
HMODULE DXGIDebug_DLL;
|
||||||
|
IDXGIDebug* DXGIDebug;
|
||||||
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
|
IDXGIInfoQueue* DXGIInfoQueue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool IsTearingSupported : 1;
|
||||||
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
// Note: This is the highest my Gfx Card supports (5700XT)
|
||||||
|
// https://en.wikipedia.org/wiki/Feature_levels_in_Direct3D#Direct3D_12
|
||||||
|
// 12_2 Adds RayTracing and others feature supported by RDNA2 and greater and Gefore 20xx and greater
|
||||||
|
constexpr D3D_FEATURE_LEVEL kD3DFeatureLevel = D3D_FEATURE_LEVEL_12_1;
|
||||||
|
constexpr auto kD3DFeatureLevelStr = "12_1";
|
||||||
|
|
||||||
bool CheckDriver()
|
bool CheckDriver()
|
||||||
{
|
{
|
||||||
HRESULT result;
|
|
||||||
// ID3D12Device *device;
|
|
||||||
IDXGIFactory4* factory4;
|
|
||||||
IDXGIFactory6* factory6;
|
|
||||||
IDXGIAdapter1* adapter;
|
|
||||||
|
|
||||||
ID3D12Object* test;
|
|
||||||
// Can create DXGI factory ?
|
// Can create DXGI factory ?
|
||||||
IDXGIFactory1* factory1 = nullptr;
|
IDXGIFactory1* factory1 = nullptr;
|
||||||
result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
HRESULT result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Cannot create DXGIFactory1");
|
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Cannot create DXGIFactory1");
|
||||||
@@ -29,6 +45,7 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Can query the 1.4 factory ?
|
// Can query the 1.4 factory ?
|
||||||
|
IDXGIFactory4* factory4 = nullptr;
|
||||||
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&factory4));
|
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&factory4));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
@@ -37,14 +54,192 @@ namespace Juliet
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
IDXGIFactory4_Release(factory4);
|
IDXGIFactory4_Release(factory4);
|
||||||
|
|
||||||
|
// Check for 1.6. (It's not mandatory).
|
||||||
|
IDXGIAdapter1* adapter = nullptr;
|
||||||
|
IDXGIFactory6* factory6 = nullptr;
|
||||||
|
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory6, reinterpret_cast<void**>(&factory6));
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
result = IDXGIFactory6_EnumAdapterByGpuPreference(factory6, 0, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||||
|
IID_IDXGIAdapter1, reinterpret_cast<void**>(&adapter));
|
||||||
|
IDXGIFactory6_Release(factory6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = IDXGIFactory1_EnumAdapters1(factory1, 0, &adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Failed to find an adapter for D3D12.");
|
||||||
|
|
||||||
|
IDXGIFactory1_Release(factory1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D12Device* device = nullptr;
|
||||||
|
result = D3D12CreateDevice(reinterpret_cast<IUnknown*>(adapter), kD3DFeatureLevel, IID_ID3D12Device,
|
||||||
|
reinterpret_cast<void**>(&device));
|
||||||
|
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
ID3D12Device_Release(device);
|
||||||
|
}
|
||||||
|
IDXGIAdapter1_Release(adapter);
|
||||||
IDXGIFactory1_Release(factory1);
|
IDXGIFactory1_Release(factory1);
|
||||||
|
|
||||||
return false;
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Warning, LogCategory::Graphics,
|
||||||
|
"DX12: Failed to create a D3D12Device with feature level %s.", kD3DFeatureLevelStr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
|
void InitializeDebugLayer(NonNullPtr<D3D12Renderer> renderer)
|
||||||
|
{
|
||||||
|
// See https://github.com/microsoft/DirectX-Graphics-Samples/blob/7aa24663f26e547a5bc437db028dfcfdb4b3c8f3/TechniqueDemos/D3D12MemoryManagement/src/Framework.cpp#L957
|
||||||
|
// For win10 only we can just use dxgiGetDebugInterface1
|
||||||
|
using LPDXGIGETDEBUGINTERFACE = HRESULT(WINAPI*)(REFIID, void**);
|
||||||
|
|
||||||
|
renderer->DXGIDebug_DLL = LoadLibraryEx(L"dxgidebug.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||||
|
if (renderer->DXGIDebug_DLL)
|
||||||
|
{
|
||||||
|
auto dxgiGetDebugInterface = reinterpret_cast<LPDXGIGETDEBUGINTERFACE>(
|
||||||
|
reinterpret_cast<void*>(GetProcAddress(renderer->DXGIDebug_DLL, "DXGIGetDebugInterface")));
|
||||||
|
|
||||||
|
HRESULT result = DXGIGetDebugInterface1(0, IID_IDXGIDebug, (void**)&renderer->DXGIDebug);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Warning, LogCategory::Graphics, "Could not get IDXGIDebug interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dxgiGetDebugInterface(IID_IDXGIInfoQueue, (void**)&renderer->DXGIInfoQueue);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
Log(LogLevel::Warning, LogCategory::Graphics, "Could not get IDXGIInfoQueue interface");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IDXGIInfoQueue_SetBreakOnSeverity(renderer->DXGIInfoQueue, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
|
IDXGIInfoQueue_SetBreakOnSeverity(renderer->DXGIInfoQueue, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||||
|
IDXGIInfoQueue_SetBreakOnSeverity(renderer->DXGIInfoQueue, DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownDebugLayer(NonNullPtr<D3D12Renderer> renderer)
|
||||||
|
{
|
||||||
|
if (renderer->DXGIDebug)
|
||||||
|
{
|
||||||
|
IDXGIDebug_ReportLiveObjects(renderer->DXGIDebug, DXGI_DEBUG_ALL,
|
||||||
|
static_cast<DXGI_DEBUG_RLO_FLAGS>(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
|
||||||
|
IDXGIDebug_Release(renderer->DXGIDebug);
|
||||||
|
renderer->DXGIDebug = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer->DXGIDebug_DLL) {
|
||||||
|
FreeLibrary(renderer->DXGIDebug_DLL);
|
||||||
|
renderer->DXGIDebug_DLL = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void DestroyRenderer_Internal(NonNullPtr<D3D12Renderer> renderer)
|
||||||
|
{
|
||||||
|
ShutdownDebugLayer(renderer);
|
||||||
|
Free(renderer.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device)
|
||||||
|
{
|
||||||
|
auto* renderer = reinterpret_cast<D3D12Renderer*>(device.Get());
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Free(device.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsDevice* CreateGraphicsDevice()
|
GraphicsDevice* CreateGraphicsDevice()
|
||||||
{
|
{
|
||||||
return nullptr;
|
auto renderer = static_cast<D3D12Renderer*>(Calloc(1, sizeof(D3D12Renderer)));
|
||||||
|
|
||||||
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
|
static const bool kDebug = true;
|
||||||
|
if (kDebug)
|
||||||
|
{
|
||||||
|
InitializeDebugLayer(renderer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IDXGIFactory1* factory1 = nullptr;
|
||||||
|
HRESULT result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Assert(false && "DX12: Cannot create DXGIFactory1");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&renderer->DXGIFactory));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Assert(false && "DX12: Cannot create DXGIFactory4. Need DXGI1.4 support. Weird because it has been "
|
||||||
|
"checked in CheckDriver");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
IDXGIFactory1_Release(factory1);
|
||||||
|
|
||||||
|
// Query DXGI1.5 and check for monitor Tearing support
|
||||||
|
IDXGIFactory5* factory5 = nullptr;
|
||||||
|
result = IDXGIFactory4_QueryInterface(renderer->DXGIFactory, IID_IDXGIFactory5, reinterpret_cast<void**>(&factory5));
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
bool isTearingSupported = false;
|
||||||
|
result = IDXGIFactory5_CheckFeatureSupport(factory5, DXGI_FEATURE_PRESENT_ALLOW_TEARING,
|
||||||
|
&isTearingSupported, sizeof(isTearingSupported));
|
||||||
|
renderer->IsTearingSupported = isTearingSupported;
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
renderer->IsTearingSupported = false;
|
||||||
|
}
|
||||||
|
IDXGIFactory1_Release(factory5);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDXGIFactory6* factory6 = nullptr;
|
||||||
|
result = IDXGIFactory4_QueryInterface(renderer->DXGIFactory, IID_IDXGIFactory6, (void**)&factory6);
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
// TODO: Put into the config
|
||||||
|
const static bool useHighPerfFirst = true;
|
||||||
|
result = IDXGIFactory6_EnumAdapterByGpuPreference(factory6, 0,
|
||||||
|
useHighPerfFirst ? DXGI_GPU_PREFERENCE_MINIMUM_POWER
|
||||||
|
: DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||||
|
IID_IDXGIAdapter1, (void**)&renderer->DXGIAdapter);
|
||||||
|
IDXGIFactory6_Release(factory6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = IDXGIFactory4_EnumAdapters1(renderer->DXGIFactory, 0, &renderer->DXGIAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Assert(false && "Could not find adapter for D3D12Device");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
||||||
|
device->DestroyDevice = DestroyGraphicsDevice;
|
||||||
|
device->Renderer = renderer;
|
||||||
|
|
||||||
|
return device;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
#include "d3d12.h"
|
#include "d3d12.h"
|
||||||
#include <DirectXMath.h>
|
#include <DirectXMath.h>
|
||||||
|
#include <dxgi1_5.h>
|
||||||
#include <dxgi1_6.h>
|
#include <dxgi1_6.h>
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@@ -21,3 +22,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <dxgi.h>
|
#include <dxgi.h>
|
||||||
|
|
||||||
|
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
|
||||||
|
#define IDXGIINFOQUEUE_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -8,4 +8,12 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
Assert(!!FAILED(hr));
|
Assert(!!FAILED(hr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void CheckFailure(HRESULT hr)
|
||||||
|
{
|
||||||
|
switch (hr)
|
||||||
|
{
|
||||||
|
case E_POINTER: Assert(false && "Invalid Pointer");
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace Juliet::RHI::DX12
|
} // namespace Juliet::RHI::DX12
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Graphics/GraphicsConfig.h>
|
#include <Graphics/GraphicsConfig.h>
|
||||||
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
|
struct GPURenderer
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
struct GraphicsDevice
|
struct GraphicsDevice
|
||||||
{
|
{
|
||||||
const char* Name = "Unknown";
|
void (*DestroyDevice)(NonNullPtr<GraphicsDevice> self);
|
||||||
|
|
||||||
|
const char* Name = "Unknown";
|
||||||
|
GPURenderer* Renderer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsDeviceFactory
|
struct GraphicsDeviceFactory
|
||||||
{
|
{
|
||||||
const char* Name = "Unknown";
|
const char* Name = "Unknown";
|
||||||
RendererType Type = RendererType::Any;
|
RendererType Type = RendererType::Any;
|
||||||
bool (*CheckDriver)(void);
|
bool (*CheckDriver)(void);
|
||||||
GraphicsDevice* (*CreateGraphicsDevice)(void);
|
GraphicsDevice* (*CreateGraphicsDevice)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GraphicsDeviceFactory DX12DeviceFactory;
|
extern GraphicsDeviceFactory DX12DeviceFactory;
|
||||||
}
|
} // namespace Juliet
|
||||||
|
|||||||
Reference in New Issue
Block a user