global singleton bugfix

This commit is contained in:
ouczbs 2024-10-22 21:52:43 +08:00
parent 9b1704246d
commit e7683d6e0e
37 changed files with 358 additions and 93 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@
build/
vsxmake*/
/tools
engine/3rdparty/

View File

@ -1 +1,2 @@
add_requires("spdlog", "lemon", "libsdl", "vulkansdk")
includes("*/xmake.lua")

View File

@ -0,0 +1,7 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout (location = 0) in vec4 vColor;
layout (location = 0) out vec4 oColor;
void main() {
oColor = vColor;
}

View File

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

View File

@ -0,0 +1,11 @@
#version 450
layout (location = 0) in vec3 iPos;
layout (location = 1) in vec2 iTex;
layout (location = 0) out vec4 vColor;
void main()
{
gl_Position = vec4(iPos.x, iPos.y, iTex.x, 1.0);
vColor = vec4(gl_Position.x, gl_Position.y, gl_Position.z, 1.0);
}

View File

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

View File

@ -4,6 +4,7 @@
#include "os/file_handle.h"
#include "archive/json.h"
namespace api {
SINGLETON_DEFINE(ResourceSystem)
using GenericPtr = ResourceSystem::GenericPtr;
using ResourceFileBlock = ResourceSystem::ResourceFileBlock;
class ResourceSystemImpl
@ -202,6 +203,7 @@ namespace api {
}
inline ResourceSystem::ResourceSystem()
{
SINGLETON_VAL();
impl = new(GlobalPool()) ResourceSystemImpl(this);
}
inline void api::ResourceSystem::Initialize()

View File

@ -1,7 +1,6 @@
#pragma once
#include "resource_system.h"
namespace api {
using refl::type_info;
class Asset : public Resource<Asset> {
public:
using Base = Resource<Asset>;
@ -16,7 +15,7 @@ namespace api {
{
if (h)
{
metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), refl::type_name<Asset>().View(), h->Meta()});
metadatas.emplace_back(SerializedMeta{ h.guid, h->Name(), type_name<Asset>().View(), h->Meta()});
}
}
}

View File

@ -4,6 +4,8 @@
#include <string>
namespace api
{
using refl::type_info;
using refl::type_name;
using pmr::Name;
using std::string_view;
using std::span;

View File

@ -47,8 +47,9 @@ namespace api {
template<typename Res>
using LoadResult = result<Res, ResourceLoadError>;
class ResourceSystemImpl;
class ASSET_API ResourceSystem : public ISystem<ResourceSystem>
class ASSET_API ResourceSystem : public ISystem
{
SINGLETON_API_PTR(ResourceSystem)
public:
struct ResourceFileBlock;
template<typename R>

View File

@ -1,16 +0,0 @@
#pragma once
template <typename T>
class Singleton{
protected:
inline static T* ms_Singleton = nullptr;
public:
explicit Singleton() {
ms_Singleton = static_cast<T*>(this);
}
~Singleton() {
ms_Singleton = nullptr;
}
static T* Ptr(void) {
return ms_Singleton;
}
};

View File

@ -10,6 +10,7 @@ namespace zlog {
}
}
namespace api {
SINGLETON_DEFINE(FileManager)
class FileManagerImpl
{
public:
@ -77,7 +78,7 @@ namespace api {
FileManagerImpl::FileManagerImpl()
{
Mount("exe", fs::GetExecutablePath());
Mount("engine", fs::GetWorkPath());
Mount("work", fs::GetWorkPath());
LoadFileMap();
}
FileManagerImpl::~FileManagerImpl()
@ -113,6 +114,7 @@ namespace api {
FileManager::FileManager()
{
impl = new(GlobalPool()) FileManagerImpl();
SINGLETON_VAL()
}
FileManager::~FileManager()
{

View File

@ -1,19 +1,5 @@
namespace api {
template <typename T>
class ISystem : public ISubSystem {
protected:
inline static T* ms_system = nullptr;
public:
explicit ISystem() {
ms_system = static_cast<T*>(this);
}
~ISystem() override{
ms_system = nullptr;
}
static constexpr T* Ptr(void) {
return ms_system;
}
};
using ISystem = ISubSystem;
template <typename ModuleClass>
struct ModuleRegistrantImpl;
struct IDynamicModule : public IModule {

View File

@ -1,12 +1,12 @@
#pragma once
#include "singleton.h"
#include "package_path.h"
namespace api
{
class FileManagerImpl;
class CORE_API FileManager : public Singleton<FileManager>
class CORE_API FileManager
{
FileManagerImpl* impl;
SINGLETON_API_PTR(FileManager)
public:
FileManager();
~FileManager();

View File

@ -1,7 +1,7 @@
#include "render/renderapi.h"
#include "render/module.h"
namespace api {
RenderAPI* API;
SINGLETON_DEFINE(RenderAPI)
IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render);
void RenderAPI::RenderView(FRenderView& view)
{
@ -18,13 +18,10 @@ namespace api {
}
RenderAPI::RenderAPI(RenderContext* ctx) : context(*ctx)
{
API = this;
SINGLETON_VAL();
}
RenderAPI::~RenderAPI()
{
delete& context;
}
RenderAPI* RenderAPI::Ptr() {
return API;
}
}

View File

@ -1,7 +1,9 @@
#include "render/window.h"
namespace api {
SINGLETON_DEFINE(Window)
inline Window::Window(CreatePFN createPFN, const Args& args, int width, int height) noexcept : mHeight(height), mWidth(width)
{
SINGLETON_VAL();
uint32_t windowFlags = args.windowFlags | SDL_WINDOW_SHOWN;
windowFlags |= args.resizeable ? SDL_WINDOW_RESIZABLE : 0;
windowFlags |= args.headless ? SDL_WINDOW_HIDDEN : 0;

View File

@ -15,5 +15,8 @@ namespace api {
RscHandle<Shader> GetShader() {
return mShader;
}
void SetShader(RscHandle<Shader> shader) {
mShader = shader;
}
};
};

View File

@ -21,5 +21,11 @@ namespace api {
RscHandle<T> GetFragHandle() {
return mFrag;
}
void SetVertHandle(RscHandle<ShaderProgram> vert) {
mVert = vert;
}
void SetFragHandle(RscHandle<ShaderProgram> frag) {
mFrag = frag;
}
};
};

View File

@ -1,5 +1,4 @@
#pragma once
#include "singleton.h"
#include "pmr/frame_allocator.h"
#include "render_context.h"
#include "graph/frame_graph.h"
@ -14,12 +13,12 @@ namespace api {
FrameGraph graph;
RenderAPI(RenderContext* ctx);
virtual ~RenderAPI();
SINGLETON_API_PTR(RenderAPI)
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());
}
void operator delete(void* p) {}
static RenderAPI* Ptr();
public:
virtual void Init() = 0;

View File

@ -0,0 +1,16 @@
#pragma once
#include "pmr/name.h"
#include <optional>
#include <shaderc/shaderc.h>
namespace api
{
using pmr::Name;
using std::optional;
using std::string_view;
class GlslToSpirv
{
public:
static shaderc_shader_kind GetShaderKind(Name name);
static optional<pmr::vector<uint32_t>> ToSpirv(const pmr::string& glsl, shaderc_shader_kind kind, string_view code_id = "unknown_shader");
};
}

View File

@ -1,9 +1,8 @@
#pragma once
#include <SDL.h>
#include "singleton.h"
#include "pmr/frame_allocator.h"
namespace api {
class RENDER_API Window : public Singleton<Window> {
class RENDER_API Window {
protected:
using CreatePFN = decltype(&SDL_CreateWindow);
int mWidth;
@ -15,6 +14,7 @@ namespace api {
bool resizeable = true;
bool headless = false;
};
SINGLETON_API_PTR(Window)
public:
void* operator new(size_t size) {
return ::operator new(size, GlobalPool());

View File

@ -1,8 +1,20 @@
#include "render/pass/demo_pass.h"
#include "render/asset/shader.h"
#include "render/asset/material.h"
#include "render/renderapi.h"
#include "asset/resource_system.h"
namespace api {
bool DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
{
static RscHandle<Shader> shader;
if (!shader) {
shader = ResourceSystem::Ptr()->LoadEmplaceResource<Shader>();
auto vert = ResourceSystem::Ptr()->Load<ShaderProgram>("/engine/assets/shader/simple.frag");
auto frag = ResourceSystem::Ptr()->Load<ShaderProgram>("/engine/assets/shader/simple.frag");
shader->SetVertHandle(vert);
shader->SetFragHandle(frag);
RenderAPI::Ptr()->LoadShader(*shader);
}
AttachmentDesc surface{};
surface.FromTexture(graph.mSurface);
surface.colorFormat = TinyImageFormat_B8G8R8A8_SRGB;

View File

@ -0,0 +1,39 @@
#include "render/tool/glsl_to_spirv.h"
#include <shaderc/shaderc.hpp>
#include "zlog.h"
namespace api
{
optional<pmr::vector<uint32_t>> GlslToSpirv::ToSpirv(const pmr::string& glsl, shaderc_shader_kind kind, string_view code_id)
{
optional<pmr::vector<uint32_t>> spirv_out{FramePool()};
{
shaderc::Compiler compiler;
shaderc::CompileOptions options;
options.SetOptimizationLevel(shaderc_optimization_level_performance);
options.SetTargetEnvironment(shaderc_target_env::shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3);
auto result = compiler.CompileGlslToSpv(glsl.data(), kind, code_id.data(), options);
if (result.GetCompilationStatus() != shaderc_compilation_status::shaderc_compilation_status_success) {
auto err_m = result.GetErrorMessage();
auto err_msg = err_m.c_str();
zlog::error("load spirv failed!!! {}", err_msg);
return spirv_out;
}
spirv_out = pmr::vector<uint32_t>{ result.cbegin(),result.cend() };
}
return spirv_out;
}
using pmr::string_hash;
shaderc_shader_kind GlslToSpirv::GetShaderKind(Name name)
{
switch (name.Hash())
{
case string_hash(".vert"): return shaderc_shader_kind::shaderc_vertex_shader;
case string_hash(".geom"): return shaderc_shader_kind::shaderc_geometry_shader;
case string_hash(".tese"): return shaderc_shader_kind::shaderc_tess_evaluation_shader;
case string_hash(".tesc"): return shaderc_shader_kind::shaderc_tess_control_shader;
case string_hash(".frag"): return shaderc_shader_kind::shaderc_fragment_shader;
default: return shaderc_shader_kind::shaderc_miss_shader;
}
}
}

View File

@ -2,6 +2,6 @@ static_component("render","engine")
add_includedirs("3rdparty", {public = true})
add_headerfiles("include/**.h", "include/**.inl", "impl/*.inl")
add_files("src/**.cpp")
add_deps("asset", "zlib", "core")
add_deps("asset", "zlib", "core","shaderc")
add_syslinks("user32", {public = true})
add_packages("lemon", "libsdl", {public = true})

View File

@ -0,0 +1,92 @@
#pragma once
#include <memory_resource>
#include <unordered_map>
namespace singleapi {
namespace pmr {
using std::pmr::unsynchronized_pool_resource;
using std::pmr::unordered_map;
};
struct MemoryInfo {
void* data;
bool isAlive;
static pmr::unsynchronized_pool_resource* Pool();
static void* Allocate(size_t size, size_t align) {
return Pool()->allocate(size, align);
}
};
class SINGLETON_API GlobalManager {
public:
MemoryInfo GetInstance(size_t hash, size_t size, size_t align = 8) {
auto it = instances.find(hash);
if (it == instances.end()) {
void* data = MemoryInfo::Allocate(size, align);
instances.emplace(hash, MemoryInfo{data, true});
return MemoryInfo{ data, false };
}
bool isAlive = it->second.isAlive;
it->second.isAlive = true;
return MemoryInfo{ it->second.data, isAlive };
}
void* KillInstance(size_t hash) {
auto it = instances.find(hash);
if (it != instances.end()) {
it->second.isAlive = false;
}
return nullptr;
}
GlobalManager(pmr::unsynchronized_pool_resource* pool) : instances{pool} {}
~GlobalManager() {}
static GlobalManager* Ptr();
private:
pmr::unordered_map<size_t, MemoryInfo> instances;
};
}
template <typename T, size_t hash = 0>
class UniquePtr {
protected:
inline static T* ms_Singleton = nullptr;
public:
template<typename... Args>
UniquePtr(Args&&... args) {
using namespace singleapi;
MemoryInfo info{};
if constexpr (hash == 0) {
size_t tHash = typeid(T).hash_code();
info = GlobalManager::Ptr()->GetInstance(tHash, sizeof(T));
}
else {
info = GlobalManager::Ptr()->GetInstance(hash, sizeof(T));
}
if (info.isAlive) {
ms_Singleton = (T*)info.data;
}
else {
ms_Singleton = new(info.data)T(std::forward<Args>(args)...);
}
}
~UniquePtr() {
using namespace singleapi;
if (ms_Singleton) {
ms_Singleton->~T();
}
if constexpr (hash == 0) {
size_t tHash = typeid(T).hash_code();
ms_Singleton = (T*)GlobalManager::Ptr()->KillInstance(tHash);
}
else {
ms_Singleton = (T*)GlobalManager::Ptr()->KillInstance(hash);
}
}
static T* Ptr(void) {
return ms_Singleton;
}
};
#define SINGLETON_API_PTR(T) \
protected:\
static T* ms_Singleton;\
public:\
static T* Ptr(void);
#define SINGLETON_DEFINE(T) T* T::ms_Singleton = nullptr;\
T* T::Ptr(){ return ms_Singleton; }
#define SINGLETON_VAL() ms_Singleton = this;

View File

@ -0,0 +1,13 @@
#include "singleton.h"
namespace singleapi {
pmr::unsynchronized_pool_resource* MemoryInfo::Pool() {
static pmr::unsynchronized_pool_resource pool;
return &pool;
}
GlobalManager* GlobalManager::Ptr()
{
static GlobalManager globalManager{ MemoryInfo::Pool()};
return &globalManager;
}
}

View File

@ -0,0 +1,7 @@
target("singleton")
set_kind("shared")
set_group("Engine/engine__comp")
add_rules("engine.api")
add_includedirs("include", {public = true})
add_headerfiles("include/*.h")
add_files("src/*.cpp")

View File

@ -1,21 +1,37 @@
#pragma once
//全局生命周期,不回收内存
ZLIB_API extern pmr::FrameAllocatorPool* GlobalPool();
//局部生命周期,每帧回收内存
ZLIB_API extern pmr::FrameAllocatorPool* FramePool();
#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();
}
extern void* operator new(std::size_t size);
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;
return &globalPool;
}
ZLIB_API inline pmr::FrameAllocatorPool* FramePool() {
static pmr::FrameAllocatorPool framePool;
return &framePool;
}
struct MemDetail {
int count{ 0 };
int new_count{ 0 };

View File

@ -7,7 +7,6 @@ namespace pmr
using table = std::pmr::unordered_map<T1, T2, Hasher>;
using std::pmr::string;
static consteval inline size_t InvalidValue() noexcept { return static_cast<size_t>(-1); }
constexpr inline size_t string_hash(std::string_view str) noexcept;
struct Name {
private:
size_t hash;
@ -61,22 +60,6 @@ namespace pmr
std::hash<T> 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;
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;
}
consteval static CName FName(std::string_view view) { return CName{ view }; };
}
namespace std {

View File

@ -1,13 +1,9 @@
namespace pmr {
using NameTable_t = table<size_t,const string>;
ZLIB_API extern NameTable_t& TableRef();
#ifdef ZLIB_API_VAL
ZLIB_API inline NameTable_t& TableRef() {
static NameTable_t Table;
return Table;
inline NameTable_t& TableRef() {
static UniquePtr<NameTable_t, string_hash("pmr::nametable")> Table;
return *Table.Ptr();
}
#endif // ZLIB_API_VAL
struct NameTable {
static const string& Find(size_t id);
template<typename T>

View File

@ -40,11 +40,9 @@ namespace refl {
}
};
ZLIB_API extern table<Name, const UClass*> ClassTable;
#ifdef ZLIB_API_VAL
ZLIB_API inline table<Name, const UClass*> ClassTable;
#endif // ZLIB_API_VAL
inline UniquePtr<table<Name, const UClass*>, string_hash("refl::ClassTable")> ClassTablePtr;
inline const UClass* find_info(Name name) {
auto& ClassTable = *ClassTablePtr.Ptr();
if (auto it = ClassTable.find(name); it != ClassTable.end()) {
return it->second;
}
@ -68,6 +66,7 @@ namespace refl {
else {
cls = new(GlobalPool()) UClass_Auto<T>{};
}
auto& ClassTable = *ClassTablePtr.Ptr();
ClassTable[name.View()] = cls;
return cls;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "render/asset/shader.h"
#include "asset/resource_system.h"
#include "vkn/vulkan_api.h"
namespace vkn {
class vkShaderProgram : public api::ShaderProgram {
private:
VkShaderModule mPtr;
public:
VkShaderModule Ptr() {
return mPtr;
}
void Load(const pmr::vector<uint32_t>& spirv);
};
class VulkanGlslLoader : public api::IFileLoader
{
inline static table<Guid, void*> ShaderTable;
public:
static void Init();
api::ResourceBundle LoadFile(api::PackagePath handle, const api::MetaBundle& meta) override;
};
}

View File

@ -28,7 +28,6 @@ namespace vkn {
table<FramebufferKey, VkFramebuffer> FramebufferCache;
public:
VulkanAPI();
void Init() override;
void Shutdown() override;

View File

@ -0,0 +1,51 @@
#include "vkn/loader/vulkan_glsl_loader.h"
#include "vkn/vulkan_api.h"
#include "vkn/wrapper/device.h"
#include "render/tool/glsl_to_spirv.h"
#include "render/asset/vertex.h"
#include "os/file_handle.h"
using namespace api;
namespace vkn {
void VulkanGlslLoader::Init()
{
//REGISTER_META_TABLE(PosVertex);
//REGISTER_META_TABLE(TexVertex);
//REGISTER_META_TABLE(BoneVertex);
ResourceSystem::Ptr()->RegisterLoader<VulkanGlslLoader>(".geom");
ResourceSystem::Ptr()->RegisterLoader<VulkanGlslLoader>(".frag");
ResourceSystem::Ptr()->RegisterLoader<VulkanGlslLoader>(".vert");
}
ResourceBundle VulkanGlslLoader::LoadFile(PackagePath path, const MetaBundle& meta)
{
auto m = meta.FetchMeta<ShaderProgram>();
auto program = m ? ResourceSystem::Ptr()->LoadEmplaceResource<vkShaderProgram>(m->guid)
: ResourceSystem::Ptr()->LoadEmplaceResource<vkShaderProgram>();
FileHandle handle(path);
if (!handle.Open(FILE_OP::READ, mFileFlag & FileFlag::File_Binary)) {
return program;
}
if (mFileFlag & FileFlag::File_Binary) {
pmr::vector<char> data = handle.ReadAll();
pmr::vector<uint32_t> spirv(data.size() / 4);
std::memcpy(spirv.data(), data.data(), data.size());
program->Load(spirv);
//LoadShaderInfo(program->GetGuid(), spirv);
}
else {
pmr::string glsl = handle.ReadAll<pmr::string>();
auto shader_kind = GlslToSpirv::GetShaderKind(path.GetExtension().ToStringView());
auto spirv = GlslToSpirv::ToSpirv(glsl, shader_kind, path.GetFileName());
if (spirv) {
program->Load(*spirv);
//LoadShaderInfo(program->GetGuid(), *spirv);
}
}
return program;
}
void vkShaderProgram::Load(const pmr::vector<uint32_t>& spirv)
{
VulkanAPI* API = VulkanAPI::Ptr();
mPtr = API->GetBackend().GetDevice().CreateShaderModule(spirv);
}
}

View File

@ -1,8 +1,10 @@
#include "vkn/module.h"
#include "vkn/loader/vulkan_glsl_loader.h"
#include "pmr/frame_allocator.h"
using namespace vkn;
void VulkanModule::OnLoad(int argc, char** argv)
{
VulkanGlslLoader::Init();
}
void VulkanModule::OnUnload()

View File

@ -7,6 +7,7 @@ function header_component(name, owner, opt)
set_group("Engine/"..owner.."__comp")
add_rules("engine.api")
add_includedirs("include", {public = true})
add_deps("singleton")
end
function static_component(name, owner, opt)
target(owner)
@ -18,6 +19,7 @@ function static_component(name, owner, opt)
add_rules("engine.api")
add_includedirs("include", {public = true})
add_includedirs("impl")
add_deps("singleton")
end
function shared_module(name, owner, opt)
target(name)

View File

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