Add resource manager

This commit is contained in:
bailwillharr 2022-12-01 15:54:28 +00:00
parent 648bdf19fe
commit 60d1452f01
14 changed files with 178 additions and 83 deletions

View File

@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.24)
# options # options
option(ENGINE_BUILD_TEST "Compile the test program" ON) option(ENGINE_BUILD_TEST "Compile the test program" ON)
option(ENGINE_BUILD_VULKAN "Use Vulkan 1.3 for graphics" ON) option(ENGINE_BUILD_VULKAN "Use Vulkan 1.3 for graphics" ON)
option(ENGINE_BUILD_OPENGL "Use OpenGL 4.5 for graphics" OFF)
project(engine LANGUAGES CXX project(engine LANGUAGES CXX
VERSION "0.1.0" VERSION "0.1.0"
@ -12,8 +11,12 @@ project(engine LANGUAGES CXX
set(SRC_FILES set(SRC_FILES
"src/application.cpp" "src/application.cpp"
"src/window.cpp" "src/window.cpp"
"src/input_manager.cpp" "src/input_manager.cpp"
"src/scene_manager.cpp" "src/scene_manager.cpp"
"src/texture_manager.cpp"
"src/texture.cpp"
"src/gfx_device_vulkan.cpp" "src/gfx_device_vulkan.cpp"
"src/scene.cpp" "src/scene.cpp"
@ -31,8 +34,14 @@ set(INCLUDE_FILES
"include/window.hpp" "include/window.hpp"
"include/inputs/keyboard.hpp" "include/inputs/keyboard.hpp"
"include/inputs/mouse.hpp" "include/inputs/mouse.hpp"
"include/input_manager.hpp" "include/input_manager.hpp"
"include/scene_manager.hpp" "include/scene_manager.hpp"
"include/resource_manager.hpp"
"include/texture_manager.hpp"
"include/texture.hpp"
"include/gfx.hpp" "include/gfx.hpp"
"include/gfx_device.hpp" "include/gfx_device.hpp"
@ -76,8 +85,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
# figure out what graphics api to use # figure out what graphics api to use
if (ENGINE_BUILD_VULKAN) if (ENGINE_BUILD_VULKAN)
target_compile_definitions(${PROJECT_NAME} PRIVATE "ENGINE_BUILD_VULKAN") target_compile_definitions(${PROJECT_NAME} PRIVATE "ENGINE_BUILD_VULKAN")
elseif(ENGINE_BUILD_OPENGL)
target_compile_definitions(${PROJECT_NAME} PRIVATE "ENGINE_BUILD_OPENGL")
else() else()
target_compile_definitions(${PROJECT_NAME} PRIVATE "ENGINE_BUILD_NULL") target_compile_definitions(${PROJECT_NAME} PRIVATE "ENGINE_BUILD_NULL")
endif() endif()
@ -119,12 +126,9 @@ if(ENGINE_BUILD_VULKAN)
set(VOLK_HEADERS_ONLY ON) set(VOLK_HEADERS_ONLY ON)
add_subdirectory(dependencies/volk) add_subdirectory(dependencies/volk)
target_link_libraries(${PROJECT_NAME} PRIVATE volk_headers) target_link_libraries(${PROJECT_NAME} PRIVATE volk_headers)
# Vulkan Memory Allocator # Vulkan Memory Allocator
target_include_directories(${PROJECT_NAME} PRIVATE dependencies/VulkanMemoryAllocator/include) target_include_directories(${PROJECT_NAME} PRIVATE dependencies/VulkanMemoryAllocator/include)
# shaderc # shaderc
if (MSVC) if (MSVC)
include(FindVulkan) include(FindVulkan)
find_package(Vulkan COMPONENTS shaderc_combined) find_package(Vulkan COMPONENTS shaderc_combined)
@ -132,7 +136,6 @@ if(ENGINE_BUILD_VULKAN)
else() else()
target_link_libraries(${PROJECT_NAME} PRIVATE shaderc_shared) target_link_libraries(${PROJECT_NAME} PRIVATE shaderc_shared)
endif() endif()
endif() endif()
# SDL2: # SDL2:

View File

@ -0,0 +1,85 @@
#pragma once
#include "engine_api.h"
#include "resources/resource.hpp"
#include <vector>
#include <unordered_map>
// Doesn't own resources, only holds weak_ptrs
namespace engine {
class ENGINE_API ResourceManager {
public:
ResourceManager();
ResourceManager(const ResourceManager&) = delete;
ResourceManager& operator=(const ResourceManager&) = delete;
~ResourceManager() = default;
template <class T>
std::shared_ptr<T> create(const std::string& name);
// creates the resource if it is not in the map or the weak_ptr has expired
template <class T>
std::shared_ptr<T> get(const std::string& name);
std::unique_ptr<std::string> getResourcesListString();
std::vector<std::weak_ptr<Resource>> getAllResourcesOfType(const std::string& type);
std::filesystem::path getFilePath(const std::string& name);
private:
std::filesystem::path m_resourcesPath;
std::unordered_map<std::string, std::weak_ptr<Resource>> m_resources;
};
template <class T>
std::shared_ptr<T> ResourceManager::create(const std::string& name)
{
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::create() error: specified type is not a subclass of 'Resource'");
}
auto resource = std::make_shared<T>(getFilePath(name));
m_resources.emplace(name, std::dynamic_pointer_cast<Resource>(resource));
return resource;
}
template <class T>
std::shared_ptr<T> ResourceManager::get(const std::string& name)
{
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::get() error: specified type is not a subclass of 'Resource'");
}
if (m_resources.contains(name)) {
std::weak_ptr<Resource> res = m_resources.at(name);
if (res.expired() == false) {
// resource definitely exists
auto castedSharedPtr = std::dynamic_pointer_cast<T>(res.lock());
if (castedSharedPtr == nullptr) {
throw std::runtime_error("error: attempt to get Resource which already exists as another type");
}
else {
return castedSharedPtr;
}
}
else {
// Resource in map but no longer exists. Delete it.
m_resources.erase(name);
}
}
return create<T>(name);
}
}

View File

@ -1,85 +1,48 @@
#pragma once #pragma once
#include "engine_api.h"
#include "resources/resource.hpp"
#include <vector>
#include <unordered_map> #include <unordered_map>
#include <string>
// Doesn't own resources, only holds weak_ptrs #include <memory>
#include <stdexcept>
namespace engine { namespace engine {
class ENGINE_API ResourceManager { template <class T>
class ResourceManager {
public: public:
ResourceManager(); ResourceManager() {}
virtual ~ResourceManager() {}
ResourceManager(const ResourceManager&) = delete; ResourceManager(const ResourceManager&) = delete;
ResourceManager& operator=(const ResourceManager&) = delete; ResourceManager& operator=(const ResourceManager&) = delete;
~ResourceManager() = default;
template <class T> std::shared_ptr<T> add(const std::string& name, std::unique_ptr<T>&& resource)
std::shared_ptr<T> create(const std::string& name); {
if (m_resources.contains(name) == false) {
std::shared_ptr<T> ptr = std::move(resource);
m_resources.emplace(name, ptr);
}
else {
throw std::runtime_error("Cannot add a resource which already exists");
}
return m_resources.at(name).lock();
}
// creates the resource if it is not in the map or the weak_ptr has expired std::shared_ptr<T> get(const std::string& name)
template <class T> {
std::shared_ptr<T> get(const std::string& name); if (m_resources.contains(name)) {
std::weak_ptr<T> resource = m_resources.at(name);
std::unique_ptr<std::string> getResourcesListString(); if (resource.expired() == false) {
return resource.lock();
std::vector<std::weak_ptr<Resource>> getAllResourcesOfType(const std::string& type); }
}
std::filesystem::path getFilePath(const std::string& name); return {};
}
private: private:
std::filesystem::path m_resourcesPath; // weak ptrs are used to check a resource's use count. If the use count of a resource hits 0, the resource can safely be deleted.
std::unordered_map<std::string, std::weak_ptr<Resource>> m_resources; std::unordered_map<std::string, std::weak_ptr<T>> m_resources{};
}; };
template <class T>
std::shared_ptr<T> ResourceManager::create(const std::string& name)
{
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::create() error: specified type is not a subclass of 'Resource'");
}
auto resource = std::make_shared<T>(getFilePath(name));
m_resources.emplace(name, std::dynamic_pointer_cast<Resource>(resource));
return resource;
}
template <class T>
std::shared_ptr<T> ResourceManager::get(const std::string& name)
{
if (std::is_base_of<Resource, T>::value == false) {
throw std::runtime_error("ResourceManager::get() error: specified type is not a subclass of 'Resource'");
}
if (m_resources.contains(name)) {
std::weak_ptr<Resource> res = m_resources.at(name);
if (res.expired() == false) {
// resource definitely exists
auto castedSharedPtr = std::dynamic_pointer_cast<T>(res.lock());
if (castedSharedPtr == nullptr) {
throw std::runtime_error("error: attempt to get Resource which already exists as another type");
}
else {
return castedSharedPtr;
}
}
else {
// Resource in map but no longer exists. Delete it.
m_resources.erase(name);
}
}
return create<T>(name);
}
} }

View File

@ -6,6 +6,7 @@
namespace engine { namespace engine {
class Scene; // "scene.hpp" class Scene; // "scene.hpp"
class TextureManager; // "texture_manager.hpp"
class SceneManager { class SceneManager {
@ -23,6 +24,8 @@ namespace engine {
std::vector<std::unique_ptr<Scene>> m_scenes; std::vector<std::unique_ptr<Scene>> m_scenes;
int m_activeSceneIndex = -1; int m_activeSceneIndex = -1;
const std::unique_ptr<TextureManager> m_textureManager;
}; };
} }

View File

@ -1,3 +1,4 @@
#if 0
#pragma once #pragma once
#include "engine_api.h" #include "engine_api.h"
@ -21,3 +22,4 @@ private:
}; };
} }
#endif

View File

@ -0,0 +1,23 @@
#pragma once
#include "resource_manager.hpp"
namespace engine {
class Texture {
};
class TextureManager : public ResourceManager<Texture> {
public:
TextureManager();
~TextureManager() override;
TextureManager(const TextureManager&) = delete;
TextureManager& operator=(const TextureManager&) = delete;
private:
};
}

View File

@ -1,3 +0,0 @@
#!/bin/sh
cd "Release/test"
./enginetest

View File

@ -56,7 +56,6 @@ namespace engine {
} }
m_gfx->waitIdle(); m_gfx->waitIdle();
} }
} }

View File

@ -1,6 +1,5 @@
// The implementation of the graphics layer using Vulkan 1.3. // The implementation of the graphics layer using Vulkan 1.3.
//#undef ENGINE_BUILD_VULKAN
#ifdef ENGINE_BUILD_VULKAN #ifdef ENGINE_BUILD_VULKAN
#include "gfx_device.hpp" #include "gfx_device.hpp"
@ -1569,7 +1568,7 @@ namespace engine {
renderPassInfo.renderArea.extent = pimpl->swapchain.extent; renderPassInfo.renderArea.extent = pimpl->swapchain.extent;
std::array<VkClearValue, 2> clearValues{}; std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 0.0f, 0.0f, 1.0f} }; clearValues[0].color = { {0.1f, 0.1f, 0.1f, 1.0f} };
clearValues[1].depthStencil = { 1.0f, 0 }; clearValues[1].depthStencil = { 1.0f, 0 };
renderPassInfo.clearValueCount = (uint32_t)clearValues.size(); renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
renderPassInfo.pClearValues = clearValues.data(); renderPassInfo.pClearValues = clearValues.data();

View File

@ -1,14 +1,16 @@
#include "scene_manager.hpp" #include "scene_manager.hpp"
#include "scene.hpp" #include "scene.hpp"
#include "texture_manager.hpp"
#include "log.hpp" #include "log.hpp"
namespace engine { namespace engine {
SceneManager::SceneManager() SceneManager::SceneManager()
: m_textureManager(std::make_unique<TextureManager>())
{ {
auto tex = std::make_unique<Texture>();
m_textureManager->add("myTexture", std::move(tex));
} }
SceneManager::~SceneManager() {} SceneManager::~SceneManager() {}

View File

@ -1,3 +1,5 @@
#if 0
#include "resources/texture.hpp" #include "resources/texture.hpp"
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@ -116,3 +118,5 @@ gfx::Texture* Texture::getHandle()
} }
} }
#endif

15
src/texture_manager.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "texture_manager.hpp"
namespace engine {
TextureManager::TextureManager()
{
}
TextureManager::~TextureManager()
{
}
}

View File

@ -8,7 +8,7 @@ void playGame()
engine::Application app(PROJECT_NAME, PROJECT_VERSION); engine::Application app(PROJECT_NAME, PROJECT_VERSION);
// configure window // configure window
app.window()->setRelativeMouseMode(true); app.window()->setRelativeMouseMode(false);
app.gameLoop(); app.gameLoop();
} }