memory bugfix

This commit is contained in:
ouczbs 2024-10-23 15:24:39 +08:00
parent e7683d6e0e
commit 2e8213c1a1
32 changed files with 152 additions and 122 deletions

View File

@ -1,6 +0,0 @@
metadatas:
- guid: a4064a70-89d5-4d8f-b3c3-6486dcf786c0
name: ""
t_hash: engineapi::ShaderProgram
meta: ~
includes: ~

View File

@ -1,6 +0,0 @@
metadatas:
- guid: 020486aa-8987-4bd1-9de9-eeb7ab82c437
name: ""
t_hash: engineapi::ShaderProgram
meta: ~
includes: ~

View File

@ -203,7 +203,7 @@ namespace api {
}
inline ResourceSystem::ResourceSystem()
{
SINGLETON_VAL();
SINGLETON_PTR();
impl = new(GlobalPool()) ResourceSystemImpl(this);
}
inline void api::ResourceSystem::Initialize()

View File

@ -49,7 +49,7 @@ namespace api {
class ResourceSystemImpl;
class ASSET_API ResourceSystem : public ISystem
{
SINGLETON_API_PTR(ResourceSystem)
SINGLETON_IMPL(ResourceSystem)
public:
struct ResourceFileBlock;
template<typename R>

View File

@ -1,4 +1,5 @@
#pragma once
#include "singleton.h"
#include "source_location.h"
#include <cstdint>
#include <stdexcept>
@ -18,39 +19,39 @@ namespace zlog {
m_logger->flush();
}
};
CORE_API zloger& get_zlog();
UNIQUER_INLINE(zloger, zlog, "zlog::zlog")
inline void flush() {
get_zlog().flush();
UNIQUER_VAL(zlog).flush();
}
template <typename... Args>
void info(format fmt, Args &&...args) {
get_zlog().log(level_enum::info, fmt, std::forward<Args>(args)...);
UNIQUER_VAL(zlog).log(level_enum::info, fmt, std::forward<Args>(args)...);
};
template <typename... Args>
void debug(format fmt, Args &&...args) {
get_zlog().log(level_enum::debug, fmt, std::forward<Args>(args)...);
UNIQUER_VAL(zlog).log(level_enum::debug, fmt, std::forward<Args>(args)...);
};
template <typename... Args>
void warn(format fmt, Args &&...args) {
get_zlog().log(level_enum::warn, fmt, std::forward<Args>(args)...);
UNIQUER_VAL(zlog).log(level_enum::warn, fmt, std::forward<Args>(args)...);
};
template <typename... Args>
void error(format fmt, Args &&...args) {
get_zlog().log(level_enum::err, fmt, std::forward<Args>(args)...);
UNIQUER_VAL(zlog).log(level_enum::err, fmt, std::forward<Args>(args)...);
};
template <typename... Args>
void errorf(format fmt, Args &&...args) {
get_zlog().log(level_enum::err, fmt, std::forward<Args>(args)...);
get_zlog().flush();
UNIQUER_VAL(zlog).log(level_enum::err, fmt, std::forward<Args>(args)...);
UNIQUER_VAL(zlog).flush();
};
template <typename... Args>
void fatal(format fmt, Args &&...args) {
get_zlog().log(level_enum::critical, fmt, std::forward<Args>(args)...);
get_zlog().flush();
UNIQUER_VAL(zlog).log(level_enum::critical, fmt, std::forward<Args>(args)...);
UNIQUER_VAL(zlog).flush();
throw std::runtime_error(std::string(fmt.value));
};
inline void fatal(format fmt) {
get_zlog().log(level_enum::critical, fmt);
UNIQUER_VAL(zlog).log(level_enum::critical, fmt);
throw std::runtime_error(std::string(fmt.value));
};
};

View File

@ -1,14 +1,6 @@
#include "os/file_manager.h"
#include "os/file_system.h"
#include <fstream>
#include "zlog.h"
namespace zlog {
zloger& get_zlog()
{
static zloger zlog;
return zlog;
}
}
namespace api {
SINGLETON_DEFINE(FileManager)
class FileManagerImpl
@ -114,7 +106,7 @@ namespace api {
FileManager::FileManager()
{
impl = new(GlobalPool()) FileManagerImpl();
SINGLETON_VAL()
SINGLETON_PTR()
}
FileManager::~FileManager()
{

View File

@ -5,7 +5,6 @@ namespace api {
using refl::Any;
using refl::UClass;
using refl::type_info;
using pmr::string_hash;
struct JsonVTable {
using Read = bool(*)(yyjson_val*, const void*);
using Write = yyjson_mut_val*(*)(yyjson_mut_doc*, const void*);

View File

@ -16,7 +16,7 @@ namespace api {
uint32_t flag{0};
FILE_OP op{ FILE_OP::NONE};
size_t size{0};
pmr::memory_resource* pool;
pmr::memory_resource* pool{nullptr};
std::variant<std::ifstream, std::ofstream, nullptr_t> vfile{nullptr};
public:
using PackagePath::PackagePath;

View File

@ -6,7 +6,7 @@ namespace api
class CORE_API FileManager
{
FileManagerImpl* impl;
SINGLETON_API_PTR(FileManager)
SINGLETON_IMPL(FileManager)
public:
FileManager();
~FileManager();

View File

@ -30,6 +30,7 @@ namespace zlog {
zloger::~zloger() noexcept
{
m_logger->flush();
spdlog::drop_all();
//spdlog::drop_all();
//spdlog::shutdown();
}
}

View File

@ -5,6 +5,9 @@
namespace api {
FileHandle& FileHandle::Open(FILE_OP _op, bool is_binarry)
{
if (!pool) {
pool = FramePool();
}
op = _op;
pmr::string file_path = RealPath();
switch (op)

View File

@ -3,7 +3,7 @@ static_component("core","engine")
files = {"include/module/module.h"}
})
add_includedirs("3rdparty", {public = true})
add_headerfiles("include/**.h","include/**.inl", "impl/*.inl")
add_headerfiles("include/**.h","include/**.inl", "impl/*.inl","3rdparty/**.h")
add_files("src/**.cpp")
add_deps("zlib")
add_packages("spdlog", {public = true})

View File

@ -18,7 +18,7 @@ namespace api {
}
RenderAPI::RenderAPI(RenderContext* ctx) : context(*ctx)
{
SINGLETON_VAL();
SINGLETON_PTR();
}
RenderAPI::~RenderAPI()
{

View File

@ -3,7 +3,7 @@ namespace api {
SINGLETON_DEFINE(Window)
inline Window::Window(CreatePFN createPFN, const Args& args, int width, int height) noexcept : mHeight(height), mWidth(width)
{
SINGLETON_VAL();
SINGLETON_PTR();
uint32_t windowFlags = args.windowFlags | SDL_WINDOW_SHOWN;
windowFlags |= args.resizeable ? SDL_WINDOW_RESIZABLE : 0;
windowFlags |= args.headless ? SDL_WINDOW_HIDDEN : 0;

View File

@ -27,7 +27,7 @@ namespace api {
void Execute(FRenderView& view);
void Clear();
TextureDesc Resource(Name name) {
constexpr size_t surface = pmr::string_hash("surface");
constexpr size_t surface = string_hash("surface");
if (name.Hash() == surface) {
return mSurface;
}

View File

@ -13,7 +13,7 @@ namespace api {
FrameGraph graph;
RenderAPI(RenderContext* ctx);
virtual ~RenderAPI();
SINGLETON_API_PTR(RenderAPI)
SINGLETON_IMPL(RenderAPI)
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());

View File

@ -14,7 +14,7 @@ namespace api {
bool resizeable = true;
bool headless = false;
};
SINGLETON_API_PTR(Window)
SINGLETON_IMPL(Window)
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());

View File

@ -22,7 +22,6 @@ namespace api
}
return spirv_out;
}
using pmr::string_hash;
shaderc_shader_kind GlslToSpirv::GetShaderKind(Name name)
{
switch (name.Hash())

View File

@ -27,12 +27,14 @@ namespace singleapi {
it->second.isAlive = true;
return MemoryInfo{ it->second.data, isAlive };
}
void* KillInstance(size_t hash) {
bool KillInstance(size_t hash) {
bool isAlive = false;
auto it = instances.find(hash);
if (it != instances.end()) {
isAlive = it->second.isAlive;
it->second.isAlive = false;
}
return nullptr;
return isAlive;
}
GlobalManager(pmr::unsynchronized_pool_resource* pool) : instances{pool} {}
~GlobalManager() {}
@ -66,22 +68,39 @@ public:
}
~UniquePtr() {
using namespace singleapi;
if (ms_Singleton) {
ms_Singleton->~T();
}
bool isAlive = false;
if constexpr (hash == 0) {
size_t tHash = typeid(T).hash_code();
ms_Singleton = (T*)GlobalManager::Ptr()->KillInstance(tHash);
isAlive = GlobalManager::Ptr()->KillInstance(tHash);
}
else {
ms_Singleton = (T*)GlobalManager::Ptr()->KillInstance(hash);
isAlive = GlobalManager::Ptr()->KillInstance(hash);
}
if (ms_Singleton && isAlive) {
ms_Singleton->~T();
}
}
static T* Ptr(void) {
return ms_Singleton;
}
};
#define SINGLETON_API_PTR(T) \
constexpr inline size_t string_hash(std::string_view str) noexcept
{
constexpr size_t fnv_offset_basis = 0xcbf29ce484222325;
constexpr size_t fnv_prime = 0x100000001b3;
auto hash = fnv_offset_basis;
for (auto& elem : str)
{
hash *= fnv_prime;
hash ^= elem;
}
hash *= fnv_prime;
hash ^= 0;
return hash;
}
#define SINGLETON_IMPL(T) \
protected:\
static T* ms_Singleton;\
public:\
@ -89,4 +108,9 @@ public:\
#define SINGLETON_DEFINE(T) T* T::ms_Singleton = nullptr;\
T* T::Ptr(){ return ms_Singleton; }
#define SINGLETON_VAL() ms_Singleton = this;
#define SINGLETON_PTR() ms_Singleton = this;
#define UNIQUER_INLINE(cls, name, hash) inline UniquePtr<cls, string_hash(hash)> name##Ptr;
#define UNIQUER_STATIC(cls, name, hash) static UniquePtr<cls, string_hash(hash)> name##Ptr;
#define UNIQUER_VAL(name) (*name##Ptr.Ptr())
#define UNIQUER_PTR(name) name##Ptr.Ptr()

View File

@ -5,7 +5,7 @@ namespace pmr {
using std::pmr::unsynchronized_pool_resource;
using std::pmr::memory_resource;
using std::pmr::vector;
class FrameAllocator : public memory_resource {
class ZLIB_API FrameAllocator : public memory_resource {
private:
char* buffer;
size_t capacity;
@ -21,10 +21,10 @@ namespace pmr {
~FrameAllocator() noexcept;
bool empty() const { return offset == 0; }
void reset() { offset = 0; };
void* try_allocate(size_t bytes, size_t alignment);
protected:
void move_clear() { buffer = nullptr; capacity = 0; offset = 0; };
friend void* try_allocate(FrameAllocator& allocator, size_t bytes, size_t alignment);
private:
void* do_allocate(size_t bytes, size_t alignment)override;
void move_clear() { buffer = nullptr; capacity = 0; offset = 0; };
void do_deallocate(void* p, size_t bytes, size_t alignment) override {};
bool do_is_equal(const memory_resource& other) const noexcept override { return this == &other; };
};

View File

@ -1,4 +1,46 @@
namespace pmr {
inline void* try_allocate(FrameAllocator& allac, size_t bytes, size_t alignment)
{
if (allac.capacity - allac.offset > bytes) {
return allac.do_allocate(bytes, alignment);
}
return nullptr;
}
inline void* FrameAllocator::do_allocate(size_t bytes, size_t alignment)
{
size_t space = capacity - offset;
void* ptr = buffer + offset;
if (std::align(alignment, bytes, ptr, space)) {
offset = capacity - space + bytes;
return ptr;
}
throw std::bad_alloc();
}
inline void* FrameAllocatorPool::allocate(size_t bytes, size_t alignment)
{
for (auto& alllocator : allocators) {
if (auto ptr = try_allocate(alllocator, bytes, alignment)) {
return ptr;
}
}
// 如果所有现有的分配器都没有足够的空间,则创建一个新的分配器
auto& it = allocators.emplace_back(allocatorSize);
return it.allocate(bytes, alignment);
}
inline void FrameAllocatorPool::reset()
{
size_t count = 0;
for (auto& allocator : allocators) {
if (!allocator.empty()) {
allocator.reset();
count++;
}
}
count = count > 0 ? count : 1;
allocators.erase(allocators.begin() + count, allocators.end());
}
#ifdef ZLIB_API_VAL //内存分配和释放必须位于同一模块(DLL)
inline FrameAllocator& FrameAllocator::operator=(FrameAllocator&& o)noexcept
{
std::construct_at(this, std::forward<FrameAllocator&&>(o));
@ -19,44 +61,5 @@ namespace pmr {
if (buffer)
delete[] buffer;
}
inline void* FrameAllocator::try_allocate(size_t bytes, size_t alignment)
{
if (capacity - offset > bytes) {
return do_allocate(bytes, alignment);
}
return nullptr;
}
inline void* FrameAllocator::do_allocate(size_t bytes, size_t alignment)
{
size_t space = capacity - offset;
void* ptr = buffer + offset;
if (std::align(alignment, bytes, ptr, space)) {
offset = capacity - space + bytes;
return ptr;
}
throw std::bad_alloc();
}
inline void* FrameAllocatorPool::allocate(size_t bytes, size_t alignment)
{
for (auto& alllocator : allocators) {
if (auto ptr = alllocator.try_allocate(bytes, alignment)) {
return ptr;
}
}
// 如果所有现有的分配器都没有足够的空间,则创建一个新的分配器
auto& it = allocators.emplace_back(allocatorSize);
return it.allocate(bytes, alignment);
}
inline void FrameAllocatorPool::reset()
{
size_t count = 0;
for (auto& allocator : allocators) {
if (!allocator.empty()) {
allocator.reset();
count++;
}
}
count = count > 0 ? count : 1;
allocators.erase(allocators.begin() + count, allocators.end());
}
#endif
};

View File

@ -1,59 +1,68 @@
#pragma once
#include "singleton.h"
namespace pmr {
constexpr inline size_t string_hash(std::string_view str) noexcept
{
constexpr size_t fnv_offset_basis = 0xcbf29ce484222325;
constexpr size_t fnv_prime = 0x100000001b3;
auto hash = fnv_offset_basis;
for (auto& elem : str)
{
hash *= fnv_prime;
hash ^= elem;
}
hash *= fnv_prime;
hash ^= 0;
return hash;
}
}
//全局生命周期,不回收内存
inline UniquePtr<pmr::FrameAllocatorPool, pmr::string_hash("pmr::globalpool")> GlobalPoolPtr;
//局部生命周期,每帧回收内存
inline UniquePtr<pmr::FrameAllocatorPool, pmr::string_hash("pmr::framepool")> FramePoolPtr;
inline pmr::FrameAllocatorPool* GlobalPool() {
return GlobalPoolPtr.Ptr();
}
inline pmr::FrameAllocatorPool* FramePool() {
return FramePoolPtr.Ptr();
}
ZLIB_API extern pmr::FrameAllocatorPool* GlobalPool();
ZLIB_API extern pmr::FrameAllocatorPool* FramePool();
extern void* operator new(std::size_t size);
extern void operator delete(void* ptr) noexcept;
extern void operator delete[](void* ptr) noexcept;
extern void* operator new(std::size_t size, std::align_val_t align);
#ifdef ZLIB_API_VAL
ZLIB_API inline pmr::FrameAllocatorPool* GlobalPool() {
static pmr::FrameAllocatorPool* globalPool = new pmr::FrameAllocatorPool();
return globalPool;
}
ZLIB_API inline pmr::FrameAllocatorPool* FramePool() {
static pmr::FrameAllocatorPool* framePool = new pmr::FrameAllocatorPool();
return framePool;
}
struct MemDetail {
int count{ 0 };
int new_count{ 0 };
int del_count{ 0 };
};
thread_local pmr::unsynchronized_pool_resource MemPool;
struct MemPoolWrap {
char pMemory[sizeof(pmr::unsynchronized_pool_resource)];
uint32_t id;
MemPoolWrap() {
static uint32_t sThreadId = 0;
id = sThreadId++;
std::construct_at((pmr::unsynchronized_pool_resource*)&pMemory);
}
~MemPoolWrap() {
auto pool = (pmr::unsynchronized_pool_resource*)&pMemory;
if (id) {
pool->~unsynchronized_pool_resource();
}
}
pmr::unsynchronized_pool_resource* operator->() {
return (pmr::unsynchronized_pool_resource*)&pMemory;
}
};
thread_local MemPoolWrap MemPool;
thread_local MemDetail detail;
void* operator new(std::size_t size) {
std::size_t alignment = alignof(std::max_align_t);
detail.count++;
detail.new_count++;
return MemPool.allocate(size, alignment);
return MemPool->allocate(size, alignment);
}
// 默认对齐方式 delete
void operator delete(void* ptr) noexcept {
detail.count--;
detail.del_count++;
MemPool.deallocate(ptr, 0);
MemPool->deallocate(ptr, 0);
}
// 默认对齐方式 delete
void operator delete[](void* ptr) noexcept {
detail.count--;
detail.del_count++;
MemPool->deallocate(ptr, 0);
}
// 自定义对齐 align
void* operator new(std::size_t size, std::align_val_t align) {
std::size_t alignment = static_cast<std::size_t>(align);
return MemPool.allocate(size, alignment);
return MemPool->allocate(size, alignment);
}
#endif //

View File

@ -1,8 +1,8 @@
namespace pmr {
using NameTable_t = table<size_t,const string>;
inline NameTable_t& TableRef() {
static UniquePtr<NameTable_t, string_hash("pmr::nametable")> Table;
return *Table.Ptr();
UNIQUER_STATIC(NameTable_t, Table, "pmr::nametable")
return UNIQUER_VAL(Table);
}
struct NameTable {
static const string& Find(size_t id);

View File

@ -6,7 +6,6 @@ namespace refl {
using pmr::Name;
using pmr::CName;
using pmr::FName;
using pmr::string_hash;
using pmr::table;
using std::span;
using Offset = uint32_t;

View File

@ -4,7 +4,6 @@ namespace gen {
using refl::real_type_t;
using pmr::CName;
using pmr::FName;
using pmr::string_hash;
template<typename T, size_t hash>
struct MetaImpl {};
template<typename T>

View File

@ -40,9 +40,10 @@ namespace refl {
}
};
inline UniquePtr<table<Name, const UClass*>, string_hash("refl::ClassTable")> ClassTablePtr;
using __tClassTable = table<Name, const UClass*>;
UNIQUER_INLINE(__tClassTable, ClassTable, "refl::ClassTable")
inline const UClass* find_info(Name name) {
auto& ClassTable = *ClassTablePtr.Ptr();
auto& ClassTable = UNIQUER_VAL(ClassTable);
if (auto it = ClassTable.find(name); it != ClassTable.end()) {
return it->second;
}
@ -66,7 +67,7 @@ namespace refl {
else {
cls = new(GlobalPool()) UClass_Auto<T>{};
}
auto& ClassTable = *ClassTablePtr.Ptr();
auto& ClassTable = UNIQUER_VAL(ClassTable);
ClassTable[name.View()] = cls;
return cls;
}

View File

@ -23,6 +23,9 @@
#define CONCATENATE_IMPL(arg1, arg2) arg1##arg2
#define MY_UNIQUE_NAME(base) CONCATENATE(base, __LINE__)
#define TOSTRING_IMPL(X) #X
#define TOSTRING(X) TOSTRING_IMPL(X)
#define USING_CTOR_NAME MY_UNIQUE_NAME(__Ctor)
#define USING_FUNC_NAME MY_UNIQUE_NAME(__Func)

View File

@ -23,6 +23,7 @@ function static_component(name, owner, opt)
end
function shared_module(name, owner, opt)
target(name)
add_defines(string.upper(name).."_ROOT="..os.curdir():gsub("\\", "\\\\"),{public = false})
set_kind("shared")
set_group("Engine/"..owner.."__dyn")
add_rules("engine.api")
@ -44,6 +45,7 @@ function add_dependency(...)
end
function game_instance(name, opt)
target(name)
set_rundir(".")
set_kind("binary")
set_group("Games")
add_rules("engine.api")

View File

@ -1,9 +1,15 @@
#include "api.h"
#include "os/file_manager.h"
class ENGINE_API EngineModule : public api::IDynamicModule
{
public:
void OnLoad(int argc, char** argv) override {};
void OnUnload() override {};
void OnLoad(int argc, char** argv) override {
#ifdef ENGINE_ROOT
api::FileManager::Ptr()->Mount("engine", TOSTRING(ENGINE_ROOT));
#endif
};
void OnUnload() override {
};
void InitMetaData(void) override {
mInfo.dependencies = {
{"core", "1.0.1", "static" },

View File

@ -6,6 +6,7 @@ target("editor")
add_includedirs("include/editor")
add_files("src/editor/*.cpp")
target("engine")
add_defines("ENGINE_ROOT="..os.curdir():gsub("\\", "\\\\"),{public = false})
add_includedirs("include", {public = true})
set_kind("shared")
set_group("Engine")

View File

@ -10,6 +10,7 @@ int main(int argc,char* argv[]) {
auto ptr = api::ModuleManager::Ptr();
ptr->MakeGraph("zworld", true, argc, argv);
ptr->MainLoop();
ptr->DestroyGraph();
SDL_Quit();
return 0;
}

View File

@ -1,6 +1,5 @@
game_instance("zworld", "src/zworld.h")
target("zworld")
set_rundir(".")
add_files("src/*.cpp")
add_headerfiles("src/*.h")
add_dependency("engine", "editor", "vulkan", {public = true})