support opengl asset

This commit is contained in:
ouczbs 2024-07-07 22:48:31 +08:00
parent a00d3bba06
commit c250a3cb4e
20 changed files with 211 additions and 161 deletions

View File

@ -1,22 +0,0 @@
#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

@ -2,24 +2,34 @@
#include "file_manager.h"
#include "yaml/yaml.h"
#include <fstream>
#include "file_handle.h"
namespace engineapi {
constexpr string asset_token = "#__asset__\n";
void AssetLoader::Init() {
ResourceManager::GetSingleton().RegisterLoader<AssetLoader>(".asset");
}
ResourceBundle AssetLoader::LoadFile(PackagePath handle, const MetaBundle& meta)
ResourceBundle AssetLoader::LoadFile(PackagePath path, const MetaBundle& meta)
{
FileHandle handle(path);
if (!handle.Open(FILE_OP::READ, mFileFlag & FileFlag::File_Binary)) {
return {};
}
string text1 = handle.ReadUntil(asset_token);
string text2 = handle.ReadUntil(asset_token);
string text3 = handle.ReadUntil(asset_token);
return ResourceBundle();
}
void AssetLoader::SaveFile(PackagePath handle, const ResourceBundle& bundle)
void AssetLoader::SaveFile(PackagePath path, const ResourceBundle& bundle)
{
YAML::Node result;
FileHandle handle(path);
handle.Open(FILE_OP::WRITE, mFileFlag & FileFlag::File_Binary);
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);
RscHandle<Asset> asset = elem.AsHandle<Asset>();
string name = string(asset->meta->name) + "=" + asset->GetGuid().ToString();
handle.WriteLine(name);
string text = YAML::Text_Serialize(refl::Any{ asset.res, asset->meta});
handle.WriteLine(text);
handle.WriteLine(asset_token);
}
//FileManager::SaveTextFile(handle, YAML::Dump(result));
}
}

View File

@ -4,7 +4,7 @@ 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;
ResourceBundle LoadFile(PackagePath path, const MetaBundle& meta) override;
void SaveFile(PackagePath path, const ResourceBundle& bundle) override;
};
}

View File

@ -1,6 +1,7 @@
#include "file_handle.h"
#include <algorithm>
#define READ_DATA_SIZE 1024
#define READ_DATA_SIZE 100
#define TOKEN_SIZE 100
namespace engineapi {
FileHandle& FileHandle::Open(FILE_OP _op, bool is_binarry)
{
@ -10,10 +11,13 @@ namespace engineapi {
{
case engineapi::FILE_OP::READ:
{
vfile = std::ifstream(file_path, is_binarry ? std::ios::binary : 0);
if (!Reader().is_open()) {
vfile = std::ifstream(file_path, is_binarry ? std::ios::binary | std::ios::ate : std::ios::ate);
auto& fi = Reader();
if (!fi.is_open()) {
return *this;
}
size = fi.tellg();
fi.seekg(0);
break;
}
case engineapi::FILE_OP::WRITE:
@ -37,54 +41,36 @@ namespace engineapi {
fi.read((char*)data, size);
return fi.gcount();
}
string FileHandle::ReadUntil(const string& token)
bool FileHandle::FindNext(const char* begin, const char* end, size_t& stop)
{
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;
size_t start = fi.tellg();
size_t cur = start;
char chunk[READ_DATA_SIZE + TOKEN_SIZE];
const char* last = chunk + READ_DATA_SIZE + TOKEN_SIZE;
while (cur < stop) {
fi.read(chunk + TOKEN_SIZE, READ_DATA_SIZE);
size_t count = fi.gcount();
if (count < READ_DATA_SIZE || cur + count > stop) {
fi.clear();
}
buffer_size += READ_DATA_SIZE;
}
return buffer;
}
vector<char> FileHandle::ReadUntil(const vector<char>& 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<char> 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;
const char* first = cur == start ? chunk + TOKEN_SIZE : chunk;
const char* it = std::search(first, last, begin, end);
if (it != last) {
fi.seekg(start);
stop = cur + (it - first) - TOKEN_SIZE;
return true;
}
buffer_size += READ_DATA_SIZE;
buffer.insert(buffer.end(), READ_DATA_SIZE, 0);
if (count < READ_DATA_SIZE) {
fi.seekg(start);
stop = cur + count;
return false;
}
cur += count;
memcpy(chunk, chunk + READ_DATA_SIZE, TOKEN_SIZE);
}
return buffer;
fi.seekg(start);
return false;
}
void FileHandle::Write(const char* data,size_t size)
{

View File

@ -15,6 +15,7 @@ namespace engineapi {
protected:
uint32_t flag{0};
FILE_OP op{ FILE_OP::NONE};
size_t size{0};
std::variant<std::ifstream, std::ofstream, nullptr_t> vfile{nullptr};
public:
using PackagePath::PackagePath;
@ -40,26 +41,27 @@ namespace engineapi {
}
template<typename T = vector<char>>
T ReadLeft();
string ReadUntil(const string& token);
vector<char> ReadUntil(const vector<char>& token);
bool FindNext(const char* begin, const char* end, size_t& stop);
template<typename T>
T ReadUntil(const T& token);
void Write(const char* data, size_t size);
};
template<typename T>
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);
template<typename T = string>
void Write(const T& data) {
Write(data.data(), data.size());
}
return data;
}
}
template<typename T = string>
void WriteLine(const T& data) {
Write<T>(data);
Write<T>(T{ "\n" });
}
};
class FileSpan {
size_t start{ 0 }, stop{ 0 };
FileHandle& handle;
public:
FileSpan(FileHandle& handle, size_t start, size_t stop = 0)
: handle(handle), start(start), stop(stop){}
};
}
#include "file_handle.inl"

View File

@ -87,7 +87,7 @@ namespace engineapi {
}
else {
string text = YAML::Text_Serialize(bundle);
handle.Write(text.data(), text.size());
handle.Write(text);
}
}
void ResourceManager::SaveDirtyFiles()
@ -106,6 +106,11 @@ namespace engineapi {
}
mDirtyBlocks.clear();
}
void ResourceManager::SaveFile(PackagePath path, const ResourceBundle& bundle)
{
auto loader = GetLoader(path.GetExtension());
loader->SaveFile(path, bundle);
}
constexpr const char* FileFlagName = "/engine/assets/file_flag.meta";
void ResourceManager::LoadFileFlag()
{
@ -131,7 +136,7 @@ namespace engineapi {
FileHandle handle(FileFlagName);
handle.Open(FILE_OP::WRITE);
string text = YAML::Text_Serialize(res);
handle.Write(text.data(), text.size());
handle.Write(text);
}
}

View File

@ -70,7 +70,7 @@ namespace engineapi {
MetaBundle GetVisitMeta(const ResourceBundle& bundle);
void SaveMeta(PackagePath path, const MetaBundle& bundle);
void SaveDirtyFiles();
void SaveFile(PackagePath path, const ResourceBundle& bundle);
void LoadFileFlag();
void SaveFileFlag();
uint32_t GetFileFlag(const Name& name);

View File

@ -10,4 +10,13 @@ namespace engineapi {
{
mPtr.BeginLoad();
}
void StaticMesh::SetMaterial(RscHandle<Material> material)
{
auto meshes = mPtr.GetMeshs();
for (auto it : meshes) {
it->SetMaterial(material);
}
}
}

View File

@ -9,10 +9,10 @@ namespace engineapi {
public:
StaticMesh(Model& model);
void LoadMesh();
Model& Ptr() {
return mPtr;
}
void LoadMesh();
void SetMaterial(RscHandle<Material> material);
};
}

View File

@ -6,6 +6,7 @@
#include "data/property/actor_property.h"
#include "asset/resource_manager.h"
#include "asset/file_manager.h"
#include "asset/asset_loader.h"
namespace engineapi {
Scene::Scene()
{
@ -16,7 +17,14 @@ namespace engineapi {
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);
auto material = ResourceManager::GetSingleton().LoaderEmplaceResource<Material>();
material->mShader = shader;
ResourceBundle bundle;
bundle.Add(shader);
bundle.Add(material);
const char* path = "/engine/assets/asset/mesh1.asset";
ResourceManager::GetSingleton().SaveFile(path, bundle);
auto bundle2 = ResourceManager::GetSingleton().Load(path);
{
ActorProperty property;
property.id = 1;
@ -24,7 +32,7 @@ namespace engineapi {
property.path = "/engine/assets/models/cube.obj";
actor1 = ActorMesh::New(property);
actor1->LoadMesh();
//actor1->Ptr().SetMaterial(material);
actor1->SetMaterial(material);
}
{
ActorProperty property;
@ -44,10 +52,10 @@ namespace engineapi {
void Scene::Render()
{
RenderAPI::GetSingletonPtr()->Render(*mCamera);
//auto meshs = actor1->Ptr().GetMeshs();
//for (auto it : meshs) {
//RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it);
//}
auto& meshs = actor1->Ptr().GetMeshs();
for (auto it : meshs) {
RenderAPI::GetSingletonPtr()->DrawStaticMesh(*it);
}
}
void Scene::AddGameObject(GameObject* gameObject)
{

View File

@ -1,5 +1,7 @@
#include "opengl_glsl_loader.h"
#include "asset/file_handle.h"
#include "render/tool/glsl_to_spirv.h"
#include <GL/glew.h>
using namespace engineapi;
namespace openglapi {
void OpenGLGlslLoader::Init()
@ -9,8 +11,53 @@ namespace openglapi {
}
ResourceBundle OpenGLGlslLoader::LoadFile(PackagePath path, const MetaBundle& meta)
{
return {};
auto m = meta.FetchMeta<ShaderProgram>();
auto program = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<glShaderProgram>(m->guid)
: ResourceManager::GetSingleton().LoaderEmplaceResource<glShaderProgram>();
FileHandle handle(path);
shaderc_shader_kind shader_kind = GlslToSpirv::GetShaderKind(path.GetExtension());
if (!handle.Open(FILE_OP::READ, mFileFlag & FileFlag::File_Binary)) {
return program;
}
if (mFileFlag & FileFlag::File_Binary) {
vector<char> data = handle.ReadAll();
std::vector<unsigned int> spirv(data.size() / 4);
std::memcpy(spirv.data(), data.data(), data.size());
program->Load(shader_kind, spirv);
}
else {
string glsl = handle.ReadAll<string>();
auto spirv = GlslToSpirv::ToSpirv(glsl, shader_kind, path.GetFileName());
if (spirv) {
program->Load(shader_kind, *spirv);
}
}
return program;
}
void glShaderProgram::Load(int _type, const std::vector<uint32_t>& spirv)
{
shaderc_shader_kind type = (shaderc_shader_kind)_type;
switch (type)
{
case shaderc_shader_kind::shaderc_vertex_shader:
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderBinary(1, &vertexShader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, spirv.data(), spirv.size() * sizeof(uint32_t));
glSpecializeShaderARB(vertexShader, "main", 0, nullptr, nullptr);
mPtr = vertexShader;
break;
}
case shaderc_shader_kind::shaderc_fragment_shader:
{
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderBinary(1, &fragmentShader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, spirv.data(), spirv.size() * sizeof(uint32_t));
glSpecializeShaderARB(fragmentShader, "main", 0, nullptr, nullptr);
mPtr = fragmentShader;
break;
}
default:
break;
}
}
}

View File

@ -3,6 +3,15 @@
#include "asset/resource_manager.h"
namespace openglapi {
using engineapi::table;
class glShaderProgram : public engineapi::ShaderProgram {
private:
uint32_t mPtr{0};
public:
uint32_t Ptr() {
return mPtr;
}
void Load(int type, const std::vector<uint32_t>& spirv);
};
class OpenGLGlslLoader : public engineapi::IFileLoader
{
inline static table<engineapi::Guid, void*> ShaderTable;

View File

@ -43,13 +43,6 @@ namespace openglapi {
void RenderOpenGLApi::BeginFrame()
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-0.5f, -0.5f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex2f(0.5f, -0.5f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2f(0.0f, 0.5f);
}
void RenderOpenGLApi::EndFrame()
{
@ -95,12 +88,26 @@ namespace openglapi {
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 解绑VAO
glBindVertexArray(0);
VAOTable[mesh.GetGuid()] = VAO;
VAOTable[mesh.GetGuid()] = OpenGLPtr{ VAO };
}
void RenderOpenGLApi::DrawStaticMesh(Mesh& mesh)
{
OpenGLPtr& shaderPtr = ShaderTable[mesh.GetShaderGuid()];
glUseProgram(shaderPtr);
OpenGLPtr& meshPtr = VAOTable[mesh.GetGuid()];
glBindVertexArray(meshPtr);
glDrawElements(GL_TRIANGLES, mesh.GetIndices().size(), GL_UNSIGNED_INT, 0);
}
void RenderOpenGLApi::LoadShader(Shader& shader)
{
auto vertModule = shader.GetVertHandle<glShaderProgram>()->Ptr();
auto fragModule = shader.GetFragHandle<glShaderProgram>()->Ptr();
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertModule);
glAttachShader(shaderProgram, fragModule);
glLinkProgram(shaderProgram);
glDeleteProgram(vertModule);
glDeleteProgram(fragModule);
ShaderTable[shader.GetGuid()] = OpenGLPtr{ shaderProgram };
}
}

View File

@ -9,14 +9,13 @@ namespace openglapi {
using engineapi::Guid;
using zstd::hash_table;
class OpenGLWindow;
struct OpenGLVAO {
int VAO;
};
using OpenGLPtr = uint32_t;
class RenderOpenGLApi : public engineapi::RenderAPI {
public:
RenderContext context;
OpenGLWindow* window;
hash_table<Guid, OpenGLVAO> VAOTable;
hash_table<Guid, OpenGLPtr> VAOTable;
hash_table<Guid, OpenGLPtr> ShaderTable;
public:
RenderContext* GetContext() override {
return &context;

View File

@ -7,6 +7,7 @@ namespace engineapi {
REFL_FRIEND(Material)
UPROPERTY()
RscHandle<Shader> mShader;
friend class Scene;
public:
Material();
~Material();

View File

@ -21,6 +21,9 @@ namespace engineapi {
Guid GetShaderGuid() {
return mMaterial->GetShader().guid;
}
void SetMaterial(RscHandle<Material> material) {
mMaterial = material;
}
RscHandle<Material> GetMaterial() {
return mMaterial;
}

View File

@ -1,8 +1,10 @@
#include "glsl_to_spirv.h"
#include <shaderc/shaderc.hpp>
#include "meta/hash.h"
using meta::string_hash;
namespace engineapi
{
optional<vector<uint32_t>> GlslToSpirv::spirv(const string& glsl, shaderc_shader_kind kind, string_view code_id)
optional<vector<uint32_t>> GlslToSpirv::ToSpirv(const string& glsl, shaderc_shader_kind kind, string_view code_id)
{
optional<vector<uint32_t>> spirv_out;
{
@ -17,5 +19,17 @@ namespace engineapi
}
return spirv_out;
}
shaderc_shader_kind GlslToSpirv::GetShaderKind(string_view ext)
{
switch (string_hash(ext))
{
case string_hash(".vert"): return shaderc_shader_kind::shaderc_vertex_shader;
case string_hash(".geom"): return shaderc_shader_kind::shaderc_geometry_shader;
case string_hash(".tese"): return shaderc_shader_kind::shaderc_tess_evaluation_shader;
case string_hash(".tesc"): return shaderc_shader_kind::shaderc_tess_control_shader;
case string_hash(".frag"): return shaderc_shader_kind::shaderc_fragment_shader;
default: return shaderc_shader_kind::shaderc_miss_shader;
}
}
}

View File

@ -12,6 +12,7 @@ namespace engineapi
class GlslToSpirv
{
public:
static optional<vector<uint32_t>> spirv(const string& glsl, shaderc_shader_kind kind, string_view code_id = "unknown_shader");
static shaderc_shader_kind GetShaderKind(string_view ext);
static optional<vector<uint32_t>> ToSpirv(const string& glsl, shaderc_shader_kind kind, string_view code_id = "unknown_shader");
};
}

View File

@ -4,38 +4,9 @@
#include "render/asset/vertex.h"
#include "vkmeta_vertex_gen.inl"
#include "asset/file_handle.h"
#include "meta/hash.h"
#include <vulkan/vulkan.hpp>
using namespace engineapi;
namespace vulkanapi {
using std::string_view;
using meta::string_hash;
shaderc_shader_kind ConvertStageSC(vk::ShaderStageFlagBits stage)
{
static hash_table< vk::ShaderStageFlagBits, shaderc_shader_kind> conv
{
{ vk::ShaderStageFlagBits::eVertex ,shaderc_shader_kind::shaderc_vertex_shader },
{ vk::ShaderStageFlagBits::eFragment ,shaderc_shader_kind::shaderc_fragment_shader },
{ vk::ShaderStageFlagBits::eGeometry ,shaderc_shader_kind::shaderc_geometry_shader },
{ vk::ShaderStageFlagBits::eTessellationControl ,shaderc_shader_kind::shaderc_tess_control_shader },
{ vk::ShaderStageFlagBits::eTessellationEvaluation,shaderc_shader_kind::shaderc_tess_evaluation_shader },
};
auto itr = conv.find(stage);
return itr->second;
}
vk::ShaderStageFlagBits GetShaderType(string_view ext)
{
switch (string_hash(ext))
{
case string_hash(".vert"): return vk::ShaderStageFlagBits::eVertex;
case string_hash(".geom"): return vk::ShaderStageFlagBits::eGeometry;
case string_hash(".tese"): return vk::ShaderStageFlagBits::eTessellationEvaluation;
case string_hash(".tesc"): return vk::ShaderStageFlagBits::eTessellationControl;
case string_hash(".frag"): return vk::ShaderStageFlagBits::eFragment;
case string_hash(".comp"): return vk::ShaderStageFlagBits::eCompute;
default: return vk::ShaderStageFlagBits::eAll;
}
}
void VulkanGlslLoader::Init()
{
REGISTER_META_TABLE(PosVertex);
@ -50,7 +21,7 @@ namespace vulkanapi {
auto m = meta.FetchMeta<ShaderProgram>();
auto program = m ? ResourceManager::GetSingleton().LoaderEmplaceResource<vkShaderProgram>(m->guid)
: ResourceManager::GetSingleton().LoaderEmplaceResource<vkShaderProgram>();
FileHandle handle(path + ".meta");
FileHandle handle(path);
if (!handle.Open(FILE_OP::READ, mFileFlag & FileFlag::File_Binary)) {
return program;
}
@ -63,8 +34,8 @@ namespace vulkanapi {
}
else {
string glsl = handle.ReadAll<string>();
auto shader_enum = GetShaderType(path.GetExtension());
auto spirv = GlslToSpirv::spirv(glsl, ConvertStageSC(shader_enum), path.GetFileName());
auto shader_kind = GlslToSpirv::GetShaderKind(path.GetExtension());
auto spirv = GlslToSpirv::ToSpirv(glsl, shader_kind, path.GetFileName());
if (spirv) {
program->Load(*spirv);
//LoadShaderInfo(program->GetGuid(), *spirv);
@ -72,7 +43,7 @@ namespace vulkanapi {
}
return program;
}
void vkShaderProgram::Load(const std::vector<unsigned int>& spirv)
void vkShaderProgram::Load(const std::vector<uint32_t>& spirv)
{
RenderVulkanAPI* renderApi = RenderVulkanAPI::GetSingletonPtr();
mPtr = renderApi->backend.GetDevice().CreateShaderModule(spirv);

View File

@ -10,7 +10,7 @@ namespace vulkanapi {
VkShaderModule Ptr() {
return mPtr;
}
void Load(const std::vector<unsigned int>& spirv);
void Load(const std::vector<uint32_t>& spirv);
};
class VulkanGlslLoader : public engineapi::IFileLoader
{