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:
2026-02-21 14:04:02 -05:00
parent e1eb9976ad
commit 49fc0a24d1
18 changed files with 646 additions and 454 deletions

View File

@@ -227,6 +227,10 @@
<CustomBuild Include="src\UnitTest\RunUnitTests.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Graphics\MeshRenderer.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Graphics\MeshRenderer.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{ab9c7e88-6c94-4f93-bc2a-7f5284b7d434}</ProjectGuid>

View File

@@ -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)
{
Assert(Arena);
@@ -172,6 +200,8 @@ namespace Juliet
Capacity = 0;
}
bool IsEmpty() const { return Count == 0; }
// C++ Accessors for loop supports and Index based access
Type& operator[](size_t index) { return DataFirst[index]; }
const Type& operator[](size_t index) const { return DataFirst[index]; }

View File

@@ -11,18 +11,10 @@ namespace Juliet
struct Mesh
{
Vertex* Vertices;
uint16* Indices;
size_t VertexCount;
size_t IndexCount;
index_t VertexOffset;
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

View 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

View File

@@ -7,4 +7,6 @@ namespace Juliet
float Position[3];
float Color[4];
};
using Index = uint16;
} // namespace Juliet

View File

@@ -42,15 +42,15 @@ namespace Juliet
#ifdef JULIET_ENABLE_IMGUI
if (NonNullPtr window = EngineInstance.Application->GetPlatformWindow())
{
ImGuiService::Initialize(window);
ImGui::SetCurrentContext(ImGuiService::GetContext());
// ImGuiService::Initialize(window);
// ImGui::SetCurrentContext(ImGuiService::GetContext());
if (device)
{
ImGuiRenderer_Initialize(device);
// ImGuiRenderer_Initialize(device);
// Run Unit Tests automatically
ImGuiService::RunTests();
// ImGuiService::RunTests();
}
}
#endif
@@ -64,9 +64,9 @@ namespace Juliet
#ifdef JULIET_ENABLE_IMGUI
if (device)
{
ImGuiRenderer_Shutdown(device);
// ImGuiRenderer_Shutdown(device);
}
ImGuiService::Shutdown();
// ImGuiService::Shutdown();
#endif
// DebugDisplay system
@@ -107,7 +107,7 @@ namespace Juliet
EngineInstance.Application->OnPreRender(cmdList);
// Prepare debug display data (before render pass)
DebugDisplay_Prepare(cmdList);
// DebugDisplay_Prepare(cmdList);
// Get render targets from application
ColorTargetInfo colorInfo = EngineInstance.Application->GetColorTargetInfo(swapChainTexture);
@@ -119,12 +119,12 @@ namespace Juliet
EngineInstance.Application->OnRender(pass, cmdList);
// Debug display flush (inside render pass)
Camera debugCamera = EngineInstance.Application->GetDebugCamera();
DebugDisplay_Flush(cmdList, pass, debugCamera);
// Camera debugCamera = EngineInstance.Application->GetDebugCamera();
// DebugDisplay_Flush(cmdList, pass, debugCamera);
#ifdef JULIET_ENABLE_IMGUI
// ImGui rendering (always last before EndRenderPass)
ImGuiRenderer_Render(cmdList, pass);
// ImGuiRenderer_Render(cmdList, pass);
#endif
EndRenderPass(pass);
@@ -178,7 +178,7 @@ namespace Juliet
while (EngineInstance.Application->IsRunning())
{
#ifdef JULIET_ENABLE_IMGUI
ImGuiRenderer_NewFrame();
// ImGuiRenderer_NewFrame();
#endif
// Logic tick

View File

@@ -113,10 +113,10 @@ namespace Juliet::D3D12
{
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
}
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
break;
}
@@ -142,10 +142,10 @@ namespace Juliet::D3D12
{
heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
}
heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
break;
}
}

View File

@@ -246,7 +246,8 @@ namespace Juliet::D3D12
d3d12Driver->GraphicsQueue->ExecuteCommandLists(1, ppCommandLists);
// 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)
{
return false;
@@ -487,7 +488,8 @@ namespace Juliet::D3D12
// Release Fence if needed
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;
}

View File

@@ -604,7 +604,8 @@ namespace Juliet::D3D12
{
if (windowData->InFlightFences[idx] != nullptr)
{
ReleaseFence(driver, windowData->InFlightFences[idx]);
ReleaseFence(driver,
windowData->InFlightFences[idx] JULIET_DEBUG_PARAM(ConstString("DeatchFromWindow")));
windowData->InFlightFences[idx] = nullptr;
}
}

View File

@@ -140,7 +140,8 @@ namespace Juliet::D3D12
{
// Wait until the fence for the frame is signaled.
// 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;
}
@@ -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;
}
@@ -219,7 +221,8 @@ namespace Juliet::D3D12
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;
}

View File

@@ -17,16 +17,21 @@ namespace Juliet::D3D12
driver->AvailableFenceCapacity = driver->AvailableFenceCapacity * 2;
driver->AvailableFences = static_cast<D3D12Fence**>(
Realloc(driver->AvailableFences, sizeof(D3D12Fence*) * driver->AvailableFenceCapacity));
LogMessage(LogCategory::Core, "ReleaseFenceToPool With Realloc");
}
driver->AvailableFences[driver->AvailableFenceCount] = fence;
driver->AvailableFenceCount += 1;
LogMessage(LogCategory::Core, "ReleaseFenceToPool %x fence. Handle %x | Event %x | Refcount %d",
fence.Get(), fence->Handle, fence->Event, fence->ReferenceCount);
}
} // namespace
bool WaitUntilGPUIsIdle(NonNullPtr<GPUDriver> driver)
{
auto d3d12driver = static_cast<D3D12Driver*>(driver.Get());
D3D12Fence* fence = Internal::AcquireFence(d3d12driver);
D3D12Fence* fence = Internal::AcquireFence(d3d12driver JULIET_DEBUG_PARAM(ConstString("WaitUntilGPUIsIdle")));
if (!fence)
{
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;
@@ -71,16 +76,17 @@ namespace Juliet::D3D12
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());
// 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)
{
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);
if (FAILED(res))
@@ -91,6 +97,13 @@ namespace Juliet::D3D12
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);
if (waitResult == WAIT_FAILED)
@@ -122,11 +135,13 @@ namespace Juliet::D3D12
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 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)
{
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;
ID3D12Fence* handle;
@@ -197,15 +212,22 @@ namespace Juliet::D3D12
fence->Handle = handle;
fence->Event = CreateEvent(nullptr, false, false, nullptr);
fence->ReferenceCount = 0;
LogMessage(LogCategory::Core, "Acquire Querier %s | Setting Signal to 0 NEW fence", CStr(querier));
}
else
{
fence = driver->AvailableFences[driver->AvailableFenceCount - 1];
driver->AvailableFenceCount -= 1;
fence->Handle->Signal(D3D12_FENCE_UNSIGNALED_VALUE);
LogMessage(LogCategory::Core, "Acquire Querier %s | Setting Signal to 0, RECYCLING", CStr(querier));
}
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;
}

View File

@@ -26,9 +26,10 @@ namespace Juliet::D3D12
};
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 void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence);
extern void ReleaseFence(NonNullPtr<GPUDriver> driver, NonNullPtr<Fence> fence JULIET_DEBUG_PARAM(String querier));
namespace Internal
{
@@ -36,7 +37,7 @@ namespace Juliet::D3D12
D3D12_RESOURCE_STATES destinationState, ID3D12Resource* resource,
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);
} // namespace Internal
} // namespace Juliet::D3D12

View File

@@ -1,13 +1,13 @@
#include <algorithm>
#include <Core/Common/EnumUtils.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Core/Memory/Allocator.h>
#include <Graphics/D3D12/D3D12CommandList.h>
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12Synchronization.h>
#include <Graphics/D3D12/D3D12Texture.h>
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12Utils.h>
#include <Core/Memory/Allocator.h>
#include <algorithm>
namespace Juliet::D3D12
{
@@ -375,13 +375,9 @@ namespace Juliet::D3D12
case TextureType::Texture_2D:
case TextureType::Texture_2DArray:
case TextureType::Texture_Cube:
case TextureType::Texture_CubeArray:
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
break;
case TextureType::Texture_CubeArray: desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; break;
case TextureType::Texture_3D:
case TextureType::Texture_3DArray:
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
break;
case TextureType::Texture_3DArray: desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; break;
}
desc.Alignment = 0;
@@ -396,14 +392,24 @@ namespace Juliet::D3D12
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if ((createInfo.Flags & TextureUsageFlag::ColorTarget) != TextureUsageFlag::None)
{
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
}
if ((createInfo.Flags & TextureUsageFlag::DepthStencilTarget) != TextureUsageFlag::None)
{
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
}
if ((createInfo.Flags & TextureUsageFlag::ComputeStorageWrite) != TextureUsageFlag::None)
{
desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}
D3D12_HEAP_PROPERTIES heapProps = {};
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;
D3D12_CLEAR_VALUE clearValue = {};
@@ -426,8 +432,9 @@ namespace Juliet::D3D12
pClearValue = &clearValue;
}
D3D12_RESOURCE_STATES initialState = GetDefaultTextureResourceState(createInfo.Flags);
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));
if (FAILED(hr))
@@ -454,7 +461,8 @@ namespace Juliet::D3D12
uint32 numLayers = std::max<uint32>(1, createInfo.LayerCount);
uint32 numMips = std::max<uint32>(1, createInfo.MipLevelCount);
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)
{
@@ -529,7 +537,6 @@ namespace Juliet::D3D12
}
return reinterpret_cast<Texture*>(textureContainer);
}
void DestroyTexture(NonNullPtr<GPUDriver> driver, NonNullPtr<Texture> texture)

View File

@@ -83,7 +83,7 @@ namespace Juliet
// Fences
bool (*WaitUntilGPUIsIdle)(NonNullPtr<GPUDriver> driver);
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
Shader* (*CreateShader)(NonNullPtr<GPUDriver> driver, ByteBuffer shaderByteCode, ShaderCreateInfo& shaderCreateInfo);

View File

@@ -5,95 +5,5 @@
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

View 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

View File

@@ -21,6 +21,7 @@
#include <Graphics/GraphicsConfig.h>
#include <Graphics/GraphicsPipeline.h>
#include <Graphics/Mesh.h>
#include <Graphics/MeshRenderer.h>
#include <Graphics/RenderPass.h>
#include <Graphics/VertexData.h>
#include <Juliet.h>
@@ -63,6 +64,8 @@ namespace
} Game;
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" };
Arena* PlatformArena = nullptr;
} // namespace
void JulietApplication::Init()
@@ -71,6 +74,8 @@ void JulietApplication::Init()
Log(LogLevel::Message, LogCategory::Tool, "%s", CStr(GetBasePath()));
PlatformArena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_PARAM("Platform Arena"));
GraphicsConfig config;
#if JULIET_DEBUG
config.EnableDebug = true;
@@ -85,42 +90,7 @@ void JulietApplication::Init()
{
AttachToWindow(GraphicsDevice, MainWindow);
{
// 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, 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;
}
Running = InitializeMeshRenderer(PlatformArena, GraphicsDevice, MainWindow);
// Create Depth Buffer
TextureCreateInfo depthCI = {};
@@ -139,50 +109,11 @@ void JulietApplication::Init()
Running = false;
}
// Create Buffers - Using StructuredBuffer for bindless SRV access in shader
BufferCreateInfo bufferCI = {};
bufferCI.Size = 1024;
bufferCI.Usage = BufferUsage::StructuredBuffer; // SRV for ResourceDescriptorHeap access
StructuredBuffer = CreateGraphicsBuffer(GraphicsDevice, bufferCI);
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);
}
// std::ignore = AddCube();
//
// CommandList* loadCmd = AcquireCommandList(GraphicsDevice);
// LoadMeshesOnGPU(loadCmd);
// SubmitCommandLists(loadCmd);
if (Running == false)
{
@@ -208,8 +139,6 @@ void JulietApplication::Shutdown()
{
Log(LogLevel::Message, LogCategory::Tool, "Shutting down Juliet Application...");
ArenaRelease(CubeArena);
if (GameCode.IsValid)
{
Game.Shutdown();
@@ -220,19 +149,14 @@ void JulietApplication::Shutdown()
{
DestroyGraphicsPipeline(GraphicsDevice, GraphicsPipeline);
}
if (StructuredBuffer)
{
DestroyGraphicsBuffer(GraphicsDevice, StructuredBuffer);
}
if (TransferBuffer)
{
DestroyGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
}
if (DepthBuffer)
{
DestroyTexture(GraphicsDevice, DepthBuffer);
}
ShutdownMeshRenderer();
if (MainWindow && GraphicsDevice)
{
DetachFromWindow(GraphicsDevice, MainWindow);
@@ -248,6 +172,8 @@ void JulietApplication::Shutdown()
DestroyGraphicsDevice(GraphicsDevice);
}
ArenaRelease(PlatformArena);
Log(LogLevel::Message, LogCategory::Tool, "Juliet App shutdown Completed");
}
@@ -281,7 +207,7 @@ void JulietApplication::Update()
}
#ifdef JULIET_ENABLE_IMGUI
ImGui::ShowDemoWindow();
// ImGui::ShowDemoWindow();
#endif
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);
#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);
}
ReloadMeshRendererShaders();
#endif
}
@@ -361,76 +267,16 @@ void JulietApplication::Update()
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
if (StructuredBuffer && TransferBuffer)
{
void* ptr = MapGraphicsTransferBuffer(GraphicsDevice, TransferBuffer);
if (ptr)
{
Vertex* vertices = static_cast<Vertex*>(ptr);
// RenderMeshes(pass, cmd, pushData);
// // Triangle 1
// 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);
// SetPushConstants(cmd, ShaderStage::Vertex, 0, sizeof(pushData) / 4, &pushData);
}
ColorTargetInfo JulietApplication::GetColorTargetInfo(Texture* swapchainTexture)

View File

@@ -42,13 +42,7 @@ class JulietApplication : public Juliet::IApplication
Juliet::GraphicsDevice* GraphicsDevice = {};
Juliet::HotReloadCode GameCode = {};
Juliet::GraphicsPipeline* GraphicsPipeline = {};
Juliet::GraphicsBuffer* StructuredBuffer = {};
Juliet::GraphicsTransferBuffer* TransferBuffer = {};
Juliet::Texture* DepthBuffer = {};
Juliet::Mesh* CubeMesh = {};
Juliet::Arena* CubeArena = nullptr;
Juliet::Arena* GameArena = nullptr;
Juliet::Arena* GameScratchArena = nullptr;