try support asset loader

This commit is contained in:
ouczbs 2024-07-03 19:51:47 +08:00
parent e6d4313f90
commit 67b41a4eee
52 changed files with 518 additions and 306 deletions

View File

@ -28,6 +28,9 @@
#define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__); #define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__);
#define REGISTER_META_TABLE(Class) refl::UClass::MetaTable.emplace(type_name<Class>().View(), &refl::TypeInfo<Class>::StaticClass); #define REGISTER_META_TABLE(Class) refl::UClass::MetaTable.emplace(type_name<Class>().View(), &refl::TypeInfo<Class>::StaticClass);
#define REFL_FRIEND(Class) friend class refl_impl::_Static<Class, refl_impl::Meta>;\
friend class refl_impl::_Meta<Class, refl_impl::Meta>;
/* /*
struct vec3{ struct vec3{
USING_OVERLOAD_CTOR(vec3) USING_OVERLOAD_CTOR(vec3)

View File

View File

@ -0,0 +1,2 @@
- name: engineapi::Mesh
data: ""

View File

@ -0,0 +1,2 @@
- name: engineapi::Mesh
data: "mMaterial:\n guid: 00000000-0000-0000-0000-000000000000"

View File

@ -0,0 +1,9 @@
metadatas:
- guid: a5943c25-1ce8-44dc-ae99-4071d07ecb63
name: ""
t_hash: engineapi::Model
t_meta: ""
- guid: 77b7a000-ed3c-4271-ae30-5e91346e09f4
name: ""
t_hash: engineapi::Asset
t_meta: engineapi::Mesh

View File

@ -0,0 +1,2 @@
- name: engineapi::Mesh
data: ""

View File

@ -0,0 +1,9 @@
metadatas:
- guid: 80671c54-88f9-41c7-948a-a72cdf3727d3
name: ""
t_hash: engineapi::Model
t_meta: ""
- guid: 54e69c4b-16ea-4fb8-87d6-0e2383d093b0
name: defaultobject
t_hash: engineapi::Asset
t_meta: engineapi::Mesh

View File

@ -0,0 +1,5 @@
metadatas:
- guid: eb1c9b43-a86b-40cb-9b3d-a3296d168c70
name: ""
t_hash: engineapi::ShaderProgram
metadata: ""

View File

@ -0,0 +1,5 @@
metadatas:
- guid: 9419e2a5-ddc4-414f-aa76-d08e9b162492
name: ""
t_hash: engineapi::ShaderProgram
metadata: ""

22
engine/cpp_input.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
//#include "meta/variant.inl"
//#include "meta/tuple.inl"
//#include "meta/comparable.inl"
//#include "meta/hash.h"
//#include "zstd/span.h"
//#include "zstd/table.h"
//#include <vector>
//#include <optional>
namespace engineapi {
using namespace meta;
using zstd::span;
using std::vector;
using std::array;
using zstd::table;
using zstd::hash_table;
template<typename T>
using opt = std::optional<T>;
template<bool val>
using sfinae = std::enable_if_t<val>;
}

View File

@ -28,6 +28,9 @@ namespace engineapi {
for (auto system : SystemList) { for (auto system : SystemList) {
system->Init(); system->Init();
} }
for (auto system : SystemList) {
system->LateInit();
}
} }
void App::Shutdown() void App::Shutdown()
{ {

View File

@ -1,6 +1,10 @@
#include "assert.h" #include "assert.h"
#include "asset_loader.h"
#include "render/asset/shader.h" #include "render/asset/shader.h"
#include "render/asset/model.h"
#include "resource_manager.h" #include "resource_manager.h"
#include "object/loader/assimp_loader.h"
#include "yaml/yaml.h"
namespace engineapi { namespace engineapi {
MetaBundle ResourceManager::GetVisitMeta(const ResourceBundle& bundle) MetaBundle ResourceManager::GetVisitMeta(const ResourceBundle& bundle)
{ {
@ -9,4 +13,10 @@ namespace engineapi {
std::visit([&](auto& handle) { new_meta.Add(handle); }, elem); std::visit([&](auto& handle) { new_meta.Add(handle); }, elem);
return new_meta; return new_meta;
} }
void Asset::__Init__()
{
YAML::TextArchive::Register<Guid>();
AssimpLoader::Init();
AssetLoader::Init();
}
} }

View File

@ -1,11 +1,22 @@
#pragma once #pragma once
#include "render/asset_struct.h" #include "render/asset_struct.h"
#include "res/resource_handle.h" #include "resource_manager.h"
#include "res/package_path.h"
namespace engineapi { namespace engineapi {
class Asset : public Resource<Asset> { class Asset : public Resource<Asset> {
private:
static void __Init__();
friend class FileManager;
public: public:
using Base = Resource<Asset>; using Base = Resource<Asset>;
using Base::Base; const refl::UClass* meta;
Asset(const refl::UClass* meta): Base(), meta(meta){}
}; };
template<>
inline void MetaBundle::Add(RscHandle<Asset> h)
{
if (h)
{
metadatas.emplace_back(SerializedMeta{ h.guid, string(h->Name()), string(type_name<Asset>().View()), string(h->meta->name)});
}
}
} }

View File

@ -0,0 +1,25 @@
#include "asset_loader.h"
#include "file_manager.h"
#include "yaml/yaml.h"
#include <fstream>
namespace engineapi {
void AssetLoader::Init() {
ResourceManager::GetSingleton().RegisterLoader<AssetLoader>(".asset");
}
ResourceBundle AssetLoader::LoadFile(PackagePath handle, const MetaBundle& meta)
{
return ResourceBundle();
}
void AssetLoader::SaveFile(PackagePath handle, const ResourceBundle& bundle)
{
YAML::Node result;
for (auto& elem : bundle.GetAll<Asset>()) {
RscHandle<Asset> handle = elem.AsHandle<Asset>();
YAML::Node meta;
meta["name"] = string(handle->meta->name);
meta["data"] = YAML::Text_Serialize(refl::Any{handle.res, handle->meta});
result.push_back(meta);
}
FileManager::SaveTextFile(handle, YAML::Dump(result));
}
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "asset.h"
namespace engineapi {
class AssetLoader :public IFileLoader{
public:
static void Init();
ResourceBundle LoadFile(PackagePath handle, const MetaBundle& meta) override;
void SaveFile(PackagePath handle, const ResourceBundle& bundle) override;
};
}

View File

@ -7,12 +7,13 @@ namespace engineapi {
{ {
std::filesystem::path path = std::filesystem::current_path(); std::filesystem::path path = std::filesystem::current_path();
Mount("engine", path.string()); Mount("engine", path.string());
Asset::__Init__();
} }
void FileManager::Shutdown() void FileManager::Shutdown()
{ {
} }
string FileManager::real_path(const PackagePath& pack_path) string FileManager::RealPath(const PackagePath& pack_path)
{ {
string_view name = pack_path.ParsePackage(); string_view name = pack_path.ParsePackage();
string_view pre_path = FindMountPath(name); string_view pre_path = FindMountPath(name);
@ -40,7 +41,7 @@ namespace engineapi {
file.exceptions(ifstream::failbit | ifstream::badbit); file.exceptions(ifstream::failbit | ifstream::badbit);
try try
{ {
string path = real_path(pack_path); string path = RealPath(pack_path);
file.open(path); file.open(path);
stringstream stream; stringstream stream;
stream << file.rdbuf(); stream << file.rdbuf();
@ -54,7 +55,7 @@ namespace engineapi {
} }
result<vector<char>,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path) result<vector<char>,FileFlag> FileManager::LoadBinaryFile(const PackagePath& pack_path)
{ {
string path = real_path(pack_path); string path = RealPath(pack_path);
// ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区 // ate:在文件末尾开始读取,从文件末尾开始读取的优点是我们可以使用读取位置来确定文件的大小并分配缓冲区
ifstream file(path, std::ios::ate | std::ios::binary); ifstream file(path, std::ios::ate | std::ios::binary);
if (!file.is_open()) { if (!file.is_open()) {
@ -74,7 +75,7 @@ namespace engineapi {
} }
result<json, FileFlag> FileManager::LoadJsonFile(const PackagePath& pack_path) result<json, FileFlag> FileManager::LoadJsonFile(const PackagePath& pack_path)
{ {
string path = real_path(pack_path); string path = RealPath(pack_path);
std::ifstream f(path); std::ifstream f(path);
if (!f.is_open()) if (!f.is_open())
{ {
@ -96,7 +97,7 @@ namespace engineapi {
} }
void FileManager::SaveTextFile(const PackagePath& pack_path,const string& value) void FileManager::SaveTextFile(const PackagePath& pack_path,const string& value)
{ {
string path = real_path(pack_path); string path = RealPath(pack_path);
std::ofstream of(path); std::ofstream of(path);
of.write(value.data(), value.size()); of.write(value.data(), value.size());
} }

View File

@ -63,9 +63,10 @@ namespace engineapi
private: private:
inline static table<NameID, std::pair<string, string>> MountMap; inline static table<NameID, std::pair<string, string>> MountMap;
inline static table<NameID, FileControlBlock> FileMap; inline static table<NameID, FileControlBlock> FileMap;
//外界不应该使用绝对路径
static string real_path(const PackagePath& pack_path);
public: public:
//外界不应该使用绝对路径
static string RealPath(const PackagePath& pack_path);
static FileFlag LoadErrorFlag(const PackagePath& pack_path); static FileFlag LoadErrorFlag(const PackagePath& pack_path);
static result<string, FileFlag> LoadTextFile(const PackagePath& pack_path); static result<string, FileFlag> LoadTextFile(const PackagePath& pack_path);

View File

@ -13,9 +13,9 @@ namespace engineapi
UPROPERTY({}) UPROPERTY({})
string t_hash{}; string t_hash{};
UPROPERTY({}) UPROPERTY({})
string metadata; string t_meta;
bool operator==(const SerializedMeta& other)const{ bool operator==(const SerializedMeta& other)const{
return guid == other.guid && name == other.name && t_hash == other.t_hash && metadata == other.metadata; return guid == other.guid && name == other.name && t_hash == other.t_hash && t_meta == other.t_meta;
} }
}; };
struct ResourceBundle; struct ResourceBundle;
@ -29,6 +29,8 @@ namespace engineapi
template<typename T> template<typename T>
const SerializedMeta* FetchMeta() const; const SerializedMeta* FetchMeta() const;
template<typename T> template<typename T>
const SerializedMeta* FetchMeta(const string_view& asset_name) const;
template<typename T>
void Add(RscHandle<T>); void Add(RscHandle<T>);
bool operator==(const MetaBundle& other)const; bool operator==(const MetaBundle& other)const;
bool operator!=(const MetaBundle& other)const; bool operator!=(const MetaBundle& other)const;

View File

@ -4,10 +4,21 @@ namespace engineapi
template<typename T> template<typename T>
inline const SerializedMeta* MetaBundle::FetchMeta() const inline const SerializedMeta* MetaBundle::FetchMeta() const
{ {
string_view name = type_name<T>().View(); string_view name = type_name<typename T::BaseResource>().View();
for (auto& elem : metadatas) for (auto& elem : metadatas)
{ {
if (string_view(elem.t_hash) == name) if (elem.t_hash == name)
return &elem;
}
return nullptr;
}
template<typename T>
inline const SerializedMeta* MetaBundle::FetchMeta(const string_view& asset_name) const
{
string_view name = type_name<typename T::BaseResource>().View();
for (auto& elem : metadatas)
{
if (elem.t_hash == name && asset_name == elem.name)
return &elem; return &elem;
} }
return nullptr; return nullptr;
@ -17,7 +28,7 @@ namespace engineapi
{ {
if (h) if (h)
{ {
metadatas.emplace_back(SerializedMeta{ h.guid, string{h->Name()}, string{type_name<T>().View()}}); metadatas.emplace_back(SerializedMeta{ h.guid, string(h->Name()), string(type_name<T>().View()) });
} }
} }
} }

View File

@ -17,5 +17,9 @@ namespace engineapi {
{ {
return PackagePath{ FileManager::FindPathView(path) }; return PackagePath{ FileManager::FindPathView(path) };
} }
string PackagePath::RealPath() const
{
return FileManager::RealPath(*this);
}
} }

View File

@ -23,6 +23,7 @@ namespace engineapi
PackagePath() {}; PackagePath() {};
PackagePath(const char* path) : path(path) {} PackagePath(const char* path) : path(path) {}
PackagePath(const string_view& path) : path(path) {} PackagePath(const string_view& path) : path(path) {}
PackagePath(const string& path) : path(path) {}
PackagePath(const string&& path) : path(path) {} PackagePath(const string&& path) : path(path) {}
size_t size() const{ size_t size() const{
return path.size(); return path.size();
@ -54,5 +55,6 @@ namespace engineapi
} }
PackagePath ToSuffixPath(const string_view& suffix)const; PackagePath ToSuffixPath(const string_view& suffix)const;
PackagePath SafePath()const; PackagePath SafePath()const;
string RealPath()const;
}; };
} }

View File

@ -3,7 +3,6 @@
namespace engineapi namespace engineapi
{ {
struct GenericResourceHandle; struct GenericResourceHandle;
struct ResourceBundle struct ResourceBundle
{ {
ResourceBundle() = default; ResourceBundle() = default;
@ -13,6 +12,7 @@ namespace engineapi
template<typename T> void Add(RscHandle<T> handle); template<typename T> void Add(RscHandle<T> handle);
template<typename T> RscHandle<T> Get() const; // get a resource from the bundle template<typename T> RscHandle<T> Get() const; // get a resource from the bundle
span<const GenericResourceHandle> GetAll() const; // gets absolutely all resources span<const GenericResourceHandle> GetAll() const; // gets absolutely all resources
template<typename T> span<const GenericResourceHandle> GetAll() const; // get all resources of one type
private: private:
struct sub_array { short index = 0, count = 0; }; struct sub_array { short index = 0, count = 0; };

View File

@ -1,5 +1,4 @@
#pragma once #pragma once
#include "resource_bundle.h"
namespace engineapi namespace engineapi
{ {
template<typename Res> template<typename Res>
@ -31,9 +30,13 @@ namespace engineapi
} }
template<typename T> template<typename T>
inline RscHandle<T> engineapi::ResourceBundle::Get() const inline RscHandle<T> ResourceBundle::Get() const
{ {
auto& subarray = subarrays[ResourceID<T>]; auto& subarray = subarrays[ResourceID<T>];
return subarray.count > 0 ? handles[subarray.index].template AsHandle<T>() : RscHandle<T>(); return subarray.count > 0 ? handles[subarray.index].template AsHandle<T>() : RscHandle<T>();
} }
template<typename T> span<const GenericResourceHandle> ResourceBundle::GetAll() const {
auto& subarray = subarrays[ResourceID<T>];
return span<const GenericResourceHandle>{handles.data() + subarray.index, handles.data() + subarray.index + subarray.count};
}
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "type.h" #include "type.h"
namespace engineapi { namespace engineapi {
class Guid;
template<typename Res> template<typename Res>
struct RscHandle; struct RscHandle;
template<typename Res> template<typename Res>
@ -8,7 +9,7 @@ namespace engineapi {
{ {
public: public:
using BaseResource = Res; using BaseResource = Res;
Guid GetGuid()const;
RscHandle<Res> GetHandle() const { return mHandle; } RscHandle<Res> GetHandle() const { return mHandle; }
Resource() = default; Resource() = default;
@ -21,6 +22,7 @@ namespace engineapi {
}; };
using Resources = std::tuple< using Resources = std::tuple<
class ShaderProgram class ShaderProgram
, class Model
, class Asset , class Asset
>; >;
template<typename Resource> template<typename Resource>

View File

@ -4,18 +4,21 @@
namespace engineapi namespace engineapi
{ {
struct RscHandleBase {
UPROPERTY({})
Guid guid;
void* res;
};
template<typename Res> template<typename Res>
struct RscHandle struct RscHandle : public RscHandleBase
{ {
Guid guid{};
void* res{};
constexpr size_t RscID()const { return ResourceID<Res>; } constexpr size_t RscID()const { return ResourceID<Res>; }
constexpr RscHandle() noexcept = default; constexpr RscHandle() noexcept = default;
template<typename T> template<typename T>
constexpr RscHandle(const RscHandle<T>& other) noexcept : guid{ other.guid }, res(other.res) {}; constexpr RscHandle(const RscHandle<T>& other) noexcept : RscHandleBase(other.guid, other.res) {};
constexpr RscHandle(const Guid& guid, Res* res) noexcept : guid{ guid }, res(res) { ((Resource<Res>*)res)->mHandle = *this; } constexpr RscHandle(const Guid& guid, Res* res) noexcept : RscHandleBase(guid, res) { ((Resource<Res>*)res)->mHandle = *this; }
void Init(); void Init();
void Clear(){ res = nullptr; }; void Clear() { res = nullptr; };
Res* operator->() { if (!res && guid) Init(); return (Res*)res; } Res* operator->() { if (!res && guid) Init(); 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; } operator bool() { if (!res && guid) Init(); return res; }
@ -23,34 +26,6 @@ namespace engineapi
Res& operator*()const { return *(Res*)res; } Res& operator*()const { return *(Res*)res; }
operator bool() const { return res; } operator bool() const { return res; }
}; };
struct GenericResourceHandle
: variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>
{
private:
using Base = variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>;
public:
using Base::Base;
using Base::operator=;
template<typename T>
GenericResourceHandle(RscHandle<T> handle) : Base(RscHandle<typename T::BaseResource>{handle}) {}
GenericResourceHandle(string_view type_name, Guid guid);
template<typename T> RscHandle<T> AsHandle() const {
return std::get<ResourceID<T>>(*this);
}
Guid guid() const;
size_t resource_id() const;
};
} }
// hashtable support #include "resource_handle.inl"
namespace std #include "resource_handle_gen.inl"
{
template<typename Res>
struct hash <engineapi::RscHandle<Res>>
{
size_t operator()(const engineapi::RscHandle<Res>& res) const noexcept
{
return std::hash<engineapi::Guid>()(res.guid);
}
};
}

View File

@ -0,0 +1,43 @@
#pragma once
namespace engineapi{
template<typename Res>
inline Guid Resource<Res>::GetGuid() const
{
return GetHandle().guid;
}
struct GenericResourceHandle
: variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>
{
private:
using Base = variant_wrap_t<tuple_to_variant_t<Resources>, RscHandle>;
public:
using Base::Base;
using Base::operator=;
template<typename T>
GenericResourceHandle(RscHandle<T> handle) : Base(RscHandle<typename T::BaseResource>{handle}) {}
GenericResourceHandle(string_view type_name, Guid guid);
template<typename T> RscHandle<T> AsHandle() const {
return std::get<ResourceID<T>>(*this);
}
Guid guid() const;
size_t resource_id() const;
};
}
// hashtable support
namespace std
{
template<typename Res>
struct hash <engineapi::RscHandle<Res>>
{
size_t operator()(const engineapi::RscHandle<Res>& res) const noexcept
{
return std::hash<engineapi::Guid>()(res.guid);
}
};
}
namespace refl {
template<typename T>
struct real_type<engineapi::RscHandle<T>> {
using type = engineapi::RscHandleBase;
};
}

View File

@ -7,6 +7,11 @@ namespace engineapi {
mResourceTable = detail::ResourceHelper::GenResourceTables(); mResourceTable = detail::ResourceHelper::GenResourceTables();
LoadFileFlag(); LoadFileFlag();
} }
void ResourceManager::LateInit()
{
SaveFileFlag();
SaveDirtyFiles();
}
void ResourceManager::Shutdown() void ResourceManager::Shutdown()
{ {
constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources(); constexpr static auto release_tables = detail::ResourceHelper::ReleaseTableResources();
@ -30,23 +35,26 @@ namespace engineapi {
return it->second.bundle; return it->second.bundle;
} }
} }
auto& res = mFileTable[path.path];
Name ext = path.GetExtension(); Name ext = path.GetExtension();
IFileLoader* loader = GetLoader(ext); IFileLoader* loader = GetLoader(ext);
MetaBundle meta = GetMeta(path); MetaBundle meta = GetMeta(path);
ResourceBundle bundle = loader->LoadFile(path, meta); ResourceBundle bundle = loader->LoadFile(path, meta);
MetaBundle new_meta = GetVisitMeta(bundle); MetaBundle new_meta = GetVisitMeta(bundle);
bool is_dirty_meta = meta != new_meta; 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()) { for (auto& elem : bundle.GetAll()) {
std::visit([&](auto& handle) { std::visit([&](auto& handle) {
using T = std::decay_t<decltype(*handle)>; using T = std::decay_t<decltype(*handle)>;
GetControlBlock<T>(handle)->file = &res; GetControlBlock<T>(handle)->file = &res;
}, elem); }, elem);
} }
if (is_dirty_meta) { if (is_dirty_meta || res.is_dirty) {
mDirtyBlocks.push_back(&res); mDirtyBlocks.push_back(&res);
} }
res.path = path.SafePath();
res.bundle = bundle;
res.is_meta_dirty = is_dirty_meta;
res.bundle = bundle;
return res.bundle; return res.bundle;
} }
@ -74,7 +82,7 @@ namespace engineapi {
} }
else { else {
string text = YAML::Text_Serialize(bundle); string text = YAML::Text_Serialize(bundle);
FileManager::SaveTextFile(path, text); FileManager::SaveTextFile(path + ".meta", text);
} }
} }
void ResourceManager::SaveDirtyFiles() void ResourceManager::SaveDirtyFiles()

View File

@ -37,6 +37,7 @@ namespace engineapi {
vector<FileControlBlock*> mDirtyBlocks; vector<FileControlBlock*> mDirtyBlocks;
public: public:
void Init() override; void Init() override;
void LateInit()override;
void Shutdown() override; void Shutdown() override;
public: public:
@ -47,8 +48,9 @@ namespace engineapi {
auto& GetTable() { auto& GetTable() {
return *reinterpret_cast<ResourceStorage<Res>*> (mResourceTable[ResourceID<Res>].get()); return *reinterpret_cast<ResourceStorage<Res>*> (mResourceTable[ResourceID<Res>].get());
} }
template<typename Res> template<typename Res>
ResourceControlBlock<Res>* GetControlBlock(RscHandle<Res> handle); ResourceControlBlock<Res>* GetControlBlock(RscHandle<Res> handle);
FileControlBlock& GetFileBlock(PackagePath path);
template<typename Res, typename ... Args> template<typename Res, typename ... Args>
[[nodiscard]] RscHandle<Res> LoaderEmplaceResource(Args&& ... args) { [[nodiscard]] RscHandle<Res> LoaderEmplaceResource(Args&& ... args) {

View File

@ -1,4 +1,3 @@
#include "resource_manager.h"
#pragma once #pragma once
namespace engineapi { namespace engineapi {
class IFileLoader class IFileLoader
@ -97,6 +96,9 @@ namespace engineapi {
auto& table = GetTable<Res>(); auto& table = GetTable<Res>();
return &table[handle.guid]; return &table[handle.guid];
} }
inline ResourceManager::FileControlBlock& ResourceManager::GetFileBlock(PackagePath path) {
return mFileTable[NameID(path.path)];
}
template<typename Res> template<typename Res>
inline void RscHandle<Res>::Init() inline void RscHandle<Res>::Init()
{ {

View File

@ -0,0 +1,149 @@
#include "zlog.h"
#include "assimp_loader.h"
#include "asset/file_manager.h"
#include "asset/resource_manager.h"
#include "assimp/Importer.hpp"
#include "assimp/scene.h"
#include "assimp/postprocess.h"
#include <fstream>
namespace engineapi {
void AssimpLoader::Init()
{
ResourceManager::GetSingleton().RegisterLoader<AssimpLoader>(".obj");
ResourceManager::GetSingleton().RegisterLoader<AssimpLoader>(".ply");
}
ResourceBundle AssimpLoader::LoadFile(PackagePath handle, const MetaBundle& meta)
{
auto m = meta.FetchMeta<Model>();
auto asset = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<Model>(m->guid)
: ResourceManager::GetSingleton().LoaderEmplaceResource<Model>();
uint32_t flag = FileManager::FindPathFlag(handle);
if (flag & FileFlag::File_Http) {
return {};
}
LoadModel(handle, *asset, meta);
ResourceBundle bundle{ asset };
for (auto& mesh : asset->GetMeshs()) {
bundle.Add(mesh);
}
PackagePath asset_handle(handle + ".asset");
std::ifstream file(asset_handle.RealPath());
if (!file.good()) {
auto& block = ResourceManager::GetSingleton().GetFileBlock(handle);
block.is_dirty = true;
}
return bundle;
}
void AssimpLoader::SaveFile(PackagePath handle, const ResourceBundle& bundle)
{
auto loader = ResourceManager::GetSingleton().GetLoader(".asset");
if(loader)
loader->SaveFile(handle + ".asset", bundle);
}
void AssimpLoader::LoadModel(PackagePath handle, Model& model, const MetaBundle& meta)
{
// 用ASSIMP加载模型文件
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(handle.RealPath(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace
| aiProcess_FixInfacingNormals | aiProcess_FlipWindingOrder | aiProcess_LimitBoneWeights);
// 检查异常
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
zlog::error("ASSIMP: {}", importer.GetErrorString());
return;
}
ProcessNode(model, meta, scene->mRootNode, scene);
}
void AssimpLoader::ProcessNode(Model& model, const MetaBundle& meta, const aiNode* pNode, const aiScene* pScene)
{
// 处理Mesh数据
auto& meshs = model.GetMeshs();
for (unsigned int i = 0; i < pNode->mNumMeshes; i++)
{
// aiNode仅包含索引来获取aiScene中的实际对象
// aiScene包含所有数据aiNode只是为了让数据组织起来(比如记录节点之间的关系)
aiMesh* mesh = pScene->mMeshes[pNode->mMeshes[i]];
auto m = meta.FetchMeta<Mesh>(mesh->mName.C_Str());
meshs.push_back(ProcessMesh(m, mesh));
}
// 加载骨骼数据
//pBoneNode->name = pNode->mName.C_Str();
//pBoneNode->transform = aiMatrix4x4ToMatrix4(pNode->mTransformation);
// 递归处理子节点
for (unsigned int i = 0; i < pNode->mNumChildren; i++)
{
//pBoneNode->children.push_back(new BoneNode());
ProcessNode(model, meta, pNode->mChildren[i], pScene);
}
}
RscHandle<Mesh> AssimpLoader::ProcessMesh(const SerializedMeta* m, const aiMesh* mesh)
{
// data to fill
vector<BoneVertex> vertices;
vector<uint32_t> indices;
// Walk through each of the mesh's vertices
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
BoneVertex vertex;
Vector3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to Vector3 class so we transfer the data to this placeholder Vector3 first.
// positions
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
// normals
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
// texture coordinates
if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
{
Vector2 vec;
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
}
else
{
vertex.TexCoords = Vector2(0.0f, 0.0f);
}
// tangent and bitangent
if (mesh->HasTangentsAndBitangents())
{
vector.x = mesh->mTangents[i].x;
vector.y = mesh->mTangents[i].y;
vector.z = mesh->mTangents[i].z;
vertex.Tangent = vector;
}
else
{
vertex.Tangent = Vector3(0.0f, 0.0f, 0.0f);
}
vertices.push_back(vertex);
}
// now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
const aiFace& face = mesh->mFaces[i];
// retrieve all indices of the face and store them in the indices vector
for (unsigned int j = 0; j < face.mNumIndices; j++)
{
indices.push_back(face.mIndices[j]);
}
}
auto asset = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<Mesh>(m->guid, vertices, indices)
: ResourceManager::GetSingleton().LoaderEmplaceResource<Mesh>(vertices, indices);
asset->Name(mesh->mName.C_Str());
return asset;
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "render/asset/model.h"
#include "asset/resource_manager.h"
class aiNode;
class aiMesh;
class aiScene;
namespace engineapi {
class AssimpLoader : public IFileLoader
{
inline static table<Guid, void*> ShaderTable;
public:
static void Init();
ResourceBundle LoadFile(PackagePath handle, const MetaBundle& meta) override;
void SaveFile(PackagePath handle, const ResourceBundle& bundle) override;
void LoadModel(PackagePath handle, Model& model, const MetaBundle& meta);
void ProcessNode(Model& model, const MetaBundle& meta, const aiNode* pNode, const aiScene* pScene);
RscHandle<Mesh> ProcessMesh(const SerializedMeta* m, const aiMesh* mesh);
};
}

View File

@ -1,4 +1,5 @@
#include "actor.h" #include "actor.h"
#include "asset/resource_manager.h"
#include "data/property/actor_property.h" #include "data/property/actor_property.h"
namespace engineapi { namespace engineapi {
ActorMesh::ActorMesh(Model& model, ActorProperty& property) ActorMesh::ActorMesh(Model& model, ActorProperty& property)
@ -9,9 +10,8 @@ namespace engineapi {
} }
ActorMesh* ActorMesh::New(ActorProperty& property) ActorMesh* ActorMesh::New(ActorProperty& property)
{ {
//Model* model = AssetManager::GetSingletonPtr()->LoadAsset<Model>(property.path, property.flags); auto res = ResourceManager::GetSingleton().Load<Model>(property.path);
//return new ActorMesh(*model, property); return new ActorMesh(*res, property);
return nullptr;
} }
ActorMesh* ActorMesh::New(uint32_t id) ActorMesh* ActorMesh::New(uint32_t id)
{ {

View File

@ -8,6 +8,6 @@ namespace engineapi {
} }
void StaticMesh::LoadMesh() void StaticMesh::LoadMesh()
{ {
mPtr.BeginLoad();
} }
} }

View File

@ -12,18 +12,19 @@ namespace engineapi {
mCamera = new Camera(); mCamera = new Camera();
int flags = 1; int flags = 1;
auto shader = ResourceManager::GetSingleton().LoaderEmplaceResource<Shader>(); auto shader = ResourceManager::GetSingleton().LoaderEmplaceResource<Shader>();
shader->mVertexName = type_name<BoneVertex>().View(); shader->Name(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"); shader->mFrag = ResourceManager::GetSingleton().Load<ShaderProgram>("/engine/assets/shader/simple.frag");
RenderAPI::GetSingleton().LoadShader(&*shader); RenderAPI::GetSingleton().LoadShader(*shader);
Material* material = new Material("/engine/assets/shader/simple.shader", flags); //Material* material = new Material("/engine/assets/shader/simple.shader", flags);
{ {
ActorProperty property; ActorProperty property;
property.id = 1; property.id = 1;
property.flags = flags; property.flags = flags;
property.path = "/engine/assets/models/cube.obj"; property.path = "/engine/assets/models/cube.obj";
actor1 = ActorMesh::New(property); actor1 = ActorMesh::New(property);
actor1->Ptr().SetMaterial(material); actor1->LoadMesh();
//actor1->Ptr().SetMaterial(material);
} }
{ {
ActorProperty property; ActorProperty property;
@ -31,7 +32,7 @@ namespace engineapi {
property.flags = flags; property.flags = flags;
property.path = "/engine/assets/models/box.ply"; property.path = "/engine/assets/models/box.ply";
actor2 = ActorMesh::New(property); actor2 = ActorMesh::New(property);
actor2->Ptr().SetMaterial(material); //actor2->Ptr().SetMaterial(material);
} }
} }
Scene::~Scene() Scene::~Scene()
@ -43,11 +44,10 @@ namespace engineapi {
void Scene::Render() void Scene::Render()
{ {
RenderAPI::GetSingletonPtr()->Render(*mCamera); RenderAPI::GetSingletonPtr()->Render(*mCamera);
auto meshs = actor1->Ptr().GetMeshs(); //auto meshs = actor1->Ptr().GetMeshs();
for (auto it : meshs) { //for (auto it : meshs) {
RenderAPI::GetSingletonPtr()->DrawStaticMesh(it); //RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it);
} //}
//RenderAPI::GetSingletonPtr()->DrawStaticMesh(actor2);
} }
void Scene::AddGameObject(GameObject* gameObject) void Scene::AddGameObject(GameObject* gameObject)
{ {

View File

@ -2,9 +2,9 @@
#include "shader.h" #include "shader.h"
#include "../renderapi.h" #include "../renderapi.h"
namespace engineapi { namespace engineapi {
Material::Material(string_view name, uint32_t flags) Material::Material() : Asset(&refl::TypeInfo<Material>::StaticClass)
{ {
//mShader = new Shader(name, flags);
} }
Material::~Material() Material::~Material()
{ {

View File

@ -1,15 +1,18 @@
#pragma once #pragma once
#include "asset/asset.h" #include "asset/asset.h"
#include "shader.h"
namespace engineapi { namespace engineapi {
class Shader;
class Material : public Asset { class Material : public Asset {
protected: protected:
uint32_t mId{0}; REFL_FRIEND(Material)
Shader* mShader; UPROPERTY()
RscHandle<Shader> mShader;
public: public:
Material(string_view name, uint32_t flags); Material();
~Material(); ~Material();
RscHandle<Shader> GetShader() {
return mShader;
}
}; };
}; };
#include "material_gen.inl"

View File

@ -3,6 +3,6 @@
namespace engineapi { namespace engineapi {
void Mesh::BeginLoad() void Mesh::BeginLoad()
{ {
RenderAPI::GetSingletonPtr()->SetStaticMesh(this); RenderAPI::GetSingletonPtr()->SetStaticMesh(*this);
} }
} }

View File

@ -1,30 +1,28 @@
#pragma once #pragma once
#include "material.h"
#include "vertex.h"
#include "refl/std/parray.h" #include "refl/std/parray.h"
#include "asset/asset.h"
#include "../meta/vertex.h"
namespace engineapi { namespace engineapi {
using refl::parray; using refl::parray;
class Texture; class Mesh : public Asset{
class Material;
class Mesh : public Asset {
protected: protected:
uint32_t VAO = 0; REFL_FRIEND(Mesh)
UPROPERTY()
RscHandle<Material> mMaterial;
parray<Vertex> mVertices; parray<Vertex> mVertices;
vector<uint32_t> mIndices; vector<uint32_t> mIndices;
public: public:
template<typename T> template<typename T>
requires std::is_base_of_v<Vertex, T> requires std::is_base_of_v<Vertex, T>
Mesh(vector<T>& vertices, vector<uint32_t>& indices) Mesh(vector<T>& vertices, vector<uint32_t>& indices);
: mVertices(vertices)
, mIndices(indices)
{
BeginLoad();
}
void BeginLoad(); void BeginLoad();
public: public:
uint32_t& GetVAO() { Guid GetShaderGuid() {
return VAO; return mMaterial->GetShader().guid;
}
RscHandle<Material> GetMaterial() {
return mMaterial;
} }
parray<Vertex>& GetVertices() { parray<Vertex>& GetVertices() {
return mVertices; return mVertices;
@ -33,4 +31,14 @@ namespace engineapi {
return mIndices; return mIndices;
} }
}; };
}; };
#include "mesh_gen.inl"
namespace engineapi {
template<typename T>
requires std::is_base_of_v<Vertex, T>
inline Mesh::Mesh(vector<T>& vertices, vector<uint32_t>& indices)
: Asset(&refl::TypeInfo<Mesh>::StaticClass), mVertices(vertices), mIndices(indices)
{
auto cls = &refl::TypeInfo<Mesh>::StaticClass;
}
}

View File

@ -1,109 +1,10 @@
#include "model.h" #include "model.h"
#include "zlog.h"
#include "assimp/Importer.hpp"
#include "assimp/scene.h"
#include "assimp/postprocess.h"
namespace engineapi { namespace engineapi {
void Model::BeginLoad() void Model::BeginLoad()
{ {
string mName = ""; for (auto mesh : mMeshes) {
// 用ASSIMP加载模型文件 mesh->BeginLoad();
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(mName, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace
| aiProcess_FixInfacingNormals | aiProcess_FlipWindingOrder | aiProcess_LimitBoneWeights);
// 检查异常
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
{
zlog::error("ASSIMP: {}", importer.GetErrorString());
return;
} }
ProcessNode(scene->mRootNode, scene);
}
void Model::ProcessNode(const aiNode* pNode, const aiScene* pScene)
{
// 处理Mesh数据
for (unsigned int i = 0; i < pNode->mNumMeshes; i++)
{
// aiNode仅包含索引来获取aiScene中的实际对象
// aiScene包含所有数据aiNode只是为了让数据组织起来(比如记录节点之间的关系)
aiMesh* mesh = pScene->mMeshes[pNode->mMeshes[i]];
mMeshes.push_back(ProcessMesh(mesh));
}
// 加载骨骼数据
//pBoneNode->name = pNode->mName.C_Str();
//pBoneNode->transform = aiMatrix4x4ToMatrix4(pNode->mTransformation);
// 递归处理子节点
for (unsigned int i = 0; i < pNode->mNumChildren; i++)
{
//pBoneNode->children.push_back(new BoneNode());
ProcessNode(pNode->mChildren[i], pScene);
}
}
Mesh* Model::ProcessMesh(const aiMesh* mesh) {
// data to fill
vector<BoneVertex> vertices;
vector<uint32_t> indices;
// Walk through each of the mesh's vertices
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{
BoneVertex vertex;
Vector3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to Vector3 class so we transfer the data to this placeholder Vector3 first.
// positions
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
// normals
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
// texture coordinates
if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates?
{
Vector2 vec;
// a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
// use models where a vertex can have multiple texture coordinates so we always take the first set (0).
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
}
else
{
vertex.TexCoords = Vector2(0.0f, 0.0f);
}
// tangent and bitangent
if (mesh->HasTangentsAndBitangents())
{
vector.x = mesh->mTangents[i].x;
vector.y = mesh->mTangents[i].y;
vector.z = mesh->mTangents[i].z;
vertex.Tangent = vector;
}
else
{
vertex.Tangent = Vector3(0.0f, 0.0f, 0.0f);
}
vertices.push_back(vertex);
}
// now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
{
const aiFace& face = mesh->mFaces[i];
// retrieve all indices of the face and store them in the indices vector
for (unsigned int j = 0; j < face.mNumIndices; j++)
{
indices.push_back(face.mIndices[j]);
}
}
return new Mesh(vertices, indices);
} }
void Model::Use() void Model::Use()
{ {

View File

@ -1,26 +1,14 @@
#pragma once #pragma once
#include "asset/asset.h"
#include "mesh.h" #include "mesh.h"
#include "material.h"
class aiNode;
class aiMesh;
class aiScene;
namespace engineapi { namespace engineapi {
class Model : public Asset { class Model : public Resource<Model> {
protected: protected:
vector<Mesh*> mMeshes; vector<RscHandle<Mesh>> mMeshes;
Material* mMaterial;
public: public:
using Asset::Asset;
void BeginLoad(); void BeginLoad();
void ProcessNode(const aiNode* pNode, const aiScene* pScene); vector<RscHandle<Mesh>>& GetMeshs() {
Mesh* ProcessMesh(const aiMesh* mesh);
vector<Mesh*>& GetMeshs() {
return mMeshes; return mMeshes;
} }
void SetMaterial(Material* material) {
mMaterial = material;
}
void Use(); void Use();
}; };
}; };

View File

@ -1,8 +1,6 @@
#include "shader.h" #include "shader.h"
#include "asset/file_manager.h"
#include "../renderapi.h"
namespace engineapi { namespace engineapi {
Shader::Shader() Shader::Shader() : Asset(&refl::TypeInfo<Shader>::StaticClass)
{ {
} }

View File

@ -5,10 +5,12 @@ namespace engineapi {
class ShaderProgram : public Resource<ShaderProgram> {}; class ShaderProgram : public Resource<ShaderProgram> {};
class Shader : public Asset { class Shader : public Asset {
private: private:
REFL_FRIEND(Shader)
uint32_t mId; uint32_t mId;
ShaderInfo mInfo; ShaderInfo mInfo;
string mVertexName; UPROPERTY()
RscHandle<ShaderProgram> mVert; RscHandle<ShaderProgram> mVert;
UPROPERTY()
RscHandle<ShaderProgram> mFrag; RscHandle<ShaderProgram> mFrag;
friend class Scene; friend class Scene;
public: public:
@ -20,9 +22,6 @@ namespace engineapi {
ShaderInfo& GetInfo() { ShaderInfo& GetInfo() {
return mInfo; return mInfo;
} }
string_view GetVertexName() {
return mVertexName;
}
template<typename T = ShaderProgram> template<typename T = ShaderProgram>
RscHandle<T> GetVertHandle() { RscHandle<T> GetVertHandle() {
return mVert; return mVert;
@ -32,4 +31,5 @@ namespace engineapi {
return mFrag; return mFrag;
} }
}; };
}; };
#include "shader_gen.inl"

View File

@ -0,0 +1,7 @@
#include "texture.h"
namespace engineapi {
Texture::Texture() : Asset(&refl::TypeInfo<Texture>::StaticClass)
{
}
}

View File

@ -3,6 +3,6 @@
namespace engineapi { namespace engineapi {
class Texture : public Asset { class Texture : public Asset {
Texture();
}; };
}; };

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "../asset/material.h" #include "../asset/material.h"
#include "../asset/mesh.h"
#include "../asset/texture.h" #include "../asset/texture.h"
#include "../render_context.h" #include "../render_context.h"
namespace engineapi { namespace engineapi {

View File

@ -31,10 +31,10 @@ namespace engineapi
virtual void BeginFrame() = 0; virtual void BeginFrame() = 0;
virtual void Render(Camera& camera); virtual void Render(Camera& camera);
virtual void EndFrame() = 0; virtual void EndFrame() = 0;
virtual void SetStaticMesh(Mesh* mesh) = 0; virtual void SetStaticMesh(Mesh& mesh) = 0;
virtual void DrawStaticMesh(Mesh* mesh) = 0; virtual void DrawStaticMesh(Mesh& mesh) = 0;
virtual void LoadShader(Shader* shader) = 0; virtual void LoadShader(Shader& shader) = 0;
virtual void SwitchContext() = 0; virtual void SwitchContext() = 0;

View File

@ -2,7 +2,7 @@
#include "vulkanapi/tool/glsl_to_spirv.h" #include "vulkanapi/tool/glsl_to_spirv.h"
#include "vulkanapi/vulkanapi.h" #include "vulkanapi/vulkanapi.h"
#include "asset/file_manager.h" #include "asset/file_manager.h"
#include "render/meta/vertex.h" #include "render/asset/vertex.h"
#include "vkmeta_vertex_gen.inl" #include "vkmeta_vertex_gen.inl"
#include <spirv_cross/spirv_reflect.hpp> #include <spirv_cross/spirv_reflect.hpp>
using namespace engineapi; using namespace engineapi;
@ -56,7 +56,7 @@ namespace vulkanapi {
auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName()); auto spirv = GlslToSpirv::spirv(glsl, shader_enum, handle.GetFileName());
if (spirv) { if (spirv) {
program->Load(*spirv); program->Load(*spirv);
LoadShaderInfo(program->GetHandle().guid, *spirv); LoadShaderInfo(program->GetGuid(), *spirv);
} }
} }
} }

View File

@ -64,13 +64,13 @@ namespace vulkanapi {
{ {
swapchain->Present(context); swapchain->Present(context);
} }
void RenderVulkanAPI::SetStaticMesh(Mesh* mesh) void RenderVulkanAPI::SetStaticMesh(Mesh& mesh)
{ {
auto Indices = mesh->GetIndices(); auto Indices = mesh.GetIndices();
auto Vertices = mesh->GetVertices(); auto Vertices = mesh.GetVertices();
auto meshBuffer = GetNextVAO(mesh->GetVAO()); VulkanVAO& meshBuffer = VAOTable[mesh.GetGuid()];
meshBuffer->indexCount = Indices.size(); meshBuffer.indexCount = Indices.size();
meshBuffer->vertexCount = Vertices.size(); meshBuffer.vertexCount = Vertices.size();
// ----------------------------------------------- Vertex Buffer ----------------------------------------------- // ----------------------------------------------- Vertex Buffer -----------------------------------------------
VkDeviceSize vertexBufferSize = Vertices.capicty(); VkDeviceSize vertexBufferSize = Vertices.capicty();
@ -84,7 +84,7 @@ namespace vulkanapi {
VkBufferUsageFlags vertexFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//加入光线追踪 VkBufferUsageFlags vertexFlags = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;//加入光线追踪
VmaAllocationCreateInfo vertexVmaCreateInfo = {}; VmaAllocationCreateInfo vertexVmaCreateInfo = {};
VkBufferCreateInfo vertexCreateInfo = Buffer::MakeDeviceInfo(vertexVmaCreateInfo, vertexBufferSize, vertexFlags); VkBufferCreateInfo vertexCreateInfo = Buffer::MakeDeviceInfo(vertexVmaCreateInfo, vertexBufferSize, vertexFlags);
meshBuffer->vertexBuffer = Buffer::CreateBuffer(vertexCreateInfo, vertexVmaCreateInfo, meshBuffer->vertexBufferAlloc); meshBuffer.vertexBuffer = Buffer::CreateBuffer(vertexCreateInfo, vertexVmaCreateInfo, meshBuffer.vertexBufferAlloc);
// ----------------------------------------------- Index Buffer ----------------------------------------------- // ----------------------------------------------- Index Buffer -----------------------------------------------
VkDeviceSize indexBufferSize = sizeof(uint32_t) * Indices.size(); VkDeviceSize indexBufferSize = sizeof(uint32_t) * Indices.size();
@ -96,11 +96,11 @@ namespace vulkanapi {
VmaAllocationCreateInfo indexVmaCreateInfo = {}; VmaAllocationCreateInfo indexVmaCreateInfo = {};
VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); VkBufferCreateInfo indexCreateInfo = Buffer::MakeDeviceInfo(indexVmaCreateInfo, indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
meshBuffer->indexBuffer = Buffer::CreateBuffer(indexCreateInfo, indexVmaCreateInfo, meshBuffer->vertexBufferAlloc); meshBuffer.indexBuffer = Buffer::CreateBuffer(indexCreateInfo, indexVmaCreateInfo, meshBuffer.vertexBufferAlloc);
auto fn = [=](CommandBuffer& cmd) { auto fn = [=](CommandBuffer& cmd) {
cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer->vertexBuffer, vertexBufferSize); cmd.CmdCopyBuffer(vertexStagingBuffer, meshBuffer.vertexBuffer, vertexBufferSize);
cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer->indexBuffer, indexBufferSize); cmd.CmdCopyBuffer(indexStagingBuffer, meshBuffer.indexBuffer, indexBufferSize);
}; };
auto callback = [=]() { auto callback = [=]() {
// 销毁StagingBuffer // 销毁StagingBuffer
@ -115,16 +115,16 @@ namespace vulkanapi {
Backend::TransferWorker->ImmediatelyExecute(fn, callback); Backend::TransferWorker->ImmediatelyExecute(fn, callback);
} }
} }
void RenderVulkanAPI::DrawStaticMesh(Mesh* mesh) void RenderVulkanAPI::DrawStaticMesh(Mesh& mesh)
{ {
auto vulkanVAO = VAOList[mesh->GetVAO()]; VulkanVAO& vulkanVAO = VAOTable[mesh.GetGuid()];
auto pipeline = PiPelineList[0]; VulkanPipeline& pipeline = PipelineTable[mesh.GetShaderGuid()];
uint32_t frame = context.frame; uint32_t frame = context.frame;
context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset); context.Pass->SetViewPort(mViewPortInfo.width, mViewPortInfo.height, mViewPortInfo.xOffset, mViewPortInfo.yOffset);
Backend::RenderWorker->Draw([=](CommandBuffer& cmd) { Backend::RenderWorker->Draw([=](CommandBuffer& cmd) {
VkCommandBuffer ptr = cmd.Ptr(); VkCommandBuffer ptr = cmd.Ptr();
context.Pass->BeginPass(cmd, frame); context.Pass->BeginPass(cmd, frame);
VkBuffer vertexBuffers[] = { vulkanVAO->vertexBuffer }; VkBuffer vertexBuffers[] = { vulkanVAO.vertexBuffer };
VkDeviceSize offsets[] = { 0 }; VkDeviceSize offsets[] = { 0 };
VkViewport viewport = {}; VkViewport viewport = {};
viewport.x = static_cast<float>(mViewPortInfo.xOffset); viewport.x = static_cast<float>(mViewPortInfo.xOffset);
@ -141,22 +141,22 @@ namespace vulkanapi {
vkCmdSetScissor(ptr, 0, 1, &scissor); vkCmdSetScissor(ptr, 0, 1, &scissor);
vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets); vkCmdBindVertexBuffers(ptr, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(ptr, vulkanVAO->indexBuffer, 0, VK_INDEX_TYPE_UINT32); vkCmdBindIndexBuffer(ptr, vulkanVAO.indexBuffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); vkCmdBindPipeline(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipelineLayout, 0, 1, &pipeline->descriptorSet, 0, VK_NULL_HANDLE); vkCmdBindDescriptorSets(ptr, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout, 0, 1, &pipeline.descriptorSet, 0, VK_NULL_HANDLE);
vkCmdDrawIndexed(ptr, 3, 1, 0, 0, 0); vkCmdDrawIndexed(ptr, 3, 1, 0, 0, 0);
context.Pass->EndPass(cmd); context.Pass->EndPass(cmd);
}); });
Backend::RenderWorker->Flush(); Backend::RenderWorker->Flush();
} }
void RenderVulkanAPI::LoadShader(Shader* shader) void RenderVulkanAPI::LoadShader(Shader& shader)
{ {
vector<VkPipelineShaderStageCreateInfo> shaderStages; vector<VkPipelineShaderStageCreateInfo> shaderStages;
std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules; std::map<VkShaderStageFlagBits, VkShaderModule> shaderModules;
auto device = backend.GetDevice(); auto device = backend.GetDevice();
auto vertModule = shader->GetVertHandle<vkShaderProgram>()->Ptr(); auto vertModule = shader.GetVertHandle<vkShaderProgram>()->Ptr();
shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule)); shaderModules.insert(make_pair(VK_SHADER_STAGE_VERTEX_BIT, vertModule));
auto fragModule = shader->GetVertHandle<vkShaderProgram>()->Ptr(); auto fragModule = shader.GetFragHandle<vkShaderProgram>()->Ptr();
shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule)); shaderModules.insert(make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule));
for (auto& shaderModule : shaderModules) for (auto& shaderModule : shaderModules)
{ {
@ -167,7 +167,7 @@ namespace vulkanapi {
shaderStageInfo.pName = "main"; shaderStageInfo.pName = "main";
shaderStages.push_back(shaderStageInfo); shaderStages.push_back(shaderStageInfo);
} }
auto it = refl::UClass::MetaTable.find(shader->GetVertexName()); auto it = refl::UClass::MetaTable.find(shader.Name());
auto meta = it->second->vtable.GetMeta("vkMeta"); auto meta = it->second->vtable.GetMeta("vkMeta");
// 设置顶点输入格式 // 设置顶点输入格式
VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
@ -277,7 +277,7 @@ namespace vulkanapi {
depthStencilInfo.front = {}; depthStencilInfo.front = {};
depthStencilInfo.back = {}; depthStencilInfo.back = {};
auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader->GetInfo()); auto descriptorSetLayout = VulkanContext::CreateDescriptorSetLayout(shader.GetInfo());
auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {}); auto pipelineLayout = VulkanContext::CreatePipelineLayout({ descriptorSetLayout }, {});
VkGraphicsPipelineCreateInfo pipelineInfo{}; VkGraphicsPipelineCreateInfo pipelineInfo{};
@ -302,48 +302,16 @@ namespace vulkanapi {
if (vkCreateGraphicsPipelines(device.Ptr(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeLine) != VK_SUCCESS) if (vkCreateGraphicsPipelines(device.Ptr(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeLine) != VK_SUCCESS)
throw std::runtime_error("failed to create graphics pipeline!"); throw std::runtime_error("failed to create graphics pipeline!");
//for (auto& shaderModule : shaderModules) for (auto& shaderModule : shaderModules)
//vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr); vkDestroyShaderModule(device.Ptr(), shaderModule.second, nullptr);
auto vulkan_pipeline = GetNextPipeline(shader->GetID()); VulkanPipeline& vulkan_pipeline = PipelineTable[shader.GetGuid()];
vulkan_pipeline->name = "";//shader->GetName(); vulkan_pipeline.name = shader.Name();
vulkan_pipeline->pipeline = pipeLine; vulkan_pipeline.pipeline = pipeLine;
vulkan_pipeline->inUse = true; vulkan_pipeline.inUse = true;
vulkan_pipeline->pipelineLayout = pipelineLayout; vulkan_pipeline.pipelineLayout = pipelineLayout;
vulkan_pipeline->descriptorSetLayout = descriptorSetLayout; vulkan_pipeline.descriptorSetLayout = descriptorSetLayout;
vulkan_pipeline->descriptorSet = backend.GetPool().Allocate(descriptorSetLayout); vulkan_pipeline.descriptorSet = backend.GetPool().Allocate(descriptorSetLayout);
} }
VulkanVAO* RenderVulkanAPI::GetNextVAO(uint32_t& index)
{
uint32_t length = (uint32_t)VAOList.size();
for (uint32_t i = 0; i < length; i++)
{
if (!VAOList[i]->inUse) {
index = i;
return VAOList[i];
}
}
index = length;
auto vao = new VulkanVAO();
VAOList.push_back(vao);
return vao;
}
VulkanPipeline* RenderVulkanAPI::GetNextPipeline(uint32_t& index)
{
uint32_t length = (uint32_t)PiPelineList.size();
for (uint32_t i = 0; i < length; i++)
{
if (!PiPelineList[i]->inUse) {
index = i;
return PiPelineList[i];
}
}
index = length;
auto info = new VulkanPipeline();
PiPelineList.push_back(info);
return info;
}
} }

View File

@ -4,8 +4,10 @@
#include "render/renderapi.h" #include "render/renderapi.h"
#include "vulkan_struct.h" #include "vulkan_struct.h"
#include "vulkan_context.h" #include "vulkan_context.h"
#include "asset/res/guid.h"
namespace vulkanapi namespace vulkanapi
{ {
using engineapi::Guid;
class RenderTarget; class RenderTarget;
class Swapchain; class Swapchain;
class RenderVulkanAPI : public RenderAPI class RenderVulkanAPI : public RenderAPI
@ -15,10 +17,9 @@ namespace vulkanapi
VulkanContext context; VulkanContext context;
Swapchain* swapchain{nullptr}; Swapchain* swapchain{nullptr};
vector<RenderTarget*> TargetList; vector<RenderTarget*> TargetList;
vector<VulkanVAO*> VAOList;
vector<RenderPass*> PassList; vector<RenderPass*> PassList;
vector<VulkanPipeline*> PiPelineList; hash_table<Guid, VulkanPipeline> PipelineTable;
hash_table<Guid, void*> ShaderInfoList; hash_table<Guid, VulkanVAO> VAOTable;
public: public:
RenderVulkanAPI(); RenderVulkanAPI();
~RenderVulkanAPI()override; ~RenderVulkanAPI()override;
@ -36,13 +37,10 @@ namespace vulkanapi
void BeginFrame()override; void BeginFrame()override;
void EndFrame()override; void EndFrame()override;
void SetStaticMesh(Mesh* mesh)override; void SetStaticMesh(Mesh& mesh)override;
void DrawStaticMesh(Mesh* mesh)override; void DrawStaticMesh(Mesh& mesh)override;
void LoadShader(Shader* shader)override; void LoadShader(Shader& shader)override;
public:
VulkanVAO* GetNextVAO(uint32_t& index);
VulkanPipeline* GetNextPipeline(uint32_t& index);
public: public:
static RenderVulkanAPI* GetSingletonPtr() { static RenderVulkanAPI* GetSingletonPtr() {
return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr(); return (RenderVulkanAPI*)RenderAPI::GetSingletonPtr();

View File

@ -7,9 +7,8 @@ target("zengine")
set_rundir(".") set_rundir(".")
add_rules("volk.env", "glsl.env") add_rules("volk.env", "glsl.env")
add_rules("c++.codegen",{ add_rules("c++.codegen",{
files = {"src/engine/render/meta/*.h", files = {"src/engine/render/asset/*.h",
"src/engine/asset/res/guid.h", "src/engine/asset/res/*.h"}
"src/engine/asset/res/meta_bundle.h",}
}) })
add_deps("zlog","zlib") add_deps("zlog","zlib")
add_defines("VULKAN_API") add_defines("VULKAN_API")