TMP / Made {GLFW,Vulkan}Managers more OO

This commit is contained in:
OLEGSHA 2023-03-27 21:33:09 +02:00
parent 50e3a44a81
commit 54f73b2e44
10 changed files with 179 additions and 106 deletions

View File

@ -8,18 +8,25 @@
#include "../../main/logging.h" #include "../../main/logging.h"
#include "../../main/meta.h" #include "../../main/meta.h"
#include "vulkan_mgmt.h" #include "../../main/util.h"
using namespace progressia::main::logging; using namespace progressia::main::logging;
namespace progressia::desktop { namespace progressia::desktop {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables): global variable required for GLFW callbacks
static GLFWwindow *window = nullptr;
static void onGlfwError(int errorCode, const char *description); static void onGlfwError(int errorCode, const char *description);
static void onWindowGeometryChange(GLFWwindow *window, int width, int height); static void onWindowGeometryChange(GLFWwindow *window, int width, int height);
void initializeGlfw() { class GlfwManagerImpl : public GlfwManager {
private:
GLFWwindow *window = nullptr;
std::function<void()> onScreenResize = nullptr;
public:
DISABLE_COPYING(GlfwManagerImpl)
DISABLE_MOVING(GlfwManagerImpl)
GlfwManagerImpl() {
debug("Beginning GLFW init"); debug("Beginning GLFW init");
glfwSetErrorCallback(onGlfwError); glfwSetErrorCallback(onGlfwError);
@ -44,24 +51,51 @@ void initializeGlfw() {
} }
constexpr auto windowDimensions = 800; constexpr auto windowDimensions = 800;
window = glfwCreateWindow(windowDimensions, windowDimensions, title.c_str(), window = glfwCreateWindow(windowDimensions, windowDimensions,
nullptr, nullptr); title.c_str(), nullptr, nullptr);
glfwSetWindowSizeCallback(window, onWindowGeometryChange); glfwSetWindowSizeCallback(window, onWindowGeometryChange);
debug("GLFW init complete"); debug("GLFW init complete");
} }
void showWindow() { ~GlfwManagerImpl() override { glfwTerminate(); }
void setOnScreenResize(std::function<void()> hook) override {
onScreenResize = hook;
}
void showWindow() override {
glfwShowWindow(window); glfwShowWindow(window);
debug("Window now visible"); debug("Window now visible");
} }
bool shouldRun() { return !glfwWindowShouldClose(window); } bool shouldRun() override { return !glfwWindowShouldClose(window); }
void doGlfwRoutine() { glfwPollEvents(); } void doGlfwRoutine() override { glfwPollEvents(); }
void shutdownGlfw() { glfwTerminate(); } friend GLFWwindow *getGLFWWindowHandle();
friend void onWindowGeometryChange(GLFWwindow *, int, int);
};
namespace {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables): global variables required by GLFW C callbacks
std::weak_ptr<GlfwManagerImpl> theGlfwManager;
} // namespace
std::shared_ptr<GlfwManager> makeGlfwManager() {
if (!theGlfwManager.expired()) {
fatal("GlfwManager already exists");
// REPORT_ERROR
exit(1);
}
std::shared_ptr<GlfwManagerImpl> aGlfwManager =
std::make_shared<GlfwManagerImpl>();
theGlfwManager = aGlfwManager;
return aGlfwManager;
}
void onGlfwError(int errorCode, const char *description) { void onGlfwError(int errorCode, const char *description) {
fatal() << "[GLFW] " << description << " (" << errorCode << ")"; fatal() << "[GLFW] " << description << " (" << errorCode << ")";
@ -71,13 +105,25 @@ void onGlfwError(int errorCode, const char *description) {
void onWindowGeometryChange(GLFWwindow *window, [[maybe_unused]] int width, void onWindowGeometryChange(GLFWwindow *window, [[maybe_unused]] int width,
[[maybe_unused]] int height) { [[maybe_unused]] int height) {
if (window != progressia::desktop::window) { if (auto manager = theGlfwManager.lock()) {
if (manager->window != window) {
return; return;
} }
resizeVulkanSurface(); if (manager->onScreenResize != nullptr) {
manager->onScreenResize();
}
} else {
return;
}
} }
GLFWwindow *getGLFWWindowHandle() { return window; } GLFWwindow *getGLFWWindowHandle() {
if (auto manager = theGlfwManager.lock()) {
return manager->window;
}
return nullptr;
}
} // namespace progressia::desktop } // namespace progressia::desktop

View File

@ -1,11 +1,22 @@
#pragma once #pragma once
#include <functional>
#include <memory>
namespace progressia::desktop { namespace progressia::desktop {
void initializeGlfw(); class GlfwManager {
void showWindow();
void shutdownGlfw(); public:
bool shouldRun(); virtual ~GlfwManager(){};
void doGlfwRoutine();
virtual void setOnScreenResize(std::function<void()>) = 0;
virtual void showWindow() = 0;
virtual bool shouldRun() = 0;
virtual void doGlfwRoutine() = 0;
};
std::shared_ptr<GlfwManager> makeGlfwManager();
} // namespace progressia::desktop } // namespace progressia::desktop

View File

@ -7,6 +7,7 @@
namespace progressia::desktop { namespace progressia::desktop {
// TODO refactor into OOP
GLFWwindow *getGLFWWindowHandle(); GLFWwindow *getGLFWWindowHandle();
} // namespace progressia::desktop } // namespace progressia::desktop

View File

@ -20,9 +20,7 @@ Image::Image(VkImage vk, VkImageView view, VkFormat format)
// do nothing // do nothing
} }
Image::~Image() { Image::~Image() = default;
// do nothing
}
/* /*
* ManagedImage * ManagedImage
@ -33,7 +31,7 @@ ManagedImage::ManagedImage(std::size_t width, std::size_t height,
VkImageUsageFlags usage, Vulkan &vulkan) VkImageUsageFlags usage, Vulkan &vulkan)
: :
Image(VK_NULL_HANDLE, VK_NULL_HANDLE, format), vulkan(vulkan), Image(VK_NULL_HANDLE, VK_NULL_HANDLE, format), memory(), vulkan(vulkan),
state{VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT} { state{VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT} {
@ -146,7 +144,8 @@ Texture::Texture(const progressia::main::Image &src, Vulkan &vulkan)
ManagedImage(src.width, src.height, VK_FORMAT_R8G8B8A8_SRGB, ManagedImage(src.width, src.height, VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
vulkan) { vulkan),
sampler() {
/* /*
* Create a staging buffer * Create a staging buffer
@ -211,9 +210,9 @@ Texture::Texture(const progressia::main::Image &src, Vulkan &vulkan)
samplerInfo.compareEnable = VK_FALSE; samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f; samplerInfo.mipLodBias = 0.0F;
samplerInfo.minLod = 0.0f; samplerInfo.minLod = 0.0F;
samplerInfo.maxLod = 0.0f; samplerInfo.maxLod = 0.0F;
vulkan.handleVkResult( vulkan.handleVkResult(
"Could not create texture sampler", "Could not create texture sampler",
@ -223,6 +222,7 @@ Texture::Texture(const progressia::main::Image &src, Vulkan &vulkan)
* Create descriptor set * Create descriptor set
*/ */
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer): sampler must be set using vkCreateSampler first
descriptorSet = vulkan.getTextureDescriptors().addTexture(view, sampler); descriptorSet = vulkan.getTextureDescriptors().addTexture(view, sampler);
} }
@ -233,8 +233,8 @@ Texture::~Texture() {
void Texture::bind() { void Texture::bind() {
// REPORT_ERROR if getCurrentFrame() == nullptr // REPORT_ERROR if getCurrentFrame() == nullptr
auto commandBuffer = vulkan.getCurrentFrame()->getCommandBuffer(); auto *commandBuffer = vulkan.getCurrentFrame()->getCommandBuffer();
auto pipelineLayout = vulkan.getPipeline().getLayout(); auto *pipelineLayout = vulkan.getPipeline().getLayout();
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipelineLayout, pipelineLayout,

View File

@ -35,8 +35,9 @@ class ManagedImage : public Image {
State state; State state;
public: public:
ManagedImage(std::size_t width, std::size_t height, VkFormat, ManagedImage(std::size_t width, std::size_t height, VkFormat format,
VkImageAspectFlags, VkImageUsageFlags, Vulkan &); VkImageAspectFlags aspect, VkImageUsageFlags usage,
Vulkan &vulkan);
~ManagedImage(); ~ManagedImage();
void transition(State); void transition(State);
@ -48,7 +49,7 @@ class Texture : public ManagedImage {
VkSampler sampler; VkSampler sampler;
VkDescriptorSet descriptorSet; VkDescriptorSet descriptorSet;
Texture(const progressia::main::Image &, Vulkan &vulkan); Texture(const main::Image &src, Vulkan &vulkan);
~Texture(); ~Texture();
void bind(); void bind();

View File

@ -8,25 +8,25 @@ using namespace progressia::main::logging;
namespace progressia::desktop { namespace progressia::desktop {
Vulkan *vulkan; VulkanManager::VulkanManager() {
void initializeVulkan() {
debug("Vulkan initializing"); debug("Vulkan initializing");
// Instance extensions // Instance extensions
std::vector<const char *> instanceExtensions; std::vector<const char *> instanceExtensions;
{ {
uint32_t glfwExtensionCount; uint32_t glfwExtensionCount = 0;
const char **glfwExtensions; const char **glfwExtensions =
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
instanceExtensions.reserve(instanceExtensions.size() +
glfwExtensionCount);
for (std::size_t i = 0; i < glfwExtensionCount; i++) { for (std::size_t i = 0; i < glfwExtensionCount; i++) {
instanceExtensions.push_back(glfwExtensions[i]); instanceExtensions.emplace_back(glfwExtensions[i]);
} }
#ifdef VULKAN_ERROR_CHECKING #ifdef VULKAN_ERROR_CHECKING
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); instanceExtensions.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif #endif
} }
@ -42,28 +42,21 @@ void initializeVulkan() {
#endif #endif
}; };
vulkan = new Vulkan(instanceExtensions, deviceExtensions, validationLayers); vulkan = std::make_unique<Vulkan>(instanceExtensions, deviceExtensions,
validationLayers);
debug("Vulkan initialized"); debug("Vulkan initialized");
} }
Vulkan *getVulkan() { return vulkan; } VulkanManager::~VulkanManager() { debug("Vulkan terminating"); }
bool startRender() { return vulkan->startRender(); } Vulkan *VulkanManager::getVulkan() { return vulkan.get(); }
const Vulkan *VulkanManager::getVulkan() const { return vulkan.get(); }
void endRender() { return vulkan->endRender(); } bool VulkanManager::startRender() { return vulkan->startRender(); }
void resizeVulkanSurface() { vulkan->getSwapChain().recreate(); } void VulkanManager::endRender() { return vulkan->endRender(); }
void shutdownVulkan() { void VulkanManager::resizeSurface() { vulkan->getSwapChain().recreate(); }
debug("Vulkan terminating");
if (vulkan != nullptr) {
delete vulkan;
vulkan = nullptr;
}
debug("Vulkan terminated");
}
} // namespace progressia::desktop } // namespace progressia::desktop

View File

@ -4,18 +4,25 @@
namespace progressia::desktop { namespace progressia::desktop {
void initializeVulkan(); class VulkanManager {
private:
std::unique_ptr<Vulkan> vulkan;
public:
VulkanManager();
~VulkanManager();
Vulkan *getVulkan(); Vulkan *getVulkan();
const Vulkan *getVulkan() const;
void resizeVulkanSurface(); void resizeSurface();
/* /*
* Returns false when the frame should be skipped * Returns false when the frame should be skipped
*/ */
bool startRender(); bool startRender();
void endRender(); void endRender();
};
void shutdownVulkan();
} // namespace progressia::desktop } // namespace progressia::desktop

View File

@ -13,7 +13,6 @@ int main(int argc, char *argv[]) {
using namespace progressia; using namespace progressia;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): infeasible to avoid in C++17
char *arg = argv[i]; char *arg = argv[i];
if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
std::cout << main::meta::NAME << " " << main::meta::VERSION << "+" std::cout << main::meta::NAME << " " << main::meta::VERSION << "+"
@ -28,30 +27,29 @@ int main(int argc, char *argv[]) {
<< main::meta::VERSION_NUMBER << ")"; << main::meta::VERSION_NUMBER << ")";
debug("Debug is enabled"); debug("Debug is enabled");
desktop::initializeGlfw(); auto glfwManager = desktop::makeGlfwManager();
desktop::initializeVulkan(); desktop::VulkanManager vulkanManager;
desktop::showWindow(); glfwManager->setOnScreenResize([&]() { vulkanManager.resizeSurface(); });
glfwManager->showWindow();
main::initialize(desktop::getVulkan()->getGint()); main::initialize(vulkanManager.getVulkan()->getGint());
info("Loading complete"); info("Loading complete");
while (desktop::shouldRun()) { while (glfwManager->shouldRun()) {
bool abortFrame = !desktop::startRender(); bool abortFrame = !vulkanManager.startRender();
if (abortFrame) { if (abortFrame) {
continue; continue;
} }
main::renderTick(); main::renderTick();
desktop::endRender(); vulkanManager.endRender();
desktop::doGlfwRoutine(); glfwManager->doGlfwRoutine();
} }
info("Shutting down"); info("Shutting down");
desktop::getVulkan()->waitIdle(); vulkanManager.getVulkan()->waitIdle();
main::shutdown(); main::shutdown();
desktop::shutdownVulkan();
desktop::shutdownGlfw();
return 0; return 0;
} }

View File

@ -29,6 +29,18 @@
} }
// clang-format on // clang-format on
// clang-format off
#define DISABLE_MOVING(CLASS) \
CLASS &operator=(CLASS &&) = delete; \
CLASS(CLASS &&) = delete; \
// clang-format on
// clang-format off
#define DISABLE_COPYING(CLASS) \
CLASS &operator=(const CLASS &) = delete; \
CLASS(const CLASS &) = delete; \
// clang-format on
namespace progressia::main { namespace progressia::main {
struct NonCopyable { struct NonCopyable {

View File

@ -13,7 +13,8 @@ Checks: "-*,\
-*-avoid-c-arrays,\ -*-avoid-c-arrays,\
-readability-else-after-return,\ -readability-else-after-return,\
-readability-named-parameter,\ -readability-named-parameter,\
-readability-use-anyofallof" -readability-use-anyofallof,\
-cppcoreguidelines-pro-bounds-pointer-arithmetic"
# modernize-use-trailing-return-type # modernize-use-trailing-return-type
# ignore reason: reduces readability # ignore reason: reduces readability
@ -43,3 +44,6 @@ Checks: "-*,\
# readability-use-anyofallof # readability-use-anyofallof
# ignore reason: these relatively obscure functions reduce readability by # ignore reason: these relatively obscure functions reduce readability by
# increasing code complexity and verbosity # increasing code complexity and verbosity
# cppcoreguidelines-pro-bounds-pointer-arithmetic
# ignore reason: infeasible to avoid in C++17