Using memory arena in the game that supports hot reload

This commit is contained in:
2026-07-28 15:44:41 -04:00
parent 39586c968a
commit 4081539ee4
24 changed files with 219 additions and 217 deletions
+19 -23
View File
@@ -18,35 +18,33 @@
constexpr Juliet::Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \ constexpr Juliet::Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \
const Juliet::Class* entity::Kind = &entityKind##entity; const Juliet::Class* entity::Kind = &entityKind##entity;
namespace Game using DerivedType = void*;
{
using DerivedType = void*;
struct Entity final struct Entity final
{ {
EntityID ID; EntityID ID;
const Juliet::Class* Kind; const Juliet::Class* Kind;
DerivedType Derived; DerivedType Derived;
float X, Y; float X, Y;
}; };
template <typename EntityType> template <typename EntityType>
concept EntityConcept = requires(EntityType entity) { concept EntityConcept = requires(EntityType entity) {
requires std::same_as<decltype(entity.Kind), const Juliet::Class*>; requires std::same_as<decltype(entity.Kind), const Juliet::Class*>;
requires std::same_as<decltype(entity.Base), Entity*>; requires std::same_as<decltype(entity.Base), Entity*>;
}; };
template <typename EntityType> template <typename EntityType>
requires EntityConcept<EntityType> requires EntityConcept<EntityType>
bool IsA(const Entity* entity) bool IsA(const Entity* entity)
{ {
return entity->Kind == EntityType::Kind; return entity->Kind == EntityType::Kind;
} }
template <typename EntityType> template <typename EntityType>
requires EntityConcept<EntityType> requires EntityConcept<EntityType>
EntityType* MakeEntity(EntityManager& manager, float x, float y) EntityType* MakeEntity(EntityManager& manager, float x, float y)
{ {
auto* arena = manager.Arena; auto* arena = manager.Arena;
EntityType* result = Juliet::ArenaPushStruct<EntityType>(arena); EntityType* result = Juliet::ArenaPushStruct<EntityType>(arena);
Entity base; Entity base;
@@ -61,14 +59,12 @@ namespace Game
RegisterEntity(manager, &base); RegisterEntity(manager, &base);
return result; return result;
} }
template <typename EntityType> template <typename EntityType>
requires EntityConcept<EntityType> requires EntityConcept<EntityType>
EntityType* DownCast(Entity* entity) EntityType* DownCast(Entity* entity)
{ {
Assert(IsA<EntityType>(entity)); Assert(IsA<EntityType>(entity));
return static_cast<EntityType*>(entity->Derived); return static_cast<EntityType*>(entity->Derived);
} }
} // namespace Game
+20 -23
View File
@@ -2,33 +2,30 @@
#include <Entity/Entity.h> #include <Entity/Entity.h>
namespace Game EntityID EntityManager::ID = 0;
void InitEntityManager(Juliet::NonNullPtr<World> world)
{ {
namespace EntityManager* newManager = Juliet::ArenaPushStruct<EntityManager>(world->WorldArena);
{ world->EntityManager = newManager;
EntityManager Manager;
}
EntityID EntityManager::ID = 0; newManager->Entities.Create(world->WorldArena JULIET_DEBUG_PARAM("Entities"));
void InitEntityManager(Juliet::NonNullPtr<Juliet::Arena> arena) newManager->Arena = Juliet::ArenaAllocate({} JULIET_DEBUG_PARAM("Entity Arena"));
{ }
Manager.Arena = arena.Get();
Manager.Entities.Create(arena JULIET_DEBUG_PARAM("Entities"));
}
void ShutdownEntityManager() void ShutdownEntityManager()
{ {
Manager.Entities.Destroy(); GetEntityManager().Entities.Destroy();
} }
EntityManager& GetEntityManager() EntityManager& GetEntityManager()
{ {
return Manager; Juliet::NonNullPtr entityManager = GetGameState()->World->EntityManager;
} return *entityManager;
}
void RegisterEntity(EntityManager& /*manager*/, Entity* entity) void RegisterEntity(EntityManager& /*manager*/, Entity* entity)
{ {
entity->ID = EntityManager::ID++; entity->ID = EntityManager::ID++;
} }
} // namespace Game
+11 -12
View File
@@ -2,23 +2,22 @@
#include <Core/Common/CoreTypes.h> #include <Core/Common/CoreTypes.h>
#include <Core/Container/Vector.h> #include <Core/Container/Vector.h>
#include <game.h>
namespace Game using EntityID = uint64_t;
struct Entity;
struct EntityManager
{ {
using EntityID = uint64_t;
struct Entity;
struct EntityManager
{
static EntityID ID; static EntityID ID;
Juliet::Arena* Arena; Juliet::Arena* Arena;
// TODO: Should be a pool // TODO: Should be a pool
Juliet::VectorArena<Entity, 1024> Entities; Juliet::VectorArena<Entity, 1024> Entities;
}; };
void InitEntityManager(Juliet::NonNullPtr<Juliet::Arena> arena); void InitEntityManager(Juliet::NonNullPtr<World> world);
void ShutdownEntityManager(); void ShutdownEntityManager();
EntityManager& GetEntityManager(); EntityManager& GetEntityManager();
void RegisterEntity(EntityManager& manager, Entity* entity); void RegisterEntity(EntityManager& manager, Entity* entity);
} // namespace Game
+1
View File
@@ -84,6 +84,7 @@
<ClCompile Include="game.cpp" /> <ClCompile Include="game.cpp" />
<ClInclude Include="Entity\Entity.h" /> <ClInclude Include="Entity\Entity.h" />
<ClInclude Include="Entity\EntityManager.h" /> <ClInclude Include="Entity\EntityManager.h" />
<ClInclude Include="game.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
+1
View File
@@ -15,5 +15,6 @@
<ClInclude Include="Entity\EntityManager.h"> <ClInclude Include="Entity\EntityManager.h">
<Filter>Entity</Filter> <Filter>Entity</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="game.h" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+35 -24
View File
@@ -3,6 +3,8 @@
#undef min #undef min
#undef max #undef max
#include <game.h>
#include <Core/HAL/Filesystem/Filesystem.h> #include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/JulietInit.h> #include <Core/JulietInit.h>
#include <Core/Logging/LogManager.h> #include <Core/Logging/LogManager.h>
@@ -10,6 +12,12 @@
#include <Entity/Entity.h> #include <Entity/Entity.h>
#include <Entity/EntityManager.h> #include <Entity/EntityManager.h>
GameState* gGameState = nullptr;
GameState* GetGameState()
{
return gGameState;
}
// Test code // Test code
namespace Game namespace Game
{ {
@@ -26,30 +34,44 @@ namespace Game
int Health; int Health;
}; };
DEFINE_ENTITY(Rock); DEFINE_ENTITY(Rock);
} // namespace Game } // namespace Game
using namespace Juliet; extern "C" JULIET_API void __cdecl GameShutdown()
extern "C" JULIET_API void GameInit(GameInitParams* params)
{ {
// Example allocation in GameArena printf("Shutting down game...\n");
struct GameState
using namespace Juliet;
using namespace Game;
ShutdownEntityManager();
}
extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_unused]] float deltaTime)
{
using namespace Juliet;
using namespace Game;
gGameState = params->GameState;
if (!gGameState)
{ {
float TotalTime; Arena* gameStateArena = ArenaAllocate({ .ReserveSize = Megabytes(1) } JULIET_DEBUG_PARAM("Game Total Arena"));
int Score; auto* gameState = ArenaPushStruct<GameState>(gameStateArena);
}; gGameState = params->GameState = gameState;
gameState->TotalArena = gameStateArena;
auto* gameState = ArenaPushStruct<GameState>(params->GameArena);
gameState->TotalTime = 0.0f; gameState->TotalTime = 0.0f;
gameState->Score = 0; gameState->Score = 0;
printf("Game Arena Allocated: %p\n", static_cast<void*>(gameState)); printf("Game Arena Allocated: %p\n", static_cast<void*>(gameState));
using namespace Game; // Bootstrap world
auto* worldArena = ArenaAllocate({ .ReserveSize = Megabytes(1) } JULIET_DEBUG_PARAM("World Arena"));
World* world = ArenaPushStruct<World>(worldArena JULIET_DEBUG_PARAM("World"));
gameState->World = world;
gameState->World->WorldArena = worldArena;
// Entity Use case // Entity Use case
InitEntityManager(params->GameArena); InitEntityManager(gameState->World);
auto& manager = GetEntityManager(); auto& manager = GetEntityManager();
Door* door = MakeEntity<Door>(manager, 10.0f, 2.0f); Door* door = MakeEntity<Door>(manager, 10.0f, 2.0f);
door->IsOpened = true; door->IsOpened = true;
@@ -64,18 +86,7 @@ extern "C" JULIET_API void GameInit(GameInitParams* params)
printf("Door is %s\n", door->IsOpened ? "Opened" : "Closed"); printf("Door is %s\n", door->IsOpened ? "Opened" : "Closed");
printf("Rock has %d health points\n", rock->Health); printf("Rock has %d health points\n", rock->Health);
} }
extern "C" JULIET_API void __cdecl GameShutdown()
{
printf("Shutting down game...\n");
using namespace Game;
ShutdownEntityManager();
}
extern "C" JULIET_API void __cdecl GameUpdate([[maybe_unused]] float deltaTime)
{
// printf("Updating game...\n"); // printf("Updating game...\n");
} }
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <Core/Memory/MemoryArena.h>
struct EntityManager;
struct World
{
Juliet::Arena* WorldArena;
EntityManager* EntityManager;
};
struct GameState
{
Juliet::Arena* TotalArena;
World* World;
float TotalTime;
int Score;
};
extern GameState* GetGameState();
-9
View File
@@ -24,23 +24,14 @@ Global
{1720427b-c8ba-3195-f931-e97f6d6125c1}.Release|x64.ActiveCfg = Release|x64 {1720427b-c8ba-3195-f931-e97f6d6125c1}.Release|x64.ActiveCfg = Release|x64
{1720427b-c8ba-3195-f931-e97f6d6125c1}.Release|x64.Build.0 = Release|x64 {1720427b-c8ba-3195-f931-e97f6d6125c1}.Release|x64.Build.0 = Release|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.ActiveCfg = Debug|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.ActiveCfg = Debug|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.Build.0 = Debug|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.ActiveCfg = Profile|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.ActiveCfg = Profile|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.Build.0 = Profile|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.ActiveCfg = Release|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.ActiveCfg = Release|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.Build.0 = Release|x64
{b568a67e-05a1-9907-ff4b-a129119528bd}.Debug|x64.ActiveCfg = Debug|x64 {b568a67e-05a1-9907-ff4b-a129119528bd}.Debug|x64.ActiveCfg = Debug|x64
{b568a67e-05a1-9907-ff4b-a129119528bd}.Debug|x64.Build.0 = Debug|x64
{b568a67e-05a1-9907-ff4b-a129119528bd}.Profile|x64.ActiveCfg = Profile|x64 {b568a67e-05a1-9907-ff4b-a129119528bd}.Profile|x64.ActiveCfg = Profile|x64
{b568a67e-05a1-9907-ff4b-a129119528bd}.Profile|x64.Build.0 = Profile|x64
{b568a67e-05a1-9907-ff4b-a129119528bd}.Release|x64.ActiveCfg = Release|x64 {b568a67e-05a1-9907-ff4b-a129119528bd}.Release|x64.ActiveCfg = Release|x64
{b568a67e-05a1-9907-ff4b-a129119528bd}.Release|x64.Build.0 = Release|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.ActiveCfg = Debug|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.ActiveCfg = Debug|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.Build.0 = Debug|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.ActiveCfg = Profile|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.ActiveCfg = Profile|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.Build.0 = Profile|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.ActiveCfg = Release|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.ActiveCfg = Release|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
-3
View File
@@ -147,10 +147,7 @@
<ClInclude Include="include\Core\Common\CoreUtils.h" /> <ClInclude Include="include\Core\Common\CoreUtils.h" />
<ClInclude Include="include\Core\Common\CRC32.h" /> <ClInclude Include="include\Core\Common\CRC32.h" />
<ClInclude Include="include\Core\Common\EnumUtils.h" /> <ClInclude Include="include\Core\Common\EnumUtils.h" />
<ClInclude Include="include\Core\Common\NonCopyable.h" />
<ClInclude Include="include\Core\Common\NonMovable.h" />
<ClInclude Include="include\Core\Common\NonNullPtr.h" /> <ClInclude Include="include\Core\Common\NonNullPtr.h" />
<ClInclude Include="include\Core\Common\Singleton.h" />
<ClInclude Include="include\Core\Common\String.h" /> <ClInclude Include="include\Core\Common\String.h" />
<ClInclude Include="include\Core\Container\Vector.h" /> <ClInclude Include="include\Core\Container\Vector.h" />
<ClInclude Include="include\Core\HAL\Display\Display.h" /> <ClInclude Include="include\Core\HAL\Display\Display.h" />
-9
View File
@@ -318,18 +318,9 @@
<ClInclude Include="include\Core\Common\EnumUtils.h"> <ClInclude Include="include\Core\Common\EnumUtils.h">
<Filter>include\Core\Common</Filter> <Filter>include\Core\Common</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\Core\Common\NonCopyable.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\NonMovable.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\NonNullPtr.h"> <ClInclude Include="include\Core\Common\NonNullPtr.h">
<Filter>include\Core\Common</Filter> <Filter>include\Core\Common</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\Core\Common\Singleton.h">
<Filter>include\Core\Common</Filter>
</ClInclude>
<ClInclude Include="include\Core\Common\String.h"> <ClInclude Include="include\Core\Common\String.h">
<Filter>include\Core\Common</Filter> <Filter>include\Core\Common</Filter>
</ClInclude> </ClInclude>
+17 -14
View File
@@ -15,7 +15,7 @@ namespace Juliet
class NonNullPtr class NonNullPtr
{ {
public: public:
inline NonNullPtr(Type* ptr) constexpr NonNullPtr(Type* ptr)
: InternalPtr(ptr) : InternalPtr(ptr)
{ {
Assert(ptr, "Tried to initialize a NonNullPtr with a null pointer"); Assert(ptr, "Tried to initialize a NonNullPtr with a null pointer");
@@ -23,14 +23,14 @@ namespace Juliet
template <typename OtherType> template <typename OtherType>
requires NonNullPtr_Convertible<OtherType*, Type*> requires NonNullPtr_Convertible<OtherType*, Type*>
NonNullPtr(const NonNullPtr<OtherType>& otherPtr) constexpr NonNullPtr(const NonNullPtr<OtherType>& otherPtr)
: InternalPtr(otherPtr.Get()) : InternalPtr(otherPtr.Get())
{ {
Assert(InternalPtr, "Fatal Error: Assigned a non null ptr using another NonNullPtr but its was null."); Assert(InternalPtr, "Fatal Error: Assigned a non null ptr using another NonNullPtr but its was null.");
} }
// Assignment // Assignment
NonNullPtr& operator=(Type* ptr) [[nodiscard]] constexpr NonNullPtr& operator=(Type* ptr)
{ {
Assert(ptr, "Tried to assign a null pointer to a NonNullPtr!"); Assert(ptr, "Tried to assign a null pointer to a NonNullPtr!");
InternalPtr = ptr; InternalPtr = ptr;
@@ -39,68 +39,71 @@ namespace Juliet
template <typename OtherType> template <typename OtherType>
requires NonNullPtr_Convertible<OtherType*, Type*> requires NonNullPtr_Convertible<OtherType*, Type*>
NonNullPtr& operator=(const NonNullPtr<OtherType>& otherPtr) [[nodiscard]] constexpr NonNullPtr& operator=(const NonNullPtr<OtherType>& otherPtr)
{ {
InternalPtr = otherPtr.Get(); InternalPtr = otherPtr.Get();
return *this; return *this;
} }
// Accessors // Accessors
operator Type*() const [[nodiscard]] constexpr operator Type*() const
{ {
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null"); Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return InternalPtr; return InternalPtr;
} }
Type* Get() const [[nodiscard]] constexpr Type* Get() const
{ {
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null"); Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return InternalPtr; return InternalPtr;
} }
Type& operator*() const [[nodiscard]] constexpr Type& operator*() const
{ {
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null"); Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return *InternalPtr; return *InternalPtr;
} }
inline Type* operator->() const [[nodiscard]] constexpr Type* operator->() const
{ {
Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null"); Assert(InternalPtr, "NonNullPtr: Internal Pointer is Null");
return InternalPtr; return InternalPtr;
} }
// Comparisons // Comparisons
bool operator==(const NonNullPtr& otherPtr) const { return InternalPtr == otherPtr.InternalPtr; } [[nodiscard]] constexpr bool operator==(const NonNullPtr& otherPtr) const
{
return InternalPtr == otherPtr.InternalPtr;
}
template <typename OtherType> template <typename OtherType>
requires NonNullPtr_SameType<Type, OtherType> requires NonNullPtr_SameType<Type, OtherType>
bool operator==(OtherType* otherRawPtr) const [[nodiscard]] constexpr bool operator==(OtherType* otherRawPtr) const
{ {
return InternalPtr == otherRawPtr; return InternalPtr == otherRawPtr;
} }
template <typename OtherType> template <typename OtherType>
requires NonNullPtr_SameType<Type, OtherType> requires NonNullPtr_SameType<Type, OtherType>
friend bool operator==(OtherType* otherRawPtr, const NonNullPtr& nonNullPtr) [[nodiscard]] constexpr friend bool operator==(OtherType* otherRawPtr, const NonNullPtr& nonNullPtr)
{ {
return otherRawPtr == nonNullPtr.InternalPtr; return otherRawPtr == nonNullPtr.InternalPtr;
} }
// Forbid assigning a nullptr at compile time // Forbid assigning a nullptr at compile time
NonNullPtr(std::nullptr_t) constexpr NonNullPtr(std::nullptr_t)
: InternalPtr(nullptr) : InternalPtr(nullptr)
{ {
static_assert(sizeof(Type) == 0, "Trying to initialize a NonNullPtr with a nullptr value"); static_assert(sizeof(Type) == 0, "Trying to initialize a NonNullPtr with a nullptr value");
} }
NonNullPtr& operator=(std::nullptr_t) [[nodiscard]] constexpr NonNullPtr& operator=(std::nullptr_t)
{ {
static_assert(sizeof(Type) == 0, "Trying to assign a NonNullPtr with a nullptr value"); static_assert(sizeof(Type) == 0, "Trying to assign a NonNullPtr with a nullptr value");
return *this; return *this;
} }
explicit operator bool() const { return true; } [[nodiscard]] constexpr explicit operator bool() const { return InternalPtr != nullptr; }
private: private:
Type* InternalPtr; Type* InternalPtr;
+5
View File
@@ -18,12 +18,16 @@ namespace Juliet
Count = 0; Count = 0;
Capacity = 0; Capacity = 0;
Arena = arena; Arena = arena;
ArenaPosAtCreation = ArenaPos(Arena);
Reserve(ReserveSize); Reserve(ReserveSize);
} }
void Destroy() void Destroy()
{ {
Assert(ArenaPos(Arena) == ArenaPosAtCreation + sizeof(Type) * Capacity);
ArenaPopTo(Arena, ArenaPosAtCreation);
DataFirst = DataLast = Data = nullptr; DataFirst = DataLast = Data = nullptr;
Count = 0; Count = 0;
Capacity = 0; Capacity = 0;
@@ -203,6 +207,7 @@ namespace Juliet
Type* Data = nullptr; Type* Data = nullptr;
size_t Count = 0; size_t Count = 0;
size_t Capacity = 0; size_t Capacity = 0;
index_t ArenaPosAtCreation = 0;
JULIET_DEBUG_ONLY(const char* Name = "VectorArena";) JULIET_DEBUG_ONLY(const char* Name = "VectorArena";)
}; };
static_assert(std::is_standard_layout_v<VectorArena<int>>, static_assert(std::is_standard_layout_v<VectorArena<int>>,
+2 -2
View File
@@ -15,9 +15,9 @@ namespace Juliet
struct Arena; struct Arena;
struct GameInitParams struct GameData
{ {
Arena* GameArena; struct GameState* GameState;
Arena* ScratchArena; Arena* ScratchArena;
}; };
-1
View File
@@ -77,7 +77,6 @@ namespace Juliet
const std::source_location& loc = std::source_location::current()); const std::source_location& loc = std::source_location::current());
JULIET_API void ArenaRelease(NonNullPtr<Arena> arena); JULIET_API void ArenaRelease(NonNullPtr<Arena> arena);
// Raw Push, can be used but templated helpers exists below
// Raw Push, can be used but templated helpers exists below // Raw Push, can be used but templated helpers exists below
[[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align, [[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr<Arena> arena, size_t size, size_t align,
bool shouldBeZeroed JULIET_DEBUG_ONLY(, const char* tag)); bool shouldBeZeroed JULIET_DEBUG_ONLY(, const char* tag));
+5 -3
View File
@@ -11,7 +11,7 @@ namespace Juliet
{ {
void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename) void InitHotReloadCode(HotReloadCode& code, String dllName, String transientDllName, String lockFilename)
{ {
code.Arena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Hot Reload")); code.Arena = ArenaAllocate({ .ReserveSize = Megabytes(1) } JULIET_DEBUG_ONLY(, "Hot Reload"));
// Get the app base path and build the dll path from there. // Get the app base path and build the dll path from there.
String basePath = GetBasePath(); String basePath = GetBasePath();
@@ -25,7 +25,8 @@ namespace Juliet
const size_t dllFullPathLength = const size_t dllFullPathLength =
basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings basePathLength + StringLength(dllName) + 1; // Need +1 because snprintf needs 0 terminated strings
code.DLLFullPath.Data = static_cast<char*>(ArenaPush(code.Arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_ONLY(, "DLL Path"))); code.DLLFullPath.Data =
static_cast<char*>(ArenaPush(code.Arena, dllFullPathLength, alignof(char), true JULIET_DEBUG_ONLY(, "DLL Path")));
int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName)); int writtenSize = snprintf(CStr(code.DLLFullPath), dllFullPathLength, "%s%s", CStr(basePath), CStr(dllName));
if (writtenSize < static_cast<int>(dllFullPathLength) - 1) if (writtenSize < static_cast<int>(dllFullPathLength) - 1)
{ {
@@ -38,7 +39,8 @@ namespace Juliet
// Lock filename path // Lock filename path
const size_t lockPathLength = const size_t lockPathLength =
basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings basePathLength + StringLength(lockFilename) + 1; // Need +1 because snprintf needs 0 terminated strings
code.LockFullPath.Data = static_cast<char*>(ArenaPush(code.Arena, lockPathLength, alignof(char), true JULIET_DEBUG_ONLY(, "Lock File Path"))); code.LockFullPath.Data =
static_cast<char*>(ArenaPush(code.Arena, lockPathLength, alignof(char), true JULIET_DEBUG_ONLY(, "Lock File Path")));
writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename)); writtenSize = snprintf(CStr(code.LockFullPath), lockPathLength, "%s%s", CStr(basePath), CStr(lockFilename));
if (writtenSize < static_cast<int>(lockPathLength) - 1) if (writtenSize < static_cast<int>(lockPathLength) - 1)
{ {
@@ -112,11 +112,10 @@ namespace Juliet
else else
{ {
code.IsValid = false; code.IsValid = false;
break;
} }
} }
} }
// Scratch memory, no free needed
} }
if (!code.IsValid) if (!code.IsValid)
@@ -549,8 +549,8 @@ namespace Juliet::D3D12
driver->D3D12SerializeVersionedRootSignatureFct = nullptr; driver->D3D12SerializeVersionedRootSignatureFct = nullptr;
Assert(ArenaPos(driver->DriverArena) == sizeof(D3D12Driver)); // Verify we didnt forget to release something
ArenaRelease(driver->DriverArena); ArenaRelease(driver->DriverArena);
Free(driver.Get());
} }
bool AttachToWindow(NonNullPtr<GPUDriver> driver, NonNullPtr<Window> window) bool AttachToWindow(NonNullPtr<GPUDriver> driver, NonNullPtr<Window> window)
@@ -698,10 +698,10 @@ namespace Juliet::D3D12
GraphicsDevice* CreateGraphicsDevice(bool enableDebug) GraphicsDevice* CreateGraphicsDevice(bool enableDebug)
{ {
auto driver = static_cast<D3D12Driver*>(Calloc(1, sizeof(D3D12Driver))); Arena* driverArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "D3D12 Driver Arena"));
D3D12Driver* driver = ArenaPushStruct<D3D12Driver>(driverArena JULIET_DEBUG_PARAM("D3D12Driver struct"));
// TODO : Convert everything to arena driver->DriverArena = driverArena;
driver->DriverArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "D3D12 Driver"));
#if JULIET_DEBUG #if JULIET_DEBUG
#ifdef IDXGIINFOQUEUE_SUPPORTED #ifdef IDXGIINFOQUEUE_SUPPORTED
@@ -517,13 +517,21 @@ namespace Juliet::D3D12
// Fix SRV format for Depth Buffers (TypeLess -> Typed) // Fix SRV format for Depth Buffers (TypeLess -> Typed)
if (createInfo.Format == TextureFormat::D32_FLOAT) if (createInfo.Format == TextureFormat::D32_FLOAT)
{
srvDesc.Format = DXGI_FORMAT_R32_FLOAT; srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
}
else if (createInfo.Format == TextureFormat::D16_UNORM) else if (createInfo.Format == TextureFormat::D16_UNORM)
{
srvDesc.Format = DXGI_FORMAT_R16_UNORM; srvDesc.Format = DXGI_FORMAT_R16_UNORM;
}
else if (createInfo.Format == TextureFormat::D24_UNORM_S8_UINT) else if (createInfo.Format == TextureFormat::D24_UNORM_S8_UINT)
{
srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; srvDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
}
else if (createInfo.Format == TextureFormat::D32_FLOAT_S8_UINT) else if (createInfo.Format == TextureFormat::D32_FLOAT_S8_UINT)
{
srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; srvDesc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
}
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+2 -2
View File
@@ -58,7 +58,6 @@ namespace Juliet
{ {
if (GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice(config.EnableDebug)) if (GraphicsDevice* newDevice = chosenFactory->CreateGraphicsDevice(config.EnableDebug))
{ {
newDevice->Name = chosenFactory->Name; newDevice->Name = chosenFactory->Name;
return newDevice; return newDevice;
} }
@@ -371,7 +370,8 @@ namespace Juliet
GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo) GraphicsBuffer* CreateGraphicsBuffer(NonNullPtr<GraphicsDevice> device, const BufferCreateInfo& createInfo)
{ {
return device->CreateGraphicsBuffer(device->Driver, createInfo.Size, createInfo.Stride, createInfo.Usage, createInfo.IsDynamic); return device->CreateGraphicsBuffer(device->Driver, createInfo.Size, createInfo.Stride, createInfo.Usage,
createInfo.IsDynamic);
} }
GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, const TransferBufferCreateInfo& createInfo) GraphicsTransferBuffer* CreateGraphicsTransferBuffer(NonNullPtr<GraphicsDevice> device, const TransferBufferCreateInfo& createInfo)
+5 -16
View File
@@ -87,17 +87,16 @@ using namespace Juliet;
namespace namespace
{ {
using GameInit_t = void (*)(GameInitParams*);
using GameShutdown_t = void (*)(void); using GameShutdown_t = void (*)(void);
using GameUpdate_t = void (*)(float deltaTime); using GameUpdate_t = void (*)(GameData* params, float deltaTime);
struct GameFunctionTable struct GameFunctionTable
{ {
GameInit_t Init = nullptr;
GameShutdown_t Shutdown = nullptr; GameShutdown_t Shutdown = nullptr;
GameUpdate_t Update = nullptr; GameUpdate_t Update = nullptr;
} Game; } Game;
GameData Data;
const char* GameFunctionTable[] = { "GameInit", "GameShutdown", "GameUpdate" }; const char* GameFunctionTable[] = { "GameShutdown", "GameUpdate" };
LightID RedLightID = 0; LightID RedLightID = 0;
LightID BlueLightID = 0; LightID BlueLightID = 0;
@@ -178,13 +177,7 @@ void JulietApplication::Init(NonNullPtr<Arena>)
GameCode.FunctionCount = ArraySize(GameFunctionTable); GameCode.FunctionCount = ArraySize(GameFunctionTable);
GameCode.FunctionNames = GameFunctionTable; GameCode.FunctionNames = GameFunctionTable;
InitHotReloadCode(GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp")); InitHotReloadCode(GameCode, ConstString("Game.dll"), ConstString("Game_Temp.dll"), ConstString("lock.tmp"));
if ((Running = GameCode.IsValid)) Running = GameCode.IsValid;
{
GameInitParams params;
params.GameArena = GameArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Game Arena"));
params.ScratchArena = GameScratchArena = ArenaAllocate({} JULIET_DEBUG_ONLY(, "Scratch Arena"));
Game.Init(&params);
}
} }
} }
@@ -429,8 +422,6 @@ void JulietApplication::Update()
ImGui::End(); ImGui::End();
#endif #endif
ArenaClear(GameScratchArena);
Vector3 redLightPos = { 5.0f, 5.0f, 2.0f }; Vector3 redLightPos = { 5.0f, 5.0f, 2.0f };
Vector3 blueLightPos = { -5.0f, 0.0f, 2.0f }; Vector3 blueLightPos = { -5.0f, 0.0f, 2.0f };
@@ -497,7 +488,7 @@ void JulietApplication::Update()
DebugDisplay_DrawSphere(blueLightPos, 0.5f, { 0.0f, 0.0f, 1.0f, 1.0f }, true); DebugDisplay_DrawSphere(blueLightPos, 0.5f, { 0.0f, 0.0f, 1.0f, 1.0f }, true);
DebugDisplay_DrawSphere(redLightPos, 0.5f, { 1.0f, 0.0f, 0.0f, 1.0f }, true); DebugDisplay_DrawSphere(redLightPos, 0.5f, { 1.0f, 0.0f, 0.0f, 1.0f }, true);
Game.Update(0.0f); Game.Update(&Data, 0.0f);
if (ShouldReloadCode(GameCode)) if (ShouldReloadCode(GameCode))
{ {
@@ -545,8 +536,6 @@ void JulietApplication::Update()
Debug::DebugDrawMemoryArena(); Debug::DebugDrawMemoryArena();
#endif #endif
} }
ArenaClear(GameScratchArena);
} }
void JulietApplication::OnPreRender(CommandList* /*cmd*/) {} void JulietApplication::OnPreRender(CommandList* /*cmd*/) {}
-2
View File
@@ -43,8 +43,6 @@ class JulietApplication : public Juliet::IApplication
Juliet::HotReloadCode GameCode = {}; Juliet::HotReloadCode GameCode = {};
Juliet::GraphicsPipeline* GraphicsPipeline = {}; Juliet::GraphicsPipeline* GraphicsPipeline = {};
Juliet::Texture* DepthBuffer = {}; Juliet::Texture* DepthBuffer = {};
Juliet::Arena* GameArena = nullptr;
Juliet::Arena* GameScratchArena = nullptr;
int AutoCloseFrameCount = -1; int AutoCloseFrameCount = -1;
bool Running = false; bool Running = false;
-6
View File
@@ -22,17 +22,11 @@ Global
{c7df05fe-d5d5-db2a-af36-e7d71d325fda}.Release|x64.ActiveCfg = Release|x64 {c7df05fe-d5d5-db2a-af36-e7d71d325fda}.Release|x64.ActiveCfg = Release|x64
{c7df05fe-d5d5-db2a-af36-e7d71d325fda}.Release|x64.Build.0 = Release|x64 {c7df05fe-d5d5-db2a-af36-e7d71d325fda}.Release|x64.Build.0 = Release|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.ActiveCfg = Debug|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.ActiveCfg = Debug|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.Build.0 = Debug|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.ActiveCfg = Profile|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.ActiveCfg = Profile|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.Build.0 = Profile|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.ActiveCfg = Release|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.ActiveCfg = Release|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.Build.0 = Release|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.ActiveCfg = Debug|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.ActiveCfg = Debug|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.Build.0 = Debug|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.ActiveCfg = Profile|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.ActiveCfg = Profile|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.Build.0 = Profile|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.ActiveCfg = Release|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.ActiveCfg = Release|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
-6
View File
@@ -22,17 +22,11 @@ Global
{767620a7-b286-e7a1-9f79-3e14ce9e5ab1}.Release|x64.ActiveCfg = Release|x64 {767620a7-b286-e7a1-9f79-3e14ce9e5ab1}.Release|x64.ActiveCfg = Release|x64
{767620a7-b286-e7a1-9f79-3e14ce9e5ab1}.Release|x64.Build.0 = Release|x64 {767620a7-b286-e7a1-9f79-3e14ce9e5ab1}.Release|x64.Build.0 = Release|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.ActiveCfg = Debug|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.ActiveCfg = Debug|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Debug|x64.Build.0 = Debug|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.ActiveCfg = Profile|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.ActiveCfg = Profile|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Profile|x64.Build.0 = Profile|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.ActiveCfg = Release|x64 {a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.ActiveCfg = Release|x64
{a93aa30f-8f29-02fe-57e2-cd3626948b68}.Release|x64.Build.0 = Release|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.ActiveCfg = Debug|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.ActiveCfg = Debug|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Debug|x64.Build.0 = Debug|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.ActiveCfg = Profile|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.ActiveCfg = Profile|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Profile|x64.Build.0 = Profile|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.ActiveCfg = Release|x64 {652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.ActiveCfg = Release|x64
{652d3fea-b417-1d5e-9f79-3f32e9604ddc}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+7 -3
View File
@@ -1091,10 +1091,14 @@ static void GenerateSolution(const char* slnName, const char** projectNames, con
const char* configs[] = { "Debug", "Profile", "Release" }; const char* configs[] = { "Debug", "Profile", "Release" };
for (int c = 0; c < 3; c++) { for (int c = 0; c < 3; c++) {
offset += sprintf_s(buf + offset, (4 * 1024 * 1024) - offset, offset += sprintf_s(buf + offset, (4 * 1024 * 1024) - offset,
" {%s}.%s|x64.ActiveCfg = %s|x64\n" " {%s}.%s|x64.ActiveCfg = %s|x64\n",
" {%s}.%s|x64.Build.0 = %s|x64\n",
projectGuids[i], configs[c], configs[c],
projectGuids[i], configs[c], configs[c]); projectGuids[i], configs[c], configs[c]);
if (i == 0) {
offset += sprintf_s(buf + offset, (4 * 1024 * 1024) - offset,
" {%s}.%s|x64.Build.0 = %s|x64\n",
projectGuids[i], configs[c], configs[c]);
}
} }
} }