First iteration of dx12 command lists.
Doing nothing for now.
This commit is contained in:
@@ -151,7 +151,8 @@
|
|||||||
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h" />
|
<ClInclude Include="src\Core\HAL\Event\WindowEvent.h" />
|
||||||
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h" />
|
<ClInclude Include="src\Core\Networking\SocketPlatformImpl.h" />
|
||||||
<ClInclude Include="src\Core\HAL\Win32.h" />
|
<ClInclude Include="src\Core\HAL\Win32.h" />
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12CommandBuffer.h" />
|
<ClInclude Include="src\Graphics\D3D12\DX12CommandList.h" />
|
||||||
|
<ClInclude Include="src\Graphics\D3D12\DX12GraphicsDevice.h" />
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12Includes.h" />
|
<ClInclude Include="src\Graphics\D3D12\DX12Includes.h" />
|
||||||
<ClInclude Include="src\Graphics\D3D12\DX12Utils.h" />
|
<ClInclude Include="src\Graphics\D3D12\DX12Utils.h" />
|
||||||
<ClInclude Include="src\Graphics\GraphicsDevice.h" />
|
<ClInclude Include="src\Graphics\GraphicsDevice.h" />
|
||||||
@@ -231,7 +232,7 @@
|
|||||||
<ClCompile Include="src\Core\Networking\TcpSocket.cpp" />
|
<ClCompile Include="src\Core\Networking\TcpSocket.cpp" />
|
||||||
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp" />
|
<ClCompile Include="src\Core\Networking\Win32\Win32SocketPlatformImpl.cpp" />
|
||||||
<ClCompile Include="src\Engine\Engine.cpp" />
|
<ClCompile Include="src\Engine\Engine.cpp" />
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12CommandBuffer.cpp" />
|
<ClCompile Include="src\Graphics\D3D12\DX12CommandList.cpp" />
|
||||||
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp" />
|
<ClCompile Include="src\Graphics\D3D12\DX12GraphicsDevice.cpp" />
|
||||||
<ClCompile Include="src\Graphics\Graphics.cpp">
|
<ClCompile Include="src\Graphics\Graphics.cpp">
|
||||||
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ namespace Juliet
|
|||||||
// Parameters of an INDEXED indirect draw command
|
// Parameters of an INDEXED indirect draw command
|
||||||
struct IndexedIndirectDrawCommand
|
struct IndexedIndirectDrawCommand
|
||||||
{
|
{
|
||||||
uint32 VertexCount; // Number of vertices to draw
|
uint32 VertexCount; // Number of vertices to draw
|
||||||
uint32 InstanceCount; // Number of instanced to draw
|
uint32 InstanceCount; // Number of instanced to draw
|
||||||
uint32 FirstIndex; // Base Index within the index buffer
|
uint32 FirstIndex; // Base Index within the index buffer
|
||||||
int32 VertexOffset; // Offset the vertex index into the buffer
|
int32 VertexOffset; // Offset the vertex index into the buffer
|
||||||
uint32 FirstInstance; // ID of the first instance to draw
|
uint32 FirstInstance; // ID of the first instance to draw
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameters of an INDEXED Indirect Dispatch Command
|
// Parameters of an INDEXED Indirect Dispatch Command
|
||||||
struct IndirectDispatchCommand
|
struct IndirectDispatchCommand
|
||||||
{
|
{
|
||||||
uint32 X_WorkGroupCount; // Number of Workgroup to dispatch on dimension X
|
uint32 X_WorkGroupCount; // Number of Workgroup to dispatch on dimension X
|
||||||
@@ -36,6 +36,20 @@ namespace Juliet
|
|||||||
uint32 Z_WorkGroupCount; // Number of Workgroup to dispatch on dimension Z
|
uint32 Z_WorkGroupCount; // Number of Workgroup to dispatch on dimension Z
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class QueueType : uint8
|
||||||
|
{
|
||||||
|
Graphics = 0,
|
||||||
|
Compute,
|
||||||
|
Copy,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
// Opaque types
|
||||||
|
struct CommandList {};
|
||||||
|
|
||||||
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
||||||
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
||||||
|
|
||||||
|
extern JULIET_API CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType = QueueType::Graphics);
|
||||||
|
extern JULIET_API void SubmitCommandLists(NonNullPtr<GraphicsDevice> device);
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
enum class RendererType : uint8
|
enum class DriverType : uint8
|
||||||
{
|
{
|
||||||
Any = 0,
|
Any = 0,
|
||||||
DX12 = 1,
|
DX12 = 1,
|
||||||
@@ -10,6 +10,6 @@ namespace Juliet
|
|||||||
|
|
||||||
struct GraphicsConfig
|
struct GraphicsConfig
|
||||||
{
|
{
|
||||||
RendererType PreferredRenderer = RendererType::DX12;
|
DriverType PreferredDriver = DriverType::DX12;
|
||||||
};
|
};
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
129
Juliet/src/Graphics/D3D12/DX12CommandList.cpp
Normal file
129
Juliet/src/Graphics/D3D12/DX12CommandList.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Memory/Allocator.h>
|
||||||
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
|
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||||
|
|
||||||
|
namespace Juliet::D3D12
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool HasD3D12CommandList(NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||||
|
{
|
||||||
|
return commandList->CommandLists[ToUnderlying(queueType)] != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateD3D12CommandList(NonNullPtr<D3D12Driver> driver, NonNullPtr<D3D12CommandList> commandList, QueueType queueType)
|
||||||
|
{
|
||||||
|
HRESULT res = 0;
|
||||||
|
auto& queueDesc = driver->QueueDesc[ToUnderlying(queueType)];
|
||||||
|
for (auto& buffer : commandList->CommandAllocator)
|
||||||
|
{
|
||||||
|
res = ID3D12Device5_CreateCommandAllocator(driver->D3D12Device, queueDesc.Type, IID_ID3D12CommandAllocator,
|
||||||
|
reinterpret_cast<void**>(&buffer[ToUnderlying(queueType)]));
|
||||||
|
|
||||||
|
if (FAILED(res))
|
||||||
|
{
|
||||||
|
Assert(false && "Error not implemented: cannot create ID3D12CommandAllocator");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& commandListSlot = commandList->CommandLists[ToUnderlying(queueType)];
|
||||||
|
if (queueType == QueueType::Graphics || queueType == QueueType::Compute)
|
||||||
|
{
|
||||||
|
ID3D12GraphicsCommandList6* d3d12GraphicsCommandList = nullptr;
|
||||||
|
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
|
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||||
|
reinterpret_cast<void**>(&d3d12GraphicsCommandList));
|
||||||
|
if (FAILED(res))
|
||||||
|
{
|
||||||
|
Assert(false && "Error not implemented: cannot create ID3D12GraphicsCommandList6 (graphics or "
|
||||||
|
"compute command list");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12GraphicsCommandList);
|
||||||
|
}
|
||||||
|
else if (queueType == QueueType::Copy)
|
||||||
|
{
|
||||||
|
ID3D12GraphicsCommandList* d3d12CopyCommandList = nullptr;
|
||||||
|
res = ID3D12Device5_CreateCommandList1(driver->D3D12Device, queueDesc.NodeMask, queueDesc.Type,
|
||||||
|
D3D12_COMMAND_LIST_FLAG_NONE, IID_ID3D12GraphicsCommandList6,
|
||||||
|
reinterpret_cast<void**>(&d3d12CopyCommandList));
|
||||||
|
if (FAILED(res))
|
||||||
|
{
|
||||||
|
Assert(false &&
|
||||||
|
"Error not implemented: cannot create ID3D12GraphicsCommandList (copy command list)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
commandListSlot = reinterpret_cast<ID3D12CommandList*>(d3d12CopyCommandList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: String library
|
||||||
|
std::wstring wide_str = L"CommandList ID:" + std::to_wstring(commandList->ID);
|
||||||
|
ID3D12GraphicsCommandList_SetName(commandListSlot, wide_str.c_str());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AllocateCommandList(NonNullPtr<D3D12Driver> driver, QueueType queueType)
|
||||||
|
{
|
||||||
|
auto* commandList = static_cast<D3D12CommandList*>(Calloc(1, sizeof(D3D12CommandList)));
|
||||||
|
if (!commandList)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "Cannot allocate D3D12CommandList: Out of memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resizedArray = static_cast<D3D12CommandList**>(
|
||||||
|
Realloc(driver->AvailableCommandLists, sizeof(D3D12CommandList*) * (driver->AvailableCommandListCapacity + 1)));
|
||||||
|
|
||||||
|
if (!resizedArray)
|
||||||
|
{
|
||||||
|
Assert(false &&
|
||||||
|
"Error not implemented, out of memory, handle that by deallocating stuff and returning false");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver->AvailableCommandLists = resizedArray;
|
||||||
|
driver->AvailableCommandLists[driver->AvailableCommandListCapacity] = commandList;
|
||||||
|
commandList->ID = driver->AvailableCommandListCapacity;
|
||||||
|
driver->AvailableCommandListCapacity += 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType)
|
||||||
|
{
|
||||||
|
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
|
||||||
|
uint8 currentCommandListIndex = d3d12Driver->CommandListCount;
|
||||||
|
if (currentCommandListIndex >= d3d12Driver->AvailableCommandListCapacity)
|
||||||
|
{
|
||||||
|
if (!AllocateCommandList(d3d12Driver, queueType))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D3D12CommandList* commandList = d3d12Driver->AvailableCommandLists[currentCommandListIndex];
|
||||||
|
if (!HasD3D12CommandList(commandList, queueType))
|
||||||
|
{
|
||||||
|
if (!CreateD3D12CommandList(d3d12Driver, commandList, queueType))
|
||||||
|
{
|
||||||
|
// TODO Shoud destroy the command list here
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<CommandList*>(commandList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitCommandLists(NonNullPtr<GPUDriver> driver)
|
||||||
|
{
|
||||||
|
auto* d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
uint8 commandLastIndex = d3d12Driver->CommandListCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Juliet::D3D12
|
||||||
25
Juliet/src/Graphics/D3D12/DX12CommandList.h
Normal file
25
Juliet/src/Graphics/D3D12/DX12CommandList.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Common/EnumUtils.h>
|
||||||
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
#include <Graphics/D3D12/DX12Includes.h>
|
||||||
|
#include <Graphics/GraphicsDevice.h>
|
||||||
|
|
||||||
|
namespace Juliet::D3D12
|
||||||
|
{
|
||||||
|
struct D3D12Driver;
|
||||||
|
|
||||||
|
struct D3D12CommandList
|
||||||
|
{
|
||||||
|
D3D12Driver* Driver;
|
||||||
|
|
||||||
|
uint64 ID;
|
||||||
|
|
||||||
|
// We create kResourceBufferCount allocator per queue to allow reusing the command list every N frames
|
||||||
|
ID3D12CommandAllocator* CommandAllocator[GPUDriver::kResourceBufferCount][ToUnderlying(QueueType::Count)];
|
||||||
|
ID3D12CommandList* CommandLists[ToUnderlying(QueueType::Count)];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CommandList* AcquireCommandList(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
||||||
|
extern void SubmitCommandLists(NonNullPtr<GPUDriver> driver);
|
||||||
|
} // namespace Juliet::D3D12
|
||||||
@@ -3,55 +3,23 @@
|
|||||||
#include <core/Common/NonNullPtr.h>
|
#include <core/Common/NonNullPtr.h>
|
||||||
#include <Core/DynLib/DynamicLibrary.h>
|
#include <Core/DynLib/DynamicLibrary.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
#include <DX12Utils.h>
|
#include <Graphics/D3D12/DX12CommandList.h>
|
||||||
|
#include <Graphics/D3D12/DX12GraphicsDevice.h>
|
||||||
#include <Graphics/D3D12/DX12Includes.h>
|
#include <Graphics/D3D12/DX12Includes.h>
|
||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.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
|
|
||||||
{
|
|
||||||
#define D3D12_DLL "d3d12.dll"
|
#define D3D12_DLL "d3d12.dll"
|
||||||
#define D3D12_CREATEDEVICE_FUNC "D3D12CreateDevice"
|
#define D3D12_CREATEDEVICE_FUNC "D3D12CreateDevice"
|
||||||
#define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature"
|
#define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature"
|
||||||
#define DXGIDEBUG_DLL "dxgidebug.dll"
|
#define DXGIDEBUG_DLL "dxgidebug.dll"
|
||||||
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
|
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
|
||||||
|
|
||||||
struct D3D12Renderer : GPURenderer
|
// 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
|
||||||
GraphicsDevice* GraphicsDevice;
|
// This will prevent us from using IID_ variables as they are defined in dxguid.lib
|
||||||
|
namespace Juliet::D3D12
|
||||||
// D3D12
|
{
|
||||||
DynamicLibrary* D3D12DLL;
|
|
||||||
ID3D12Device* D3D12Device;
|
|
||||||
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFct;
|
|
||||||
ID3D12CommandQueue* CommandQueue;
|
|
||||||
|
|
||||||
// Indirect commands signature
|
|
||||||
ID3D12CommandSignature* IndirectDrawCommandSignature;
|
|
||||||
ID3D12CommandSignature* IndirectIndexedDrawCommandSignature;
|
|
||||||
ID3D12CommandSignature* IndirectDispatchCommandSignature;
|
|
||||||
|
|
||||||
// DXGI
|
|
||||||
IDXGIFactory4* DXGIFactory;
|
|
||||||
IDXGIAdapter1* DXGIAdapter;
|
|
||||||
DynamicLibrary* DXGIDebugDLL;
|
|
||||||
IDXGIDebug* DXGIDebug;
|
|
||||||
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
|
||||||
IDXGIInfoQueue* DXGIInfoQueue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool IsTearingSupported : 1;
|
|
||||||
|
|
||||||
// UMA
|
|
||||||
bool IsUMAAvailable : 1;
|
|
||||||
bool IsUMACacheCoherent : 1;
|
|
||||||
|
|
||||||
bool GPUUploadHeapSupported : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Note: This is the highest my Gfx Card supports (5700XT)
|
// Note: This is the highest my Gfx Card supports (5700XT)
|
||||||
@@ -128,7 +96,7 @@ namespace Juliet
|
|||||||
|
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
ID3D12Device_Release(device);
|
ID3D12Device5_Release(device);
|
||||||
}
|
}
|
||||||
IDXGIAdapter1_Release(adapter);
|
IDXGIAdapter1_Release(adapter);
|
||||||
IDXGIFactory1_Release(factory1);
|
IDXGIFactory1_Release(factory1);
|
||||||
@@ -144,129 +112,130 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
void InitializeDXGIDebug(NonNullPtr<D3D12Renderer> renderer)
|
void InitializeDXGIDebug(NonNullPtr<D3D12Driver> driver)
|
||||||
{
|
{
|
||||||
// See https://github.com/microsoft/DirectX-Graphics-Samples/blob/7aa24663f26e547a5bc437db028dfcfdb4b3c8f3/TechniqueDemos/D3D12MemoryManagement/src/Framework.cpp#L957
|
// See https://github.com/microsoft/DirectX-Graphics-Samples/blob/7aa24663f26e547a5bc437db028dfcfdb4b3c8f3/TechniqueDemos/D3D12MemoryManagement/src/Framework.cpp#L957
|
||||||
// For win10 only we can just use dxgiGetDebugInterface1
|
// For win10 only we can just use dxgiGetDebugInterface1
|
||||||
using LPDXGIGETDEBUGINTERFACE = HRESULT(WINAPI*)(REFIID, void**);
|
using LPDXGIGETDEBUGINTERFACE = HRESULT(WINAPI*)(REFIID, void**);
|
||||||
|
|
||||||
renderer->DXGIDebugDLL = LoadDynamicLibrary(DXGIDEBUG_DLL);
|
driver->DXGIDebugDLL = LoadDynamicLibrary(DXGIDEBUG_DLL);
|
||||||
if (renderer->DXGIDebugDLL)
|
if (driver->DXGIDebugDLL)
|
||||||
{
|
{
|
||||||
auto dxgiGetDebugInterface = reinterpret_cast<LPDXGIGETDEBUGINTERFACE>(
|
auto dxgiGetDebugInterface =
|
||||||
LoadFunction(renderer->DXGIDebugDLL, DXGI_GET_DEBUG_INTERFACE_FUNC));
|
reinterpret_cast<LPDXGIGETDEBUGINTERFACE>(LoadFunction(driver->DXGIDebugDLL, DXGI_GET_DEBUG_INTERFACE_FUNC));
|
||||||
HRESULT result = dxgiGetDebugInterface(IID_IDXGIDebug, (void**)&renderer->DXGIDebug);
|
HRESULT result = dxgiGetDebugInterface(IID_IDXGIDebug, (void**)&driver->DXGIDebug);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Warning, LogCategory::Graphics, "Could not get IDXGIDebug interface");
|
Log(LogLevel::Warning, LogCategory::Graphics, "Could not get IDXGIDebug interface");
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dxgiGetDebugInterface(IID_IDXGIInfoQueue, (void**)&renderer->DXGIInfoQueue);
|
result = dxgiGetDebugInterface(IID_IDXGIInfoQueue, (void**)&driver->DXGIInfoQueue);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
Log(LogLevel::Warning, LogCategory::Graphics, "Could not get IDXGIInfoQueue interface");
|
Log(LogLevel::Warning, LogCategory::Graphics, "Could not get IDXGIInfoQueue interface");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IDXGIInfoQueue_SetBreakOnSeverity(renderer->DXGIInfoQueue, DXGI_DEBUG_ALL,
|
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
|
||||||
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
IDXGIInfoQueue_SetBreakOnSeverity(renderer->DXGIInfoQueue, DXGI_DEBUG_ALL,
|
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
|
||||||
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||||
IDXGIInfoQueue_SetBreakOnSeverity(renderer->DXGIInfoQueue, DXGI_DEBUG_ALL,
|
IDXGIInfoQueue_SetBreakOnSeverity(driver->DXGIInfoQueue, DXGI_DEBUG_ALL,
|
||||||
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
|
DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownDXGIDebug(NonNullPtr<D3D12Renderer> renderer)
|
void ShutdownDXGIDebug(NonNullPtr<D3D12Driver> driver)
|
||||||
{
|
{
|
||||||
if (renderer->DXGIDebug)
|
if (driver->DXGIDebug)
|
||||||
{
|
{
|
||||||
IDXGIDebug_ReportLiveObjects(renderer->DXGIDebug, DXGI_DEBUG_ALL,
|
IDXGIDebug_ReportLiveObjects(driver->DXGIDebug, DXGI_DEBUG_ALL,
|
||||||
static_cast<DXGI_DEBUG_RLO_FLAGS>(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
|
static_cast<DXGI_DEBUG_RLO_FLAGS>(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
|
||||||
IDXGIDebug_Release(renderer->DXGIDebug);
|
IDXGIDebug_Release(driver->DXGIDebug);
|
||||||
renderer->DXGIDebug = nullptr;
|
driver->DXGIDebug = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer->DXGIDebugDLL)
|
if (driver->DXGIDebugDLL)
|
||||||
{
|
{
|
||||||
UnloadDynamicLibrary(renderer->DXGIDebugDLL);
|
UnloadDynamicLibrary(driver->DXGIDebugDLL);
|
||||||
renderer->DXGIDebugDLL = nullptr;
|
driver->DXGIDebugDLL = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void DestroyRenderer_Internal(NonNullPtr<D3D12Renderer> renderer)
|
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
|
||||||
{
|
{
|
||||||
if (renderer->IndirectDrawCommandSignature)
|
if (driver->IndirectDrawCommandSignature)
|
||||||
{
|
{
|
||||||
ID3D12CommandSignature_Release(renderer->IndirectDrawCommandSignature);
|
ID3D12CommandSignature_Release(driver->IndirectDrawCommandSignature);
|
||||||
renderer->IndirectDrawCommandSignature = nullptr;
|
driver->IndirectDrawCommandSignature = nullptr;
|
||||||
}
|
}
|
||||||
if (renderer->IndirectIndexedDrawCommandSignature)
|
if (driver->IndirectIndexedDrawCommandSignature)
|
||||||
{
|
{
|
||||||
ID3D12CommandSignature_Release(renderer->IndirectIndexedDrawCommandSignature);
|
ID3D12CommandSignature_Release(driver->IndirectIndexedDrawCommandSignature);
|
||||||
renderer->IndirectIndexedDrawCommandSignature = nullptr;
|
driver->IndirectIndexedDrawCommandSignature = nullptr;
|
||||||
}
|
}
|
||||||
if (renderer->IndirectDispatchCommandSignature)
|
if (driver->IndirectDispatchCommandSignature)
|
||||||
{
|
{
|
||||||
ID3D12CommandSignature_Release(renderer->IndirectDispatchCommandSignature);
|
ID3D12CommandSignature_Release(driver->IndirectDispatchCommandSignature);
|
||||||
renderer->IndirectDispatchCommandSignature = nullptr;
|
driver->IndirectDispatchCommandSignature = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer->CommandQueue)
|
if (driver->GraphicsQueue)
|
||||||
{
|
{
|
||||||
ID3D12CommandQueue_Release(renderer->CommandQueue);
|
ID3D12CommandQueue_Release(driver->GraphicsQueue);
|
||||||
renderer->CommandQueue = nullptr;
|
driver->GraphicsQueue = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer->D3D12Device)
|
if (driver->D3D12Device)
|
||||||
{
|
{
|
||||||
ID3D12Device_Release(renderer->D3D12Device);
|
ID3D12Device5_Release(driver->D3D12Device);
|
||||||
renderer->D3D12Device = nullptr;
|
driver->D3D12Device = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer->DXGIAdapter)
|
if (driver->DXGIAdapter)
|
||||||
{
|
{
|
||||||
IDXGIAdapter1_Release(renderer->DXGIAdapter);
|
IDXGIAdapter1_Release(driver->DXGIAdapter);
|
||||||
renderer->DXGIAdapter = nullptr;
|
driver->DXGIAdapter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer->DXGIFactory)
|
if (driver->DXGIFactory)
|
||||||
{
|
{
|
||||||
IDXGIFactory4_Release(renderer->DXGIFactory);
|
IDXGIFactory4_Release(driver->DXGIFactory);
|
||||||
renderer->DXGIFactory = nullptr;
|
driver->DXGIFactory = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShutdownDXGIDebug(renderer);
|
ShutdownDXGIDebug(driver);
|
||||||
|
|
||||||
if (renderer->D3D12DLL)
|
if (driver->D3D12DLL)
|
||||||
{
|
{
|
||||||
UnloadDynamicLibrary(renderer->D3D12DLL);
|
UnloadDynamicLibrary(driver->D3D12DLL);
|
||||||
renderer->D3D12DLL = nullptr;
|
driver->D3D12DLL = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->D3D12SerializeRootSignatureFct = nullptr;
|
driver->D3D12SerializeRootSignatureFct = nullptr;
|
||||||
|
|
||||||
Free(renderer.Get());
|
Free(driver.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device)
|
void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device)
|
||||||
{
|
{
|
||||||
auto* renderer = static_cast<D3D12Renderer*>(device->Renderer);
|
// Note: Its a down cast so clang suggest not to do it but we are totally sure about it.
|
||||||
DestroyRenderer_Internal(renderer);
|
auto* driver = static_cast<D3D12Driver*>(device->Driver);
|
||||||
|
DestroyDriver_Internal(driver);
|
||||||
Free(device.Get());
|
Free(device.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsDevice* CreateGraphicsDevice()
|
GraphicsDevice* CreateGraphicsDevice()
|
||||||
{
|
{
|
||||||
auto renderer = static_cast<D3D12Renderer*>(Calloc(1, sizeof(D3D12Renderer)));
|
auto driver = static_cast<D3D12Driver*>(Calloc(1, sizeof(D3D12Driver)));
|
||||||
|
|
||||||
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
static const bool kDebug = true;
|
static const bool kDebug = true;
|
||||||
if (kDebug)
|
if (kDebug)
|
||||||
{
|
{
|
||||||
InitializeDXGIDebug(renderer);
|
InitializeDXGIDebug(driver);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -274,15 +243,15 @@ namespace Juliet
|
|||||||
HRESULT result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
HRESULT result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Assert(false && "DX12: Cannot create DXGIFactory1");
|
Assert(false && "DX12: Cannot create DXGIFactory1");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&renderer->DXGIFactory));
|
result = IDXGIFactory1_QueryInterface(factory1, IID_IDXGIFactory4, reinterpret_cast<void**>(&driver->DXGIFactory));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Assert(false && "DX12: Cannot create DXGIFactory4. Need DXGI1.4 support. Weird because it has been "
|
Assert(false && "DX12: Cannot create DXGIFactory4. Need DXGI1.4 support. Weird because it has been "
|
||||||
"checked in CheckDriver");
|
"checked in CheckDriver");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -291,16 +260,16 @@ namespace Juliet
|
|||||||
|
|
||||||
// Query DXGI1.5 and check for monitor Tearing support
|
// Query DXGI1.5 and check for monitor Tearing support
|
||||||
IDXGIFactory5* factory5 = nullptr;
|
IDXGIFactory5* factory5 = nullptr;
|
||||||
result = IDXGIFactory4_QueryInterface(renderer->DXGIFactory, IID_IDXGIFactory5, reinterpret_cast<void**>(&factory5));
|
result = IDXGIFactory4_QueryInterface(driver->DXGIFactory, IID_IDXGIFactory5, reinterpret_cast<void**>(&factory5));
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
bool isTearingSupported = false;
|
bool isTearingSupported = false;
|
||||||
result = IDXGIFactory5_CheckFeatureSupport(factory5, DXGI_FEATURE_PRESENT_ALLOW_TEARING,
|
result = IDXGIFactory5_CheckFeatureSupport(factory5, DXGI_FEATURE_PRESENT_ALLOW_TEARING,
|
||||||
&isTearingSupported, sizeof(isTearingSupported));
|
&isTearingSupported, sizeof(isTearingSupported));
|
||||||
renderer->IsTearingSupported = isTearingSupported;
|
driver->IsTearingSupported = isTearingSupported;
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
renderer->IsTearingSupported = false;
|
driver->IsTearingSupported = false;
|
||||||
}
|
}
|
||||||
IDXGIFactory5_Release(factory5);
|
IDXGIFactory5_Release(factory5);
|
||||||
}
|
}
|
||||||
@@ -309,7 +278,7 @@ namespace Juliet
|
|||||||
// 1.6 should be available on most Win10 PC if they didnt their windows update.
|
// 1.6 should be available on most Win10 PC if they didnt their windows update.
|
||||||
// Lets support not having it for now...
|
// Lets support not having it for now...
|
||||||
IDXGIFactory6* factory6 = nullptr;
|
IDXGIFactory6* factory6 = nullptr;
|
||||||
result = IDXGIFactory4_QueryInterface(renderer->DXGIFactory, IID_IDXGIFactory6, (void**)&factory6);
|
result = IDXGIFactory4_QueryInterface(driver->DXGIFactory, IID_IDXGIFactory6, (void**)&factory6);
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
// TODO: Put into the config
|
// TODO: Put into the config
|
||||||
@@ -318,81 +287,81 @@ namespace Juliet
|
|||||||
useLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER
|
useLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER
|
||||||
: DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
: DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
|
||||||
IID_IDXGIAdapter1,
|
IID_IDXGIAdapter1,
|
||||||
reinterpret_cast<void**>(&renderer->DXGIAdapter));
|
reinterpret_cast<void**>(&driver->DXGIAdapter));
|
||||||
IDXGIFactory6_Release(factory6);
|
IDXGIFactory6_Release(factory6);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = IDXGIFactory4_EnumAdapters1(renderer->DXGIFactory, 0, &renderer->DXGIAdapter);
|
result = IDXGIFactory4_EnumAdapters1(driver->DXGIFactory, 0, &driver->DXGIAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Assert(false && "Could not find adapter for D3D12Device");
|
Assert(false && "Could not find adapter for D3D12Device");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapter is setup, get all the relevant info in the descriptor
|
// Adapter is setup, get all the relevant info in the descriptor
|
||||||
DXGI_ADAPTER_DESC1 adapterDesc;
|
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||||
result = IDXGIAdapter1_GetDesc1(renderer->DXGIAdapter, &adapterDesc);
|
result = IDXGIAdapter1_GetDesc1(driver->DXGIAdapter, &adapterDesc);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Assert(false && "Could not get DXGIAdapter description");
|
Assert(false && "Could not get DXGIAdapter description");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Driver version
|
// Driver version
|
||||||
LARGE_INTEGER umdVersion;
|
LARGE_INTEGER umdVersion;
|
||||||
result = IDXGIAdapter1_CheckInterfaceSupport(renderer->DXGIAdapter, IID_IDXGIDevice, &umdVersion);
|
result = IDXGIAdapter1_CheckInterfaceSupport(driver->DXGIAdapter, IID_IDXGIDevice, &umdVersion);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Assert(false && "Could not get DXGIAdapter driver version");
|
Assert(false && "Could not get DXGIAdapter driver version");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Graphics, "D3D12 Renderer Infos:");
|
Log(LogLevel::Message, LogCategory::Graphics, "D3D12 Driver Infos:");
|
||||||
Log(LogLevel::Message, LogCategory::Graphics, "D3D12 Adapter: %S", adapterDesc.Description);
|
Log(LogLevel::Message, LogCategory::Graphics, "D3D12 Adapter: %S", adapterDesc.Description);
|
||||||
Log(LogLevel::Message, LogCategory::Graphics, "D3D12 Driver Version: %d.%d.%d.%d", HIWORD(umdVersion.HighPart),
|
Log(LogLevel::Message, LogCategory::Graphics, "D3D12 Driver Version: %d.%d.%d.%d", HIWORD(umdVersion.HighPart),
|
||||||
LOWORD(umdVersion.HighPart), HIWORD(umdVersion.LowPart), LOWORD(umdVersion.LowPart));
|
LOWORD(umdVersion.HighPart), HIWORD(umdVersion.LowPart), LOWORD(umdVersion.LowPart));
|
||||||
|
|
||||||
renderer->D3D12DLL = LoadDynamicLibrary(D3D12_DLL);
|
driver->D3D12DLL = LoadDynamicLibrary(D3D12_DLL);
|
||||||
if (renderer->D3D12DLL == nullptr)
|
if (driver->D3D12DLL == nullptr)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Couldn't find " D3D12_DLL);
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Couldn't find " D3D12_DLL);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* D3D12CreateDeviceFuncPtr =
|
auto* D3D12CreateDeviceFuncPtr =
|
||||||
reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(LoadFunction(renderer->D3D12DLL, D3D12_CREATEDEVICE_FUNC));
|
reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(LoadFunction(driver->D3D12DLL, D3D12_CREATEDEVICE_FUNC));
|
||||||
if (D3D12CreateDeviceFuncPtr == nullptr)
|
if (D3D12CreateDeviceFuncPtr == nullptr)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Couldn't Load function " D3D12_CREATEDEVICE_FUNC " in " D3D12_DLL);
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Couldn't Load function " D3D12_CREATEDEVICE_FUNC " in " D3D12_DLL);
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->D3D12SerializeRootSignatureFct = reinterpret_cast<PFN_D3D12_SERIALIZE_ROOT_SIGNATURE>(
|
driver->D3D12SerializeRootSignatureFct = reinterpret_cast<PFN_D3D12_SERIALIZE_ROOT_SIGNATURE>(
|
||||||
LoadFunction(renderer->D3D12DLL, D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC));
|
LoadFunction(driver->D3D12DLL, D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC));
|
||||||
if (renderer->D3D12SerializeRootSignatureFct == nullptr)
|
if (driver->D3D12SerializeRootSignatureFct == nullptr)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Error, LogCategory::Graphics,
|
Log(LogLevel::Error, LogCategory::Graphics,
|
||||||
"DX12: Couldn't Load function " D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC " in " D3D12_DLL);
|
"DX12: Couldn't Load function " D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC " in " D3D12_DLL);
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : D3D12 Debug Layer here
|
// TODO : D3D12 Debug Layer here
|
||||||
// InitializeD3D12DebugLayer()
|
// InitializeD3D12DebugLayer()
|
||||||
|
|
||||||
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(renderer->DXGIAdapter), kD3DFeatureLevel,
|
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(driver->DXGIAdapter), kD3DFeatureLevel,
|
||||||
IID_ID3D12Device, reinterpret_cast<void**>(&renderer->D3D12Device));
|
IID_ID3D12Device5, reinterpret_cast<void**>(&driver->D3D12Device));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12Device");
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12Device5");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,16 +371,16 @@ namespace Juliet
|
|||||||
// Check if UMA (unified memory architecture) is available. Used on APU i think ??
|
// Check if UMA (unified memory architecture) is available. Used on APU i think ??
|
||||||
D3D12_FEATURE_DATA_ARCHITECTURE architecture;
|
D3D12_FEATURE_DATA_ARCHITECTURE architecture;
|
||||||
architecture.NodeIndex = 0;
|
architecture.NodeIndex = 0;
|
||||||
result = ID3D12Device_CheckFeatureSupport(renderer->D3D12Device, D3D12_FEATURE_ARCHITECTURE, &architecture,
|
result = ID3D12Device5_CheckFeatureSupport(driver->D3D12Device, D3D12_FEATURE_ARCHITECTURE, &architecture,
|
||||||
sizeof(D3D12_FEATURE_DATA_ARCHITECTURE));
|
sizeof(D3D12_FEATURE_DATA_ARCHITECTURE));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not get the device architecture");
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not get the device architecture");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
renderer->IsUMAAvailable = architecture.UMA;
|
driver->IsUMAAvailable = architecture.UMA;
|
||||||
renderer->IsUMACacheCoherent = architecture.CacheCoherentUMA;
|
driver->IsUMACacheCoherent = architecture.CacheCoherentUMA;
|
||||||
|
|
||||||
#ifndef E_INVALIDARG
|
#ifndef E_INVALIDARG
|
||||||
#define E_INVALIDARG (HRESULT)0x80070057L
|
#define E_INVALIDARG (HRESULT)0x80070057L
|
||||||
@@ -419,28 +388,31 @@ namespace Juliet
|
|||||||
|
|
||||||
// Check "GPU Upload Heap" support (for fast uniform buffers. Not supported on my 5700xt
|
// Check "GPU Upload Heap" support (for fast uniform buffers. Not supported on my 5700xt
|
||||||
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
|
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
|
||||||
renderer->GPUUploadHeapSupported = false;
|
driver->GPUUploadHeapSupported = false;
|
||||||
result = ID3D12Device_CheckFeatureSupport(renderer->D3D12Device, D3D12_FEATURE_D3D12_OPTIONS16, &options16,
|
result = ID3D12Device5_CheckFeatureSupport(driver->D3D12Device, D3D12_FEATURE_D3D12_OPTIONS16, &options16,
|
||||||
sizeof(options16));
|
sizeof(options16));
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
renderer->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
|
driver->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command Queue
|
// Command Queues
|
||||||
|
// Graphics Queue only for now
|
||||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
queueDesc.NodeMask = 0;
|
queueDesc.NodeMask = 0;
|
||||||
queueDesc.Priority = 0;
|
queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
|
||||||
result = ID3D12Device_CreateCommandQueue(renderer->D3D12Device, &queueDesc, IID_ID3D12CommandQueue,
|
result = ID3D12Device5_CreateCommandQueue(driver->D3D12Device, &queueDesc, IID_ID3D12CommandQueue,
|
||||||
reinterpret_cast<void**>(&renderer->CommandQueue));
|
reinterpret_cast<void**>(&driver->GraphicsQueue));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12CommandQueue");
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12CommandQueue: Graphics");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
ID3D12CommandQueue_SetName(driver->GraphicsQueue, L"GRAPHICS_QUEUE");
|
||||||
|
driver->QueueDesc[ToUnderlying(QueueType::Graphics)] = queueDesc;
|
||||||
|
|
||||||
// Indirect Commands
|
// Indirect Commands
|
||||||
D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
|
D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
|
||||||
@@ -452,11 +424,11 @@ namespace Juliet
|
|||||||
commandSignatureDesc.ByteStride = sizeof(IndirectDrawCommand);
|
commandSignatureDesc.ByteStride = sizeof(IndirectDrawCommand);
|
||||||
commandSignatureDesc.NumArgumentDescs = 1;
|
commandSignatureDesc.NumArgumentDescs = 1;
|
||||||
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
||||||
result = ID3D12Device_CreateCommandSignature(renderer->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
result = ID3D12Device5_CreateCommandSignature(driver->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
||||||
reinterpret_cast<void**>(&renderer->IndirectDrawCommandSignature));
|
reinterpret_cast<void**>(&driver->IndirectDrawCommandSignature));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create indirect draw command signature");
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create indirect draw command signature");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -465,12 +437,12 @@ namespace Juliet
|
|||||||
commandSignatureDesc.ByteStride = sizeof(IndexedIndirectDrawCommand);
|
commandSignatureDesc.ByteStride = sizeof(IndexedIndirectDrawCommand);
|
||||||
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
||||||
|
|
||||||
result = ID3D12Device_CreateCommandSignature(renderer->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
result = ID3D12Device5_CreateCommandSignature(driver->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
||||||
reinterpret_cast<void**>(&renderer->IndirectIndexedDrawCommandSignature));
|
reinterpret_cast<void**>(&driver->IndirectIndexedDrawCommandSignature));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
|
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create INDEXED Indirect draw command signature");
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create INDEXED Indirect draw command signature");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -479,11 +451,11 @@ namespace Juliet
|
|||||||
commandSignatureDesc.ByteStride = sizeof(IndirectDispatchCommand);
|
commandSignatureDesc.ByteStride = sizeof(IndirectDispatchCommand);
|
||||||
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
||||||
|
|
||||||
result = ID3D12Device_CreateCommandSignature(renderer->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
result = ID3D12Device5_CreateCommandSignature(driver->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
||||||
reinterpret_cast<void**>(&renderer->IndirectDispatchCommandSignature));
|
reinterpret_cast<void**>(&driver->IndirectDispatchCommandSignature));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create Indirect dispatch command signature");
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create Indirect dispatch command signature");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -491,22 +463,30 @@ namespace Juliet
|
|||||||
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
||||||
if (!device)
|
if (!device)
|
||||||
{
|
{
|
||||||
DestroyRenderer_Internal(renderer);
|
DestroyDriver_Internal(driver);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
device->DestroyDevice = DestroyGraphicsDevice;
|
|
||||||
device->Renderer = renderer;
|
// Assign Functions to the device
|
||||||
renderer->GraphicsDevice = device;
|
device->DestroyDevice = DestroyGraphicsDevice;
|
||||||
|
device->AcquireCommandList = AcquireCommandList;
|
||||||
|
device->SubmitCommandLists = SubmitCommandLists;
|
||||||
|
|
||||||
|
device->Driver = driver;
|
||||||
|
driver->GraphicsDevice = device;
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
} // namespace Juliet::D3D12
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
GraphicsDeviceFactory DX12DeviceFactory = {
|
GraphicsDeviceFactory DX12DeviceFactory = {
|
||||||
.Name="DirectX12",
|
.Name="DirectX12",
|
||||||
.Type=RendererType::DX12,
|
.Type=DriverType::DX12,
|
||||||
.CheckDriver = CheckDriver,
|
.CheckDriver = D3D12::CheckDriver,
|
||||||
.CreateGraphicsDevice = CreateGraphicsDevice };
|
.CreateGraphicsDevice = D3D12::CreateGraphicsDevice };
|
||||||
// clang-format on
|
// clang-format on
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
50
Juliet/src/Graphics/D3D12/DX12GraphicsDevice.h
Normal file
50
Juliet/src/Graphics/D3D12/DX12GraphicsDevice.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <DX12Utils.h>
|
||||||
|
#include <Graphics/GraphicsDevice.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct DynamicLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Juliet::D3D12
|
||||||
|
{
|
||||||
|
struct D3D12Driver : GPUDriver
|
||||||
|
{
|
||||||
|
GraphicsDevice* GraphicsDevice;
|
||||||
|
|
||||||
|
// D3D12
|
||||||
|
DynamicLibrary* D3D12DLL;
|
||||||
|
ID3D12Device5* D3D12Device;
|
||||||
|
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFct;
|
||||||
|
ID3D12CommandQueue* GraphicsQueue;
|
||||||
|
D3D12_COMMAND_QUEUE_DESC QueueDesc[ToUnderlying(QueueType::Copy)];
|
||||||
|
|
||||||
|
// Indirect commands signature
|
||||||
|
ID3D12CommandSignature* IndirectDrawCommandSignature;
|
||||||
|
ID3D12CommandSignature* IndirectIndexedDrawCommandSignature;
|
||||||
|
ID3D12CommandSignature* IndirectDispatchCommandSignature;
|
||||||
|
|
||||||
|
// DXGI
|
||||||
|
IDXGIFactory4* DXGIFactory;
|
||||||
|
IDXGIAdapter1* DXGIAdapter;
|
||||||
|
DynamicLibrary* DXGIDebugDLL;
|
||||||
|
IDXGIDebug* DXGIDebug;
|
||||||
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
|
IDXGIInfoQueue* DXGIInfoQueue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
D3D12CommandList** AvailableCommandLists;
|
||||||
|
uint8 AvailableCommandListCapacity;
|
||||||
|
|
||||||
|
bool IsTearingSupported : 1;
|
||||||
|
|
||||||
|
// UMA
|
||||||
|
bool IsUMAAvailable : 1;
|
||||||
|
bool IsUMACacheCoherent : 1;
|
||||||
|
|
||||||
|
bool GPUUploadHeapSupported : 1;
|
||||||
|
};
|
||||||
|
} // namespace Juliet::D3D12
|
||||||
@@ -16,12 +16,12 @@ namespace Juliet
|
|||||||
GraphicsDeviceFactory* ChooseFactory(GraphicsConfig config)
|
GraphicsDeviceFactory* ChooseFactory(GraphicsConfig config)
|
||||||
{
|
{
|
||||||
// First try to check the preferred renderer from the config if any.
|
// First try to check the preferred renderer from the config if any.
|
||||||
if (config.PreferredRenderer != RendererType::Any)
|
if (config.PreferredDriver != DriverType::Any)
|
||||||
{
|
{
|
||||||
for (GraphicsDeviceFactory* factory : Factories)
|
for (GraphicsDeviceFactory* factory : Factories)
|
||||||
{
|
{
|
||||||
// If the config has a preferred renderer, immediately pick it up.
|
// If the config has a preferred renderer, immediately pick it up.
|
||||||
if (factory->Type == config.PreferredRenderer)
|
if (factory->Type == config.PreferredDriver)
|
||||||
{
|
{
|
||||||
if (factory->CheckDriver())
|
if (factory->CheckDriver())
|
||||||
{
|
{
|
||||||
@@ -63,4 +63,22 @@ namespace Juliet
|
|||||||
device->DestroyDevice(device);
|
device->DestroyDevice(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandList* AcquireCommandList(NonNullPtr<GraphicsDevice> device, QueueType queueType /* = QueueType::Graphics */)
|
||||||
|
{
|
||||||
|
GPUDriver* driver = device->Driver;
|
||||||
|
CommandList* cmdList = device->AcquireCommandList(driver, queueType);
|
||||||
|
|
||||||
|
driver->CommandListCount += 1;
|
||||||
|
|
||||||
|
return cmdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubmitCommandLists(NonNullPtr<GraphicsDevice> device)
|
||||||
|
{
|
||||||
|
GPUDriver* driver = device->Driver;
|
||||||
|
device->SubmitCommandLists(driver);
|
||||||
|
|
||||||
|
driver->CommandListCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -1,26 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Graphics/GraphicsConfig.h>
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
#include <Graphics/Graphics.h>
|
||||||
|
#include <Graphics/GraphicsConfig.h>
|
||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
struct GPURenderer
|
struct GPUDriver
|
||||||
{
|
{
|
||||||
|
uint8 CommandListCount;
|
||||||
|
|
||||||
|
static constexpr uint8 kResourceBufferCount = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsDevice
|
struct GraphicsDevice
|
||||||
{
|
{
|
||||||
void (*DestroyDevice)(NonNullPtr<GraphicsDevice> self);
|
void (*DestroyDevice)(NonNullPtr<GraphicsDevice> self);
|
||||||
|
CommandList* (*AcquireCommandList)(NonNullPtr<GPUDriver> driver, QueueType queueType);
|
||||||
|
void (*SubmitCommandLists)(NonNullPtr<GPUDriver> driver);
|
||||||
|
|
||||||
const char* Name = "Unknown";
|
const char* Name = "Unknown";
|
||||||
GPURenderer* Renderer = nullptr;
|
GPUDriver* Driver = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GraphicsDeviceFactory
|
struct GraphicsDeviceFactory
|
||||||
{
|
{
|
||||||
const char* Name = "Unknown";
|
const char* Name = "Unknown";
|
||||||
RendererType Type = RendererType::Any;
|
DriverType Type = DriverType::Any;
|
||||||
bool (*CheckDriver)(void);
|
bool (*CheckDriver)(void);
|
||||||
GraphicsDevice* (*CreateGraphicsDevice)(void);
|
GraphicsDevice* (*CreateGraphicsDevice)(void);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ void Win32EditorApplication::Update()
|
|||||||
|
|
||||||
// Draw here for now
|
// Draw here for now
|
||||||
// 1) Acquire a Command Buffer
|
// 1) Acquire a Command Buffer
|
||||||
|
CommandList* cmdList = AcquireCommandList(GraphicsDevice, QueueType::Graphics);
|
||||||
|
|
||||||
|
// Submit Commands
|
||||||
|
SubmitCommandLists(GraphicsDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32EditorApplication::IsRunning()
|
bool Win32EditorApplication::IsRunning()
|
||||||
|
|||||||
Reference in New Issue
Block a user