From f5e2424f0f01aa626dc98bafc6a3f287e26669df Mon Sep 17 00:00:00 2001 From: ouczbs Date: Thu, 1 Aug 2024 15:38:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E7=8E=B0=E4=BA=86=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=8C=E5=85=88=E5=A4=87=E4=BB=BD=E4=B8=80?= =?UTF-8?q?=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- engine/include/editor/api.h | 2 + engine/include/engine/api.h | 2 + .../engine/asset/include/asset/asset.h | 21 +++ .../engine/asset/include/asset/asset_loader.h | 11 ++ .../engine/asset/include/asset/module.h | 11 ++ .../engine/asset/include/asset/res/guid.h | 78 ++++++++++ .../engine/asset/include/asset/res/guid.inl | 15 ++ .../asset/include/asset/res/meta_bundle.h | 42 +++++ .../asset/include/asset/res/meta_bundle.inl | 34 ++++ .../asset/include/asset/res/resource_bundle.h | 24 +++ .../include/asset/res/resource_bundle.inl | 47 ++++++ .../asset/include/asset/res/resource_config.h | 46 ++++++ .../asset/include/asset/res/resource_handle.h | 34 ++++ .../include/asset/res/resource_handle.inl | 43 ++++++ .../engine/asset/include/asset/res/type.h | 18 +++ .../asset/include/asset/resource_system.h | 130 ++++++++++++++++ .../asset/include/asset/resource_system.inl | 145 ++++++++++++++++++ engine/modules/engine/asset/src/asset.cpp | 13 ++ .../modules/engine/asset/src/asset_loader.cpp | 25 +++ engine/modules/engine/asset/src/module.cpp | 14 ++ .../engine/asset/src/res/meta_bundle.cpp | 23 +++ .../engine/asset/src/res/resource_handle.cpp | 17 ++ .../engine/asset/src/resource_system.cpp | 137 +++++++++++++++++ engine/modules/engine/asset/xmake.lua | 5 +- .../engine/core/include/3rdparty/singleton.h | 1 + .../engine/core/include/archive/json.h | 8 +- .../core/include/archive/json/serialize.h | 14 +- .../core/include/archive/json/serialize.inl | 32 ++-- .../engine/core/include/module/module.h | 35 +++-- .../engine/core/include/module/module.inl | 21 ++- .../core/include/module/module_manager.h | 16 +- .../engine/core/include/os/file_handle.h | 61 ++++++++ .../engine/core/include/os/file_handle.inl | 39 +++++ .../engine/core/include/os/file_manager.h | 23 +-- .../engine/core/include/os/package_path.h | 12 +- .../modules/engine/core/src/module/module.cpp | 41 +++++ .../engine/core/src/module/module_manager.cpp | 58 +++++-- .../engine/core/src/os/file_handle.cpp | 75 +++++++++ .../engine/core/src/os/file_manager.cpp | 6 +- .../engine/core/src/os/package_path.cpp | 2 +- .../engine/zlib/include/meta/comparable.h | 18 +++ .../engine/zlib/include/meta/comparable.inl | 43 ++++++ .../modules/engine/zlib/include/meta/tuple.h | 43 ++++++ .../engine/zlib/include/meta/tuple.inl | 30 ++++ .../engine/zlib/include/meta/variant.h | 27 ++++ .../engine/zlib/include/meta/variant.inl | 64 ++++++++ .../engine/zlib/include/pmr/frame_allocator.h | 33 ++-- engine/modules/engine/zlib/include/pmr/name.h | 6 + .../modules/engine/zlib/include/pmr/name.inl | 2 +- .../engine/zlib/include/refl/detail/any.h | 2 + .../engine/zlib/include/refl/detail/any.inl | 5 + .../engine/zlib/include/refl/detail/uclass.h | 72 +++++++-- .../zlib/include/refl/detail/uclass.inl | 11 +- engine/modules/render/vulkan/xmake.lua | 2 +- engine/modules/xmake.lua | 8 +- engine/src/editor/api.cpp | 2 + engine/src/engine/api.cpp | 14 ++ engine/tools/make_plugin/src/main.cpp | 2 +- engine/xmake.lua | 13 +- engine/xmake/rule_tool/xmake.lua | 10 +- game/zworld/editor/main.cpp | 5 +- 61 files changed, 1675 insertions(+), 118 deletions(-) create mode 100644 engine/include/editor/api.h create mode 100644 engine/include/engine/api.h create mode 100644 engine/modules/engine/asset/include/asset/asset_loader.h create mode 100644 engine/modules/engine/asset/include/asset/module.h create mode 100644 engine/modules/engine/asset/include/asset/res/guid.h create mode 100644 engine/modules/engine/asset/include/asset/res/guid.inl create mode 100644 engine/modules/engine/asset/include/asset/res/meta_bundle.h create mode 100644 engine/modules/engine/asset/include/asset/res/meta_bundle.inl create mode 100644 engine/modules/engine/asset/include/asset/res/resource_bundle.h create mode 100644 engine/modules/engine/asset/include/asset/res/resource_bundle.inl create mode 100644 engine/modules/engine/asset/include/asset/res/resource_config.h create mode 100644 engine/modules/engine/asset/include/asset/res/resource_handle.h create mode 100644 engine/modules/engine/asset/include/asset/res/resource_handle.inl create mode 100644 engine/modules/engine/asset/include/asset/res/type.h create mode 100644 engine/modules/engine/asset/include/asset/resource_system.h create mode 100644 engine/modules/engine/asset/include/asset/resource_system.inl create mode 100644 engine/modules/engine/asset/src/asset_loader.cpp create mode 100644 engine/modules/engine/asset/src/module.cpp create mode 100644 engine/modules/engine/asset/src/res/meta_bundle.cpp create mode 100644 engine/modules/engine/asset/src/res/resource_handle.cpp create mode 100644 engine/modules/engine/asset/src/resource_system.cpp create mode 100644 engine/modules/engine/core/include/os/file_handle.h create mode 100644 engine/modules/engine/core/include/os/file_handle.inl create mode 100644 engine/modules/engine/core/src/os/file_handle.cpp create mode 100644 engine/modules/engine/zlib/include/meta/comparable.h create mode 100644 engine/modules/engine/zlib/include/meta/comparable.inl create mode 100644 engine/modules/engine/zlib/include/meta/tuple.h create mode 100644 engine/modules/engine/zlib/include/meta/tuple.inl create mode 100644 engine/modules/engine/zlib/include/meta/variant.h create mode 100644 engine/modules/engine/zlib/include/meta/variant.inl create mode 100644 engine/src/editor/api.cpp create mode 100644 engine/src/engine/api.cpp diff --git a/engine/include/editor/api.h b/engine/include/editor/api.h new file mode 100644 index 0000000..ccba8af --- /dev/null +++ b/engine/include/editor/api.h @@ -0,0 +1,2 @@ +#pragma once +EDITOR_API extern int editor_v; \ No newline at end of file diff --git a/engine/include/engine/api.h b/engine/include/engine/api.h new file mode 100644 index 0000000..dff51e5 --- /dev/null +++ b/engine/include/engine/api.h @@ -0,0 +1,2 @@ +#include "asset/module.h" +#include "module/module_manager.h" \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/asset.h b/engine/modules/engine/asset/include/asset/asset.h index e69de29..b6ea531 100644 --- a/engine/modules/engine/asset/include/asset/asset.h +++ b/engine/modules/engine/asset/include/asset/asset.h @@ -0,0 +1,21 @@ +#pragma once +#include "resource_system.h" +namespace api { + class Asset : public Resource { + public: + using Base = Resource; + const refl::UClass* meta; + Asset(const refl::UClass* meta): Base(), meta(meta){} + refl::Any Meta() { + return refl::Any{ this, meta }; + } + }; + template<> + inline void MetaBundle::Add(RscHandle h) + { + if (h) + { + metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), refl::type_name().View(), h->Meta()}); + } + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/asset_loader.h b/engine/modules/engine/asset/include/asset/asset_loader.h new file mode 100644 index 0000000..f7b5fcc --- /dev/null +++ b/engine/modules/engine/asset/include/asset/asset_loader.h @@ -0,0 +1,11 @@ +#pragma once +#include "asset.h" +#include "os/package_path.h" +namespace api { + class AssetLoader :public IFileLoader{ + public: + static void Init(); + ResourceBundle LoadFile(PackagePath path, const MetaBundle& meta) override; + void SaveFile(PackagePath path, const ResourceBundle& bundle) override; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/module.h b/engine/modules/engine/asset/include/asset/module.h new file mode 100644 index 0000000..30d2e2f --- /dev/null +++ b/engine/modules/engine/asset/include/asset/module.h @@ -0,0 +1,11 @@ +#include "module/module_manager.h" +namespace api { + class AssetModule : public IStaticModule + { + public: + void OnLoad(int argc, char** argv) override; + void OnUnload() override; + void InitMetaData(void) override {}; + }; + IMPLEMENT_STATIC_MODULE(AssetModule, asset) +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/guid.h b/engine/modules/engine/asset/include/asset/res/guid.h new file mode 100644 index 0000000..98d2a88 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/guid.h @@ -0,0 +1,78 @@ +#pragma once +#include "refl/pch.h" +#include +#include +namespace api +{ + using pmr::Name; + using std::string_view; + using std::span; + struct Guid + { + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; + + Guid() noexcept + : Data1{ 0 }, Data2{ 0 }, Data3{ 0 }, Data4{ 0,0,0,0,0,0,0,0 } + {} + + USING_OVERLOAD_CTOR(Guid, string_view) + UFUNCTION({}, ref = USING_CTOR_NAME) + Guid(string_view str) noexcept + : Guid{} + { + sscanf_s(str.data(), + "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + &Data1, &Data2, &Data3, + &Data4[0], &Data4[1], &Data4[2], &Data4[3], + &Data4[4], &Data4[5], &Data4[6], &Data4[7]); + + } + constexpr Guid(unsigned int a, unsigned short b, unsigned short c, unsigned long long d) + : Data1{ a } + , Data2{ b } + , Data3{ c } + , Data4{ + (unsigned char)(d >> 56 & 0xFF) + , (unsigned char)(d >> 48 & 0xFF) + , (unsigned char)(d >> 40 & 0xFF) + , (unsigned char)(d >> 32 & 0xFF) + , (unsigned char)(d >> 24 & 0xFF) + , (unsigned char)(d >> 16 & 0xFF) + , (unsigned char)(d >> 8 & 0xFF) + , (unsigned char)(d >> 0 & 0xFF) + } + {}; + UFUNCTION({}) + std::string ToString()const { + char guid_cstr[39]; + snprintf(guid_cstr, sizeof(guid_cstr), + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + Data1, Data2, Data3, + Data4[0], Data4[1], Data4[2], Data4[3], + Data4[4], Data4[5], Data4[6], Data4[7]); + return std::string{ guid_cstr }; + } + public: + auto operator<=>(const Guid&) const noexcept = default; + operator bool() const noexcept + { + return *reinterpret_cast(this) != GUID_NULL; + } + operator std::string() const + { + return ToString(); + } + public: + UFUNCTION({}) + static Guid Make() + { + Guid guid; + const auto res = CoCreateGuid((GUID*)&guid); + return guid; + } + }; +} +#include "guid.inl" \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/guid.inl b/engine/modules/engine/asset/include/asset/res/guid.inl new file mode 100644 index 0000000..3947840 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/guid.inl @@ -0,0 +1,15 @@ +#pragma once +namespace std +{ + template<> struct hash + { + size_t operator()(const api::Guid& guid) const noexcept + { + const size_t* p = reinterpret_cast(&guid); + size_t seed = 0; + ::pmr::hash_combine(seed, p[0]); + ::pmr::hash_combine(seed, p[1]); + return seed; + } + }; +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/meta_bundle.h b/engine/modules/engine/asset/include/asset/res/meta_bundle.h new file mode 100644 index 0000000..1970c6c --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/meta_bundle.h @@ -0,0 +1,42 @@ +#pragma once +#include "type.h" +#include "guid.h" +#include "resource_bundle.h" +namespace api +{ + struct SerializedMeta + { + UPROPERTY({}) + Guid guid; + UPROPERTY({}) + Name name; + UPROPERTY({}) + Name t_hash; + UPROPERTY({}) + refl::Any meta; + bool operator==(const SerializedMeta& other)const{ + return guid == other.guid && name == other.name && t_hash == other.t_hash; + } + }; + struct ResourceBundle; + struct MetaBundle + { + UPROPERTY({}) + vector metadatas; + UPROPERTY({}) + vector includes; + MetaBundle() = default; + + const SerializedMeta* FetchMeta(const Guid& guid) const; + template + const SerializedMeta* FetchMeta() const; + template + const SerializedMeta* FetchMeta(string_view asset_name) const; + template + void Add(RscHandle); + bool operator==(const MetaBundle& other)const; + bool operator!=(const MetaBundle& other)const; + }; +} +#include "meta_bundle.inl" +#include "meta_bundle_gen.inl" \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/meta_bundle.inl b/engine/modules/engine/asset/include/asset/res/meta_bundle.inl new file mode 100644 index 0000000..7be590d --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/meta_bundle.inl @@ -0,0 +1,34 @@ +#pragma once +namespace api +{ + template + inline const SerializedMeta* MetaBundle::FetchMeta() const + { + string_view name = type_name().View(); + for (auto& elem : metadatas) + { + if (elem.t_hash == name) + return &elem; + } + return nullptr; + } + template + inline const SerializedMeta* MetaBundle::FetchMeta(string_view asset_name) const + { + string_view name = type_name().View(); + for (auto& elem : metadatas) + { + if (elem.t_hash == name && asset_name == elem.name) + return &elem; + } + return nullptr; + } + template + void MetaBundle::Add(RscHandle h) + { + if (h) + { + metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), type_name().View() }); + } + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/resource_bundle.h b/engine/modules/engine/asset/include/asset/res/resource_bundle.h new file mode 100644 index 0000000..fb452ca --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/resource_bundle.h @@ -0,0 +1,24 @@ +#pragma once +#include "resource_handle.h" +namespace api +{ + struct GenericResourceHandle; + struct ResourceBundle + { + ResourceBundle() = default; + template // conversion from single resource + ResourceBundle(const RscHandle& handle); + operator bool(); + // will reshuffle vector and invalidate span, but you shouldn't be accessing vector directly anyway so this is ok + template void Add(RscHandle handle); + template RscHandle Get() const; // get a resource from the bundle + span GetAll() const; // gets absolutely all resources + template span GetAll() const; // get all resources of one type + private: + struct sub_array { short index = 0, count = 0; }; + + vector handles; // always sorted so that we can simply span + array subarrays; + }; +} +#include "resource_bundle.inl" \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/resource_bundle.inl b/engine/modules/engine/asset/include/asset/res/resource_bundle.inl new file mode 100644 index 0000000..d556c67 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/resource_bundle.inl @@ -0,0 +1,47 @@ +#include "resource_bundle.h" +#pragma once +namespace api +{ + template + inline ResourceBundle::ResourceBundle(const RscHandle& handle) + { + Add(handle); + } + template + inline void ResourceBundle::Add(RscHandle handle) + { + auto& sub_arr = subarrays[ResourceID]; + auto new_ind = sub_arr.index + sub_arr.count++; + + + // make space for new resource + handles.emplace_back(); + std::move_backward(handles.data() + new_ind, handles.data() + handles.size() - 1, handles.data() + handles.size()); + + // assign new resource + handles[new_ind] = handle; + + // push back all subsequent resources + for (auto& elem : span{ &sub_arr + 1, subarrays.data() + subarrays.size() }) + ++elem.index; + } + inline ResourceBundle::operator bool() + { + return !handles.empty(); + } + inline span ResourceBundle::GetAll() const + { + return span(handles); + } + + template + inline RscHandle ResourceBundle::Get() const + { + auto& subarray = subarrays[ResourceID]; + return subarray.count > 0 ? handles[subarray.index].template AsHandle() : RscHandle(); + } + template span ResourceBundle::GetAll() const { + auto& subarray = subarrays[ResourceID]; + return span{handles.data() + subarray.index, handles.data() + subarray.index + subarray.count}; + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/resource_config.h b/engine/modules/engine/asset/include/asset/res/resource_config.h new file mode 100644 index 0000000..a9c26ba --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/resource_config.h @@ -0,0 +1,46 @@ +#pragma once +#include "type.h" +namespace api { + class Guid; + template + struct RscHandle; + template + class Resource + { + public: + using BaseResource = Res; + Guid GetGuid()const; + RscHandle GetHandle() const { return mHandle; } + Resource() = default; + + pmr::Name Name() const { return mName; } + void Name(pmr::Name n) { mName = n; } + private: + RscHandle mHandle; + pmr::Name mName; + friend class RscHandle; + friend class ResourceSystem; + }; + using Resources = std::tuple< + class ShaderProgram + , class Model + , class Asset + >; + template + concept is_resource_v = requires { typename Resource::BaseResource; }; + + template + struct ResourceID_impl { + static constexpr auto value() { return index_in_tuple_v; } + }; + + template + struct ResourceID_impl>> { + static constexpr auto value() { return index_in_tuple_v; } + }; + + template + constexpr auto ResourceID = ResourceID_impl::value(); + + constexpr auto ResourceCount = std::tuple_size_v; +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/resource_handle.h b/engine/modules/engine/asset/include/asset/res/resource_handle.h new file mode 100644 index 0000000..989d2c6 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/resource_handle.h @@ -0,0 +1,34 @@ +#pragma once +#include "guid.h" +#include "resource_config.h" + +namespace api +{ + struct RscHandleBase { + UPROPERTY({}) + Guid guid; + void* res{nullptr}; + }; + template + struct RscHandle : public RscHandleBase + { + constexpr size_t RscID()const { return ResourceID; } + constexpr RscHandle() noexcept = default; + template + constexpr RscHandle(const RscHandle& other) noexcept : RscHandleBase(other.guid, other.res) {}; + constexpr RscHandle(const Guid& guid, Res* res) noexcept : RscHandleBase(guid, res) {} + void Init(); + void Clear() { res = nullptr; }; + Res* Ptr() { + return (Res*)res; + } + Res* operator->() { if (!res && guid) Init(); return (Res*)res; } + Res& operator*() { if (!res && guid) Init(); return *(Res*)res; } + operator bool() { if (!res && guid) Init(); return res; } + Res* operator->() const { return (Res*)res; } + Res& operator*()const { return *(Res*)res; } + operator bool() const { return res; } + }; +} +#include "resource_handle.inl" +#include "resource_handle_gen.inl" \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/resource_handle.inl b/engine/modules/engine/asset/include/asset/res/resource_handle.inl new file mode 100644 index 0000000..b775e86 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/resource_handle.inl @@ -0,0 +1,43 @@ +#pragma once +namespace api{ + template + inline Guid Resource::GetGuid() const + { + return GetHandle().guid; + } + struct GenericResourceHandle + : variant_wrap_t, RscHandle> + { + private: + using Base = variant_wrap_t, RscHandle>; + public: + using Base::Base; + using Base::operator=; + template + GenericResourceHandle(RscHandle handle) : Base(RscHandle{handle}) {} + GenericResourceHandle(string_view type_name, Guid guid); + template RscHandle AsHandle() const { + return std::get>(*this); + } + Guid guid() const; + size_t resource_id() const; + }; +} +// hashtable support +namespace std +{ + template + struct hash > + { + size_t operator()(const api::RscHandle& res) const noexcept + { + return std::hash()(res.guid); + } + }; +} +namespace refl::detail { + template + struct real_type> { + using type = api::RscHandleBase; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/res/type.h b/engine/modules/engine/asset/include/asset/res/type.h new file mode 100644 index 0000000..29749cc --- /dev/null +++ b/engine/modules/engine/asset/include/asset/res/type.h @@ -0,0 +1,18 @@ + +#pragma once +#include "pmr/name.h" +#include "meta/variant.h" +#include "meta/tuple.h" +#include "meta/comparable.h" +#include +#include +namespace api { + using namespace meta; + using std::vector; + using std::array; + using pmr::table; + template + using opt = std::optional; + template + using sfinae = std::enable_if_t; +} \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/resource_system.h b/engine/modules/engine/asset/include/asset/resource_system.h new file mode 100644 index 0000000..0967b66 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/resource_system.h @@ -0,0 +1,130 @@ +#pragma once +#include "module/module.h" +#include "res/resource_config.h" +#include "res/resource_bundle.h" +#include "res/meta_bundle.h" +#include "os/package_path.h" +#include "meta/result.h" +#include +#include +namespace api { + using std::array; + using std::shared_ptr; + class IFileLoader; + enum class ResourceLoadError : char + { + ExtensionNotRegistered, + FileDoesNotExist, + FailedToLoadResource, + }; + struct ResourceFileFlag{ + enum Value : uint32_t { + File_Default = 0, + File_Dirty = 1 << 0, + File_Meta_Dirty = 1 << 1, + File_Loaded = 1 << 2, + }; + Value val{ File_Default }; + // 构造函数和操作符重载,使类实例像整数一样使用 + ResourceFileFlag(Value v = File_Default) : val(v) {} + operator uint32_t() const { return val; } + ResourceFileFlag& operator=(Value v) { + val = v; + return *this; + } + }; + template + using LoadResult = result; + class ResourceSystem : public ISystem + { + public: + struct ResourceFileBlock; + template + struct ResourceBlock; + template + using ResourceStorage = table>; + using GenericPtr = shared_ptr; + private: + uint32_t mFileFlag; + + array mResourceTable; + table mResourceFile; + table mFileLoader; + table> mFileFlags; + table mFileBlock; + vector mDirtyBlock; + public: + ResourceSystem(); + void Initialize() override; + void Finalize() override; + public: + template + Res* Get(const RscHandle& handle,bool sync = true); + + template + auto& GetTable() { + return *reinterpret_cast*> (mResourceTable[ResourceID].get()); + } + template + ResourceBlock* GetBlock(const RscHandle& handle); + ResourceFileBlock& GetFileBlock(PackagePath path); + FileBlock* GetResourceFile(const Guid& guid); + template + [[nodiscard]] RscHandle LoadFromMeta(const Guid& ,const SerializedMeta& meta); + template + [[nodiscard]] RscHandle LoadEmplaceResource(Args&& ... args) { + return LoadEmplaceResource(Guid::Make(), args...); + }; + template + [[nodiscard]] RscHandle LoadEmplaceResource(Guid, Args&& ... args); + + IFileLoader* GetLoader(Name extension); + template + FLoader& RegisterLoader(Name ext, Args&& ... args); + + template + RscHandle Load(PackagePath path, bool reload_resource = true); + ResourceBundle& Load(PackagePath path, bool reload_resource = true, int deep = 0); + MetaBundle GetMeta(PackagePath path); + MetaBundle GetVisitMeta(const ResourceBundle& bundle); + void SaveMeta(PackagePath path, const MetaBundle& bundle); + void SaveDirtyFile(); + void SaveFile(PackagePath path, const ResourceBundle& bundle); + void LoadFileFlags(); + void SaveFileFlags(); + void LoadResourceFile(); + void SaveResourceFile(); + uint32_t GetFileFlag(Name name); + void SetFileFlag(Name name, uint32_t flag); + }; + struct ResourceSystem::ResourceFileBlock + { + ResourceBundle bundle; + PackagePath path; + uint32_t flag{0}; + ResourceFileBlock& SetFlag(bool is, ResourceFileFlag _flag) { + if (is) + flag |= _flag; + else + flag &= ~_flag; + return *this; + } + operator bool() { + return IsLoaded(); + } + ResourceFileBlock& Loaded(bool is) { return SetFlag(is, ResourceFileFlag::File_Loaded); } + ResourceFileBlock& Dirty(bool is) { return SetFlag(is, ResourceFileFlag::File_Dirty); } + ResourceFileBlock& MetaDirty(bool is) { return SetFlag(is, ResourceFileFlag::File_Meta_Dirty); } + bool IsLoaded() { return flag & ResourceFileFlag::File_Loaded; } + bool IsDirty() { return flag & ResourceFileFlag::File_Dirty; } + bool IsMetaDirty() { return flag & ResourceFileFlag::File_Meta_Dirty; } + }; + template + struct ResourceSystem::ResourceBlock + { + R* resource{nullptr}; + ResourceFileBlock* file{ nullptr }; + bool valid() const { return resource; } + }; +} +#include "resource_system.inl" \ No newline at end of file diff --git a/engine/modules/engine/asset/include/asset/resource_system.inl b/engine/modules/engine/asset/include/asset/resource_system.inl new file mode 100644 index 0000000..d2b0226 --- /dev/null +++ b/engine/modules/engine/asset/include/asset/resource_system.inl @@ -0,0 +1,145 @@ +#include "resource_system.h" +#pragma once +namespace api { + class IFileLoader + { + protected: + uint32_t mFileFlag = 0; + public: + void SetFileFlag(uint32_t flag) { + mFileFlag = flag; + } + virtual ResourceBundle LoadFile(PackagePath handle, const MetaBundle& meta) = 0; + virtual void SaveFile(PackagePath handle, const ResourceBundle& bundle) {}; + virtual ~IFileLoader() = default; + }; + namespace detail { + template struct ResourceSystem_detail; + + template + struct ResourceSystem_detail> + { + constexpr static array, sizeof...(Rs)> GenResourceTables() + { + return array, sizeof...(Rs)>{ + std::make_shared>()... + }; + } + + constexpr static array ReleaseTableResources() + { + return array{ + [](ResourceSystem* resource_man) + { + if (auto table = &resource_man->GetTable()) + table->clear(); + }... + }; + } + }; + + using ResourceHelper = ResourceSystem_detail; + } + template + inline RscHandle ResourceSystem::LoadFromMeta(const Guid& guid, const SerializedMeta& meta) + { + if (!guid || !meta.meta) { + return {}; + } + Res* res = meta.meta.CastTo(); + auto& table = GetTable(); + auto& control_block = table[guid]; // don't care just replace + if (control_block.resource) { + //meta.meta.MoveTo(control_block.resource); + res = control_block.resource; + } + else { + control_block.resource = res; + res->mHandle.guid = guid; + } + res->Name(meta.name); + return RscHandle{guid, res}; + } + template + inline RscHandle ResourceSystem::LoadEmplaceResource(Guid guid, Args&& ...args) + { + auto& table = GetTable(); + auto& control_block = table[guid]; // don't care just replace + // attempt to put on other thread + Res* res = new Res(std::forward(args)...); + res->mHandle.guid = guid; + control_block.resource = res; + return RscHandle{guid, res}; + } + template + inline FLoader& ResourceSystem::RegisterLoader(Name ext, Args&& ...args) + { + auto& ptr = mFileLoader[ext]; + if (ptr) { + delete ptr; + } + ptr = new FLoader(std::forward(args)...); + ptr->SetFileFlag(GetFileFlag(ext)); + return *(FLoader*)ptr; + } + template + inline RscHandle ResourceSystem::Load(PackagePath path, bool reload_resource) + { + auto& res = Load(path, reload_resource); + return res.Get(); + } + template + inline Res* ResourceSystem::Get(const RscHandle& handle, bool sync) + { + auto& table = GetTable(); + auto itr = table.find(handle.guid); + if (itr == table.end()) { + FileBlock* file = sync ? GetResourceFile(handle.guid) : nullptr; + if (file) { + Load(file->path); + return Get(handle, false); + } + return nullptr; + } + return itr->second.resource; + } + inline uint32_t ResourceSystem::GetFileFlag(Name name) + { + auto it = mFileFlags.find(name); + if (it == mFileFlags.end()) { + return 0; + } + return it->second.second; + } + inline void ResourceSystem::SetFileFlag(Name name, uint32_t flag) + { + auto it = mFileFlags.find(name); + if (it == mFileFlags.end()) { + mFileFlags.emplace(name, std::make_pair(std::string(name.ToStringView()), flag)); + } + else { + it->second.second = flag; + } + } + template + inline ResourceSystem::ResourceBlock* ResourceSystem::GetBlock(const RscHandle& handle) + { + auto& table = GetTable(); + return &table[handle.guid]; + } + inline ResourceSystem::ResourceFileBlock& ResourceSystem::GetFileBlock(PackagePath path) { + return mFileBlock[Name(path())]; + } + inline FileBlock* ResourceSystem::GetResourceFile(const Guid& guid) + { + auto it = mResourceFile.find(guid); + if(it == mResourceFile.end()) + return nullptr; + return it->second; + } + template + inline void RscHandle::Init() + { + res = ResourceSystem::Ptr()->Get(*this); + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/src/asset.cpp b/engine/modules/engine/asset/src/asset.cpp index e69de29..b719f5e 100644 --- a/engine/modules/engine/asset/src/asset.cpp +++ b/engine/modules/engine/asset/src/asset.cpp @@ -0,0 +1,13 @@ +#include "assert.h" +#include "asset_loader.h" +#include "resource_system.h" +namespace api { + void FindIncludes(MetaBundle& bundle, Asset* asset) { + + } + MetaBundle ResourceSystem::GetVisitMeta(const ResourceBundle& bundle) + { + MetaBundle new_meta = MetaBundle{}; + return new_meta; + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/src/asset_loader.cpp b/engine/modules/engine/asset/src/asset_loader.cpp new file mode 100644 index 0000000..376faa3 --- /dev/null +++ b/engine/modules/engine/asset/src/asset_loader.cpp @@ -0,0 +1,25 @@ +#include "asset_loader.h" +#include "os/file_manager.h" +#include "os/file_handle.h" +#include +namespace api { + void AssetLoader::Init() { + ResourceSystem::Ptr()->RegisterLoader(".asset"); + } + ResourceBundle AssetLoader::LoadFile(PackagePath path, const MetaBundle& metas) + { + ResourceBundle bundle; + for (auto meta : metas.metadatas) { + if (!meta.meta) + continue; + auto rsc = ResourceSystem::Ptr()->LoadFromMeta(meta.guid, meta); + bundle.Add(rsc); + } + return bundle; + } + void AssetLoader::SaveFile(PackagePath path, const ResourceBundle& bundle) + { + MetaBundle new_meta = ResourceSystem::Ptr()->GetVisitMeta(bundle); + ResourceSystem::Ptr()->SaveMeta(path, new_meta); + } +} diff --git a/engine/modules/engine/asset/src/module.cpp b/engine/modules/engine/asset/src/module.cpp new file mode 100644 index 0000000..d7078d8 --- /dev/null +++ b/engine/modules/engine/asset/src/module.cpp @@ -0,0 +1,14 @@ +#include "module.h" +#include "resource_system.h" +#include "asset_loader.h" +namespace api { + void AssetModule::OnLoad(int argc, char** argv) + { + AddSystem(); + AssetLoader::Init(); + } + void AssetModule::OnUnload() + { + + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/src/res/meta_bundle.cpp b/engine/modules/engine/asset/src/res/meta_bundle.cpp new file mode 100644 index 0000000..c2e14d3 --- /dev/null +++ b/engine/modules/engine/asset/src/res/meta_bundle.cpp @@ -0,0 +1,23 @@ +#include "res/meta_bundle.h" +#include + +namespace api +{ + const SerializedMeta* MetaBundle::FetchMeta(const Guid& guid) const + { + for (auto& elem : metadatas) + { + if (elem.guid == guid) + return &elem; + } + return nullptr; + } + bool MetaBundle::operator==(const MetaBundle& other)const + { + return metadatas == other.metadatas && includes == other.includes; + } + bool MetaBundle::operator!=(const MetaBundle& other)const + { + return !(*this == other); + } +} \ No newline at end of file diff --git a/engine/modules/engine/asset/src/res/resource_handle.cpp b/engine/modules/engine/asset/src/res/resource_handle.cpp new file mode 100644 index 0000000..acb6020 --- /dev/null +++ b/engine/modules/engine/asset/src/res/resource_handle.cpp @@ -0,0 +1,17 @@ +#include "res/resource_handle.h" +namespace api +{ + GenericResourceHandle::GenericResourceHandle(string_view type_name, Guid guid) + { + + } + Guid GenericResourceHandle::guid() const + { + return std::visit([](const auto& handle) { return handle.guid; }, *this); + } + + size_t GenericResourceHandle::resource_id() const + { + return std::visit([](const auto& handle) { return handle.RscID(); }, *this); + } +} diff --git a/engine/modules/engine/asset/src/resource_system.cpp b/engine/modules/engine/asset/src/resource_system.cpp new file mode 100644 index 0000000..b64a1b5 --- /dev/null +++ b/engine/modules/engine/asset/src/resource_system.cpp @@ -0,0 +1,137 @@ +#include "resource_system.h" +#include "os/file_manager.h" +#include "os/file_handle.h" +#include "archive/json.h" +namespace api { + ResourceSystem::ResourceSystem() + { + mResourceTable = detail::ResourceHelper::GenResourceTables(); + LoadFileFlags(); + LoadResourceFile(); + } + void ResourceSystem::Initialize() + { + SaveFileFlags(); + SaveDirtyFile(); + } + void ResourceSystem::Finalize() + { + constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources(); + for (auto& elem : release_tables) + elem(this); + SaveFileFlags(); + SaveDirtyFile(); + SaveResourceFile(); + } + IFileLoader* ResourceSystem::GetLoader(Name extension) + { + auto itr = mFileLoader.find(extension); + if (itr == mFileLoader.end()) + return nullptr; + return itr->second; + } + ResourceBundle& ResourceSystem::Load(PackagePath path, bool reload_resource, int deep) + { + Name name = path(); + auto it = mFileBlock.find(name); + auto& res = mFileBlock[name]; + if (deep > 5 || (!reload_resource && res && it != mFileBlock.end())) { + return res.bundle; + } + Name ext = path.GetExtension(); + IFileLoader* loader = GetLoader(ext); + MetaBundle meta = GetMeta(path); + ResourceBundle bundle = loader->LoadFile(path, meta); + MetaBundle new_meta = GetVisitMeta(bundle); + bool is_dirty_meta = meta != new_meta; + for (auto& elem : bundle.GetAll()) { + std::visit([&](auto& handle) { + using T = std::decay_t; + GetBlock(handle)->file = &res; + mResourceFile[handle.guid] = FileManager::Ptr()->FindPathBlock(path); + }, elem); + } + if (is_dirty_meta || res.IsDirty()) { + mDirtyBlock.push_back(&res); + } + res.path = path.SafePath(); + res.bundle = bundle; + res.Loaded(true).MetaDirty(is_dirty_meta); + res.bundle = bundle; + if (!new_meta.includes.empty()) { + for (auto include : new_meta.includes) { + Load(include, false, deep + 1); + } + } + return res.bundle; + } + + MetaBundle ResourceSystem::GetMeta(PackagePath path) + { + FileHandle handle(path + ".meta"); + if (!handle.Open(FILE_OP::READ, mFileFlag & FileFlag::File_Binary)) { + return {}; + } + meta::result res; + if (mFileFlag & FileFlag::File_Binary) { + + } + else { + pmr::string text = handle.ReadAll(); + res = JsonDeserialize(text); + } + if (!res) { + return {}; + } + return res.value(); + } + void ResourceSystem::SaveMeta(PackagePath path, const MetaBundle& bundle) + { + FileHandle handle(path + ".meta"); + handle.Open(FILE_OP::WRITE, mFileFlag & FileFlag::File_Binary); + if (mFileFlag & FileFlag::File_Binary) { + + } + else { + handle.Write(JsonSerialize(bundle)); + } + } + void ResourceSystem::SaveDirtyFile() + { + for (auto block : mDirtyBlock) { + if (block->IsMetaDirty()) { + block->MetaDirty(false); + MetaBundle new_meta = GetVisitMeta(block->bundle); + SaveMeta(block->path, new_meta); + } + if (block->IsDirty()) { + block->Dirty(false); + auto loader = GetLoader(block->path.GetExtension()); + loader->SaveFile(block->path, block->bundle); + } + } + mDirtyBlock.clear(); + } + void ResourceSystem::SaveFile(PackagePath path, const ResourceBundle& bundle) + { + auto loader = GetLoader(path.GetExtension()); + loader->SaveFile(path, bundle); + } + void ResourceSystem::LoadFileFlags() + { + + } + void ResourceSystem::SaveFileFlags() + { + + } + void ResourceSystem::LoadResourceFile() + { + + } + void ResourceSystem::SaveResourceFile() + { + + } +} + diff --git a/engine/modules/engine/asset/xmake.lua b/engine/modules/engine/asset/xmake.lua index 4c36c84..076121c 100644 --- a/engine/modules/engine/asset/xmake.lua +++ b/engine/modules/engine/asset/xmake.lua @@ -1,5 +1,8 @@ static_component("asset","engine") + add_rules("c++.codegen",{ + files = {"include/asset/res/*.h"} + }) add_includedirs("include/asset") - add_headerfiles("include/**.h") + add_headerfiles("include/**.h","include/**.inl") add_files("src/**.cpp") add_deps("core", {public = true}) \ No newline at end of file diff --git a/engine/modules/engine/core/include/3rdparty/singleton.h b/engine/modules/engine/core/include/3rdparty/singleton.h index 9fd0069..f3f2e12 100644 --- a/engine/modules/engine/core/include/3rdparty/singleton.h +++ b/engine/modules/engine/core/include/3rdparty/singleton.h @@ -1,3 +1,4 @@ +#pragma once template class Singleton{ protected: diff --git a/engine/modules/engine/core/include/archive/json.h b/engine/modules/engine/core/include/archive/json.h index 1d9be85..eeccf51 100644 --- a/engine/modules/engine/core/include/archive/json.h +++ b/engine/modules/engine/core/include/archive/json.h @@ -7,8 +7,8 @@ namespace api { using std::string_view; enum class SerializeError : char { - EMPTY, - ERROR, + SERDE_EMPTY, + SERDE_ERROR, }; template inline bool JsonDeserialize(string_view text, T* obj) { @@ -27,12 +27,12 @@ namespace api { template inline result JsonDeserialize(string_view text, Args&& ...args) { if (text.empty()) { - return SerializeError::EMPTY; + return SerializeError::SERDE_EMPTY; } T* obj = new(FramePool)T(std::forward(args)...); bool bsuccess = JsonDeserialize(text, obj); using ResultType = result; - return bsuccess ? ResultType{ *obj } : ResultType{ SerializeError::ERROR }; + return bsuccess ? ResultType{ *obj } : ResultType{ SerializeError::SERDE_ERROR }; } template inline string_view JsonSerialize(const T& t) { diff --git a/engine/modules/engine/core/include/archive/json/serialize.h b/engine/modules/engine/core/include/archive/json/serialize.h index da39d95..1a41ce6 100644 --- a/engine/modules/engine/core/include/archive/json/serialize.h +++ b/engine/modules/engine/core/include/archive/json/serialize.h @@ -5,19 +5,15 @@ namespace api { using refl::Any; using refl::UClass; using refl::TypeInfo; + using pmr::string_hash; struct JsonVTable { - bool(*Read)(yyjson_val*, const void*) = nullptr; - yyjson_mut_val*(*Write)(yyjson_mut_doc*, const void*) = nullptr; - template - static JsonVTable Make() { - return { &gen::JsonSerde::Read, &gen::JsonSerde::Write }; - } + using Read = bool(*)(yyjson_val*, const void*); + using Write = yyjson_mut_val*(*)(yyjson_mut_doc*, const void*); }; - using JsonFuncTable = std::pmr::unordered_map; struct JsonArchive { private: - static JsonFuncTable BuildFuncTable(); - inline static JsonFuncTable FuncTable = BuildFuncTable(); + static bool InitJsonSerde(); + inline static bool HasInit = InitJsonSerde(); public: template static void Register(); diff --git a/engine/modules/engine/core/include/archive/json/serialize.inl b/engine/modules/engine/core/include/archive/json/serialize.inl index 81b193d..ab77072 100644 --- a/engine/modules/engine/core/include/archive/json/serialize.inl +++ b/engine/modules/engine/core/include/archive/json/serialize.inl @@ -27,28 +27,38 @@ namespace api { alc.ctx = mr; return alc; } - inline JsonFuncTable JsonArchive::BuildFuncTable() + inline bool JsonArchive::InitJsonSerde() { - JsonFuncTable funcTable{ MemPool }; using std::string_view; -#define RegisterAny(T) funcTable.emplace(&TypeInfo::StaticClass,JsonVTable::Make()) +#define RegisterAny(T) Register(); #include "../register.inl" #undef RegisterAny - return funcTable; + return true; + } + constexpr size_t VJsonSerdeRead() { + return string_hash("JsonSerdeRead"); + } + constexpr size_t VJsonSerdeWrite() { + return string_hash("JsonSerdeWrite"); } template inline void JsonArchive::Register() { - FuncTable.emplace(&TypeInfo::StaticClass, JsonVTable::Make()); + auto uclass = &TypeInfo::StaticClass; + auto [bfind, it] = uclass->vtable.FindLast(VJsonSerdeRead()); + if (!bfind && it) { + it = it->Insert(VJsonSerdeRead(), (void*) &gen::JsonSerde::Read); + it = it->Insert(VJsonSerdeWrite(), (void*) &gen::JsonSerde::Write); + } } inline yyjson_mut_val* JsonArchive::Serialize(yyjson_mut_doc* doc, Any any) { if (!any) { return {}; } - auto it = FuncTable.find(any.cls); - if (it != FuncTable.end()) { - return it->second.Write(doc, any.ptr); + auto it = any.FindVtable(VJsonSerdeWrite()); + if (it) { + return it(doc, any.ptr); } return {}; } @@ -57,9 +67,9 @@ namespace api { if (!any) { return false; } - auto it = FuncTable.find(any.cls); - if (it != FuncTable.end()) { - return it->second.Read(res, any.ptr); + auto it = any.FindVtable(VJsonSerdeRead()); + if (it) { + return it(res, any.ptr); } return false; } diff --git a/engine/modules/engine/core/include/module/module.h b/engine/modules/engine/core/include/module/module.h index d05f1ee..2bcb9ab 100644 --- a/engine/modules/engine/core/include/module/module.h +++ b/engine/modules/engine/core/include/module/module.h @@ -3,6 +3,14 @@ #include "enum_macro.h" #include "os/shared_library.h" #include "refl/pch.h" +//可变生命周期,回收内存 +inline thread_local pmr::unsynchronized_pool_resource MemPool; +// 默认对齐方式 new +void* operator new(std::size_t size); +// 默认对齐方式 delete +void operator delete(void* ptr) noexcept; +// 自定义对齐 align +void* operator new(std::size_t size, std::align_val_t align); namespace api { using pmr::Name; enum class EModuleFlag : uint32_t { @@ -38,20 +46,17 @@ namespace api { Name copyright; //!< copyright of the plugin UPROPERTY() pmr::vector dependencies; - ModuleInfo(pmr::memory_resource* mr = MemPool) : dependencies(mr){}; public: bool IsReload() { return !!(flag & EModuleFlag::Reload); } }; - struct IModuleSubsystem + struct ISubSystem { - using CreatePFN = IModuleSubsystem* (*)(); - virtual ~IModuleSubsystem() = default; + using CreatePFN = ISubSystem* (*)(); + virtual ~ISubSystem() = default; virtual void Initialize() = 0; virtual void Finalize() = 0; - virtual void BeginLoad() {} - virtual void EndLoad() {} }; struct IModule { public: @@ -60,20 +65,26 @@ namespace api { IModule() = default; IModule(const IModule& rhs) = delete; IModule& operator=(const IModule& rhs) = delete; - virtual ~IModule() {}; - + virtual ~IModule(); virtual void OnLoad(int argc, char** argv) = 0; virtual void OnUnload() = 0; virtual void InitMetaData(void) = 0; - - virtual int Main(int argc, char** argv) { return 0; } - virtual const ModuleInfo* GetModuleInfo() + virtual void Initialize(); + virtual void Finalize(); + template + T* AddSystem(Args&&... args) { + T* ptr = new (GlobalPool) T(std::forward(args)...); + mSystems.push_back(ptr); + return ptr; + } + const ModuleInfo* GetModuleInfo() { return &mInfo; } + protected: ModuleInfo mInfo; - pmr::vector mSubSystems; + pmr::vector mSystems; }; } #include "module.inl" diff --git a/engine/modules/engine/core/include/module/module.inl b/engine/modules/engine/core/include/module/module.inl index 65b720a..8cd6f33 100644 --- a/engine/modules/engine/core/include/module/module.inl +++ b/engine/modules/engine/core/include/module/module.inl @@ -1,4 +1,21 @@ namespace api { + template + class ISystem : public ISubSystem { + protected: + inline static T* ms_system = nullptr; + public: + explicit ISystem() { + ms_system = static_cast(this); + } + ~ISystem() override{ + ms_system = nullptr; + } + static constexpr T* Ptr(void) { + return ms_system; + } + }; + template + struct ModuleRegistrantImpl; struct IDynamicModule : public IModule { virtual ~IDynamicModule() override { @@ -20,11 +37,11 @@ namespace api { }; } #define IMPLEMENT_STATIC_MODULE(ModuleImplClass, ModuleName) \ - inline const api::ModuleRegistrantImpl __RegisterModule__##ModuleName(#ModuleName); + inline static const api::ModuleRegistrantImpl __RegisterModule__##ModuleName(#ModuleName); #define IMPLEMENT_DYNAMIC_MODULE(DLL_APL, ModuleImplClass, ModuleName) \ using __##ModuleName##__module = ModuleImplClass; \ extern "C" DLL_APL api::IModule* __newDynamicModule__##ModuleName() \ { \ - return new(MemPool) ModuleImplClass(); \ + return new(GlobalPool) ModuleImplClass(); \ } \ No newline at end of file diff --git a/engine/modules/engine/core/include/module/module_manager.h b/engine/modules/engine/core/include/module/module_manager.h index 26ce28e..2f66498 100644 --- a/engine/modules/engine/core/include/module/module_manager.h +++ b/engine/modules/engine/core/include/module/module_manager.h @@ -1,12 +1,13 @@ #pragma once #include "module.h" namespace api { - class ModuleManager + class DLL_API ModuleManager { friend struct IModule; private: struct ModuleBlock { - bool isActive; + bool isLoad; + bool isInit; }; struct ExecuteInfo { Name name; @@ -16,18 +17,21 @@ namespace api { }; ExecuteInfo mInfo; SharedLibrary mProcessLib; - pmr::table mModuleBlocks{ GetMemPool() }; - pmr::table mModuleTable{GetMemPool()}; - pmr::table mInitializeTable{ GetMemPool() }; + pmr::table mModuleBlocks; + pmr::table mModuleTable; + pmr::table mInitializeTable; + pmr::table> mInitializeSubSystems;; public: static ModuleManager* Ptr(); public: ModuleManager(); ~ModuleManager(); IModule* GetModule(Name name); - void RegisterModule(Name name, IModule::CreatePFN fn) { mInitializeTable[name] = fn; } + void RegisterModule(Name name, IModule::CreatePFN fn); void CreateModule(Name name, bool shared); void DestroyModule(Name name); + void InitModule(Name name); + void ShutModule(Name name); void MakeGraph(Name name, bool shared, int argc, char** argv); void DestroyGraph(); protected: diff --git a/engine/modules/engine/core/include/os/file_handle.h b/engine/modules/engine/core/include/os/file_handle.h new file mode 100644 index 0000000..f58c032 --- /dev/null +++ b/engine/modules/engine/core/include/os/file_handle.h @@ -0,0 +1,61 @@ +#include "package_path.h" +#include +#include +#include +namespace api { + using std::vector; + enum class FILE_OP + { + READ, + WRITE, + APPEND, + NONE + }; + class FileHandle : PackagePath{ + protected: + uint32_t flag{0}; + FILE_OP op{ FILE_OP::NONE}; + size_t size{0}; + pmr::memory_resource* pool; + std::variant vfile{nullptr}; + public: + using PackagePath::PackagePath; + FileHandle(PackagePath path, pmr::memory_resource* pool = FramePool) : PackagePath(path) , pool(pool) {} + uint32_t Flag() { + return flag; + } + operator bool() { + return flag & File_Success; + } + std::ifstream& Reader() { + return std::get(vfile); + } + std::ofstream& Writer() { + return std::get(vfile); + } + FileHandle& Open(FILE_OP op, bool is_binarry = false); + int Read(void* data, int size); + template> + T ReadAll() { + Reader().seekg(0); + return ReadLeft(); + } + template> + T ReadLeft(); + bool FindNext(const char* begin, const char* end, size_t& stop); + //这里出问题了,二进制的\r\n会被读取成\n,大小对不上 + template + T ReadUntil(const T& token); + void Write(const char* data, size_t size){ Writer().write(data, size); } + template + void Write(const T& data) { + Write(data.data(), data.size()); + } + template + void WriteLine(const T& data) { + Write(data); + Write(T{ "\n"}); + } + }; +} +#include "file_handle.inl" \ No newline at end of file diff --git a/engine/modules/engine/core/include/os/file_handle.inl b/engine/modules/engine/core/include/os/file_handle.inl new file mode 100644 index 0000000..4911b95 --- /dev/null +++ b/engine/modules/engine/core/include/os/file_handle.inl @@ -0,0 +1,39 @@ +namespace api{ + template + inline T FileHandle::ReadLeft() + { + T data{pool}; + auto& fi = Reader(); + size_t read_size = size - fi.tellg(); + data.resize(read_size, '\0'); + fi.read(data.data(), read_size); + // 检查实际读取的字节数 + size_t count = (size_t)fi.gcount(); + if (count != read_size) { + data.resize(count); + } + return data; + } + template + inline T FileHandle::ReadUntil(const T& token) + { + auto& fi = Reader(); + size_t start = fi.tellg(); + size_t stop = size; + size_t skip_to = 0; + if (FindNext(token.data(), &token.back(), stop)) { + skip_to = stop + token.size(); + } + T buffer{pool}; + buffer.resize(stop - start); + fi.read(buffer.data(), stop - start); + size_t count = (size_t)fi.gcount(); + if (count != stop - start) { + buffer.resize(count); + } + if (skip_to) { + fi.seekg(skip_to); + } + return buffer; + } +} \ No newline at end of file diff --git a/engine/modules/engine/core/include/os/file_manager.h b/engine/modules/engine/core/include/os/file_manager.h index 0e579d0..f7fd1fb 100644 --- a/engine/modules/engine/core/include/os/file_manager.h +++ b/engine/modules/engine/core/include/os/file_manager.h @@ -9,23 +9,24 @@ namespace api FileManager(); ~FileManager(); public: - void Mount(Name name, const string& path) { + void Mount(Name name, const std::string& path) { MountMap.emplace(name, std::make_pair(name, path)); } - std::pair FindMount(Name id) { + std::pair* FindMount(Name id) { auto it = MountMap.find(id); if (it != MountMap.end()) { - return it->second; + return &it->second; } - return {}; + static std::pair pair("", ""); + return &pair; } string_view FindMountName(Name id) { auto pair = FindMount(id); - return pair.first; + return pair->first; } string_view FindMountPath(Name id) { auto pair = FindMount(id); - return pair.second; + return pair->second; } string_view FindPathView(Name name) { auto it = FileMap.find(name); @@ -42,14 +43,14 @@ namespace api auto res = FileMap.emplace(name, FileBlock{ FileFlag::File_Default, name.ToString()}); return res.first->second.path; } - uint32_t FindPathFlag(const PackagePath& pack_path) { + uint32_t FindPathFlag(PackagePath pack_path) { auto it = FileMap.find(pack_path()); if (it == FileMap.end()) { return FileFlag::File_Not_Exist; } return it->second.flag; } - FileBlock* FindPathBlock(const PackagePath& pack_path) { + FileBlock* FindPathBlock(PackagePath pack_path) { auto it = FileMap.find(pack_path()); if (it == FileMap.end()) { return nullptr; @@ -60,10 +61,10 @@ namespace api void LoadFileMap(); void SaveFileMap(); private: - pmr::table> MountMap{GetMemPool()}; - pmr::table FileMap{GetMemPool()}; + pmr::table> MountMap; + pmr::table FileMap; public: //外界不应该使用绝对路径 - pmr::string RealPath(const PackagePath& pack_path); + pmr::string RealPath(PackagePath pack_path); }; } diff --git a/engine/modules/engine/core/include/os/package_path.h b/engine/modules/engine/core/include/os/package_path.h index 9b01692..59d32c2 100644 --- a/engine/modules/engine/core/include/os/package_path.h +++ b/engine/modules/engine/core/include/os/package_path.h @@ -3,7 +3,6 @@ #include "pmr/name.h" namespace api { - using std::string; using std::string_view; using pmr::Name; enum FileFlag : uint32_t { @@ -18,8 +17,8 @@ namespace api //占位符浪费了四个字节 struct FileBlock { uint32_t flag{ 0 }; - string path; - string addr; + std::string path; + std::string addr; operator bool() { return !(flag & FileFlag::File_Not_Exist); } @@ -29,8 +28,9 @@ namespace api PackagePath() {}; PackagePath(const char* path) : path(path) {} PackagePath(string_view path) : path(path) {} - PackagePath(const string& path) : path(path) {} + PackagePath(const std::string& path) : path(path) {} PackagePath(const pmr::string& path) : path(path) {} + PackagePath(pmr::Name name) : path(name.ToStringView()) {} operator bool() { return path != ""; } @@ -41,13 +41,13 @@ namespace api return path.size(); } pmr::string operator+(const char* suffix) const { - return pmr::string(path, FramePool) + suffix; + return pmr::string(path) + suffix; } string_view ParsePackage()const { string_view name; if (path[0] == '/') { size_t pos = path.find('/', 1); - if (pos != string::npos) { + if (pos != std::string::npos) { return path.substr(1, pos - 1); } } diff --git a/engine/modules/engine/core/src/module/module.cpp b/engine/modules/engine/core/src/module/module.cpp index f94aa96..ed421a7 100644 --- a/engine/modules/engine/core/src/module/module.cpp +++ b/engine/modules/engine/core/src/module/module.cpp @@ -1,5 +1,28 @@ #include "module/module_manager.h" #include "os/file_manager.h" +struct MemDetail { + int count{ 0 }; + int new_count{ 0 }; + int del_count{ 0 }; +}; +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); +} +// 默认对齐方式 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(align); + return MemPool.allocate(size, alignment); +} namespace api { void CoreModule::OnLoad(int argc, char** argv) { @@ -13,4 +36,22 @@ namespace api { { } + IModule::~IModule() + { + for (auto system : mSystems) { + delete system; + } + } + void IModule::Initialize() + { + for (auto system : mSystems) { + system->Initialize(); + } + } + void IModule::Finalize() + { + for (auto system : mSystems) { + system->Finalize(); + } + } } diff --git a/engine/modules/engine/core/src/module/module_manager.cpp b/engine/modules/engine/core/src/module/module_manager.cpp index a393654..07eb3f1 100644 --- a/engine/modules/engine/core/src/module/module_manager.cpp +++ b/engine/modules/engine/core/src/module/module_manager.cpp @@ -8,7 +8,7 @@ namespace api { } ModuleManager::ModuleManager() { - GetMemPool(); + GetGlobalPool(); GetFramePool(); mProcessLib.Load(); new FileManager(); @@ -17,8 +17,8 @@ namespace api { { DestroyGraph(); delete FileManager::Ptr(); - delete GetFramePool(); - delete GetMemPool(); + delete FramePool; + delete GlobalPool; } void ModuleManager::CreateModule(Name name, bool shared) { @@ -27,7 +27,7 @@ namespace api { spawnDynamicModule(name, hotfix) : spawnStaticModule(name); if (!module) { return; } - mModuleBlocks[name] = ModuleBlock{false}; + mModuleBlocks[name] = ModuleBlock{false, false}; ModuleBlock& block = mModuleBlocks[name]; auto& moduleInfo = module->mInfo; for (auto& dep : moduleInfo.dependencies) { @@ -35,12 +35,12 @@ namespace api { CreateModule(dep.name, dep.kind == pmr::FName("shared")); } module->OnLoad(mInfo.argc, mInfo.argv); - block.isActive = true; + block.isLoad = true; } void ModuleManager::DestroyModule(Name name) { auto it = mModuleBlocks.find(name); - if (it == mModuleBlocks.end() || !it->second.isActive) { + if (it == mModuleBlocks.end() || !it->second.isLoad) { return; } IModule* module = mModuleTable[name]; @@ -48,17 +48,49 @@ namespace api { for (auto& dep : moduleInfo.dependencies) { DestroyModule(dep.name); } - it->second.isActive = false; + module->OnUnload(); + it->second.isLoad = false; + } + void ModuleManager::InitModule(Name name) + { + auto it = mModuleBlocks.find(name); + if (it == mModuleBlocks.end() || it->second.isInit) { + return; + } + IModule* module = mModuleTable[name]; + auto& moduleInfo = module->mInfo; + for (auto& dep : moduleInfo.dependencies) { + InitModule(dep.name); + } + module->Initialize(); + it->second.isInit = true; + } + void ModuleManager::ShutModule(Name name) + { + auto it = mModuleBlocks.find(name); + if (it == mModuleBlocks.end() || !it->second.isInit) { + return; + } + IModule* module = mModuleTable[name]; + auto& moduleInfo = module->mInfo; + for (auto& dep : moduleInfo.dependencies) { + ShutModule(dep.name); + } + module->Finalize(); + it->second.isInit = false; } void ModuleManager::MakeGraph(Name name, bool shared, int argc, char** argv) { mInfo = { name, argc, argv , true}; CreateModule(name, shared); + InitModule(name); } void ModuleManager::DestroyGraph() { - if(mInfo.isActive) + if(mInfo.isActive){ + ShutModule(mInfo.name); DestroyModule(mInfo.name); + } } IModule* ModuleManager::spawnDynamicModule(Name name, bool hotfix) { @@ -67,11 +99,11 @@ namespace api { } SharedLibrary sharedLib; string_view name_view = name.ToStringView(); - pmr::string newFuncName("__newDynamicModule__", FramePool); + pmr::string newFuncName("__newDynamicModule__"); newFuncName.append(name_view); void* newFuncAddr = mProcessLib.GetSymbol(newFuncName.data()); if (!newFuncAddr) { - pmr::string libPath("/exe/", FramePool); + pmr::string libPath("/exe/"); libPath.reserve(10 + name_view.size()); libPath.append(name_view); libPath.append(SharedLibrary::GetExtensionName()); @@ -79,7 +111,7 @@ namespace api { newFuncAddr = sharedLib.GetSymbol(newFuncName.data()); } } - IDynamicModule* module = newFuncAddr ? (IDynamicModule*)((IModule::CreatePFN)newFuncAddr)() : new(MemPool) DefaultDynamicModule(name); + IDynamicModule* module = newFuncAddr ? (IDynamicModule*)((IModule::CreatePFN)newFuncAddr)() : new(GlobalPool) DefaultDynamicModule(name); mModuleTable[name] = module; module->mSharedLib = sharedLib; module->InitMetaData(); @@ -107,4 +139,8 @@ namespace api { } return it->second; } + void ModuleManager::RegisterModule(Name name, IModule::CreatePFN fn) + { + mInitializeTable[name] = fn; + } } \ No newline at end of file diff --git a/engine/modules/engine/core/src/os/file_handle.cpp b/engine/modules/engine/core/src/os/file_handle.cpp new file mode 100644 index 0000000..731a331 --- /dev/null +++ b/engine/modules/engine/core/src/os/file_handle.cpp @@ -0,0 +1,75 @@ +#include "os/file_handle.h" +#include +#define READ_DATA_SIZE 100 +#define TOKEN_SIZE 100 +namespace api { + FileHandle& FileHandle::Open(FILE_OP _op, bool is_binarry) + { + op = _op; + pmr::string file_path = RealPath(); + switch (op) + { + case api::FILE_OP::READ: + { + vfile = std::ifstream(file_path.c_str(), is_binarry ? std::ios::binary | std::ios::ate : std::ios::ate); + auto& fi = Reader(); + if (!fi.is_open()) { + return *this; + } + size = fi.tellg(); + fi.seekg(0); + break; + } + case api::FILE_OP::WRITE: + vfile = std::ofstream(file_path.c_str(), is_binarry ? std::ios::binary : 0); + break; + case api::FILE_OP::APPEND: + vfile = std::ofstream(file_path.c_str(), is_binarry ? std::ios::app | std::ios::binary : std::ios::app); + break; + default: + break; + } + flag = FileFlag::File_Success | (is_binarry ? FileFlag::File_Binary : 0); + return *this; + } + int FileHandle::Read(void* data, int size) + { + auto& fi = Reader(); + if (!fi) { + return -1; + } + fi.read((char*)data, size); + return fi.gcount(); + } + bool FileHandle::FindNext(const char* begin, const char* end, size_t& stop) + { + auto& fi = Reader(); + size_t start = fi.tellg(); + size_t cur = start; + char chunk[READ_DATA_SIZE + TOKEN_SIZE]; + const char* last = chunk + READ_DATA_SIZE + TOKEN_SIZE; + while (cur < stop) { + fi.read(chunk + TOKEN_SIZE, READ_DATA_SIZE); + size_t count = fi.gcount(); + if (count < READ_DATA_SIZE || cur + count > stop) { + fi.clear(); + } + const char* first = cur == start ? chunk + TOKEN_SIZE : chunk; + const char* it = std::search(first, last, begin, end); + if (it != last) { + fi.seekg(start); + stop = cur + (it - first) - TOKEN_SIZE; + return true; + } + if (count < READ_DATA_SIZE) { + fi.seekg(start); + stop = cur + count; + return false; + } + cur += count; + memcpy(chunk, chunk + READ_DATA_SIZE, TOKEN_SIZE); + } + fi.seekg(start); + return false; + } +} diff --git a/engine/modules/engine/core/src/os/file_manager.cpp b/engine/modules/engine/core/src/os/file_manager.cpp index 200736c..33bb58e 100644 --- a/engine/modules/engine/core/src/os/file_manager.cpp +++ b/engine/modules/engine/core/src/os/file_manager.cpp @@ -26,14 +26,14 @@ namespace api { { } - pmr::string FileManager::RealPath(const PackagePath& pack_path) + pmr::string FileManager::RealPath(PackagePath pack_path) { string_view name = pack_path.ParsePackage(); string_view pre_path = FindMountPath(name); if (name.empty() || pre_path.empty()) { - return pmr::string(pack_path(), FramePool); + return pmr::string(pack_path()); } - pmr::string path{FramePool}; + pmr::string path{}; path.reserve(pre_path.size() + pack_path.size() - name.size() - 1); path.append(pre_path); path.append(pack_path().substr(name.size() + 1)); diff --git a/engine/modules/engine/core/src/os/package_path.cpp b/engine/modules/engine/core/src/os/package_path.cpp index c90f29e..4b53e7c 100644 --- a/engine/modules/engine/core/src/os/package_path.cpp +++ b/engine/modules/engine/core/src/os/package_path.cpp @@ -6,7 +6,7 @@ namespace api { string_view name = ParsePackage(); if (name.empty() || suffix.empty()) return *this; - string suffixPath; + pmr::string suffixPath; suffixPath.reserve(path.size() + suffix.size()); suffixPath.append(name); suffixPath.append(suffix); diff --git a/engine/modules/engine/zlib/include/meta/comparable.h b/engine/modules/engine/zlib/include/meta/comparable.h new file mode 100644 index 0000000..5a056dc --- /dev/null +++ b/engine/modules/engine/zlib/include/meta/comparable.h @@ -0,0 +1,18 @@ +#pragma once +#include +namespace meta +{ + template + struct comparable + { + bool operator>(const T&) const; + bool operator<=(const T&) const; + bool operator>=(const T&) const; + bool operator==(const T&) const; + bool operator!=(const T&) const; + private: + T& me(); + const T& me() const; + }; +} +#include "comparable.inl" \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/meta/comparable.inl b/engine/modules/engine/zlib/include/meta/comparable.inl new file mode 100644 index 0000000..cc5826c --- /dev/null +++ b/engine/modules/engine/zlib/include/meta/comparable.inl @@ -0,0 +1,43 @@ +#pragma once +namespace meta +{ + template + inline bool comparable::operator>(const T& rhs) const + { + static_assert(std::is_same_v() < std::declval()), bool>, "type must be override bool operator<(const T&) const"); + return rhs < me(); + } + template + inline bool comparable::operator<=(const T& rhs) const + { + return !(rhs > me()); + } + template + inline bool comparable::operator>=(const T& rhs) const + { + return !(me() < rhs); + } + template + inline bool comparable::operator==(const T& rhs) const + { + return !operator!=(rhs); + } + + template + inline bool comparable::operator!=(const T& rhs) const + { + return me() < rhs || rhs < me(); + } + + template + inline T& comparable::me() + { + return *static_cast(this); + } + + template + inline const T& comparable::me() const + { + return *static_cast(this); + } +} \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/meta/tuple.h b/engine/modules/engine/zlib/include/meta/tuple.h new file mode 100644 index 0000000..ba78540 --- /dev/null +++ b/engine/modules/engine/zlib/include/meta/tuple.h @@ -0,0 +1,43 @@ +#pragma once +// tuple utils + +#include + +namespace meta +{ + template typename Wrap> + struct tuple_wrap; + + template typename Wrap> + using tuple_wrap_t = typename tuple_wrap::type; + + + template + using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); + + template + struct tuple_join; + + template + using tuple_join_t = typename tuple_join::type; + + template + consteval std::size_t index_in_tuple() { + if constexpr (Index == std::tuple_size_v) { + return Index; // 如果没有找到,返回元组的大小作为标志 + } + else if constexpr (std::is_same_v>) { + return Index; // 找到匹配的类型,返回当前索引 + } + else { + return index_in_tuple(); // 递归检查下一个索引 + } + } + + template + constexpr uint8_t index_in_tuple_v = index_in_tuple(); + + template + constexpr auto tuple_construct(const std::tuple&) noexcept; +} +#include "tuple.inl" \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/meta/tuple.inl b/engine/modules/engine/zlib/include/meta/tuple.inl new file mode 100644 index 0000000..6a84f95 --- /dev/null +++ b/engine/modules/engine/zlib/include/meta/tuple.inl @@ -0,0 +1,30 @@ +#pragma once +#include +namespace meta +{ + namespace detail + { + template + auto tuple_construct_helper(const std::tuple& arg_tuple, std::index_sequence) + { + return T{(std::get(arg_tuple))...}; + } + } + template + constexpr auto tuple_construct(const std::tuple& arg_tuple) noexcept + { + return detail::tuple_construct_helper(arg_tuple, std::make_index_sequence < std::tuple_size_v >> {}); + } + + template + struct tuple_join, std::tuple> + { + using type = std::tuple; + }; + + template typename Wrap> + struct tuple_wrap, Wrap> + { + using type = std::tuple...>; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/meta/variant.h b/engine/modules/engine/zlib/include/meta/variant.h new file mode 100644 index 0000000..a618a4a --- /dev/null +++ b/engine/modules/engine/zlib/include/meta/variant.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include +namespace meta +{ + template typename Template> + struct variant_wrap; + + template typename Template> + using variant_wrap_t = typename variant_wrap::type; + + template + struct tuple_to_variant; + + template + using tuple_to_variant_t = typename tuple_to_variant::type; + + template + constexpr auto variant_construct(size_t) noexcept; + + template + struct index_in_variant; + + template + constexpr auto index_in_variant_v = index_in_variant::value; +} +#include "variant.inl" \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/meta/variant.inl b/engine/modules/engine/zlib/include/meta/variant.inl new file mode 100644 index 0000000..25a3b36 --- /dev/null +++ b/engine/modules/engine/zlib/include/meta/variant.inl @@ -0,0 +1,64 @@ +#pragma once +namespace meta +{ + namespace detail + { + template + struct variant_helper; + + template + struct variant_helper> + { + static constexpr auto ConstructJT() + { + using T = std::variant; + return std::array + { + []() -> T + { + return Ts{}; + } ... + }; + } + }; + } + template typename Template, typename ...Ts> + struct variant_wrap , Template> + { + using type = std::variant...>; + }; + + template + struct tuple_to_variant > + { + using type = std::variant; + }; + + + template + constexpr auto variant_construct(size_t i) noexcept + { + constexpr auto jt = detail::variant_helper::ConstructJT(); + return jt[i](); + } + + + + template + struct index_in_variant> + { + static constexpr uint8_t value = 0; + }; + + template + struct index_in_variant> + { + static constexpr uint8_t value = 0; + }; + + template + struct index_in_variant> + { + static constexpr uint8_t value = index_in_variant>::value + 1; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/pmr/frame_allocator.h b/engine/modules/engine/zlib/include/pmr/frame_allocator.h index ac0a30a..aa630ce 100644 --- a/engine/modules/engine/zlib/include/pmr/frame_allocator.h +++ b/engine/modules/engine/zlib/include/pmr/frame_allocator.h @@ -2,6 +2,7 @@ #include #include namespace pmr { + using std::pmr::unsynchronized_pool_resource; using std::pmr::memory_resource; using std::pmr::vector; class FrameAllocator : public memory_resource { @@ -47,18 +48,28 @@ inline void* operator new(size_t size, pmr::FrameAllocatorPool* pool, size_t ali return pool->allocate(size, alignment); } #include "frame_allocator.inl" - -inline pmr::FrameAllocatorPool* MemPool{}; -inline pmr::FrameAllocatorPool* FramePool{}; -inline pmr::FrameAllocatorPool* GetMemPool(){ - if(!MemPool){ - MemPool = new pmr::FrameAllocatorPool(); +#ifdef DLL_API_VALUE +//全局生命周期,不回收内存 +extern DLL_API inline pmr::FrameAllocatorPool* GlobalPool; +//局部生命周期,每帧回收内存 +extern DLL_API inline pmr::FrameAllocatorPool* FramePool; +DLL_API pmr::FrameAllocatorPool* GetGlobalPool(); +DLL_API pmr::FrameAllocatorPool* GetFramePool(); +#else +//全局生命周期,不回收内存 +inline pmr::FrameAllocatorPool* GlobalPool; +//局部生命周期,每帧回收内存 +inline pmr::FrameAllocatorPool* FramePool; +inline pmr::FrameAllocatorPool* GetGlobalPool() { + if (!GlobalPool) { + GlobalPool = new pmr::FrameAllocatorPool(); } - return MemPool; + return GlobalPool; } -inline pmr::FrameAllocatorPool* GetFramePool(){ - if(!FramePool){ - FramePool = new(GetMemPool()) pmr::FrameAllocatorPool(); +inline pmr::FrameAllocatorPool* GetFramePool() { + if (!FramePool) { + FramePool = new(GetGlobalPool()) pmr::FrameAllocatorPool(); } return FramePool; -} \ No newline at end of file +} +#endif // DLL_API \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/pmr/name.h b/engine/modules/engine/zlib/include/pmr/name.h index d9445e6..3063928 100644 --- a/engine/modules/engine/zlib/include/pmr/name.h +++ b/engine/modules/engine/zlib/include/pmr/name.h @@ -55,6 +55,12 @@ namespace pmr inline bool operator==(const CName& cname, const Name& name) { return cname.Hash() == name.Hash(); } + template + constexpr inline void hash_combine(size_t& seed, const T& v) noexcept + { + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } constexpr inline size_t string_hash(std::string_view str) noexcept { constexpr size_t fnv_offset_basis = 0xcbf29ce484222325; diff --git a/engine/modules/engine/zlib/include/pmr/name.inl b/engine/modules/engine/zlib/include/pmr/name.inl index 9a1fd9b..f99e3cd 100644 --- a/engine/modules/engine/zlib/include/pmr/name.inl +++ b/engine/modules/engine/zlib/include/pmr/name.inl @@ -6,7 +6,7 @@ namespace pmr { template static std::string_view MakePair(size_t id, T&& str); static NameTable_t& TableRef() { - static NameTable_t Table{GetMemPool()}; + static NameTable_t Table{GetGlobalPool()}; return Table; } }; diff --git a/engine/modules/engine/zlib/include/refl/detail/any.h b/engine/modules/engine/zlib/include/refl/detail/any.h index 2960111..5cc0dd3 100644 --- a/engine/modules/engine/zlib/include/refl/detail/any.h +++ b/engine/modules/engine/zlib/include/refl/detail/any.h @@ -32,5 +32,7 @@ namespace refl { public: operator bool()const { return cls && ptr; } bool Check(const UClass* parent) const; + template + T FindVtable(size_t name)const; }; } \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/detail/any.inl b/engine/modules/engine/zlib/include/refl/detail/any.inl index 78f9b53..efb9eea 100644 --- a/engine/modules/engine/zlib/include/refl/detail/any.inl +++ b/engine/modules/engine/zlib/include/refl/detail/any.inl @@ -11,4 +11,9 @@ namespace refl{ } return cls->IsChildOf(parent); } + template + inline T Any::FindVtable(size_t name) const + { + return (T)cls->vtable.Find(name); + } } \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/detail/uclass.h b/engine/modules/engine/zlib/include/refl/detail/uclass.h index f1c22f2..72b95c2 100644 --- a/engine/modules/engine/zlib/include/refl/detail/uclass.h +++ b/engine/modules/engine/zlib/include/refl/detail/uclass.h @@ -24,18 +24,70 @@ namespace refl { FIND_METHODS,//函数重载 特别是构造函数 }; struct vtable_uclass - { + { + struct Node { + size_t name; + void* method; + Node* next; + Node(size_t name, void* ptr) :name(name), method(ptr), next(nullptr) {} + Node* Insert(size_t name, void* ptr) { + Node* it = new Node(name, ptr); + next = it; + return it; + } + }; + Node* header{nullptr}; + operator bool() { return header; } + void Add(Name name, void* ptr) { + Add(name.Hash(), ptr); + } + void Add(size_t name, void* ptr) { + auto [bfind, it] = FindLast(name); + if (bfind) { + return; + } + Node* next = new Node(name, ptr); + Node** prev= it ? &(it->next) : &header; + *prev = next; + } + std::pair FindLast(size_t name) const{ + Node *prev = nullptr, *it = header; + while (it) { + if (it->name == name) { + return std::make_pair(true, it); + } + prev = it; + it = it->next; + } + return std::make_pair(false, prev); + } + void* Find(size_t name) const { + Node* it = header; + while (it) { + if (it->name == name) { + return it->method; + } + it = it->next; + } + return nullptr; + } //class - span(*GetFields)(const UClass*, EFieldFind find, Name name); + using GetFields_t = span(*)(const UClass*, EFieldFind find, Name name); + //class meta + using GetMeta_t = const UClass* (*)(Name); //function - span(*GetParams)(const UClass*); - //function - void (*Call)(const FieldPtr*, span ArgsList); - //meta - const UClass* (*GetMeta)(Name); + using GetParams_t = span(*)(const UClass*); + //function args + using Call_t = void (*)(const FieldPtr*, span ArgsList); //object - bool (*Construct)(void* ptr, const UClass* cls, span ArgsList); - void (*Destruct)(void*); + using Construct_t = bool (*)(void* ptr, const UClass* cls, span ArgsList); + using Destruct_t = void (*)(void*); + GetFields_t GetFields() const { return (GetFields_t) Find(string_hash("GetFields")); } + GetMeta_t GetMeta() const { return (GetMeta_t) Find(string_hash("GetMeta")); } + GetParams_t GetParams() const { return (GetParams_t) Find(string_hash("GetParams")); } + Call_t Call() const { return (Call_t) Find(string_hash("Call")); } + Construct_t Construct() const { return (Construct_t) Find(string_hash("Construct")); } + Destruct_t Destruct() const { return (Destruct_t) Find(string_hash("Destruct")); } }; class UClass { public: @@ -43,7 +95,7 @@ namespace refl { uint32_t size; uint32_t flag{0}; const UClass* parent; - vtable_uclass* vtable{nullptr}; + vtable_uclass vtable; UClass(const UClass*) = delete; UClass& operator=(const UClass*) = delete; public: diff --git a/engine/modules/engine/zlib/include/refl/detail/uclass.inl b/engine/modules/engine/zlib/include/refl/detail/uclass.inl index 52cbe76..54f2d32 100644 --- a/engine/modules/engine/zlib/include/refl/detail/uclass.inl +++ b/engine/modules/engine/zlib/include/refl/detail/uclass.inl @@ -24,9 +24,8 @@ namespace refl{ parent = &TypeInfo::StaticClass; } else { - vtable = new(MemPool)vtable_uclass(); - vtable->Construct = &UClass::Construct; - vtable->Destruct = &UClass::Destruct; + vtable.Add(string_hash("Construct"), (void*) &UClass::Construct); + vtable.Add(string_hash("Destruct"), (void*) &UClass::Destruct); } } }; @@ -44,15 +43,15 @@ namespace refl{ template struct TypeInfoImpl { using MyUClass = UClass_Auto; - inline static MyUClass StaticClass{}; + const inline static MyUClass StaticClass{}; }; template<> struct TypeInfoImpl { - inline static UClass StaticClass{ type_name().View(), 0 }; + const inline static UClass StaticClass{ type_name().View(), 0 }; }; template struct TypeInfoImpl { using MyUClass = UClass_Meta>; - inline static MyUClass StaticClass{}; + const inline static MyUClass StaticClass{}; }; } \ No newline at end of file diff --git a/engine/modules/render/vulkan/xmake.lua b/engine/modules/render/vulkan/xmake.lua index ca84eb4..48e41db 100644 --- a/engine/modules/render/vulkan/xmake.lua +++ b/engine/modules/render/vulkan/xmake.lua @@ -2,4 +2,4 @@ shared_module("vulkan","engine") add_includedirs("include/vulkan") add_headerfiles("include/**.h") add_files("src/**.cpp") - add_dependency("core", "asset", {public = true}) \ No newline at end of file + add_dependency("engine", {public = true}) \ No newline at end of file diff --git a/engine/modules/xmake.lua b/engine/modules/xmake.lua index 6b652f9..9aa4190 100644 --- a/engine/modules/xmake.lua +++ b/engine/modules/xmake.lua @@ -9,12 +9,16 @@ function header_component(name, owner, opt) end function static_component(name, owner, opt) target(owner) - add_deps(name, { public = opt and opt.public or true }) + add_deps(name) + add_defines("DLL_API_VALUE", {public = true}) + add_includedirs("include", {public = true}) target_end() target(name) set_kind("static") set_group("Engine/"..owner.."__comp") - add_includedirs("include", {public = true}) + add_rules("engine.api") + add_defines("DLL_API=") + add_includedirs("include") end function shared_module(name, owner, opt) target(name) diff --git a/engine/src/editor/api.cpp b/engine/src/editor/api.cpp new file mode 100644 index 0000000..faf0887 --- /dev/null +++ b/engine/src/editor/api.cpp @@ -0,0 +1,2 @@ +#include "api.h" +int editor_v; \ No newline at end of file diff --git a/engine/src/engine/api.cpp b/engine/src/engine/api.cpp new file mode 100644 index 0000000..25e5fc3 --- /dev/null +++ b/engine/src/engine/api.cpp @@ -0,0 +1,14 @@ +#include "api.h" +class ENGINE_API EngineModule : public api::IDynamicModule +{ +public: + void OnLoad(int argc, char** argv) override {}; + void OnUnload() override {}; + void InitMetaData(void) override { + mInfo.dependencies = { + {"core", "1.0.1", "static" }, + {"asset", "1.0.1", "static" }, + }; + }; +}; +IMPLEMENT_DYNAMIC_MODULE(ENGINE_API, EngineModule, engine) \ No newline at end of file diff --git a/engine/tools/make_plugin/src/main.cpp b/engine/tools/make_plugin/src/main.cpp index 81e90c3..0119315 100644 --- a/engine/tools/make_plugin/src/main.cpp +++ b/engine/tools/make_plugin/src/main.cpp @@ -48,7 +48,7 @@ void genPlugin(const char* file_path, ParseData& pd) { } else if (md.macro == PUBLIC_MODULE_DEPENDENCY) { for (auto& args : md.args) { - std::pmr::string upname{ args, FramePool}; + std::pmr::string upname{ args}; std::transform(upname.begin(), upname.end(), upname.begin(), std::toupper); info.dependencies.push_back({args, upname + "_VERSION", upname + "_KIND"}); } diff --git a/engine/xmake.lua b/engine/xmake.lua index d636009..efa148f 100644 --- a/engine/xmake.lua +++ b/engine/xmake.lua @@ -1,9 +1,18 @@ target("editor") - set_kind("static") + set_kind("shared") set_group("Engine") + add_rules("engine.api", {targets = {"dll", "editor"}}) + add_headerfiles("include/editor/*.h") + add_includedirs("include/editor") + add_files("src/editor/*.cpp") target("engine") - set_kind("static") + add_includedirs("include", {public = true}) + set_kind("shared") set_group("Engine") + add_rules("engine.api", {targets = {"dll", "engine"}}) + add_headerfiles("include/engine/*.h") + add_includedirs("include/engine") + add_files("src/engine/*.cpp") includes("xmake/xmake.lua") includes("3rdparty/xmake.lua") includes("tools/xmake.lua") diff --git a/engine/xmake/rule_tool/xmake.lua b/engine/xmake/rule_tool/xmake.lua index f7a8b96..34d1378 100644 --- a/engine/xmake/rule_tool/xmake.lua +++ b/engine/xmake/rule_tool/xmake.lua @@ -9,7 +9,11 @@ rule("engine.tool") end) rule("engine.api") on_load(function (target) - local api = string.upper(target:name()) .. "_API" - target:add("defines", api.."=__declspec(dllimport)", {interface=true}) - target:add("defines", api.."=__declspec(dllexport)", {public=false}) + local deps = target:extraconf("rules", "engine.api", "targets") + deps = deps or {target:name()} + for k,v in ipairs(deps) do + local api = string.upper(v) .. "_API" + target:add("defines", api.."=__declspec(dllimport)", {interface=true}) + target:add("defines", api.."=__declspec(dllexport)", {public=false}) + end end) \ No newline at end of file diff --git a/game/zworld/editor/main.cpp b/game/zworld/editor/main.cpp index 01c51f6..aeee66c 100644 --- a/game/zworld/editor/main.cpp +++ b/game/zworld/editor/main.cpp @@ -1,10 +1,7 @@ #include #include #include -#include "pmr/frame_allocator.h" -#include "pmr/name.h" -#include "refl/pch.h" -#include "module/module_manager.h" +#include "engine/api.h" void test(std::string_view str = "") { std::cout << "test " << str << std::endl; }