diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f4ee13e1f..1a779b961 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,3 +1,5 @@ target_sources(SRB2SDL2 PRIVATE + memory.cpp + memory.h static_vec.hpp ) diff --git a/src/core/memory.cpp b/src/core/memory.cpp new file mode 100644 index 000000000..7aebb4768 --- /dev/null +++ b/src/core/memory.cpp @@ -0,0 +1,70 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by Ronald "Eidolon" Kinard +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#include "memory.h" + +#include +#include + +#include "../z_zone.h" + +namespace +{ + +class LinearMemory +{ + size_t size_; + size_t height_; + void* memory_; + +public: + constexpr explicit LinearMemory(size_t size) noexcept; + + void* allocate(size_t size); + void reset() noexcept; +}; + +constexpr LinearMemory::LinearMemory(size_t size) noexcept : size_(size), height_{0}, memory_{nullptr} {} + +void* LinearMemory::allocate(size_t size) +{ + size_t aligned_size = (size + 15) & ~15; + if (height_ + aligned_size > size_) + { + throw std::bad_alloc(); + } + + if (memory_ == nullptr) + { + memory_ = Z_Malloc(size_, PU_STATIC, nullptr); + } + + void* ptr = (void*)((uintptr_t)(memory_) + height_); + height_ += aligned_size; + return ptr; +} + +void LinearMemory::reset() noexcept +{ + height_ = 0; +} + +} // namespace + +static LinearMemory g_frame_memory {4 * 1024 * 1024}; + +void* Z_Frame_Alloc(size_t size) +{ + return g_frame_memory.allocate(size); +} + +void Z_Frame_Reset() +{ + g_frame_memory.reset(); +} diff --git a/src/core/memory.h b/src/core/memory.h new file mode 100644 index 000000000..a1b479b21 --- /dev/null +++ b/src/core/memory.h @@ -0,0 +1,31 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2023 by Ronald "Eidolon" Kinard +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- + +#ifndef __SRB2_CORE_MEMORY_H__ +#define __SRB2_CORE_MEMORY_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cpluspplus + +/// @brief Allocate a block of memory with a lifespan of the current main-thread frame. +/// This function is NOT thread-safe, but the allocated memory may be used across threads. +/// @return a pointer to a block of memory aligned with libc malloc alignment, or null if allocation fails +void* Z_Frame_Alloc(size_t size); + +/// @brief Resets per-frame memory. Not thread safe. +void Z_Frame_Reset(void); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // __SRB2_CORE_MEMORY_H__ diff --git a/src/d_main.cpp b/src/d_main.cpp index 2343a837c..af7b7d9a3 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -72,6 +72,7 @@ #include "filesrch.h" // refreshdirmenu #include "g_input.h" // tutorial mode control scheming #include "m_perfstats.h" +#include "core/memory.h" #include "monocypher/monocypher.h" #include "stun.h" @@ -821,6 +822,8 @@ void D_SRB2Loop(void) precise_t enterprecise = I_GetPreciseTime(); precise_t finishprecise = enterprecise; + Z_Frame_Reset(); + { // Casting the return value of a function is bad practice (apparently) double budget = round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision());