Merge pull request #5 from Jiga228/main #1

Merged
Jiga228 merged 12 commits from render into main 2026-06-01 09:20:12 +00:00
47 changed files with 8772 additions and 783 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
[submodule "glfw"]
path = glfw
url = https://github.com/glfw/glfw.git
url = https://git.burntroosters.twc1.net/Jiga228/glfw.git
+31 -6
View File
@@ -4,13 +4,12 @@ find_package(Vulkan REQUIRED)
file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.h" "*.hpp")
add_library(${CORE_NAME} STATIC ${SRC})
target_compile_features(${CORE_NAME} PRIVATE cxx_std_17)
target_include_directories(${CORE_NAME} PUBLIC
add_library(Core STATIC ${SRC})
target_compile_features(Core PRIVATE cxx_std_17)
target_include_directories(Core PUBLIC
${PROJECT_SOURCE_DIR}/FastRTTI
${PROJECT_SOURCE_DIR}/Delegate
)
target_include_directories(${CORE_NAME}
target_include_directories(Core
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/glfw/Include
@@ -18,9 +17,35 @@ target_include_directories(${CORE_NAME}
${Vulkan_INCLUDE_DIRS}
)
target_link_libraries(${CORE_NAME} PRIVATE
target_link_libraries(Core PRIVATE
${CMAKE_DL_LIBS} # For linux
FastRTTI
glfw
Vulkan::Vulkan
)
file(GLOB_RECURSE HEADERS
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.hpp"
)
foreach (HEADER ${HEADERS})
file(RELATIVE_PATH R_PATH
"${CMAKE_CURRENT_SOURCE_DIR}"
"${HEADER}"
)
get_filename_component(HEADER_DIR ${R_PATH} DIRECTORY)
add_custom_command(
TARGET Core
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include/${HEADER_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${HEADER}"
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include/${R_PATH}"
COMMENT "Copy Core headers"
)
endforeach ()
+2
View File
@@ -74,6 +74,7 @@ CoreInstance::CoreInstance()
render_engine_ = RenderEngineFactory(*this);
} catch (const std::exception& e)
{
render_engine_ = nullptr;
std::cerr << "[!] Init render engine: " << e.what() << '\n';
return;
}
@@ -83,6 +84,7 @@ CoreInstance::CoreInstance()
game_ = GameFactory(*this);
} catch (const std::exception& e)
{
game_ = nullptr;
std::cout << "[!] Init game instance: " << e.what() << '\n';
return;
}
+6 -7
View File
@@ -2,7 +2,6 @@
#include "Game/SaveMap/SaveMap.hpp"
#include "Game/World/World.hpp"
#include "Log/Log.hpp"
void Actor::OnDestroy()
{
@@ -16,17 +15,17 @@ Actor::Actor() : loc_(new Vector3D), rot_(new Vector3D), scale_(new Vector3D)
std::shared_ptr<SaveMap> Actor::save()
{
return std::make_shared<SaveMap>("Actor")
->SaveObject("loc", static_cast<UType::object_ptr<ISave>>(loc_))
->SaveObject("rot", static_cast<UType::object_ptr<ISave>>(rot_))
->SaveObject("scale", UType::object_ptr<ISave>(scale_))
->SaveObject("loc", loc_)
->SaveObject("rot", rot_)
->SaveObject("scale", scale_)
->SaveListStrings("tags", std::move(tags));
}
void Actor::load(std::shared_ptr<SaveMap> save)
{
loc_ = static_cast<UType::object_ptr<Vector3D>>(save->GetObject("loc"));
rot_ = static_cast<UType::object_ptr<Vector3D>>(save->GetObject("rot"));
scale_ = static_cast<UType::object_ptr<Vector3D>>(save->GetObject("scale"));
loc_ = std::static_pointer_cast<Vector3D>(save->GetObject("loc"));
rot_ = std::static_pointer_cast<Vector3D>(save->GetObject("rot"));
scale_ = std::static_pointer_cast<Vector3D>(save->GetObject("scale"));
tags = std::move(save->GetListString("tags"));
}
+3 -4
View File
@@ -7,7 +7,6 @@
#include "Game/SaveMap/ISave.h"
#include "Delegate/Delegate.h"
#include "Math/Vector.hpp"
#include "Types/object_ptr.hpp"
class World;
GENERATE_META(Actor)
@@ -17,7 +16,7 @@ class Actor : public ISave, public IRTTI
World* world_;
std::string name_;
UType::object_ptr<Vector3D> loc_, rot_, scale_;
std::shared_ptr<Vector3D> loc_, rot_, scale_;
std::list<std::string> tags;
@@ -42,14 +41,14 @@ public:
* Вызывает делегат OnSetActorLocate
*/
void SetActorLocate(const Vector3D& loc) noexcept;
inline const UType::object_ptr<Vector3D> GetActorLocate() const { return loc_; }
inline Vector3D GetActorLocate() const { return *loc_; }
/*
* Изменяет ориентацию в пространстве
* Вызывает делегат OnSetActorRotate
*/
void SetActorRotate(const Vector3D& rot) noexcept;
inline const UType::object_ptr<Vector3D> GetActorRotate() const { return rot_; }
inline Vector3D GetActorRotate() const { return *rot_; }
void AddTag(const std::string& tag) noexcept;
void RemoveTag(const std::string& tag) noexcept;
-2
View File
@@ -1,12 +1,10 @@
#include "ObjectFactory.hpp"
#include "Actors/Mesh/StaticMesh.hpp"
#include "Game/Actors/Actor.hpp"
#include "Math/Vector.hpp"
std::vector<ObjectFactory> base_object_factories = {
GENERATE_FACTORY_OBJECT(Actor)
GENERATE_FACTORY_OBJECT(StaticMesh)
GENERATE_FACTORY_OBJECT(Vector2D)
GENERATE_FACTORY_OBJECT(Vector3D)
};
-5
View File
@@ -1,11 +1,9 @@
#include "GameInstance.hpp"
#include <filesystem>
#include <fstream>
#include <chrono>
#include <thread>
#include "ModelManager.hpp"
#include "Core/CoreInstance.hpp"
#include "Game/WorldFactory.hpp"
#include "Game/World/World.hpp"
@@ -19,8 +17,6 @@ GameInstance::GameInstance(CoreInstance& core) : core(core)
// Init directories
std::filesystem::create_directories(std::filesystem::path("./Resources"));
current_model_manager_ = new ModelManager();
for (auto& factories : world_factories)
{
if (factories.world_name == base_world)
@@ -38,7 +34,6 @@ GameInstance::GameInstance(CoreInstance& core) : core(core)
GameInstance::~GameInstance()
{
delete world;
delete current_model_manager_;
}
void GameInstance::start()
-3
View File
@@ -5,7 +5,6 @@
class CoreInstance;
class World;
class ModelManager;
#define GENERATE_FACTORY_GAME_INSTANCE(Class) \
GameInstance* GameFactory(CoreInstance& core) { return new Class(core); }
@@ -14,7 +13,6 @@ class GameInstance
{
CoreInstance& core;
World* world = nullptr;
ModelManager* current_model_manager_ = nullptr;
std::atomic<bool> is_running = true;
@@ -31,7 +29,6 @@ public:
World* GetWorld() const { return world; }
CoreInstance& GetCore() const { return core; }
ModelManager* GetCurrentModelManager() const { return current_model_manager_; }
friend class CoreInstance;
};
-107
View File
@@ -1,107 +0,0 @@
#include "ModelManager.hpp"
#include "Log/Log.hpp"
ModelManager::StaticModel::StaticModel(const std::vector<Voxel>& voxels, std::string name):
name_(std::move(name)),
voxels_(voxels)
{
glm::ivec3 sum_moments{0, 0, 0};
int sum_masses = 0;
for (auto& i : voxels_)
{
sum_moments += glm::ivec3{i.loc.x * i.mass, i.loc.y * i.mass, i.loc.z * i.mass};
sum_masses += i.mass;
}
if(sum_masses != 0)
sum_moments /= sum_masses;
else if (!voxels_.empty())
{
sum_moments.x /= static_cast<int>(voxels_.size());
sum_moments.y /= static_cast<int>(voxels_.size());
sum_moments.z /= static_cast<int>(voxels_.size());
}
mass_center_ = sum_moments;
}
ModelManager::StaticModel::~StaticModel()
{
OnDestroy.Call(name_);
}
ModelManager::owner_counter::owner_counter(const owner_counter& other) : counter(other.counter.load()), model(other.model)
{
}
unsigned int ModelManager::FNV1aHash(const char* buf)
{
unsigned int h_val = 0x811c9dc5;
while (*buf)
{
h_val ^= static_cast<unsigned int>(*buf++);
h_val *= 0x01000193;
}
return h_val;
}
void ModelManager::OnDestroySometimeModelCaller(const std::string& name)
{
Loging::Log("Free model: " + name);
OnDestroySometimeModel.Call(name);
}
ModelManager::~ModelManager()
{
for (const auto& [it, counter] : models)
{
counter.model->OnDestroy.unbind(this, &ModelManager::OnDestroySometimeModelCaller);
}
models.clear();
}
ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name)
{
if (name.empty())
return nullptr;
unsigned int hash = FNV1aHash(name.c_str());
auto counter = models.find(hash);
if (counter != models.cend())
{
++counter->second.counter;
return counter->second.model;
}
Loging::Log("Load new model: " + name);
std::vector<Voxel> model_data;
// Load model_data
owner_counter new_counter;
new_counter.counter.store(1);
new_counter.model = new StaticModel(model_data, name);
new_counter.model->OnDestroy.bind(this, &ModelManager::OnDestroySometimeModelCaller);
models.try_emplace(hash, new_counter);
OnLoadSometimeModel.Call(new_counter.model);
return new_counter.model;
}
void ModelManager::FreeModel(const std::string& name)
{
if (name.empty())
return;
unsigned int hash = FNV1aHash(name.c_str());
auto counter = models.find(hash);
--counter->second.counter;
StaticModel* model = counter->second.model;
if (counter->second.counter.load() == 0)
{
models.erase(hash);
delete model;
}
}
-58
View File
@@ -1,58 +0,0 @@
#pragma once
#include <unordered_map>
#include <vector>
#include <string>
#include <Delegate/Delegate.h>
#include <glm/glm.hpp>
class ModelManager
{
public:
struct Voxel
{
glm::vec3 loc, color;
int mass;
};
class StaticModel
{
std::string name_;
std::vector<Voxel> voxels_;
glm::vec3 mass_center_;
public:
Delegate<const std::string&> OnDestroy;
StaticModel(const std::vector<Voxel>& voxels, std::string name);
~StaticModel();
const std::vector<Voxel>& GetVoxels() const { return voxels_; }
glm::vec3 GetMassCenter() const { return mass_center_; }
const std::string& GetName() const { return name_; }
};
struct owner_counter
{
std::atomic_ullong counter;
StaticModel* model;
owner_counter() = default;
owner_counter(const owner_counter& other);
};
private:
std::unordered_map<unsigned int, owner_counter> models;
static unsigned int FNV1aHash (const char *buf);
void OnDestroySometimeModelCaller(const std::string& name);
public:
Delegate<std::string> OnDestroySometimeModel;
Delegate<StaticModel*> OnLoadSometimeModel;
~ModelManager();
StaticModel* LoadModel(const std::string& name);
void FreeModel(const std::string& name);
};
+13 -13
View File
@@ -97,7 +97,7 @@ SaveMap::SaveMap(const std::string& json_data)
end = object_json.find('\"', begin);
std::string object_name = object_json.substr(begin, end - begin);
UType::object_ptr<ISave> object_ptr(MakeObjectByName(object_name));
std::shared_ptr<ISave> object_ptr(MakeObjectByName(object_name));
object_ptr->load(std::make_shared<SaveMap>(object_json));
save_objects[name.c_str() + 1] = object_ptr;
@@ -171,10 +171,10 @@ SaveMap::SaveMap(const std::string& json_data)
}
} else if (name[1] == 'o')
{
save_vector_objects[key] = std::vector<UType::object_ptr<ISave>>();
save_vector_objects[key] = std::vector<std::shared_ptr<ISave>>();
if (arr_data.length() == 2)
continue;
std::vector<UType::object_ptr<ISave>>& vector_object = save_vector_objects[key];
std::vector<std::shared_ptr<ISave>>& vector_object = save_vector_objects[key];
size_t j = 1;
while (j < arr_data.length())
@@ -198,7 +198,7 @@ SaveMap::SaveMap(const std::string& json_data)
size_t end_name = object_json.find('\"', begin_name);
std::string object_name = object_json.substr(begin_name, end_name - begin_name);
UType::object_ptr<ISave> object_ptr(MakeObjectByName(object_name));
std::shared_ptr<ISave> object_ptr(MakeObjectByName(object_name));
object_ptr->load(std::make_shared<SaveMap>(object_json));
vector_object.push_back(object_ptr);
@@ -272,10 +272,10 @@ SaveMap::SaveMap(const std::string& json_data)
}
} else if (name[1] == 'o')
{
save_list_objects[key] = std::list<UType::object_ptr<ISave>>();
save_list_objects[key] = std::list<std::shared_ptr<ISave>>();
if (arr_data.length() == 2)
continue;
std::list<UType::object_ptr<ISave>>& list_object = save_list_objects[key];
std::list<std::shared_ptr<ISave>>& list_object = save_list_objects[key];
size_t j = 1;
while (j < arr_data.length())
@@ -299,7 +299,7 @@ SaveMap::SaveMap(const std::string& json_data)
size_t end_name = object_json.find('\"', begin_name);
std::string object_name = object_json.substr(begin_name, end_name - begin_name);
UType::object_ptr<ISave> object_ptr(MakeObjectByName(object_name));
std::shared_ptr<ISave> object_ptr(MakeObjectByName(object_name));
object_ptr->load(std::make_shared<SaveMap>(object_json));
list_object.push_back(object_ptr);
@@ -389,7 +389,7 @@ std::shared_ptr<SaveMap> SaveMap::SaveString(const char* name, const std::string
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveObject(const char* name, UType::object_ptr<ISave> object) noexcept
std::shared_ptr<SaveMap> SaveMap::SaveObject(const char* name, std::shared_ptr<ISave> object) noexcept
{
save_objects[name] = object;
return std::shared_ptr<SaveMap>(this);
@@ -413,7 +413,7 @@ std::shared_ptr<SaveMap> SaveMap::SaveVectorStrings(const char* name, std::vecto
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveVectorObject(const char* name, std::vector<UType::object_ptr<ISave>>&& value) noexcept
std::shared_ptr<SaveMap> SaveMap::SaveVectorObject(const char* name, std::vector<std::shared_ptr<ISave>>&& value) noexcept
{
save_vector_objects[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
@@ -437,7 +437,7 @@ std::shared_ptr<SaveMap> SaveMap::SaveListStrings(const char* name, std::list<st
return std::shared_ptr<SaveMap>(this);
}
std::shared_ptr<SaveMap> SaveMap::SaveListObject(const char* name, std::list<UType::object_ptr<ISave>>&& value) noexcept
std::shared_ptr<SaveMap> SaveMap::SaveListObject(const char* name, std::list<std::shared_ptr<ISave>>&& value) noexcept
{
save_list_objects[name] = std::move(value);
return std::shared_ptr<SaveMap>(this);
@@ -458,7 +458,7 @@ std::string SaveMap::GetString(const char* name)
return save_string[name];
}
UType::object_ptr<ISave> SaveMap::GetObject(const char* name)
std::shared_ptr<ISave> SaveMap::GetObject(const char* name)
{
return save_objects[name];
}
@@ -478,7 +478,7 @@ std::vector<std::string> SaveMap::GetVectorString(const char* name)
return save_vector_strings[name];
}
std::vector<UType::object_ptr<ISave>>& SaveMap::GetVectorObject(const char* name)
std::vector<std::shared_ptr<ISave>>& SaveMap::GetVectorObject(const char* name)
{
return save_vector_objects[name];
}
@@ -498,7 +498,7 @@ std::list<std::string>& SaveMap::GetListString(const char* name)
return save_list_strings[name];
}
std::list<UType::object_ptr<ISave>>& SaveMap::GetListObject(const char* name)
std::list<std::shared_ptr<ISave>>& SaveMap::GetListObject(const char* name)
{
return save_list_objects[name];
}
+9 -10
View File
@@ -1,7 +1,6 @@
#pragma once
#include "ISave.h"
#include "Types/object_ptr.hpp"
#include <unordered_map>
#include <memory>
@@ -18,18 +17,18 @@ class SaveMap final
std::unordered_map<std::string, long long> save_long;
std::unordered_map<std::string, double> save_double;
std::unordered_map<std::string, std::string> save_string;
std::unordered_map<std::string, UType::object_ptr<ISave>> save_objects;
std::unordered_map<std::string, std::shared_ptr<ISave>> save_objects;
// Массивы
std::unordered_map<std::string, std::vector<long long>> save_vector_integer;
std::unordered_map<std::string, std::vector<double>> save_vector_double;
std::unordered_map<std::string, std::vector<UType::object_ptr<ISave>>> save_vector_objects;
std::unordered_map<std::string, std::vector<std::shared_ptr<ISave>>> save_vector_objects;
std::unordered_map<std::string, std::vector<std::string>> save_vector_strings;
// Связаные списки
std::unordered_map<std::string, std::list<long long>> save_list_integer;
std::unordered_map<std::string, std::list<double>> save_list_double;
std::unordered_map<std::string, std::list<UType::object_ptr<ISave>>> save_list_objects;
std::unordered_map<std::string, std::list<std::shared_ptr<ISave>>> save_list_objects;
std::unordered_map<std::string, std::list<std::string>> save_list_strings;
static ISave* MakeObjectByName(const std::string& name);
@@ -48,29 +47,29 @@ public:
std::shared_ptr<SaveMap> SaveInteger(const char* name, int value) noexcept;
std::shared_ptr<SaveMap> SaveDouble(const char* name, double value) noexcept;
std::shared_ptr<SaveMap> SaveString(const char* name, const std::string& value) noexcept;
std::shared_ptr<SaveMap> SaveObject(const char* name, UType::object_ptr<ISave> object) noexcept;
std::shared_ptr<SaveMap> SaveObject(const char* name, std::shared_ptr<ISave> object) noexcept;
std::shared_ptr<SaveMap> SaveVectorInteger(const char* name, std::vector<long long>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorDouble(const char* name, std::vector<double>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorStrings(const char* name, std::vector<std::string>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorObject(const char* name, std::vector<UType::object_ptr<ISave>>&& value) noexcept;
std::shared_ptr<SaveMap> SaveVectorObject(const char* name, std::vector<std::shared_ptr<ISave>>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListInteger(const char* name, std::list<long long>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListDouble(const char* name, std::list<double>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListStrings(const char* name, std::list<std::string>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListObject(const char* name, std::list<UType::object_ptr<ISave>>&& value) noexcept;
std::shared_ptr<SaveMap> SaveListObject(const char* name, std::list<std::shared_ptr<ISave>>&& value) noexcept;
// Методы получения значенй
long long GetInteger(const char* name);
double GetDouble(const char* name);
std::string GetString(const char* name);
UType::object_ptr<ISave> GetObject(const char* name);
std::shared_ptr<ISave> GetObject(const char* name);
std::vector<long long>& GetVectorInteger(const char* name);
std::vector<double>& GetVectorDouble(const char* name);
std::vector<std::string> GetVectorString(const char* name);
std::vector<UType::object_ptr<ISave>>& GetVectorObject(const char* name);
std::vector<std::shared_ptr<ISave>>& GetVectorObject(const char* name);
std::list<long long>& GetListInteger(const char* name);
std::list<double>& GetListDouble(const char* name);
std::list<std::string>& GetListString(const char* name);
std::list<UType::object_ptr<ISave>>& GetListObject(const char* name);
std::list<std::shared_ptr<ISave>>& GetListObject(const char* name);
std::shared_ptr<SaveMap> getParent() const { return parent_; }
const std::string& getClassName() const { return class_name; }
+7 -7
View File
@@ -2,7 +2,7 @@
#include "Game/SaveMap/SaveMap.hpp"
World::World(GameInstance& game_instance) : game_instance(game_instance)
World::World(GameInstance& game_instance) : game_instance_(game_instance)
{
}
@@ -34,7 +34,7 @@ std::shared_ptr<SaveMap> World::save()
void World::load(std::shared_ptr<SaveMap> save)
{
std::vector<std::string> actors_IDs = save->GetVectorString("ActorsIDs");
std::list<UType::object_ptr<Actor>> act = std::move(reinterpret_cast<std::list<UType::object_ptr<Actor>>&>(save->GetListObject("Actors")));
std::list<std::shared_ptr<Actor>> act = std::move(reinterpret_cast<std::list<std::shared_ptr<Actor>>&>(save->GetListObject("Actors")));
size_t i_id = 0;
for (auto& i : act)
@@ -46,13 +46,13 @@ void World::load(std::shared_ptr<SaveMap> save)
}
}
void World::DestroyActor(UType::object_ptr<Actor> ptr)
void World::DestroyActor(std::weak_ptr<Actor> ptr)
{
if (ptr.get() == nullptr)
std::shared_ptr<Actor> actor = ptr.lock();
if (actor.get() == nullptr)
return;
std::string name = ptr->GetName();
std::string name = actor->GetName();
actor->OnDestroy();
actors_map.erase(name);
ptr->OnDestroy();
ptr.destroy();
}
+17 -14
View File
@@ -7,17 +7,15 @@
#include "RTTI.h"
#include "Game/Actors/Actor.hpp"
#include "Game/Actors/Mesh/Mesh.hpp"
#include "Types/object_ptr.hpp"
class GameInstance;
GENERATE_META(World);
class World : public ISave
{
GameInstance& game_instance;
GameInstance& game_instance_;
std::unordered_map<std::string, UType::object_ptr<Actor>> actors_map;
std::unordered_map<std::string, std::shared_ptr<Actor>> actors_map;
public:
World(GameInstance& game_instance);
@@ -26,7 +24,7 @@ public:
virtual void BeginPlay();
virtual void Tick(double delta_time);
GameInstance& GetGameInstance() const { return game_instance; }
GameInstance& GetGameInstance() const { return game_instance_; }
#pragma region ISave
std::shared_ptr<SaveMap> save() override;
@@ -34,29 +32,30 @@ public:
#pragma endregion
template<class T>
std::vector<UType::object_ptr<T>> GetActorsByClass()
std::vector<std::weak_ptr<T>> GetActorsByClass()
{
std::vector<UType::object_ptr<T>> list;
std::vector<std::weak_ptr<T>> list;
for (auto i = actors_map.cbegin(); i != actors_map.cend(); ++i)
{
if (T* cast_object = RTTI::dyn_cast<T, Actor>(i->second.get()))
list.push_back(UType::object_ptr<T>(cast_object));
if (RTTI::dyn_cast<T, Actor>(i->second.get()))
list.push_back(std::static_pointer_cast<T>(i->second));
}
return list;
}
template<class T>
UType::object_ptr<T> SpawnActorFormClass(std::string name, const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 })
std::weak_ptr<T> SpawnActorFormClass(std::string name, const Vector3D& loc = { 0, 0, 0 }, const Vector3D& rot = { 0, 0, 0 })
{
UType::object_ptr<T> object(new T());
std::shared_ptr<T> object = std::make_shared<T>();
object->SetActorLocate(loc);
object->SetActorRotate(rot);
static_cast<Actor*>(object)->world_ = this;
static_cast<Actor*>(object)->name_ = name;
actors_map.try_emplace(name, object);
return object;
}
void DestroyActor(UType::object_ptr<Actor> ptr);
void DestroyActor(std::weak_ptr<Actor> ptr);
template<class T, class Container = std::vector<T*>>
Container GetActorsByTag(std::string tag)
@@ -77,9 +76,13 @@ public:
}
template<class T>
UType::object_ptr<T> GetActorByID(const std::string& id)
std::weak_ptr<T> GetActorByID(const std::string& id)
{
return actors_map[id];
auto it = actors_map.find(id);
if (it == actors_map.end() || it->second == nullptr)
return {};
return std::static_pointer_cast<T>(it->second);
}
};
+2 -2
View File
@@ -2,7 +2,7 @@
#include "Game/SaveMap/SaveMap.hpp"
Vector2D::Vector2D(const double x, const double y) : x(x), y(y)
Vector2D::Vector2D(double x, double y) : x(x), y(y)
{}
Vector2D::Vector2D(const Vector3D& vec3D) : x(vec3D.x), y(vec3D.y)
@@ -31,7 +31,7 @@ void Vector2D::load(std::shared_ptr<SaveMap> save)
y = save->GetDouble("y");
}
Vector3D::Vector3D(const double x, const double y, const double z) : x(x), y(y), z(z)
Vector3D::Vector3D(double x, double y, double z) : x(x), y(y), z(z)
{}
Vector3D::Vector3D(const Vector2D& vec2D) : x(vec2D.x), y(vec2D.y)
-3
View File
@@ -1,3 +0,0 @@
#include "object_ptr.hpp"
std::unordered_map<void*, UType::counter::counter_owners> UType::counter::owners_map;
-185
View File
@@ -1,185 +0,0 @@
#pragma once
#include <mutex>
#include <unordered_map>
#include <list>
namespace UType
{
template<typename Ty>
class object_ptr;
class counter
{
struct counter_owners
{
std::atomic_bool is_destroyed;
std::mutex mutex;
std::list<void*> owners;
counter_owners()
: is_destroyed(false)
{
}
counter_owners(const counter_owners&) = delete;
counter_owners& operator=(const counter_owners&) = delete;
counter_owners(counter_owners&& other) noexcept
: is_destroyed(other.is_destroyed.load())
, owners(std::move(other.owners))
{
}
counter_owners& operator=(counter_owners&& other) noexcept
{
if (this != &other)
{
is_destroyed.store(other.is_destroyed.load());
owners = std::move(other.owners);
}
return *this;
}
};
static std::unordered_map<void*, counter_owners> owners_map;
public:
template<typename Ty>
static void add_owner(object_ptr<Ty>& ptr)
{
auto counter = owners_map.find(ptr.ptr_.load());
if (counter == owners_map.end())
{
counter_owners owners;
owners.owners.push_back(&ptr);
auto [it, inserted] = owners_map.try_emplace(ptr.ptr_.load(), std::move(owners));
if (!inserted)
{
ptr.ptr_.store(nullptr);
}
}
else if (!counter->second.is_destroyed)
{
std::lock_guard<std::mutex> lock(counter->second.mutex);
counter->second.owners.push_back(&ptr);
}
else
ptr.ptr_.store(nullptr);
}
template<typename Ty>
static void remove_owner(object_ptr<Ty>& ptr)
{
auto counter = owners_map.find(ptr.ptr_);
if (counter != owners_map.end())
{
counter->second.owners.remove(&ptr);
if (counter->second.is_destroyed)
{
ptr.ptr_.store(nullptr);
}
else if (counter->second.owners.empty())
{
counter->second.is_destroyed.store(true);
for (auto& owner : counter->second.owners)
static_cast<object_ptr<Ty>*>(owner)->ptr_.store(nullptr);
delete static_cast<Ty*>(counter->first);
owners_map.erase(counter);
}
}
}
template<typename Ty>
static void remove_object(Ty* ptr)
{
auto counter = owners_map.find(ptr);
if (counter != owners_map.end())
{
counter->second.is_destroyed.store(true);
for (auto& owner : counter->second.owners)
static_cast<object_ptr<Ty>*>(owner)->ptr_.store(nullptr);
delete ptr;
owners_map.erase(counter);
}
}
};
template<typename Ty>
class object_ptr
{
std::atomic<Ty*> ptr_;
public:
explicit object_ptr(Ty* ptr = nullptr)
{
ptr_.store(ptr);
if (ptr) counter::add_owner<Ty>(*this);
}
object_ptr(const object_ptr& ptr)
{
ptr_.store(ptr.ptr_);
if (ptr.ptr_) counter::add_owner<Ty>(*this);
}
object_ptr(object_ptr&& ptr) noexcept
{
ptr_.store(ptr.ptr_);
if (ptr.ptr_) counter::add_owner<Ty>(*this);
ptr.ptr_.store(nullptr);
}
~object_ptr()
{
if (ptr_) counter::remove_owner<Ty>(*this);
}
void reset(Ty* new_ptr = nullptr)
{
if (ptr_) counter::remove_owner<Ty>(*this);
ptr_.store(new_ptr);
if (new_ptr) counter::add_owner<Ty>(*this);
}
void reset(const object_ptr& ptr)
{
if (ptr_) counter::remove_owner<Ty>(*this);
ptr_.store(ptr.ptr_);
if (ptr.ptr_) counter::add_owner<Ty>(*this);
}
void destroy()
{
if (ptr_) counter::remove_object<Ty>(ptr_);
}
Ty* get() const { return ptr_.load(); }
Ty& operator*() const
{
if (!ptr_.load())
throw std::runtime_error("Null pointer");
return *ptr_;
}
Ty* operator->() const
{
if (!ptr_.load())
throw std::runtime_error("Null pointer");
return ptr_.load();
}
operator bool() const noexcept { return ptr_.load() != nullptr; }
object_ptr<Ty>& operator=(const object_ptr<Ty>& ptr)
{
reset(ptr);
return *this;
}
template<typename target_Ty>
explicit operator object_ptr<target_Ty>() const noexcept
{
return object_ptr<target_Ty>(reinterpret_cast<target_Ty*>(ptr_.load()));
}
friend class counter;
};
}
+1 -1
View File
@@ -13,5 +13,5 @@ template<class T> struct Meta;
// Enum type classes
enum class Classes
{
IRTTI, IResource, Actor, TestActor, Mesh, StaticMesh, World, TestWorld
IRTTI, IResource, Actor, World, Mesh, StaticMesh, Camera, TestWorld, TestActor
};
+15
View File
@@ -3,3 +3,18 @@ set(CMAKE_CXX_STANDARD 20)
file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.h" "*.hpp")
add_executable(ProjectGenerator ${SRC})
if(MSVC)
set(OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>)
else()
set(OUTPUT_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()
add_custom_command(
TARGET ProjectGenerator
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/ProjectFile.txt
${OUTPUT_PATH}/ProjectFile.txt
COMMENT "Copying project files"
)
@@ -0,0 +1,125 @@
#include "DeviceFunctions.hpp"
#include <stdexcept>
#include <string>
VkExtent2D DeviceFunctions::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
{
// The acceptable rendering sparsity is calculated here
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
return capabilities.currentExtent;
else
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
VkExtent2D actualExtent = {
static_cast<uint32_t>(width),
static_cast<uint32_t>(height)
};
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
return actualExtent;
}
}
uint32_t DeviceFunctions::find_memory_type(VkPhysicalDevice physical_device, uint32_t typeFilter,
VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties memory_properties{};
vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties);
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i)
{
if (typeFilter & (1 << i) && (memory_properties.memoryTypes[i].propertyFlags & properties) == properties)
return i;
}
throw std::runtime_error("failed to find suitable memory type!");
}
void DeviceFunctions::device_memcpy(VkDevice device, uint32_t transfer_queue_family, VkBuffer src, VkBuffer dst, size_t size)
{
VkCommandPool copy_pool;
VkCommandPoolCreateInfo copy_pool_info{};
copy_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
copy_pool_info.queueFamilyIndex = transfer_queue_family;
copy_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VK_CHECK(vkCreateCommandPool(device, &copy_pool_info, nullptr, &copy_pool));
VkCommandBufferAllocateInfo command_buffer_allocate_info{};
command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_buffer_allocate_info.commandPool = copy_pool;
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
command_buffer_allocate_info.commandBufferCount = 1;
VkCommandBuffer copy_buffer;
VK_CHECK(vkAllocateCommandBuffers(device, &command_buffer_allocate_info, &copy_buffer));
VkCommandBufferBeginInfo command_buffer_begin_info{};
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VK_CHECK(vkBeginCommandBuffer(copy_buffer, &command_buffer_begin_info));
VkBufferCopy buffer_copy{};
buffer_copy.srcOffset = 0;
buffer_copy.dstOffset = 0;
buffer_copy.size = size;
vkCmdCopyBuffer(copy_buffer, src, dst, 1, &buffer_copy);
vkEndCommandBuffer(copy_buffer);
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &copy_buffer;
VkQueue transfer_queue;
vkGetDeviceQueue(device, transfer_queue_family, 0, &transfer_queue);
vkQueueSubmit(transfer_queue, 1, &submit_info, VK_NULL_HANDLE);
vkQueueWaitIdle(transfer_queue);
vkFreeCommandBuffers(device, copy_pool, 1, &copy_buffer);
vkDestroyCommandPool(device, copy_pool, nullptr);
}
VkBuffer DeviceFunctions::create_buffer(VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage,
const std::vector<uint32_t>& queue_families)
{
VkBufferCreateInfo buffer_info{};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = usage;
if (queue_families.size() > 1)
{
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
buffer_info.queueFamilyIndexCount = static_cast<uint32_t>(queue_families.size());
buffer_info.pQueueFamilyIndices = queue_families.data();
}
else
{
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
buffer_info.queueFamilyIndexCount = 0;
buffer_info.pQueueFamilyIndices = nullptr;
}
VkBuffer buffer;
VK_CHECK(vkCreateBuffer(device, &buffer_info, nullptr, &buffer));
return buffer;
}
VkDeviceMemory DeviceFunctions::allocate_device_memory(VkPhysicalDevice physical_device, VkDevice device, VkBuffer buffer, VkMemoryPropertyFlags property)
{
VkMemoryRequirements requirements{};
vkGetBufferMemoryRequirements(device, buffer, &requirements);
VkMemoryAllocateInfo allocate_info{};
allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocate_info.allocationSize = requirements.size;
allocate_info.memoryTypeIndex = find_memory_type(physical_device, requirements.memoryTypeBits, property);
VkDeviceMemory device_memory;
VK_CHECK(vkAllocateMemory(device, &allocate_info, nullptr, &device_memory));
return device_memory;
}
@@ -0,0 +1,22 @@
#pragma once
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <vector>
#ifdef _DEBUG
#include <assert.h>
#define VK_CHECK(res) assert(res == VK_SUCCESS);
#else
#define VK_CHECK(val) {int res = (val); if ((res) != VK_SUCCESS) throw std::runtime_error("Vulkan error: " + std::to_string(static_cast<int>(res)));}
#endif
namespace DeviceFunctions
{
VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t typeFilter, VkMemoryPropertyFlags properties);
void device_memcpy(VkDevice device, uint32_t transfer_queue_family, VkBuffer src, VkBuffer dst, size_t size);
VkBuffer create_buffer(VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, const std::vector<uint32_t>& queue_families);
VkDeviceMemory allocate_device_memory(VkPhysicalDevice physical_device, VkDevice device, VkBuffer buffer, VkMemoryPropertyFlags property);
}
+1
View File
@@ -8,6 +8,7 @@ add_executable(${GAME_NAME} ${SRC})
target_link_libraries(${GAME_NAME} PRIVATE Core UwURenderEngine)
target_include_directories(${GAME_NAME} PRIVATE
${PROJECT_SOURCE_DIR}/Core
${PROJECT_SOURCE_DIR}/UwURenderEngine
)
if(MSVC)
+26 -1
View File
@@ -3,8 +3,33 @@
"dtime": 5.000000,
"Parent parameters": {
"Class name":"World",
"vsActorsIDs": ["TestMesh1","TestMesh2"],
"vsActorsIDs": ["MainCamera", "TestMesh1","TestMesh2"],
"loActors": [
{
"Class name": "Camera",
"Parent parameters": {
"Class name":"Actor",
"oloc": {
"Class name":"Vector3D",
"dx":2.0,
"dy":2.0,
"dz":2.0
},
"orot": {
"Class name":"Vector3D",
"dx":-2.335,
"dy":-0.785,
"dz":0.0
},
"oscale": {
"Class name": "Vector3D",
"dx": 1.0,
"dy": 1.0,
"dz": 1.0
},
"tags":[]
}
},
{
"Class name": "StaticMesh",
"Parent parameters": {
+4
View File
@@ -1,7 +1,11 @@
#include "Game/ObjectFactory.hpp"
#include "../Actors/TestActor.h"
#include "Game/Actors/Camera.hpp"
#include "Game/Actors/Mesh/StaticMesh.hpp"
FACTORIES_LIST{
GENERATE_FACTORY_OBJECT(StaticMesh)
GENERATE_FACTORY_OBJECT(TestActor)
GENERATE_FACTORY_OBJECT(Camera)
};
+22 -5
View File
@@ -1,8 +1,13 @@
#include "TestWorld.h"
#include <glm/glm.hpp>
#include <glm/ext/scalar_constants.hpp>
#include "Game/GameInstance.hpp"
#include "Game/Actors/Camera.hpp"
#include "Game/SaveMap/SaveMap.hpp"
#include "Log/Log.hpp"
#include "Game/Actors/Mesh/Mesh.hpp"
TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance)
{}
@@ -10,23 +15,35 @@ TestWorld::TestWorld(GameInstance& game_instance) : World(game_instance)
void TestWorld::BeginPlay()
{
World::BeginPlay();
std::vector<UType::object_ptr<Actor>> meshes = GetActorsByClass<Actor>();
std::vector<std::weak_ptr<Actor>> meshes = GetActorsByClass<Actor>();
for (const auto& i : meshes)
Loging::Log("Load actor: " + i->GetName());
{
Loging::Log("Load actor: " + i.lock()->GetName());
}
GetActorsByClass<Camera>()[0].lock()->SetActive();
}
void TestWorld::Tick(double delta_time)
{
World::Tick(delta_time);
static double time1 = 0.0;
time1 += delta_time;
double delta1 = sin(time1);
double delta2 = sin(3*time1);
GetActorsByClass<Camera>()[0].lock()->SetActorLocate(Vector3D{2 + delta2, 2 + delta2, 2 + delta2});
GetActorsByClass<Camera>()[0].lock()->SetActorRotate(Vector3D{-3*glm::pi<double>()/4 + glm::pi<double>()/4 * delta1, glm::pi<double>() / -4, 0});
time += delta_time;
if (time >= 10.0)
{
std::vector<UType::object_ptr<Mesh>> meshes = GetActorsByClass<Mesh>();
std::vector<std::weak_ptr<Mesh>> meshes = GetActorsByClass<Mesh>();
if (!meshes.empty())
{
Loging::Message("TestWorld destroy: " + meshes[0]->GetName());
DestroyActor(static_cast<UType::object_ptr<Actor>>(meshes[0]));
std::shared_ptr<Mesh> mesh = meshes[0].lock();
Loging::Message("TestWorld destroy: " + mesh->GetName());
DestroyActor(meshes[0]);
time = 7.0;
return;
}
-1
View File
@@ -15,7 +15,6 @@ file(GLOB SRC
"ObjectPtrTest.cpp"
"${PROJECT_SOURCE_DIR}/Core/Game/SaveMap/SaveMap.cpp"
"${PROJECT_SOURCE_DIR}/Core/Types/object_ptr.cpp"
)
add_executable(Tests ${SRC})
-59
View File
@@ -1,59 +0,0 @@
#include <gtest/gtest.h>
#include "Types/object_ptr.hpp"
class TestClass
{
int* test_ptr_;
public:
TestClass(int* test_ptr) : test_ptr_(test_ptr)
{
*test_ptr_ = 1;
}
~TestClass()
{
*test_ptr_ = 2;
}
};
TEST(object_ptr_test, base_test)
{
int* test = new int(123);
UType::object_ptr<int> ptr(test);
EXPECT_EQ(*ptr.get(), 123);
UType::object_ptr<int> ptr2(ptr);
EXPECT_EQ(*ptr2.get(), 123);
EXPECT_EQ(ptr2.get(), ptr.get());
ptr.destroy();
EXPECT_EQ(ptr.get(), nullptr);
EXPECT_EQ(ptr2.get(), nullptr);
}
TEST(object_ptr_test, check_destry)
{
UType::object_ptr<int> ptr(new int(123)), ptr2(ptr);
ptr.destroy();
EXPECT_EQ(ptr.get(), nullptr);
EXPECT_EQ(ptr2.get(), nullptr);
}
TEST(object_ptr_test, check_destroy)
{
int* test = new int(0);
{
UType::object_ptr<TestClass> ptr(new TestClass(test));
EXPECT_EQ(*test, 1);
}
EXPECT_EQ(*test, 2);
*test = 0;
{
UType::object_ptr<TestClass> ptr(new TestClass(test));
UType::object_ptr<TestClass> ptr2(ptr);
EXPECT_EQ(*test, 1);
}
EXPECT_EQ(*test, 2);
}
+3 -3
View File
@@ -158,14 +158,15 @@ TEST(SaveMapTest, check_load_with_custom_type)
EXPECT_EQ(test_vector_string[i], save_map.GetVectorString("TestVectorString")[i]);
}
UType::object_ptr<CustomObject> obj = static_cast<UType::object_ptr<CustomObject>>(save_map.GetObject("CustomObject"));
std::shared_ptr obj = std::static_pointer_cast<CustomObject>(save_map.GetObject("CustomObject"));
CustomObject test_obj;
test_obj.num = 123;
test_obj.str = "str123";
test_obj.dbl = 123.45;
EXPECT_EQ(*obj.get(), test_obj);
std::vector<UType::object_ptr<CustomObject>> vec_obj = reinterpret_cast<std::vector<UType::object_ptr<CustomObject>>&>(save_map.GetVectorObject("CustomObjects"));
std::vector<std::shared_ptr<CustomObject>> vec_obj = reinterpret_cast<std::vector<std::shared_ptr<CustomObject>>&>(save_map.GetVectorObject("CustomObjects"));
std::vector<CustomObject*> vec_obj_test = {
new CustomObject,
new CustomObject,
@@ -179,7 +180,6 @@ TEST(SaveMapTest, check_load_with_custom_type)
for (auto i = 0; i < 2; i++)
{
EXPECT_EQ(*vec_obj[i].get(), *vec_obj_test[i]);
vec_obj[i].destroy();
delete vec_obj_test[i];
}
}
+28 -2
View File
@@ -1,7 +1,33 @@
file(GLOB_RECURSE SRC "*.cpp" "*.c" "*.hpp" "*.h")
add_library(UwURenderEngine ${SRC})
target_include_directories(UwURenderEngine PRIVATE ${PROJECT_SOURCE_DIR}/RenderEngineSDK)
target_link_libraries(UwURenderEngine PRIVATE RenderEngineSDK)
target_include_directories(UwURenderEngine PUBLIC ${PROJECT_SOURCE_DIR}/RenderEngineSDK)
target_link_libraries(UwURenderEngine PUBLIC RenderEngineSDK)
target_compile_features(UwURenderEngine PRIVATE cxx_std_17)
file(GLOB_RECURSE HEADERS
"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/*.hpp"
)
foreach (HEADER ${HEADERS})
file(RELATIVE_PATH R_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/"
"${HEADER}"
)
get_filename_component(HEADER_DIR "${R_PATH}" DIRECTORY)
add_custom_command(
TARGET UwURenderEngine
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include/${HEADER_DIR}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${HEADER}"
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/include/${R_PATH}"
COMMENT "Copy UwURenderEngine headers"
)
endforeach ()
+27
View File
@@ -0,0 +1,27 @@
#include "Camera.hpp"
#include "../../RenderEngine/UwURenderEngine.hpp"
#include "Core/CoreInstance.hpp"
#include "Game/GameInstance.hpp"
#include "Game/SaveMap/SaveMap.hpp"
#include "Game/World/World.hpp"
Camera::Camera()
{
SetType(Classes::Camera);
}
std::shared_ptr<SaveMap> Camera::save()
{
return std::make_shared<SaveMap>("Camera")->connect_to(Actor::save());
}
void Camera::load(std::shared_ptr<SaveMap> save)
{
Actor::load(save->getParent());
}
void Camera::SetActive() const noexcept
{
GET_RENDER_ENGINE->SetActiveCamera(GetWorld()->GetActorByID<Camera>(GetName()));
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "RTTI_Meta.h"
#include "Game/Actors/Actor.hpp"
GENERATE_META(Camera)
class Camera : public Actor
{
public:
Camera();
std::shared_ptr<SaveMap> save() override;
void load(std::shared_ptr<SaveMap> save) override;
void SetActive() const noexcept;
};
@@ -2,7 +2,7 @@
#include <string>
#include "../Actor.hpp"
#include "Game/Actors/Actor.hpp"
GENERATE_META(Mesh)
class Mesh : public Actor
@@ -4,6 +4,7 @@
#include "Game/GameInstance.hpp"
#include "Game/SaveMap/SaveMap.hpp"
#include "Game/World/World.hpp"
#include "../../../RenderEngine/UwURenderEngine.hpp"
StaticMesh::StaticMesh()
{
@@ -23,12 +24,13 @@ void StaticMesh::load(std::shared_ptr<SaveMap> save)
void StaticMesh::load_model(const std::string& model_name)
{
model_name_ = model_name;
model_ = GET_RENDER_ENGINE->GetModelManager()->LoadModel(model_name);
SetModelName(model_name);
model_ = GetWorld()->GetGameInstance().GetCurrentModelManager()->LoadModel(model_name);
}
void StaticMesh::OnDestroy()
{
Mesh::OnDestroy();
GetWorld()->GetGameInstance().GetCurrentModelManager()->FreeModel(model_name_);
GET_RENDER_ENGINE->GetModelManager()->FreeModel(model_name_);
}
@@ -1,7 +1,7 @@
#pragma once
#include "Mesh.hpp"
#include "Game/ModelManager.hpp"
#include "../../../RenderEngine/ModelManager.hpp"
GENERATE_META(StaticMesh)
@@ -0,0 +1,22 @@
#include "GPU_GarbageCollector.h"
GPU_GarbageCollector::GPU_GarbageCollector(VkDevice device) : device_(device)
{}
void GPU_GarbageCollector::AddGarbage(Garbage garbage)
{
std::scoped_lock lock(m_heap_);
heap_.push_back(garbage);
}
void GPU_GarbageCollector::FreeHeap()
{
std::scoped_lock lock(m_heap_);
for (auto& i : heap_)
{
vkFreeMemory(device_, i.device_memory, nullptr);
vkDestroyBuffer(device_, i.buffer, nullptr);
}
heap_.clear();
}
@@ -0,0 +1,27 @@
#pragma once
#include <list>
#include <mutex>
#include <vulkan/vulkan.h>
class GPU_GarbageCollector
{
public:
struct Garbage
{
VkBuffer buffer;
VkDeviceMemory device_memory;
};
private:
VkDevice device_ = VK_NULL_HANDLE;
std::list<Garbage> heap_;
std::mutex m_heap_;
public:
GPU_GarbageCollector() = default;
explicit GPU_GarbageCollector(VkDevice device);
void AddGarbage(Garbage garbage);
void FreeHeap();
};
@@ -0,0 +1,113 @@
#include "ModelManager.hpp"
#include <array>
#include "Log/Log.hpp"
ModelManager::StaticModel::StaticModel(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices,
VkPhysicalDevice physical_device, VkDevice device):
physical_device_(physical_device),
device_(device)
{
}
ModelManager::StaticModel::~StaticModel()
{
}
VkVertexInputBindingDescription ModelManager::Vertex::get_binding_description()
{
VkVertexInputBindingDescription description;
description.binding = 0;
description.stride = sizeof(Vertex);
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return description;
}
std::array<VkVertexInputAttributeDescription, 2> ModelManager::Vertex::get_vertex_attribute_descriptions()
{
std::array<VkVertexInputAttributeDescription, 2> descriptions;
// Bind vertex loc
descriptions[0].binding = 0;
descriptions[0].location = 0;
descriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
descriptions[0].offset = offsetof(Vertex, pos);
// Bind color
descriptions[1].binding = 0;
descriptions[1].location = 1;
descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
descriptions[1].offset = offsetof(Vertex, color);
return descriptions;
}
ModelManager::owner_counter::owner_counter(const owner_counter& other) : counter(other.counter.load()), model(other.model)
{
}
unsigned int ModelManager::FNV1aHash(const char* buf)
{
unsigned int h_val = 0x811c9dc5;
while (*buf)
{
h_val ^= static_cast<unsigned int>(*buf++);
h_val *= 0x01000193;
}
return h_val;
}
ModelManager::ModelManager(VkPhysicalDevice physical_device, VkDevice device):
physical_device_(physical_device),
device_(device)
{}
ModelManager::~ModelManager()
{
models.clear();
}
ModelManager::StaticModel* ModelManager::LoadModel(const std::string& name)
{
if (name.empty())
return nullptr;
unsigned int hash = FNV1aHash(name.c_str());
auto counter = models.find(hash);
if (counter != models.cend())
{
++counter->second.counter;
return counter->second.model;
}
Loging::Log("Load new model: " + name);
std::vector<Vertex> vertices;
std::vector<uint32_t> indices;
// Load model_data
owner_counter new_counter;
new_counter.counter.store(1);
new_counter.model = new StaticModel(vertices, indices, physical_device_, device_);
models.try_emplace(hash, new_counter);
return new_counter.model;
}
void ModelManager::FreeModel(const std::string& name)
{
if (name.empty())
return;
unsigned int hash = FNV1aHash(name.c_str());
auto counter = models.find(hash);
--counter->second.counter;
StaticModel* model = counter->second.model;
if (counter->second.counter.load() == 0)
{
Loging::Log("Free model: " + name);
models.erase(hash);
delete model;
}
}
@@ -0,0 +1,57 @@
#pragma once
#include <unordered_map>
#include <string>
#include <atomic>
#include <glm/vec3.hpp>
#include <vulkan/vulkan.h>
class ModelManager
{
public:
struct Vertex
{
glm::vec3 pos, color;
static VkVertexInputBindingDescription get_binding_description();
static std::array<VkVertexInputAttributeDescription, 2> get_vertex_attribute_descriptions();
};
class StaticModel
{
VkPhysicalDevice physical_device_;
VkDevice device_;
VkBuffer vertex_buffer_;
VkBuffer index_buffer_;
public:
StaticModel(const std::vector<Vertex>& vertices, const std::vector<uint32_t>& indices,
VkPhysicalDevice physical_device, VkDevice device);
~StaticModel();
};
struct owner_counter
{
std::atomic_ullong counter;
StaticModel* model;
owner_counter() = default;
owner_counter(const owner_counter& other);
};
private:
VkPhysicalDevice physical_device_;
VkDevice device_;
std::unordered_map<unsigned int, owner_counter> models;
static unsigned int FNV1aHash (const char *buf);
public:
ModelManager(VkPhysicalDevice physical_device, VkDevice device);
~ModelManager();
StaticModel* LoadModel(const std::string& name);
void FreeModel(const std::string& name);
};
@@ -1,25 +1,29 @@
#include "UwURenderEngine.hpp"
#include <array>
#include <queue>
#include <set>
#include <stdexcept>
#include <fstream>
#include <chrono>
#include <glm/gtc/matrix_transform.hpp>
#include "GPU_GarbageCollector.h"
#include "../Game/Actors/Camera.hpp"
#include "Core/CoreInstance.hpp"
#include "Log/Log.hpp"
#include "Game/GameInstance.hpp"
#include "Game/World/World.hpp"
#include "Game/Actors/Mesh/Mesh.hpp"
#include "GLFW/glfw3.h"
#include "../Game/Actors/Mesh/Mesh.hpp"
#include "DeviceFunctions/DeviceFunctions.hpp"
const std::vector<const char*> UwURenderEngine::deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
RENDER_ENGINE_FACTORY_GENERATE(UwURenderEngine)
#ifdef _DEBUG
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
@@ -48,14 +52,14 @@ UwURenderEngine::SwapchainSupportDetails UwURenderEngine::query_swapchain_detail
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device_, surface_, &details.capabilities);
uint32_t surface_format_cnt = 0;
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, nullptr));
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, nullptr))
details.formats.resize(surface_format_cnt);
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, details.formats.data()));
VK_CHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device_, surface_, &surface_format_cnt, details.formats.data()))
uint32_t present_modes_cnt = 0;
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, nullptr));
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, nullptr))
details.present_modes.resize(surface_format_cnt);
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, details.present_modes.data()));
VK_CHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &present_modes_cnt, details.present_modes.data()))
return details;
}
@@ -72,33 +76,6 @@ std::vector<const char*> UwURenderEngine::get_required_extensions()
return extensions;
}
VkVertexInputBindingDescription UwURenderEngine::Vertex::get_binding_description()
{
VkVertexInputBindingDescription description;
description.binding = 0;
description.stride = sizeof(Vertex);
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return description;
}
std::array<VkVertexInputAttributeDescription, 2> UwURenderEngine::Vertex::get_vertex_attribute_descriptions()
{
std::array<VkVertexInputAttributeDescription, 2> descriptions;
// Bind vertex loc
descriptions[0].binding = 0;
descriptions[0].location = 0;
descriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
descriptions[0].offset = offsetof(Vertex, pos);
// Bind color
descriptions[1].binding = 0;
descriptions[1].location = 1;
descriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
descriptions[1].offset = offsetof(Vertex, color);
return descriptions;
}
bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface)
{
VkPhysicalDeviceProperties device_properties;
@@ -108,7 +85,7 @@ bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR s
try {
// Ловить исключения имеет смысыл только здесь
QueueFamilyIndices indices = find_queue_family_indices(device, surface);
find_queue_family_indices(device, surface);
} catch (...) {
return false;
}
@@ -119,9 +96,9 @@ bool UwURenderEngine::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR s
bool UwURenderEngine::check_device_extensions_support(VkPhysicalDevice device)
{
uint32_t extension_count;
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr));
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr))
std::vector<VkExtensionProperties> available_extensions(extension_count);
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data()));
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data()))
for (const auto& extension : deviceExtensions)
{
@@ -155,49 +132,60 @@ UwURenderEngine::QueueFamilyIndices UwURenderEngine::find_queue_family_indices(V
if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
queue_family_indices.graphics_family = i;
queue_family_indices.is_find_graphics_family = true;
break;
}
}
if (queue_family_indices.graphics_family.has_value() == false)
if (queue_family_indices.is_find_graphics_family == false)
throw std::runtime_error("Failed to find a graphics queue family");
// Find present
VkBool32 present_support = false;
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family.value(), surface, &present_support));
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family, surface, &present_support))
// Если графическая очередь поддерживет презентацию кадров, то используем её
if (present_support == VK_TRUE)
{
queue_family_indices.present_family = queue_family_indices.graphics_family;
queue_family_indices.is_find_present_family = true;
}
// иначе ищем другую подходящую очередь
else
{
for(uint32_t i = 0; i < family_properties.size(); ++i)
{
present_support = false;
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support));
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support))
if (present_support == VK_TRUE)
{
queue_family_indices.present_family = i;
queue_family_indices.is_find_present_family = true;
break;
}
}
}
if (queue_family_indices.present_family.has_value() == false)
if (queue_family_indices.is_find_present_family == false)
throw std::runtime_error("Failed to find a present queue family");
// С начала пытаемся найти очередь специалезированную
// для копирования отличную от графической
for(uint32_t i = 0; i < family_properties.size(); ++i)
{
if (i == queue_family_indices.graphics_family.value())
if (i == queue_family_indices.graphics_family)
continue;
if (family_properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT)
{
queue_family_indices.transfer_family = i;
queue_family_indices.is_find_transfer_family = true;
}
}
// Если не находим, то используем графическую
if (queue_family_indices.transfer_family.has_value() == false)
if (queue_family_indices.is_find_transfer_family == false)
{
queue_family_indices.transfer_family = queue_family_indices.graphics_family;
queue_family_indices.is_find_transfer_family = true;
}
return queue_family_indices;
}
@@ -221,24 +209,6 @@ VkPresentModeKHR UwURenderEngine::choose_present_mode(const std::vector<VkPresen
return VK_PRESENT_MODE_FIFO_KHR;
}
VkExtent2D UwURenderEngine::choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
{
// Здесь вычисляется допустимое разрешение рендера
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
return capabilities.currentExtent;
else
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
VkExtent2D actualExtent = {
static_cast<uint32_t>(width),
static_cast<uint32_t>(height)
};
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
return actualExtent;
}
}
VkShaderModule UwURenderEngine::create_shader_module(const std::string& code) const
{
VkShaderModuleCreateInfo shader_module_info{};
@@ -247,47 +217,10 @@ VkShaderModule UwURenderEngine::create_shader_module(const std::string& code) co
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(code.c_str());
VkShaderModule shader_module;
VK_CHECK(vkCreateShaderModule(device_, &shader_module_info, nullptr, &shader_module));
VK_CHECK(vkCreateShaderModule(device_, &shader_module_info, nullptr, &shader_module))
return shader_module;
}
void UwURenderEngine::create_buffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkBuffer* buffer, const std::vector<uint32_t>& queue_families)
{
VkBufferCreateInfo buffer_info{};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = usage;
if (queue_families.size() > 1)
{
buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
buffer_info.queueFamilyIndexCount = static_cast<uint32_t>(queue_families.size());
buffer_info.pQueueFamilyIndices = queue_families.data();
}
else
{
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
buffer_info.queueFamilyIndexCount = 0;
buffer_info.pQueueFamilyIndices = nullptr;
}
VK_CHECK(vkCreateBuffer(device_, &buffer_info, nullptr, buffer));
}
void UwURenderEngine::allocate_memory(VkBuffer buffer, VkMemoryPropertyFlags property, VkDeviceMemory* device_memory)
{
VkMemoryRequirements requirements{};
vkGetBufferMemoryRequirements(device_, buffer, &requirements);
VkMemoryAllocateInfo allocate_info{};
allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocate_info.allocationSize = requirements.size;
allocate_info.memoryTypeIndex = find_memory_type(requirements.memoryTypeBits, property);
VK_CHECK(vkAllocateMemory(device_, &allocate_info, nullptr, device_memory));
}
void UwURenderEngine::create_instance()
{
std::vector<const char*> extensions = get_required_extensions();
@@ -319,9 +252,9 @@ void UwURenderEngine::create_instance()
debug_messenger_create_info.pfnUserCallback = &debugCallback;
instance_create_info.pNext = &debug_messenger_create_info;
#endif
VK_CHECK(vkCreateInstance(&instance_create_info, nullptr, &instance_));
VK_CHECK(vkCreateInstance(&instance_create_info, nullptr, &instance_))
#ifdef _DEBUG
VK_CHECK(enable_layer_validation(&debug_messenger_create_info));
VK_CHECK(enable_layer_validation(&debug_messenger_create_info))
#endif
}
@@ -329,9 +262,9 @@ void UwURenderEngine::pick_physical_device()
{
uint32_t device_count = 0;
std::vector<VkPhysicalDevice> devices;
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, nullptr));
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, nullptr))
devices.resize(device_count);
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, devices.data()));
VK_CHECK(vkEnumeratePhysicalDevices(instance_, &device_count, devices.data()))
for (const auto& device : devices)
{
@@ -356,9 +289,9 @@ void UwURenderEngine::create_logical_device()
VkPhysicalDeviceFeatures device_features{};
std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
std::set<uint32_t> unique_queue_families = {indices.graphics_family.value(),
indices.present_family.value(),
indices.transfer_family.value()};
std::set<uint32_t> unique_queue_families = {indices.graphics_family,
indices.present_family,
indices.transfer_family};
float queue_priority = 1.0f;
VkDeviceQueueCreateInfo device_queue_create_info{};
@@ -390,10 +323,10 @@ void UwURenderEngine::create_logical_device()
device_create_info.ppEnabledLayerNames = nullptr;
#endif
VK_CHECK(vkCreateDevice(physical_device_, &device_create_info, nullptr, &device_));
vkGetDeviceQueue(device_, indices.graphics_family.value(), 0, &graphics_queue_);
vkGetDeviceQueue(device_, indices.present_family.value(), 0, &present_queue_);
vkGetDeviceQueue(device_, indices.transfer_family.value(), 0, &transfer_queue_);
VK_CHECK(vkCreateDevice(physical_device_, &device_create_info, nullptr, &device_))
vkGetDeviceQueue(device_, indices.graphics_family, 0, &graphics_queue_);
vkGetDeviceQueue(device_, indices.present_family, 0, &present_queue_);
vkGetDeviceQueue(device_, indices.transfer_family, 0, &transfer_queue_);
}
void UwURenderEngine::create_swapchain()
@@ -401,7 +334,7 @@ void UwURenderEngine::create_swapchain()
SwapchainSupportDetails swapchain_support = query_swapchain_details();
VkSurfaceFormatKHR surface_format = choose_surface_format(swapchain_support.formats);
VkPresentModeKHR present_mode = choose_present_mode(swapchain_support.present_modes, VK_PRESENT_MODE_MAILBOX_KHR);
VkExtent2D extent = choose_extent(swapchain_support.capabilities, get_window());
VkExtent2D extent = DeviceFunctions::choose_extent(swapchain_support.capabilities, get_window());
uint32_t image_count = swapchain_support.capabilities.minImageCount + 1;
if (swapchain_support.capabilities.maxImageCount > 0 && image_count > swapchain_support.capabilities.maxImageCount)
@@ -423,9 +356,9 @@ void UwURenderEngine::create_swapchain()
swapchain_create_info.oldSwapchain = VK_NULL_HANDLE;
QueueFamilyIndices family_indices = find_queue_family_indices(physical_device_, surface_);
const std::set<uint32_t> queue_family_indices = { family_indices.graphics_family.value(),
family_indices.present_family.value(),
family_indices.transfer_family.value() };
const std::set<uint32_t> queue_family_indices = { family_indices.graphics_family,
family_indices.present_family,
family_indices.transfer_family };
std::vector<uint32_t> arr_families;
if (queue_family_indices.size() > 1)
{
@@ -445,7 +378,7 @@ void UwURenderEngine::create_swapchain()
swapchain_create_info.pQueueFamilyIndices = nullptr;
}
VK_CHECK(vkCreateSwapchainKHR(device_, &swapchain_create_info, nullptr, &swapchain_));
VK_CHECK(vkCreateSwapchainKHR(device_, &swapchain_create_info, nullptr, &swapchain_))
vkGetSwapchainImagesKHR(device_, swapchain_, &image_count, nullptr);
swapchain_images_.resize(image_count);
@@ -475,7 +408,7 @@ void UwURenderEngine::create_image_views()
for (uint32_t i = 0; i < swapchain_images_.size(); ++i)
{
image_view_info.image = swapchain_images_[i];
VK_CHECK(vkCreateImageView(device_, &image_view_info, nullptr, &swapchain_image_views_[i]));
VK_CHECK(vkCreateImageView(device_, &image_view_info, nullptr, &swapchain_image_views_[i]))
}
}
@@ -517,12 +450,12 @@ void UwURenderEngine::create_render_pass()
render_pass_info.dependencyCount = 1;
render_pass_info.pDependencies = &dependency;
VK_CHECK(vkCreateRenderPass(device_, &render_pass_info, nullptr, &render_pass_));
VK_CHECK(vkCreateRenderPass(device_, &render_pass_info, nullptr, &render_pass_))
}
void UwURenderEngine::create_description_set_layout()
{
VkDescriptorSetLayoutBinding ubo_layout_binding{};
VkDescriptorSetLayoutBinding ubo_layout_binding;
ubo_layout_binding.binding = 0;
ubo_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
ubo_layout_binding.descriptorCount = 1;
@@ -534,7 +467,7 @@ void UwURenderEngine::create_description_set_layout()
ubo_layout_info.bindingCount = 1;
ubo_layout_info.pBindings = &ubo_layout_binding;
VK_CHECK(vkCreateDescriptorSetLayout(device_, &ubo_layout_info, nullptr, &ubo_layout_binding_));
VK_CHECK(vkCreateDescriptorSetLayout(device_, &ubo_layout_info, nullptr, &ubo_layout_binding_))
}
void UwURenderEngine::create_uniform_buffers()
@@ -547,8 +480,8 @@ void UwURenderEngine::create_uniform_buffers()
for (size_t i = 0; i < swapchain_images_.size(); ++i)
{
const VkDeviceSize size = sizeof(UniformBufferObject);
create_buffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &uniform_buffers_[i], arr_indices);
allocate_memory(uniform_buffers_[i], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniform_buffers_memory_[i]);
uniform_buffers_[i] = DeviceFunctions::create_buffer(device_, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, arr_indices);
uniform_buffers_memory_[i] = DeviceFunctions::allocate_device_memory(physical_device_, device_, uniform_buffers_[i], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkBindBufferMemory(device_, uniform_buffers_[i], uniform_buffers_memory_[i], 0);
vkMapMemory(device_, uniform_buffers_memory_[i], 0, size, 0, &uniform_buffers_mapped_[i]);
@@ -557,7 +490,7 @@ void UwURenderEngine::create_uniform_buffers()
void UwURenderEngine::create_descriptor_pool()
{
VkDescriptorPoolSize pool_size{};
VkDescriptorPoolSize pool_size;
pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
pool_size.descriptorCount = static_cast<uint32_t>(swapchain_images_.size());
@@ -567,7 +500,7 @@ void UwURenderEngine::create_descriptor_pool()
descriptor_pool_info.pPoolSizes = &pool_size;
descriptor_pool_info.maxSets = static_cast<uint32_t>(swapchain_images_.size());
VK_CHECK(vkCreateDescriptorPool(device_, &descriptor_pool_info, nullptr, &descriptor_pool_));
VK_CHECK(vkCreateDescriptorPool(device_, &descriptor_pool_info, nullptr, &descriptor_pool_))
}
void UwURenderEngine::create_descriptor_sets()
@@ -580,7 +513,7 @@ void UwURenderEngine::create_descriptor_sets()
descriptor_set_allocate_info.pSetLayouts = layouts.data();
descriptor_sets_.resize(swapchain_images_.size());
VK_CHECK(vkAllocateDescriptorSets(device_, &descriptor_set_allocate_info, descriptor_sets_.data()));
VK_CHECK(vkAllocateDescriptorSets(device_, &descriptor_set_allocate_info, descriptor_sets_.data()))
for (size_t i = 0; i < swapchain_images_.size(); ++i)
{
@@ -646,8 +579,8 @@ void UwURenderEngine::create_graphics_pipeline()
dynamic_state_info.dynamicStateCount = static_cast<uint32_t>(dynamic_states.size());
dynamic_state_info.pDynamicStates = dynamic_states.data();
VkVertexInputBindingDescription binding_description = Vertex::get_binding_description();
std::array<VkVertexInputAttributeDescription, 2> attribute_descriptions = Vertex::get_vertex_attribute_descriptions();
VkVertexInputBindingDescription binding_description = ModelManager::Vertex::get_binding_description();
std::array<VkVertexInputAttributeDescription, 2> attribute_descriptions = ModelManager::Vertex::get_vertex_attribute_descriptions();
VkPipelineVertexInputStateCreateInfo vertex_input_info{};
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
@@ -720,7 +653,7 @@ void UwURenderEngine::create_graphics_pipeline()
pipeline_layout_info.setLayoutCount = 1;
pipeline_layout_info.pSetLayouts = &ubo_layout_binding_;
VK_CHECK(vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr, &pipeline_layout_));
VK_CHECK(vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr, &pipeline_layout_))
VkGraphicsPipelineCreateInfo graphics_pipeline_info{};
graphics_pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -740,7 +673,7 @@ void UwURenderEngine::create_graphics_pipeline()
graphics_pipeline_info.basePipelineHandle = nullptr;
graphics_pipeline_info.basePipelineIndex = -1;
VK_CHECK(vkCreateGraphicsPipelines(device_, nullptr, 1, &graphics_pipeline_info, nullptr, &graphics_pipeline_));
VK_CHECK(vkCreateGraphicsPipelines(device_, nullptr, 1, &graphics_pipeline_info, nullptr, &graphics_pipeline_))
vkDestroyShaderModule(device_, vertex_shader, nullptr);
vkDestroyShaderModule(device_, fragment_shader, nullptr);
@@ -761,7 +694,7 @@ void UwURenderEngine::create_framebuffers()
for (size_t i = 0; i < framebuffers_.size(); ++i)
{
framebuffer_info.pAttachments = &swapchain_image_views_[i];
VK_CHECK(vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &framebuffers_[i]));
VK_CHECK(vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &framebuffers_[i]))
}
}
@@ -771,31 +704,17 @@ void UwURenderEngine::create_command_pool()
VkCommandPoolCreateInfo command_pool_info{};
command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
command_pool_info.queueFamilyIndex = queue_family_indices.graphics_family.value();
command_pool_info.queueFamilyIndex = queue_family_indices.graphics_family;
command_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VK_CHECK(vkCreateCommandPool(device_, &command_pool_info, nullptr, &command_pool_));
}
uint32_t UwURenderEngine::find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const
{
VkPhysicalDeviceMemoryProperties memory_properties{};
vkGetPhysicalDeviceMemoryProperties(physical_device_, &memory_properties);
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i)
{
if (typeFilter & (1 << i) && (memory_properties.memoryTypes[i].propertyFlags & properties) == properties)
return i;
}
throw std::runtime_error("failed to find suitable memory type!");
VK_CHECK(vkCreateCommandPool(device_, &command_pool_info, nullptr, &command_pool_))
}
std::vector<uint32_t> UwURenderEngine::get_unique_family_indices(const QueueFamilyIndices& indices)
{
std::set<uint32_t> set_indices = {indices.graphics_family.value(),
indices.present_family.value(),
indices.transfer_family.value()};
std::set<uint32_t> set_indices = {indices.graphics_family,
indices.present_family,
indices.transfer_family};
std::vector<uint32_t> arr_indices;
arr_indices.reserve(set_indices.size());
@@ -810,27 +729,27 @@ void UwURenderEngine::allocate_vertex_buffer()
std::vector<uint32_t> arr_indices = get_unique_family_indices(indices);
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
VkBuffer staging_buffer = VK_NULL_HANDLE;
VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
std::vector<uint32_t> transfer_index = {indices.transfer_family};
VkDeviceSize size_buffer = sizeof(vertices_[0]) * vertices_.size();
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index);
allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory);
VkBuffer staging_buffer = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
transfer_index);
VkDeviceMemory staging_buffer_memory = DeviceFunctions::allocate_device_memory(
physical_device_, device_, staging_buffer,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &vertex_buffer_, arr_indices);
allocate_memory(vertex_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertex_buffer_memory_);
vertex_buffer_ = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, arr_indices);
vertex_buffer_memory_ = DeviceFunctions::allocate_device_memory(physical_device_, device_, vertex_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK(vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0));
VK_CHECK(vkBindBufferMemory(device_, vertex_buffer_, vertex_buffer_memory_, 0));
VK_CHECK(vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0))
VK_CHECK(vkBindBufferMemory(device_, vertex_buffer_, vertex_buffer_memory_, 0))
void* data;
VK_CHECK(vkMapMemory(device_, staging_buffer_memory, 0, size_buffer, 0, &data));
VK_CHECK(vkMapMemory(device_, staging_buffer_memory, 0, size_buffer, 0, &data))
memcpy(data, vertices_.data(), size_buffer);
vkUnmapMemory(device_, staging_buffer_memory);
copy_memory(staging_buffer, vertex_buffer_, size_buffer);
DeviceFunctions::device_memcpy(device_, indices.transfer_family, staging_buffer, vertex_buffer_, size_buffer);
vkFreeMemory(device_, staging_buffer_memory, nullptr);
vkDestroyBuffer(device_, staging_buffer, nullptr);
@@ -839,18 +758,19 @@ void UwURenderEngine::allocate_vertex_buffer()
void UwURenderEngine::allocate_index_buffer()
{
QueueFamilyIndices indices = find_queue_family_indices(physical_device_, surface_);
std::set<uint32_t> set_indices = {indices.graphics_family.value(),
indices.present_family.value(),
indices.transfer_family.value()};
std::set<uint32_t> set_indices = {indices.graphics_family,
indices.present_family,
indices.transfer_family};
std::vector<uint32_t> arr_indices = get_unique_family_indices(indices);
std::vector<uint32_t> transfer_index = {indices.transfer_family.value()};
std::vector<uint32_t> transfer_index = {indices.transfer_family};
VkBuffer staging_buffer = VK_NULL_HANDLE;
VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
VkDeviceSize size_buffer = sizeof(indices_[0]) * indices_.size();
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging_buffer, transfer_index);
allocate_memory(staging_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &staging_buffer_memory);
VkBuffer staging_buffer = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
transfer_index);
VkDeviceMemory staging_buffer_memory = DeviceFunctions::allocate_device_memory(
physical_device_, device_, staging_buffer,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkBindBufferMemory(device_, staging_buffer, staging_buffer_memory, 0);
void* data;
@@ -858,61 +778,16 @@ void UwURenderEngine::allocate_index_buffer()
memcpy(data, indices_.data(), size_buffer);
vkUnmapMemory(device_, staging_buffer_memory);
create_buffer(size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, &index_buffer_, arr_indices);
allocate_memory(index_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &index_buffer_memory_);
index_buffer_ = DeviceFunctions::create_buffer(device_, size_buffer, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, arr_indices);
index_buffer_memory_ = DeviceFunctions::allocate_device_memory(physical_device_, device_, index_buffer_, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkBindBufferMemory(device_, index_buffer_, index_buffer_memory_, 0);
copy_memory(staging_buffer, index_buffer_, size_buffer);
DeviceFunctions::device_memcpy(device_, indices.transfer_family,staging_buffer, index_buffer_, size_buffer);
vkDestroyBuffer(device_, staging_buffer, nullptr);
vkFreeMemory(device_, staging_buffer_memory, nullptr);
}
void UwURenderEngine::copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size)
{
QueueFamilyIndices indices = find_queue_family_indices(physical_device_, surface_);
VkCommandPool copy_pool;
VkCommandPoolCreateInfo copy_pool_info{};
copy_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
copy_pool_info.queueFamilyIndex = indices.transfer_family.value();
copy_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VK_CHECK(vkCreateCommandPool(device_, &copy_pool_info, nullptr, &copy_pool));
VkCommandBufferAllocateInfo command_buffer_allocate_info{};
command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_buffer_allocate_info.commandPool = copy_pool;
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
command_buffer_allocate_info.commandBufferCount = 1;
VkCommandBuffer copy_buffer;
VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, &copy_buffer));
VkCommandBufferBeginInfo command_buffer_begin_info{};
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VK_CHECK(vkBeginCommandBuffer(copy_buffer, &command_buffer_begin_info));
VkBufferCopy buffer_copy{};
buffer_copy.srcOffset = 0;
buffer_copy.dstOffset = 0;
buffer_copy.size = size;
vkCmdCopyBuffer(copy_buffer, src, dst, 1, &buffer_copy);
vkEndCommandBuffer(copy_buffer);
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &copy_buffer;
vkQueueSubmit(transfer_queue_, 1, &submit_info, VK_NULL_HANDLE);
vkQueueWaitIdle(transfer_queue_);
vkFreeCommandBuffers(device_, copy_pool, 1, &copy_buffer);
vkDestroyCommandPool(device_, copy_pool, nullptr);
}
void UwURenderEngine::allocate_command_buffers()
{
command_buffers_.resize(swapchain_images_.size());
@@ -923,7 +798,7 @@ void UwURenderEngine::allocate_command_buffers()
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
command_buffer_allocate_info.commandBufferCount = static_cast<uint32_t>(command_buffers_.size());
VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, command_buffers_.data()));
VK_CHECK(vkAllocateCommandBuffers(device_, &command_buffer_allocate_info, command_buffers_.data()))
}
void UwURenderEngine::create_sync_objects()
@@ -941,9 +816,9 @@ void UwURenderEngine::create_sync_objects()
for (size_t i = 0; i < swapchain_images_.size(); ++i)
{
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &image_available_semaphores_[i]));
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &render_finished_semaphores_[i]));
VK_CHECK(vkCreateFence(device_, &fence_info, nullptr, &in_flight_fences_[i]));
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &image_available_semaphores_[i]))
VK_CHECK(vkCreateSemaphore(device_, &semaphore_info, nullptr, &render_finished_semaphores_[i]))
VK_CHECK(vkCreateFence(device_, &fence_info, nullptr, &in_flight_fences_[i]))
}
}
@@ -951,7 +826,7 @@ void UwURenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint
{
VkCommandBufferBeginInfo command_buffer_begin_info{};
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
VK_CHECK(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info));
VK_CHECK(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info))
constexpr VkClearValue clear_color = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
VkRenderPassBeginInfo render_pass_begin_info{};
@@ -991,17 +866,33 @@ void UwURenderEngine::record_command_buffer(VkCommandBuffer command_buffer, uint
vkCmdDrawIndexed(command_buffer, static_cast<uint32_t>(indices_.size()), 1, 0, 0, 0);
vkCmdEndRenderPass(command_buffer);
VK_CHECK(vkEndCommandBuffer(command_buffer));
VK_CHECK(vkEndCommandBuffer(command_buffer))
}
void UwURenderEngine::update_uniform_buffer(uint32_t current_frame)
void UwURenderEngine::update_uniform_buffer(uint32_t current_frame) const
{
glm::vec3 eye{0, 0, 0};
glm::vec3 center{0, 0, 0};
glm::vec3 up{0, 1, 0};
if (active_camera_.expired() == false)
{
std::shared_ptr<Camera> camera = active_camera_.lock();
Vector3D loc = camera->GetActorLocate();
eye = {loc.x, loc.y, loc.z};
Vector3D rot = camera->GetActorRotate();
glm::vec3 direction{glm::cos(rot.x)*glm::cos(rot.y), glm::sin(rot.x)*glm::cos(rot.y), glm::sin(rot.y)};
center = eye + direction;
up = {0, glm::sin(rot.z), glm::cos(rot.z)};
}
static auto start_time = std::chrono::high_resolution_clock::now();
auto current_time = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration_cast<std::chrono::duration<float>>(current_time - start_time).count();
UniformBufferObject ubo{};
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
UniformBufferObject ubo;
ubo.model = glm::rotate(glm::mat4(1.0f), /*time * glm::radians(45.0f)*/0.f, glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(eye, center, up);
ubo.proj = glm::perspective(glm::radians(45.0f), static_cast<float>(swapchain_extent_.width) / static_cast<float>(swapchain_extent_.height), 0.1f, 256.0f);
ubo.proj[1][1] *= -1;
memcpy(uniform_buffers_mapped_[current_frame], &ubo, sizeof(ubo));
@@ -1012,13 +903,16 @@ void UwURenderEngine::draw_frame()
vkWaitForFences(device_, 1, &in_flight_fences_[current_frame_], VK_TRUE, UINT64_MAX);
vkResetFences(device_, 1, &in_flight_fences_[current_frame_]);
// Free video memory
garbage_collector_->FreeHeap();
uint32_t image_index;
vkAcquireNextImageKHR(device_, swapchain_, UINT64_MAX, image_available_semaphores_[current_frame_], VK_NULL_HANDLE, &image_index);
vkResetCommandBuffer(command_buffers_[current_frame_], 0);
record_command_buffer(command_buffers_[current_frame_], image_index);
update_uniform_buffer(current_frame_);
record_command_buffer(command_buffers_[current_frame_], image_index);
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo submit_info{};
@@ -1031,7 +925,7 @@ void UwURenderEngine::draw_frame()
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &render_finished_semaphores_[current_frame_];
VK_CHECK(vkQueueSubmit(graphics_queue_, 1, &submit_info, in_flight_fences_[current_frame_]));
VK_CHECK(vkQueueSubmit(graphics_queue_, 1, &submit_info, in_flight_fences_[current_frame_]))
VkPresentInfoKHR present_info{};
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@@ -1044,12 +938,12 @@ void UwURenderEngine::draw_frame()
vkQueuePresentKHR(present_queue_, &present_info);
current_frame_ = (current_frame_ + 1) % static_cast<int>(swapchain_images_.size());
current_frame_ = (current_frame_ + 1) % static_cast<unsigned int>(swapchain_images_.size());
}
void UwURenderEngine::create_surface()
{
VK_CHECK(glfwCreateWindowSurface(instance_, get_window(), nullptr, &surface_));
VK_CHECK(glfwCreateWindowSurface(instance_, get_window(), nullptr, &surface_))
}
UwURenderEngine::UwURenderEngine(CoreInstance& core):
@@ -1076,6 +970,9 @@ core_(core)
allocate_command_buffers();
allocate_index_buffer();
create_sync_objects();
garbage_collector_.reset(new GPU_GarbageCollector(device_));
model_manager_.reset(new ModelManager(physical_device_, device_));
}
UwURenderEngine::~UwURenderEngine()
@@ -1163,9 +1060,12 @@ UwURenderEngine::~UwURenderEngine()
void UwURenderEngine::start()
{
World* world = core_.GetGameInstance()->GetWorld();
std::vector<UType::object_ptr<Mesh>> meshes = world->GetActorsByClass<Mesh>();
std::vector<std::weak_ptr<Mesh>> meshes = world->GetActorsByClass<Mesh>();
for (auto& i : meshes)
i->load_model(i->GetModelName());
{
std::shared_ptr<Mesh> mesh = i.lock();
mesh->load_model(mesh->GetModelName());
}
while (!glfwWindowShouldClose(get_window()))
{
@@ -1179,3 +1079,9 @@ void UwURenderEngine::stop_render() const
if (!glfwWindowShouldClose(get_window()))
glfwSetWindowShouldClose(get_window(), true);
}
void UwURenderEngine::SetActiveCamera(std::weak_ptr<Camera> camera)
{
std::scoped_lock lock(m_active_camera_);
active_camera_ = camera;
}
@@ -1,42 +1,37 @@
#pragma once
#include "RenderEngineBase.hpp"
#include "ModelManager.hpp"
#include <optional>
#include <vector>
#include <string>
#include <memory>
#define GLM_FORCE_RADIANS
#include <mutex>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#ifdef _DEBUG
#include <assert.h>
#define VK_CHECK(res) assert(res == VK_SUCCESS)
#else
#define VK_CHECK(res) if ((res) != VK_SUCCESS) throw std::runtime_error("Vulkan error: " + std::to_string(res))
#endif
class Camera;
class GPU_GarbageCollector;
#define GET_RENDER_ENGINE static_cast<UwURenderEngine*>(GetWorld()->GetGameInstance().GetCore().GetRenderEngine())
class UwURenderEngine : public RenderEngineBase
{
struct QueueFamilyIndices
{
std::optional<uint32_t> graphics_family;
std::optional<uint32_t> present_family;
std::optional<uint32_t> transfer_family;
uint32_t graphics_family = 0;
uint32_t present_family = 0;
uint32_t transfer_family = 0;
bool is_find_graphics_family = false;
bool is_find_present_family = false;
bool is_find_transfer_family = false;
};
struct SwapchainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> present_modes;
};
struct Vertex
{
glm::vec3 pos;
glm::vec3 color;
static VkVertexInputBindingDescription get_binding_description();
static std::array<VkVertexInputAttributeDescription, 2> get_vertex_attribute_descriptions();
VkSurfaceCapabilitiesKHR capabilities;
};
struct UniformBufferObject {
glm::mat4 model;
@@ -44,7 +39,7 @@ class UwURenderEngine : public RenderEngineBase
glm::mat4 proj;
};
const std::vector<Vertex> vertices_ = {
const std::vector<ModelManager::Vertex> vertices_ = {
{{-0.5f, -0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}},
{{0.5f, -0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
{{0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
@@ -65,9 +60,14 @@ class UwURenderEngine : public RenderEngineBase
static const std::vector<const char*> deviceExtensions;
int current_frame_ = 0;
// Counting frame from the beginning
unsigned int current_frame_ = 0;
CoreInstance& core_;
std::shared_ptr<ModelManager> model_manager_;
std::shared_ptr<GPU_GarbageCollector> garbage_collector_;
std::weak_ptr<Camera> active_camera_;
std::mutex m_active_camera_;
VkInstance instance_ = VK_NULL_HANDLE;
VkSurfaceKHR surface_ = VK_NULL_HANDLE;
@@ -114,13 +114,8 @@ class UwURenderEngine : public RenderEngineBase
static QueueFamilyIndices find_queue_family_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface);
static VkSurfaceFormatKHR choose_surface_format(const std::vector<VkSurfaceFormatKHR>& surface_formats);
static VkPresentModeKHR choose_present_mode(const std::vector<VkPresentModeKHR>& present_modes, VkPresentModeKHR desired_present_mode);
static VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window);
VkShaderModule create_shader_module(const std::string& code) const;
void create_buffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkBuffer* buffer, const std::vector<uint32_t>& queue_families);
void allocate_memory(VkBuffer buffer, VkMemoryPropertyFlags property, VkDeviceMemory* device_memory);
uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) const;
std::vector<uint32_t> get_unique_family_indices(const QueueFamilyIndices& indices);
static std::vector<uint32_t> get_unique_family_indices(const QueueFamilyIndices& indices);
void create_instance();
void create_surface();
@@ -141,18 +136,18 @@ class UwURenderEngine : public RenderEngineBase
void allocate_vertex_buffer();
void allocate_index_buffer();
void copy_memory(VkBuffer src, VkBuffer dst, VkDeviceSize size);
void record_command_buffer(VkCommandBuffer command_buffer, uint32_t image_index) const;
void update_uniform_buffer(uint32_t current_frame);
void update_uniform_buffer(uint32_t current_frame) const;
void draw_frame();
public:
// Can throw the exception
UwURenderEngine(CoreInstance& core);
explicit UwURenderEngine(CoreInstance& core);
~UwURenderEngine() override;
void start() override;
void stop_render() const override;
};
std::shared_ptr<ModelManager> GetModelManager() const { return model_manager_; }
RENDER_ENGINE_FACTORY_GENERATE(UwURenderEngine)
void SetActiveCamera(std::weak_ptr<Camera> camera);
};
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,4 +1,5 @@
@echo off
cd build
cmake -DBUILD_MODE=All ..
cmake --build . --config Release
pause
-5
View File
@@ -3,9 +3,4 @@ mkdir .\build
cd build
cmake -DBUILD_MODE=Engine ..
cmake --build . --config Release
cd ..
mkdir ".\build\bin\include"
robocopy ".\Core" ".\build\bin\include\Core" *.h *.hpp /S
robocopy ".\Delegate" ".\build\bin\include\Delegate" *.h *.hpp /S
robocopy ".\FastRTTI" ".\build\bin\include\FastRTTI" *.h *.hpp /S
pause
+1 -1
Submodule glfw updated: 8e15281d34...b00e6a8a88