Meshrenderer first step. Adding logs to debug a weird crash since the add of mesh renderer and some clean up.
This commit is contained in:
@@ -227,6 +227,10 @@
|
|||||||
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp" />
|
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="include\Graphics\MeshRenderer.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\Graphics\MeshRenderer.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{ab9c7e88-6c94-4f93-bc2a-7f5284b7d434}</ProjectGuid>
|
<ProjectGuid>{ab9c7e88-6c94-4f93-bc2a-7f5284b7d434}</ProjectGuid>
|
||||||
|
|||||||
@@ -98,6 +98,34 @@ namespace Juliet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PushBack(const Type* buffer, size_t amount)
|
||||||
|
{
|
||||||
|
Assert(Arena);
|
||||||
|
|
||||||
|
if (Count + amount > Capacity)
|
||||||
|
{
|
||||||
|
if (Capacity == 0 && Count + amount < ReserveSize)
|
||||||
|
{
|
||||||
|
Reserve(ReserveSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t newCapacity = Max(Capacity * 2, AlignPow2(Capacity + amount, AlignOf(Type)));
|
||||||
|
Reserve(newCapacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Type* dst = Data + Count;
|
||||||
|
MemCopy(dst, buffer, amount * sizeof(Type));
|
||||||
|
|
||||||
|
if (Count == 0)
|
||||||
|
{
|
||||||
|
DataFirst = dst;
|
||||||
|
}
|
||||||
|
DataLast = dst + amount;
|
||||||
|
Count += amount;
|
||||||
|
}
|
||||||
|
|
||||||
void PushBack(const Type& value)
|
void PushBack(const Type& value)
|
||||||
{
|
{
|
||||||
Assert(Arena);
|
Assert(Arena);
|
||||||
@@ -172,6 +200,8 @@ namespace Juliet
|
|||||||
Capacity = 0;
|
Capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const { return Count == 0; }
|
||||||
|
|
||||||
// C++ Accessors for loop supports and Index based access
|
// C++ Accessors for loop supports and Index based access
|
||||||
Type& operator[](size_t index) { return DataFirst[index]; }
|
Type& operator[](size_t index) { return DataFirst[index]; }
|
||||||
const Type& operator[](size_t index) const { return DataFirst[index]; }
|
const Type& operator[](size_t index) const { return DataFirst[index]; }
|
||||||
|
|||||||
@@ -11,18 +11,10 @@ namespace Juliet
|
|||||||
|
|
||||||
struct Mesh
|
struct Mesh
|
||||||
{
|
{
|
||||||
Vertex* Vertices;
|
|
||||||
uint16* Indices;
|
|
||||||
|
|
||||||
size_t VertexCount;
|
size_t VertexCount;
|
||||||
size_t IndexCount;
|
size_t IndexCount;
|
||||||
|
|
||||||
index_t VertexOffset;
|
index_t VertexOffset;
|
||||||
index_t IndexOffset;
|
index_t IndexOffset;
|
||||||
index_t IndexByteOffset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JULIET_API Mesh* CreateCubeMesh(NonNullPtr<Arena> arena);
|
|
||||||
JULIET_API Mesh* CreateQuadMesh(NonNullPtr<Arena> arena);
|
|
||||||
JULIET_API void DestroyMesh(NonNullPtr<Mesh> mesh);
|
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
63
Juliet/include/Graphics/MeshRenderer.h
Normal file
63
Juliet/include/Graphics/MeshRenderer.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/Container/Vector.h>
|
||||||
|
#include <Core/Math/Matrix.h>
|
||||||
|
#include <Graphics/VertexData.h>
|
||||||
|
#include <Juliet.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
struct GraphicsTransferBuffer;
|
||||||
|
struct RenderPass;
|
||||||
|
struct CommandList;
|
||||||
|
struct GraphicsBuffer;
|
||||||
|
struct Window;
|
||||||
|
struct GraphicsPipeline;
|
||||||
|
struct GraphicsDevice;
|
||||||
|
struct Mesh;
|
||||||
|
|
||||||
|
using MeshID = index_t;
|
||||||
|
|
||||||
|
constexpr size_t kGeometryPage = Megabytes(64);
|
||||||
|
constexpr size_t kIndexPage = Megabytes(32);
|
||||||
|
constexpr size_t kDefaultMeshNumber = 500;
|
||||||
|
constexpr size_t kDefaultVertexCount = 2'000'000; // Fit less than one geometry page
|
||||||
|
constexpr size_t kDefaultIndexCount = 16'000'000; // Fit less than one index page
|
||||||
|
|
||||||
|
struct MeshRenderer
|
||||||
|
{
|
||||||
|
// Note we prevent realloc for now.
|
||||||
|
VectorArena<Mesh, kDefaultMeshNumber, false> Meshes;
|
||||||
|
VectorArena<Vertex, kDefaultVertexCount, false> Vertices;
|
||||||
|
VectorArena<Index, kDefaultIndexCount, false> Indices;
|
||||||
|
|
||||||
|
GraphicsBuffer* VertexBuffer;
|
||||||
|
GraphicsBuffer* IndexBuffer;
|
||||||
|
GraphicsTransferBuffer* StreamCopyBuffer;
|
||||||
|
GraphicsTransferBuffer* LoadCopyBuffer;
|
||||||
|
|
||||||
|
GraphicsDevice* Device;
|
||||||
|
GraphicsPipeline* Pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PushData
|
||||||
|
{
|
||||||
|
Matrix ViewProjection;
|
||||||
|
uint32 BufferIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] JULIET_API bool InitializeMeshRenderer(NonNullPtr<Arena> arena, NonNullPtr<GraphicsDevice> device,
|
||||||
|
NonNullPtr<Window> window);
|
||||||
|
JULIET_API void ShutdownMeshRenderer();
|
||||||
|
JULIET_API void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList);
|
||||||
|
JULIET_API void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData);
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
[[nodiscard]] JULIET_API MeshID AddCube();
|
||||||
|
[[nodiscard]] JULIET_API MeshID AddQuad();
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
JULIET_API void ReloadMeshRendererShaders();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace Juliet
|
||||||
@@ -7,4 +7,6 @@ namespace Juliet
|
|||||||
float Position[3];
|
float Position[3];
|
||||||
float Color[4];
|
float Color[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Index = uint16;
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
@@ -42,15 +42,15 @@ namespace Juliet
|
|||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
if (NonNullPtr window = EngineInstance.Application->GetPlatformWindow())
|
if (NonNullPtr window = EngineInstance.Application->GetPlatformWindow())
|
||||||
{
|
{
|
||||||
ImGuiService::Initialize(window);
|
// ImGuiService::Initialize(window);
|
||||||
ImGui::SetCurrentContext(ImGuiService::GetContext());
|
// ImGui::SetCurrentContext(ImGuiService::GetContext());
|
||||||
|
|
||||||
if (device)
|
if (device)
|
||||||
{
|
{
|
||||||
ImGuiRenderer_Initialize(device);
|
// ImGuiRenderer_Initialize(device);
|
||||||
|
|
||||||
// Run Unit Tests automatically
|
// Run Unit Tests automatically
|
||||||
ImGuiService::RunTests();
|
// ImGuiService::RunTests();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -64,9 +64,9 @@ namespace Juliet
|
|||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
if (device)
|
if (device)
|
||||||
{
|
{
|
||||||
ImGuiRenderer_Shutdown(device);
|
// ImGuiRenderer_Shutdown(device);
|
||||||
}
|
}
|
||||||
ImGuiService::Shutdown();
|
// ImGuiService::Shutdown();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// DebugDisplay system
|
// DebugDisplay system
|
||||||
@@ -107,7 +107,7 @@ namespace Juliet
|
|||||||
EngineInstance.Application->OnPreRender(cmdList);
|
EngineInstance.Application->OnPreRender(cmdList);
|
||||||
|
|
||||||
// Prepare debug display data (before render pass)
|
// Prepare debug display data (before render pass)
|
||||||
DebugDisplay_Prepare(cmdList);
|
// DebugDisplay_Prepare(cmdList);
|
||||||
|
|
||||||
// Get render targets from application
|
// Get render targets from application
|
||||||
ColorTargetInfo colorInfo = EngineInstance.Application->GetColorTargetInfo(swapChainTexture);
|
ColorTargetInfo colorInfo = EngineInstance.Application->GetColorTargetInfo(swapChainTexture);
|
||||||
@@ -119,12 +119,12 @@ namespace Juliet
|
|||||||
EngineInstance.Application->OnRender(pass, cmdList);
|
EngineInstance.Application->OnRender(pass, cmdList);
|
||||||
|
|
||||||
// Debug display flush (inside render pass)
|
// Debug display flush (inside render pass)
|
||||||
Camera debugCamera = EngineInstance.Application->GetDebugCamera();
|
// Camera debugCamera = EngineInstance.Application->GetDebugCamera();
|
||||||
DebugDisplay_Flush(cmdList, pass, debugCamera);
|
// DebugDisplay_Flush(cmdList, pass, debugCamera);
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
// ImGui rendering (always last before EndRenderPass)
|
// ImGui rendering (always last before EndRenderPass)
|
||||||
ImGuiRenderer_Render(cmdList, pass);
|
// ImGuiRenderer_Render(cmdList, pass);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EndRenderPass(pass);
|
EndRenderPass(pass);
|
||||||
@@ -178,7 +178,7 @@ namespace Juliet
|
|||||||
while (EngineInstance.Application->IsRunning())
|
while (EngineInstance.Application->IsRunning())
|
||||||
{
|
{
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
ImGuiRenderer_NewFrame();
|
// ImGuiRenderer_NewFrame();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Logic tick
|
// Logic tick
|
||||||
|
|||||||
@@ -113,10 +113,10 @@ namespace Juliet::D3D12
|
|||||||
{
|
{
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||||
|
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||||
}
|
}
|
||||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -142,10 +142,10 @@ namespace Juliet::D3D12
|
|||||||
{
|
{
|
||||||
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||||
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
|
||||||
|
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||||
}
|
}
|
||||||
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,7 +246,8 @@ namespace Juliet::D3D12
|
|||||||
d3d12Driver->GraphicsQueue->ExecuteCommandLists(1, ppCommandLists);
|
d3d12Driver->GraphicsQueue->ExecuteCommandLists(1, ppCommandLists);
|
||||||
|
|
||||||
// Acquire a fence and set it to the in-flight fence
|
// Acquire a fence and set it to the in-flight fence
|
||||||
d3d12CommandList->InFlightFence = Internal::AcquireFence(d3d12Driver);
|
d3d12CommandList->InFlightFence =
|
||||||
|
Internal::AcquireFence(d3d12Driver JULIET_DEBUG_PARAM(ConstString("SubmitCommandLists")));
|
||||||
if (!d3d12CommandList->InFlightFence)
|
if (!d3d12CommandList->InFlightFence)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -487,7 +488,8 @@ namespace Juliet::D3D12
|
|||||||
// Release Fence if needed
|
// Release Fence if needed
|
||||||
if (commandList->AutoReleaseFence)
|
if (commandList->AutoReleaseFence)
|
||||||
{
|
{
|
||||||
ReleaseFence(driver.Get(), reinterpret_cast<Fence*>(commandList->InFlightFence));
|
ReleaseFence(driver.Get(), reinterpret_cast<Fence*>(commandList->InFlightFence)
|
||||||
|
JULIET_DEBUG_PARAM(ConstString("CleanCommandList")));
|
||||||
commandList->InFlightFence = nullptr;
|
commandList->InFlightFence = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -604,7 +604,8 @@ namespace Juliet::D3D12
|
|||||||
{
|
{
|
||||||
if (windowData->InFlightFences[idx] != nullptr)
|
if (windowData->InFlightFences[idx] != nullptr)
|
||||||
{
|
{
|
||||||
ReleaseFence(driver, windowData->InFlightFences[idx]);
|
ReleaseFence(driver,
|
||||||
|
windowData->InFlightFences[idx] JULIET_DEBUG_PARAM(ConstString("DeatchFromWindow")));
|
||||||
windowData->InFlightFences[idx] = nullptr;
|
windowData->InFlightFences[idx] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,7 +140,8 @@ namespace Juliet::D3D12
|
|||||||
{
|
{
|
||||||
// Wait until the fence for the frame is signaled.
|
// Wait until the fence for the frame is signaled.
|
||||||
// In VSYNC this means waiting that the least recent presented frame is done
|
// In VSYNC this means waiting that the least recent presented frame is done
|
||||||
if (!Wait(driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter], 1))
|
if (!Wait(driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter],
|
||||||
|
1 JULIET_DEBUG_PARAM(ConstString("AcquireSwapChainTexture"))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -155,7 +156,8 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseFence(driver, windowData->InFlightFences[windowData->WindowFrameCounter]);
|
ReleaseFence(driver, windowData->InFlightFences[windowData->WindowFrameCounter] JULIET_DEBUG_PARAM(
|
||||||
|
ConstString("AcquireSwapChainTexture")));
|
||||||
windowData->InFlightFences[windowData->WindowFrameCounter] = nullptr;
|
windowData->InFlightFences[windowData->WindowFrameCounter] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +221,8 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
if (windowData->InFlightFences[windowData->WindowFrameCounter] != nullptr)
|
if (windowData->InFlightFences[windowData->WindowFrameCounter] != nullptr)
|
||||||
{
|
{
|
||||||
if (!Wait(d3d12Driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter], 1))
|
if (!Wait(d3d12Driver, true, &windowData->InFlightFences[windowData->WindowFrameCounter],
|
||||||
|
1 JULIET_DEBUG_PARAM(ConstString("WaitForSwapchain"))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,21 @@ namespace Juliet::D3D12
|
|||||||
driver->AvailableFenceCapacity = driver->AvailableFenceCapacity * 2;
|
driver->AvailableFenceCapacity = driver->AvailableFenceCapacity * 2;
|
||||||
driver->AvailableFences = static_cast<D3D12Fence**>(
|
driver->AvailableFences = static_cast<D3D12Fence**>(
|
||||||
Realloc(driver->AvailableFences, sizeof(D3D12Fence*) * driver->AvailableFenceCapacity));
|
Realloc(driver->AvailableFences, sizeof(D3D12Fence*) * driver->AvailableFenceCapacity));
|
||||||
|
|
||||||
|
LogMessage(LogCategory::Core, "ReleaseFenceToPool With Realloc");
|
||||||
}
|
}
|
||||||
driver->AvailableFences[driver->AvailableFenceCount] = fence;
|
driver->AvailableFences[driver->AvailableFenceCount] = fence;
|
||||||
driver->AvailableFenceCount += 1;
|
driver->AvailableFenceCount += 1;
|
||||||
|
|
||||||
|
LogMessage(LogCategory::Core, "ReleaseFenceToPool %x fence. Handle %x | Event %x | Refcount %d",
|
||||||
|
fence.Get(), fence->Handle, fence->Event, fence->ReferenceCount);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool WaitUntilGPUIsIdle(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 JULIET_DEBUG_PARAM(ConstString("WaitUntilGPUIsIdle")));
|
||||||
if (!fence)
|
if (!fence)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -56,7 +61,7 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseFence(driver, reinterpret_cast<Fence*>(fence));
|
ReleaseFence(driver, reinterpret_cast<Fence*>(fence) JULIET_DEBUG_PARAM(ConstString("WaitUntilGPUIsIdle")));
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
@@ -71,16 +76,17 @@ namespace Juliet::D3D12
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences)
|
bool Wait(NonNullPtr<GPUDriver> driver, bool waitForAll, Fence* const* fences, uint32 numFences JULIET_DEBUG_PARAM(String querier))
|
||||||
{
|
{
|
||||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
|
|
||||||
// TODO: use scratch allocator for alloca (stack alloc)
|
// TODO: use scratch allocator for alloca (stack alloc)
|
||||||
auto events = static_cast<HANDLE*>(alloca(sizeof(HANDLE) * numFences));
|
HANDLE* events = static_cast<HANDLE*>(alloca(sizeof(HANDLE) * numFences));
|
||||||
|
MemoryZero(events, sizeof(HANDLE) * numFences);
|
||||||
|
|
||||||
for (uint32 i = 0; i < numFences; ++i)
|
for (uint32 i = 0; i < numFences; ++i)
|
||||||
{
|
{
|
||||||
auto fence = reinterpret_cast<D3D12Fence*>(fences[i]);
|
D3D12Fence* fence = reinterpret_cast<D3D12Fence*>(fences[i]);
|
||||||
|
|
||||||
HRESULT res = fence->Handle->SetEventOnCompletion(D3D12_FENCE_SIGNAL_VALUE, fence->Event);
|
HRESULT res = fence->Handle->SetEventOnCompletion(D3D12_FENCE_SIGNAL_VALUE, fence->Event);
|
||||||
if (FAILED(res))
|
if (FAILED(res))
|
||||||
@@ -91,6 +97,13 @@ namespace Juliet::D3D12
|
|||||||
|
|
||||||
events[i] = fence->Event;
|
events[i] = fence->Event;
|
||||||
}
|
}
|
||||||
|
LogMessage(LogCategory::Core, "Waiting for %d fences. Querier %s", numFences, CStr(querier));
|
||||||
|
for (uint32 i = 0; i < numFences; ++i)
|
||||||
|
{
|
||||||
|
D3D12Fence* d3d12fence = reinterpret_cast<D3D12Fence*>(fences[i]);
|
||||||
|
LogMessage(LogCategory::Core, "Waiting for %x fence. Handle %x | Event %x | Refcount %d", d3d12fence,
|
||||||
|
d3d12fence->Handle, d3d12fence->Event, d3d12fence->ReferenceCount);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD waitResult = WaitForMultipleObjects(numFences, events, waitForAll, INFINITE);
|
DWORD waitResult = WaitForMultipleObjects(numFences, events, waitForAll, INFINITE);
|
||||||
if (waitResult == WAIT_FAILED)
|
if (waitResult == WAIT_FAILED)
|
||||||
@@ -122,11 +135,13 @@ namespace Juliet::D3D12
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence)
|
void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence JULIET_DEBUG_PARAM(String querier))
|
||||||
{
|
{
|
||||||
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
|
||||||
auto d3d12Fence = reinterpret_cast<D3D12Fence*>(fence.Get());
|
auto d3d12Fence = reinterpret_cast<D3D12Fence*>(fence.Get());
|
||||||
|
|
||||||
|
LogMessage(LogCategory::Core, "ReleaseFence Querier %s | %x fence. Handle %x | Event %x | Refcount %d",
|
||||||
|
CStr(querier), d3d12Fence, d3d12Fence->Handle, d3d12Fence->Event, d3d12Fence->ReferenceCount);
|
||||||
if (--d3d12Fence->ReferenceCount == 0)
|
if (--d3d12Fence->ReferenceCount == 0)
|
||||||
{
|
{
|
||||||
ReleaseFenceToPool(d3d12driver, d3d12Fence);
|
ReleaseFenceToPool(d3d12driver, d3d12Fence);
|
||||||
@@ -170,7 +185,7 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver)
|
D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver JULIET_DEBUG_PARAM(String querier))
|
||||||
{
|
{
|
||||||
D3D12Fence* fence;
|
D3D12Fence* fence;
|
||||||
ID3D12Fence* handle;
|
ID3D12Fence* handle;
|
||||||
@@ -197,15 +212,22 @@ namespace Juliet::D3D12
|
|||||||
fence->Handle = handle;
|
fence->Handle = handle;
|
||||||
fence->Event = CreateEvent(nullptr, false, false, nullptr);
|
fence->Event = CreateEvent(nullptr, false, false, nullptr);
|
||||||
fence->ReferenceCount = 0;
|
fence->ReferenceCount = 0;
|
||||||
|
LogMessage(LogCategory::Core, "Acquire Querier %s | Setting Signal to 0 NEW fence", CStr(querier));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
|
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
|
||||||
driver->AvailableFenceCount -= 1;
|
driver->AvailableFenceCount -= 1;
|
||||||
fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
|
fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
|
||||||
|
LogMessage(LogCategory::Core, "Acquire Querier %s | Setting Signal to 0, RECYCLING", CStr(querier));
|
||||||
}
|
}
|
||||||
|
|
||||||
fence->ReferenceCount += 1;
|
fence->ReferenceCount += 1;
|
||||||
|
Assert(fence->ReferenceCount == 1);
|
||||||
|
|
||||||
|
LogMessage(LogCategory::Core, "Acquire Querier %s | %x fence. Handle %x | Event %x | Refcount %d",
|
||||||
|
CStr(querier), fence, fence->Handle, fence->Event, fence->ReferenceCount);
|
||||||
|
|
||||||
return fence;
|
return fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ namespace Juliet::D3D12
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern bool WaitUntilGPUIsIdle(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 JULIET_DEBUG_PARAM(String querier));
|
||||||
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 JULIET_DEBUG_PARAM(String querier));
|
||||||
|
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
@@ -36,7 +37,7 @@ namespace Juliet::D3D12
|
|||||||
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
|
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
|
||||||
uint32 subresourceIndex, bool needsUavBarrier);
|
uint32 subresourceIndex, bool needsUavBarrier);
|
||||||
|
|
||||||
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver);
|
extern D3D12Fence* AcquireFence(NonNullPtr<D3D12Driver> driver JULIET_DEBUG_PARAM(String querier));
|
||||||
extern void DestroyFence(NonNullPtr<D3D12Fence> fence);
|
extern void DestroyFence(NonNullPtr<D3D12Fence> fence);
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Juliet::D3D12
|
} // namespace Juliet::D3D12
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <Core/Common/EnumUtils.h>
|
#include <Core/Common/EnumUtils.h>
|
||||||
#include <Core/Logging/LogManager.h>
|
#include <Core/Logging/LogManager.h>
|
||||||
#include <Core/Logging/LogTypes.h>
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Memory/Allocator.h>
|
||||||
#include <Graphics/D3D12/D3D12CommandList.h>
|
#include <Graphics/D3D12/D3D12CommandList.h>
|
||||||
|
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
|
||||||
#include <Graphics/D3D12/D3D12Synchronization.h>
|
#include <Graphics/D3D12/D3D12Synchronization.h>
|
||||||
#include <Graphics/D3D12/D3D12Texture.h>
|
#include <Graphics/D3D12/D3D12Texture.h>
|
||||||
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
|
|
||||||
#include <Graphics/D3D12/D3D12Utils.h>
|
#include <Graphics/D3D12/D3D12Utils.h>
|
||||||
#include <Core/Memory/Allocator.h>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace Juliet::D3D12
|
namespace Juliet::D3D12
|
||||||
{
|
{
|
||||||
@@ -375,13 +375,9 @@ namespace Juliet::D3D12
|
|||||||
case TextureType::Texture_2D:
|
case TextureType::Texture_2D:
|
||||||
case TextureType::Texture_2DArray:
|
case TextureType::Texture_2DArray:
|
||||||
case TextureType::Texture_Cube:
|
case TextureType::Texture_Cube:
|
||||||
case TextureType::Texture_CubeArray:
|
case TextureType::Texture_CubeArray: desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; break;
|
||||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
|
||||||
break;
|
|
||||||
case TextureType::Texture_3D:
|
case TextureType::Texture_3D:
|
||||||
case TextureType::Texture_3DArray:
|
case TextureType::Texture_3DArray: desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; break;
|
||||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.Alignment = 0;
|
desc.Alignment = 0;
|
||||||
@@ -396,14 +392,24 @@ namespace Juliet::D3D12
|
|||||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
if ((createInfo.Flags & TextureUsageFlag::ColorTarget) != TextureUsageFlag::None)
|
if ((createInfo.Flags & TextureUsageFlag::ColorTarget) != TextureUsageFlag::None)
|
||||||
|
{
|
||||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
|
}
|
||||||
if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
|
if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
|
||||||
|
{
|
||||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||||
|
}
|
||||||
if ((createInfo.Flags & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None)
|
if ((createInfo.Flags & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None)
|
||||||
|
{
|
||||||
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
D3D12_HEAP_PROPERTIES heapProps = {};
|
D3D12_HEAP_PROPERTIES heapProps = {};
|
||||||
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||||
|
heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||||
|
heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||||
|
heapProps.CreationNodeMask = 0; // We don't do multi-adapter operation
|
||||||
|
heapProps.VisibleNodeMask = 0; // We don't do multi-adapter operation
|
||||||
|
|
||||||
ID3D12Resource* resource = nullptr;
|
ID3D12Resource* resource = nullptr;
|
||||||
D3D12_CLEAR_VALUE clearValue = {};
|
D3D12_CLEAR_VALUE clearValue = {};
|
||||||
@@ -426,8 +432,9 @@ namespace Juliet::D3D12
|
|||||||
pClearValue = &clearValue;
|
pClearValue = &clearValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3D12_RESOURCE_STATES initialState = GetDefaultTextureResourceState(createInfo.Flags);
|
||||||
HRESULT hr = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
|
HRESULT hr = d3d12Driver->D3D12Device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc,
|
||||||
D3D12_RESOURCE_STATE_COMMON, pClearValue, IID_ID3D12Resource,
|
initialState, pClearValue, IID_ID3D12Resource,
|
||||||
reinterpret_cast<void**>(&resource));
|
reinterpret_cast<void**>(&resource));
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
@@ -454,7 +461,8 @@ namespace Juliet::D3D12
|
|||||||
uint32 numLayers = std::max<uint32>(1, createInfo.LayerCount);
|
uint32 numLayers = std::max<uint32>(1, createInfo.LayerCount);
|
||||||
uint32 numMips = std::max<uint32>(1, createInfo.MipLevelCount);
|
uint32 numMips = std::max<uint32>(1, createInfo.MipLevelCount);
|
||||||
texture->SubresourceCount = numLayers * numMips;
|
texture->SubresourceCount = numLayers * numMips;
|
||||||
texture->Subresources = static_cast<D3D12TextureSubresource*>(Calloc(texture->SubresourceCount, sizeof(D3D12TextureSubresource)));
|
texture->Subresources =
|
||||||
|
static_cast<D3D12TextureSubresource*>(Calloc(texture->SubresourceCount, sizeof(D3D12TextureSubresource)));
|
||||||
|
|
||||||
for (uint32 layer = 0; layer < numLayers; ++layer)
|
for (uint32 layer = 0; layer < numLayers; ++layer)
|
||||||
{
|
{
|
||||||
@@ -529,7 +537,6 @@ namespace Juliet::D3D12
|
|||||||
}
|
}
|
||||||
|
|
||||||
return reinterpret_cast<Texture*>(textureContainer);
|
return reinterpret_cast<Texture*>(textureContainer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)
|
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace Juliet
|
|||||||
// Fences
|
// Fences
|
||||||
bool (*WaitUntilGPUIsIdle)(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 JULIET_DEBUG_PARAM(String querier));
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
Shader* (*CreateShader)(NonNullPtr<GPUDriver> driver, ByteBuffer shaderByteCode, ShaderCreateInfo& shaderCreateInfo);
|
Shader* (*CreateShader)(NonNullPtr<GPUDriver> driver, ByteBuffer shaderByteCode, ShaderCreateInfo& shaderCreateInfo);
|
||||||
|
|||||||
@@ -5,95 +5,5 @@
|
|||||||
|
|
||||||
namespace Juliet
|
namespace Juliet
|
||||||
{
|
{
|
||||||
Mesh* CreateCubeMesh(NonNullPtr<Arena> arena)
|
|
||||||
{
|
|
||||||
Mesh* result = ArenaPushStruct<Mesh>(arena.Get());
|
|
||||||
|
|
||||||
constexpr Vertex vertexData[] = {
|
|
||||||
// Front Face (Z = -0.5f)
|
|
||||||
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f } }, // 0: Top Left
|
|
||||||
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f } }, // 1: Top Right
|
|
||||||
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, // 2: Bottom Right
|
|
||||||
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, // 3: Bottom Left
|
|
||||||
|
|
||||||
// Back Face (Z = 0.5f)
|
|
||||||
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 4: Top Left
|
|
||||||
{ { -0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 5: Top Right
|
|
||||||
{ { -0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 6: Bottom Right
|
|
||||||
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } }, // 7: Bottom Left
|
|
||||||
|
|
||||||
// Top Face (Y = 0.5f)
|
|
||||||
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 8: Top Left
|
|
||||||
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 9: Top Right
|
|
||||||
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 1.0f } }, // 10: Bottom Right
|
|
||||||
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f } }, // 11: Bottom Left
|
|
||||||
|
|
||||||
// Bottom Face (Y = -0.5f)
|
|
||||||
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f } }, // 12: Top Left
|
|
||||||
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f } }, // 13: Top Right
|
|
||||||
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 14: Bottom Right
|
|
||||||
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } }, // 15: Bottom Left
|
|
||||||
|
|
||||||
// Right Face (X = 0.5f)
|
|
||||||
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f } }, // 16: Top Left
|
|
||||||
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 17: Top Right
|
|
||||||
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 18: Bottom Right
|
|
||||||
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, // 19: Bottom Left
|
|
||||||
|
|
||||||
// Left Face (X = -0.5f)
|
|
||||||
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 20: Top Left
|
|
||||||
{ { -0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f } }, // 21: Top Right
|
|
||||||
{ { -0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, // 22: Bottom Right
|
|
||||||
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } } // 23: Bottom Left
|
|
||||||
};
|
|
||||||
constexpr size_t cubeVertexCount = ArraySize(vertexData);
|
|
||||||
result->VertexCount = cubeVertexCount;
|
|
||||||
result->Vertices = ArenaPushArray<Vertex>(arena.Get(), cubeVertexCount);
|
|
||||||
MemCopy(result->Vertices, vertexData, sizeof(Vertex) * cubeVertexCount);
|
|
||||||
|
|
||||||
constexpr uint16 indices[] = { 0, 1, 2, 0, 2, 3, // Front
|
|
||||||
4, 5, 6, 4, 6, 7, // Back
|
|
||||||
8, 9, 10, 8, 10, 11, // Top
|
|
||||||
12, 13, 14, 12, 14, 15, // Bottom
|
|
||||||
16, 17, 18, 16, 18, 19, // Right
|
|
||||||
20, 21, 22, 20, 22, 23 }; // Left
|
|
||||||
constexpr size_t indexCubeCount = ArraySize(indices);
|
|
||||||
result->IndexCount = indexCubeCount;
|
|
||||||
result->Indices = ArenaPushArray<uint16>(arena.Get(), indexCubeCount JULIET_DEBUG_PARAM("Indices"));
|
|
||||||
MemCopy(result->Indices, indices, sizeof(uint16) * indexCubeCount);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mesh* CreateQuadMesh(NonNullPtr<Arena> arena)
|
|
||||||
{
|
|
||||||
Mesh* result = ArenaPushStruct<Mesh>(arena.Get());
|
|
||||||
|
|
||||||
// Using the exact 6 vertices from the working triangles!
|
|
||||||
constexpr Vertex vertexData[] = {
|
|
||||||
// Triangle 1 (Clockwise)
|
|
||||||
{ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 0: Red
|
|
||||||
{ { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1: Green
|
|
||||||
{ { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2: Blue
|
|
||||||
|
|
||||||
// Triangle 2 (Clockwise)
|
|
||||||
{ { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }, // 3: Yellow
|
|
||||||
{ { 0.0f, 0.8f, 0.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, // 4: Cyan
|
|
||||||
{ { 0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f, 1.0f, 1.0f } } // 5: Magenta
|
|
||||||
};
|
|
||||||
constexpr size_t triVertexCount = ArraySize(vertexData);
|
|
||||||
result->VertexCount = triVertexCount;
|
|
||||||
result->Vertices = ArenaPushArray<Vertex>(arena.Get(), triVertexCount);
|
|
||||||
MemCopy(result->Vertices, vertexData, sizeof(Vertex) * triVertexCount);
|
|
||||||
|
|
||||||
// Just the 6 indices for the two triangles
|
|
||||||
constexpr uint16 indices[] = { 0, 1, 2, 3, 4, 5 };
|
|
||||||
constexpr size_t triIndexCount = ArraySize(indices);
|
|
||||||
result->IndexCount = triIndexCount;
|
|
||||||
result->Indices = ArenaPushArray<uint16>(arena.Get(), triIndexCount JULIET_DEBUG_PARAM("Indices"));
|
|
||||||
MemCopy(result->Indices, indices, sizeof(uint16) * triIndexCount);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Juliet
|
} // namespace Juliet
|
||||||
|
|||||||
315
Juliet/src/Graphics/MeshRenderer.cpp
Normal file
315
Juliet/src/Graphics/MeshRenderer.cpp
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
#include <Graphics/MeshRenderer.h>
|
||||||
|
|
||||||
|
#include <Core/Logging/LogManager.h>
|
||||||
|
#include <Core/Logging/LogTypes.h>
|
||||||
|
#include <Core/Math/Matrix.h>
|
||||||
|
#include <Graphics/GraphicsDevice.h>
|
||||||
|
#include <Graphics/Mesh.h>
|
||||||
|
#include <Graphics/VertexData.h>
|
||||||
|
|
||||||
|
namespace Juliet
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
MeshRenderer g_MeshRenderer;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
bool InitializeMeshRenderer(NonNullPtr<Arena> arena, NonNullPtr<GraphicsDevice> device, NonNullPtr<Window> window)
|
||||||
|
{
|
||||||
|
(void)arena;
|
||||||
|
(void)device;
|
||||||
|
(void)window;
|
||||||
|
return true;
|
||||||
|
// bool result = true;
|
||||||
|
//
|
||||||
|
// g_MeshRenderer.Meshes.Create(arena JULIET_DEBUG_PARAM("Meshes"));
|
||||||
|
// g_MeshRenderer.Vertices.Create(arena JULIET_DEBUG_PARAM("Vertices"));
|
||||||
|
// g_MeshRenderer.Indices.Create(arena JULIET_DEBUG_PARAM("Indices"));
|
||||||
|
//
|
||||||
|
// GraphicsDevice* graphicsDevice = g_MeshRenderer.Device = device.Get();
|
||||||
|
//
|
||||||
|
// // Create graphics pipeline
|
||||||
|
// String entryPoint = WrapString("main");
|
||||||
|
// ShaderCreateInfo shaderCI = {};
|
||||||
|
// shaderCI.EntryPoint = entryPoint;
|
||||||
|
//
|
||||||
|
// // TODO: Assets management that handles path to assets or something.
|
||||||
|
// 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);
|
||||||
|
//
|
||||||
|
// ColorTargetDescription colorTargetDescription = {};
|
||||||
|
// colorTargetDescription.Format = GetSwapChainTextureFormat(graphicsDevice, window);
|
||||||
|
//
|
||||||
|
// GraphicsPipelineCreateInfo pipelineCI = {};
|
||||||
|
// pipelineCI.VertexShader = vertexShader;
|
||||||
|
// pipelineCI.FragmentShader = fragmentShader;
|
||||||
|
// pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
|
||||||
|
// pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
|
||||||
|
// .NumColorTargets = 1,
|
||||||
|
// .DepthStencilFormat = TextureFormat::D32_FLOAT,
|
||||||
|
// .HasDepthStencilTarget = true };
|
||||||
|
// pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
||||||
|
// pipelineCI.DepthStencilState.EnableDepthTest = true;
|
||||||
|
// pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
||||||
|
// pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
||||||
|
//
|
||||||
|
// g_MeshRenderer.Pipeline = CreateGraphicsPipeline(graphicsDevice, pipelineCI);
|
||||||
|
// if (g_MeshRenderer.Pipeline == nullptr)
|
||||||
|
// {
|
||||||
|
// LogError(LogCategory::Graphics, "Failed to create graphics pipeline!");
|
||||||
|
// result = false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Create the vertex and index buffers
|
||||||
|
// BufferCreateInfo vertexBufferCI = {};
|
||||||
|
// vertexBufferCI.Size = kGeometryPage;
|
||||||
|
// vertexBufferCI.Usage = BufferUsage::VertexBuffer;
|
||||||
|
// g_MeshRenderer.VertexBuffer = CreateGraphicsBuffer(graphicsDevice, vertexBufferCI);
|
||||||
|
//
|
||||||
|
// BufferCreateInfo indexBufferCI = {};
|
||||||
|
// indexBufferCI.Size = kIndexPage;
|
||||||
|
// indexBufferCI.Usage = BufferUsage::IndexBuffer;
|
||||||
|
// g_MeshRenderer.IndexBuffer = CreateGraphicsBuffer(graphicsDevice, indexBufferCI);
|
||||||
|
//
|
||||||
|
// if (vertexShader)
|
||||||
|
// {
|
||||||
|
// DestroyShader(graphicsDevice, vertexShader);
|
||||||
|
// }
|
||||||
|
// if (fragmentShader)
|
||||||
|
// {
|
||||||
|
// DestroyShader(graphicsDevice, fragmentShader);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShutdownMeshRenderer()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
// DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.IndexBuffer);
|
||||||
|
// DestroyGraphicsBuffer(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
||||||
|
//
|
||||||
|
// g_MeshRenderer.Indices.Destroy();
|
||||||
|
// g_MeshRenderer.Vertices.Destroy();
|
||||||
|
// g_MeshRenderer.Meshes.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadMeshesOnGPU(NonNullPtr<CommandList> cmdList)
|
||||||
|
{
|
||||||
|
if (g_MeshRenderer.Meshes.IsEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading everything in one go.
|
||||||
|
// Destroy the buffer at the end
|
||||||
|
|
||||||
|
TransferBufferCreateInfo uploadBCI = {};
|
||||||
|
uploadBCI.Usage = TransferBufferUsage::Upload;
|
||||||
|
uploadBCI.Size = kGeometryPage + kIndexPage;
|
||||||
|
g_MeshRenderer.LoadCopyBuffer = CreateGraphicsTransferBuffer(g_MeshRenderer.Device, uploadBCI);
|
||||||
|
|
||||||
|
void* map = MapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||||
|
|
||||||
|
Vertex* vertices = g_MeshRenderer.Vertices.Data;
|
||||||
|
if (!vertices)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index* indices = g_MeshRenderer.Indices.Data;
|
||||||
|
if (!indices)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all meshes! This supports only one page for now
|
||||||
|
// Copy ALL Vertices in one block
|
||||||
|
size_t totalVertexBytes = g_MeshRenderer.Vertices.Count * sizeof(Vertex);
|
||||||
|
MemCopy(map, g_MeshRenderer.Vertices.Data, totalVertexBytes);
|
||||||
|
|
||||||
|
// Copy ALL Indices in one block
|
||||||
|
size_t indexOfByteOffset = (kGeometryPage + 255) & static_cast<size_t>(~255);
|
||||||
|
uint8* ptrOneByte = static_cast<uint8*>(map);
|
||||||
|
size_t totalIndexBytes = g_MeshRenderer.Indices.Count * sizeof(Index);
|
||||||
|
|
||||||
|
MemCopy(ptrOneByte + indexOfByteOffset, g_MeshRenderer.Indices.Data, totalIndexBytes);
|
||||||
|
|
||||||
|
// index_t index = 0;
|
||||||
|
// for (Mesh& mesh : g_MeshRenderer.Meshes)
|
||||||
|
// {
|
||||||
|
// // Vertices first
|
||||||
|
// Vertex* mapVertices = static_cast<Vertex*>(map);
|
||||||
|
// MemCopy(mapVertices + index, vertices + mesh.VertexOffset, mesh.VertexCount * sizeOfVertex);
|
||||||
|
//
|
||||||
|
// // Indices next
|
||||||
|
// uint8* ptrOneByte = static_cast<uint8*>(map);
|
||||||
|
// uint16* dst = reinterpret_cast<uint16*>(ptrOneByte + indexOfByteOffset);
|
||||||
|
// MemCopy(dst, indices, mesh.IndexCount * sizeOfIndex);
|
||||||
|
//
|
||||||
|
// ++index;
|
||||||
|
// }
|
||||||
|
|
||||||
|
CopyBuffer(cmdList, g_MeshRenderer.VertexBuffer, g_MeshRenderer.LoadCopyBuffer, totalVertexBytes, 0, 0);
|
||||||
|
CopyBuffer(cmdList, g_MeshRenderer.IndexBuffer, g_MeshRenderer.LoadCopyBuffer, totalIndexBytes, 0, indexOfByteOffset);
|
||||||
|
|
||||||
|
// Transition vertex buffer to SRV state (this barrier waits for copy to complete)
|
||||||
|
TransitionBufferToReadable(cmdList, g_MeshRenderer.VertexBuffer);
|
||||||
|
TransitionBufferToReadable(cmdList, g_MeshRenderer.IndexBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderMeshes(NonNullPtr<RenderPass> pass, NonNullPtr<CommandList> cmdList, PushData& pushData)
|
||||||
|
{
|
||||||
|
// First destroy any buffer that needs to be
|
||||||
|
if (g_MeshRenderer.LoadCopyBuffer)
|
||||||
|
{
|
||||||
|
WaitUntilGPUIsIdle(g_MeshRenderer.Device);
|
||||||
|
UnmapGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||||
|
DestroyGraphicsTransferBuffer(g_MeshRenderer.Device, g_MeshRenderer.LoadCopyBuffer);
|
||||||
|
g_MeshRenderer.LoadCopyBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BindGraphicsPipeline(pass, g_MeshRenderer.Pipeline);
|
||||||
|
|
||||||
|
uint32 vertexDescriptorIndex = GetDescriptorIndex(g_MeshRenderer.Device, g_MeshRenderer.VertexBuffer);
|
||||||
|
|
||||||
|
pushData.BufferIndex = vertexDescriptorIndex;
|
||||||
|
SetPushConstants(cmdList, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
||||||
|
|
||||||
|
for (Mesh& mesh : g_MeshRenderer.Meshes)
|
||||||
|
{
|
||||||
|
SetIndexBuffer(cmdList, g_MeshRenderer.IndexBuffer, IndexFormat::UInt16, mesh.IndexCount, 0);
|
||||||
|
// DrawIndexedPrimitives(pass, static_cast<uint32>(mesh.IndexCount), 1, static_cast<uint32>(mesh.IndexOffset),
|
||||||
|
// static_cast<uint32>(mesh.VertexOffset), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshID AddCube()
|
||||||
|
{
|
||||||
|
Mesh result = {};
|
||||||
|
|
||||||
|
constexpr Vertex vertexData[] = {
|
||||||
|
// Front Face (Z = -0.5f)
|
||||||
|
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f } }, // 0: Top Left
|
||||||
|
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f } }, // 1: Top Right
|
||||||
|
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, // 2: Bottom Right
|
||||||
|
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, // 3: Bottom Left
|
||||||
|
|
||||||
|
// Back Face (Z = 0.5f)
|
||||||
|
{ { 0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 4: Top Left
|
||||||
|
{ { -0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 5: Top Right
|
||||||
|
{ { -0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 6: Bottom Right
|
||||||
|
{ { 0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } }, // 7: Bottom Left
|
||||||
|
|
||||||
|
// Top Face (Y = 0.5f)
|
||||||
|
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 8: Top Left
|
||||||
|
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 9: Top Right
|
||||||
|
{ { 0.5f, 0.5f, -0.5f }, { 1.0f, 1.0f } }, // 10: Bottom Right
|
||||||
|
{ { -0.5f, 0.5f, -0.5f }, { 0.0f, 1.0f } }, // 11: Bottom Left
|
||||||
|
|
||||||
|
// Bottom Face (Y = -0.5f)
|
||||||
|
{ { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f } }, // 12: Top Left
|
||||||
|
{ { 0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f } }, // 13: Top Right
|
||||||
|
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 14: Bottom Right
|
||||||
|
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } }, // 15: Bottom Left
|
||||||
|
|
||||||
|
// Right Face (X = 0.5f)
|
||||||
|
{ { 0.5f, 0.5f, -0.5f }, { 0.0f, 0.0f } }, // 16: Top Left
|
||||||
|
{ { 0.5f, 0.5f, 0.5f }, { 1.0f, 0.0f } }, // 17: Top Right
|
||||||
|
{ { 0.5f, -0.5f, 0.5f }, { 1.0f, 1.0f } }, // 18: Bottom Right
|
||||||
|
{ { 0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, // 19: Bottom Left
|
||||||
|
|
||||||
|
// Left Face (X = -0.5f)
|
||||||
|
{ { -0.5f, 0.5f, 0.5f }, { 0.0f, 0.0f } }, // 20: Top Left
|
||||||
|
{ { -0.5f, 0.5f, -0.5f }, { 1.0f, 0.0f } }, // 21: Top Right
|
||||||
|
{ { -0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, // 22: Bottom Right
|
||||||
|
{ { -0.5f, -0.5f, 0.5f }, { 0.0f, 1.0f } } // 23: Bottom Left
|
||||||
|
};
|
||||||
|
constexpr size_t cubeVertexCount = ArraySize(vertexData);
|
||||||
|
result.VertexCount = cubeVertexCount;
|
||||||
|
result.VertexOffset = g_MeshRenderer.Vertices.Count;
|
||||||
|
g_MeshRenderer.Vertices.PushBack(vertexData, cubeVertexCount);
|
||||||
|
|
||||||
|
constexpr uint16 indices[] = { 0, 1, 2, 0, 2, 3, // Front
|
||||||
|
4, 5, 6, 4, 6, 7, // Back
|
||||||
|
8, 9, 10, 8, 10, 11, // Top
|
||||||
|
12, 13, 14, 12, 14, 15, // Bottom
|
||||||
|
16, 17, 18, 16, 18, 19, // Right
|
||||||
|
20, 21, 22, 20, 22, 23 }; // Left
|
||||||
|
constexpr size_t indexCubeCount = ArraySize(indices);
|
||||||
|
result.IndexCount = indexCubeCount;
|
||||||
|
result.IndexOffset = g_MeshRenderer.Indices.Count;
|
||||||
|
g_MeshRenderer.Indices.PushBack(indices, indexCubeCount);
|
||||||
|
|
||||||
|
MeshID id = g_MeshRenderer.Meshes.Count;
|
||||||
|
g_MeshRenderer.Meshes.PushBack(result);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshID AddQuad()
|
||||||
|
{
|
||||||
|
// Mesh result = {};
|
||||||
|
|
||||||
|
// // Using the exact 6 vertices from the working triangles!
|
||||||
|
// constexpr Vertex vertexData[] = {
|
||||||
|
// // Triangle 1 (Clockwise)
|
||||||
|
// { { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 0: Red
|
||||||
|
// { { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1: Green
|
||||||
|
// { { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2: Blue
|
||||||
|
//
|
||||||
|
// // Triangle 2 (Clockwise)
|
||||||
|
// { { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }, // 3: Yellow
|
||||||
|
// { { 0.0f, 0.8f, 0.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, // 4: Cyan
|
||||||
|
// { { 0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f, 1.0f, 1.0f } } // 5: Magenta
|
||||||
|
// };
|
||||||
|
// constexpr size_t triVertexCount = ArraySize(vertexData);
|
||||||
|
// result.VertexCount = triVertexCount;
|
||||||
|
// result.Vertices = ArenaPushArray<Vertex>(arena.Get(), triVertexCount);
|
||||||
|
// MemCopy(result.Vertices, vertexData, sizeof(Vertex) * triVertexCount);
|
||||||
|
//
|
||||||
|
// // Just the 6 indices for the two triangles
|
||||||
|
// constexpr uint16 indices[] = { 0, 1, 2, 3, 4, 5 };
|
||||||
|
// constexpr size_t triIndexCount = ArraySize(indices);
|
||||||
|
// result.IndexCount = triIndexCount;
|
||||||
|
// result.Indices = ArenaPushArray<uint16>(arena.Get(), triIndexCount JULIET_DEBUG_PARAM("Indices"));
|
||||||
|
// MemCopy(result.Indices, indices, sizeof(uint16) * triIndexCount);
|
||||||
|
//
|
||||||
|
// g_MeshRenderer.Meshes.PushBack(std::move(result));
|
||||||
|
return g_MeshRenderer.Meshes.Count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
|
void ReloadMeshRendererShaders()
|
||||||
|
{
|
||||||
|
auto* pipeline = g_MeshRenderer.Pipeline;
|
||||||
|
auto* device = g_MeshRenderer.Device;
|
||||||
|
|
||||||
|
String entryPoint = WrapString("main");
|
||||||
|
ShaderCreateInfo shaderCI = {};
|
||||||
|
shaderCI.EntryPoint = entryPoint;
|
||||||
|
String shaderPath = WrapString("../../Assets/compiled/Triangle.vert.dxil");
|
||||||
|
shaderCI.Stage = ShaderStage::Vertex;
|
||||||
|
Shader* vertexShader = CreateShader(device, shaderPath, shaderCI);
|
||||||
|
|
||||||
|
shaderPath = WrapString("../../Assets/compiled/SolidColor.frag.dxil");
|
||||||
|
shaderCI.Stage = ShaderStage::Fragment;
|
||||||
|
Shader* fragmentShader = CreateShader(device, shaderPath, shaderCI);
|
||||||
|
|
||||||
|
UpdateGraphicsPipelineShaders(device, pipeline, vertexShader, fragmentShader);
|
||||||
|
|
||||||
|
if (vertexShader)
|
||||||
|
{
|
||||||
|
DestroyShader(device, vertexShader);
|
||||||
|
}
|
||||||
|
if (fragmentShader)
|
||||||
|
{
|
||||||
|
DestroyShader(device, fragmentShader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} // namespace Juliet
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <Graphics/GraphicsConfig.h>
|
#include <Graphics/GraphicsConfig.h>
|
||||||
#include <Graphics/GraphicsPipeline.h>
|
#include <Graphics/GraphicsPipeline.h>
|
||||||
#include <Graphics/Mesh.h>
|
#include <Graphics/Mesh.h>
|
||||||
|
#include <Graphics/MeshRenderer.h>
|
||||||
#include <Graphics/RenderPass.h>
|
#include <Graphics/RenderPass.h>
|
||||||
#include <Graphics/VertexData.h>
|
#include <Graphics/VertexData.h>
|
||||||
#include <Juliet.h>
|
#include <Juliet.h>
|
||||||
@@ -63,6 +64,8 @@ namespace
|
|||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
|
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
|
||||||
|
|
||||||
|
Arena* PlatformArena = nullptr;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void JulietApplication::Init()
|
void JulietApplication::Init()
|
||||||
@@ -71,6 +74,8 @@ void JulietApplication::Init()
|
|||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Tool, "%s", CStr(GetBasePath()));
|
Log(LogLevel::Message, LogCategory::Tool, "%s", CStr(GetBasePath()));
|
||||||
|
|
||||||
|
PlatformArena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_PARAM("Platform Arena"));
|
||||||
|
|
||||||
GraphicsConfig config;
|
GraphicsConfig config;
|
||||||
#if JULIET_DEBUG
|
#if JULIET_DEBUG
|
||||||
config.EnableDebug = true;
|
config.EnableDebug = true;
|
||||||
@@ -85,42 +90,7 @@ void JulietApplication::Init()
|
|||||||
{
|
{
|
||||||
AttachToWindow(GraphicsDevice, MainWindow);
|
AttachToWindow(GraphicsDevice, MainWindow);
|
||||||
{
|
{
|
||||||
// Create graphics pipeline
|
Running = InitializeMeshRenderer(PlatformArena, GraphicsDevice, MainWindow);
|
||||||
String entryPoint = WrapString("main");
|
|
||||||
ShaderCreateInfo shaderCI = {};
|
|
||||||
shaderCI.EntryPoint = entryPoint;
|
|
||||||
|
|
||||||
// TODO: Assets management that handles path to assets or something.
|
|
||||||
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);
|
|
||||||
|
|
||||||
ColorTargetDescription colorTargetDescription = {};
|
|
||||||
colorTargetDescription.Format = GetSwapChainTextureFormat(GraphicsDevice, MainWindow);
|
|
||||||
|
|
||||||
GraphicsPipelineCreateInfo pipelineCI = {};
|
|
||||||
pipelineCI.VertexShader = vertexShader;
|
|
||||||
pipelineCI.FragmentShader = fragmentShader;
|
|
||||||
pipelineCI.PrimitiveType = PrimitiveType::TriangleList;
|
|
||||||
pipelineCI.TargetInfo = { .ColorTargetDescriptions = &colorTargetDescription,
|
|
||||||
.NumColorTargets = 1,
|
|
||||||
.DepthStencilFormat = TextureFormat::D32_FLOAT,
|
|
||||||
.HasDepthStencilTarget = true };
|
|
||||||
pipelineCI.RasterizerState.FillMode = FillMode::Solid;
|
|
||||||
pipelineCI.DepthStencilState.EnableDepthTest = true;
|
|
||||||
pipelineCI.DepthStencilState.EnableDepthWrite = true;
|
|
||||||
pipelineCI.DepthStencilState.CompareOperation = CompareOperation::Less;
|
|
||||||
|
|
||||||
GraphicsPipeline = CreateGraphicsPipeline(GraphicsDevice, pipelineCI);
|
|
||||||
if (GraphicsPipeline == nullptr)
|
|
||||||
{
|
|
||||||
LogError(LogCategory::Game, "Failed to create graphics pipeline!");
|
|
||||||
Running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Depth Buffer
|
// Create Depth Buffer
|
||||||
TextureCreateInfo depthCI = {};
|
TextureCreateInfo depthCI = {};
|
||||||
@@ -139,50 +109,11 @@ void JulietApplication::Init()
|
|||||||
Running = false;
|
Running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Buffers - Using StructuredBuffer for bindless SRV access in shader
|
// std::ignore = AddCube();
|
||||||
BufferCreateInfo bufferCI = {};
|
//
|
||||||
bufferCI.Size = 1024;
|
// CommandList* loadCmd = AcquireCommandList(GraphicsDevice);
|
||||||
bufferCI.Usage = BufferUsage::StructuredBuffer; // SRV for ResourceDescriptorHeap access
|
// LoadMeshesOnGPU(loadCmd);
|
||||||
StructuredBuffer = CreateGraphicsBuffer(GraphicsDevice, bufferCI);
|
// SubmitCommandLists(loadCmd);
|
||||||
|
|
||||||
TransferBufferCreateInfo transferCI = {};
|
|
||||||
transferCI.Size = 1024;
|
|
||||||
transferCI.Usage = TransferBufferUsage::Upload;
|
|
||||||
TransferBuffer = CreateGraphicsTransferBuffer(GraphicsDevice, transferCI);
|
|
||||||
|
|
||||||
// Upload Static Data for Test
|
|
||||||
if (TransferBuffer && StructuredBuffer)
|
|
||||||
{
|
|
||||||
void* data = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
|
||||||
if (data)
|
|
||||||
{
|
|
||||||
Matrix projection = PerspectiveFov(60.0f * (3.14159f / 180.0f), 1200.0f / 800.0f, 0.1f, 1000.0f);
|
|
||||||
Matrix view = LookAt({ 30.0f, 0.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f });
|
|
||||||
Matrix model = Matrix::Identity();
|
|
||||||
Matrix mvp = projection * view * model;
|
|
||||||
|
|
||||||
MemCopy(data, &mvp, sizeof(Matrix));
|
|
||||||
UnmapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
|
||||||
|
|
||||||
CommandList* initCmd = AcquireCommandList(GraphicsDevice);
|
|
||||||
CopyBuffer(initCmd, StructuredBuffer, TransferBuffer, 256);
|
|
||||||
TransitionBufferToReadable(initCmd, StructuredBuffer);
|
|
||||||
SubmitCommandLists(initCmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CubeArena = ArenaAllocate({ .ReserveSize = Kilobytes(1llu), .CommitSize = Kilobytes(1llu) } JULIET_DEBUG_PARAM("CubeArena"));
|
|
||||||
CubeMesh = CreateCubeMesh(CubeArena);
|
|
||||||
// CubeMesh = CreateQuadMesh(CubeArena);
|
|
||||||
|
|
||||||
if (vertexShader)
|
|
||||||
{
|
|
||||||
DestroyShader(GraphicsDevice, vertexShader);
|
|
||||||
}
|
|
||||||
if (fragmentShader)
|
|
||||||
{
|
|
||||||
DestroyShader(GraphicsDevice, fragmentShader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Running == false)
|
if (Running == false)
|
||||||
{
|
{
|
||||||
@@ -208,8 +139,6 @@ void JulietApplication::Shutdown()
|
|||||||
{
|
{
|
||||||
Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application...");
|
Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application...");
|
||||||
|
|
||||||
ArenaRelease(CubeArena);
|
|
||||||
|
|
||||||
if (GameCode.IsValid)
|
if (GameCode.IsValid)
|
||||||
{
|
{
|
||||||
Game.Shutdown();
|
Game.Shutdown();
|
||||||
@@ -220,19 +149,14 @@ void JulietApplication::Shutdown()
|
|||||||
{
|
{
|
||||||
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
|
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
|
||||||
}
|
}
|
||||||
if (StructuredBuffer)
|
|
||||||
{
|
|
||||||
DestroyGraphicsBuffer(GraphicsDevice, StructuredBuffer);
|
|
||||||
}
|
|
||||||
if (TransferBuffer)
|
|
||||||
{
|
|
||||||
DestroyGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
|
||||||
}
|
|
||||||
if (DepthBuffer)
|
if (DepthBuffer)
|
||||||
{
|
{
|
||||||
DestroyTexture(GraphicsDevice, DepthBuffer);
|
DestroyTexture(GraphicsDevice, DepthBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShutdownMeshRenderer();
|
||||||
|
|
||||||
if (MainWindow && GraphicsDevice)
|
if (MainWindow && GraphicsDevice)
|
||||||
{
|
{
|
||||||
DetachFromWindow(GraphicsDevice, MainWindow);
|
DetachFromWindow(GraphicsDevice, MainWindow);
|
||||||
@@ -248,6 +172,8 @@ void JulietApplication::Shutdown()
|
|||||||
DestroyGraphicsDevice(GraphicsDevice);
|
DestroyGraphicsDevice(GraphicsDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArenaRelease(PlatformArena);
|
||||||
|
|
||||||
Log(LogLevel::Message, LogCategory::Tool, "Juliet App shutdown Completed");
|
Log(LogLevel::Message, LogCategory::Tool, "Juliet App shutdown Completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +207,7 @@ void JulietApplication::Update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JULIET_ENABLE_IMGUI
|
#ifdef JULIET_ENABLE_IMGUI
|
||||||
ImGui::ShowDemoWindow();
|
// ImGui::ShowDemoWindow();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
|
DebugDisplay_DrawLine({ 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f }, false);
|
||||||
@@ -301,27 +227,7 @@ void JulietApplication::Update()
|
|||||||
WaitUntilGPUIsIdle(GraphicsDevice);
|
WaitUntilGPUIsIdle(GraphicsDevice);
|
||||||
|
|
||||||
#if ALLOW_SHADER_HOT_RELOAD
|
#if ALLOW_SHADER_HOT_RELOAD
|
||||||
String entryPoint = WrapString("main");
|
ReloadMeshRendererShaders();
|
||||||
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,76 +267,16 @@ void JulietApplication::Update()
|
|||||||
ArenaClear(GameScratchArena);
|
ArenaClear(GameScratchArena);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JulietApplication::OnPreRender(CommandList* cmd)
|
void JulietApplication::OnPreRender(CommandList* /*cmd*/) {}
|
||||||
|
|
||||||
|
void JulietApplication::OnRender(RenderPass*, CommandList*)
|
||||||
{
|
{
|
||||||
index_t index = 0;
|
// PushData pushData = {};
|
||||||
|
// pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
|
||||||
|
|
||||||
// Buffer uploads
|
// RenderMeshes(pass, cmd, pushData);
|
||||||
if (StructuredBuffer && TransferBuffer)
|
|
||||||
{
|
|
||||||
void* ptr = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
Vertex* vertices = static_cast<Vertex*>(ptr);
|
|
||||||
|
|
||||||
// // Triangle 1
|
// SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
||||||
// vertices[index++] = { { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }; // Red
|
|
||||||
// vertices[index++] = { { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }; // Green
|
|
||||||
// vertices[index++] = { { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }; // Blue
|
|
||||||
//
|
|
||||||
// // Triangle 2
|
|
||||||
// vertices[index++] = { { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 0.0f, 1.0f } }; // Yellow
|
|
||||||
// vertices[index++] = { { 0.0f, 0.8f, 0.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }; // Cyan
|
|
||||||
// vertices[index++] = { { 0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f, 1.0f, 1.0f } }; // Magenta
|
|
||||||
|
|
||||||
if (CubeMesh)
|
|
||||||
{
|
|
||||||
CubeMesh->VertexOffset = index;
|
|
||||||
size_t vertexSize = CubeMesh->VertexCount * sizeof(Vertex);
|
|
||||||
MemCopy(vertices + index, CubeMesh->Vertices, vertexSize);
|
|
||||||
|
|
||||||
CubeMesh->IndexByteOffset = (index + CubeMesh->VertexCount) * sizeof(Vertex);
|
|
||||||
// Align
|
|
||||||
CubeMesh->IndexByteOffset = (CubeMesh->IndexByteOffset + 255) & static_cast<size_t>(~255);
|
|
||||||
|
|
||||||
size_t indexSize = CubeMesh->IndexCount * sizeof(uint16);
|
|
||||||
|
|
||||||
CubeMesh->IndexOffset = 0;
|
|
||||||
|
|
||||||
uint8* ptrOneByte = static_cast<uint8*>(ptr);
|
|
||||||
uint16* dst = reinterpret_cast<uint16*>(ptrOneByte + CubeMesh->IndexByteOffset);
|
|
||||||
MemCopy(dst, CubeMesh->Indices, indexSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
UnmapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
CopyBuffer(cmd, StructuredBuffer, TransferBuffer, CubeMesh->IndexByteOffset + (CubeMesh->IndexCount * sizeof(uint16)));
|
|
||||||
TransitionBufferToReadable(cmd, StructuredBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JulietApplication::OnRender(RenderPass* pass, CommandList* cmd)
|
|
||||||
{
|
|
||||||
BindGraphicsPipeline(pass, GraphicsPipeline);
|
|
||||||
|
|
||||||
uint32 descriptorIndex = GetDescriptorIndex(GraphicsDevice, StructuredBuffer);
|
|
||||||
|
|
||||||
struct PushData
|
|
||||||
{
|
|
||||||
Matrix ViewProjection;
|
|
||||||
uint32 BufferIndex;
|
|
||||||
} pushData = {};
|
|
||||||
pushData.BufferIndex = descriptorIndex;
|
|
||||||
pushData.ViewProjection = Camera_GetViewProjectionMatrix(GetDebugCamera());
|
|
||||||
|
|
||||||
SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
|
|
||||||
|
|
||||||
SetIndexBuffer(cmd, StructuredBuffer, IndexFormat::UInt16, CubeMesh->IndexCount, CubeMesh->IndexByteOffset);
|
|
||||||
// DrawIndexedPrimitives(pass, static_cast<uint32>(CubeMesh->IndexCount), 1, 0, 0, 0);
|
|
||||||
|
|
||||||
DrawIndexedPrimitives(pass, static_cast<uint32>(CubeMesh->IndexCount), 1,
|
|
||||||
static_cast<uint32>(CubeMesh->IndexOffset), static_cast<uint32>(CubeMesh->VertexOffset), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture)
|
ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture)
|
||||||
|
|||||||
@@ -42,13 +42,7 @@ class JulietApplication : public Juliet::IApplication
|
|||||||
Juliet::GraphicsDevice* GraphicsDevice = {};
|
Juliet::GraphicsDevice* GraphicsDevice = {};
|
||||||
Juliet::HotReloadCode GameCode = {};
|
Juliet::HotReloadCode GameCode = {};
|
||||||
Juliet::GraphicsPipeline* GraphicsPipeline = {};
|
Juliet::GraphicsPipeline* GraphicsPipeline = {};
|
||||||
Juliet::GraphicsBuffer* StructuredBuffer = {};
|
|
||||||
Juliet::GraphicsTransferBuffer* TransferBuffer = {};
|
|
||||||
Juliet::Texture* DepthBuffer = {};
|
Juliet::Texture* DepthBuffer = {};
|
||||||
|
|
||||||
Juliet::Mesh* CubeMesh = {};
|
|
||||||
Juliet::Arena* CubeArena = nullptr;
|
|
||||||
|
|
||||||
Juliet::Arena* GameArena = nullptr;
|
Juliet::Arena* GameArena = nullptr;
|
||||||
Juliet::Arena* GameScratchArena = nullptr;
|
Juliet::Arena* GameScratchArena = nullptr;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user