Squash improve-ide-compat into main

Fixes GH-5

- cppcheck replaced with clang-tidy
- clang-tidy lint warnings fixed
- Reworked build tools from scratch to make IDE setup easier
- Added 1.5 IDE setup guides
This commit is contained in:
2023-11-10 21:30:55 +01:00
parent 189d19fd4a
commit ae4e265a90
66 changed files with 2017 additions and 1498 deletions

View File

@@ -8,59 +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 {
namespace desktop {
static GLFWwindow *window = nullptr;
namespace progressia::desktop {
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();
}
window = glfwCreateWindow(800, 800, 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
@@ -69,14 +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;
}
} // namespace desktop
} // namespace progressia
return nullptr;
}
} // namespace progressia::desktop

View File

@@ -1,13 +1,22 @@
#pragma once
namespace progressia {
namespace desktop {
#include <functional>
#include <memory>
void initializeGlfw();
void showWindow();
void shutdownGlfw();
bool shouldRun();
void doGlfwRoutine();
namespace progressia::desktop {
} // namespace desktop
} // namespace progressia
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

View File

@@ -5,10 +5,9 @@
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
namespace progressia {
namespace desktop {
namespace progressia::desktop {
// TODO refactor into OOP
GLFWwindow *getGLFWWindowHandle();
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -2,6 +2,7 @@
#include "vulkan_common.h"
#include <array>
#include <cstddef>
#include <fstream>
#include <memory>
@@ -25,8 +26,7 @@
#include <embedded_resources.h>
namespace progressia {
namespace desktop {
namespace progressia::desktop {
using progressia::main::Vertex;
@@ -50,7 +50,7 @@ auto getVertexFieldProperties() {
namespace {
std::vector<char> tmp_readFile(const std::string &path) {
auto resource = __embedded_resources::getEmbeddedResource(path.c_str());
auto resource = __embedded_resources::getEmbeddedResource(path);
if (resource.data == nullptr) {
// REPORT_ERROR
@@ -59,7 +59,7 @@ std::vector<char> tmp_readFile(const std::string &path) {
exit(1);
}
return std::vector<char>(resource.data, resource.data + resource.length);
return {resource.data, resource.data + resource.length};
}
} // namespace
@@ -82,25 +82,26 @@ Adapter::Adapter(Vulkan &vulkan)
VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_DONT_CARE,
{1.0f, 0},
{1.0F, 0},
nullptr});
}
Adapter::~Adapter() {
// Do nothing
}
Adapter::~Adapter() = default;
std::vector<Attachment> &Adapter::getAttachments() { return attachments; }
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
std::vector<char> Adapter::loadVertexShader() {
return tmp_readFile("shader.vert.spv");
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
std::vector<char> Adapter::loadFragmentShader() {
return tmp_readFile("shader.frag.spv");
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
VkVertexInputBindingDescription Adapter::getVertexInputBindingDescription() {
VkVertexInputBindingDescription bindingDescription{};
bindingDescription.binding = 0;
@@ -111,6 +112,7 @@ VkVertexInputBindingDescription Adapter::getVertexInputBindingDescription() {
}
std::vector<VkVertexInputAttributeDescription>
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
Adapter::getVertexInputAttributeDescriptions() {
std::vector<VkVertexInputAttributeDescription> attributeDescriptions;
@@ -151,8 +153,8 @@ void Adapter::onPreFrame() {
* graphics_interface implementation
*/
} // namespace desktop
namespace main {
} // namespace progressia::desktop
namespace progressia::main {
using namespace progressia::desktop;
@@ -163,122 +165,125 @@ struct DrawRequest {
glm::mat4 modelTransform;
};
// NOLINTNEXTLINE: TODO
std::vector<DrawRequest> pendingDrawCommands;
constexpr std::size_t PENDING_DRAW_COMMANDS_MAX_SIZE = 100000;
// NOLINTNEXTLINE: TODO
glm::mat4 currentModelTransform;
} // namespace
progressia::main::Texture::Texture(Backend backend) : backend(backend) {}
struct progressia::main::Texture::Backend {
progressia::desktop::Texture texture;
};
progressia::main::Texture::~Texture() {
delete static_cast<progressia::desktop::Texture *>(this->backend);
}
progressia::main::Texture::Texture(std::unique_ptr<Backend> backend)
: backend(std::move(backend)) {}
namespace {
struct PrimitiveBackend {
progressia::main::Texture::~Texture() = default;
struct Primitive::Backend {
IndexedBuffer<Vertex> buf;
progressia::main::Texture *tex;
};
} // namespace
Primitive::Primitive(Backend backend) : backend(backend) {}
Primitive::Primitive(std::unique_ptr<Backend> backend)
: backend(std::move(backend)) {}
Primitive::~Primitive() {
delete static_cast<PrimitiveBackend *>(this->backend);
}
Primitive::~Primitive() = default;
void Primitive::draw() {
auto backend = static_cast<PrimitiveBackend *>(this->backend);
if (pendingDrawCommands.size() > 100000) {
if (pendingDrawCommands.size() > PENDING_DRAW_COMMANDS_MAX_SIZE) {
backend->buf.getVulkan().getGint().flush();
}
pendingDrawCommands.push_back(
{static_cast<progressia::desktop::Texture *>(backend->tex->backend),
&backend->buf, currentModelTransform});
pendingDrawCommands.push_back({&backend->tex->backend->texture,
&backend->buf, currentModelTransform});
}
const progressia::main::Texture *Primitive::getTexture() const {
return static_cast<PrimitiveBackend *>(this->backend)->tex;
return backend->tex;
}
View::View(Backend backend) : backend(backend) {}
struct View::Backend {
Adapter::ViewUniform::State state;
};
View::~View() {
delete static_cast<Adapter::ViewUniform::State *>(this->backend);
}
View::View(std::unique_ptr<Backend> backend) : backend(std::move(backend)) {}
View::~View() = default;
void View::configure(const glm::mat4 &proj, const glm::mat4 &view) {
static_cast<Adapter::ViewUniform::State *>(this->backend)
->update(proj, view);
backend->state.update(proj, view);
}
void View::use() {
auto backend = static_cast<Adapter::ViewUniform::State *>(this->backend);
backend->uniform->getVulkan().getGint().flush();
backend->bind();
backend->state.uniform->getVulkan().getGint().flush();
backend->state.bind();
}
Light::Light(Backend backend) : backend(backend) {}
struct Light::Backend {
Adapter::LightUniform::State state;
};
Light::~Light() {
delete static_cast<Adapter::LightUniform::State *>(this->backend);
}
Light::Light(std::unique_ptr<Backend> backend) : backend(std::move(backend)) {}
Light::~Light() = default;
void Light::configure(const glm::vec3 &color, const glm::vec3 &from,
float contrast, float softness) {
static_cast<Adapter::LightUniform::State *>(this->backend)
->update(Adapter::Light{glm::vec4(color, 1.0f),
glm::vec4(glm::normalize(from), 1.0f), contrast,
softness});
backend->state.update(Adapter::Light{glm::vec4(color, 1.0F),
glm::vec4(glm::normalize(from), 1.0F),
contrast, softness});
}
void Light::use() {
auto backend = static_cast<Adapter::LightUniform::State *>(this->backend);
backend->uniform->getVulkan().getGint().flush();
backend->bind();
backend->state.uniform->getVulkan().getGint().flush();
backend->state.bind();
}
GraphicsInterface::GraphicsInterface(Backend backend) : backend(backend) {}
GraphicsInterface::~GraphicsInterface() {
// Do nothing
}
GraphicsInterface::~GraphicsInterface() = default;
progressia::main::Texture *
std::unique_ptr<progressia::main::Texture>
GraphicsInterface::newTexture(const progressia::main::Image &src) {
auto backend = new progressia::desktop::Texture(
src, *static_cast<Vulkan *>(this->backend));
using Backend = progressia::main::Texture::Backend;
return new Texture(backend);
return std::make_unique<progressia::main::Texture>(
std::unique_ptr<Backend>(new Backend{progressia::desktop::Texture(
src, *static_cast<Vulkan *>(this->backend))}));
}
Primitive *
std::unique_ptr<Primitive>
GraphicsInterface::newPrimitive(const std::vector<Vertex> &vertices,
const std::vector<Vertex::Index> &indices,
progressia::main::Texture *texture) {
auto backend = new PrimitiveBackend{
IndexedBuffer<Vertex>(vertices.size(), indices.size(),
*static_cast<Vulkan *>(this->backend)),
texture};
auto primitive = std::make_unique<Primitive>(
std::unique_ptr<Primitive::Backend>(new Primitive::Backend{
IndexedBuffer<Vertex>(vertices.size(), indices.size(),
*static_cast<Vulkan *>(this->backend)),
texture}));
backend->buf.load(vertices.data(), indices.data());
primitive->backend->buf.load(vertices.data(), indices.data());
return new Primitive(backend);
return primitive;
}
View *GraphicsInterface::newView() {
return new View(new Adapter::ViewUniform::State(
static_cast<Vulkan *>(this->backend)->getAdapter().createView()));
std::unique_ptr<View> GraphicsInterface::newView() {
return std::make_unique<View>(std::unique_ptr<View::Backend>(
new View::Backend{Adapter::ViewUniform::State(
static_cast<Vulkan *>(this->backend)->getAdapter().createView())}));
}
Light *GraphicsInterface::newLight() {
return new Light(new Adapter::LightUniform::State(
static_cast<Vulkan *>(this->backend)->getAdapter().createLight()));
std::unique_ptr<Light> GraphicsInterface::newLight() {
return std::make_unique<Light>(
std::unique_ptr<Light::Backend>(new Light::Backend{
Adapter::LightUniform::State(static_cast<Vulkan *>(this->backend)
->getAdapter()
.createLight())}));
}
glm::vec2 GraphicsInterface::getViewport() const {
@@ -287,16 +292,17 @@ glm::vec2 GraphicsInterface::getViewport() const {
return {extent.width, extent.height};
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
void GraphicsInterface::setModelTransform(const glm::mat4 &m) {
currentModelTransform = m;
}
void GraphicsInterface::flush() {
auto commandBuffer = static_cast<Vulkan *>(this->backend)
->getCurrentFrame()
->getCommandBuffer();
auto pipelineLayout =
auto *commandBuffer = static_cast<Vulkan *>(this->backend)
->getCurrentFrame()
->getCommandBuffer();
auto *pipelineLayout =
static_cast<Vulkan *>(this->backend)->getPipeline().getLayout();
progressia::desktop::Texture *lastTexture = nullptr;
@@ -328,11 +334,11 @@ void GraphicsInterface::flush() {
pendingDrawCommands.clear();
}
// NOLINTNEXTLINE: TODO
float GraphicsInterface::tmp_getTime() { return glfwGetTime(); }
uint64_t GraphicsInterface::getLastStartedFrame() {
return static_cast<Vulkan *>(this->backend)->getLastStartedFrame();
}
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -1,13 +1,11 @@
#pragma once
#include "boost/core/noncopyable.hpp"
#include "vulkan_common.h"
#include "vulkan_descriptor_set.h"
#include "vulkan_image.h"
#include "vulkan_uniform.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class Attachment {
public:
@@ -68,5 +66,4 @@ class Adapter : public VkObjectWrapper {
void onPreFrame();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,12 +1,10 @@
#pragma once
#include <boost/core/noncopyable.hpp>
#include <vector>
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
/*
* A single buffer with a chunk of allocated memory.
@@ -192,5 +190,4 @@ class IndexedBufferBase : public VkObjectWrapper {
template <typename Vertex>
using IndexedBuffer = IndexedBufferBase<Vertex, uint16_t, VK_INDEX_TYPE_UINT16>;
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,8 +1,8 @@
#include "vulkan_common.h"
#include "../config.h"
#include "vulkan_adapter.h"
#include "vulkan_frame.h"
#include "vulkan_physical_device.h"
#include "vulkan_pick_device.h"
#include "vulkan_pipeline.h"
#include "vulkan_render_pass.h"
@@ -15,8 +15,7 @@
using namespace progressia::main::logging;
namespace progressia {
namespace desktop {
namespace progressia::desktop {
/*
* Vulkan
@@ -27,7 +26,7 @@ Vulkan::Vulkan(std::vector<const char *> instanceExtensions,
std::vector<const char *> validationLayers)
:
frames(MAX_FRAMES_IN_FLIGHT), isRenderingFrame(false),
frames(MAX_FRAMES_IN_FLIGHT), currentFrame(0), isRenderingFrame(false),
lastStartedFrame(0) {
/*
@@ -58,7 +57,7 @@ Vulkan::Vulkan(std::vector<const char *> instanceExtensions,
// Enable extensions
{
uint32_t extensionCount;
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount,
nullptr);
std::vector<VkExtensionProperties> available(extensionCount);
@@ -89,7 +88,7 @@ Vulkan::Vulkan(std::vector<const char *> instanceExtensions,
// Enable validation layers
{
uint32_t layerCount;
uint32_t layerCount = 0;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> available(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, available.data());
@@ -150,31 +149,25 @@ Vulkan::Vulkan(std::vector<const char *> instanceExtensions,
exit(1);
}
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
std::vector<VkPhysicalDevice> vkDevices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, vkDevices.data());
std::vector<PhysicalDeviceData> choices;
for (const auto &device : devices) {
PhysicalDeviceData data = {};
data.device = device;
vkGetPhysicalDeviceProperties(device, &data.properties);
vkGetPhysicalDeviceFeatures(device, &data.features);
choices.push_back(data);
std::vector<PhysicalDevice> choices;
choices.reserve(deviceCount);
for (const auto &vkDevice : vkDevices) {
choices.emplace_back(PhysicalDevice(vkDevice));
}
const auto &result =
pickPhysicalDevice(choices, *this, deviceExtensions);
physicalDevice = result.device;
physicalDevice = std::make_unique<PhysicalDevice>(result);
}
/*
* Setup queues
*/
queues = std::make_unique<Queues>(physicalDevice, *this);
queues = std::make_unique<Queues>(physicalDevice->getVk(), *this);
/*
* Create logical device
@@ -207,9 +200,9 @@ Vulkan::Vulkan(std::vector<const char *> instanceExtensions,
// Create logical device
handleVkResult(
"Could not create logical device",
vkCreateDevice(physicalDevice, &createInfo, nullptr, &device));
handleVkResult("Could not create logical device",
vkCreateDevice(physicalDevice->getVk(), &createInfo,
nullptr, &device));
// Store queue handles
@@ -259,7 +252,6 @@ Vulkan::Vulkan(std::vector<const char *> instanceExtensions,
for (auto &container : frames) {
container.emplace(*this);
}
currentFrame = 0;
gint = std::make_unique<progressia::main::GraphicsInterface>(this);
}
@@ -275,13 +267,16 @@ Vulkan::~Vulkan() {
commandPool.reset();
vkDestroyDevice(device, nullptr);
surface.reset();
physicalDevice.reset();
errorHandler.reset();
vkDestroyInstance(instance, nullptr);
}
VkInstance Vulkan::getInstance() const { return instance; }
VkPhysicalDevice Vulkan::getPhysicalDevice() const { return physicalDevice; }
const PhysicalDevice &Vulkan::getPhysicalDevice() const {
return *physicalDevice;
}
VkDevice Vulkan::getDevice() const { return device; }
@@ -333,7 +328,8 @@ VkFormat Vulkan::findSupportedFormat(const std::vector<VkFormat> &candidates,
for (VkFormat format : candidates) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);
vkGetPhysicalDeviceFormatProperties(physicalDevice->getVk(), format,
&props);
if (tiling == VK_IMAGE_TILING_LINEAR &&
(props.linearTilingFeatures & features) == features) {
@@ -351,8 +347,7 @@ VkFormat Vulkan::findSupportedFormat(const std::vector<VkFormat> &candidates,
uint32_t Vulkan::findMemoryType(uint32_t allowedByDevice,
VkMemoryPropertyFlags desiredProperties) {
VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
auto memProperties = physicalDevice->getMemory();
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
if (((1 << i) & allowedByDevice) == 0) {
@@ -383,9 +378,9 @@ Frame *Vulkan::getCurrentFrame() {
return nullptr;
}
uint64_t Vulkan::getLastStartedFrame() { return lastStartedFrame; }
uint64_t Vulkan::getLastStartedFrame() const { return lastStartedFrame; }
std::size_t Vulkan::getFrameInFlightIndex() { return currentFrame; }
std::size_t Vulkan::getFrameInFlightIndex() const { return currentFrame; }
bool Vulkan::startRender() {
if (currentFrame >= MAX_FRAMES_IN_FLIGHT - 1) {
@@ -421,16 +416,21 @@ void Vulkan::waitIdle() {
* VulkanErrorHandler
*/
VulkanErrorHandler::VulkanErrorHandler(Vulkan &vulkan) : vulkan(vulkan) {
VulkanErrorHandler::VulkanErrorHandler(Vulkan &vulkan)
: debugMessenger(nullptr), vulkan(vulkan) {
// do nothing
}
VulkanErrorHandler::~VulkanErrorHandler() {
#ifdef VULKAN_ERROR_CHECKING
vulkan.callVoid("vkDestroyDebugUtilsMessengerEXT",
(VkDebugUtilsMessengerEXT)debugMessenger, nullptr);
#endif
VulkanErrorHandler::~VulkanErrorHandler() {
if (debugMessenger != nullptr) {
vulkan.callVoid("vkDestroyDebugUtilsMessengerEXT",
(VkDebugUtilsMessengerEXT)debugMessenger, nullptr);
}
}
#else
VulkanErrorHandler::~VulkanErrorHandler() = default;
#endif
#ifdef VULKAN_ERROR_CHECKING
namespace {
@@ -445,7 +445,8 @@ debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
return VK_FALSE;
}
[[maybe_unused]] auto &vk = *reinterpret_cast<const Vulkan *>(pUserData);
[[maybe_unused]] const auto &vk =
*reinterpret_cast<const Vulkan *>(pUserData);
const char *severityStr =
messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
@@ -456,7 +457,7 @@ debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
? "info"
: "verbose";
const char *typeStr;
const char *typeStr = "";
switch (messageType) {
case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT:
typeStr = "general";
@@ -513,8 +514,9 @@ VulkanErrorHandler::attachDebugProbe(VkInstanceCreateInfo &createInfo) {
#else
(void)createInfo;
return std::unique_ptr<VkDebugUtilsMessengerCreateInfoEXT>();
(void)createInfo; // unused argument
(void)this; // not static
return {};
#endif
}
@@ -533,6 +535,7 @@ void VulkanErrorHandler::onInstanceReady() {
#endif
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
void VulkanErrorHandler::handleVkResult(const char *errorMessage,
VkResult result) {
if (result == VK_SUCCESS) {
@@ -548,7 +551,7 @@ void VulkanErrorHandler::handleVkResult(const char *errorMessage,
* Surface
*/
Surface::Surface(Vulkan &vulkan) : vulkan(vulkan) {
Surface::Surface(Vulkan &vulkan) : vk(), vulkan(vulkan) {
vulkan.handleVkResult("Could not create window surface (what?)",
glfwCreateWindowSurface(vulkan.getInstance(),
getGLFWWindowHandle(),
@@ -563,7 +566,7 @@ VkSurfaceKHR Surface::getVk() { return vk; }
* Queue
*/
Queue::Queue(Test test) : test(test) {
Queue::Queue(Test test) : test(std::move(test)), vk() {
// do nothing
}
@@ -619,7 +622,7 @@ Queues::Queues(VkPhysicalDevice physicalDevice, Vulkan &vulkan)
for (std::size_t index = 0; index < queueFamilyCount; index++) {
for (auto queue : {&graphicsQueue, &presentQueue}) {
for (auto *queue : {&graphicsQueue, &presentQueue}) {
if (!queue->isSuitable(physicalDevice, index, vulkan,
properties[index])) {
continue;
@@ -634,12 +637,10 @@ Queues::Queues(VkPhysicalDevice physicalDevice, Vulkan &vulkan)
}
}
Queues::~Queues() {
// do nothing
}
Queues::~Queues() = default;
void Queues::storeHandles(VkDevice device) {
for (auto queue : {&graphicsQueue, &presentQueue}) {
for (auto *queue : {&graphicsQueue, &presentQueue}) {
vkGetDeviceQueue(device, queue->getFamilyIndex(), 0, &queue->vk);
}
}
@@ -648,7 +649,7 @@ std::unique_ptr<Queues::CreationRequest>
Queues::requestCreation(VkDeviceCreateInfo &createInfo) const {
std::unique_ptr result = std::make_unique<CreationRequest>();
result->priority = 1.0f;
result->priority = 1.0F;
std::unordered_set<uint32_t> uniqueQueues;
for (const auto *queue : {&graphicsQueue, &presentQueue}) {
@@ -673,7 +674,7 @@ Queues::requestCreation(VkDeviceCreateInfo &createInfo) const {
}
bool Queues::isComplete() const {
for (auto queue : {&graphicsQueue, &presentQueue}) {
for (const auto *queue : {&graphicsQueue, &presentQueue}) {
if (!queue->familyIndex.has_value()) {
return false;
}
@@ -691,7 +692,7 @@ const Queue &Queues::getPresentQueue() const { return presentQueue; }
*/
CommandPool::CommandPool(Vulkan &vulkan, const Queue &queue)
: queue(queue), vulkan(vulkan) {
: pool(), queue(queue), vulkan(vulkan) {
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
@@ -714,12 +715,13 @@ VkCommandBuffer CommandPool::allocateCommandBuffer() {
allocInfo.commandPool = pool;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
auto *commandBuffer = VkCommandBuffer();
vkAllocateCommandBuffers(vulkan.getDevice(), &allocInfo, &commandBuffer);
return commandBuffer;
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
void CommandPool::beginCommandBuffer(VkCommandBuffer commandBuffer,
VkCommandBufferUsageFlags usage) {
VkCommandBufferBeginInfo beginInfo{};
@@ -773,5 +775,4 @@ void CommandPool::freeMultiUse(VkCommandBuffer buffer) {
vkFreeCommandBuffers(vulkan.getDevice(), pool, 1, &buffer);
}
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -17,13 +17,12 @@
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <boost/core/noncopyable.hpp>
#include "../../main/util.h"
#include "../../main/logging.h"
#include "../../main/rendering/graphics_interface.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
namespace CstrUtils {
struct CstrHash {
@@ -54,13 +53,14 @@ struct CstrCompare {
using CstrHashSet = std::unordered_set<const char *, CstrHash, CstrEqual>;
} // namespace CstrUtils
class VkObjectWrapper : private boost::noncopyable {
class VkObjectWrapper : private progressia::main::NonCopyable {
// empty
};
constexpr std::size_t MAX_FRAMES_IN_FLIGHT = 2;
class VulkanErrorHandler;
class PhysicalDevice;
class Surface;
class Queue;
class Queues;
@@ -75,10 +75,10 @@ class Frame;
class Vulkan : public VkObjectWrapper {
private:
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE;
std::unique_ptr<VulkanErrorHandler> errorHandler;
std::unique_ptr<PhysicalDevice> physicalDevice;
std::unique_ptr<Surface> surface;
std::unique_ptr<Queues> queues;
std::unique_ptr<CommandPool> commandPool;
@@ -103,9 +103,9 @@ class Vulkan : public VkObjectWrapper {
~Vulkan();
VkInstance getInstance() const;
VkPhysicalDevice getPhysicalDevice() const;
VkDevice getDevice() const;
const PhysicalDevice &getPhysicalDevice() const;
Surface &getSurface();
const Surface &getSurface() const;
Queues &getQueues();
@@ -135,8 +135,8 @@ class Vulkan : public VkObjectWrapper {
bool startRender();
void endRender();
uint64_t getLastStartedFrame();
std::size_t getFrameInFlightIndex();
uint64_t getLastStartedFrame() const;
std::size_t getFrameInFlightIndex() const;
void waitIdle();
@@ -192,12 +192,13 @@ class VulkanErrorHandler : public VkObjectWrapper {
Vulkan &vulkan;
public:
VulkanErrorHandler(Vulkan &);
VulkanErrorHandler(Vulkan &vulkan);
std::unique_ptr<VkDebugUtilsMessengerCreateInfoEXT>
attachDebugProbe(VkInstanceCreateInfo &);
void onInstanceReady();
// NOLINTNEXTLINE(performance-trivially-destructible): fixing this makes code less readable due to use of macros in implementation
~VulkanErrorHandler();
void handleVkResult(const char *errorMessage, VkResult result);
@@ -209,7 +210,7 @@ class Surface : public VkObjectWrapper {
Vulkan &vulkan;
public:
Surface(Vulkan &);
Surface(Vulkan &vulkan);
~Surface();
VkSurfaceKHR getVk();
@@ -226,7 +227,7 @@ class Queue {
friend class Queues;
Queue(Test);
Queue(Test test);
public:
bool isSuitable(VkPhysicalDevice, uint32_t familyIndex, Vulkan &,
@@ -275,7 +276,7 @@ class CommandPool : public VkObjectWrapper {
VkCommandBufferUsageFlags usage);
public:
CommandPool(Vulkan &, const Queue &);
CommandPool(Vulkan &vulkan, const Queue &queue);
~CommandPool();
VkCommandBuffer beginSingleUse();
@@ -287,5 +288,4 @@ class CommandPool : public VkObjectWrapper {
void freeMultiUse(VkCommandBuffer);
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,11 +1,10 @@
#include "vulkan_descriptor_set.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
DescriptorSetInterface::DescriptorSetInterface(uint32_t setNumber,
Vulkan &vulkan)
: setNumber(setNumber), vulkan(vulkan) {}
: layout(), setNumber(setNumber), vulkan(vulkan) {}
VkDescriptorSetLayout DescriptorSetInterface::getLayout() const {
return layout;
@@ -15,5 +14,4 @@ uint32_t DescriptorSetInterface::getSetNumber() const { return setNumber; }
Vulkan &DescriptorSetInterface::getVulkan() { return vulkan; }
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -2,8 +2,7 @@
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class DescriptorSetInterface : public VkObjectWrapper {
protected:
@@ -19,5 +18,4 @@ class DescriptorSetInterface : public VkObjectWrapper {
Vulkan &getVulkan();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -8,12 +8,11 @@
#include "vulkan_render_pass.h"
#include "vulkan_swap_chain.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
Frame::Frame(Vulkan &vulkan)
: vulkan(vulkan),
commandBuffer(vulkan.getCommandPool().allocateMultiUse()) {
: vulkan(vulkan), commandBuffer(vulkan.getCommandPool().allocateMultiUse()),
imageAvailableSemaphore(), renderFinishedSemaphore(), inFlightFence() {
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@@ -98,12 +97,12 @@ bool Frame::startRender() {
vulkan.getPipeline().getVk());
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.x = 0.0F;
viewport.y = 0.0F;
viewport.width = (float)extent.width;
viewport.height = (float)extent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
viewport.minDepth = 0.0F;
viewport.maxDepth = 1.0F;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor{};
@@ -170,5 +169,4 @@ void Frame::endRender() {
VkCommandBuffer Frame::getCommandBuffer() { return commandBuffer; }
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -2,8 +2,7 @@
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class Frame : public VkObjectWrapper {
private:
@@ -32,5 +31,4 @@ class Frame : public VkObjectWrapper {
VkCommandBuffer getCommandBuffer();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -9,8 +9,7 @@
#include "vulkan_pipeline.h"
#include "vulkan_texture_descriptors.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
/*
* Image
@@ -21,9 +20,7 @@ Image::Image(VkImage vk, VkImageView view, VkFormat format)
// do nothing
}
Image::~Image() {
// do nothing
}
Image::~Image() = default;
/*
* ManagedImage
@@ -34,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} {
@@ -147,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
@@ -212,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",
@@ -224,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);
}
@@ -234,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,
@@ -243,5 +242,4 @@ void Texture::bind() {
&descriptorSet, 0, nullptr);
}
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,6 +1,5 @@
#pragma once
#include <boost/core/noncopyable.hpp>
#include <vector>
#include "vulkan_buffer.h"
@@ -8,8 +7,7 @@
#include "../../main/rendering/image.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class Image : public VkObjectWrapper {
public:
@@ -37,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);
@@ -50,11 +49,10 @@ 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();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,34 +1,32 @@
#include "vulkan_mgmt.h"
#include "../config.h"
#include "vulkan_common.h"
#include "vulkan_swap_chain.h"
#include "../../main/logging.h"
using namespace progressia::main::logging;
namespace progressia {
namespace desktop {
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
}
@@ -44,29 +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");
void VulkanManager::resizeSurface() { vulkan->getSwapChain().recreate(); }
if (vulkan != nullptr) {
delete vulkan;
vulkan = nullptr;
}
debug("Vulkan terminated");
}
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -2,22 +2,27 @@
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
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();
} // namespace desktop
} // namespace progressia
/*
* Returns false when the frame should be skipped
*/
bool startRender();
void endRender();
};
} // namespace progressia::desktop

View File

@@ -0,0 +1,51 @@
#include "vulkan_physical_device.h"
namespace progressia::desktop {
PhysicalDevice::PhysicalDevice(VkPhysicalDevice vk)
: vk(vk), properties(), features(), memory() {
vkGetPhysicalDeviceProperties(vk, &properties);
vkGetPhysicalDeviceFeatures(vk, &features);
vkGetPhysicalDeviceMemoryProperties(vk, &memory);
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
bool PhysicalDevice::isSuitable() const {
// Add feature, limit, etc. checks here.
// Return false and debug() if problems arise.
return true;
}
VkPhysicalDevice PhysicalDevice::getVk() const { return vk; }
const VkPhysicalDeviceProperties &PhysicalDevice::getProperties() const {
return properties;
}
const VkPhysicalDeviceFeatures &PhysicalDevice::getFeatures() const {
return features;
}
const VkPhysicalDeviceLimits &PhysicalDevice::getLimits() const {
return properties.limits;
}
const VkPhysicalDeviceMemoryProperties &PhysicalDevice::getMemory() const {
return memory;
}
VkPhysicalDeviceType PhysicalDevice::getType() const {
return properties.deviceType;
}
const char *PhysicalDevice::getName() const { return properties.deviceName; }
VkDeviceSize PhysicalDevice::getMinUniformOffset() const {
return getLimits().minUniformBufferOffsetAlignment;
}
uint32_t PhysicalDevice::getMaxTextureSize() const {
return getLimits().maxImageDimension2D;
}
} // namespace progressia::desktop

View File

@@ -0,0 +1,33 @@
#pragma once
#include "vulkan_common.h"
namespace progressia::desktop {
class PhysicalDevice {
private:
VkPhysicalDevice vk;
VkPhysicalDeviceProperties properties;
VkPhysicalDeviceFeatures features;
VkPhysicalDeviceMemoryProperties memory;
public:
PhysicalDevice(VkPhysicalDevice vk);
bool isSuitable() const;
VkPhysicalDevice getVk() const;
const VkPhysicalDeviceProperties &getProperties() const;
const VkPhysicalDeviceFeatures &getFeatures() const;
const VkPhysicalDeviceLimits &getLimits() const;
const VkPhysicalDeviceMemoryProperties &getMemory() const;
VkPhysicalDeviceType getType() const;
const char *getName() const;
VkDeviceSize getMinUniformOffset() const;
uint32_t getMaxTextureSize() const;
};
} // namespace progressia::desktop

View File

@@ -4,8 +4,7 @@
#include "vulkan_swap_chain.h"
using namespace progressia::main::logging;
namespace progressia {
namespace desktop {
namespace progressia::desktop {
namespace {
@@ -14,7 +13,7 @@ bool checkDeviceExtensions(VkPhysicalDevice device,
CstrUtils::CstrHashSet toFind(deviceExtensions.cbegin(),
deviceExtensions.cend());
uint32_t extensionCount;
uint32_t extensionCount = 0;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount,
nullptr);
@@ -29,20 +28,24 @@ bool checkDeviceExtensions(VkPhysicalDevice device,
return toFind.empty();
}
bool isDeviceSuitable(const PhysicalDeviceData &data, Vulkan &vulkan,
bool isDeviceSuitable(const PhysicalDevice &data, Vulkan &vulkan,
const std::vector<const char *> &deviceExtensions) {
if (!Queues(data.device, vulkan).isComplete()) {
if (!data.isSuitable()) {
return false;
}
if (!checkDeviceExtensions(data.device, deviceExtensions)) {
if (!Queues(data.getVk(), vulkan).isComplete()) {
return false;
}
if (!checkDeviceExtensions(data.getVk(), deviceExtensions)) {
return false;
}
// Check requires that the swap chain extension is present
if (!SwapChain::isSwapChainSuitable(
SwapChain::querySwapChainSupport(data.device, vulkan))) {
SwapChain::querySwapChainSupport(data.getVk(), vulkan))) {
return false;
}
@@ -51,8 +54,8 @@ bool isDeviceSuitable(const PhysicalDeviceData &data, Vulkan &vulkan,
} // namespace
const PhysicalDeviceData &
pickPhysicalDevice(std::vector<PhysicalDeviceData> &choices, Vulkan &vulkan,
const PhysicalDevice &
pickPhysicalDevice(std::vector<PhysicalDevice> &choices, Vulkan &vulkan,
const std::vector<const char *> &deviceExtensions) {
// Remove unsuitable devices
@@ -82,20 +85,17 @@ pickPhysicalDevice(std::vector<PhysicalDeviceData> &choices, Vulkan &vulkan,
{"Virtual GPU", +1},
{"CPU", -1}};
auto type = option.properties.deviceType;
m << "\n\t- " << opinions[type].description << " "
<< option.properties.deviceName;
auto type = option.getType();
m << "\n\t- " << opinions[type].description << " " << option.getName();
if (opinions[pick->properties.deviceType].value <
opinions[type].value) {
if (opinions[pick->getType()].value < opinions[type].value) {
pick = &option;
}
}
m << "\n";
m << "Picked device " << pick->properties.deviceName;
m << "Picked device " << pick->getName();
return *pick;
}
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,21 +1,14 @@
#pragma once
#include "vulkan_common.h"
#include "vulkan_physical_device.h"
#include <vector>
namespace progressia {
namespace desktop {
namespace progressia::desktop {
struct PhysicalDeviceData {
VkPhysicalDevice device;
VkPhysicalDeviceProperties properties;
VkPhysicalDeviceFeatures features;
};
const PhysicalDeviceData &
pickPhysicalDevice(std::vector<PhysicalDeviceData> &, Vulkan &,
const PhysicalDevice &
pickPhysicalDevice(std::vector<PhysicalDevice> &, Vulkan &,
const std::vector<const char *> &deviceExtensions);
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -5,17 +5,16 @@
#include "vulkan_descriptor_set.h"
#include "vulkan_render_pass.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
Pipeline::Pipeline(Vulkan &vulkan) : vulkan(vulkan) {
Pipeline::Pipeline(Vulkan &vulkan) : layout(), vk(), vulkan(vulkan) {
auto &adapter = vulkan.getAdapter();
// Shaders
auto vertShader = createShaderModule(adapter.loadVertexShader());
auto fragShader = createShaderModule(adapter.loadFragmentShader());
auto *vertShader = createShaderModule(adapter.loadVertexShader());
auto *fragShader = createShaderModule(adapter.loadFragmentShader());
VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
vertShaderStageInfo.sType =
@@ -81,13 +80,13 @@ Pipeline::Pipeline(Vulkan &vulkan) : vulkan(vulkan) {
rasterizer.depthClampEnable = VK_FALSE;
rasterizer.rasterizerDiscardEnable = VK_FALSE;
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1.0f;
rasterizer.lineWidth = 1.0F;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasEnable = VK_FALSE;
rasterizer.depthBiasConstantFactor = 0.0f; // Optional
rasterizer.depthBiasClamp = 0.0f; // Optional
rasterizer.depthBiasSlopeFactor = 0.0f; // Optional
rasterizer.depthBiasConstantFactor = 0.0F; // Optional
rasterizer.depthBiasClamp = 0.0F; // Optional
rasterizer.depthBiasSlopeFactor = 0.0F; // Optional
// Multisampling (disabled)
@@ -96,7 +95,7 @@ Pipeline::Pipeline(Vulkan &vulkan) : vulkan(vulkan) {
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling.sampleShadingEnable = VK_FALSE;
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
multisampling.minSampleShading = 1.0f; // Optional
multisampling.minSampleShading = 1.0F; // Optional
multisampling.pSampleMask = nullptr; // Optional
multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
multisampling.alphaToOneEnable = VK_FALSE; // Optional
@@ -138,10 +137,10 @@ Pipeline::Pipeline(Vulkan &vulkan) : vulkan(vulkan) {
colorBlending.logicOp = VK_LOGIC_OP_COPY; // Optional
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &colorBlendAttachment;
colorBlending.blendConstants[0] = 0.0f; // Optional
colorBlending.blendConstants[1] = 0.0f; // Optional
colorBlending.blendConstants[2] = 0.0f; // Optional
colorBlending.blendConstants[3] = 0.0f; // Optional
colorBlending.blendConstants[0] = 0.0F; // Optional
colorBlending.blendConstants[1] = 0.0F; // Optional
colorBlending.blendConstants[2] = 0.0F; // Optional
colorBlending.blendConstants[3] = 0.0F; // Optional
// Pipeline
@@ -202,7 +201,7 @@ VkShaderModule Pipeline::createShaderModule(const std::vector<char> &bytecode) {
// Important - the buffer must be aligned properly. std::vector does that.
createInfo.pCode = reinterpret_cast<const uint32_t *>(bytecode.data());
VkShaderModule shaderModule;
VkShaderModule shaderModule = nullptr;
vulkan.handleVkResult("Could not load shader",
vkCreateShaderModule(vulkan.getDevice(), &createInfo,
nullptr, &shaderModule));
@@ -219,5 +218,4 @@ VkPipeline Pipeline::getVk() { return vk; }
VkPipelineLayout Pipeline::getLayout() { return layout; }
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -2,8 +2,7 @@
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class Pipeline : public VkObjectWrapper {
@@ -23,5 +22,4 @@ class Pipeline : public VkObjectWrapper {
VkPipelineLayout getLayout();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -3,10 +3,9 @@
#include "vulkan_adapter.h"
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
RenderPass::RenderPass(Vulkan &vulkan) : vulkan(vulkan) {
RenderPass::RenderPass(Vulkan &vulkan) : vk(), vulkan(vulkan) {
std::vector<VkAttachmentDescription> attachmentDescriptions;
std::vector<VkAttachmentReference> attachmentReferences;
@@ -15,8 +14,8 @@ RenderPass::RenderPass(Vulkan &vulkan) : vulkan(vulkan) {
for (std::size_t i = 0; i < attachments.size(); i++) {
const auto &attachment = attachments[i];
VkAttachmentDescription *desc;
VkAttachmentReference *ref;
VkAttachmentDescription *desc = nullptr;
VkAttachmentReference *ref = nullptr;
attachmentDescriptions.push_back({});
desc = &attachmentDescriptions.back();
@@ -79,5 +78,4 @@ RenderPass::~RenderPass() {
VkRenderPass RenderPass::getVk() { return vk; }
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -2,8 +2,7 @@
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class RenderPass : public VkObjectWrapper {
@@ -19,5 +18,4 @@ class RenderPass : public VkObjectWrapper {
VkRenderPass getVk();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -7,23 +7,23 @@
#include "glfw_mgmt_details.h"
#include "vulkan_adapter.h"
#include "vulkan_common.h"
#include "vulkan_physical_device.h"
#include "vulkan_render_pass.h"
#include "../../main/logging.h"
using namespace progressia::main::logging;
namespace progressia {
namespace desktop {
namespace progressia::desktop {
SwapChain::SupportDetails
SwapChain::querySwapChainSupport(VkPhysicalDevice device, Vulkan &vulkan) {
SupportDetails details;
auto surface = vulkan.getSurface().getVk();
auto *surface = vulkan.getSurface().getVk();
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface,
&details.capabilities);
uint32_t formatCount;
uint32_t formatCount = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount,
nullptr);
@@ -33,7 +33,7 @@ SwapChain::querySwapChainSupport(VkPhysicalDevice device, Vulkan &vulkan) {
details.formats.data());
}
uint32_t presentModeCount;
uint32_t presentModeCount = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface,
&presentModeCount, nullptr);
@@ -51,7 +51,8 @@ bool SwapChain::isSwapChainSuitable(const SupportDetails &details) {
}
void SwapChain::create() {
auto details = querySwapChainSupport(vulkan.getPhysicalDevice(), vulkan);
auto details =
querySwapChainSupport(vulkan.getPhysicalDevice().getVk(), vulkan);
auto surfaceFormat = chooseSurfaceFormat(details.formats);
auto presentMode = choosePresentMode(details.presentModes, true);
this->extent = chooseExtent(details.capabilities);
@@ -188,6 +189,7 @@ void SwapChain::create() {
}
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
VkSurfaceFormatKHR SwapChain::chooseSurfaceFormat(
const std::vector<VkSurfaceFormatKHR> &supported) {
for (const auto &option : supported) {
@@ -202,6 +204,7 @@ VkSurfaceFormatKHR SwapChain::chooseSurfaceFormat(
exit(1);
}
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
bool SwapChain::isTripleBufferingSupported(
const std::vector<VkPresentModeKHR> &supported) {
return std::find(supported.begin(), supported.end(),
@@ -219,13 +222,15 @@ SwapChain::choosePresentMode(const std::vector<VkPresentModeKHR> &supported,
}
VkExtent2D
// NOLINTNEXTLINE(readability-convert-member-functions-to-static): future-proofing
SwapChain::chooseExtent(const VkSurfaceCapabilitiesKHR &capabilities) {
if (capabilities.currentExtent.width !=
std::numeric_limits<uint32_t>::max()) {
return capabilities.currentExtent;
}
int width, height;
int width = 0;
int height = 0;
glfwGetFramebufferSize(getGLFWWindowHandle(), &width, &height);
VkExtent2D actualExtent = {static_cast<uint32_t>(width),
@@ -242,7 +247,7 @@ SwapChain::chooseExtent(const VkSurfaceCapabilitiesKHR &capabilities) {
}
void SwapChain::destroy() {
for (auto framebuffer : framebuffers) {
for (auto *framebuffer : framebuffers) {
vkDestroyFramebuffer(vulkan.getDevice(), framebuffer, nullptr);
}
framebuffers.clear();
@@ -259,7 +264,7 @@ void SwapChain::destroy() {
}
}
for (auto colorBufferView : colorBufferViews) {
for (auto *colorBufferView : colorBufferViews) {
vkDestroyImageView(vulkan.getDevice(), colorBufferView, nullptr);
}
colorBufferViews.clear();
@@ -271,10 +276,10 @@ void SwapChain::destroy() {
}
SwapChain::SwapChain(Vulkan &vulkan)
: vk(VK_NULL_HANDLE), colorBuffer(nullptr),
colorBufferViews(), extent{0, 0}, depthBuffer(nullptr), framebuffers(),
vulkan(vulkan) {
auto details = querySwapChainSupport(vulkan.getPhysicalDevice(), vulkan);
: vk(VK_NULL_HANDLE), colorBuffer(nullptr), extent{0, 0},
depthBuffer(nullptr), vulkan(vulkan) {
auto details =
querySwapChainSupport(vulkan.getPhysicalDevice().getVk(), vulkan);
auto surfaceFormat = chooseSurfaceFormat(details.formats);
vulkan.getAdapter().getAttachments().push_back(
@@ -289,7 +294,7 @@ SwapChain::SwapChain(Vulkan &vulkan)
VK_ATTACHMENT_LOAD_OP_CLEAR,
VK_ATTACHMENT_STORE_OP_STORE,
{{{0.0f, 0.0f, 0.0f, 1.0f}}},
{{{0.0F, 0.0F, 0.0F, 1.0F}}},
std::make_unique<Image>(static_cast<VkImage>(VK_NULL_HANDLE),
static_cast<VkImageView>(VK_NULL_HANDLE),
@@ -325,5 +330,4 @@ VkFramebuffer SwapChain::getFramebuffer(std::size_t index) const {
VkExtent2D SwapChain::getExtent() const { return extent; }
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -3,8 +3,7 @@
#include "vulkan_adapter.h"
#include "vulkan_common.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class SwapChain : public VkObjectWrapper {
@@ -54,5 +53,4 @@ class SwapChain : public VkObjectWrapper {
VkExtent2D getExtent() const;
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,7 +1,6 @@
#include "vulkan_texture_descriptors.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
void TextureDescriptors::allocatePool() {
pools.resize(pools.size() + 1);
@@ -16,7 +15,7 @@ void TextureDescriptors::allocatePool() {
poolInfo.pPoolSizes = &poolSize;
poolInfo.maxSets = POOL_SIZE;
auto output = &pools[pools.size() - 1];
auto *output = &pools[pools.size() - 1];
vulkan.handleVkResult(
"Could not create texture descriptor pool",
vkCreateDescriptorPool(vulkan.getDevice(), &poolInfo, nullptr, output));
@@ -25,7 +24,7 @@ void TextureDescriptors::allocatePool() {
}
TextureDescriptors::TextureDescriptors(Vulkan &vulkan)
: DescriptorSetInterface(SET_NUMBER, vulkan) {
: DescriptorSetInterface(SET_NUMBER, vulkan), lastPoolCapacity(0) {
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
@@ -48,7 +47,7 @@ TextureDescriptors::TextureDescriptors(Vulkan &vulkan)
}
TextureDescriptors::~TextureDescriptors() {
for (auto pool : pools) {
for (auto *pool : pools) {
vkDestroyDescriptorPool(vulkan.getDevice(), pool, nullptr);
}
@@ -72,7 +71,7 @@ VkDescriptorSet TextureDescriptors::addTexture(VkImageView view,
allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = &layout;
VkDescriptorSet descriptorSet;
VkDescriptorSet descriptorSet = nullptr;
vulkan.handleVkResult("Could not create texture descriptor set",
vkAllocateDescriptorSets(vulkan.getDevice(),
&allocInfo, &descriptorSet));
@@ -102,5 +101,4 @@ VkDescriptorSet TextureDescriptors::addTexture(VkImageView view,
return descriptorSet;
}
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -5,8 +5,7 @@
#include "vulkan_common.h"
#include "vulkan_descriptor_set.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
class TextureDescriptors : public DescriptorSetInterface {
private:
@@ -25,5 +24,4 @@ class TextureDescriptors : public DescriptorSetInterface {
VkDescriptorSet addTexture(VkImageView, VkSampler);
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop

View File

@@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <memory>
#include <vector>
@@ -7,8 +8,7 @@
#include "vulkan_common.h"
#include "vulkan_descriptor_set.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
template <typename... Entries> class Uniform : public DescriptorSetInterface {
@@ -70,7 +70,6 @@ template <typename... Entries> class Uniform : public DescriptorSetInterface {
void doUpdates();
};
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop
#include "vulkan_uniform.inl"

View File

@@ -5,14 +5,29 @@
#include "../../main/util.h"
#include "vulkan_frame.h"
#include "vulkan_pipeline.h"
#include "vulkan_physical_device.h"
namespace progressia {
namespace desktop {
namespace progressia::desktop {
namespace detail {
template <typename T>
std::size_t offsetOf(Vulkan &vulkan) {
auto step = vulkan.getPhysicalDevice().getMinUniformOffset();
return ((sizeof(T) - 1) / step + 1) * step; // Round up to multiple
}
template <typename T>
std::size_t offsetOf(Vulkan &vulkan, const T&) {
return offsetOf<T>(vulkan);
}
}
template <typename... Entries>
Uniform<Entries...>::StateImpl::Set::Set(VkDescriptorSet vk, Vulkan &vulkan)
: vk(vk),
contents((sizeof(Entries) + ...), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
contents((detail::offsetOf<Entries>(vulkan) + ...), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
vulkan) {}
@@ -48,7 +63,7 @@ Uniform<Entries...>::StateImpl::StateImpl(
writes[index].descriptorCount = 1;
writes[index].pBufferInfo = &bufferInfos[index];
offset += sizeof(Entry);
offset += detail::offsetOf<Entry>(vulkan);
index++;
})
}
@@ -71,7 +86,7 @@ void Uniform<Entries...>::State::update(const Entries &...entries) {
auto *dst = state.newContents.data();
FOR_PACK(Entries, entries, e, {
std::memcpy(dst, &e, sizeof(e));
dst += sizeof(e);
dst += detail::offsetOf(uniform->getVulkan(), e);
})
state.setsToUpdate = state.sets.size();
}
@@ -190,5 +205,4 @@ template <typename... Entries> void Uniform<Entries...>::doUpdates() {
}
}
} // namespace desktop
} // namespace progressia
} // namespace progressia::desktop