rebuild file_manager
This commit is contained in:
parent
b67411cb43
commit
9d09dee27f
Binary file not shown.
Binary file not shown.
@ -1,20 +0,0 @@
|
||||
@echo off
|
||||
setlocal EnableDelayedExpansion
|
||||
set /p=<nul>exec.bat
|
||||
set destPath=%2cpp/
|
||||
ECHO @echo on >>exec.bat
|
||||
for %%i in (*.vs.glsl) do (
|
||||
set "s=%%i"
|
||||
echo !s:vs.glsl=vert.spv!
|
||||
set /p="glslc -fshader-stage=vertex %%i -o !s:vs.glsl=vert.spv!"<nul >> exec.bat
|
||||
ECHO.>> exec.bat
|
||||
)
|
||||
for %%i in (*.ps.glsl) do (
|
||||
set "s=%%i"
|
||||
echo !s:ps.glsl=frag.spv!
|
||||
set /p="glslc -fshader-stage=fragment %%i -o !s:ps.glsl=frag.spv!"<nul >> exec.bat
|
||||
ECHO.>> exec.bat
|
||||
)
|
||||
ECHO @echo off>> exec.bat
|
||||
call exec.bat
|
||||
del exec.bat
|
||||
Binary file not shown.
@ -1,8 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main() {
|
||||
outColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
// 顶点位置输入变量
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texture;
|
||||
layout (location = 2) in vec3 normal;
|
||||
@ -9,8 +8,6 @@ layout (location = 3) in vec3 tangent;
|
||||
layout (location = 4) in vec4 weights;
|
||||
layout (location = 5) in uvec4 bones;
|
||||
|
||||
|
||||
// 顶点位置输出变量
|
||||
//out vec4 outPosition;
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
|
||||
Binary file not shown.
@ -1,27 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
// 顶点位置输入变量
|
||||
layout (location = 0) in vec3 position;
|
||||
layout (location = 1) in vec2 texture;
|
||||
layout (location = 2) in vec3 normal;
|
||||
layout (location = 3) in vec3 tangent;
|
||||
layout (location = 4) in vec4 weights;
|
||||
layout (location = 5) in uvec4 bones;
|
||||
|
||||
|
||||
// 顶点位置输出变量
|
||||
//out vec4 outPosition;
|
||||
out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(0.0, -0.5),
|
||||
vec2(0.5, 0.5),
|
||||
vec2(-0.5, 0.5)
|
||||
);
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||
}
|
||||
12
engine/src/engine/asset/asset.cpp
Normal file
12
engine/src/engine/asset/asset.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "assert.h"
|
||||
#include "render/asset/shader.h"
|
||||
#include "resource_manager.h"
|
||||
namespace engineapi {
|
||||
MetaBundle ResourceManager::GetVisitMeta(const ResourceBundle& bundle)
|
||||
{
|
||||
MetaBundle new_meta = MetaBundle{};
|
||||
for (auto& elem : bundle.GetAll())
|
||||
std::visit([&](auto& handle) { new_meta.Add(handle); }, elem);
|
||||
return new_meta;
|
||||
}
|
||||
}
|
||||
@ -12,34 +12,53 @@ namespace engineapi {
|
||||
{
|
||||
|
||||
}
|
||||
string FileManager::LoadTextFile(const string& path)
|
||||
string FileManager::real_path(const PackagePath& pack_path)
|
||||
{
|
||||
string_view name = pack_path.ParsePackage();
|
||||
string_view pre_path = FindMountPath(name);
|
||||
if (name.empty() || pre_path.empty()) {
|
||||
return string(pack_path.path);
|
||||
}
|
||||
string path;
|
||||
path.reserve(pre_path.size() + pack_path.size() - name.size() - 1);
|
||||
path.append(pre_path);
|
||||
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<string, FileFlag> FileManager::LoadTextFile(const PackagePath& pack_path)
|
||||
{
|
||||
string text = "";
|
||||
ifstream file;
|
||||
file.exceptions(ifstream::failbit | ifstream::badbit);
|
||||
|
||||
try
|
||||
{
|
||||
string path = real_path(pack_path);
|
||||
file.open(path);
|
||||
stringstream stream;
|
||||
stream << file.rdbuf();
|
||||
file.close();
|
||||
text = stream.str();
|
||||
return stream.str();
|
||||
}
|
||||
catch (ifstream::failure e)
|
||||
{
|
||||
zlog::info("Failed to load text file: {}", path);
|
||||
return LoadErrorFlag(pack_path);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
vector<char> FileManager::LoadBinaryFile(const string& path)
|
||||
result<vector<char>,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path)
|
||||
{
|
||||
string path = real_path(pack_path);
|
||||
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
|
||||
ifstream file(path, std::ios::ate | std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
zlog::info("Failed to load binary file: {}", path);
|
||||
return vector<char>();
|
||||
return LoadErrorFlag(pack_path);
|
||||
}
|
||||
|
||||
// 使用读取位置来确定文件的大小并分配缓冲区
|
||||
@ -53,13 +72,13 @@ namespace engineapi {
|
||||
|
||||
return data;
|
||||
}
|
||||
json FileManager::LoadJsonFile(const string& path)
|
||||
result<json, FileFlag> FileManager::LoadJsonFile(const PackagePath& pack_path)
|
||||
{
|
||||
string path = real_path(pack_path);
|
||||
std::ifstream f(path);
|
||||
if (!f.is_open())
|
||||
{
|
||||
zlog::error("Load asset failed: {}", path);
|
||||
return NULL;
|
||||
return LoadErrorFlag(pack_path);
|
||||
}
|
||||
json data;
|
||||
try
|
||||
@ -71,8 +90,15 @@ namespace engineapi {
|
||||
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 = real_path(pack_path);
|
||||
std::ofstream of(path);
|
||||
of.write(value.data(), value.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,27 @@
|
||||
#pragma once
|
||||
#include "asset.h"
|
||||
#include "singleton.h"
|
||||
#include "meta/result.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
namespace engineapi
|
||||
{
|
||||
using json = nlohmann::json;
|
||||
using meta::result;
|
||||
class FileManager : public ISingleton<FileManager>
|
||||
{
|
||||
public:
|
||||
//占位符浪费了四个字节
|
||||
struct FileControlBlock {
|
||||
uint32_t flag;
|
||||
string path;
|
||||
string addr;
|
||||
};
|
||||
public:
|
||||
void Init() override;
|
||||
void Shutdown() override;
|
||||
public:
|
||||
static void Mount(const string& name, const string& path) {
|
||||
MountMap.emplace(NameID(name), std::make_pair(name,path));
|
||||
MountMap.emplace(NameID(name), std::make_pair(name, path));
|
||||
}
|
||||
static std::pair<string, string> FindMount(NameID id) {
|
||||
auto it = MountMap.find(id);
|
||||
@ -21,18 +30,48 @@ namespace engineapi
|
||||
}
|
||||
return {};
|
||||
}
|
||||
static string FindMountName(NameID id) {
|
||||
static string_view FindMountName(NameID id) {
|
||||
auto pair = FindMount(id);
|
||||
return pair.first;
|
||||
}
|
||||
static string FindMountPath(NameID id) {
|
||||
static string_view FindMountPath(NameID id) {
|
||||
auto pair = FindMount(id);
|
||||
return pair.second;
|
||||
}
|
||||
static string_view FindPathView(const string_view& name) {
|
||||
auto it = FileMap.find(name);
|
||||
if (it != FileMap.end()) {
|
||||
return it->second.path;
|
||||
}
|
||||
auto res = FileMap.emplace(name, FileControlBlock{ FileFlag::File_Default, string(name)});
|
||||
return res.first->second.path;
|
||||
}
|
||||
static uint32_t FindPathFlag(const PackagePath& pack_path) {
|
||||
auto it = FileMap.find(pack_path.path);
|
||||
if (it == FileMap.end()) {
|
||||
return FileFlag::File_Not_Exist;
|
||||
}
|
||||
return it->second.flag;
|
||||
}
|
||||
static result<FileControlBlock, FileFlag> FindPathBlock(const PackagePath& pack_path) {
|
||||
auto it = FileMap.find(pack_path.path);
|
||||
if (it == FileMap.end()) {
|
||||
return FileFlag::File_Not_Exist;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
private:
|
||||
inline static table<NameID, std::pair<string, string>> MountMap;
|
||||
inline static table<NameID, FileControlBlock> FileMap;
|
||||
//外界不应该使用绝对路径
|
||||
static string real_path(const PackagePath& pack_path);
|
||||
public:
|
||||
static string LoadTextFile(const string& path);
|
||||
static vector<char> LoadBinaryFile(const string& path);
|
||||
static json LoadJsonFile(const string& path);
|
||||
static FileFlag LoadErrorFlag(const PackagePath& pack_path);
|
||||
|
||||
static result<string, FileFlag> LoadTextFile(const PackagePath& pack_path);
|
||||
static result<vector<char>, FileFlag> LoadBinaryFile(const PackagePath& pack_path);
|
||||
static result<json, FileFlag> LoadJsonFile(const PackagePath& pack_path);
|
||||
|
||||
static void SaveTextFile(const PackagePath& pack_path, const string& value);
|
||||
};
|
||||
}
|
||||
|
||||
@ -3,5 +3,12 @@
|
||||
|
||||
namespace engineapi
|
||||
{
|
||||
|
||||
bool MetaBundle::operator==(const MetaBundle& other)const
|
||||
{
|
||||
return metadatas == other.metadatas;
|
||||
}
|
||||
bool MetaBundle::operator!=(const MetaBundle& other)const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,9 @@ namespace engineapi
|
||||
string t_hash{};
|
||||
UPROPERTY({})
|
||||
string metadata;
|
||||
bool operator==(const SerializedMeta& other)const{
|
||||
return guid == other.guid && name == other.name && t_hash == other.t_hash && metadata == other.metadata;
|
||||
}
|
||||
};
|
||||
struct ResourceBundle;
|
||||
struct MetaBundle
|
||||
@ -25,6 +28,10 @@ namespace engineapi
|
||||
|
||||
template<typename T>
|
||||
const SerializedMeta* FetchMeta() const;
|
||||
template<typename T>
|
||||
void Add(RscHandle<T>);
|
||||
bool operator==(const MetaBundle& other)const;
|
||||
bool operator!=(const MetaBundle& other)const;
|
||||
};
|
||||
}
|
||||
#include "meta_bundle.inl"
|
||||
|
||||
@ -12,4 +12,12 @@ namespace engineapi
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
template<typename T>
|
||||
void MetaBundle::Add(RscHandle<T> h)
|
||||
{
|
||||
if (h)
|
||||
{
|
||||
metadatas.emplace_back(SerializedMeta{ h.guid, string{h->Name()}, string{type_name<T>().View()}});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,21 @@
|
||||
#include "package_path.h"
|
||||
#include "asset/file_manager.h"
|
||||
namespace engineapi {
|
||||
PackagePath PackagePath::ToSuffixPath(const string_view& suffix)
|
||||
PackagePath PackagePath::ToSuffixPath(const string_view& suffix)const
|
||||
{
|
||||
if (CheckPackage()) {
|
||||
return { FileManager::FindMountName(name) + string(suffix) , path};
|
||||
}
|
||||
return *this;
|
||||
string_view name = ParsePackage();
|
||||
if(name.empty() || suffix.empty())
|
||||
return *this;
|
||||
string suffixPath;
|
||||
suffixPath.reserve(path.size() + suffix.size());
|
||||
suffixPath.append(name);
|
||||
suffixPath.append(suffix);
|
||||
suffixPath.append(path.substr(name.size()));
|
||||
return PackagePath{FileManager::FindPathView(suffixPath)};
|
||||
}
|
||||
string PackagePath::AbsolutePath()
|
||||
PackagePath PackagePath::SafePath()const
|
||||
{
|
||||
if (CheckPackage()) {
|
||||
return FileManager::FindMountPath(name) + string(path);
|
||||
}
|
||||
return string(path);
|
||||
return PackagePath{ FileManager::FindPathView(path) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,48 +10,49 @@ namespace engineapi
|
||||
using zstd::hash_table;
|
||||
using Ubpa::Name;
|
||||
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,
|
||||
};
|
||||
struct PackagePath {
|
||||
NameID name;
|
||||
string_view path;
|
||||
PackagePath(const string& name,const string_view& path) : name(name), path(path) {}
|
||||
PackagePath() {};
|
||||
PackagePath(const char* path) : path(path) {}
|
||||
PackagePath(const string_view& path) : path(path) {}
|
||||
PackagePath(const string& path) : path(StringView(path)) {};
|
||||
PackagePath(const string&& path) : path(path) {}
|
||||
bool CheckPackage() {
|
||||
if (name.Valid()) {
|
||||
return true;
|
||||
}
|
||||
size_t size() const{
|
||||
return path.size();
|
||||
}
|
||||
string operator+(const char* suffix) const {
|
||||
return string(path) + suffix;
|
||||
}
|
||||
string_view ParsePackage()const {
|
||||
string_view name;
|
||||
if (path[0] == '/') {
|
||||
size_t pos = path.find('/', 1);
|
||||
if (pos != string::npos) {
|
||||
name = path.substr(1, pos - 1);
|
||||
path = path.substr(pos);
|
||||
return true;
|
||||
return path.substr(1, pos - 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return name;
|
||||
}
|
||||
Name GetExtension() {
|
||||
string_view GetFileName()const {
|
||||
size_t pos = path.rfind('/');
|
||||
if (pos != std::string::npos)
|
||||
return path.substr(pos + 1);
|
||||
return "";
|
||||
}
|
||||
Name GetExtension() const{
|
||||
size_t pos = path.rfind('.');
|
||||
if (pos != std::string::npos)
|
||||
return path.substr(pos);
|
||||
return "";
|
||||
}
|
||||
PackagePath ToSuffixPath(const string_view& suffix);
|
||||
string AbsolutePath();
|
||||
static string AbsolutePath(string_view path) {
|
||||
return PackagePath(path).AbsolutePath();
|
||||
};
|
||||
static string_view StringView(const string& str) {
|
||||
NameID id = NameID(str);
|
||||
auto it = StringTable.find(id);
|
||||
if (it == StringTable.end()) {
|
||||
it = StringTable.emplace_hint(it, id, str);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
private:
|
||||
inline static table<NameID, string> StringTable;
|
||||
PackagePath ToSuffixPath(const string_view& suffix)const;
|
||||
PackagePath SafePath()const;
|
||||
};
|
||||
}
|
||||
@ -12,6 +12,7 @@ namespace engineapi
|
||||
// will reshuffle vector and invalidate span, but you shouldn't be accessing vector directly anyway so this is ok
|
||||
template<typename T> void Add(RscHandle<T> handle);
|
||||
template<typename T> RscHandle<T> Get() const; // get a resource from the bundle
|
||||
span<const GenericResourceHandle> GetAll() const; // gets absolutely all resources
|
||||
private:
|
||||
struct sub_array { short index = 0, count = 0; };
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#include "resource_bundle.h"
|
||||
#pragma once
|
||||
#include "resource_bundle.h"
|
||||
namespace engineapi
|
||||
{
|
||||
template<typename Res>
|
||||
@ -25,6 +25,11 @@ namespace engineapi
|
||||
for (auto& elem : span<sub_array>{ &sub_arr + 1, subarrays.data() + subarrays.size() })
|
||||
++elem.index;
|
||||
}
|
||||
inline span<const GenericResourceHandle> ResourceBundle::GetAll() const
|
||||
{
|
||||
return span<const GenericResourceHandle>(handles);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline RscHandle<T> engineapi::ResourceBundle::Get() const
|
||||
{
|
||||
|
||||
@ -11,8 +11,12 @@ namespace engineapi {
|
||||
|
||||
RscHandle<Res> GetHandle() const { return mHandle; }
|
||||
Resource() = default;
|
||||
|
||||
std::string_view Name() const { return mName; }
|
||||
void Name(std::string_view n) { mName = n; }
|
||||
private:
|
||||
RscHandle<Res> mHandle;
|
||||
std::string mName;
|
||||
friend class RscHandle<Res>;
|
||||
};
|
||||
using Resources = std::tuple<
|
||||
|
||||
@ -14,9 +14,14 @@ namespace engineapi
|
||||
template<typename T>
|
||||
constexpr RscHandle(const RscHandle<T>& other) noexcept : guid{ other.guid }, res(other.res) {};
|
||||
constexpr RscHandle(const Guid& guid, Res* res) noexcept : guid{ guid }, res(res) { ((Resource<Res>*)res)->mHandle = *this; }
|
||||
void init();
|
||||
Res* operator->() { if (!res && guid) init(); return (Res*)res; }
|
||||
Res& operator*() { if (!res && guid) init(); return *(Res*)res; }
|
||||
void Init();
|
||||
void Clear(){ res = nullptr; };
|
||||
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; }
|
||||
};
|
||||
|
||||
struct GenericResourceHandle
|
||||
|
||||
@ -5,12 +5,15 @@ namespace engineapi {
|
||||
void ResourceManager::Init()
|
||||
{
|
||||
mResourceTable = detail::ResourceHelper::GenResourceTables();
|
||||
LoadFileFlag();
|
||||
}
|
||||
void ResourceManager::Shutdown()
|
||||
{
|
||||
constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources();
|
||||
for (auto& elem : release_tables)
|
||||
elem(this);
|
||||
SaveFileFlag();
|
||||
SaveDirtyFiles();
|
||||
}
|
||||
IFileLoader* ResourceManager::GetLoader(Name extension)
|
||||
{
|
||||
@ -19,23 +22,99 @@ namespace engineapi {
|
||||
return nullptr;
|
||||
return itr->second;
|
||||
}
|
||||
LoadResult<ResourceBundle> ResourceManager::Load(PackagePath path, bool reload_resource)
|
||||
ResourceBundle& ResourceManager::Load(PackagePath path, bool reload_resource)
|
||||
{
|
||||
auto ext = path.GetExtension();
|
||||
auto* loader = GetLoader(ext);
|
||||
auto it = mFileTable.find(path.path);
|
||||
if (it != mFileTable.end()) {
|
||||
if (!reload_resource) {
|
||||
return it->second.bundle;
|
||||
}
|
||||
}
|
||||
Name ext = path.GetExtension();
|
||||
IFileLoader* loader = GetLoader(ext);
|
||||
MetaBundle meta = GetMeta(path);
|
||||
return loader->LoadFile(path, meta);
|
||||
ResourceBundle bundle = loader->LoadFile(path, meta);
|
||||
MetaBundle new_meta = GetVisitMeta(bundle);
|
||||
bool is_dirty_meta = meta != new_meta;
|
||||
mFileTable[path.path] = {bundle, path.SafePath(), false, is_dirty_meta};
|
||||
auto& res = mFileTable[path.path];
|
||||
for (auto& elem : bundle.GetAll()) {
|
||||
std::visit([&](auto& handle) {
|
||||
using T = std::decay_t<decltype(*handle)>;
|
||||
GetControlBlock<T>(handle)->file = &res;
|
||||
}, elem);
|
||||
}
|
||||
if (is_dirty_meta) {
|
||||
mDirtyBlocks.push_back(&res);
|
||||
}
|
||||
return res.bundle;
|
||||
}
|
||||
|
||||
MetaBundle ResourceManager::GetMeta(PackagePath path)
|
||||
{
|
||||
string text = FileManager::LoadTextFile(path.AbsolutePath() + ".meta");
|
||||
auto res = YAML::Text_Unserialize<MetaBundle>(text);
|
||||
if (res) {
|
||||
return res.value();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
meta::result<MetaBundle, YAML::SerializeError> res;
|
||||
if (mFileFlag & FileFlag::File_Binary) {
|
||||
|
||||
}
|
||||
else {
|
||||
auto res_text = FileManager::LoadTextFile(path + ".meta");
|
||||
if (res_text) {
|
||||
res = YAML::Text_Unserialize<MetaBundle>(res_text.value());
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
return {};
|
||||
}
|
||||
return res.value();
|
||||
}
|
||||
void ResourceManager::SaveMeta(PackagePath path, const MetaBundle& bundle)
|
||||
{
|
||||
if (mFileFlag & FileFlag::File_Binary) {
|
||||
|
||||
}
|
||||
else {
|
||||
string text = YAML::Text_Serialize(bundle);
|
||||
FileManager::SaveTextFile(path, text);
|
||||
}
|
||||
}
|
||||
void ResourceManager::SaveDirtyFiles()
|
||||
{
|
||||
for (auto block : mDirtyBlocks) {
|
||||
if (block->is_meta_dirty) {
|
||||
block->is_meta_dirty = false;
|
||||
MetaBundle new_meta = GetVisitMeta(block->bundle);
|
||||
SaveMeta(block->path, new_meta);
|
||||
}
|
||||
if (block->is_dirty) {
|
||||
block->is_dirty = false;
|
||||
auto loader = GetLoader(block->path.GetExtension());
|
||||
loader->SaveFile(block->path, block->bundle);
|
||||
}
|
||||
}
|
||||
mDirtyBlocks.clear();
|
||||
}
|
||||
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<table<string, uint32_t>>(res_text.value());
|
||||
if (res) {
|
||||
for (auto it : res.value()) {
|
||||
mFileFlagTable.emplace(NameID(it.first), it);
|
||||
}
|
||||
mFileFlag = GetFileFlag(".meta");
|
||||
}
|
||||
}
|
||||
}
|
||||
void ResourceManager::SaveFileFlag()
|
||||
{
|
||||
table<string, uint32_t> res;
|
||||
for (auto it : mFileFlagTable) {
|
||||
res.emplace(it.second);
|
||||
}
|
||||
string text = YAML::Text_Serialize(res);
|
||||
FileManager::SaveTextFile(FileFlagName, text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,14 +22,19 @@ namespace engineapi {
|
||||
class ResourceManager : public ISingleton<ResourceManager>
|
||||
{
|
||||
public:
|
||||
struct FileControlBlock;
|
||||
template<typename R>
|
||||
struct ResourceControlBlock;
|
||||
template<typename R>
|
||||
using ResourceStorage = hash_table<Guid, ResourceControlBlock<R>>;
|
||||
using GenericPtr = shared_ptr<void>;
|
||||
private:
|
||||
array<GenericPtr, ResourceCount> mResourceTable;
|
||||
hash_table<Name, IFileLoader*> mFileLoader;
|
||||
uint32_t mFileFlag;
|
||||
array<GenericPtr, ResourceCount> mResourceTable;
|
||||
hash_table<NameID, IFileLoader*> mFileLoader;
|
||||
hash_table<NameID, std::pair<string, uint32_t>> mFileFlagTable;
|
||||
hash_table<NameID, FileControlBlock> mFileTable;
|
||||
vector<FileControlBlock*> mDirtyBlocks;
|
||||
public:
|
||||
void Init() override;
|
||||
void Shutdown() override;
|
||||
@ -42,6 +47,9 @@ namespace engineapi {
|
||||
auto& GetTable() {
|
||||
return *reinterpret_cast<ResourceStorage<Res>*> (mResourceTable[ResourceID<Res>].get());
|
||||
}
|
||||
template<typename Res>
|
||||
ResourceControlBlock<Res>* GetControlBlock(RscHandle<Res> handle);
|
||||
|
||||
template<typename Res, typename ... Args>
|
||||
[[nodiscard]] RscHandle<Res> LoaderEmplaceResource(Args&& ... args) {
|
||||
return LoaderEmplaceResource<Res>(Guid::Make(), args...);
|
||||
@ -55,21 +63,30 @@ namespace engineapi {
|
||||
|
||||
template<typename Res>
|
||||
RscHandle<Res> Load(PackagePath path, bool reload_resource = true);
|
||||
LoadResult<ResourceBundle> Load(PackagePath path, bool reload_resource = true);
|
||||
ResourceBundle& Load(PackagePath path, bool reload_resource = true);
|
||||
MetaBundle GetMeta(PackagePath path);
|
||||
MetaBundle GetVisitMeta(const ResourceBundle& bundle);
|
||||
void SaveMeta(PackagePath path, const MetaBundle& bundle);
|
||||
void SaveDirtyFiles();
|
||||
|
||||
void LoadFileFlag();
|
||||
void SaveFileFlag();
|
||||
uint32_t GetFileFlag(const Name& name);
|
||||
void SetFileFlag(const Name& name, uint32_t flag);
|
||||
};
|
||||
struct ResourceManager::FileControlBlock
|
||||
{
|
||||
ResourceBundle bundle;
|
||||
PackagePath path;
|
||||
bool is_dirty{ false };
|
||||
bool is_meta_dirty{ false };
|
||||
};
|
||||
template<typename R>
|
||||
struct ResourceManager::ResourceControlBlock
|
||||
{
|
||||
bool dirty{ false };
|
||||
std::optional<string> path{ std::nullopt };
|
||||
R* resource;
|
||||
|
||||
// meta data
|
||||
shared_ptr<void> userdata;
|
||||
bool dirty_meta{ false };
|
||||
|
||||
bool valid() const { return s_cast<bool>(resource); }
|
||||
FileControlBlock* file;
|
||||
bool valid() const { return resource; }
|
||||
};
|
||||
}
|
||||
#include "resource_manager.inl"
|
||||
@ -3,8 +3,14 @@
|
||||
namespace engineapi {
|
||||
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 {
|
||||
@ -48,17 +54,15 @@ namespace engineapi {
|
||||
inline FLoader& ResourceManager::RegisterLoader(Name ext, Args&& ...args)
|
||||
{
|
||||
FLoader* ptr = new FLoader(std::forward<Args>(args)...);
|
||||
ptr->SetFileFlag(GetFileFlag(ext));
|
||||
mFileLoader[ext] = ptr;
|
||||
return *ptr;
|
||||
}
|
||||
template<typename Res>
|
||||
inline RscHandle<Res> ResourceManager::Load(PackagePath path, bool reload_resource)
|
||||
{
|
||||
auto res = Load(path, reload_resource);
|
||||
if (!res)
|
||||
return {};
|
||||
|
||||
return res.value().Get<Res>();
|
||||
auto& res = Load(path, reload_resource);
|
||||
return res.Get<Res>();
|
||||
}
|
||||
template<typename Res>
|
||||
inline Res* ResourceManager::Get(const RscHandle<Res>& handle)
|
||||
@ -69,8 +73,32 @@ namespace engineapi {
|
||||
return nullptr;
|
||||
return itr->second.resource;
|
||||
}
|
||||
inline uint32_t ResourceManager::GetFileFlag(const Name& name)
|
||||
{
|
||||
auto it = mFileFlagTable.find(name.GetID());
|
||||
if (it == mFileFlagTable.end()) {
|
||||
return 0;
|
||||
}
|
||||
return it->second.second;
|
||||
}
|
||||
inline void ResourceManager::SetFileFlag(const Name& name, uint32_t flag)
|
||||
{
|
||||
auto it = mFileFlagTable.find(name.GetID());
|
||||
if (it == mFileFlagTable.end()) {
|
||||
mFileFlagTable.emplace(name.GetID(), std::make_pair(string(name.GetView()), flag));
|
||||
}
|
||||
else {
|
||||
it->second.second = flag;
|
||||
}
|
||||
}
|
||||
template<typename Res>
|
||||
inline void RscHandle<Res>::init()
|
||||
inline ResourceManager::ResourceControlBlock<Res>* ResourceManager::GetControlBlock(RscHandle<Res> handle)
|
||||
{
|
||||
auto& table = GetTable<Res>();
|
||||
return &table[handle.guid];
|
||||
}
|
||||
template<typename Res>
|
||||
inline void RscHandle<Res>::Init()
|
||||
{
|
||||
res = ResourceManager::GetSingleton().Get(*this);
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ namespace engineapi {
|
||||
int flags = 1;
|
||||
auto shader = ResourceManager::GetSingleton().LoaderEmplaceResource<Shader>();
|
||||
shader->mVertexName = type_name<BoneVertex>().View();
|
||||
//shader->mVert = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.vert");
|
||||
shader->mVert = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.vert");
|
||||
shader->mFrag = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.frag");
|
||||
RenderAPI::GetSingleton().LoadShader(&*shader);
|
||||
Material* material = new Material("/engine/assets/shader/simple.shader", flags);
|
||||
|
||||
@ -9,7 +9,7 @@ namespace engineapi {
|
||||
string mName = "";
|
||||
// 用ASSIMP加载模型文件
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(PackagePath::AbsolutePath(mName), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace
|
||||
const aiScene* scene = importer.ReadFile(mName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace
|
||||
| aiProcess_FixInfacingNormals | aiProcess_FlipWindingOrder | aiProcess_LimitBoneWeights);
|
||||
|
||||
// 检查异常
|
||||
|
||||
@ -32,18 +32,25 @@ namespace vulkanapi {
|
||||
int x = 1;
|
||||
int y = 2;
|
||||
}
|
||||
//string PreprocessGlsl(string glsl);
|
||||
ResourceBundle VulkanGlslLoader::LoadFile(PackagePath handle, const MetaBundle& meta)
|
||||
{
|
||||
auto m = meta.FetchMeta<ShaderProgram>();
|
||||
auto program = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<vkShaderProgram>(m->guid)
|
||||
: ResourceManager::GetSingleton().LoaderEmplaceResource<vkShaderProgram>();
|
||||
string glsl = FileManager::LoadTextFile(handle.AbsolutePath());
|
||||
auto shader_enum = GetShaderType(handle.GetExtension());
|
||||
glsl = GlslToSpirv::PreprocessGlsl(glsl);
|
||||
auto spirv = GlslToSpirv::spirv(glsl, shader_enum);
|
||||
if (spirv) {
|
||||
program->Load(*spirv);
|
||||
if (mFileFlag & FileFlag::File_Binary) {
|
||||
|
||||
}
|
||||
else {
|
||||
auto res = FileManager::LoadTextFile(handle);
|
||||
if (res) {
|
||||
string glsl = res.value();
|
||||
auto shader_enum = GetShaderType(handle.GetExtension());
|
||||
//glsl = GlslToSpirv::PreprocessGlsl(glsl);
|
||||
auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName());
|
||||
if (spirv) {
|
||||
program->Load(*spirv);
|
||||
}
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "glsl_to_spirv.h"
|
||||
#include "zstd/table.h"
|
||||
#include "meta/pad.h"
|
||||
#include "meta/hash.h"
|
||||
#include "yaml/yaml.h"
|
||||
#include <shaderc/shaderc.hpp>
|
||||
@ -45,19 +44,18 @@ namespace vulkanapi
|
||||
|
||||
return shader_code.substr(0, version_end) + replacer + shader_code.substr(version_end, shader_code.size() - version_end);
|
||||
}
|
||||
std::optional<std::vector<unsigned int>> GlslToSpirv::spirv(string_view glsl, vk::ShaderStageFlagBits v_stage, string_view code_id)
|
||||
std::optional<std::vector<unsigned int>> GlslToSpirv::spirv(const string& glsl, vk::ShaderStageFlagBits v_stage, string_view code_id)
|
||||
{
|
||||
string val = static_cast<string>(glsl);
|
||||
std::optional<std::vector<unsigned int>> spirv_out;
|
||||
{
|
||||
shaderc::Compiler compiler;
|
||||
shaderc::CompileOptions opt;
|
||||
opt.SetTargetEnvironment(shaderc_target_env::shaderc_target_env_vulkan, 0);
|
||||
auto result = compiler.CompileGlslToSpv(val, ConvertStageSC(v_stage), code_id.data(), opt);
|
||||
shaderc::CompileOptions options;
|
||||
options.SetOptimizationLevel(shaderc_optimization_level_performance);
|
||||
options.SetTargetEnvironment(shaderc_target_env::shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2);
|
||||
auto result = compiler.CompileGlslToSpv(glsl, ConvertStageSC(v_stage), code_id.data(), options);
|
||||
if (result.GetCompilationStatus() != shaderc_compilation_status::shaderc_compilation_status_success)
|
||||
return spirv_out;
|
||||
spirv_out = vector<unsigned int>{ result.begin(),result.end() };
|
||||
//meta::padding_vector(*spirv_out, (unsigned int)4, (unsigned int)0);
|
||||
}
|
||||
return spirv_out;
|
||||
}
|
||||
|
||||
@ -11,6 +11,6 @@ namespace vulkanapi
|
||||
{
|
||||
public:
|
||||
static string PreprocessGlsl(string glsl);
|
||||
static std::optional<std::vector<unsigned int>> spirv(string_view glsl, vk::ShaderStageFlagBits v_stage, string_view code_id = "unknown_shader");
|
||||
static std::optional<std::vector<unsigned int>> spirv(const string& glsl, vk::ShaderStageFlagBits v_stage, string_view code_id = "unknown_shader");
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user