should prob put this on git sometime
This commit is contained in:
43
destrum/include/destrum/App.h
Normal file
43
destrum/include/destrum/App.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef APP_H
|
||||
#define APP_H
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#include "glm/vec2.hpp"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <destrum/Graphics/GfxDevice.h>
|
||||
|
||||
|
||||
class App {
|
||||
public:
|
||||
struct AppParams {
|
||||
glm::ivec2 windowSize{};
|
||||
glm::ivec2 renderSize{};
|
||||
std::string appName{"Destrum App"};
|
||||
std::string windowTitle;
|
||||
std::filesystem::path exeDir;
|
||||
};
|
||||
|
||||
void init(const AppParams& params);
|
||||
void run();
|
||||
void cleanup();
|
||||
|
||||
protected:
|
||||
SDL_Window* window{nullptr};
|
||||
AppParams m_params{};
|
||||
|
||||
GfxDevice gfxDevice;
|
||||
|
||||
bool isRunning{false};
|
||||
bool gamePaused{false};
|
||||
|
||||
bool frameLimit{true};
|
||||
float frameTime{0.f};
|
||||
float avgFPS{0.f};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //APP_H
|
||||
32
destrum/include/destrum/FS/AssetFS.h
Normal file
32
destrum/include/destrum/FS/AssetFS.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef ASSETFS_H
|
||||
#define ASSETFS_H
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <destrum/Singleton.h>
|
||||
|
||||
struct FSMount {
|
||||
std::string scheme; // "engine", "game"
|
||||
std::filesystem::path root;
|
||||
};
|
||||
|
||||
class AssetFS final: public Singleton<AssetFS> {
|
||||
public:
|
||||
void Init(std::filesystem::path exeDir);
|
||||
void Mount(std::string scheme, std::filesystem::path root);
|
||||
|
||||
std::vector<uint8_t> ReadBytes(std::string_view vpath);
|
||||
|
||||
[[nodiscard]] std::filesystem::path GetFullPath(std::string_view vpath) const;
|
||||
|
||||
private:
|
||||
static std::vector<uint8_t> ReadFile(const std::filesystem::path& fullPath);
|
||||
|
||||
std::vector<FSMount> mounts;
|
||||
|
||||
bool initialized{false};
|
||||
};
|
||||
|
||||
#endif //ASSETFS_H
|
||||
94
destrum/include/destrum/Graphics/GfxDevice.h
Normal file
94
destrum/include/destrum/Graphics/GfxDevice.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef GFXDEVICE_H
|
||||
#define GFXDEVICE_H
|
||||
|
||||
#include <VkBootstrap.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <destrum/Graphics/VImage.h>
|
||||
#include <destrum/Graphics/Swapchain.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <volk.h>
|
||||
#include <VkBootstrap.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
|
||||
#include "ImmediateExecuter.h"
|
||||
|
||||
#include <destrum/Graphics/Swapchain.h>
|
||||
|
||||
using ImageId = std::uint32_t;
|
||||
static const auto NULL_IMAGE_ID = std::numeric_limits<std::uint32_t>::max();
|
||||
|
||||
namespace {
|
||||
using ImmediateExecuteFunction = std::function<void(VkCommandBuffer)>;
|
||||
}
|
||||
|
||||
class GfxDevice {
|
||||
public:
|
||||
struct FrameData {
|
||||
VkCommandPool commandPool;
|
||||
VkCommandBuffer commandBuffer;
|
||||
};
|
||||
|
||||
GfxDevice();
|
||||
GfxDevice(const GfxDevice&) = delete;
|
||||
GfxDevice& operator=(const GfxDevice&) = delete;
|
||||
|
||||
void init(SDL_Window* window, const std::string& appName, bool vSync);
|
||||
void recreateSwapchain(int width, int height);
|
||||
|
||||
VkCommandBuffer beginFrame();
|
||||
bool needsSwapchainRecreate() const { return swapchain.isDirty(); }
|
||||
|
||||
|
||||
struct EndFrameProps {
|
||||
const VkClearColorValue clearColor{ {0.f, 0.f, 0.f, 1.f} };
|
||||
glm::ivec4 drawImageBlitRect{}; // where to blit draw image to
|
||||
};
|
||||
void endFrame(VkCommandBuffer cmd, const VImage& drawImage, const EndFrameProps& props);
|
||||
void cleanup();
|
||||
|
||||
void waitIdle();
|
||||
|
||||
void immediateSubmit(ImmediateExecuteFunction&& f) const;
|
||||
|
||||
vkb::Device getDevice() const { return device; }
|
||||
|
||||
std::uint32_t getCurrentFrameIndex() const
|
||||
{
|
||||
return frameNumber % FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
FrameData& getCurrentFrame() {
|
||||
return frames[getCurrentFrameIndex()];
|
||||
}
|
||||
|
||||
VkExtent2D getSwapchainExtent() const { return swapchain.getExtent(); }
|
||||
|
||||
|
||||
private:
|
||||
vkb::Instance instance;
|
||||
vkb::PhysicalDevice physicalDevice;
|
||||
vkb::Device device;
|
||||
VmaAllocator allocator;
|
||||
|
||||
std::uint32_t graphicsQueueFamily;
|
||||
VkQueue graphicsQueue;
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
VkFormat swapchainFormat;
|
||||
Swapchain swapchain;
|
||||
|
||||
std::array<FrameData, FRAMES_IN_FLIGHT> frames{};
|
||||
std::uint32_t frameNumber{0};
|
||||
|
||||
VulkanImmediateExecutor executor;
|
||||
|
||||
ImageId whiteImageId{NULL_IMAGE_ID};
|
||||
ImageId errorImageId{NULL_IMAGE_ID};
|
||||
};
|
||||
|
||||
|
||||
#endif //GFXDEVICE_H
|
||||
27
destrum/include/destrum/Graphics/ImmediateExecuter.h
Normal file
27
destrum/include/destrum/Graphics/ImmediateExecuter.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef IMMEDIATEEXECUTER_H
|
||||
#define IMMEDIATEEXECUTER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
class VulkanImmediateExecutor {
|
||||
public:
|
||||
void init(VkDevice device, std::uint32_t graphicsQueueFamily, VkQueue graphicsQueue);
|
||||
void cleanup(VkDevice device);
|
||||
|
||||
void immediateSubmit(std::function<void(VkCommandBuffer cmd)>&& function) const;
|
||||
|
||||
private:
|
||||
bool initialized{false};
|
||||
|
||||
VkDevice device;
|
||||
VkQueue graphicsQueue;
|
||||
|
||||
VkCommandBuffer immCommandBuffer;
|
||||
VkCommandPool immCommandPool;
|
||||
VkFence immFence;
|
||||
};
|
||||
|
||||
#endif //IMMEDIATEEXECUTER_H
|
||||
62
destrum/include/destrum/Graphics/Init.h
Normal file
62
destrum/include/destrum/Graphics/Init.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef INIT_H
|
||||
#define INIT_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
struct VImage;
|
||||
|
||||
namespace vkinit
|
||||
{
|
||||
VkImageSubresourceRange imageSubresourceRange(VkImageAspectFlags aspectMask);
|
||||
VkSemaphoreSubmitInfo semaphoreSubmitInfo(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore);
|
||||
|
||||
VkCommandPoolCreateInfo commandPoolCreateInfo(
|
||||
VkCommandPoolCreateFlags flags,
|
||||
std::uint32_t queueFamilyIndex);
|
||||
|
||||
VkCommandBufferSubmitInfo commandBufferSubmitInfo(VkCommandBuffer cmd);
|
||||
VkCommandBufferAllocateInfo commandBufferAllocateInfo(
|
||||
VkCommandPool commandPool,
|
||||
std::uint32_t commandBufferCount);
|
||||
|
||||
VkSubmitInfo2 submitInfo(
|
||||
const VkCommandBufferSubmitInfo* cmd,
|
||||
const VkSemaphoreSubmitInfo* waitSemaphoreInfo,
|
||||
const VkSemaphoreSubmitInfo* signalSemaphoreInfo);
|
||||
|
||||
VkImageCreateInfo imageCreateInfo(
|
||||
VkFormat format,
|
||||
VkImageUsageFlags usageFlags,
|
||||
VkExtent3D extent,
|
||||
std::uint32_t mipLevels = 1);
|
||||
VkImageViewCreateInfo imageViewCreateInfo(
|
||||
VkFormat format,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectFlags);
|
||||
|
||||
VkRenderingAttachmentInfo attachmentInfo(
|
||||
VkImageView view,
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
std::optional<VkClearValue> clearValue = std::nullopt);
|
||||
|
||||
VkRenderingAttachmentInfo depthAttachmentInfo(
|
||||
VkImageView view,
|
||||
VkImageLayout layout,
|
||||
std::optional<float> depthClearValue = 0.f);
|
||||
|
||||
VkRenderingInfo renderingInfo(
|
||||
VkExtent2D renderExtent,
|
||||
const VkRenderingAttachmentInfo* colorAttachment,
|
||||
const VkRenderingAttachmentInfo* depthAttachment);
|
||||
|
||||
VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo(
|
||||
VkShaderStageFlagBits stage,
|
||||
VkShaderModule shaderModule);
|
||||
} // end of namespace vkinit
|
||||
|
||||
#endif //INIT_H
|
||||
58
destrum/include/destrum/Graphics/Pipeline.h
Normal file
58
destrum/include/destrum/Graphics/Pipeline.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef VPIPELINE_H
|
||||
#define VPIPELINE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <destrum/Graphics/GfxDevice.h>
|
||||
|
||||
struct PipelineConfigInfo {
|
||||
std::string name;
|
||||
VkPipelineViewportStateCreateInfo viewportInfo{};
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo{};
|
||||
VkPipelineRasterizationStateCreateInfo rasterizationInfo{};
|
||||
VkPipelineMultisampleStateCreateInfo multisampleInfo{};
|
||||
VkPipelineColorBlendAttachmentState colorBlendAttachment{};
|
||||
VkPipelineColorBlendStateCreateInfo colorBlendInfo{};
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilInfo{};
|
||||
std::vector<VkDynamicState> dynamicStateEnables{};
|
||||
VkPipelineDynamicStateCreateInfo dynamicStateInfo{};
|
||||
|
||||
std::vector<VkFormat> colorAttachments{};
|
||||
VkFormat depthAttachment{VK_FORMAT_UNDEFINED};
|
||||
|
||||
|
||||
std::vector<VkVertexInputBindingDescription> vertexBindingDescriptions{};
|
||||
std::vector<VkVertexInputAttributeDescription> vertexAttributeDescriptions{};
|
||||
|
||||
VkPipelineLayout pipelineLayout = nullptr;
|
||||
};
|
||||
|
||||
class Pipeline {
|
||||
public:
|
||||
Pipeline(GfxDevice& device, const std::string& vertPath, const std::string& fragPath, const PipelineConfigInfo& configInfo);
|
||||
~Pipeline();
|
||||
|
||||
Pipeline(const Pipeline& other) = delete;
|
||||
Pipeline(Pipeline&& other) noexcept = delete;
|
||||
Pipeline& operator=(const Pipeline& other) = delete;
|
||||
Pipeline& operator=(Pipeline&& other) noexcept = delete;
|
||||
|
||||
void bind(VkCommandBuffer buffer) const;
|
||||
static void DefaultPipelineConfigInfo(PipelineConfigInfo& configInfo);
|
||||
|
||||
private:
|
||||
static std::vector<char> readFile(const std::string& filename);
|
||||
|
||||
void CreateGraphicsPipeline(const std::string& vertPath, const std::string& fragPath, const PipelineConfigInfo& configInfo);
|
||||
|
||||
void CreateShaderModule(const std::vector<char>& code, VkShaderModule* shaderModule) const;
|
||||
|
||||
GfxDevice& m_device;
|
||||
|
||||
VkPipeline m_graphicsPipeline{VK_NULL_HANDLE};
|
||||
VkShaderModule m_vertShaderModule{VK_NULL_HANDLE};
|
||||
VkShaderModule m_fragShaderModule{VK_NULL_HANDLE};
|
||||
};
|
||||
|
||||
#endif //VPIPELINE_H
|
||||
24
destrum/include/destrum/Graphics/Pipelines/MeshPipeline.h
Normal file
24
destrum/include/destrum/Graphics/Pipelines/MeshPipeline.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef MESHPIPELINE_H
|
||||
#define MESHPIPELINE_H
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <memory>
|
||||
#include <destrum/Graphics/Pipeline.h>
|
||||
|
||||
class MeshPipeline {
|
||||
public:
|
||||
MeshPipeline();
|
||||
~MeshPipeline();
|
||||
|
||||
void init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat);
|
||||
void draw();
|
||||
|
||||
|
||||
private:
|
||||
VkPipelineLayout m_pipelineLayout;
|
||||
|
||||
std::unique_ptr<Pipeline> m_pipeline;
|
||||
|
||||
};
|
||||
|
||||
#endif //MESHPIPELINE_H
|
||||
10
destrum/include/destrum/Graphics/Renderer.h
Normal file
10
destrum/include/destrum/Graphics/Renderer.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
class GameRenderer {
|
||||
public:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif //RENDERER_H
|
||||
15
destrum/include/destrum/Graphics/Resources/Buffer.h
Normal file
15
destrum/include/destrum/Graphics/Resources/Buffer.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef BUFFER_H
|
||||
#define BUFFER_H
|
||||
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
struct GPUBuffer {
|
||||
VkBuffer buffer{VK_NULL_HANDLE};
|
||||
VmaAllocation allocation;
|
||||
VmaAllocationInfo info;
|
||||
|
||||
VkDeviceAddress address{0};
|
||||
};
|
||||
|
||||
#endif //BUFFER_H
|
||||
53
destrum/include/destrum/Graphics/Resources/Mesh.h
Normal file
53
destrum/include/destrum/Graphics/Resources/Mesh.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef MESH_H
|
||||
#define MESH_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
struct CPUMesh {
|
||||
std::vector<std::uint32_t> indices;
|
||||
|
||||
struct Vertex {
|
||||
glm::vec3 position;
|
||||
float uv_x{};
|
||||
glm::vec3 normal;
|
||||
float uv_y{};
|
||||
glm::vec4 tangent;
|
||||
};
|
||||
std::vector<Vertex> vertices;
|
||||
|
||||
std::string name;
|
||||
|
||||
glm::vec3 minPos;
|
||||
glm::vec3 maxPos;
|
||||
};
|
||||
|
||||
|
||||
struct GPUMesh {
|
||||
GPUBuffer vertexBuffer;
|
||||
GPUBuffer indexBuffer;
|
||||
|
||||
std::uint32_t numVertices{0};
|
||||
std::uint32_t numIndices{0};
|
||||
|
||||
// AABB
|
||||
glm::vec3 minPos;
|
||||
glm::vec3 maxPos;
|
||||
math::Sphere boundingSphere;
|
||||
|
||||
bool hasSkeleton{false};
|
||||
// skinned meshes only
|
||||
GPUBuffer skinningDataBuffer;
|
||||
};
|
||||
|
||||
struct SkinnedMesh {
|
||||
GPUBuffer skinnedVertexBuffer;
|
||||
};
|
||||
|
||||
|
||||
#endif //MESH_H
|
||||
54
destrum/include/destrum/Graphics/Swapchain.h
Normal file
54
destrum/include/destrum/Graphics/Swapchain.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef SWAPCHAIN_H
|
||||
#define SWAPCHAIN_H
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "VkBootstrap.h"
|
||||
|
||||
class GfxDevice;
|
||||
static constexpr int FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
class Swapchain {
|
||||
public:
|
||||
void initSync(VkDevice device);
|
||||
//Ye ye, passing a pointer is bad bla bla @Kobe
|
||||
void createSwapchain(GfxDevice* gfxDevice, VkFormat format, std::uint32_t width, std::uint32_t height, bool vSync);
|
||||
void recreateSwapchain(const GfxDevice& gfxDevice, VkFormat format, std::uint32_t width, std::uint32_t height, bool vSync);
|
||||
void cleanup();
|
||||
|
||||
[[nodiscard]] VkExtent2D getExtent() const { return extent; }
|
||||
|
||||
[[nodiscard]] const std::vector<VkImage>& getImages() const { return images; }
|
||||
[[nodiscard]] std::uint32_t getImageCount() const { return static_cast<std::uint32_t>(images.size()); }
|
||||
|
||||
void beginFrame(int index) const;
|
||||
|
||||
void resetFences(int index) const;
|
||||
|
||||
std::pair<VkImage, int> acquireNextImage(int index);
|
||||
|
||||
void submitAndPresent(VkCommandBuffer cmd, VkQueue graphicsQueue, std::uint32_t imageIndex, std::uint32_t frameIndex);
|
||||
|
||||
[[nodiscard]] bool isDirty() const { return dirty; }
|
||||
|
||||
[[nodiscard]] VkImageView getImageView(int index) const { return imageViews[index]; }
|
||||
|
||||
private:
|
||||
struct FrameData {
|
||||
VkSemaphore swapchainSemaphore;
|
||||
VkFence renderFence;
|
||||
};
|
||||
std::vector<VkSemaphore> imageRenderSemaphores;
|
||||
|
||||
std::array<FrameData, FRAMES_IN_FLIGHT> frames;
|
||||
vkb::Swapchain m_swapchain; //Euuuh, m_ cuz like cpluhpluh
|
||||
std::vector<VkImage> images;
|
||||
std::vector<VkImageView> imageViews;
|
||||
bool dirty{false};
|
||||
GfxDevice* m_gfxDevice{nullptr};
|
||||
VkExtent2D extent{};
|
||||
};
|
||||
|
||||
#endif //SWAPCHAIN_H
|
||||
39
destrum/include/destrum/Graphics/Util.h
Normal file
39
destrum/include/destrum/Graphics/Util.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
||||
#define VK_CHECK(call) \
|
||||
do { \
|
||||
VkResult result_ = call; \
|
||||
assert(result_ == VK_SUCCESS); \
|
||||
} while (0)
|
||||
|
||||
namespace vkutil {
|
||||
void transitionImage(
|
||||
VkCommandBuffer cmd,
|
||||
VkImage image,
|
||||
VkImageLayout currentLayout,
|
||||
VkImageLayout newLayout);
|
||||
|
||||
void copyImageToImage(
|
||||
VkCommandBuffer cmd,
|
||||
VkImage source,
|
||||
VkImage destination,
|
||||
VkExtent2D srcSize,
|
||||
VkExtent2D dstSize,
|
||||
VkFilter filter);
|
||||
|
||||
void copyImageToImage(
|
||||
VkCommandBuffer cmd,
|
||||
VkImage source,
|
||||
VkImage destination,
|
||||
VkExtent2D srcSize,
|
||||
int destX,
|
||||
int destY,
|
||||
int destW,
|
||||
int destH,
|
||||
VkFilter filter);
|
||||
}
|
||||
#endif //UTIL_H
|
||||
48
destrum/include/destrum/Graphics/VImage.h
Normal file
48
destrum/include/destrum/Graphics/VImage.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef VIMAGE_H
|
||||
#define VIMAGE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class VImage {
|
||||
public:
|
||||
glm::ivec2 getSize2D() const { return glm::ivec2{extent.width, extent.height}; }
|
||||
VkExtent2D getExtent2D() const { return VkExtent2D{extent.width, extent.height}; }
|
||||
|
||||
std::uint32_t getBindlessId() const
|
||||
{
|
||||
assert(id != NULL_BINDLESS_ID && "Image wasn't added to bindless set");
|
||||
return id;
|
||||
}
|
||||
|
||||
void setBindlessId(const std::uint32_t id)
|
||||
{
|
||||
assert(id != NULL_BINDLESS_ID);
|
||||
this->id = id;
|
||||
}
|
||||
|
||||
bool isInitialized() const { return id != NULL_BINDLESS_ID; }
|
||||
|
||||
VkImage getImage() const { return image; }
|
||||
VkImageView getImageView() const { return imageView; }
|
||||
VmaAllocation getAllocation() const { return allocation; }
|
||||
private:
|
||||
VkImage image;
|
||||
VkImageView imageView;
|
||||
VmaAllocation allocation;
|
||||
VkFormat format;
|
||||
VkImageUsageFlags usage;
|
||||
VkExtent3D extent;
|
||||
std::uint32_t mipLevels{1};
|
||||
std::uint32_t numLayers{1};
|
||||
std::string debugName{};
|
||||
std::uint32_t id{NULL_BINDLESS_ID}; // bindless id - always equals to ImageId
|
||||
|
||||
static const auto NULL_BINDLESS_ID = std::numeric_limits<std::uint32_t>::max();
|
||||
|
||||
};
|
||||
|
||||
#endif //VIMAGE_H
|
||||
22
destrum/include/destrum/Singleton.h
Normal file
22
destrum/include/destrum/Singleton.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef SINGLETON_H
|
||||
#define SINGLETON_H
|
||||
|
||||
template <typename T>
|
||||
class Singleton {
|
||||
public:
|
||||
static T& GetInstance() {
|
||||
static T instance{};
|
||||
return instance;
|
||||
}
|
||||
|
||||
virtual ~Singleton() = default;
|
||||
Singleton(const Singleton& other) = delete;
|
||||
Singleton(Singleton&& other) = delete;
|
||||
Singleton& operator=(const Singleton& other) = delete;
|
||||
Singleton& operator=(Singleton&& other) = delete;
|
||||
|
||||
protected:
|
||||
Singleton() = default;
|
||||
};
|
||||
|
||||
#endif //SINGLETON_H
|
||||
Reference in New Issue
Block a user