Compare commits
16 Commits
e34abea452
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d1692198af | |||
| 1cfbfd61be | |||
| a76120b73a | |||
| 52ba89f193 | |||
| a1cf661286 | |||
| e1db9fd588 | |||
| 6389e6b25f | |||
| fa3e987e93 | |||
| 582b23d0f8 | |||
| 9db3d9b0e2 | |||
| 5b6974aa8b | |||
| 12a55521bd | |||
| 734db410d1 | |||
| 1ab74b8128 | |||
| 740c80e8c7 | |||
| 1f88e0f0b9 |
+2
-1
@@ -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
@@ -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 ()
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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,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)
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#include "object_ptr.hpp"
|
||||
|
||||
std::unordered_map<void*, UType::counter::counter_owners> UType::counter::owners_map;
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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, ©_pool_info, nullptr, ©_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, ©_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 = ©_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, ©_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);
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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 ()
|
||||
@@ -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()));
|
||||
}
|
||||
@@ -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
-2
@@ -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
-1
@@ -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);
|
||||
};
|
||||
+139
-233
@@ -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_, ©_pool_info, nullptr, ©_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, ©_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 = ©_buffer;
|
||||
|
||||
vkQueueSubmit(transfer_queue_, 1, &submit_info, VK_NULL_HANDLE);
|
||||
vkQueueWaitIdle(transfer_queue_);
|
||||
|
||||
vkFreeCommandBuffers(device_, copy_pool, 1, ©_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;
|
||||
}
|
||||
+27
-32
@@ -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);
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
@echo off
|
||||
cd build
|
||||
cmake -DBUILD_MODE=All ..
|
||||
cmake --build . --config Release
|
||||
pause
|
||||
+32
-5
@@ -1,11 +1,38 @@
|
||||
@echo off
|
||||
|
||||
if "%VULKAN_SDK%"=="" (
|
||||
echo Vulkan SDK not found.
|
||||
|
||||
:: Запрашиваем подтверждение установки. Значение по умолчанию — Y
|
||||
set "ANSWER=y"
|
||||
set /p "ANSWER=Would you like to install it? [y/n, default: y]: "
|
||||
|
||||
:: Проверяем ответ с использованием отложенного расширения (! вместо %)
|
||||
if /i not "!ANSWER!"=="y" (
|
||||
echo Installation cancelled by user.
|
||||
exit /b
|
||||
)
|
||||
|
||||
echo Downloading Vulkan SDK...
|
||||
curl -L -o ".\vulkan_sdk.exe" "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe"
|
||||
|
||||
if exist ".\vulkan_sdk.exe" (
|
||||
echo Downloading finished successfully.
|
||||
echo Starting installation...
|
||||
|
||||
:: Запуск установщика в тихом режиме (параметр /S)
|
||||
start "" /wait ".\vulkan_sdk.exe" /S
|
||||
del .\vulkan_sdk.exe
|
||||
echo Installation completed.
|
||||
) else (
|
||||
echo Error: Failed to download Vulkan SDK.
|
||||
)
|
||||
) else (
|
||||
echo Vulkan SDK is already installed at: %VULKAN_SDK%
|
||||
)
|
||||
|
||||
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,4 +1,36 @@
|
||||
@echo off
|
||||
|
||||
if "%VULKAN_SDK%"=="" (
|
||||
echo Vulkan SDK not found.
|
||||
|
||||
:: Запрашиваем подтверждение установки. Значение по умолчанию — Y
|
||||
set "ANSWER=y"
|
||||
set /p "ANSWER=Would you like to install it? [y/n, default: y]: "
|
||||
|
||||
:: Проверяем ответ с использованием отложенного расширения (! вместо %)
|
||||
if /i not "!ANSWER!"=="y" (
|
||||
echo Installation cancelled by user.
|
||||
exit /b
|
||||
)
|
||||
|
||||
echo Downloading Vulkan SDK...
|
||||
curl -L -o ".\vulkan_sdk.exe" "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe"
|
||||
|
||||
if exist ".\vulkan_sdk.exe" (
|
||||
echo Downloading finished successfully.
|
||||
echo Starting installation...
|
||||
|
||||
:: Запуск установщика в тихом режиме (параметр /S)
|
||||
start "" /wait ".\vulkan_sdk.exe" /S
|
||||
del .\vulkan_sdk.exe
|
||||
echo Installation completed.
|
||||
) else (
|
||||
echo Error: Failed to download Vulkan SDK.
|
||||
)
|
||||
) else (
|
||||
echo Vulkan SDK is already installed at: %VULKAN_SDK%
|
||||
)
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DBUILD_MODE=All .. -A Win32
|
||||
|
||||
@@ -1,4 +1,36 @@
|
||||
@echo off
|
||||
|
||||
if "%VULKAN_SDK%"=="" (
|
||||
echo Vulkan SDK not found.
|
||||
|
||||
:: Запрашиваем подтверждение установки. Значение по умолчанию — Y
|
||||
set "ANSWER=y"
|
||||
set /p "ANSWER=Would you like to install it? [y/n, default: y]: "
|
||||
|
||||
:: Проверяем ответ с использованием отложенного расширения (! вместо %)
|
||||
if /i not "!ANSWER!"=="y" (
|
||||
echo Installation cancelled by user.
|
||||
exit /b
|
||||
)
|
||||
|
||||
echo Downloading Vulkan SDK...
|
||||
curl -L -o ".\vulkan_sdk.exe" "https://sdk.lunarg.com/sdk/download/latest/windows/vulkan-sdk.exe"
|
||||
|
||||
if exist ".\vulkan_sdk.exe" (
|
||||
echo Downloading finished successfully.
|
||||
echo Starting installation...
|
||||
|
||||
:: Запуск установщика в тихом режиме (параметр /S)
|
||||
start "" /wait ".\vulkan_sdk.exe" /S
|
||||
del .\vulkan_sdk.exe
|
||||
echo Installation completed.
|
||||
) else (
|
||||
echo Error: Failed to download Vulkan SDK.
|
||||
)
|
||||
) else (
|
||||
echo Vulkan SDK is already installed at: %VULKAN_SDK%
|
||||
)
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DBUILD_MODE=All .. -A x64
|
||||
|
||||
+1
-1
Submodule glfw updated: 8e15281d34...b00e6a8a88
Reference in New Issue
Block a user