Compare commits
2 Commits
f01c8c3ccb
...
f4ba25bec1
| Author | SHA1 | Date | |
|---|---|---|---|
| f4ba25bec1 | |||
| c9cd01bb31 |
@@ -20,8 +20,8 @@ using size_t = std::size_t;
|
|||||||
|
|
||||||
struct ByteBuffer
|
struct ByteBuffer
|
||||||
{
|
{
|
||||||
Byte* Data;
|
Byte* Data;
|
||||||
size_t Size;
|
size_t Size;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FunctionPtr = auto (*)(void) -> void;
|
using FunctionPtr = auto (*)(void) -> void;
|
||||||
@@ -37,7 +37,7 @@ constexpr uint16 uint16Max = MaxValueOf<uint16>();
|
|||||||
constexpr uint32 uint32Max = MaxValueOf<uint32>();
|
constexpr uint32 uint32Max = MaxValueOf<uint32>();
|
||||||
constexpr uint64 uint64Max = MaxValueOf<uint64>();
|
constexpr uint64 uint64Max = MaxValueOf<uint64>();
|
||||||
|
|
||||||
constexpr int8 int8Max = MaxValueOf<int8>();
|
constexpr int8 int8Max = MaxValueOf<int8>();
|
||||||
constexpr int16 int16Max = MaxValueOf<int16>();
|
constexpr int16 int16Max = MaxValueOf<int16>();
|
||||||
constexpr int32 int32Max = MaxValueOf<int32>();
|
constexpr int32 int32Max = MaxValueOf<int32>();
|
||||||
constexpr int64 int64Max = MaxValueOf<int64>();
|
constexpr int64 int64Max = MaxValueOf<int64>();
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ namespace Juliet
|
|||||||
uint16 Raw;
|
uint16 Raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool IsKeyDown(ScanCode scanCode);
|
extern JULIET_API bool IsKeyDown(ScanCode scanCode);
|
||||||
|
|
||||||
extern KeyMod GetKeyModState();
|
extern JULIET_API KeyMod GetKeyModState();
|
||||||
extern KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
|
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -10,10 +10,13 @@
|
|||||||
#include <Graphics/Shader.h>
|
#include <Graphics/Shader.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
#ifdef JULIET_DEBUG
|
||||||
|
#define ALLOW_SHADER_HOT_RELOAD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
// Graphics Interface
|
// Graphics Interface
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
|
|
||||||
// Opaque types
|
// Opaque types
|
||||||
struct CommandList;
|
struct CommandList;
|
||||||
struct GraphicsDevice;
|
struct GraphicsDevice;
|
||||||
@@ -118,6 +121,9 @@ namespace Juliet
|
|||||||
extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances,
|
extern JULIET_API void DrawPrimitives(NonNullPtr<RenderPass> renderPass, uint32 numVertices, uint32 numInstances,
|
||||||
uint32 firstVertex, uint32 firstInstance);
|
uint32 firstVertex, uint32 firstInstance);
|
||||||
|
|
||||||
|
// Fences
|
||||||
|
extern JULIET_API bool WaitUntilGPUIsIdle(NonNullPtr<GraphicsDevice> device);
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
extern JULIET_API Shader* CreateShader(NonNullPtr<GraphicsDevice> device, String filename, ShaderCreateInfo& shaderCreateInfo);
|
extern JULIET_API Shader* CreateShader(NonNullPtr<GraphicsDevice> device, String filename, ShaderCreateInfo& shaderCreateInfo);
|
||||||
extern JULIET_API void DestroyShader(NonNullPtr<GraphicsDevice> device, NonNullPtr<Shader> shader);
|
extern JULIET_API void DestroyShader(NonNullPtr<GraphicsDevice> device, NonNullPtr<Shader> shader);
|
||||||
@@ -126,5 +132,10 @@ namespace Juliet
|
|||||||
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
|
extern JULIET_API GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GraphicsDevice> device,
|
||||||
const GraphicsPipelineCreateInfo& createInfo);
|
const GraphicsPipelineCreateInfo& createInfo);
|
||||||
extern JULIET_API void DestroyGraphicsPipeline(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
extern JULIET_API void DestroyGraphicsPipeline(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
// Allows updating the graphics pipeline shaders. Can update either one or both shaders.
|
||||||
|
extern JULIET_API bool UpdateGraphicsPipelineShaders(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
||||||
|
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ namespace Juliet::D3D12
|
|||||||
auto* windowData = d3d12Driver->WindowData;
|
auto* windowData = d3d12Driver->WindowData;
|
||||||
Assert(windowData && "Trying to destroy a swapchain but no Window Data exists");
|
Assert(windowData && "Trying to destroy a swapchain but no Window Data exists");
|
||||||
|
|
||||||
Wait(driver);
|
WaitUntilGPUIsIdle(driver);
|
||||||
|
|
||||||
for (uint32 idx = 0; idx < GPUDriver::kMaxFramesInFlight; idx += 1)
|
for (uint32 idx = 0; idx < GPUDriver::kMaxFramesInFlight; idx += 1)
|
||||||
{
|
{
|
||||||
@@ -748,13 +748,14 @@ namespace Juliet::D3D12
|
|||||||
device->SetStencilReference = SetStencilReference;
|
device->SetStencilReference = SetStencilReference;
|
||||||
device->BindGraphicsPipeline = BindGraphicsPipeline;
|
device->BindGraphicsPipeline = BindGraphicsPipeline;
|
||||||
device->DrawPrimitives = DrawPrimitives;
|
device->DrawPrimitives = DrawPrimitives;
|
||||||
device->Wait = Wait;
|
device->WaitUntilGPUIsIdle = WaitUntilGPUIsIdle;
|
||||||
device->QueryFence = QueryFence;
|
device->QueryFence = QueryFence;
|
||||||
device->ReleaseFence = ReleaseFence;
|
device->ReleaseFence = ReleaseFence;
|
||||||
device->CreateShader = CreateShader;
|
device->CreateShader = CreateShader;
|
||||||
device->DestroyShader = DestroyShader;
|
device->DestroyShader = DestroyShader;
|
||||||
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
|
device->CreateGraphicsPipeline = CreateGraphicsPipeline;
|
||||||
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
|
device->DestroyGraphicsPipeline = DestroyGraphicsPipeline;
|
||||||
|
device->UpdateGraphicsPipelineShaders = UpdateGraphicsPipelineShaders;
|
||||||
|
|
||||||
device->Driver = driver;
|
device->Driver = driver;
|
||||||
device->DebugEnabled = enableDebug;
|
device->DebugEnabled = enableDebug;
|
||||||
|
|||||||
@@ -596,6 +596,25 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
Free(rootSignature.Get());
|
Free(rootSignature.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CopyShader(NonNullPtr<D3D12Shader> destination, NonNullPtr<D3D12Shader> source)
|
||||||
|
{
|
||||||
|
D3D12Shader* src = source.Get();
|
||||||
|
D3D12Shader* dst = destination.Get();
|
||||||
|
|
||||||
|
ByteBuffer dstBuffer = dst->ByteCode;
|
||||||
|
|
||||||
|
if (src->ByteCode.Size != dstBuffer.Size)
|
||||||
|
{
|
||||||
|
dstBuffer.Data = static_cast<Byte*>(Realloc(dstBuffer.Data, src->ByteCode.Size));
|
||||||
|
dstBuffer.Size = src->ByteCode.Size;
|
||||||
|
}
|
||||||
|
// Copy the shader data. Infortunately this will overwrite the bytecode if it exists so we patch it back just after
|
||||||
|
MemCopy(dst, src, sizeof(D3D12Shader));
|
||||||
|
dst->ByteCode = dstBuffer;
|
||||||
|
|
||||||
|
MemCopy(dst->ByteCode.Data, src->ByteCode.Data, src->ByteCode.Size);
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo)
|
GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo)
|
||||||
@@ -668,7 +687,7 @@ namespace Juliet::D3D12
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pipeline->RootSignature = rootSignature;
|
pipeline->RootSignature = rootSignature;
|
||||||
psoDesc.pRootSignature = rootSignature->Handle;
|
psoDesc.pRootSignature = rootSignature->Handle;
|
||||||
|
|
||||||
ID3D12PipelineState* pipelineState;
|
ID3D12PipelineState* pipelineState;
|
||||||
HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState,
|
HRESULT res = ID3D12Device_CreateGraphicsPipelineState(d3d12Driver->D3D12Device, &psoDesc, IID_ID3D12PipelineState,
|
||||||
@@ -702,6 +721,16 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
pipeline->ReferenceCount = 0;
|
pipeline->ReferenceCount = 0;
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
// Save the PSODesc and shaders to be able to recreate the graphics pipeline when needed
|
||||||
|
pipeline->PSODescTemplate = psoDesc;
|
||||||
|
|
||||||
|
pipeline->VertexShaderCache = static_cast<D3D12Shader*>(Calloc(1, sizeof(D3D12Shader)));
|
||||||
|
pipeline->FragmentShaderCache = static_cast<D3D12Shader*>(Calloc(1, sizeof(D3D12Shader)));
|
||||||
|
CopyShader(pipeline->VertexShaderCache, vertexShader);
|
||||||
|
CopyShader(pipeline->FragmentShaderCache, fragmentShader);
|
||||||
|
#endif
|
||||||
|
|
||||||
return reinterpret_cast<GraphicsPipeline*>(pipeline);
|
return reinterpret_cast<GraphicsPipeline*>(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,6 +750,90 @@ namespace Juliet::D3D12
|
|||||||
d3d12Driver->GraphicsPipelinesToDisposeCount += 1;
|
d3d12Driver->GraphicsPipelinesToDisposeCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
bool UpdateGraphicsPipelineShaders(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
||||||
|
Shader* optional_vertexShader, Shader* optional_fragmentShader)
|
||||||
|
{
|
||||||
|
auto d3d12Driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
auto d3d12GraphicsPipeline = reinterpret_cast<D3D12GraphicsPipeline*>(graphicsPipeline.Get());
|
||||||
|
|
||||||
|
Assert(d3d12GraphicsPipeline->ReferenceCount == 0 &&
|
||||||
|
"Trying to update a d3d12 graphics pipeline that is currently being used! Call WaitUntilGPUIsIdle "
|
||||||
|
"before updating!");
|
||||||
|
|
||||||
|
auto vertexShader = reinterpret_cast<D3D12Shader*>(optional_vertexShader);
|
||||||
|
auto fragmentShader = reinterpret_cast<D3D12Shader*>(optional_fragmentShader);
|
||||||
|
|
||||||
|
if (!vertexShader)
|
||||||
|
{
|
||||||
|
vertexShader = d3d12GraphicsPipeline->VertexShaderCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fragmentShader)
|
||||||
|
{
|
||||||
|
fragmentShader = d3d12GraphicsPipeline->FragmentShaderCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recreate a new root signature and pipeline state
|
||||||
|
D3D12GraphicsRootSignature* rootSignature = CreateGraphicsRootSignature(d3d12Driver, vertexShader, fragmentShader);
|
||||||
|
if (rootSignature == nullptr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto psoDesc = d3d12GraphicsPipeline->PSODescTemplate;
|
||||||
|
psoDesc.VS.pShaderBytecode = vertexShader->ByteCode.Data;
|
||||||
|
psoDesc.VS.BytecodeLength = vertexShader->ByteCode.Size;
|
||||||
|
psoDesc.PS.pShaderBytecode = fragmentShader->ByteCode.Data;
|
||||||
|
psoDesc.PS.BytecodeLength = fragmentShader->ByteCode.Size;
|
||||||
|
|
||||||
|
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);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
d3d12GraphicsPipeline->VertexSamplerCount = vertexShader->NumSamplers;
|
||||||
|
d3d12GraphicsPipeline->VertexStorageTextureCount = vertexShader->NumStorageTextures;
|
||||||
|
d3d12GraphicsPipeline->VertexStorageBufferCount = vertexShader->NumStorageBuffers;
|
||||||
|
d3d12GraphicsPipeline->VertexUniformBufferCount = vertexShader->NumUniformBuffers;
|
||||||
|
|
||||||
|
d3d12GraphicsPipeline->FragmentSamplerCount = fragmentShader->NumSamplers;
|
||||||
|
d3d12GraphicsPipeline->FragmentStorageTextureCount = fragmentShader->NumStorageTextures;
|
||||||
|
d3d12GraphicsPipeline->FragmentStorageBufferCount = fragmentShader->NumStorageBuffers;
|
||||||
|
d3d12GraphicsPipeline->FragmentUniformBufferCount = fragmentShader->NumUniformBuffers;
|
||||||
|
|
||||||
|
// If everything worked, we patch the graphics pipeline and destroy everything irrelevant
|
||||||
|
if (d3d12GraphicsPipeline->PipelineState)
|
||||||
|
{
|
||||||
|
ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState);
|
||||||
|
}
|
||||||
|
d3d12GraphicsPipeline->PipelineState = pipelineState;
|
||||||
|
|
||||||
|
if (d3d12GraphicsPipeline->RootSignature)
|
||||||
|
{
|
||||||
|
DestroyGraphicsRootSignature(d3d12GraphicsPipeline->RootSignature);
|
||||||
|
}
|
||||||
|
d3d12GraphicsPipeline->RootSignature = rootSignature;
|
||||||
|
|
||||||
|
if (vertexShader != d3d12GraphicsPipeline->VertexShaderCache)
|
||||||
|
{
|
||||||
|
CopyShader(d3d12GraphicsPipeline->VertexShaderCache, vertexShader);
|
||||||
|
}
|
||||||
|
if (fragmentShader != d3d12GraphicsPipeline->FragmentShaderCache)
|
||||||
|
{
|
||||||
|
CopyShader(d3d12GraphicsPipeline->FragmentShaderCache, fragmentShader);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
void ReleaseGraphicsPipeline(NonNullPtr<D3D12GraphicsPipeline> d3d12GraphicsPipeline)
|
void ReleaseGraphicsPipeline(NonNullPtr<D3D12GraphicsPipeline> d3d12GraphicsPipeline)
|
||||||
@@ -730,6 +843,12 @@ namespace Juliet::D3D12
|
|||||||
ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState);
|
ID3D12PipelineState_Release(d3d12GraphicsPipeline->PipelineState);
|
||||||
}
|
}
|
||||||
DestroyGraphicsRootSignature(d3d12GraphicsPipeline->RootSignature);
|
DestroyGraphicsRootSignature(d3d12GraphicsPipeline->RootSignature);
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
SafeFree(d3d12GraphicsPipeline->VertexShaderCache);
|
||||||
|
SafeFree(d3d12GraphicsPipeline->FragmentShaderCache);
|
||||||
|
#endif
|
||||||
|
|
||||||
Free(d3d12GraphicsPipeline.Get());
|
Free(d3d12GraphicsPipeline.Get());
|
||||||
}
|
}
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/Common/NonNullPtr.h>
|
#include <Core/Common/NonNullPtr.h>
|
||||||
|
#include <D3D12Shader.h>
|
||||||
#include <Graphics/D3D12/D3D12Includes.h>
|
#include <Graphics/D3D12/D3D12Includes.h>
|
||||||
#include <Graphics/GraphicsDevice.h>
|
#include <Graphics/GraphicsDevice.h>
|
||||||
#include <Graphics/GraphicsPipeline.h>
|
#include <Graphics/GraphicsPipeline.h>
|
||||||
@@ -35,6 +36,17 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
struct D3D12GraphicsPipeline
|
struct D3D12GraphicsPipeline
|
||||||
{
|
{
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
// Template to recreate an ID3D12PipelineState when shader are hot reloaded
|
||||||
|
// Stripped out in shipping build as the struct is huge
|
||||||
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC PSODescTemplate;
|
||||||
|
|
||||||
|
// Keeping shaders byte code to make it easier to recreate the ID3D12PipelineState
|
||||||
|
// Those will be freed when the pipeline is destroyed or updated
|
||||||
|
D3D12Shader * VertexShaderCache;
|
||||||
|
D3D12Shader * FragmentShaderCache;
|
||||||
|
#endif
|
||||||
|
|
||||||
ID3D12PipelineState* PipelineState;
|
ID3D12PipelineState* PipelineState;
|
||||||
D3D12GraphicsRootSignature* RootSignature;
|
D3D12GraphicsRootSignature* RootSignature;
|
||||||
PrimitiveType PrimitiveType;
|
PrimitiveType PrimitiveType;
|
||||||
@@ -56,7 +68,8 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
extern GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
|
extern GraphicsPipeline* CreateGraphicsPipeline(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
|
||||||
extern void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
extern void DestroyGraphicsPipeline(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline);
|
||||||
|
extern bool UpdateGraphicsPipelineShaders(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
||||||
|
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
extern void ReleaseGraphicsPipeline(NonNullPtr<D3D12GraphicsPipeline> d3d12GraphicsPipeline);
|
extern void ReleaseGraphicsPipeline(NonNullPtr<D3D12GraphicsPipeline> d3d12GraphicsPipeline);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool Wait(NonNullPtr<GPUDriver> driver)
|
bool WaitUntilGPUIsIdle(NonNullPtr<GPUDriver> driver)
|
||||||
{
|
{
|
||||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
|
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Juliet::D3D12
|
|||||||
int32 ReferenceCount; // TODO : Atomic
|
int32 ReferenceCount; // TODO : Atomic
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool Wait(NonNullPtr<GPUDriver> driver);
|
extern bool WaitUntilGPUIsIdle(NonNullPtr<GPUDriver> driver);
|
||||||
extern bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences);
|
extern bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences);
|
||||||
extern bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
extern bool QueryFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||||
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||||
|
|||||||
@@ -258,6 +258,12 @@ namespace Juliet
|
|||||||
commandListHeader->Device->DrawPrimitives(commandList, numVertices, numInstances, firstVertex, firstInstance);
|
commandListHeader->Device->DrawPrimitives(commandList, numVertices, numInstances, firstVertex, firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fences
|
||||||
|
bool WaitUntilGPUIsIdle(NonNullPtr<GraphicsDevice> device)
|
||||||
|
{
|
||||||
|
return device->WaitUntilGPUIsIdle(device->Driver);
|
||||||
|
}
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
Shader* CreateShader(NonNullPtr<GraphicsDevice> device, String filename, ShaderCreateInfo& shaderCreateInfo)
|
Shader* CreateShader(NonNullPtr<GraphicsDevice> device, String filename, ShaderCreateInfo& shaderCreateInfo)
|
||||||
{
|
{
|
||||||
@@ -305,4 +311,11 @@ namespace Juliet
|
|||||||
device->DestroyGraphicsPipeline(device->Driver, graphicsPipeline);
|
device->DestroyGraphicsPipeline(device->Driver, graphicsPipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
bool UpdateGraphicsPipelineShaders(NonNullPtr<GraphicsDevice> device, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
||||||
|
Shader* optional_vertexShader, Shader* optional_fragmentShader)
|
||||||
|
{
|
||||||
|
return device->UpdateGraphicsPipelineShaders(device->Driver, graphicsPipeline, optional_vertexShader, optional_fragmentShader);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace Juliet
|
|||||||
uint32 firstVertex, uint32 firstInstance);
|
uint32 firstVertex, uint32 firstInstance);
|
||||||
|
|
||||||
// Fences
|
// Fences
|
||||||
bool (*Wait)(NonNullPtr<GPUDriver> driver);
|
bool (*WaitUntilGPUIsIdle)(NonNullPtr<GPUDriver> driver);
|
||||||
bool (*QueryFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
bool (*QueryFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||||
void (*ReleaseFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
void (*ReleaseFence)(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
|
||||||
|
|
||||||
@@ -80,6 +80,8 @@ namespace Juliet
|
|||||||
// Pipeline
|
// Pipeline
|
||||||
GraphicsPipeline* (*CreateGraphicsPipeline)(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
|
GraphicsPipeline* (*CreateGraphicsPipeline)(NonNullPtr<GPUDriver> driver, const GraphicsPipelineCreateInfo& createInfo);
|
||||||
void (*DestroyGraphicsPipeline)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> pipeline);
|
void (*DestroyGraphicsPipeline)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> pipeline);
|
||||||
|
bool (*UpdateGraphicsPipelineShaders)(NonNullPtr<GPUDriver> driver, NonNullPtr<GraphicsPipeline> graphicsPipeline,
|
||||||
|
Shader* optional_vertexShader, Shader* optional_fragmentShader);
|
||||||
|
|
||||||
const char* Name = "Unknown";
|
const char* Name = "Unknown";
|
||||||
GPUDriver* Driver = nullptr;
|
GPUDriver* Driver = nullptr;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <main.h>
|
#include <main.h>
|
||||||
|
|
||||||
#include <Core/Application/ApplicationManager.h>
|
#include <Core/Application/ApplicationManager.h>
|
||||||
|
#include <Core/Common/EnumUtils.h>
|
||||||
#include <Core/HAL/Display/Display.h>
|
#include <Core/HAL/Display/Display.h>
|
||||||
#include <Core/HAL/Event/SystemEvent.h>
|
#include <Core/HAL/Event/SystemEvent.h>
|
||||||
#include <Core/HAL/Filesystem/Filesystem.h>
|
#include <Core/HAL/Filesystem/Filesystem.h>
|
||||||
@@ -158,6 +159,9 @@ void JulietApplication::Shutdown()
|
|||||||
|
|
||||||
void JulietApplication::Update()
|
void JulietApplication::Update()
|
||||||
{
|
{
|
||||||
|
bool reloadShaders = false;
|
||||||
|
static bool reloadShadersDebounce = false;
|
||||||
|
|
||||||
SystemEvent evt;
|
SystemEvent evt;
|
||||||
while (GetEvent(evt))
|
while (GetEvent(evt))
|
||||||
{
|
{
|
||||||
@@ -168,6 +172,23 @@ void JulietApplication::Update()
|
|||||||
Running = false;
|
Running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (evt.Type == EventType::Key_Down)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shader hot reload using keyboard.
|
||||||
|
// TODO: Add Input debounce in the library. (Just pressed vs pressed)
|
||||||
|
if (!reloadShadersDebounce && ((GetKeyModState() & KeyMod::Alt) != KeyMod::None) && IsKeyDown(ScanCode::R))
|
||||||
|
{
|
||||||
|
reloadShaders = true;
|
||||||
|
reloadShadersDebounce = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reloadShadersDebounce && !IsKeyDown(ScanCode::R))
|
||||||
|
{
|
||||||
|
reloadShadersDebounce = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Game.Update(0.0f);
|
Game.Update(0.0f);
|
||||||
@@ -177,6 +198,36 @@ void JulietApplication::Update()
|
|||||||
ReloadCode(GameCode);
|
ReloadCode(GameCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reloadShaders)
|
||||||
|
{
|
||||||
|
// We need to wait for the gpu to be idle to recreate our graphics pipelines
|
||||||
|
WaitUntilGPUIsIdle(GraphicsDevice);
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
String entryPoint = WrapString("main");
|
||||||
|
ShaderCreateInfo shaderCI = {};
|
||||||
|
shaderCI.EntryPoint = entryPoint;
|
||||||
|
String shaderPath = WrapString("../../../Assets/compiled/Triangle.vert.dxil");
|
||||||
|
shaderCI.Stage = ShaderStage::Vertex;
|
||||||
|
Shader* vertexShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
|
||||||
|
|
||||||
|
shaderPath = WrapString("../../../Assets/compiled/SolidColor.frag.dxil");
|
||||||
|
shaderCI.Stage = ShaderStage::Fragment;
|
||||||
|
Shader* fragmentShader = CreateShader(GraphicsDevice, shaderPath, shaderCI);
|
||||||
|
|
||||||
|
UpdateGraphicsPipelineShaders(GraphicsDevice, GraphicsPipeline, vertexShader, fragmentShader);
|
||||||
|
|
||||||
|
if (vertexShader)
|
||||||
|
{
|
||||||
|
DestroyShader(GraphicsDevice, vertexShader);
|
||||||
|
}
|
||||||
|
if (fragmentShader)
|
||||||
|
{
|
||||||
|
DestroyShader(GraphicsDevice, fragmentShader);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Draw here for now
|
// Draw here for now
|
||||||
// 1) Acquire a Command Buffer
|
// 1) Acquire a Command Buffer
|
||||||
CommandList* cmdList = AcquireCommandList(GraphicsDevice, QueueType::Graphics);
|
CommandList* cmdList = AcquireCommandList(GraphicsDevice, QueueType::Graphics);
|
||||||
|
|||||||
Reference in New Issue
Block a user