Graphics pipeline creation is working

This commit is contained in:
2025-03-11 22:45:21 -04:00
parent a9fe4683fb
commit 0d93cd9e6d
13 changed files with 461 additions and 46 deletions

View File

@@ -117,5 +117,6 @@ namespace Juliet
// Pipelines
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
const GraphicsPipelineCreateInfo& createInfo);
extern JULIET_API void DestroyGraphicsPipeline(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline);
} // namespace Juliet

View File

@@ -11,5 +11,6 @@ namespace Juliet
struct GraphicsConfig
{
DriverType PreferredDriver = DriverType::DX12;
bool EnableDebug;
};
} // namespace Juliet

View File

@@ -9,8 +9,8 @@ namespace Juliet
enum class FillMode : uint8
{
Wireframe,
Solid,
Wireframe,
Count
};

View File

@@ -8,8 +8,10 @@
#include <Graphics/D3D12/D3D12GraphicsPipeline.h>
#include <Graphics/D3D12/D3D12Includes.h>
#include <Graphics/D3D12/D3D12RenderPass.h>
#include <Graphics/D3D12/D3D12Shader.h>
#include <Graphics/D3D12/D3D12SwapChain.h>
#include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/D3D12Utils.h>
#include <Graphics/Graphics.h>
#include <Graphics/GraphicsDevice.h>
@@ -18,6 +20,7 @@
#define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature"
#define DXGIDEBUG_DLL "dxgidebug.dll"
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
#define D3D12_GET_DEBUG_INTERFACE_FUNC "D3D12GetDebugInterface"
// 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
@@ -168,6 +171,116 @@ namespace Juliet::D3D12
}
#endif
#ifdef JULIET_DEBUG
void InitializeD3D12DebugLayer(NonNullPtr<D3D12Driver> driver)
{
auto D3D12GetDebugInterfaceFunc =
reinterpret_cast<PFN_D3D12_GET_DEBUG_INTERFACE>(LoadFunction(driver->D3D12DLL, D3D12_GET_DEBUG_INTERFACE_FUNC));
if (D3D12GetDebugInterfaceFunc == nullptr)
{
LogWarning(LogCategory::Graphics, "Could not load function: " D3D12_GET_DEBUG_INTERFACE_FUNC);
return;
}
HRESULT result = D3D12GetDebugInterfaceFunc(IID_ID3D12Debug1, reinterpret_cast<void**>(&driver->D3D12Debug));
if (FAILED(result))
{
LogWarning(LogCategory::Graphics, "Could not get ID3D12Debug interface");
return;
}
ID3D12Debug1_EnableDebugLayer(driver->D3D12Debug);
}
bool InitializeD3D12DebugInfoQueue(NonNullPtr<D3D12Driver> driver)
{
ID3D12InfoQueue* infoQueue = NULL;
D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
HRESULT result =
ID3D12Device_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue, reinterpret_cast<void**>(&infoQueue));
if (FAILED(result))
{
LogError(driver, "Failed to convert ID3D12Device to ID3D12InfoQueue", result);
return false;
}
D3D12_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumSeverities = 1;
filter.DenyList.pSeverityList = severities;
ID3D12InfoQueue_PushStorageFilter(infoQueue, &filter);
ID3D12InfoQueue_SetBreakOnSeverity(infoQueue, D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
ID3D12InfoQueue_Release(infoQueue);
return true;
}
#ifdef ID3D12InfoQueue1_SUPPORTED
void WINAPI OnD3D12DebugInfoMsg(D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
D3D12_MESSAGE_ID id, LPCSTR description, void* context)
{
String catStr;
switch (category)
{
case D3D12_MESSAGE_CATEGORY_APPLICATION_DEFINED: catStr = WrapString("APPLICATION_DEFINED"); break;
case D3D12_MESSAGE_CATEGORY_MISCELLANEOUS: catStr = WrapString("MISCELLANEOUS"); break;
case D3D12_MESSAGE_CATEGORY_INITIALIZATION: catStr = WrapString("INITIALIZATION"); break;
case D3D12_MESSAGE_CATEGORY_CLEANUP: catStr = WrapString("CLEANUP"); break;
case D3D12_MESSAGE_CATEGORY_COMPILATION: catStr = WrapString("COMPILATION"); break;
case D3D12_MESSAGE_CATEGORY_STATE_CREATION: catStr = WrapString("STATE_CREATION"); break;
case D3D12_MESSAGE_CATEGORY_STATE_SETTING: catStr = WrapString("STATE_SETTING"); break;
case D3D12_MESSAGE_CATEGORY_STATE_GETTING: catStr = WrapString("STATE_GETTING"); break;
case D3D12_MESSAGE_CATEGORY_RESOURCE_MANIPULATION: catStr = WrapString("RESOURCE_MANIPULATION"); break;
case D3D12_MESSAGE_CATEGORY_EXECUTION: catStr = WrapString("EXECUTION"); break;
case D3D12_MESSAGE_CATEGORY_SHADER: catStr = WrapString("SHADER"); break;
default: catStr = WrapString("UNKNOWN"); break;
}
String severityStr;
switch (severity)
{
case D3D12_MESSAGE_SEVERITY_CORRUPTION: severityStr = WrapString("CORRUPTION"); break;
case D3D12_MESSAGE_SEVERITY_ERROR: severityStr = WrapString("ERROR"); break;
case D3D12_MESSAGE_SEVERITY_WARNING: severityStr = WrapString("WARNING"); break;
case D3D12_MESSAGE_SEVERITY_INFO: severityStr = WrapString("INFO"); break;
case D3D12_MESSAGE_SEVERITY_MESSAGE: severityStr = WrapString("MESSAGE"); break;
default: severityStr = WrapString("UNKNOWN"); break;
}
if (severity <= D3D12_MESSAGE_SEVERITY_ERROR)
{
LogWarning(LogCategory::Graphics, "D3D12 ERROR: %s [%s %s #%d]", description, CStr(catStr), CStr(severityStr), id);
}
else
{
LogWarning(LogCategory::Graphics, "D3D12 WARNING: %s [%s %s #%d]", description, CStr(catStr),
CStr(severityStr), id);
}
}
void InitializeD3D12DebugInfoLogger(NonNullPtr<D3D12Driver> driver)
{
ID3D12InfoQueue* infoQueue = NULL;
HRESULT result =
ID3D12Device5_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue, reinterpret_cast<void**>(&infoQueue));
if (FAILED(result))
{
LogError(driver, "Failed to get ID3D12InfoQueue", result);
return;
}
ID3D12InfoQueue1* infoQueue1 = nullptr;
result = ID3D12Device5_QueryInterface(driver->D3D12Device, IID_ID3D12InfoQueue1, reinterpret_cast<void**>(&infoQueue1));
if (FAILED(result))
{
return;
}
ID3D12InfoQueue1_RegisterMessageCallback(infoQueue1, OnD3D12DebugInfoMsg, D3D12_MESSAGE_CALLBACK_FLAG_NONE, NULL, NULL);
ID3D12InfoQueue1_Release(infoQueue);
}
#endif
#endif
void DestroyDriver_Internal(NonNullPtr<D3D12Driver> driver)
{
// Destroy pools
@@ -323,13 +436,12 @@ namespace Juliet::D3D12
Free(device.Get());
}
GraphicsDevice* CreateGraphicsDevice()
GraphicsDevice* CreateGraphicsDevice(bool enableDebug)
{
auto driver = static_cast<D3D12Driver*>(Calloc(1, sizeof(D3D12Driver)));
#ifdef IDXGIINFOQUEUE_SUPPORTED
static const bool kDebug = true;
if (kDebug)
if (enableDebug)
{
InitializeDXGIDebug(driver);
}
@@ -449,8 +561,12 @@ namespace Juliet::D3D12
return nullptr;
}
// TODO : D3D12 Debug Layer here
// InitializeD3D12DebugLayer()
#ifdef JULIET_DEBUG
if (enableDebug)
{
InitializeD3D12DebugLayer(driver);
}
#endif
result = D3D12CreateDeviceFuncPtr(reinterpret_cast<IUnknown*>(driver->DXGIAdapter), kD3DFeatureLevel,
IID_ID3D12Device5, reinterpret_cast<void**>(&driver->D3D12Device));
@@ -461,8 +577,18 @@ namespace Juliet::D3D12
return nullptr;
}
// TODO : D3D12 Debug Info Queue
// InitializeD3D12DebugInfoQueue
#ifdef JULIET_DEBUG
if (enableDebug)
{
if (!InitializeD3D12DebugInfoQueue(driver))
{
return nullptr;
}
#ifdef ID3D12InfoQueue1_SUPPORTED
InitializeD3D12DebugInfoLogger(driver);
#endif
}
#endif
// Check if UMA (unified memory architecture) is available. Used on APU i think ??
D3D12_FEATURE_DATA_ARCHITECTURE architecture;
@@ -616,6 +742,7 @@ namespace Juliet::D3D12
device->CreateShader = CreateShader;
device->DestroyShader = DestroyShader;
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
device->Driver = driver;
driver->GraphicsDevice = device;
@@ -633,9 +760,9 @@ namespace Juliet::D3D12
void DisposePendingResourcces(NonNullPtr<D3D12Driver> driver)
{
// TODO Destroy anything (buffer, texture, etc...)
for (uint32 idx = driver->GraphicsPipelinesToDisposeCount - 1; idx >= 0ul; --idx)
for (int32 idx = driver->GraphicsPipelinesToDisposeCount - 1; idx >= 0; --idx)
{
if (--driver->GraphicsPipelinesToDispose[idx]->ReferenceCount == 0)
if ((--(driver->GraphicsPipelinesToDispose[idx]->ReferenceCount)) == 0)
{
ReleaseGraphicsPipeline(driver->GraphicsPipelinesToDispose[idx]);

View File

@@ -46,6 +46,9 @@ namespace Juliet::D3D12
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFct;
ID3D12CommandQueue* GraphicsQueue;
D3D12_COMMAND_QUEUE_DESC QueueDesc[ToUnderlying(QueueType::Copy)];
#ifdef JULIET_DEBUG
ID3D12Debug1* D3D12Debug;
#endif
// Indirect commands signature
ID3D12CommandSignature* IndirectDrawCommandSignature;

View File

@@ -2,6 +2,7 @@
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12GraphicsPipeline.h>
#include <Graphics/D3D12/D3D12Shader.h>
#include <Graphics/D3D12/D3D12Utils.h>
#include <Core/Common/NonNullPtr.h>
@@ -318,11 +319,269 @@ namespace Juliet::D3D12
return true;
}
D3D12GraphicsRootSignature* CreateGraphicsRootSignature(NonNullPtr<D3D12Driver> renderer, NonNullPtr<D3D12Shader> vertexShader,
void DestroyGraphicsRootSignature(NonNullPtr<D3D12GraphicsRootSignature> rootSignature);
constexpr size_t kMaxRootSignatureParameters = 64;
D3D12GraphicsRootSignature* CreateGraphicsRootSignature(NonNullPtr<D3D12Driver> d3d12Driver,
NonNullPtr<D3D12Shader> vertexShader,
NonNullPtr<D3D12Shader> fragmentShader)
{
// TODO: Investigate bindless resources
D3D12_ROOT_PARAMETER rootParameters[kMaxRootSignatureParameters];
D3D12_DESCRIPTOR_RANGE descriptorRanges[kMaxRootSignatureParameters];
ZeroArray(rootParameters);
ZeroArray(descriptorRanges);
return nullptr;
uint32 parameterCount = 0;
uint32 rangeCount = 0;
D3D12_DESCRIPTOR_RANGE descriptorRange = {};
D3D12_ROOT_PARAMETER rootParameter = {};
auto d3d12GraphicsRootSignature =
static_cast<D3D12GraphicsRootSignature*>(Calloc(1, sizeof(D3D12GraphicsRootSignature)));
if (!d3d12GraphicsRootSignature)
{
return nullptr;
}
d3d12GraphicsRootSignature->VertexSamplerRootIndex = -1;
d3d12GraphicsRootSignature->VertexSamplerTextureRootIndex = -1;
d3d12GraphicsRootSignature->VertexStorageTextureRootIndex = -1;
d3d12GraphicsRootSignature->VertexStorageBufferRootIndex = -1;
d3d12GraphicsRootSignature->FragmentSamplerRootIndex = -1;
d3d12GraphicsRootSignature->FragmentSamplerTextureRootIndex = -1;
d3d12GraphicsRootSignature->FragmentStorageTextureRootIndex = -1;
d3d12GraphicsRootSignature->FragmentStorageBufferRootIndex = -1;
for (uint32 i = 0; i < GPUDriver::kMaxUniformBuffersPerStage; ++i)
{
d3d12GraphicsRootSignature->VertexUniformBufferRootIndex[i] = -1;
d3d12GraphicsRootSignature->FragmentUniformBufferRootIndex[i] = -1;
}
if (vertexShader->NumSamplers > 0)
{
// Vertex Samplers
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
descriptorRange.NumDescriptors = vertexShader->NumSamplers;
descriptorRange.BaseShaderRegister = 0;
descriptorRange.RegisterSpace = 0;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->VertexSamplerRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptorRange.NumDescriptors = vertexShader->NumSamplers;
descriptorRange.BaseShaderRegister = 0;
descriptorRange.RegisterSpace = 0;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->VertexSamplerTextureRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
}
if (vertexShader->NumStorageTextures)
{
// Vertex storage textures
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptorRange.NumDescriptors = vertexShader->NumStorageTextures;
descriptorRange.BaseShaderRegister = vertexShader->NumSamplers;
descriptorRange.RegisterSpace = 0;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->VertexStorageTextureRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
}
if (vertexShader->NumStorageBuffers)
{
// Vertex storage buffers
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptorRange.NumDescriptors = vertexShader->NumStorageBuffers;
descriptorRange.BaseShaderRegister = vertexShader->NumSamplers + vertexShader->NumStorageBuffers;
descriptorRange.RegisterSpace = 0;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->VertexStorageBufferRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
}
// Vertex Uniforms
for (uint32 i = 0; i < vertexShader->NumUniformBuffers; ++i)
{
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
rootParameter.Descriptor.ShaderRegister = i;
rootParameter.Descriptor.RegisterSpace = 1;
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->VertexUniformBufferRootIndex[i] = parameterCount;
parameterCount += 1;
}
if (fragmentShader->NumSamplers)
{
// Fragment Samplers
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
descriptorRange.NumDescriptors = fragmentShader->NumSamplers;
descriptorRange.BaseShaderRegister = 0;
descriptorRange.RegisterSpace = 2;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->FragmentSamplerRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptorRange.NumDescriptors = fragmentShader->NumSamplers;
descriptorRange.BaseShaderRegister = 0;
descriptorRange.RegisterSpace = 2;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->FragmentSamplerTextureRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
}
if (fragmentShader->NumStorageTextures)
{
// Fragment Storage Textures
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptorRange.NumDescriptors = fragmentShader->NumStorageTextures;
descriptorRange.BaseShaderRegister = fragmentShader->NumSamplers;
descriptorRange.RegisterSpace = 2;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->FragmentStorageTextureRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
}
if (fragmentShader->NumStorageBuffers)
{
// Fragment Storage Buffers
descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
descriptorRange.NumDescriptors = fragmentShader->NumStorageBuffers;
descriptorRange.BaseShaderRegister = fragmentShader->NumSamplers + fragmentShader->NumStorageTextures;
descriptorRange.RegisterSpace = 2;
descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
descriptorRanges[rangeCount] = descriptorRange;
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
rootParameter.DescriptorTable.NumDescriptorRanges = 1;
rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->FragmentStorageBufferRootIndex = parameterCount;
rangeCount += 1;
parameterCount += 1;
}
// Fragment Uniforms
for (uint32 i = 0; i < fragmentShader->NumUniformBuffers; ++i)
{
rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
rootParameter.Descriptor.ShaderRegister = i;
rootParameter.Descriptor.RegisterSpace = 3;
rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
rootParameters[parameterCount] = rootParameter;
d3d12GraphicsRootSignature->FragmentUniformBufferRootIndex[i] = parameterCount;
parameterCount += 1;
}
Assert(parameterCount <= kMaxRootSignatureParameters);
Assert(rangeCount <= kMaxRootSignatureParameters);
// Create the root signature description
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
rootSignatureDesc.NumParameters = parameterCount;
rootSignatureDesc.pParameters = rootParameters;
rootSignatureDesc.NumStaticSamplers = 0;
rootSignatureDesc.pStaticSamplers = nullptr;
rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
// Serialize the root signature
ID3DBlob* serializedRootSignature;
ID3DBlob* errorBlob;
HRESULT res = d3d12Driver->D3D12SerializeRootSignatureFct(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1_0,
&serializedRootSignature, &errorBlob);
if (FAILED(res))
{
if (errorBlob)
{
auto errorBuffer = ID3D10Blob_GetBufferPointer(errorBlob);
LogError(LogCategory::Graphics, "Failed to serialize RootSignature: %s", errorBuffer);
ID3D10Blob_Release(errorBlob);
}
DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
return NULL;
}
// Create the root signature
ID3D12RootSignature* rootSignature;
res = ID3D12Device_CreateRootSignature(d3d12Driver->D3D12Device, 0, ID3D10Blob_GetBufferPointer(serializedRootSignature),
ID3D10Blob_GetBufferSize(serializedRootSignature),
IID_ID3D12RootSignature, reinterpret_cast<void**>(&rootSignature));
if (FAILED(res))
{
if (errorBlob)
{
LogError(LogCategory::Graphics, "Failed to create RootSignature: %s",
(const char*)ID3D10Blob_GetBufferPointer(errorBlob));
ID3D10Blob_Release(errorBlob);
}
DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
return nullptr;
}
d3d12GraphicsRootSignature->Handle = rootSignature;
return d3d12GraphicsRootSignature;
}
void DestroyGraphicsRootSignature(NonNullPtr<D3D12GraphicsRootSignature> rootSignature)
@@ -331,9 +590,9 @@ namespace Juliet::D3D12
{
return;
}
if (rootSignature->handle)
if (rootSignature->Handle)
{
ID3D12RootSignature_Release(rootSignature->handle);
ID3D12RootSignature_Release(rootSignature->Handle);
}
Free(rootSignature.Get());
}
@@ -351,9 +610,9 @@ namespace Juliet::D3D12
psoDesc.PS.pShaderBytecode = fragmentShader->ByteCode.Data; // PS == Pixel Shader == Fragment Shader
psoDesc.PS.BytecodeLength = fragmentShader->ByteCode.Size;
D3D12_INPUT_ELEMENT_DESC inputElementDescs[D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
if (createInfo.VertexInputState.NumVertexAttributes > 0)
{
D3D12_INPUT_ELEMENT_DESC inputElementDescs[D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
psoDesc.InputLayout.pInputElementDescs = inputElementDescs;
psoDesc.InputLayout.NumElements = createInfo.VertexInputState.NumVertexAttributes;
ConvertVertexInputState(createInfo.VertexInputState, inputElementDescs, d3d12Driver->Semantic);
@@ -403,20 +662,19 @@ namespace Juliet::D3D12
psoDesc.NodeMask = 0;
D3D12GraphicsRootSignature* rootSignature = CreateGraphicsRootSignature(d3d12Driver, vertexShader, fragmentShader);
if (rootSignature == NULL)
if (rootSignature == nullptr)
{
Internal::ReleaseGraphicsPipeline(pipeline);
return nullptr;
}
pipeline->RootSignature = rootSignature;
psoDesc.pRootSignature = rootSignature->Handle;
ID3D12PipelineState* pipelineState;
HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState,
reinterpret_cast<void**>(&pipelineState));
if (FAILED(res))
{
LogError(d3d12Driver, "Could not create graphics pipeline state", res);
Internal::ReleaseGraphicsPipeline(pipeline);
return nullptr;

View File

@@ -16,7 +16,7 @@ namespace Juliet::D3D12
{
struct D3D12GraphicsRootSignature
{
ID3D12RootSignature* handle;
ID3D12RootSignature* Handle;
int32 VertexSamplerRootIndex;
int32 VertexSamplerTextureRootIndex;

View File

@@ -11,27 +11,22 @@
#define COBJMACROS
#define CINTERFACE ;
#include <d3dcompiler.h>
#include <DirectXMath.h>
#include <dxgi1_5.h>
#include <dxgi1_6.h>
#include "d3d12.h"
#include <d3d12shader.h>
// TODO: Should not use this when shipping
// Prebake the shaders and embed .dxil files
// When not shipping, thats ok to compile them
// #include <dxcapi.h>
#include <dxgi1_6.h>
#ifdef _DEBUG
#include <dxgidebug.h>
#endif
#include <dxgi.h>
//#include <dxgi.h>
#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__
#define IDXGIINFOQUEUE_SUPPORTED
#endif
#ifdef __ID3D12InfoQueue1_INTERFACE_DEFINED__
#define ID3D12InfoQueue1_SUPPORTED
#endif
#undef min
#undef max

View File

@@ -13,8 +13,8 @@ namespace Juliet::D3D12
return nullptr;
}
size_t allocSize = sizeof(D3D12Shader) + shaderByteCode.Size;
auto shader = static_cast<D3D12Shader*>(Malloc(allocSize));
size_t allocSize = sizeof(D3D12Shader) + shaderByteCode.Size;
auto shader = static_cast<D3D12Shader*>(Calloc(1, allocSize));
if (!shader)
{
LogError(LogCategory::Graphics, "Cannot allocate a new D3D12Shader: Out of memory");

View File

@@ -51,7 +51,7 @@ namespace Juliet
GraphicsDeviceFactory* chosenFactory = ChooseFactory(config);
if (chosenFactory)
{
GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice();
GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice(config.EnableDebug);
newDevice->Name = chosenFactory->Name;
return newDevice;
}
@@ -222,4 +222,10 @@ namespace Juliet
{
return device->CreateGraphicsPipeline(device->Driver, createInfo);
}
void DestroyGraphicsPipeline(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline)
{
device->DestroyGraphicsPipeline(device->Driver, graphicsPipeline);
}
} // namespace Juliet

View File

@@ -74,6 +74,7 @@ namespace Juliet
// Pipeline
GraphicsPipeline* (*CreateGraphicsPipeline)(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
void (*DestroyGraphicsPipeline)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> pipeline);
const char* Name = "Unknown";
GPUDriver* Driver = nullptr;
@@ -84,7 +85,7 @@ namespace Juliet
const char* Name = "Unknown";
DriverType Type = DriverType::Any;
bool (*CheckDriver)(void);
GraphicsDevice* (*CreateGraphicsDevice)(void);
GraphicsDevice* (*CreateGraphicsDevice)(bool enableDebug);
};
extern GraphicsDeviceFactory DX12DeviceFactory;

View File

@@ -9,12 +9,12 @@
#include <Core/Logging/LogTypes.h>
#include <Graphics/Graphics.h>
#include <Graphics/GraphicsConfig.h>
#include <Graphics/GraphicsPipeline.h>
#include <Graphics/RenderPass.h>
#include <Core/Common/String.h>
#include <Core/Memory/Utils.h>
#include <cstdlib>
#include <Graphics/GraphicsPipeline.h>
// TODO : Replace with message box from framework + call main and not winmain + subsystem
// TODO : Think how to do the draw pipeline.
@@ -49,6 +49,9 @@ void JulietApplication::Init()
Log(LogLevel::Message, LogCategory::Tool, "%s", CStr(GetBasePath()));
GraphicsConfig config;
#if JULIET_DEBUG
config.EnableDebug = true;
#endif
GraphicsDevice = CreateGraphicsDevice(config);
MainWindow = CreatePlatformWindow("Juliet Editor", 1280, 720);
@@ -81,13 +84,18 @@ void JulietApplication::Init()
pipelineCI.VertexShader = vertexShader;
pipelineCI.FragmentShader = fragmentShader;
pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
pipelineCI.TargetInfo = {
.ColorTargetDescriptions = &colorTargetDescription,
.NumColorTargets = 1,
};
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
.NumColorTargets = 1,
.DepthStencilFormat = {},
.HasDepthStencilTarget = false };
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
GraphicsPipeline* mainPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
GraphicsPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
if (GraphicsPipeline == nullptr)
{
LogError(LogCategory::Game, "Failed to create graphics pipeline!");
Running = false;
}
if (vertexShader)
{
@@ -97,6 +105,11 @@ void JulietApplication::Init()
{
DestroyShader(GraphicsDevice, fragmentShader);
}
if (Running == false)
{
return;
}
}
GameCode.Functions = reinterpret_cast<void**>(&Game);
@@ -114,8 +127,16 @@ void JulietApplication::Shutdown()
{
Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application...");
Game.Shutdown();
ShutdownHotReloadCode(GameCode);
if (GameCode.IsValid)
{
Game.Shutdown();
ShutdownHotReloadCode(GameCode);
}
if (GraphicsPipeline)
{
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
}
if (MainWindow && GraphicsDevice)
{

View File

@@ -4,6 +4,7 @@
#include <Core/HAL/Display/Display.h>
#include <Core/HAL/DynLib/DynamicLibrary.h>
#include <Core/HotReload/HotReload.h>
#include <Graphics/GraphicsPipeline.h>
namespace Juliet
{
@@ -20,9 +21,10 @@ class JulietApplication : public Juliet::IApplication
bool IsRunning() override;
private:
Juliet::Window* MainWindow = {};
Juliet::GraphicsDevice* GraphicsDevice = {};
Juliet::HotReloadCode GameCode = {};
Juliet::Window* MainWindow = {};
Juliet::GraphicsDevice* GraphicsDevice = {};
Juliet::HotReloadCode GameCode = {};
Juliet::GraphicsPipeline* GraphicsPipeline = {};
bool Running = false;
};