Graphics pipeline creation is working
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -11,5 +11,6 @@ namespace Juliet
|
||||
struct GraphicsConfig
|
||||
{
|
||||
DriverType PreferredDriver = DriverType::DX12;
|
||||
bool EnableDebug;
|
||||
};
|
||||
} // namespace Juliet
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace Juliet
|
||||
|
||||
enum class FillMode : uint8
|
||||
{
|
||||
Wireframe,
|
||||
Solid,
|
||||
Wireframe,
|
||||
Count
|
||||
};
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Juliet::D3D12
|
||||
{
|
||||
struct D3D12GraphicsRootSignature
|
||||
{
|
||||
ID3D12RootSignature* handle;
|
||||
ID3D12RootSignature* Handle;
|
||||
|
||||
int32 VertexSamplerRootIndex;
|
||||
int32 VertexSamplerTextureRootIndex;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user