mirror of
https://gitea.windcorp.ru/Wind-Corporation/Progressia.git
synced 2025-04-21 16:10:47 +03:00
TMP / Made {GLFW,Vulkan}Managers more OO
This commit is contained in:
parent
50e3a44a81
commit
54f73b2e44
@ -8,61 +8,95 @@
|
||||
|
||||
#include "../../main/logging.h"
|
||||
#include "../../main/meta.h"
|
||||
#include "vulkan_mgmt.h"
|
||||
#include "../../main/util.h"
|
||||
|
||||
using namespace progressia::main::logging;
|
||||
|
||||
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 onWindowGeometryChange(GLFWwindow *window, int width, int height);
|
||||
|
||||
void initializeGlfw() {
|
||||
debug("Beginning GLFW init");
|
||||
class GlfwManagerImpl : public GlfwManager {
|
||||
private:
|
||||
GLFWwindow *window = nullptr;
|
||||
std::function<void()> onScreenResize = nullptr;
|
||||
|
||||
glfwSetErrorCallback(onGlfwError);
|
||||
public:
|
||||
DISABLE_COPYING(GlfwManagerImpl)
|
||||
DISABLE_MOVING(GlfwManagerImpl)
|
||||
|
||||
if (!glfwInit()) {
|
||||
fatal("glfwInit() failed");
|
||||
GlfwManagerImpl() {
|
||||
debug("Beginning GLFW init");
|
||||
|
||||
glfwSetErrorCallback(onGlfwError);
|
||||
|
||||
if (!glfwInit()) {
|
||||
fatal("glfwInit() failed");
|
||||
// REPORT_ERROR
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
|
||||
std::string title;
|
||||
|
||||
{
|
||||
std::stringstream accumulator;
|
||||
accumulator << progressia::main::meta::NAME << " "
|
||||
<< progressia::main::meta::VERSION << " build "
|
||||
<< progressia::main::meta::BUILD_ID;
|
||||
title = accumulator.str();
|
||||
}
|
||||
|
||||
constexpr auto windowDimensions = 800;
|
||||
window = glfwCreateWindow(windowDimensions, windowDimensions,
|
||||
title.c_str(), nullptr, nullptr);
|
||||
|
||||
glfwSetWindowSizeCallback(window, onWindowGeometryChange);
|
||||
|
||||
debug("GLFW init complete");
|
||||
}
|
||||
|
||||
~GlfwManagerImpl() override { glfwTerminate(); }
|
||||
|
||||
void setOnScreenResize(std::function<void()> hook) override {
|
||||
onScreenResize = hook;
|
||||
}
|
||||
|
||||
void showWindow() override {
|
||||
glfwShowWindow(window);
|
||||
debug("Window now visible");
|
||||
}
|
||||
|
||||
bool shouldRun() override { return !glfwWindowShouldClose(window); }
|
||||
|
||||
void doGlfwRoutine() override { glfwPollEvents(); }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
std::shared_ptr<GlfwManagerImpl> aGlfwManager =
|
||||
std::make_shared<GlfwManagerImpl>();
|
||||
|
||||
std::string title;
|
||||
|
||||
{
|
||||
std::stringstream accumulator;
|
||||
accumulator << progressia::main::meta::NAME << " "
|
||||
<< progressia::main::meta::VERSION << " build "
|
||||
<< progressia::main::meta::BUILD_ID;
|
||||
title = accumulator.str();
|
||||
}
|
||||
|
||||
constexpr auto windowDimensions = 800;
|
||||
window = glfwCreateWindow(windowDimensions, windowDimensions, title.c_str(),
|
||||
nullptr, nullptr);
|
||||
|
||||
glfwSetWindowSizeCallback(window, onWindowGeometryChange);
|
||||
|
||||
debug("GLFW init complete");
|
||||
theGlfwManager = aGlfwManager;
|
||||
return aGlfwManager;
|
||||
}
|
||||
|
||||
void showWindow() {
|
||||
glfwShowWindow(window);
|
||||
debug("Window now visible");
|
||||
}
|
||||
|
||||
bool shouldRun() { return !glfwWindowShouldClose(window); }
|
||||
|
||||
void doGlfwRoutine() { glfwPollEvents(); }
|
||||
|
||||
void shutdownGlfw() { glfwTerminate(); }
|
||||
|
||||
void onGlfwError(int errorCode, const char *description) {
|
||||
fatal() << "[GLFW] " << description << " (" << errorCode << ")";
|
||||
// REPORT_ERROR
|
||||
@ -71,13 +105,25 @@ void onGlfwError(int errorCode, const char *description) {
|
||||
|
||||
void onWindowGeometryChange(GLFWwindow *window, [[maybe_unused]] int width,
|
||||
[[maybe_unused]] int height) {
|
||||
if (window != progressia::desktop::window) {
|
||||
if (auto manager = theGlfwManager.lock()) {
|
||||
if (manager->window != window) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (manager->onScreenResize != nullptr) {
|
||||
manager->onScreenResize();
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
resizeVulkanSurface();
|
||||
}
|
||||
|
||||
GLFWwindow *getGLFWWindowHandle() { return window; }
|
||||
GLFWwindow *getGLFWWindowHandle() {
|
||||
if (auto manager = theGlfwManager.lock()) {
|
||||
return manager->window;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace progressia::desktop
|
||||
|
@ -1,11 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace progressia::desktop {
|
||||
|
||||
void initializeGlfw();
|
||||
void showWindow();
|
||||
void shutdownGlfw();
|
||||
bool shouldRun();
|
||||
void doGlfwRoutine();
|
||||
class GlfwManager {
|
||||
|
||||
public:
|
||||
virtual ~GlfwManager(){};
|
||||
|
||||
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
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
namespace progressia::desktop {
|
||||
|
||||
// TODO refactor into OOP
|
||||
GLFWwindow *getGLFWWindowHandle();
|
||||
|
||||
} // namespace progressia::desktop
|
||||
|
@ -20,9 +20,7 @@ Image::Image(VkImage vk, VkImageView view, VkFormat format)
|
||||
// do nothing
|
||||
}
|
||||
|
||||
Image::~Image() {
|
||||
// do nothing
|
||||
}
|
||||
Image::~Image() = default;
|
||||
|
||||
/*
|
||||
* ManagedImage
|
||||
@ -33,7 +31,7 @@ ManagedImage::ManagedImage(std::size_t width, std::size_t height,
|
||||
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} {
|
||||
|
||||
@ -146,7 +144,8 @@ Texture::Texture(const progressia::main::Image &src, Vulkan &vulkan)
|
||||
ManagedImage(src.width, src.height, VK_FORMAT_R8G8B8A8_SRGB,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
vulkan) {
|
||||
vulkan),
|
||||
sampler() {
|
||||
|
||||
/*
|
||||
* Create a staging buffer
|
||||
@ -211,9 +210,9 @@ Texture::Texture(const progressia::main::Image &src, Vulkan &vulkan)
|
||||
samplerInfo.compareEnable = VK_FALSE;
|
||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
samplerInfo.mipLodBias = 0.0f;
|
||||
samplerInfo.minLod = 0.0f;
|
||||
samplerInfo.maxLod = 0.0f;
|
||||
samplerInfo.mipLodBias = 0.0F;
|
||||
samplerInfo.minLod = 0.0F;
|
||||
samplerInfo.maxLod = 0.0F;
|
||||
|
||||
vulkan.handleVkResult(
|
||||
"Could not create texture sampler",
|
||||
@ -223,6 +222,7 @@ Texture::Texture(const progressia::main::Image &src, Vulkan &vulkan)
|
||||
* Create descriptor set
|
||||
*/
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer): sampler must be set using vkCreateSampler first
|
||||
descriptorSet = vulkan.getTextureDescriptors().addTexture(view, sampler);
|
||||
}
|
||||
|
||||
@ -233,8 +233,8 @@ Texture::~Texture() {
|
||||
|
||||
void Texture::bind() {
|
||||
// REPORT_ERROR if getCurrentFrame() == nullptr
|
||||
auto commandBuffer = vulkan.getCurrentFrame()->getCommandBuffer();
|
||||
auto pipelineLayout = vulkan.getPipeline().getLayout();
|
||||
auto *commandBuffer = vulkan.getCurrentFrame()->getCommandBuffer();
|
||||
auto *pipelineLayout = vulkan.getPipeline().getLayout();
|
||||
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipelineLayout,
|
||||
|
@ -35,8 +35,9 @@ class ManagedImage : public Image {
|
||||
State state;
|
||||
|
||||
public:
|
||||
ManagedImage(std::size_t width, std::size_t height, VkFormat,
|
||||
VkImageAspectFlags, VkImageUsageFlags, Vulkan &);
|
||||
ManagedImage(std::size_t width, std::size_t height, VkFormat format,
|
||||
VkImageAspectFlags aspect, VkImageUsageFlags usage,
|
||||
Vulkan &vulkan);
|
||||
~ManagedImage();
|
||||
|
||||
void transition(State);
|
||||
@ -48,7 +49,7 @@ class Texture : public ManagedImage {
|
||||
VkSampler sampler;
|
||||
VkDescriptorSet descriptorSet;
|
||||
|
||||
Texture(const progressia::main::Image &, Vulkan &vulkan);
|
||||
Texture(const main::Image &src, Vulkan &vulkan);
|
||||
~Texture();
|
||||
|
||||
void bind();
|
||||
|
@ -8,25 +8,25 @@ using namespace progressia::main::logging;
|
||||
|
||||
namespace progressia::desktop {
|
||||
|
||||
Vulkan *vulkan;
|
||||
|
||||
void initializeVulkan() {
|
||||
VulkanManager::VulkanManager() {
|
||||
debug("Vulkan initializing");
|
||||
|
||||
// Instance extensions
|
||||
|
||||
std::vector<const char *> instanceExtensions;
|
||||
{
|
||||
uint32_t glfwExtensionCount;
|
||||
const char **glfwExtensions;
|
||||
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||
uint32_t glfwExtensionCount = 0;
|
||||
const char **glfwExtensions =
|
||||
glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||
|
||||
instanceExtensions.reserve(instanceExtensions.size() +
|
||||
glfwExtensionCount);
|
||||
for (std::size_t i = 0; i < glfwExtensionCount; i++) {
|
||||
instanceExtensions.push_back(glfwExtensions[i]);
|
||||
instanceExtensions.emplace_back(glfwExtensions[i]);
|
||||
}
|
||||
|
||||
#ifdef VULKAN_ERROR_CHECKING
|
||||
instanceExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
instanceExtensions.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -42,28 +42,21 @@ void initializeVulkan() {
|
||||
#endif
|
||||
};
|
||||
|
||||
vulkan = new Vulkan(instanceExtensions, deviceExtensions, validationLayers);
|
||||
vulkan = std::make_unique<Vulkan>(instanceExtensions, deviceExtensions,
|
||||
validationLayers);
|
||||
|
||||
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() {
|
||||
debug("Vulkan terminating");
|
||||
|
||||
if (vulkan != nullptr) {
|
||||
delete vulkan;
|
||||
vulkan = nullptr;
|
||||
}
|
||||
|
||||
debug("Vulkan terminated");
|
||||
}
|
||||
void VulkanManager::resizeSurface() { vulkan->getSwapChain().recreate(); }
|
||||
|
||||
} // namespace progressia::desktop
|
||||
|
@ -4,18 +4,25 @@
|
||||
|
||||
namespace progressia::desktop {
|
||||
|
||||
void initializeVulkan();
|
||||
class VulkanManager {
|
||||
|
||||
Vulkan *getVulkan();
|
||||
private:
|
||||
std::unique_ptr<Vulkan> vulkan;
|
||||
|
||||
void resizeVulkanSurface();
|
||||
public:
|
||||
VulkanManager();
|
||||
~VulkanManager();
|
||||
|
||||
/*
|
||||
* Returns false when the frame should be skipped
|
||||
*/
|
||||
bool startRender();
|
||||
void endRender();
|
||||
Vulkan *getVulkan();
|
||||
const Vulkan *getVulkan() const;
|
||||
|
||||
void shutdownVulkan();
|
||||
void resizeSurface();
|
||||
|
||||
/*
|
||||
* Returns false when the frame should be skipped
|
||||
*/
|
||||
bool startRender();
|
||||
void endRender();
|
||||
};
|
||||
|
||||
} // namespace progressia::desktop
|
||||
|
@ -13,7 +13,6 @@ int main(int argc, char *argv[]) {
|
||||
using namespace progressia;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): infeasible to avoid in C++17
|
||||
char *arg = argv[i];
|
||||
if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
|
||||
std::cout << main::meta::NAME << " " << main::meta::VERSION << "+"
|
||||
@ -28,30 +27,29 @@ int main(int argc, char *argv[]) {
|
||||
<< main::meta::VERSION_NUMBER << ")";
|
||||
debug("Debug is enabled");
|
||||
|
||||
desktop::initializeGlfw();
|
||||
desktop::initializeVulkan();
|
||||
desktop::showWindow();
|
||||
auto glfwManager = desktop::makeGlfwManager();
|
||||
desktop::VulkanManager vulkanManager;
|
||||
glfwManager->setOnScreenResize([&]() { vulkanManager.resizeSurface(); });
|
||||
glfwManager->showWindow();
|
||||
|
||||
main::initialize(desktop::getVulkan()->getGint());
|
||||
main::initialize(vulkanManager.getVulkan()->getGint());
|
||||
|
||||
info("Loading complete");
|
||||
while (desktop::shouldRun()) {
|
||||
bool abortFrame = !desktop::startRender();
|
||||
while (glfwManager->shouldRun()) {
|
||||
bool abortFrame = !vulkanManager.startRender();
|
||||
if (abortFrame) {
|
||||
continue;
|
||||
}
|
||||
|
||||
main::renderTick();
|
||||
|
||||
desktop::endRender();
|
||||
desktop::doGlfwRoutine();
|
||||
vulkanManager.endRender();
|
||||
glfwManager->doGlfwRoutine();
|
||||
}
|
||||
info("Shutting down");
|
||||
|
||||
desktop::getVulkan()->waitIdle();
|
||||
vulkanManager.getVulkan()->waitIdle();
|
||||
main::shutdown();
|
||||
desktop::shutdownVulkan();
|
||||
desktop::shutdownGlfw();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
12
main/util.h
12
main/util.h
@ -29,6 +29,18 @@
|
||||
}
|
||||
// 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 {
|
||||
|
||||
struct NonCopyable {
|
||||
|
@ -13,7 +13,8 @@ Checks: "-*,\
|
||||
-*-avoid-c-arrays,\
|
||||
-readability-else-after-return,\
|
||||
-readability-named-parameter,\
|
||||
-readability-use-anyofallof"
|
||||
-readability-use-anyofallof,\
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic"
|
||||
|
||||
# modernize-use-trailing-return-type
|
||||
# ignore reason: reduces readability
|
||||
@ -43,3 +44,6 @@ Checks: "-*,\
|
||||
# readability-use-anyofallof
|
||||
# ignore reason: these relatively obscure functions reduce readability by
|
||||
# increasing code complexity and verbosity
|
||||
|
||||
# cppcoreguidelines-pro-bounds-pointer-arithmetic
|
||||
# ignore reason: infeasible to avoid in C++17
|
||||
|
Loading…
x
Reference in New Issue
Block a user