copying code over from alphane engine
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui_impl_vulkan.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include "types.hpp"
|
||||
#include "window.hpp"
|
||||
|
||||
#define HEP_VULKAN_API_VERSION VK_API_VERSION_1_3
|
||||
|
||||
namespace hep {
|
||||
|
||||
struct QueueFamilyIndices {
|
||||
std::optional<uint32_t> graphicsFamily;
|
||||
std::optional<uint32_t> presentFamily;
|
||||
|
||||
bool isComplete() {
|
||||
return graphicsFamily.has_value() && presentFamily.has_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct SwapchainSupportDetails {
|
||||
std::vector<vk::SurfaceFormatKHR> formats;
|
||||
std::vector<vk::PresentModeKHR> presentModes;
|
||||
vk::SurfaceCapabilitiesKHR capabilities;
|
||||
};
|
||||
|
||||
class Device {
|
||||
public:
|
||||
Device(const Device&) = delete;
|
||||
Device& operator=(const Device&) = delete;
|
||||
Device(Device&&) = delete;
|
||||
Device& operator=(Device&&) = delete;
|
||||
|
||||
Device(Window& window);
|
||||
~Device();
|
||||
|
||||
const vk::Device* get() const {
|
||||
assert(this->device);
|
||||
return &this->device.get();
|
||||
}
|
||||
|
||||
void waitIdle() { this->device->waitIdle(); }
|
||||
|
||||
vk::CommandPool getCommandPool() const { return this->commandPool; }
|
||||
vk::SurfaceKHR getSurface() const { return surface; }
|
||||
vk::Queue getGraphicsQueue() const { return graphicsQueue; }
|
||||
vk::Queue getPresentQueue() const { return presentQueue; }
|
||||
|
||||
QueueFamilyIndices getQueueIndices() {
|
||||
return findQueueFamilies(this->physicalDevice);
|
||||
}
|
||||
|
||||
SwapchainSupportDetails getSwapchainSupport() {
|
||||
return querySwapchainSupport(this->physicalDevice);
|
||||
}
|
||||
|
||||
u32 findMemoryType(u32 typeFilter, vk::MemoryPropertyFlags properties);
|
||||
|
||||
vk::Format findSupportedFormat(const std::vector<vk::Format>& candidates,
|
||||
vk::ImageTiling tiling,
|
||||
vk::FormatFeatureFlags features);
|
||||
|
||||
void createBuffer(vk::DeviceSize size,
|
||||
vk::BufferUsageFlags usage,
|
||||
vk::MemoryPropertyFlags properties,
|
||||
vk::Buffer& buffer,
|
||||
vk::DeviceMemory& bufferMemory);
|
||||
|
||||
vk::CommandBuffer beginSingleTimeCommands();
|
||||
|
||||
void endSingleTimeCommands(vk::CommandBuffer commandBuffer);
|
||||
|
||||
void copyBuffer(vk::Buffer sourceBuffer,
|
||||
vk::Buffer destinationBuffer,
|
||||
vk::DeviceSize size);
|
||||
|
||||
void createImageWithInfo(const vk::ImageCreateInfo& imageInfo,
|
||||
vk::MemoryPropertyFlags properties,
|
||||
vk::Image& image,
|
||||
vk::DeviceMemory& imageMemory);
|
||||
|
||||
void populateImGuiInitInfo(ImGui_ImplVulkan_InitInfo& initInfo);
|
||||
|
||||
vk::PhysicalDeviceProperties properties;
|
||||
|
||||
private:
|
||||
void setupDebugMessenger();
|
||||
|
||||
bool checkValidationLayerSupport();
|
||||
std::vector<const char*> getRequiredExtensions();
|
||||
void createVulkanInstance();
|
||||
|
||||
QueueFamilyIndices findQueueFamilies(vk::PhysicalDevice device);
|
||||
bool checkDeviceExtensionSupport(const vk::PhysicalDevice& device);
|
||||
bool isPhysicalDeviceSuitable(const vk::PhysicalDevice& device);
|
||||
void pickPhysicalDevice();
|
||||
|
||||
SwapchainSupportDetails querySwapchainSupport(vk::PhysicalDevice device);
|
||||
|
||||
void createLogicalDevice();
|
||||
void createCommandPool();
|
||||
|
||||
vk::UniqueInstance instance;
|
||||
VkDebugUtilsMessengerEXT debugMessenger;
|
||||
|
||||
Window& window;
|
||||
vk::SurfaceKHR surface;
|
||||
|
||||
vk::PhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
vk::UniqueDevice device;
|
||||
|
||||
vk::Queue graphicsQueue;
|
||||
vk::Queue presentQueue;
|
||||
|
||||
vk::CommandPool commandPool;
|
||||
|
||||
#ifdef NDEBUG
|
||||
const bool enableValidationLayers = false;
|
||||
const std::vector<const char*> enabledLayers;
|
||||
#else
|
||||
const bool enableValidationLayers = true;
|
||||
const std::vector<const char*> enabledLayers = {
|
||||
"VK_LAYER_KHRONOS_validation"};
|
||||
#endif
|
||||
const std::vector<const char*> enabledExtensions = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME};
|
||||
};
|
||||
|
||||
} // namespace hep
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace hep
|
||||
{
|
||||
|
||||
using u8 = uint8_t;
|
||||
using u16 = uint16_t;
|
||||
using u32 = uint32_t;
|
||||
using u64 = uint64_t;
|
||||
|
||||
using s8 = int8_t;
|
||||
using s16 = int16_t;
|
||||
using s32 = int32_t;
|
||||
using s64 = int64_t;
|
||||
|
||||
using f32 = float;
|
||||
using f64 = double;
|
||||
|
||||
} // namespace hep
|
||||
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include "util/logger.hpp"
|
||||
|
||||
#define DEFAULT_DELEGATE_FUNCTOR_ALLOC 5
|
||||
|
||||
namespace hep {
|
||||
|
||||
class expired_weak_object : public std::runtime_error {
|
||||
public:
|
||||
explicit expired_weak_object(const std::string& message)
|
||||
: std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a weak function that safely calls a method if the
|
||||
* object is alive.
|
||||
*
|
||||
* @tparam O Class owning the method
|
||||
* @tparam A Variadic template parameters for the method arguments
|
||||
*
|
||||
* @param method Pointer to the static method to be called
|
||||
* @param obj Shared pointer to the object instance
|
||||
* @returns std::function that calls method on obj if alive, or throws if
|
||||
* expired
|
||||
* @throws std::invalid_argument If obj is null.
|
||||
* @throws expired_weak_object If the object has expired when called
|
||||
*
|
||||
* @note Could investigate removing throwing exceptions, and instead return a
|
||||
* bool if the weak pointer is alive. This may improve performance
|
||||
*/
|
||||
template <class O, typename... A>
|
||||
std::function<void(A...)> createWeakFunction(void (O::*method)(A...),
|
||||
std::shared_ptr<O> obj) {
|
||||
if (!obj) { throw std::invalid_argument("method and obj must not be null"); }
|
||||
|
||||
std::weak_ptr<O> weakObj = obj;
|
||||
|
||||
return std::function<void(A...)>([method = std::move(method),
|
||||
weakObj = std::move(weakObj)](A... args) {
|
||||
if (auto lockedObj = weakObj.lock()) {
|
||||
(lockedObj.get()->*method)(std::forward<A>(args)...);
|
||||
} else {
|
||||
throw expired_weak_object("Attempting to call function of a dead class");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename... A>
|
||||
class Delegate {
|
||||
public:
|
||||
using Functor = std::function<void(A...)>;
|
||||
|
||||
Delegate() { this->functors.reserve(DEFAULT_DELEGATE_FUNCTOR_ALLOC); }
|
||||
|
||||
void add(const Functor& func) { functors.push_back(func); }
|
||||
|
||||
template <class O>
|
||||
void addMethod(void (O::*memberFn)(A...), std::shared_ptr<O> obj) {
|
||||
functors.push_back(createWeakFunction(memberFn, obj));
|
||||
}
|
||||
|
||||
void clear() { this->functors.clear(); }
|
||||
|
||||
void invoke(A... args) {
|
||||
if (this->functors.empty()) {
|
||||
log::warning("invoking empty delegate");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<size_t> deadFunctorIndexs;
|
||||
|
||||
for (size_t i = 0; i < functors.size(); i++) {
|
||||
if (this->functors[i]) {
|
||||
try {
|
||||
this->functors[i](std::forward<A>(args)...);
|
||||
} catch (const expired_weak_object& e) {
|
||||
log::error("delegate invoke error: ", e.what());
|
||||
deadFunctorIndexs.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = deadFunctorIndexs.rbegin(); it != deadFunctorIndexs.rend();
|
||||
++it) {
|
||||
functors.erase(functors.begin() + *it);
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(Functor c) {
|
||||
clear();
|
||||
|
||||
if (c != nullptr) { add(c); }
|
||||
}
|
||||
|
||||
void operator+=(Functor c) { add(c); }
|
||||
|
||||
void operator()() { invoke(); }
|
||||
|
||||
private:
|
||||
std::vector<Functor> functors;
|
||||
};
|
||||
|
||||
} // namespace hep
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* Lots of work still needs to be done in here.
|
||||
*
|
||||
* Usage:
|
||||
* using namespace hep;
|
||||
* log::fatal("fatal message")
|
||||
* log::info("Infomation message")
|
||||
*
|
||||
* TODO Impl some form of log error handling
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
#include "types.hpp"
|
||||
|
||||
namespace hep
|
||||
{
|
||||
namespace log
|
||||
{
|
||||
|
||||
enum class LEVEL
|
||||
{
|
||||
NONE,
|
||||
FATAL,
|
||||
ERROR,
|
||||
WARNING,
|
||||
INFO,
|
||||
VERBOSE,
|
||||
DEBUGGING,
|
||||
TRACE,
|
||||
};
|
||||
|
||||
// Helper print functions
|
||||
#define LOG_PRINT_HELPER(MSG) std::cout << MSG
|
||||
#define LOG_PREFIX_FATAL LOG_PRINT_HELPER("\033[1;91m[FATAL]\033[0m ")
|
||||
#define LOG_PREFIX_ERROR LOG_PRINT_HELPER("\033[1;31m[ERROR]\033[0m ")
|
||||
#define LOG_PREFIX_WARNING LOG_PRINT_HELPER("\033[1;33m[WARNING]\033[0m ")
|
||||
#define LOG_PREFIX_INFO LOG_PRINT_HELPER("\033[32m[INFO]\033[0m ")
|
||||
#define LOG_PREFIX_VERBOSE LOG_PRINT_HELPER("\033[36m[VERBOSE]\033[0m ")
|
||||
#define LOG_PREFIX_DEBUG LOG_PRINT_HELPER("\033[1;34m[DEBUG]\033[0m ")
|
||||
#define LOG_PREFIX_TRACE LOG_PRINT_HELPER("\033[1;90m[TRACE]\033[0m ")
|
||||
|
||||
template <typename... Args>
|
||||
void log(LEVEL level = LEVEL::NONE, Args... args)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
switch (level)
|
||||
{
|
||||
case LEVEL::FATAL:
|
||||
LOG_PREFIX_FATAL;
|
||||
break;
|
||||
case LEVEL::ERROR:
|
||||
LOG_PREFIX_ERROR;
|
||||
break;
|
||||
case LEVEL::WARNING:
|
||||
LOG_PREFIX_WARNING;
|
||||
break;
|
||||
case LEVEL::INFO:
|
||||
LOG_PREFIX_INFO;
|
||||
break;
|
||||
case LEVEL::VERBOSE:
|
||||
LOG_PREFIX_VERBOSE;
|
||||
break;
|
||||
// case LEVEL::DEBUGGING:
|
||||
// LOG_PREFIX_DEBUG;
|
||||
// break;
|
||||
case LEVEL::TRACE:
|
||||
LOG_PREFIX_TRACE;
|
||||
break;
|
||||
default:
|
||||
std::cout << "\033[1;90m[LOG]\033[0m ";
|
||||
break;
|
||||
}
|
||||
|
||||
((std::cout << ' ' << std::forward<Args>(args)), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)level;
|
||||
(void)std::initializer_list<int>{((void)args, 0)...};
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void fatal(Args... args)
|
||||
{
|
||||
log(LEVEL::FATAL, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void error(Args... args)
|
||||
{
|
||||
log(LEVEL::ERROR, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void warning(Args... args)
|
||||
{
|
||||
log(LEVEL::WARNING, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void info(Args... args)
|
||||
{
|
||||
log(LEVEL::INFO, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void verbose(Args... args)
|
||||
{
|
||||
log(LEVEL::VERBOSE, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void debug(const char *file, u16 line, Args... args)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
LOG_PREFIX_DEBUG;
|
||||
std::cout << file << "::" << line;
|
||||
((std::cout << ' ' << std::forward<Args>(args)), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)std::initializer_list<int>{((void)args, 0)...};
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
// trick
|
||||
#define debug(...) debug(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
template <typename... Args>
|
||||
void trace(Args... args)
|
||||
{
|
||||
log(LEVEL::TRACE, args...);
|
||||
}
|
||||
|
||||
} // namespace log
|
||||
} // namespace hep
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <string>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include "event.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace hep {
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window(const Window&) = delete;
|
||||
Window& operator=(const Window&) = delete;
|
||||
|
||||
Window(int width, int height, const std::string& name = "hephaestus");
|
||||
~Window();
|
||||
|
||||
bool shouldClose() { return glfwWindowShouldClose(window); }
|
||||
|
||||
int getWidth() const { return this->width; }
|
||||
int getHeight() const { return this->height; }
|
||||
|
||||
vk::Extent2D getExtent() {
|
||||
return {static_cast<u32>(width), static_cast<u32>(height)};
|
||||
}
|
||||
void createSurface(const vk::Instance& instance, vk::SurfaceKHR& surface);
|
||||
bool wasResized() const { return this->resized; };
|
||||
void resetResizedFlag() { this->resized = false; }
|
||||
|
||||
GLFWwindow* getGLFWwindow() { return this->window; }
|
||||
|
||||
private:
|
||||
static void resizeCallback(GLFWwindow* window, int width, int height);
|
||||
static void keyEventCallback(GLFWwindow* window,
|
||||
int key,
|
||||
int scancode,
|
||||
int action,
|
||||
int mods);
|
||||
void initialize();
|
||||
|
||||
int width, height;
|
||||
bool resized = false;
|
||||
std::string name;
|
||||
GLFWwindow* window;
|
||||
};
|
||||
|
||||
} // namespace hep
|
||||
Reference in New Issue
Block a user