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);