summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-10-06 14:42:03 -0400
committerJonathan Bradley <jcb@pikum.xyz>2023-10-06 17:20:20 -0400
commit791c153aabd579f518a9b00613459cba13734797 (patch)
tree858ec6f9a8398398a8a53ec5a886bca5825c62e0 /src
parent286bf5539527500429cfca4ded0bb78406f6364b (diff)
Memory management - ctors and dtors
Diffstat (limited to 'src')
-rw-r--r--src/asset-manager.cpp2
-rw-r--r--src/dynamic-array.hpp28
-rw-r--r--src/ecs.cpp8
-rw-r--r--src/ecs.hpp1
-rw-r--r--src/entities.cpp8
-rw-r--r--src/event.cpp4
-rw-r--r--src/event.hpp1
-rw-r--r--src/game.cpp14
-rw-r--r--src/macros.hpp3
-rw-r--r--src/main.cpp2
-rw-r--r--src/memory.cpp2
-rw-r--r--src/memory.hpp23
-rw-r--r--src/window.cpp1
13 files changed, 81 insertions, 16 deletions
diff --git a/src/asset-manager.cpp b/src/asset-manager.cpp
index ff20360..fab26f7 100644
--- a/src/asset-manager.cpp
+++ b/src/asset-manager.cpp
@@ -82,7 +82,7 @@ const Asset *AM_Get(AssetHandle assetHandle) {
}
void AM_DebugPrint() {
- printf("Asset Manager printout\n");
+ printf("Asset Manager printout:\n");
for (uint64_t b = 0; b <= Asset_BucketContainer.bucketCounter; ++b) {
auto &bkt = Asset_BucketContainer.buckets[b];
long counter = b == Asset_BucketContainer.bucketCounter ? Asset_BucketContainer.itemCounter >> 32 : maxAssetItemsPerBucket;
diff --git a/src/dynamic-array.hpp b/src/dynamic-array.hpp
index 6b22f6b..284ddcc 100644
--- a/src/dynamic-array.hpp
+++ b/src/dynamic-array.hpp
@@ -7,6 +7,7 @@
#include <cstdint>
#include <cstring>
#include <cassert>
+#include <type_traits>
#define BAKE_DYN_ARRAY(T) template struct DynArray<T>;
@@ -48,6 +49,11 @@ void DynArrayDestroy(DynArrayBase *arr);
template <typename T> inline DynArray<T>::DynArray(int64_t count) {
this->elementSize = sizeof(T);
if (count > 0) DynArrayReserve(this, count);
+ if IS_CONSTRUCTIBLE(T) {
+ for (long i = 0; i < count; ++i) {
+ new (this->ptr + (i * sizeof(T))) T{};
+ }
+ }
}
template <typename T> inline DynArray<T>::DynArray() {
@@ -89,6 +95,12 @@ template <typename T> inline DynArray<T> &DynArray<T>::operator=(DynArray<T> &&r
}
template <typename T> inline DynArray<T>::~DynArray() {
+ if (this->ptr == nullptr || this->ptr == CAFE_BABE(char)) return;
+ if IS_DESTRUCTIBLE(T) {
+ for (long i = 0; i < this->elementCount; ++i) {
+ reinterpret_cast<T *>(this->ptr + (i * sizeof(T)))->~T();
+ }
+ }
DynArrayDestroy(this);
}
@@ -136,9 +148,12 @@ template <typename T> inline void DynArray<T>::Remove(std::size_t index) {
assert(index >= this->elementCount && "Invalid DynArray<T>::Remove() - Out of bounds");
uint64_t moveCount = (this->elementCount - index - 1);
auto *tmp = Pke_New(this->elementSize * moveCount);
+ if IS_DESTRUCTIBLE(T) {
+ reinterpret_cast<T>(this->ptr + (index * sizeof(T))).~T();
+ }
memcpy(tmp, this->ptr + (this->elementSize * (index + 1)), this->elementSize * moveCount);
memcpy(this->ptr + (this->elementSize * index), tmp, this->elementSize * moveCount);
- Pke_Delete(tmp, moveCount * this->elementSize);
+ Pke_Delete<T>(tmp, moveCount * this->elementSize);
this->elementCount -= 1;
}
@@ -150,8 +165,19 @@ template <typename T> inline void DynArray<T>::Reserve(int64_t count) {
}
template <typename T> inline void DynArray<T>::Resize(int64_t count) {
+ int64_t beforeCount = this->elementCount;
+ if IS_DESTRUCTIBLE(T) {
+ for (long i = count; i > beforeCount; --i) {
+ reinterpret_cast<T *>(this->ptr + (i * sizeof(T)))->~T();
+ }
+ }
if (count > 0) {
DynArrayReserve(this, count);
+ if IS_CONSTRUCTIBLE(T) {
+ for (long i = beforeCount; i < count; ++i) {
+ new (this->ptr + (i * sizeof(T))) T{};
+ }
+ }
}
this->elementCount = count;
}
diff --git a/src/ecs.cpp b/src/ecs.cpp
index 03596f3..88088f5 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -18,6 +18,7 @@ struct InstanceBucket {
};
DynArray<EntityHandle> EntitiesToBeRemoved{16}; // public
+DynArray<Entity> entitiesYetToBeRemoved{0};
DynArray<EntityHandle> entitiesMarkedForRemoval{16};
BucketContainer<EntityBucket, EntityHandle_T> Entities_BucketContainer{};
@@ -74,7 +75,6 @@ void ECS_MarkForRemoval(EntityHandle entityHandle) {
}
void ECS_Tick_Early(double delta) {
- static DynArray<Entity> entitiesYetToBeRemoved{0};
entitiesYetToBeRemoved.Resize(EntitiesToBeRemoved.Count());
EntitiesToBeRemoved.Resize(0);
for (long b = 0; b <= Entities_BucketContainer.bucketCounter; ++b) {
@@ -392,3 +392,9 @@ CompInstance *ECS_GetInstances(uint64_t bucketIndex, uint64_t &itemCount) {
}
return Comp_Instance_BucketContainer.buckets[bucketIndex].instances;
}
+
+void ECS_Teardown() {
+ entitiesYetToBeRemoved.~DynArray();
+ EntitiesToBeRemoved.~DynArray();
+ entitiesMarkedForRemoval.~DynArray();
+}
diff --git a/src/ecs.hpp b/src/ecs.hpp
index a7fd2ac..83646af 100644
--- a/src/ecs.hpp
+++ b/src/ecs.hpp
@@ -17,6 +17,7 @@ static struct {
} ComponentTypes;
void ECS_Init();
+void ECS_Teardown();
void ECS_Tick_Early(double delta);
void ECS_Tick_Late(double delta);
EntityHandle ECS_CreateEntity(EntityHandle parentEntHandle = EntityHandle{EntityHandle_T{0xFFFFFFFFFFFFFFFF}});
diff --git a/src/entities.cpp b/src/entities.cpp
index efa22ae..9b088ec 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -921,7 +921,7 @@ void EntityType_Teardown() {
// If we switch to a global pool, we will need to free here, and
// destroy the pool outside of this loop
vkDestroyDescriptorPool(vkDevice, et->vkDescriptorPool, vkAllocator);
- Pke_Delete(grBinds->vkDescriptorSets, MAX_FRAMES_IN_FLIGHT);
+ Pke_Delete<VkDescriptorSet>(grBinds->vkDescriptorSets, MAX_FRAMES_IN_FLIGHT);
}
if (grBinds->vertexBuffer != VK_NULL_HANDLE)
vkDestroyBuffer(vkDevice, grBinds->vertexBuffer, vkAllocator);
@@ -944,6 +944,12 @@ void EntityType_Teardown() {
vkFreeMemory(vkDevice, et->deviceMemoryVert, vkAllocator);
if (et->deviceMemoryTexture != VK_NULL_HANDLE)
vkFreeMemory(vkDevice, et->deviceMemoryTexture, vkAllocator);
+ if (et->modelsDir)
+ Pke_Delete<char>(et->modelsDir, strlen(et->modelsDir));
+ if (et->modelFile)
+ Pke_Delete<char>(et->modelFile, strlen(et->modelFile));
+ if (et->entityTypeCode)
+ Pke_Delete<char>(et->entityTypeCode, strlen(et->entityTypeCode));
}
if (vkSampler_Texture != VK_NULL_HANDLE)
vkDestroySampler(vkDevice, vkSampler_Texture, vkAllocator);
diff --git a/src/event.cpp b/src/event.cpp
index a129490..62ebd88 100644
--- a/src/event.cpp
+++ b/src/event.cpp
@@ -57,3 +57,7 @@ void Event_Dispatch(const char *name) {
}
}
+void Event_Teardown() {
+ eventBuckets.~DynArray();
+}
+
diff --git a/src/event.hpp b/src/event.hpp
index b7a5ffa..defa588 100644
--- a/src/event.hpp
+++ b/src/event.hpp
@@ -13,5 +13,6 @@ typedef void (*EventHandler)();
void Event_RegisterCallback(const char *name, EventHandler handler);
void Event_UnregisterCallback(const char *name, EventHandler handler);
void Event_Dispatch(const char *name);
+void Event_Teardown();
#endif /* PKE_EVENT_HPP */
diff --git a/src/game.cpp b/src/game.cpp
index f464c41..2345d72 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -483,17 +483,9 @@ void RecordImGuiUBO() {
void RecordImGuiModalCreateEntityType() {
if (ImGui::BeginPopupModal("CreateEntityType", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
- static bool needsReset = true;
static char modelsDir[64];
static char modelFile[64];
static char entityTypeCode[32];
- if (needsReset) {
- memset(modelsDir, '\0', 64);
- memset(modelFile, '\0', 64);
- memset(entityTypeCode, '\0', 32);
- entityTypeToCreate = Pke_New<EntityType>();
- needsReset = false;
- }
ImGui::InputText("Models Dir", modelsDir, 63);
ImGui::InputText("Model File", modelFile, 63);
@@ -508,6 +500,11 @@ void RecordImGuiModalCreateEntityType() {
if (ImGui::Button("Create")) {
// TODO some type of validation
+ memset(modelsDir, '\0', 64);
+ memset(modelFile, '\0', 64);
+ memset(entityTypeCode, '\0', 32);
+ assert(entityTypeToCreate == nullptr || entityTypeToCreate == CAFE_BABE(EntityType));
+ entityTypeToCreate = Pke_New<EntityType>();
char *sModelsDir = Pke_New<char>(strlen(modelsDir) + 1);
strncpy(sModelsDir, modelsDir, 63);
@@ -522,7 +519,6 @@ void RecordImGuiModalCreateEntityType() {
entityTypeToCreate->entityTypeCode = sEntityTypeCode;
shouldCreateEntityType = true;
- needsReset = true;
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
diff --git a/src/macros.hpp b/src/macros.hpp
index 33d942a..02ebb3d 100644
--- a/src/macros.hpp
+++ b/src/macros.hpp
@@ -8,6 +8,9 @@
#define CAFE_BABE(T) reinterpret_cast<T *>(0xCAFEBABE)
+#define IS_CONSTRUCTIBLE(T) constexpr(std::is_constructible<T>::value && !std::is_integral<T>::value && !std::is_floating_point<T>::value)
+#define IS_DESTRUCTIBLE(T) constexpr(std::is_destructible<T>::value && !std::is_integral<T>::value && !std::is_floating_point<T>::value)
+
#define TypeSafeInt2_H(TypeName, Type, Max, TypeName_T, TypeName_MAX, TypeName_T_MAX)\
using TypeName_T = Type; \
enum class TypeName : TypeName_T; \
diff --git a/src/main.cpp b/src/main.cpp
index d3ddd1c..5026013 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -97,7 +97,9 @@ int main() {
printf("UNHANDLED EXCEPTION\n");
}
printf("PKE SHUTDOWN INITIATED\n");
+ Event_Teardown();
EntityType_Teardown();
+ ECS_Teardown();
DestroyWindow();
Pke_DebugPrint();
AM_DebugPrint();
diff --git a/src/memory.cpp b/src/memory.cpp
index 87d5eca..360e2e2 100644
--- a/src/memory.cpp
+++ b/src/memory.cpp
@@ -126,7 +126,7 @@ uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, ui
void Pke_DebugPrint() {
printf("Memory Manager printout:\nBucket count: %li\n", bucketHead + 1);
- for (long i = 0; i < bucketHead + 1; ++i) {
+ for (long i = 0; i <= bucketHead; ++i) {
printf("- bucket #%li\n", i);
printf("\tsize: %li\n", buckets[i].size);
printf("\thead: %li\n", buckets[i].head);
diff --git a/src/memory.hpp b/src/memory.hpp
index bde3f2b..6d431fc 100644
--- a/src/memory.hpp
+++ b/src/memory.hpp
@@ -8,6 +8,8 @@
#include <cstdlib>
#include <cstdio>
#include <cassert>
+#include <type_traits>
+#include <new>
// 256MB
#define DEFAULT_BUCKET_SIZE 1UL << 27
@@ -35,18 +37,35 @@ void Pke_MemoryFlush();
template <typename T>
inline T *Pke_New() {
void *ptr = Pke_New(sizeof(T));
- return new (ptr) T{};
+ if IS_CONSTRUCTIBLE(T) {
+ return new (ptr) T{};
+ }
+ return reinterpret_cast<T *>(ptr);
}
template <typename T>
inline T *Pke_New(long count) {
- return reinterpret_cast<T *>(Pke_New(sizeof(T) * count));
+ char *ptr = static_cast<char *>(Pke_New(sizeof(T) * count));
+ if IS_CONSTRUCTIBLE(T) {
+ for (long i = 0; i < count; ++i) {
+ new (ptr + (i * sizeof(T))) T{};
+ }
+ }
+ return reinterpret_cast<T *>(ptr);
}
template <typename T>
inline void Pke_Delete(const void *ptr) {
+ if IS_DESTRUCTIBLE(T) {
+ reinterpret_cast<const T *>(ptr)->~T();
+ }
return Pke_Delete(ptr, sizeof(T));
}
template <typename T>
inline void Pke_Delete(const void *ptr, long count) {
+ if IS_DESTRUCTIBLE(T) {
+ for (long i = 0; i < count; ++i) {
+ reinterpret_cast<const T *>(reinterpret_cast<const char *>(ptr) + (i * sizeof(T)))->~T();
+ }
+ }
return Pke_Delete(ptr, sizeof(T) * count);
}
diff --git a/src/window.cpp b/src/window.cpp
index 2f97be6..0bd1140 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -203,6 +203,7 @@ unsigned int FindQueueFamilyIndex(VkPhysicalDevice device, short hasPresentSuppo
continue;
}
}
+ Pke_Delete<VkQueueFamilyProperties>(queueFamilyProperties, queueFamilyPropertyCount);
return i;
}