dx12 dynamic lib loading + creation of device first pass.
This commit is contained in:
@@ -24,4 +24,6 @@ namespace Juliet
|
|||||||
const byte* Data;
|
const byte* Data;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using FunctionPtr = auto (*)(void) -> void;
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -2,13 +2,16 @@
|
|||||||
|
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
#define Assert(expression) \
|
#define Assert(expression) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if (!(expression)) \
|
if (!(expression)) \
|
||||||
{ \
|
{ \
|
||||||
JulietAssert("Assertion Failed: " #expression); \
|
Juliet::JulietAssert("Assertion Failed: " #expression); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
@@ -17,4 +20,16 @@
|
|||||||
#define Assert(Expression)
|
#define Assert(Expression)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void JULIET_API JulietAssert(const char* expression);
|
extern void JULIET_API JulietAssert(const char* expression);
|
||||||
|
|
||||||
|
#define ZeroStruct(structInstance) ZeroSize(sizeof(structInstance), &(structInstance))
|
||||||
|
#define ZeroArray(Count, Pointer) ZeroSize((Count) * sizeof((Pointer)[0]), Pointer)
|
||||||
|
inline void ZeroSize(size_t size, void* ptr)
|
||||||
|
{
|
||||||
|
auto Byte = (uint8*)ptr;
|
||||||
|
while (size--)
|
||||||
|
{
|
||||||
|
*Byte++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <core/Common/NonNullPtr.h>
|
||||||
#include <Graphics/GraphicsConfig.h>
|
#include <Graphics/GraphicsConfig.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
@@ -8,5 +9,33 @@ namespace Juliet
|
|||||||
{
|
{
|
||||||
struct GraphicsDevice;
|
struct GraphicsDevice;
|
||||||
|
|
||||||
|
// Parameters of an indirect draw command
|
||||||
|
struct IndirectDrawCommand
|
||||||
|
{
|
||||||
|
uint32 VertexCount; // Number of vertices to draw
|
||||||
|
uint32 InstanceCount; // Number of instanced to draw
|
||||||
|
uint32 FirstVertex; // Index of the first vertex to draw
|
||||||
|
uint32 FirstInstance; // ID of the first instance to draw
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameters of an INDEXED indirect draw command
|
||||||
|
struct IndexedIndirectDrawCommand
|
||||||
|
{
|
||||||
|
uint32 VertexCount; // Number of vertices to draw
|
||||||
|
uint32 InstanceCount; // Number of instanced to draw
|
||||||
|
uint32 FirstIndex; // Base Index within the index buffer
|
||||||
|
int32 VertexOffset; // Offset the vertex index into the buffer
|
||||||
|
uint32 FirstInstance; // ID of the first instance to draw
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parameters of an INDEXED Indirect Dispatch Command
|
||||||
|
struct IndirectDispatchCommand
|
||||||
|
{
|
||||||
|
uint32 X_WorkGroupCount; // Number of Workgroup to dispatch on dimension X
|
||||||
|
uint32 Y_WorkGroupCount; // Number of Workgroup to dispatch on dimension Y
|
||||||
|
uint32 Z_WorkGroupCount; // Number of Workgroup to dispatch on dimension Z
|
||||||
|
};
|
||||||
|
|
||||||
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
extern JULIET_API GraphicsDevice* CreateGraphicsDevice(GraphicsConfig config);
|
||||||
|
extern JULIET_API void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device);
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
void JulietAssert(const char* expression)
|
namespace Juliet
|
||||||
{
|
{
|
||||||
Juliet::Log(Juliet::LogLevel::Error, Juliet::LogCategory::Core, expression);
|
void JulietAssert(const char* expression)
|
||||||
__debugbreak();
|
{
|
||||||
}
|
Juliet::Log(Juliet::LogLevel::Error, Juliet::LogCategory::Core, expression);
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
|
#include <Core/Common/CoreTypes.h>
|
||||||
#include <Core/HAL/Display/Display_Private.h>
|
#include <Core/HAL/Display/Display_Private.h>
|
||||||
#include <Core/HAL/Display/DisplayDevice.h>
|
#include <Core/HAL/Display/DisplayDevice.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
@@ -20,7 +21,8 @@ namespace Juliet
|
|||||||
Assert(!CurrentDisplayDevice);
|
Assert(!CurrentDisplayDevice);
|
||||||
|
|
||||||
DisplayDevice* candidateDevice = nullptr;
|
DisplayDevice* candidateDevice = nullptr;
|
||||||
DisplayDeviceFactory* candidateFactory = nullptr;
|
DisplayDeviceFactory*
|
||||||
|
candidateFactory = nullptr;
|
||||||
for (DisplayDeviceFactory* factory : Factories)
|
for (DisplayDeviceFactory* factory : Factories)
|
||||||
{
|
{
|
||||||
if (factory)
|
if (factory)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include <pch.h>
|
#include <pch.h>
|
||||||
|
|
||||||
#include <core/Common/NonNullPtr.h>
|
#include <core/Common/NonNullPtr.h>
|
||||||
|
#include <Core/DynLib/DynamicLibrary.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
#include <Core/Memory/Allocator.h>
|
||||||
#include <DX12Utils.h>
|
#include <DX12Utils.h>
|
||||||
#include <Graphics/D3D12/DX12Includes.h>
|
#include <Graphics/D3D12/DX12Includes.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
|
// TODO : Use LoadLibrary and not link to the lib. Allows failing earlier if Dx12 is not installed for some reason
|
||||||
@@ -11,18 +13,43 @@
|
|||||||
// This will prevent us from using IID_ variables as they are defined in dxguid.lib
|
// This will prevent us from using IID_ variables as they are defined in dxguid.lib
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
|
#define D3D12_DLL "d3d12.dll"
|
||||||
|
#define D3D12_CREATEDEVICE_FUNC "D3D12CreateDevice"
|
||||||
|
#define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature"
|
||||||
|
#define DXGIDEBUG_DLL "dxgidebug.dll"
|
||||||
|
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
|
||||||
|
|
||||||
struct D3D12Renderer : GPURenderer
|
struct D3D12Renderer : GPURenderer
|
||||||
{
|
{
|
||||||
IDXGIFactory4* DXGIFactory;
|
GraphicsDevice* GraphicsDevice;
|
||||||
IDXGIAdapter1* DXGIAdapter;
|
|
||||||
|
|
||||||
HMODULE DXGIDebug_DLL;
|
// D3D12
|
||||||
IDXGIDebug* DXGIDebug;
|
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
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
IDXGIInfoQueue* DXGIInfoQueue;
|
IDXGIInfoQueue* DXGIInfoQueue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool IsTearingSupported : 1;
|
bool IsTearingSupported : 1;
|
||||||
|
|
||||||
|
// UMA
|
||||||
|
bool IsUMAAvailable : 1;
|
||||||
|
bool IsUMACacheCoherent : 1;
|
||||||
|
|
||||||
|
bool GPUUploadHeapSupported : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -35,6 +62,23 @@ namespace Juliet
|
|||||||
|
|
||||||
bool CheckDriver()
|
bool CheckDriver()
|
||||||
{
|
{
|
||||||
|
// Can we Load D3D12.dll and the create device function
|
||||||
|
DynamicLibrary* d3d12_dll = LoadDynamicLibrary(D3D12_DLL);
|
||||||
|
if (d3d12_dll == nullptr)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Couldn't find " D3D12_DLL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* D3D12CreateDeviceFuncPtr =
|
||||||
|
reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(LoadFunction(d3d12_dll, D3D12_CREATEDEVICE_FUNC));
|
||||||
|
if (D3D12CreateDeviceFuncPtr == nullptr)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Warning, LogCategory::Graphics, "DX12: Couldn't find function " D3D12_CREATEDEVICE_FUNC " in " D3D12_DLL);
|
||||||
|
UnloadDynamicLibrary(d3d12_dll);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Can create DXGI factory ?
|
// Can create DXGI factory ?
|
||||||
IDXGIFactory1* factory1 = nullptr;
|
IDXGIFactory1* factory1 = nullptr;
|
||||||
HRESULT result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
HRESULT result = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void**>(&factory1));
|
||||||
@@ -79,8 +123,8 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Device* device = nullptr;
|
ID3D12Device* device = nullptr;
|
||||||
result = D3D12CreateDevice(reinterpret_cast<IUnknown*>(adapter), kD3DFeatureLevel, IID_ID3D12Device,
|
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(adapter), kD3DFeatureLevel, IID_ID3D12Device,
|
||||||
reinterpret_cast<void**>(&device));
|
reinterpret_cast<void**>(&device));
|
||||||
|
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
@@ -100,19 +144,18 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
#ifdef IDXGIINFOQUEUE_SUPPORTED
|
||||||
void InitializeDebugLayer(NonNullPtr<D3D12Renderer> renderer)
|
void InitializeDXGIDebug(NonNullPtr<D3D12Renderer> renderer)
|
||||||
{
|
{
|
||||||
// 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->DXGIDebug_DLL = LoadLibraryEx(L"dxgidebug.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
renderer->DXGIDebugDLL = LoadDynamicLibrary(DXGIDEBUG_DLL);
|
||||||
if (renderer->DXGIDebug_DLL)
|
if (renderer->DXGIDebugDLL)
|
||||||
{
|
{
|
||||||
auto dxgiGetDebugInterface = reinterpret_cast<LPDXGIGETDEBUGINTERFACE>(
|
auto dxgiGetDebugInterface = reinterpret_cast<LPDXGIGETDEBUGINTERFACE>(
|
||||||
reinterpret_cast<void*>(GetProcAddress(renderer->DXGIDebug_DLL, "DXGIGetDebugInterface")));
|
LoadFunction(renderer->DXGIDebugDLL, DXGI_GET_DEBUG_INTERFACE_FUNC));
|
||||||
|
HRESULT result = dxgiGetDebugInterface(IID_IDXGIDebug, (void**)&renderer->DXGIDebug);
|
||||||
HRESULT result = DXGIGetDebugInterface1(0, IID_IDXGIDebug, (void**)&renderer->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");
|
||||||
@@ -135,7 +178,7 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownDebugLayer(NonNullPtr<D3D12Renderer> renderer)
|
void ShutdownDXGIDebug(NonNullPtr<D3D12Renderer> renderer)
|
||||||
{
|
{
|
||||||
if (renderer->DXGIDebug)
|
if (renderer->DXGIDebug)
|
||||||
{
|
{
|
||||||
@@ -145,17 +188,44 @@ namespace Juliet
|
|||||||
renderer->DXGIDebug = nullptr;
|
renderer->DXGIDebug = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderer->DXGIDebug_DLL)
|
if (renderer->DXGIDebugDLL)
|
||||||
{
|
{
|
||||||
FreeLibrary(renderer->DXGIDebug_DLL);
|
UnloadDynamicLibrary(renderer->DXGIDebugDLL);
|
||||||
renderer->DXGIDebug_DLL = nullptr;
|
renderer->DXGIDebugDLL = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void DestroyRenderer_Internal(NonNullPtr<D3D12Renderer> renderer)
|
void DestroyRenderer_Internal(NonNullPtr<D3D12Renderer> renderer)
|
||||||
{
|
{
|
||||||
ShutdownDebugLayer(renderer);
|
if (renderer->D3D12Device)
|
||||||
|
{
|
||||||
|
ID3D12Device_Release(renderer->D3D12Device);
|
||||||
|
renderer->D3D12Device = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer->DXGIAdapter)
|
||||||
|
{
|
||||||
|
IDXGIAdapter1_Release(renderer->DXGIAdapter);
|
||||||
|
renderer->DXGIAdapter = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (renderer->DXGIFactory)
|
||||||
|
{
|
||||||
|
IDXGIFactory4_Release(renderer->DXGIFactory);
|
||||||
|
renderer->DXGIFactory = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShutdownDXGIDebug(renderer);
|
||||||
|
|
||||||
|
if (renderer->D3D12DLL)
|
||||||
|
{
|
||||||
|
UnloadDynamicLibrary(renderer->D3D12DLL);
|
||||||
|
renderer->D3D12DLL = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->D3D12SerializeRootSignatureFct = nullptr;
|
||||||
|
|
||||||
Free(renderer.Get());
|
Free(renderer.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +244,7 @@ namespace Juliet
|
|||||||
static const bool kDebug = true;
|
static const bool kDebug = true;
|
||||||
if (kDebug)
|
if (kDebug)
|
||||||
{
|
{
|
||||||
InitializeDebugLayer(renderer);
|
InitializeDXGIDebug(renderer);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -266,9 +336,145 @@ namespace Juliet
|
|||||||
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));
|
||||||
|
|
||||||
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
renderer->D3D12DLL = LoadDynamicLibrary(D3D12_DLL);
|
||||||
device->DestroyDevice = DestroyGraphicsDevice;
|
if (renderer->D3D12DLL == nullptr)
|
||||||
device->Renderer = renderer;
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Couldn't find " D3D12_DLL);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* D3D12CreateDeviceFuncPtr =
|
||||||
|
reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(LoadFunction(renderer->D3D12DLL, D3D12_CREATEDEVICE_FUNC));
|
||||||
|
if (D3D12CreateDeviceFuncPtr == nullptr)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Couldn't Load function " D3D12_CREATEDEVICE_FUNC " in " D3D12_DLL);
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->D3D12SerializeRootSignatureFct = reinterpret_cast<PFN_D3D12_SERIALIZE_ROOT_SIGNATURE>(
|
||||||
|
LoadFunction(renderer->D3D12DLL, D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC));
|
||||||
|
if (renderer->D3D12SerializeRootSignatureFct == nullptr)
|
||||||
|
{
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics,
|
||||||
|
"DX12: Couldn't Load function " D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC " in " D3D12_DLL);
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : D3D12 Debug Layer here
|
||||||
|
// InitializeD3D12DebugLayer()
|
||||||
|
|
||||||
|
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(renderer->DXGIAdapter), kD3DFeatureLevel,
|
||||||
|
IID_ID3D12Device, reinterpret_cast<void**>(&renderer->D3D12Device));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12Device");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : D3D12 Debug Info Queue
|
||||||
|
// InitializeD3D12DebugInfoQueue
|
||||||
|
|
||||||
|
// Check if UMA (unified memory architecture) is available. Used on APU i think ??
|
||||||
|
D3D12_FEATURE_DATA_ARCHITECTURE architecture;
|
||||||
|
architecture.NodeIndex = 0;
|
||||||
|
result = ID3D12Device_CheckFeatureSupport(renderer->D3D12Device, D3D12_FEATURE_ARCHITECTURE, &architecture,
|
||||||
|
sizeof(D3D12_FEATURE_DATA_ARCHITECTURE));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not get the device architecture");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
renderer->IsUMAAvailable = architecture.UMA;
|
||||||
|
renderer->IsUMACacheCoherent = architecture.CacheCoherentUMA;
|
||||||
|
|
||||||
|
#ifndef E_INVALIDARG
|
||||||
|
#define E_INVALIDARG (HRESULT)0x80070057L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check "GPU Upload Heap" support (for fast uniform buffers. Not supported on my 5700xt
|
||||||
|
D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16;
|
||||||
|
renderer->GPUUploadHeapSupported = false;
|
||||||
|
result = ID3D12Device_CheckFeatureSupport(renderer->D3D12Device, D3D12_FEATURE_D3D12_OPTIONS16, &options16,
|
||||||
|
sizeof(options16));
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
renderer->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command Queue
|
||||||
|
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||||
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||||
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
|
queueDesc.NodeMask = 0;
|
||||||
|
queueDesc.Priority = 0;
|
||||||
|
result = ID3D12Device_CreateCommandQueue(renderer->D3D12Device, &queueDesc, IID_ID3D12CommandQueue,
|
||||||
|
reinterpret_cast<void**>(&renderer->CommandQueue));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create D3D12CommandQueue");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indirect Commands
|
||||||
|
D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
|
||||||
|
D3D12_INDIRECT_ARGUMENT_DESC indirectArgumentDesc;
|
||||||
|
ZeroStruct(indirectArgumentDesc);
|
||||||
|
|
||||||
|
indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
|
||||||
|
commandSignatureDesc.NodeMask = 0;
|
||||||
|
commandSignatureDesc.ByteStride = sizeof(IndirectDrawCommand);
|
||||||
|
commandSignatureDesc.NumArgumentDescs = 1;
|
||||||
|
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
||||||
|
result = ID3D12Device_CreateCommandSignature(renderer->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
||||||
|
reinterpret_cast<void**>(&renderer->IndirectDrawCommandSignature));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create indirect draw command signature");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
|
||||||
|
commandSignatureDesc.ByteStride = sizeof(IndexedIndirectDrawCommand);
|
||||||
|
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
||||||
|
|
||||||
|
result = ID3D12Device_CreateCommandSignature(renderer->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
||||||
|
reinterpret_cast<void**>(&renderer->IndirectIndexedDrawCommandSignature));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create INDEXED Indirect draw command signature");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;
|
||||||
|
commandSignatureDesc.ByteStride = sizeof(IndirectDispatchCommand);
|
||||||
|
commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
|
||||||
|
|
||||||
|
result = ID3D12Device_CreateCommandSignature(renderer->D3D12Device, &commandSignatureDesc, NULL, IID_ID3D12CommandSignature,
|
||||||
|
reinterpret_cast<void**>(&renderer->IndirectDispatchCommandSignature));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
Log(LogLevel::Error, LogCategory::Graphics, "DX12: Could not create Indirect dispatch command signature");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto device = static_cast<GraphicsDevice*>(Calloc(1, sizeof(GraphicsDevice)));
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
DestroyRenderer_Internal(renderer);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
device->DestroyDevice = DestroyGraphicsDevice;
|
||||||
|
device->Renderer = renderer;
|
||||||
|
renderer->GraphicsDevice = device;
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,4 +57,10 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DestroyGraphicsDevice(NonNullPtr<GraphicsDevice> device)
|
||||||
|
{
|
||||||
|
device->DestroyDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -14,62 +14,76 @@
|
|||||||
#include <Graphics/Graphics.h>
|
#include <Graphics/Graphics.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace Juliet
|
// TODO : Think how to do the draw pipeline.
|
||||||
|
// Ex: Expose a Draw method ?
|
||||||
|
// Store a graphics context ?
|
||||||
|
// For now. Put everything in Update down below.
|
||||||
|
// Should split update from draw, update should have a != timestep than graphics (60fps or more)
|
||||||
|
using namespace Juliet;
|
||||||
|
|
||||||
|
void Win32EditorApplication::Init()
|
||||||
{
|
{
|
||||||
void Win32EditorApplication::Init()
|
Log(LogLevel::Message, LogCategory::Editor, "Initializing Editor Application...");
|
||||||
|
|
||||||
|
GraphicsConfig config;
|
||||||
|
GraphicsDevice = CreateGraphicsDevice(config);
|
||||||
|
|
||||||
|
MainWindow = CreatePlatformWindow("Juliet Editor", 1280, 720);
|
||||||
|
|
||||||
|
// TODO : Assign the graphics device to the main window (and detach)
|
||||||
|
|
||||||
|
Running = MainWindow != nullptr && GraphicsDevice != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Win32EditorApplication::Shutdown()
|
||||||
|
{
|
||||||
|
Log(LogLevel::Message, LogCategory::Editor, "Shutdown Editor Application...");
|
||||||
|
|
||||||
|
if (MainWindow)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Message, LogCategory::Editor, "Initializing Editor Application...");
|
DestroyPlatformWindow(MainWindow);
|
||||||
|
|
||||||
MainWindow = CreatePlatformWindow("Juliet Editor", 1280, 720);
|
|
||||||
|
|
||||||
GraphicsConfig config;
|
|
||||||
GraphicsDevice* device = CreateGraphicsDevice(config);
|
|
||||||
Assert(!device && "Currently not implemented so device should be null");
|
|
||||||
|
|
||||||
Running = MainWindow != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32EditorApplication::Shutdown()
|
if (GraphicsDevice)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Message, LogCategory::Editor, "Shutdown Editor Application...");
|
DestroyGraphicsDevice(GraphicsDevice);
|
||||||
|
|
||||||
if (MainWindow)
|
|
||||||
{
|
|
||||||
DestroyPlatformWindow(MainWindow);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Win32EditorApplication::Update()
|
void Win32EditorApplication::Update()
|
||||||
|
{
|
||||||
|
SystemEvent evt;
|
||||||
|
while (GetEvent(evt))
|
||||||
{
|
{
|
||||||
SystemEvent evt;
|
if (evt.Type == EventType::Window_Close_Request)
|
||||||
while (GetEvent(evt))
|
|
||||||
{
|
{
|
||||||
if (evt.Type == EventType::Window_Close_Request)
|
if (evt.Data.Window.AssociatedWindowID == GetWindowID(MainWindow))
|
||||||
{
|
{
|
||||||
if (evt.Data.Window.AssociatedWindowID == GetWindowID(MainWindow))
|
Running = false;
|
||||||
{
|
|
||||||
Running = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32EditorApplication::IsRunning()
|
// Draw here for now
|
||||||
{
|
// 1) Acquire a Command Buffer
|
||||||
return Running;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
Win32EditorApplication EditorApplication;
|
|
||||||
}
|
|
||||||
|
|
||||||
Win32EditorApplication& GetEditorApplication()
|
}
|
||||||
{
|
|
||||||
return EditorApplication;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Juliet
|
bool Win32EditorApplication::IsRunning()
|
||||||
|
{
|
||||||
|
return Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
Win32EditorApplication EditorApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
Win32EditorApplication& GetEditorApplication()
|
||||||
|
{
|
||||||
|
return EditorApplication;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@@ -80,7 +94,7 @@ int main(int argc, char** argv)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartApplication(Juliet::EditorApplication, Juliet::JulietInit_Flags::Display);
|
StartApplication(EditorApplication, JulietInit_Flags::Display);
|
||||||
|
|
||||||
// Pause here to not close the console window immediatly on stop
|
// Pause here to not close the console window immediatly on stop
|
||||||
system("PAUSE");
|
system("PAUSE");
|
||||||
|
|||||||
@@ -5,20 +5,23 @@
|
|||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
|
struct GraphicsDevice;
|
||||||
struct Window;
|
struct Window;
|
||||||
|
}
|
||||||
|
|
||||||
class Win32EditorApplication : public IApplication
|
class Win32EditorApplication : public Juliet::IApplication
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void Init() override;
|
void Init() override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
void Update() override;
|
void Update() override;
|
||||||
bool IsRunning() override;
|
bool IsRunning() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Window* MainWindow = {};
|
Juliet::Window* MainWindow = {};
|
||||||
bool Running = false;
|
Juliet::GraphicsDevice* GraphicsDevice = {};
|
||||||
};
|
|
||||||
|
|
||||||
Win32EditorApplication& GetEditorApplication();
|
bool Running = false;
|
||||||
} // namespace Juliet
|
};
|
||||||
|
|
||||||
|
Win32EditorApplication& GetEditorApplication();
|
||||||
|
|||||||
Reference in New Issue
Block a user