diff --git a/engine/src/engine/asset/asset_loader.cpp b/engine/src/engine/asset/asset_loader.cpp index a4c5f93..058ab03 100644 --- a/engine/src/engine/asset/asset_loader.cpp +++ b/engine/src/engine/asset/asset_loader.cpp @@ -20,6 +20,6 @@ namespace engineapi { meta["data"] = YAML::Text_Serialize(refl::Any{handle.res, handle->meta}); result.push_back(meta); } - FileManager::SaveTextFile(handle, YAML::Dump(result)); + //FileManager::SaveTextFile(handle, YAML::Dump(result)); } } diff --git a/engine/src/engine/asset/file_handle.cpp b/engine/src/engine/asset/file_handle.cpp new file mode 100644 index 0000000..51e0677 --- /dev/null +++ b/engine/src/engine/asset/file_handle.cpp @@ -0,0 +1,93 @@ +#include "file_handle.h" +#include +#define READ_DATA_SIZE 1024 +namespace engineapi { + FileHandle& FileHandle::Open(FILE_OP _op, bool is_binarry) + { + op = _op; + string file_path = RealPath(); + switch (op) + { + case engineapi::FILE_OP::READ: + { + vfile = std::ifstream(file_path, is_binarry ? std::ios::binary : 0); + if (!Reader().is_open()) { + return *this; + } + break; + } + case engineapi::FILE_OP::WRITE: + vfile = std::ofstream(file_path, is_binarry ? std::ios::binary : 0); + break; + case engineapi::FILE_OP::APPEND: + vfile = std::ofstream(file_path, 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(); + } + string FileHandle::ReadUntil(const string& token) + { + auto& fi = Reader(); + size_t cur = fi.tellg(); + fi.seekg(0, std::ios::end); + size_t size = (size_t)fi.tellg() - cur; + fi.seekg(cur); + size_t buffer_size = READ_DATA_SIZE; + string buffer; + char chunk[READ_DATA_SIZE]; + while (buffer_size < size) { + fi.read(chunk, READ_DATA_SIZE); + buffer.append(chunk, READ_DATA_SIZE); + size_t offset = buffer_size > READ_DATA_SIZE ? buffer_size - READ_DATA_SIZE - token.size() : 0; + size_t it = buffer.substr(offset).find(token); + if (it != std::string::npos) { + buffer_size = offset + it; + buffer.resize(buffer_size); + fi.seekg(cur + buffer_size + token.size()); + return buffer; + } + buffer_size += READ_DATA_SIZE; + } + return buffer; + } + vector FileHandle::ReadUntil(const vector& token) + { + auto& fi = Reader(); + size_t cur = fi.tellg(); + fi.seekg(0, std::ios::end); + size_t size = (size_t)fi.tellg() - cur; + fi.seekg(cur); + size_t buffer_size = READ_DATA_SIZE; + vector buffer(buffer_size); + while (buffer_size < size) { + fi.read(buffer.data(), READ_DATA_SIZE); + size_t offset = buffer_size > READ_DATA_SIZE ? buffer_size - READ_DATA_SIZE - token.size() : 0; + auto it = std::search(buffer.begin() + offset, buffer.end(), token.begin(), token.end()); + if (it != buffer.end()) { + buffer_size += it - buffer.end(); + buffer.resize(buffer_size); + fi.seekg(cur + buffer_size + token.size()); + return buffer; + } + buffer_size += READ_DATA_SIZE; + buffer.insert(buffer.end(), READ_DATA_SIZE, 0); + } + return buffer; + } + void FileHandle::Write(const char* data,size_t size) + { + Writer().write(data, size); + } +} diff --git a/engine/src/engine/asset/file_handle.h b/engine/src/engine/asset/file_handle.h new file mode 100644 index 0000000..4bb4ba1 --- /dev/null +++ b/engine/src/engine/asset/file_handle.h @@ -0,0 +1,65 @@ +#include "res/package_path.h" +#include +#include +#include +namespace engineapi { + 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}; + std::variant vfile{nullptr}; + public: + using PackagePath::PackagePath; + FileHandle(const PackagePath& path) : PackagePath(path){} + 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(); + string ReadUntil(const string& token); + vector ReadUntil(const vector& token); + void Write(const char* data, size_t size); + }; + template + inline T FileHandle::ReadLeft() + { + auto& fi = Reader(); + size_t cur = fi.tellg(); + fi.seekg(0, std::ios::end); + size_t size = (size_t)fi.tellg() - cur; + fi.seekg(cur); + T data; + data.resize(size, '\0'); + fi.read(data.data(), size); + // 检查实际读取的字节数 + size_t read = (size_t)fi.gcount(); + if (read != size) { + data.resize(read); + } + return data; + } +} \ No newline at end of file diff --git a/engine/src/engine/asset/file_manager.cpp b/engine/src/engine/asset/file_manager.cpp index ccea8a5..4fa9cae 100644 --- a/engine/src/engine/asset/file_manager.cpp +++ b/engine/src/engine/asset/file_manager.cpp @@ -26,80 +26,5 @@ namespace engineapi { path.append(pack_path.path.substr(name.size() + 1)); return path; } - FileFlag FileManager::LoadErrorFlag(const PackagePath& pack_path) - { - uint32_t flag = FindPathFlag(pack_path); - if (flag & FileFlag::File_Http) { - return FileFlag::File_Http; - } - zlog::info("Failed to load file: {}", pack_path.path); - return FileFlag::File_Not_Exist; - } - result FileManager::LoadTextFile(const PackagePath& pack_path) - { - ifstream file; - file.exceptions(ifstream::failbit | ifstream::badbit); - try - { - string path = RealPath(pack_path); - file.open(path); - stringstream stream; - stream << file.rdbuf(); - file.close(); - return stream.str(); - } - catch (ifstream::failure e) - { - return LoadErrorFlag(pack_path); - } - } - result,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path) - { - string path = RealPath(pack_path); - // ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区 - ifstream file(path, std::ios::ate | std::ios::binary); - if (!file.is_open()) { - return LoadErrorFlag(pack_path); - } - - // 使用读取位置来确定文件的大小并分配缓冲区 - size_t fileSize = (size_t)file.tellg(); - vector data(fileSize); - - // 返回文件开头,真正读取内容 - file.seekg(0); - file.read(data.data(), fileSize); - file.close(); - - return data; - } - result FileManager::LoadJsonFile(const PackagePath& pack_path) - { - string path = RealPath(pack_path); - std::ifstream f(path); - if (!f.is_open()) - { - return LoadErrorFlag(pack_path); - } - json data; - try - { - data = json::parse(f); - } - catch (json::exception& e) - { - zlog::error("Asset format error: {}", path); - string msg = e.what(); - zlog::error("Error detail: {}", msg); - return FileFlag::File_Error; - } - return data; - } - void FileManager::SaveTextFile(const PackagePath& pack_path,const string& value) - { - string path = RealPath(pack_path); - std::ofstream of(path); - of.write(value.data(), value.size()); - } } diff --git a/engine/src/engine/asset/file_manager.h b/engine/src/engine/asset/file_manager.h index 8d0e8cb..e972ca3 100644 --- a/engine/src/engine/asset/file_manager.h +++ b/engine/src/engine/asset/file_manager.h @@ -66,13 +66,5 @@ namespace engineapi public: //外界不应该使用绝对路径 static string RealPath(const PackagePath& pack_path); - - static FileFlag LoadErrorFlag(const PackagePath& pack_path); - - static result LoadTextFile(const PackagePath& pack_path); - static result, FileFlag> LoadBinaryFile(const PackagePath& pack_path); - static result LoadJsonFile(const PackagePath& pack_path); - - static void SaveTextFile(const PackagePath& pack_path, const string& value); }; } diff --git a/engine/src/engine/asset/res/package_path.h b/engine/src/engine/asset/res/package_path.h index e999283..6a72942 100644 --- a/engine/src/engine/asset/res/package_path.h +++ b/engine/src/engine/asset/res/package_path.h @@ -12,11 +12,12 @@ namespace engineapi using Ubpa::NameID; enum FileFlag : uint32_t { File_Default = 0, - File_Binary = 1 << 0, - File_Compress = 1 << 1, - File_Http = 1 << 2, - File_Not_Exist = 1 << 3, - File_Error = 1 << 4, + File_Success = 1 << 0, + File_Binary = 1 << 1, + File_Compress = 1 << 2, + File_Http = 1 << 3, + File_Not_Exist = 1 << 4, + File_Error = 1 << 5, }; struct PackagePath { string_view path; diff --git a/engine/src/engine/asset/resource_manager.cpp b/engine/src/engine/asset/resource_manager.cpp index d7af3c5..de8838e 100644 --- a/engine/src/engine/asset/resource_manager.cpp +++ b/engine/src/engine/asset/resource_manager.cpp @@ -1,5 +1,6 @@ #include "resource_manager.h" #include "file_manager.h" +#include "file_handle.h" #include "yaml/yaml.h" namespace engineapi { void ResourceManager::Init() @@ -60,15 +61,17 @@ namespace engineapi { MetaBundle ResourceManager::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 { - auto res_text = FileManager::LoadTextFile(path + ".meta"); - if (res_text) { - res = YAML::Text_Unserialize(res_text.value()); - } + string text = handle.ReadAll(); + res = YAML::Text_Unserialize(text); } if (!res) { return {}; @@ -77,12 +80,14 @@ namespace engineapi { } void ResourceManager::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 { string text = YAML::Text_Serialize(bundle); - FileManager::SaveTextFile(path + ".meta", text); + handle.Write(text.data(), text.size()); } } void ResourceManager::SaveDirtyFiles() @@ -104,9 +109,11 @@ namespace engineapi { constexpr const char* FileFlagName = "/engine/assets/file_flag.meta"; void ResourceManager::LoadFileFlag() { - auto res_text = FileManager::LoadTextFile(FileFlagName); - if (res_text) { - auto res = YAML::Text_Unserialize>(res_text.value()); + FileHandle handle(FileFlagName); + handle.Open(FILE_OP::READ); + if (handle) { + string text = handle.ReadAll(); + auto res = YAML::Text_Unserialize>(text); if (res) { for (auto it : res.value()) { mFileFlagTable.emplace(NameID(it.first), it); @@ -121,8 +128,10 @@ namespace engineapi { for (auto it : mFileFlagTable) { res.emplace(it.second); } + FileHandle handle(FileFlagName); + handle.Open(FILE_OP::WRITE); string text = YAML::Text_Serialize(res); - FileManager::SaveTextFile(FileFlagName, text); + handle.Write(text.data(), text.size()); } } diff --git a/engine/src/engine/asset/resource_manager.inl b/engine/src/engine/asset/resource_manager.inl index 09936c9..a887a8f 100644 --- a/engine/src/engine/asset/resource_manager.inl +++ b/engine/src/engine/asset/resource_manager.inl @@ -52,10 +52,13 @@ namespace engineapi { template inline FLoader& ResourceManager::RegisterLoader(Name ext, Args&& ...args) { - FLoader* ptr = new FLoader(std::forward(args)...); + auto& ptr = mFileLoader[ext]; + if (ptr) { + delete ptr; + } + ptr = new FLoader(std::forward(args)...); ptr->SetFileFlag(GetFileFlag(ext)); - mFileLoader[ext] = ptr; - return *ptr; + return *(FLoader*)ptr; } template inline RscHandle ResourceManager::Load(PackagePath path, bool reload_resource) diff --git a/engine/src/engine/vulkanapi/loader/vulkan_glsl_loader.cpp b/engine/src/engine/vulkanapi/loader/vulkan_glsl_loader.cpp index 454985d..1f45ac3 100644 --- a/engine/src/engine/vulkanapi/loader/vulkan_glsl_loader.cpp +++ b/engine/src/engine/vulkanapi/loader/vulkan_glsl_loader.cpp @@ -5,6 +5,7 @@ #include "render/asset/vertex.h" #include "vkmeta_vertex_gen.inl" #include +#include "asset/file_handle.h" using namespace engineapi; namespace vulkanapi { vk::ShaderStageFlagBits GetShaderType(string_view ext) @@ -40,24 +41,29 @@ namespace vulkanapi { auto set = compiler.get_decoration(ub.id, spv::Decoration::DecorationDescriptorSet); } } - ResourceBundle VulkanGlslLoader::LoadFile(PackagePath handle, const MetaBundle& meta) + ResourceBundle VulkanGlslLoader::LoadFile(PackagePath path, const MetaBundle& meta) { auto m = meta.FetchMeta(); auto program = m ? ResourceManager::GetSingleton().LoaderEmplaceResource(m->guid) : ResourceManager::GetSingleton().LoaderEmplaceResource(); + FileHandle handle(path + ".meta"); + if (!handle.Open(FILE_OP::READ, mFileFlag & FileFlag::File_Binary)) { + return program; + } if (mFileFlag & FileFlag::File_Binary) { - + vector data = handle.ReadAll(); + std::vector spirv(data.size() / 4); + std::memcpy(spirv.data(), data.data(), data.size()); + program->Load(spirv); + LoadShaderInfo(program->GetGuid(), spirv); } else { - auto res = FileManager::LoadTextFile(handle); - if (res) { - string glsl = res.value(); - auto shader_enum = GetShaderType(handle.GetExtension()); - auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName()); - if (spirv) { - program->Load(*spirv); - LoadShaderInfo(program->GetGuid(), *spirv); - } + string glsl = handle.ReadAll(); + auto shader_enum = GetShaderType(path.GetExtension()); + auto spirv = GlslToSpirv::spirv(glsl, shader_enum, path.GetFileName()); + if (spirv) { + program->Load(*spirv); + LoadShaderInfo(program->GetGuid(), *spirv); } } return program;