From 679edf48ed3f7e06cb5535549d281564ad699712 Mon Sep 17 00:00:00 2001 From: Patedam Date: Sun, 8 Feb 2026 22:21:31 -0500 Subject: [PATCH] Converted everything that was using the old "EngineArena" to our new Arena type --- Juliet/Juliet.vcxproj | 1 - Juliet/Juliet.vcxproj.filters | 3 - Juliet/include/Core/Container/Vector.h | 10 +- Juliet/include/Core/HotReload/HotReload.h | 5 +- Juliet/include/Core/Memory/MemoryArena.h | 6 + Juliet/include/Juliet.h | 2 + Juliet/src/Core/HAL/Display/Display.cpp | 1 - .../HAL/Display/Win32/Win32DisplayDevice.cpp | 1 - .../Core/HAL/Display/Win32/Win32Window.cpp | 3 +- Juliet/src/Core/HotReload/HotReload.cpp | 11 +- Juliet/src/Core/ImGui/ImGuiService.cpp | 29 +---- Juliet/src/Core/Memory/EngineArena.h | 10 -- Juliet/src/Core/Memory/MemoryArena.cpp | 15 +-- Juliet/src/Engine/Debug/MemoryDebugger.cpp | 2 - .../src/Graphics/D3D12/D3D12CommandList.cpp | 7 +- Juliet/src/Graphics/D3D12/D3D12Common.cpp | 16 ++- Juliet/src/Graphics/D3D12/D3D12Common.h | 9 +- .../Graphics/D3D12/D3D12DescriptorHeap.cpp | 115 ++++++++++-------- .../src/Graphics/D3D12/D3D12DescriptorHeap.h | 31 +++-- .../Graphics/D3D12/D3D12GraphicsDevice.cpp | 55 ++------- Juliet/src/Graphics/GraphicsDevice.h | 13 +- 21 files changed, 156 insertions(+), 189 deletions(-) delete mode 100644 Juliet/src/Core/Memory/EngineArena.h diff --git a/Juliet/Juliet.vcxproj b/Juliet/Juliet.vcxproj index de66553..2e691f3 100644 --- a/Juliet/Juliet.vcxproj +++ b/Juliet/Juliet.vcxproj @@ -156,7 +156,6 @@ - diff --git a/Juliet/Juliet.vcxproj.filters b/Juliet/Juliet.vcxproj.filters index 9f1d957..2394074 100644 --- a/Juliet/Juliet.vcxproj.filters +++ b/Juliet/Juliet.vcxproj.filters @@ -315,9 +315,6 @@ src\Core\Memory - - src\Core\Memory - src\Core\Memory diff --git a/Juliet/include/Core/Container/Vector.h b/Juliet/include/Core/Container/Vector.h index 82b89fb..a8bee89 100644 --- a/Juliet/include/Core/Container/Vector.h +++ b/Juliet/include/Core/Container/Vector.h @@ -16,7 +16,7 @@ namespace Juliet DataFirst = DataLast = nullptr; Count = 0; Stride = sizeof(Type); - Arena = ArenaAllocate(); + Arena = ArenaAllocate(JULIET_DEBUG_ONLY({ .CanReserveMore = false })); } void Destroy() { @@ -27,6 +27,14 @@ namespace Juliet Arena = nullptr; } + void Resize(size_t newCount) + { + Type* entry = ArenaPushArray(Arena, newCount); + Count = newCount; + DataFirst = entry; + DataLast = entry + newCount; + } + void PushBack(const Type& value) { Assert(Arena); diff --git a/Juliet/include/Core/HotReload/HotReload.h b/Juliet/include/Core/HotReload/HotReload.h index da236a8..25dff9a 100644 --- a/Juliet/include/Core/HotReload/HotReload.h +++ b/Juliet/include/Core/HotReload/HotReload.h @@ -9,6 +9,8 @@ namespace Juliet struct HotReloadCode { + Arena* Arena; + String DLLFullPath; String LockFullPath; String TransientDLLName; @@ -26,8 +28,7 @@ namespace Juliet bool IsValid : 1; }; - extern JULIET_API void InitHotReloadCode(HotReloadCode& code, String dllName, - String transientDllName, String lockFilename); + extern JULIET_API void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename); extern JULIET_API void ShutdownHotReloadCode(HotReloadCode& code); extern JULIET_API void LoadCode(HotReloadCode& code); diff --git a/Juliet/include/Core/Memory/MemoryArena.h b/Juliet/include/Core/Memory/MemoryArena.h index 7f29ed1..2c6d190 100644 --- a/Juliet/include/Core/Memory/MemoryArena.h +++ b/Juliet/include/Core/Memory/MemoryArena.h @@ -30,6 +30,8 @@ namespace Juliet uint64 Reserved; Arena* FreeLast; + + JULIET_DEBUG_ONLY(bool CanReserveMore : 1;) }; static_assert(sizeof(Arena) <= k_ArenaHeaderSize); @@ -37,6 +39,10 @@ namespace Juliet { uint64 ReserveSize = g_Arena_Default_Reserve_Size; uint64 CommitSize = g_Arena_Default_Commit_Size; + + // When false, will assert if a new block is reserved. + // Useful for Vectors as they are guaranteed to be linear and i wont need to implement memcopy to increase capacity + JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;) }; [[nodiscard]] Arena* ArenaAllocate(const ArenaParams& params = {}, diff --git a/Juliet/include/Juliet.h b/Juliet/include/Juliet.h index 9026b29..b202916 100644 --- a/Juliet/include/Juliet.h +++ b/Juliet/include/Juliet.h @@ -21,8 +21,10 @@ #ifdef DEBUG #define JULIET_DEBUG 1 +#define JULIET_DEBUG_ONLY(expr) expr #else #define JULIET_DEBUG 0 +#define JULIET_DEBUG_ONLY(expr) #endif // Manual override to disable ImGui diff --git a/Juliet/src/Core/HAL/Display/Display.cpp b/Juliet/src/Core/HAL/Display/Display.cpp index 1d8745e..db66949 100644 --- a/Juliet/src/Core/HAL/Display/Display.cpp +++ b/Juliet/src/Core/HAL/Display/Display.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include namespace Juliet diff --git a/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp b/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp index f700464..241ea09 100644 --- a/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp +++ b/Juliet/src/Core/HAL/Display/Win32/Win32DisplayDevice.cpp @@ -1,7 +1,6 @@ #include #include #include -#include namespace Juliet::Win32 { diff --git a/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp b/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp index aa3f7db..1ba3b9a 100644 --- a/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp +++ b/Juliet/src/Core/HAL/Display/Win32/Win32Window.cpp @@ -2,8 +2,7 @@ #include #include #include -#include -#include +#include namespace Juliet::Win32 { diff --git a/Juliet/src/Core/HotReload/HotReload.cpp b/Juliet/src/Core/HotReload/HotReload.cpp index da31704..9d41a68 100644 --- a/Juliet/src/Core/HotReload/HotReload.cpp +++ b/Juliet/src/Core/HotReload/HotReload.cpp @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include #include @@ -13,6 +11,8 @@ namespace Juliet { void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename) { + code.Arena = ArenaAllocate(); + // Get the app base path and build the dll path from there. String basePath = GetBasePath(); size_t basePathLength = StringLength(basePath); @@ -24,7 +24,8 @@ namespace Juliet // TODO: Add path composition into filesystem + string format + string builder const size_t dllFullPathLength = basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings - code.DLLFullPath.Data = ArenaPushArray(GetEngineArena(), dllFullPathLength, ConstString("DLLFullPath")); + + code.DLLFullPath.Data = ArenaPushArray(code.Arena, dllFullPathLength); int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName)); if (writtenSize < static_cast(dllFullPathLength) - 1) { @@ -37,7 +38,7 @@ namespace Juliet // Lock filename path const size_t lockPathLength = basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings - code.LockFullPath.Data = ArenaPushArray(GetEngineArena(), lockPathLength, ConstString("LockFullPath")); + code.LockFullPath.Data = ArenaPushArray(code.Arena, lockPathLength); writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename)); if (writtenSize < static_cast(lockPathLength) - 1) { @@ -59,6 +60,8 @@ namespace Juliet // Arena memory persists until engine shutdown code.LockFullPath.Size = 0; // Arena memory persists until engine shutdown + + ArenaRelease(code.Arena); } void ReloadCode(HotReloadCode& code) diff --git a/Juliet/src/Core/ImGui/ImGuiService.cpp b/Juliet/src/Core/ImGui/ImGuiService.cpp index a4a07e5..667632b 100644 --- a/Juliet/src/Core/ImGui/ImGuiService.cpp +++ b/Juliet/src/Core/ImGui/ImGuiService.cpp @@ -9,7 +9,6 @@ #include #include -#include #include // Forward declare implementation functions from backends @@ -24,34 +23,16 @@ namespace Juliet::ImGuiService // Dedicated Paged Arena for ImGui // Sharing the same underlying Engine Pool for blocks, but separate Arena chain. - MemoryArena g_ImGuiArena; + Arena* g_ImGuiArena = {}; void* ImGuiAllocWrapper(size_t size, void* /*user_data*/) { - // Store size in header to allow Pop - // Align total size to 16 to avoid padding issues with ArenaPop LIFO check - size_t actualSize = size + 16; - actualSize = (actualSize + 15) & ~static_cast(15); - - // We do save the size when we push so we can pop exactly the size. - if (void* ptr = ArenaPush(&g_ImGuiArena, actualSize, 16, ConstString("ImGui"))) - { - // Write size at start - *static_cast(ptr) = actualSize; - return static_cast(ptr) + 16; - } - return nullptr; + return ArenaPush(g_ImGuiArena, size, 8, false); } - void ImGuiFreeWrapper(void* ptr, void* /*user_data*/) + void ImGuiFreeWrapper(void* /*ptr*/, void* /*user_data*/) { - Assert(ptr); - - uint8* originalPtr = static_cast(ptr) - 16; - size_t actualSize = *reinterpret_cast(originalPtr); - - // Attempt LIFO Pop - ArenaPop(&g_ImGuiArena, originalPtr, actualSize); + // TODO : Free list of imgui elements. } } // namespace @@ -60,7 +41,7 @@ namespace Juliet::ImGuiService Assert(!g_Initialized); // Initialize ImGui Arena using Engine Pool - MemoryArenaCreate(&g_ImGuiArena, GetEngineArena()->BackingPool); + g_ImGuiArena = ArenaAllocate(); // Setup Allocator ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper, nullptr); diff --git a/Juliet/src/Core/Memory/EngineArena.h b/Juliet/src/Core/Memory/EngineArena.h deleted file mode 100644 index e64a49d..0000000 --- a/Juliet/src/Core/Memory/EngineArena.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -namespace Juliet -{ - // Persistent engine-only arena. - // Not exported to the Game DLL. - MemoryArena* GetEngineArena(); -} // namespace Juliet diff --git a/Juliet/src/Core/Memory/MemoryArena.cpp b/Juliet/src/Core/Memory/MemoryArena.cpp index 469e3d4..f7ac744 100644 --- a/Juliet/src/Core/Memory/MemoryArena.cpp +++ b/Juliet/src/Core/Memory/MemoryArena.cpp @@ -44,6 +44,8 @@ namespace Juliet arena->BasePosition = 0; arena->Position = k_ArenaHeaderSize; + arena->CanReserveMore = params.CanReserveMore; + return arena; } @@ -65,6 +67,8 @@ namespace Juliet // If allowed and needed, add a new block and chain it to the arena. if (current->Reserved < positionPostPush /* flags : chaining allowed */) { + Assert(arena->CanReserveMore); + Arena* newBlock = nullptr; { Arena* prev_block; @@ -552,11 +556,9 @@ namespace Juliet namespace { MemoryPool g_ScratchMemory; - MemoryPool g_EngineMemory; MemoryPool g_GameMemory; MemoryArena g_ScratchArena; - MemoryArena g_EngineArena; MemoryArena g_GameArena; // Backing Buffers @@ -565,7 +567,6 @@ namespace Juliet void* g_GameBuffer = nullptr; constexpr size_t kScratchSize = Megabytes(64); - constexpr size_t kEngineSize = Megabytes(256); constexpr size_t kGameSize = Megabytes(512); void InitPool(MemoryPool* pool, void* buffer, size_t size) @@ -589,10 +590,7 @@ namespace Juliet { return &g_ScratchArena; } - MemoryArena* GetEngineArena() - { - return &g_EngineArena; - } + MemoryArena* GetGameArena() { return &g_GameArena; @@ -606,15 +604,12 @@ namespace Juliet void MemoryArenasInit() { g_ScratchBuffer = Malloc(kScratchSize); - g_EngineBuffer = Malloc(kEngineSize); g_GameBuffer = Malloc(kGameSize); InitPool(&g_ScratchMemory, g_ScratchBuffer, kScratchSize); - InitPool(&g_EngineMemory, g_EngineBuffer, kEngineSize); InitPool(&g_GameMemory, g_GameBuffer, kGameSize); MemoryArenaCreate(&g_ScratchArena, &g_ScratchMemory); - MemoryArenaCreate(&g_EngineArena, &g_EngineMemory); MemoryArenaCreate(&g_GameArena, &g_GameMemory); #if JULIET_DEBUG diff --git a/Juliet/src/Engine/Debug/MemoryDebugger.cpp b/Juliet/src/Engine/Debug/MemoryDebugger.cpp index c47498b..a519065 100644 --- a/Juliet/src/Engine/Debug/MemoryDebugger.cpp +++ b/Juliet/src/Engine/Debug/MemoryDebugger.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -420,7 +419,6 @@ namespace Juliet::Debug if (ImGui::Begin("Memory Debugger")) { DrawMemoryArena(ConstString("Game Arena"), *GetGameArena(), s_ConfirmedHovered, frameHovered); - DrawMemoryArena(ConstString("Engine Arena"), *GetEngineArena(), s_ConfirmedHovered, frameHovered); } ImGui::End(); diff --git a/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp b/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp index d5e61fb..fc5ab4c 100644 --- a/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12CommandList.cpp @@ -454,8 +454,11 @@ namespace Juliet::D3D12 return false; } - ReturnSamplerHeapToPool(driver, commandList->Sampler_Heap); - commandList->Sampler_Heap = nullptr; + if (commandList->Sampler_Heap) [[likely]] + { + ReturnSamplerHeapToPool(driver, commandList->Sampler_Heap); + commandList->Sampler_Heap = nullptr; + } commandList->CRB_SRV_UAV_Heap = nullptr; // Clean up resource tracking diff --git a/Juliet/src/Graphics/D3D12/D3D12Common.cpp b/Juliet/src/Graphics/D3D12/D3D12Common.cpp index b5ccea6..afe5656 100644 --- a/Juliet/src/Graphics/D3D12/D3D12Common.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12Common.cpp @@ -4,8 +4,8 @@ #include #include #include -#include +// TODO: Convert the whole file to memory arenas namespace Juliet::D3D12::Internal { namespace @@ -25,8 +25,8 @@ namespace Juliet::D3D12::Internal bool ExtendStagingDescriptorPool(NonNullPtr driver, D3D12StagingDescriptorPool& pool) { - D3D12DescriptorHeap* heap = - Internal::CreateDescriptorHeap(driver, pool.Heaps[0]->HeapType, kStagingHeapDescriptorExpectedCount, true); + D3D12DescriptorHeap* heap = Internal::CreateDescriptorHeap(driver, pool.Arena, pool.Heaps[0]->HeapType, + kStagingHeapDescriptorExpectedCount, true); if (!heap) { return false; @@ -49,13 +49,17 @@ namespace Juliet::D3D12::Internal D3D12StagingDescriptorPool* CreateStagingDescriptorPool(NonNullPtr driver, D3D12_DESCRIPTOR_HEAP_TYPE type) { - D3D12DescriptorHeap* heap = CreateDescriptorHeap(driver, type, kStagingHeapDescriptorExpectedCount, true); + Arena* arena = ArenaAllocate(); + + D3D12DescriptorHeap* heap = CreateDescriptorHeap(driver, arena, type, kStagingHeapDescriptorExpectedCount, true); if (!heap) { + ArenaRelease(arena); return nullptr; } - auto pool = static_cast(Calloc(1, sizeof(D3D12StagingDescriptorPool))); + auto pool = static_cast(Calloc(1, sizeof(D3D12StagingDescriptorPool))); + pool->Arena = arena; // First create the heaps pool->HeapCount = 1; @@ -113,6 +117,8 @@ namespace Juliet::D3D12::Internal Free(pool->Heaps); Free(pool->FreeDescriptors); + + ArenaRelease(pool->Arena); Free(pool.Get()); } } // namespace Juliet::D3D12::Internal diff --git a/Juliet/src/Graphics/D3D12/D3D12Common.h b/Juliet/src/Graphics/D3D12/D3D12Common.h index ff0f676..afccec4 100644 --- a/Juliet/src/Graphics/D3D12/D3D12Common.h +++ b/Juliet/src/Graphics/D3D12/D3D12Common.h @@ -22,8 +22,9 @@ namespace Juliet::D3D12 struct D3D12StagingDescriptorPool { + Arena* Arena; Internal::D3D12DescriptorHeap** Heaps; - uint32 HeapCount; + uint32 HeapCount; // Descriptor handles are owned by resources, so these can be thought of as descriptions of a free index within a heap. uint32 FreeDescriptorCapacity; @@ -35,9 +36,9 @@ namespace Juliet::D3D12 struct D3D12StagingDescriptor { D3D12StagingDescriptorPool* Pool; - Internal::D3D12DescriptorHeap* Heap; - D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle; - uint32 CpuHandleIndex; + Internal::D3D12DescriptorHeap* Heap; + D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle; + uint32 CpuHandleIndex; }; namespace Internal diff --git a/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.cpp b/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.cpp index 05921ab..2cd7c4a 100644 --- a/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.cpp @@ -1,26 +1,52 @@ #include #include #include -#include #include #include #include namespace Juliet::D3D12::Internal { - D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr driver, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging) + void CreateDescriptorHeapPool(NonNullPtr driver, D3D12DescriptorHeapPool& heapPool, + D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count) { - auto heap = ArenaPushType(GetEngineArena(), ConstString("D3D12DescriptorHeap")); - if (!heap) + // Heap pool is just single linked list of free elements + constexpr size_t kInitialCapacity = 4; + heapPool.Arena = ArenaAllocate(); + heapPool.FirstFreeDescriptorHeap = nullptr; + + // Pre allocate 4 + for (uint32 i = 0; i < kInitialCapacity; ++i) { - return nullptr; + D3D12DescriptorHeap* descriptorHeap = CreateDescriptorHeap(driver, heapPool.Arena, type, count, false); + descriptorHeap->Next = heapPool.FirstFreeDescriptorHeap; + heapPool.FirstFreeDescriptorHeap = descriptorHeap; } + } + + void DestroyDescriptorHeapPool(D3D12DescriptorHeapPool& heapPool) + { + D3D12DescriptorHeap* current = heapPool.FirstFreeDescriptorHeap; + while (current != nullptr) + { + D3D12DescriptorHeap* next = current->Next; + DestroyDescriptorHeap(current); + current = next; + } + ArenaRelease(heapPool.Arena); + } + + D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr driver, NonNullPtr arena, + D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging) + { + D3D12DescriptorHeap* heap = ArenaPushStruct(arena.Get()); + Assert(heap); heap->CurrentDescriptorIndex = 0; - heap->FreeIndicesCapacity = 16; - heap->FreeIndicesCount = 0; - heap->FreeIndices = ArenaPushArray(GetEngineArena(), heap->FreeIndicesCapacity, - ConstString("D3D12DescriptorHeap/FreeIndices")); + + heap->FreeIndices.Create(); + heap->FreeIndices.Resize(16); + heap->CurrentFreeIndex = 0; D3D12_DESCRIPTOR_HEAP_DESC heapDesc; heapDesc.NumDescriptors = count; @@ -54,23 +80,21 @@ namespace Juliet::D3D12::Internal void DestroyDescriptorHeap(NonNullPtr heap) { + heap->FreeIndices.Destroy(); if (heap->Handle) { heap->Handle->Release(); } - // TODO: should not free because its on an arena, but need to use arena properly - // SafeFree(heap->FreeIndices); - // Free(heap.Get()); } bool AssignDescriptor(D3D12DescriptorHeap* heap, D3D12Descriptor& outDescriptor) { uint32 index = UINT32_MAX; - if (heap->FreeIndicesCount > 0) + if (heap->CurrentFreeIndex > 0) { - heap->FreeIndicesCount -= 1; - index = heap->FreeIndices[heap->FreeIndicesCount]; + heap->CurrentFreeIndex -= 1; + index = heap->FreeIndices[heap->CurrentFreeIndex]; } else if (heap->CurrentDescriptorIndex < heap->MaxDescriptors) { @@ -102,55 +126,42 @@ namespace Juliet::D3D12::Internal D3D12DescriptorHeap* heap = descriptor.Heap; - if (heap->FreeIndicesCount >= heap->FreeIndicesCapacity) + if (heap->CurrentFreeIndex >= heap->FreeIndices.Count) { - size_t oldCapacity = heap->FreeIndicesCapacity; - heap->FreeIndicesCapacity *= 2; - heap->FreeIndices = ArenaRealloc(GetEngineArena(), heap->FreeIndices, oldCapacity, - heap->FreeIndicesCapacity, ConstString("FreeIndices")); - } - - heap->FreeIndices[heap->FreeIndicesCount] = descriptor.Index; - heap->FreeIndicesCount++; - } - - D3D12DescriptorHeap* AcquireSamplerHeapFromPool(NonNullPtr d3d12Driver, DescriptorHeapCreator creator) - { - D3D12DescriptorHeap* result; - D3D12DescriptorHeapPool* pool = &d3d12Driver->SamplerHeapPool; - - if (pool->Count > 0) - { - result = pool->Heaps[pool->Count - 1]; - pool->Count -= 1; + heap->FreeIndices.PushBack(descriptor.Index); } else { - result = creator(d3d12Driver, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GPUDriver::kSampler_HeapDescriptorCount, false); + heap->FreeIndices[heap->CurrentFreeIndex] = descriptor.Index; + heap->CurrentFreeIndex++; + } + } + + D3D12DescriptorHeap* AcquireSamplerHeapFromPool(NonNullPtr d3d12Driver) + { + D3D12DescriptorHeapPool& pool = d3d12Driver->SamplerHeapPool; + + D3D12DescriptorHeap* result = pool.FirstFreeDescriptorHeap; + if (result) + { + pool.FirstFreeDescriptorHeap = pool.FirstFreeDescriptorHeap->Next; + } + else + { + result = CreateDescriptorHeap(d3d12Driver, pool.Arena, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, + GPUDriver::kSampler_HeapDescriptorCount, false); } return result; } - void ReturnSamplerHeapToPool(NonNullPtr d3d12Driver, D3D12DescriptorHeap* heap) + void ReturnSamplerHeapToPool(NonNullPtr d3d12Driver, NonNullPtr heap) { - if (heap == nullptr) - { - return; - } - - D3D12DescriptorHeapPool* pool = &d3d12Driver->SamplerHeapPool; + D3D12DescriptorHeapPool& pool = d3d12Driver->SamplerHeapPool; heap->CurrentDescriptorIndex = 0; - if (pool->Count >= pool->Capacity) - { - size_t oldCapacity = pool->Capacity; - pool->Capacity *= 2; - pool->Heaps = ArenaRealloc(GetEngineArena(), pool->Heaps, oldCapacity, pool->Capacity, ConstString("Heaps")); - } - - pool->Heaps[pool->Count] = heap; - pool->Count += 1; + heap->Next = pool.FirstFreeDescriptorHeap; + pool.FirstFreeDescriptorHeap = heap; } } // namespace Juliet::D3D12::Internal diff --git a/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.h b/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.h index c101473..4804c0b 100644 --- a/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.h +++ b/Juliet/src/Graphics/D3D12/D3D12DescriptorHeap.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include // Forward declare @@ -14,6 +15,7 @@ namespace Juliet::D3D12::Internal // https://learn.microsoft.com/en-us/windows/win32/direct3d12/descriptor-heaps struct D3D12DescriptorHeap { + D3D12DescriptorHeap* Next; ID3D12DescriptorHeap* Handle; D3D12_DESCRIPTOR_HEAP_TYPE HeapType; D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHeapCPUStart; @@ -22,11 +24,10 @@ namespace Juliet::D3D12::Internal uint32 DescriptorSize; uint32 CurrentDescriptorIndex; // only used by GPU heaps - uint32* FreeIndices; - uint32 FreeIndicesCapacity; - uint32 FreeIndicesCount; + VectorArena FreeIndices; + index_t CurrentFreeIndex; - bool Staging : 1; + bool Staging : 1; }; struct D3D12Descriptor @@ -39,20 +40,24 @@ namespace Juliet::D3D12::Internal struct D3D12DescriptorHeapPool { - D3D12DescriptorHeap** Heaps; - size_t Capacity; - size_t Count; + Arena* Arena; + D3D12DescriptorHeap* FirstFreeDescriptorHeap; }; - using DescriptorHeapCreator = D3D12DescriptorHeap* (*)(NonNullPtr, D3D12_DESCRIPTOR_HEAP_TYPE, uint32, bool); + using DescriptorHeapCreator = D3D12DescriptorHeap* (*)(NonNullPtr, D3D12DescriptorHeapPool& heapPool, + D3D12_DESCRIPTOR_HEAP_TYPE, uint32, bool); - extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr driver, - D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging); + extern void CreateDescriptorHeapPool(NonNullPtr driver, D3D12DescriptorHeapPool& heapPool, + D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count); + extern void DestroyDescriptorHeapPool(D3D12DescriptorHeapPool& pool); + + extern D3D12DescriptorHeap* CreateDescriptorHeap(NonNullPtr driver, NonNullPtr arena, + D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count, bool isStaging); extern void DestroyDescriptorHeap(NonNullPtr heap); - extern D3D12DescriptorHeap* AcquireSamplerHeapFromPool(NonNullPtr d3d12Driver, DescriptorHeapCreator creator = CreateDescriptorHeap); - extern void ReturnSamplerHeapToPool(NonNullPtr d3d12Driver, D3D12DescriptorHeap* heap); + extern D3D12DescriptorHeap* AcquireSamplerHeapFromPool(NonNullPtr d3d12Driver); + extern void ReturnSamplerHeapToPool(NonNullPtr d3d12Driver, NonNullPtr heap); extern bool AssignDescriptor(D3D12DescriptorHeap* heap, D3D12Descriptor& outDescriptor); extern void ReleaseDescriptor(const D3D12Descriptor& descriptor); -} // namespace Juliet::D3D12 +} // namespace Juliet::D3D12::Internal diff --git a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp index 483499b..bbe2971 100644 --- a/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp +++ b/Juliet/src/Graphics/D3D12/D3D12GraphicsDevice.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -471,22 +470,7 @@ namespace Juliet::D3D12 } } - auto DestroyDescriptorHeapPool = [](Internal::D3D12DescriptorHeapPool& heapPool) - { - if (heapPool.Heaps) - { - for (uint32 i = 0; i < heapPool.Count; ++i) - { - if (heapPool.Heaps[i]) - { - Internal::DestroyDescriptorHeap(heapPool.Heaps[i]); - heapPool.Heaps[i] = nullptr; - } - } - // SafeFree(heapPool.Heaps); // Allocated with Arena, do not free. - } - }; - DestroyDescriptorHeapPool(driver->SamplerHeapPool); + Internal::DestroyDescriptorHeapPool(driver->SamplerHeapPool); // Release command buffers for (uint32 i = 0; i < driver->AvailableCommandListCount; i += 1) @@ -571,6 +555,7 @@ namespace Juliet::D3D12 driver->D3D12SerializeVersionedRootSignatureFct = nullptr; + ArenaRelease(driver->DriverArena); Free(driver.Get()); } @@ -745,6 +730,9 @@ namespace Juliet::D3D12 { auto driver = static_cast(Calloc(1, sizeof(D3D12Driver))); + // TODO : Convert everything to arena + driver->DriverArena = ArenaAllocate(); + #if JULIET_DEBUG #ifdef IDXGIINFOQUEUE_SUPPORTED if (enableDebug) @@ -1023,32 +1011,8 @@ namespace Juliet::D3D12 } } - // Other Descriptor pools - auto CreateDescriptorPool = [&](Internal::D3D12DescriptorHeapPool& heapPool, - D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 count) -> bool - { - heapPool.Capacity = 4; - heapPool.Count = 4; - heapPool.Heaps = ArenaPushArray(GetEngineArena(), heapPool.Capacity, - ConstString("DescriptorHeap")); - - for (uint32 i = 0; i < heapPool.Capacity; ++i) - { - heapPool.Heaps[i] = Internal::CreateDescriptorHeap(driver, type, count, false); - - if (heapPool.Heaps[i] == nullptr) - { - return false; - } - } - return true; - }; - - if (!CreateDescriptorPool(driver->SamplerHeapPool, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GPUDriver::kSampler_HeapDescriptorCount)) - { - DestroyDriver_Internal(driver); - return nullptr; - } + CreateDescriptorHeapPool(driver, driver->SamplerHeapPool, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, + GPUDriver::kSampler_HeapDescriptorCount); // Deferred dispose vectors driver->GraphicsPipelinesToDisposeCapacity = 4; @@ -1125,8 +1089,9 @@ namespace Juliet::D3D12 driver->GraphicsDevice = device; // Create Global Bindless Heap that stays alive for the driver whole lifetime - driver->BindlessDescriptorHeap = Internal::CreateDescriptorHeap(driver, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - GPUDriver::kCBV_SRV_UAV_HeapDescriptorCount, false); + driver->BindlessDescriptorHeap = + Internal::CreateDescriptorHeap(driver, driver->DriverArena, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + GPUDriver::kCBV_SRV_UAV_HeapDescriptorCount, false); return device; } diff --git a/Juliet/src/Graphics/GraphicsDevice.h b/Juliet/src/Graphics/GraphicsDevice.h index 6086224..7ce668e 100644 --- a/Juliet/src/Graphics/GraphicsDevice.h +++ b/Juliet/src/Graphics/GraphicsDevice.h @@ -30,6 +30,8 @@ namespace Juliet struct GPUDriver { + Arena* DriverArena = {}; + static constexpr uint8 kMaxFramesInFlight = 3; static constexpr uint8 kMaxColorTargetInfo = 4; static constexpr uint8 kMaxUniformBuffersPerStage = 4; @@ -74,9 +76,6 @@ namespace Juliet void (*DrawIndexedPrimitives)(NonNullPtr commandList, uint32 numIndices, uint32 numInstances, uint32 firstIndex, uint32 vertexOffset, uint32 firstInstance); - - - void (*SetPushConstants)(NonNullPtr commandList, ShaderStage stage, uint32 rootParameterIndex, uint32 numConstants, const void* constants); @@ -108,10 +107,10 @@ namespace Juliet void* (*MapGraphicsTransferBuffer)(NonNullPtr driver, NonNullPtr buffer); void (*UnmapGraphicsTransferBuffer)(NonNullPtr driver, NonNullPtr buffer); - void (*CopyBuffer)(NonNullPtr commandList, NonNullPtr dst, - NonNullPtr src, size_t size, size_t dstOffset, size_t srcOffset); - void (*CopyBufferToTexture)(NonNullPtr commandList, NonNullPtr dst, - NonNullPtr src); // Assume full copy for now + void (*CopyBuffer)(NonNullPtr commandList, NonNullPtr dst, + NonNullPtr src, size_t size, size_t dstOffset, size_t srcOffset); + void (*CopyBufferToTexture)(NonNullPtr commandList, NonNullPtr dst, + NonNullPtr src); // Assume full copy for now void (*TransitionBufferToReadable)(NonNullPtr commandList, NonNullPtr buffer); uint32 (*GetDescriptorIndex)(NonNullPtr device, NonNullPtr buffer);