Add namespace to all classes

This commit is contained in:
Thraix
2023-02-05 10:52:27 +01:00
parent 708b81c571
commit 88979a5ab9
32 changed files with 2611 additions and 2535 deletions
-1
View File
@@ -192,7 +192,6 @@
<ClInclude Include="src\VertexBuffer.h" /> <ClInclude Include="src\VertexBuffer.h" />
<ClInclude Include="src\VertexDescriptor.h" /> <ClInclude Include="src\VertexDescriptor.h" />
<ClInclude Include="src\VulkanException.h" /> <ClInclude Include="src\VulkanException.h" />
<ClInclude Include="src\Window.h" />
<ClInclude Include="src\VertexPassthrough.h" /> <ClInclude Include="src\VertexPassthrough.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
-3
View File
@@ -50,9 +50,6 @@
<ClInclude Include="src\Instance.h"> <ClInclude Include="src\Instance.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\Window.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Timer.h"> <ClInclude Include="src\Timer.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
+239
View File
@@ -0,0 +1,239 @@
#pragma once
#include "Buffer.h"
#include "DescriptorPool.h"
#include "DescriptorSet.h"
#include "Framebuffer.h"
#include "IndexBuffer.h"
#include "Instance.h"
#include "Pipeline.h"
#include "Texture2D.h"
#include "Timer.h"
#include "UniformBuffer.h"
#include "Vertex.h"
#include "VertexBuffer.h"
#include "VertexPassthrough.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <optional>
#include <set>
#include <vector>
namespace Copium
{
const std::vector<Vertex> vertices = {
Vertex{{-0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
Vertex{{ 0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
Vertex{{ 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
Vertex{{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
Vertex{{-0.5f, 0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
Vertex{{ 0.5f, 0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
Vertex{{ 0.5f, 0.0f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
Vertex{{-0.5f, 0.0f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
};
const std::vector<uint16_t> indices = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
};
const std::vector<VertexPassthrough> verticesPassthrough = {
VertexPassthrough{{-1.0f, -1.0f}},
VertexPassthrough{{ 1.0f, -1.0f}},
VertexPassthrough{{ 1.0f, 1.0f}},
VertexPassthrough{{-1.0f, 1.0f}},
};
const std::vector<uint16_t> indicesPassthrough = {
0, 1, 2, 2, 3, 0,
};
struct alignas(64) ShaderUniform
{
alignas(16) glm::mat4 projection;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 model;
alignas(16) glm::vec3 lightPos;
};
class Application final
{
private:
std::unique_ptr<Instance> instance;
std::unique_ptr<Pipeline> graphicsPipeline;
std::unique_ptr<Texture2D> texture2D;
std::unique_ptr<UniformBuffer> shaderUniformBuffer;
std::unique_ptr<DescriptorPool> descriptorPool;
std::unique_ptr<DescriptorSet> descriptorSet;
std::unique_ptr<VertexBuffer> vertexBuffer;
std::unique_ptr<IndexBuffer> indexBuffer;
std::unique_ptr<CommandBuffer> commandBuffer;
std::unique_ptr<Framebuffer> framebuffer;
std::unique_ptr<Pipeline> graphicsPipelinePassthrough;
std::unique_ptr<VertexBuffer> vertexBufferPassthrough;
std::unique_ptr<IndexBuffer> indexBufferPassthrough;
std::unique_ptr<DescriptorSet> descriptorSetPassthrough;
public:
Application()
{
InitializeInstance();
InitializeFrameBuffer();
InitializeGraphicsPipeline();
InitializeTextureSampler();
InitializeUniformBuffer();
InitializeDescriptorSets();
InitializeVertexBuffer();
InitializeIndexBuffer();
InitializeCommandBuffer();
}
~Application()
{
vkDeviceWaitIdle(instance->GetDevice());
}
Application(Application&&) = delete;
Application(const Application&) = delete;
Application& operator=(Application&&) = delete;
Application& operator=(const Application&) = delete;
bool Update()
{
if (!instance->BeginPresent())
return true;
RecordCommandBuffer();
commandBuffer->SubmitAsGraphicsQueue();
return instance->EndPresent();
}
private:
void InitializeInstance()
{
instance = std::make_unique<Instance>("Copium Engine");
}
void InitializeFrameBuffer()
{
framebuffer = std::make_unique<Framebuffer>(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height);
}
void InitializeTextureSampler()
{
texture2D = std::make_unique<Texture2D>(*instance, "res/textures/texture.png");
}
void InitializeUniformBuffer()
{
shaderUniformBuffer = std::make_unique<UniformBuffer>(*instance, sizeof(ShaderUniform));
}
void InitializeDescriptorSets()
{
descriptorPool = std::make_unique<DescriptorPool>(*instance);
descriptorSet = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
descriptorSet->AddUniform(*shaderUniformBuffer, 0);
descriptorSet->AddTexture2D(*texture2D, 1);
descriptorSetPassthrough = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0));
descriptorSetPassthrough->AddTexture2D(framebuffer->GetTexture2D(), 0);
}
void InitializeGraphicsPipeline()
{
PipelineCreator creator{framebuffer->GetRenderPass(), "res/shaders/shader.vert", "res/shaders/shader.frag"};
creator.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
creator.AddDescriptorSetLayoutBinding(0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creator.SetVertexDescriptor(Vertex::GetDescriptor());
creator.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipeline = std::make_unique<Pipeline>(*instance, creator);
PipelineCreator creatorPassthrough{instance->GetSwapChain().GetRenderPass(), "res/shaders/passthrough.vert", "res/shaders/passthrough.frag"};
creatorPassthrough.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creatorPassthrough.SetVertexDescriptor(VertexPassthrough::GetDescriptor());
creatorPassthrough.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipelinePassthrough = std::make_unique<Pipeline>(*instance, creatorPassthrough);
}
void InitializeVertexBuffer()
{
vertexBuffer = std::make_unique<VertexBuffer>(*instance, Vertex::GetDescriptor(), vertices.size());
vertexBuffer->Update(0, (void*)vertices.data());
vertexBufferPassthrough = std::make_unique<VertexBuffer>(*instance, VertexPassthrough::GetDescriptor(), verticesPassthrough.size());
vertexBufferPassthrough->Update(0, (void*)verticesPassthrough.data());
}
void InitializeIndexBuffer()
{
indexBuffer = std::make_unique<IndexBuffer>(*instance, indices.size());
indexBuffer->UpdateStaging((void*)indices.data());
indexBufferPassthrough = std::make_unique<IndexBuffer>(*instance, indicesPassthrough.size());
indexBufferPassthrough->UpdateStaging((void*)indicesPassthrough.data());
}
void InitializeCommandBuffer()
{
commandBuffer = std::make_unique<CommandBuffer>(*instance, CommandBuffer::Type::Dynamic);
}
void RecordCommandBuffer()
{
commandBuffer->Begin();
std::vector<VkClearValue> clearValues{2};
clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
clearValues[1].depthStencil = {1.0f, 0};
framebuffer->Bind(*commandBuffer);
graphicsPipeline->Bind(*commandBuffer);
UpdateUniformBuffer();
vertexBuffer->Bind(*commandBuffer);
indexBuffer->Bind(*commandBuffer);
graphicsPipeline->SetDescriptorSet(0, *descriptorSet);
graphicsPipeline->BindDescriptorSets(commandBuffer->GetHandle());
indexBuffer->Draw(*commandBuffer);
framebuffer->Unbind(*commandBuffer);
instance->GetSwapChain().BeginFrameBuffer(*commandBuffer);
graphicsPipelinePassthrough->Bind(*commandBuffer);
graphicsPipelinePassthrough->SetDescriptorSet(0, *descriptorSetPassthrough);
graphicsPipelinePassthrough->BindDescriptorSets(commandBuffer->GetHandle());
vertexBufferPassthrough->Bind(*commandBuffer);
indexBufferPassthrough->Bind(*commandBuffer);
indexBufferPassthrough->Draw(*commandBuffer);
instance->GetSwapChain().EndFrameBuffer(*commandBuffer);
commandBuffer->End();
}
void UpdateUniformBuffer()
{
static Timer startTimer;
float time = startTimer.Elapsed();
ShaderUniform shaderUniform;
shaderUniform.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
shaderUniform.projection = glm::perspective(glm::radians(45.0f), instance->GetSwapChain().GetExtent().width / (float)instance->GetSwapChain().GetExtent().height, 0.1f, 10.0f);
shaderUniform.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f));
shaderUniform.projection[1][1] *= -1;
shaderUniform.lightPos = glm::rotate(glm::mat4{1.0f}, time * glm::radians(45.0f), glm::vec3(0, 1, 0)) * glm::vec4{0.3, 0.1, 0, 1};
shaderUniformBuffer->Update(shaderUniform);
}
};
}
+7 -4
View File
@@ -5,10 +5,12 @@
#include <optional> #include <optional>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
class Buffer namespace Copium
{ {
class Buffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(Buffer); CP_DELETE_COPY_AND_MOVE_CTOR(Buffer);
protected: protected:
Instance& instance; Instance& instance;
VkDeviceMemory memory; VkDeviceMemory memory;
@@ -18,7 +20,7 @@ protected:
void* mappedData = nullptr; void* mappedData = nullptr;
public: public:
Buffer(Instance& instance, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkDeviceSize size, int count) Buffer(Instance& instance, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkDeviceSize size, int count)
: instance{instance}, size{size}, count{count} : instance{instance}, size{size}, count{count}
{ {
@@ -167,4 +169,5 @@ public:
vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), 1, &commandBuffer); vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), 1, &commandBuffer);
} }
}; };
}
+18 -15
View File
@@ -4,26 +4,28 @@
#include "Instance.h" #include "Instance.h"
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
enum class CommandBufferType namespace Copium
{
SingleUse, Dynamic
};
class CommandBuffer
{ {
class CommandBuffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(CommandBuffer); CP_DELETE_COPY_AND_MOVE_CTOR(CommandBuffer);
private: public:
enum class Type
{
SingleUse, Dynamic
};
private:
Instance& instance; Instance& instance;
std::vector<VkCommandBuffer> commandBuffers; std::vector<VkCommandBuffer> commandBuffers;
const CommandBufferType type; const Type type;
VkCommandBuffer currentCommandBuffer{VK_NULL_HANDLE}; VkCommandBuffer currentCommandBuffer{VK_NULL_HANDLE};
public: public:
CommandBuffer(Instance& instance, CommandBufferType type) CommandBuffer(Instance& instance, Type type)
: instance{instance}, type{type} : instance{instance}, type{type}
{ {
if (type == CommandBufferType::Dynamic) if (type == Type::Dynamic)
commandBuffers.resize(instance.GetMaxFramesInFlight()); commandBuffers.resize(instance.GetMaxFramesInFlight());
else else
commandBuffers.resize(1); commandBuffers.resize(1);
@@ -53,13 +55,13 @@ public:
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0; beginInfo.flags = 0;
beginInfo.pInheritanceInfo = nullptr; beginInfo.pInheritanceInfo = nullptr;
switch(type) switch (type)
{ {
case CommandBufferType::SingleUse: case Type::SingleUse:
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
currentCommandBuffer = commandBuffers.front(); currentCommandBuffer = commandBuffers.front();
break; break;
case CommandBufferType::Dynamic: case Type::Dynamic:
currentCommandBuffer = commandBuffers[instance.GetFlightIndex()]; currentCommandBuffer = commandBuffers[instance.GetFlightIndex()];
break; break;
default: default:
@@ -96,4 +98,5 @@ public:
{ {
return currentCommandBuffer; return currentCommandBuffer;
} }
}; };
}
+7 -4
View File
@@ -3,12 +3,14 @@
#include "Common.h" #include "Common.h"
#include "CommandBuffer.h" #include "CommandBuffer.h"
class CommandBufferScoped : public CommandBuffer namespace Copium
{ {
class CommandBufferScoped : public CommandBuffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(CommandBufferScoped); CP_DELETE_COPY_AND_MOVE_CTOR(CommandBufferScoped);
public: public:
CommandBufferScoped(Instance& instance) CommandBufferScoped(Instance& instance)
: CommandBuffer{instance, CommandBufferType::SingleUse} : CommandBuffer{instance, Type::SingleUse}
{ {
CommandBuffer::Begin(); CommandBuffer::Begin();
} }
@@ -18,4 +20,5 @@ public:
CommandBuffer::End(); CommandBuffer::End();
CommandBuffer::Submit(); CommandBuffer::Submit();
} }
}; };
}
+21 -19
View File
@@ -3,29 +3,29 @@
#include "VulkanException.h" #include "VulkanException.h"
#include <iostream> #include <iostream>
#define TERM_RED "\x1B[31m" #define CP_TERM_RED "\x1B[31m"
#define TERM_GREEN "\x1B[32m" #define CP_TERM_GREEN "\x1B[32m"
#define TERM_YELLOW "\x1B[33m" #define CP_TERM_YELLOW "\x1B[33m"
#define TERM_GRAY "\x1B[90m" #define CP_TERM_GRAY "\x1B[90m"
#define TERM_CLEAR "\033[0m" #define CP_TERM_CLEAR "\033[0m"
#define CP_DEBUG(format, ...) std::cout << TERM_GRAY << "[DBG] " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl #define CP_DEBUG(format, ...) std::cout << CP_TERM_GRAY << "[DBG] " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
#define CP_INFO(format, ...) std::cout << "[INF] " << StringFormat(format, __VA_ARGS__) << std::endl #define CP_INFO(format, ...) std::cout << "[INF] " << Copium::StringFormat(format, __VA_ARGS__) << std::endl
#define CP_WARN(format, ...) std::cout << TERM_YELLOW << "[WRN] " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl #define CP_WARN(format, ...) std::cout << CP_TERM_YELLOW << "[WRN] " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
#define CP_ERR(format, ...) std::cout << TERM_RED << "[ERR] " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl #define CP_ERR(format, ...) std::cout << CP_TERM_RED << "[ERR] " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
// Continue traces, will not print the [XXX] tag before the log // Continue traces, will not print the [XXX] tag before the log
#define CP_DEBUG_CONT(format, ...) std::cout << TERM_GRAY << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl #define CP_DEBUG_CONT(format, ...) std::cout << CP_TERM_GRAY << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
#define CP_INFO_CONT(format, ...) std::cout << " " << StringFormat(format, __VA_ARGS__) << std::endl #define CP_INFO_CONT(format, ...) std::cout << " " << Copium::StringFormat(format, __VA_ARGS__) << std::endl
#define CP_WARN_CONT(format, ...) std::cout << TERM_YELLOW << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl #define CP_WARN_CONT(format, ...) std::cout << CP_TERM_YELLOW << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
#define CP_ERR_CONT(format, ...) std::cout << TERM_RED << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl #define CP_ERR_CONT(format, ...) std::cout << CP_TERM_RED << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
#define CP_UNIMPLEMENTED() CP_WARN("%s is unimplemented", __FUNCTION__) #define CP_UNIMPLEMENTED() CP_WARN("%s is unimplemented", __FUNCTION__)
#define CP_ABORT(format, ...) \ #define CP_ABORT(format, ...) \
do \ do \
{ \ { \
CP_ERR(format, __VA_ARGS__); \ CP_ERR(format, __VA_ARGS__); \
throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \ throw std::runtime_error(Copium::StringFormat(format, __VA_ARGS__)); \
} while(false) } while(false)
#define CP_ASSERT(Function, format, ...) \ #define CP_ASSERT(Function, format, ...) \
do \ do \
@@ -33,7 +33,7 @@
if(!(Function)) \ if(!(Function)) \
{ \ { \
CP_ERR(format, __VA_ARGS__); \ CP_ERR(format, __VA_ARGS__); \
throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \ throw std::runtime_error(Copium::StringFormat(format, __VA_ARGS__)); \
} \ } \
} while(false) } while(false)
#define CP_VK_ASSERT(Function, format, ...) \ #define CP_VK_ASSERT(Function, format, ...) \
@@ -42,7 +42,7 @@
if(Function != VK_SUCCESS) \ if(Function != VK_SUCCESS) \
{ \ { \
CP_ERR(format, __VA_ARGS__); \ CP_ERR(format, __VA_ARGS__); \
throw VulkanException(StringFormat(format, __VA_ARGS__)); \ throw VulkanException(Copium::StringFormat(format, __VA_ARGS__)); \
} \ } \
} while(false) } while(false)
#define CP_DELETE_COPY_AND_MOVE_CTOR(ClassName) \ #define CP_DELETE_COPY_AND_MOVE_CTOR(ClassName) \
@@ -51,13 +51,15 @@
ClassName& operator=(ClassName&&) = delete; \ ClassName& operator=(ClassName&&) = delete; \
ClassName& operator=(const ClassName&) = delete ClassName& operator=(const ClassName&) = delete
template<typename ... Args> namespace Copium
std::string StringFormat(const std::string& format, Args... args)
{ {
template<typename ... Args>
std::string StringFormat(const std::string& format, Args... args)
{
int size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; int size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
CP_ASSERT(size > 0, "Error during formatting"); CP_ASSERT(size > 0, "Error during formatting");
std::unique_ptr<char[]> buf(new char[size]); std::unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...); std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1); return std::string(buf.get(), buf.get() + size - 1);
}
} }
+16 -13
View File
@@ -1,18 +1,20 @@
#pragma once #pragma once
#include "Common.h" #include "Common.h"
namespace Copium
class DebugMessenger
{ {
class DebugMessenger
{
CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger); CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger);
public: public:
VkInstance instance; VkInstance instance;
VkDebugUtilsMessengerEXT debugMessenger; VkDebugUtilsMessengerEXT debugMessenger;
DebugMessenger(VkInstance instance) DebugMessenger(VkInstance instance)
: instance{instance} : instance{instance}
{ {
#ifndef NDEBUG #ifndef NDEBUG
VkDebugUtilsMessengerCreateInfoEXT createInfo{}; VkDebugUtilsMessengerCreateInfoEXT createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
@@ -24,31 +26,31 @@ public:
createInfo.pfnUserCallback = DebugCallback; createInfo.pfnUserCallback = DebugCallback;
createInfo.pUserData = nullptr; createInfo.pUserData = nullptr;
CP_VK_ASSERT(vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger), "Failed to initialze debug messenger"); CP_VK_ASSERT(vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger), "Failed to initialze debug messenger");
#endif #endif
} }
~DebugMessenger() ~DebugMessenger()
{ {
#ifndef NDEBUG #ifndef NDEBUG
vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
#endif #endif
} }
static void AddRequiredExtensions(std::vector<const char*>* extensions) static void AddRequiredExtensions(std::vector<const char*>* extensions)
{ {
#ifndef NDEBUG #ifndef NDEBUG
extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
#endif #endif
} }
static void AddRequiredLayers(std::vector<const char*>* layers) static void AddRequiredLayers(std::vector<const char*>* layers)
{ {
#ifndef NDEBUG #ifndef NDEBUG
layers->emplace_back("VK_LAYER_KHRONOS_validation"); layers->emplace_back("VK_LAYER_KHRONOS_validation");
#endif #endif
} }
private: private:
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType, VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
@@ -85,4 +87,5 @@ private:
func(instance, debugMessenger, pAllocator); func(instance, debugMessenger, pAllocator);
} }
} }
}; };
}
+7 -4
View File
@@ -4,15 +4,17 @@
#include "Instance.h" #include "Instance.h"
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
class DescriptorPool final namespace Copium
{ {
class DescriptorPool final
{
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorPool); CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorPool);
private: private:
Instance& instance; Instance& instance;
VkDescriptorPool descriptorPool; VkDescriptorPool descriptorPool;
static const int DESCRIPTOR_SET_COUNT = 100; static const int DESCRIPTOR_SET_COUNT = 100;
public: public:
DescriptorPool(Instance& instance) DescriptorPool(Instance& instance)
: instance{instance} : instance{instance}
{ {
@@ -58,4 +60,5 @@ public:
{ {
vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data()); vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data());
} }
}; };
}
+7 -4
View File
@@ -6,17 +6,19 @@
#include "UniformBuffer.h" #include "UniformBuffer.h"
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
class DescriptorSet final namespace Copium
{ {
class DescriptorSet final
{
CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet); CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet);
private: private:
Instance& instance; Instance& instance;
DescriptorPool& descriptorPool; DescriptorPool& descriptorPool;
VkDescriptorSetLayout descriptorSetLayout; VkDescriptorSetLayout descriptorSetLayout;
std::vector<VkDescriptorSet> descriptorSets; std::vector<VkDescriptorSet> descriptorSets;
public: public:
DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout) DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout)
: instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout} : instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}
{ {
@@ -69,4 +71,5 @@ public:
{ {
return descriptorSets[instance.GetFlightIndex()]; return descriptorSets[instance.GetFlightIndex()];
} }
}; };
}
+8 -3
View File
@@ -8,14 +8,18 @@
#include <fstream> #include <fstream>
namespace FileSystem namespace Copium
{ {
class FileSystem
{
FileSystem() = delete;
public:
static std::vector<char> ReadFile(const std::string& filename) static std::vector<char> ReadFile(const std::string& filename)
{ {
std::ifstream file(filename, std::ios::ate | std::ios::binary); std::ifstream file(filename, std::ios::ate | std::ios::binary);
CP_ASSERT(file.is_open(), "Failed to open file"); CP_ASSERT(file.is_open(), "Failed to open file");
size_t fileSize = (size_t) file.tellg(); size_t fileSize = (size_t)file.tellg();
std::vector<char> buffer(fileSize); std::vector<char> buffer(fileSize);
file.seekg(0); file.seekg(0);
@@ -29,7 +33,7 @@ namespace FileSystem
std::ifstream file(filename, std::ios::ate | std::ios::binary); std::ifstream file(filename, std::ios::ate | std::ios::binary);
CP_ASSERT(file.is_open(), "Failed to open file"); CP_ASSERT(file.is_open(), "Failed to open file");
size_t fileSize = (size_t) file.tellg(); size_t fileSize = (size_t)file.tellg();
std::string buffer; std::string buffer;
buffer.resize(fileSize); buffer.resize(fileSize);
@@ -69,4 +73,5 @@ namespace FileSystem
CP_ASSERT(stat(filename.c_str(), &result) == 0, "Cannot stat file %s", filename.c_str()); CP_ASSERT(stat(filename.c_str(), &result) == 0, "Cannot stat file %s", filename.c_str());
return (int64_t)result.st_mtime; return (int64_t)result.st_mtime;
} }
};
} }
+9 -6
View File
@@ -7,11 +7,13 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
// TODO: Add resizing (recreate image, depthImage, framebuffers) namespace Copium
class Framebuffer
{ {
// TODO: Add resizing (recreate image, depthImage, framebuffers)
class Framebuffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer); CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer);
private: private:
Instance& instance; Instance& instance;
std::unique_ptr<Texture2D> image; std::unique_ptr<Texture2D> image;
@@ -21,7 +23,7 @@ private:
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
public: public:
Framebuffer(Instance& instance, uint32_t width, uint32_t height) Framebuffer(Instance& instance, uint32_t width, uint32_t height)
: instance{instance}, width{width}, height{height} : instance{instance}, width{width}, height{height}
{ {
@@ -75,7 +77,7 @@ public:
return *image; return *image;
} }
private: private:
void InitializeImages() void InitializeImages()
{ {
@@ -171,4 +173,5 @@ private:
CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer"); CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer");
} }
} }
}; };
}
+12 -7
View File
@@ -6,10 +6,12 @@
#include "CommandBufferScoped.h" #include "CommandBufferScoped.h"
#include "Instance.h" #include "Instance.h"
class Image namespace Copium
{ {
class Image
{
Image() = delete; Image() = delete;
public: public:
static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory) static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory)
{ {
VkImageCreateInfo createInfo{}; VkImageCreateInfo createInfo{};
@@ -91,7 +93,8 @@ public:
if (HasStencilComponent(format)) { if (HasStencilComponent(format)) {
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
} }
} else { }
else {
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
} }
@@ -101,7 +104,8 @@ public:
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { }
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
@@ -156,7 +160,7 @@ public:
return SelectSupportedFormat(instance, {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); return SelectSupportedFormat(instance, {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
} }
private: private:
static bool HasStencilComponent(VkFormat format) static bool HasStencilComponent(VkFormat format)
{ {
return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
@@ -168,7 +172,7 @@ private:
{ {
VkFormatProperties properties; VkFormatProperties properties;
vkGetPhysicalDeviceFormatProperties(instance.GetPhysicalDevice(), format, &properties); vkGetPhysicalDeviceFormatProperties(instance.GetPhysicalDevice(), format, &properties);
if(tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features) if (tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features)
{ {
return format; return format;
} }
@@ -179,4 +183,5 @@ private:
} }
CP_ABORT("SelectSupportedFormat : Failed to select supported format"); CP_ABORT("SelectSupportedFormat : Failed to select supported format");
} }
}; };
}
+7 -4
View File
@@ -2,12 +2,14 @@
#include "Buffer.h" #include "Buffer.h"
class IndexBuffer : public Buffer namespace Copium
{ {
class IndexBuffer : public Buffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(IndexBuffer); CP_DELETE_COPY_AND_MOVE_CTOR(IndexBuffer);
private: private:
int indexCount; int indexCount;
public: public:
IndexBuffer(Instance& instance, int indexCount) IndexBuffer(Instance& instance, int indexCount)
: Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexCount * sizeof(uint16_t), 1}, indexCount{indexCount} : Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexCount * sizeof(uint16_t), 1}, indexCount{indexCount}
{} {}
@@ -21,4 +23,5 @@ public:
{ {
vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
} }
}; };
}
+10 -7
View File
@@ -9,10 +9,12 @@
#include "SwapChain.h" #include "SwapChain.h"
#include "Timer.h" #include "Timer.h"
class Instance final namespace Copium
{ {
class Instance final
{
CP_DELETE_COPY_AND_MOVE_CTOR(Instance); CP_DELETE_COPY_AND_MOVE_CTOR(Instance);
private: private:
static const int MAX_FRAMES_IN_FLIGHT = 2; static const int MAX_FRAMES_IN_FLIGHT = 2;
static const int WINDOW_WIDTH = 1920; static const int WINDOW_WIDTH = 1920;
static const int WINDOW_HEIGHT = 1080; static const int WINDOW_HEIGHT = 1080;
@@ -38,7 +40,7 @@ private:
int frameCount = 0; int frameCount = 0;
Timer timer; Timer timer;
public: public:
Instance(const std::string& applicationName) Instance(const std::string& applicationName)
{ {
timer.Start(); timer.Start();
@@ -170,7 +172,7 @@ public:
throw std::runtime_error("Failed to find suitable memory type"); throw std::runtime_error("Failed to find suitable memory type");
} }
private: private:
void InitializeWindow(const std::string& applicationName) void InitializeWindow(const std::string& applicationName)
{ {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
@@ -278,7 +280,7 @@ private:
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{}; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
std::set<uint32_t> uniqueQueueFamilies{query.graphicsFamily.value(), query.presentFamily.value()}; std::set<uint32_t> uniqueQueueFamilies{query.graphicsFamily.value(), query.presentFamily.value()};
for(auto&& queueFamily : uniqueQueueFamilies) for (auto&& queueFamily : uniqueQueueFamilies)
{ {
VkDeviceQueueCreateInfo queueCreateInfo{}; VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
@@ -304,7 +306,7 @@ private:
graphicsQueueIndex = query.graphicsFamily.value(); graphicsQueueIndex = query.graphicsFamily.value();
presentQueueIndex = query.presentFamily.value(); presentQueueIndex = query.presentFamily.value();
vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue); vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue);
vkGetDeviceQueue(device, presentQueueIndex , 0, &presentQueue); vkGetDeviceQueue(device, presentQueueIndex, 0, &presentQueue);
} }
void InitializeSwapChain() void InitializeSwapChain()
@@ -444,4 +446,5 @@ private:
Instance* instance = static_cast<Instance*>(glfwGetWindowUserPointer(window)); Instance* instance = static_cast<Instance*>(glfwGetWindowUserPointer(window));
instance->framebufferResized = true; instance->framebufferResized = true;
} }
}; };
}
+9 -7
View File
@@ -11,11 +11,12 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include <map> #include <map>
namespace Copium
class Pipeline
{ {
class Pipeline
{
CP_DELETE_COPY_AND_MOVE_CTOR(Pipeline); CP_DELETE_COPY_AND_MOVE_CTOR(Pipeline);
private: private:
Instance& instance; Instance& instance;
std::vector<VkDescriptorSetLayout> descriptorSetLayouts{}; std::vector<VkDescriptorSetLayout> descriptorSetLayouts{};
@@ -23,7 +24,7 @@ private:
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline; VkPipeline graphicsPipeline;
public: public:
Pipeline(Instance& instance, PipelineCreator creator) Pipeline(Instance& instance, PipelineCreator creator)
: instance{instance} : instance{instance}
{ {
@@ -75,7 +76,7 @@ public:
return descriptorSetLayouts[setIndex]; return descriptorSetLayouts[setIndex];
} }
private: private:
void InitializeDescriptorSetLayout(const PipelineCreator& creator) void InitializeDescriptorSetLayout(const PipelineCreator& creator)
{ {
boundDescriptorSets.resize(creator.descriptorSetLayouts.size()); boundDescriptorSets.resize(creator.descriptorSetLayouts.size());
@@ -106,7 +107,7 @@ private:
void InitializePipeline(const PipelineCreator& creator) void InitializePipeline(const PipelineCreator& creator)
{ {
Shader shader{instance, ShaderType::GlslFile, creator.vertexShader, creator.fragmentShader}; Shader shader{instance, Shader::Type::GlslFile, creator.vertexShader, creator.fragmentShader};
VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo{}; VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo{};
vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
@@ -253,4 +254,5 @@ private:
return shaderModule; return shaderModule;
} }
}; };
}
+7 -4
View File
@@ -6,8 +6,10 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include <map> #include <map>
class PipelineCreator namespace Copium
{ {
class PipelineCreator
{
struct DescriptorSetBinding struct DescriptorSetBinding
{ {
uint32_t binding; uint32_t binding;
@@ -16,7 +18,7 @@ class PipelineCreator
VkShaderStageFlags flags; VkShaderStageFlags flags;
}; };
friend class Pipeline; friend class Pipeline;
private: private:
std::map<uint32_t, std::vector<DescriptorSetBinding>> descriptorSetLayouts{}; std::map<uint32_t, std::vector<DescriptorSetBinding>> descriptorSetLayouts{};
std::string vertexShader; std::string vertexShader;
@@ -27,7 +29,7 @@ private:
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
VkRenderPass renderPass = VK_NULL_HANDLE; VkRenderPass renderPass = VK_NULL_HANDLE;
public: public:
PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader) PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader)
: vertexShader{vertexShader}, fragmentShader{fragmentShader}, renderPass{renderPass} : vertexShader{vertexShader}, fragmentShader{fragmentShader}, renderPass{renderPass}
{} {}
@@ -57,4 +59,5 @@ public:
{ {
frontFace = cullFrontFace; frontFace = cullFrontFace;
} }
}; };
}
+6 -3
View File
@@ -4,8 +4,10 @@
#include <optional> #include <optional>
#include <vector> #include <vector>
struct QueueFamiliesQuery namespace Copium
{ {
struct QueueFamiliesQuery
{
std::optional<uint32_t> graphicsFamily; std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily; std::optional<uint32_t> presentFamily;
@@ -19,7 +21,7 @@ struct QueueFamiliesQuery
int i = 0; int i = 0;
for (auto&& queueFamily : queueFamilies) for (auto&& queueFamily : queueFamilies)
{ {
if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{ {
graphicsFamily = i; graphicsFamily = i;
} }
@@ -38,4 +40,5 @@ struct QueueFamiliesQuery
{ {
return graphicsFamily.has_value() && presentFamily.has_value(); return graphicsFamily.has_value() && presentFamily.has_value();
} }
}; };
}
+25 -21
View File
@@ -6,44 +6,47 @@
#include "Common.h" #include "Common.h"
#include "Instance.h" #include "Instance.h"
enum class ShaderType namespace Copium
{
GlslFile, GlslCode, SpvFile, SpvCode
};
class Shader
{ {
class Shader
{
CP_DELETE_COPY_AND_MOVE_CTOR(Shader); CP_DELETE_COPY_AND_MOVE_CTOR(Shader);
private: public:
enum class Type
{
GlslFile, GlslCode, SpvFile, SpvCode
};
private:
Instance& instance; Instance& instance;
VkShaderModule vertShaderModule; VkShaderModule vertShaderModule;
VkShaderModule fragShaderModule; VkShaderModule fragShaderModule;
std::vector<VkPipelineShaderStageCreateInfo> shaderStages; std::vector<VkPipelineShaderStageCreateInfo> shaderStages;
public: public:
Shader(Instance& instance, ShaderType shaderType, const std::string& vertexInput, const std::string& fragmentInput) Shader(Instance& instance, Type type, const std::string& vertexInput, const std::string& fragmentInput)
: instance{instance} : instance{instance}
{ {
switch (shaderType) switch (type)
{ {
case ShaderType::GlslCode: case Type::GlslCode:
vertShaderModule = InitializeShaderModuleFromGlslCode(vertexInput, shaderc_vertex_shader); vertShaderModule = InitializeShaderModuleFromGlslCode(vertexInput, shaderc_vertex_shader);
fragShaderModule = InitializeShaderModuleFromGlslCode(fragmentInput, shaderc_fragment_shader); fragShaderModule = InitializeShaderModuleFromGlslCode(fragmentInput, shaderc_fragment_shader);
break; break;
case ShaderType::GlslFile: case Type::GlslFile:
vertShaderModule = InitializeShaderModuleFromGlslFile(vertexInput, shaderc_vertex_shader); vertShaderModule = InitializeShaderModuleFromGlslFile(vertexInput, shaderc_vertex_shader);
fragShaderModule = InitializeShaderModuleFromGlslFile(fragmentInput, shaderc_fragment_shader); fragShaderModule = InitializeShaderModuleFromGlslFile(fragmentInput, shaderc_fragment_shader);
break; break;
case ShaderType::SpvCode: case Type::SpvCode:
vertShaderModule = InitializeShaderModule(vertexInput); vertShaderModule = InitializeShaderModule(vertexInput);
fragShaderModule = InitializeShaderModule(fragmentInput); fragShaderModule = InitializeShaderModule(fragmentInput);
break; break;
case ShaderType::SpvFile: case Type::SpvFile:
vertShaderModule = InitializeShaderModule(FileSystem::ReadFile(vertexInput)); vertShaderModule = InitializeShaderModule(FileSystem::ReadFile(vertexInput));
fragShaderModule = InitializeShaderModule(FileSystem::ReadFile(fragmentInput)); fragShaderModule = InitializeShaderModule(FileSystem::ReadFile(fragmentInput));
break; break;
default: default:
CP_ASSERT(false, "Unreachable switch case %d", (int)shaderType); CP_ASSERT(false, "Unreachable switch case %d", (int)type);
} }
shaderStages.resize(2); shaderStages.resize(2);
@@ -71,7 +74,7 @@ public:
return shaderStages; return shaderStages;
} }
private: private:
VkShaderModule InitializeShaderModule(const std::vector<uint32_t>& codeSpv) VkShaderModule InitializeShaderModule(const std::vector<uint32_t>& codeSpv)
{ {
return InitializeShaderModule(codeSpv.data(), codeSpv.size() * sizeof(uint32_t)); return InitializeShaderModule(codeSpv.data(), codeSpv.size() * sizeof(uint32_t));
@@ -87,7 +90,7 @@ private:
return InitializeShaderModule(reinterpret_cast<const uint32_t*>(codeSpv.data()), codeSpv.size()); return InitializeShaderModule(reinterpret_cast<const uint32_t*>(codeSpv.data()), codeSpv.size());
} }
VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind shaderType) VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind type)
{ {
std::string spvFilename = ".cache/" + filename + ".spv"; std::string spvFilename = ".cache/" + filename + ".spv";
try try
@@ -114,7 +117,7 @@ private:
options.SetOptimizationLevel(shaderc_optimization_level_size); options.SetOptimizationLevel(shaderc_optimization_level_size);
std::vector<char> glslCode = FileSystem::ReadFile(filename); std::vector<char> glslCode = FileSystem::ReadFile(filename);
shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(glslCode.data(), glslCode.size(), shaderType, filename.c_str(), options); shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(glslCode.data(), glslCode.size(), type, filename.c_str(), options);
CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile shader: %s\n%s", filename.c_str(), result.GetErrorMessage().c_str()); CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile shader: %s\n%s", filename.c_str(), result.GetErrorMessage().c_str());
std::vector<uint32_t> data{result.cbegin(), result.cend()}; std::vector<uint32_t> data{result.cbegin(), result.cend()};
@@ -122,14 +125,14 @@ private:
return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t)); return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t));
} }
VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind shaderType) VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type)
{ {
shaderc::Compiler compiler; shaderc::Compiler compiler;
shaderc::CompileOptions options; shaderc::CompileOptions options;
options.SetOptimizationLevel(shaderc_optimization_level_size); options.SetOptimizationLevel(shaderc_optimization_level_size);
shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(code.data(), shaderType, "inline_shader_code", options); shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(code.data(), type, "inline_shader_code", options);
CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile inline shader code: %s", result.GetErrorMessage()); CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile inline shader code: %s", result.GetErrorMessage());
std::vector<uint32_t> data{result.cbegin(), result.cend()}; std::vector<uint32_t> data{result.cbegin(), result.cend()};
@@ -148,4 +151,5 @@ private:
return shaderModule; return shaderModule;
} }
}; };
}
+67 -64
View File
@@ -10,8 +10,10 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <vector> #include <vector>
SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice) namespace Copium
{ {
SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice)
{
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities);
uint32_t formatCount; uint32_t formatCount;
@@ -29,31 +31,31 @@ SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysica
presentModes.resize(presentModeCount); presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data()); vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data());
} }
} }
bool SwapChainSupportDetails::Valid() bool SwapChainSupportDetails::Valid()
{ {
return !formats.empty() && !presentModes.empty(); return !formats.empty() && !presentModes.empty();
} }
SwapChain::SwapChain(Instance& instance) SwapChain::SwapChain(Instance& instance)
: instance{instance} : instance{instance}
{ {
Initialize(); Initialize();
InitializeImageViews(); InitializeImageViews();
InitializeDepthBuffer(); InitializeDepthBuffer();
InitializeRenderPass(); InitializeRenderPass();
InitializeFramebuffers(); InitializeFramebuffers();
} }
SwapChain::~SwapChain() SwapChain::~SwapChain()
{ {
Destroy(); Destroy();
vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr); vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
} }
void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const
{ {
std::vector<VkClearValue> clearValues{2}; std::vector<VkClearValue> clearValues{2};
clearValues[0].color = {{0.02f, 0.02f, 0.02f, 1.0f}}; clearValues[0].color = {{0.02f, 0.02f, 0.02f, 1.0f}};
clearValues[1].depthStencil = {1.0f, 0}; clearValues[1].depthStencil = {1.0f, 0};
@@ -67,35 +69,35 @@ void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const
renderPassBeginInfo.clearValueCount = clearValues.size(); renderPassBeginInfo.clearValueCount = clearValues.size();
renderPassBeginInfo.pClearValues = clearValues.data(); renderPassBeginInfo.pClearValues = clearValues.data();
vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
} }
void SwapChain::EndFrameBuffer(const CommandBuffer& commandBuffer) const void SwapChain::EndFrameBuffer(const CommandBuffer& commandBuffer) const
{ {
vkCmdEndRenderPass(commandBuffer); vkCmdEndRenderPass(commandBuffer);
} }
VkSwapchainKHR SwapChain::GetHandle() const VkSwapchainKHR SwapChain::GetHandle() const
{ {
return handle; return handle;
} }
VkRenderPass SwapChain::GetRenderPass() const VkRenderPass SwapChain::GetRenderPass() const
{ {
return renderPass; return renderPass;
} }
VkExtent2D SwapChain::GetExtent() const VkExtent2D SwapChain::GetExtent() const
{ {
return extent; return extent;
} }
VkFramebuffer SwapChain::GetFramebuffer() const VkFramebuffer SwapChain::GetFramebuffer() const
{ {
return framebuffers[imageIndex]; return framebuffers[imageIndex];
} }
bool SwapChain::BeginPresent(VkSemaphore signalSemaphore) bool SwapChain::BeginPresent(VkSemaphore signalSemaphore)
{ {
VkResult result = vkAcquireNextImageKHR(instance.GetDevice(), handle, UINT64_MAX, signalSemaphore, VK_NULL_HANDLE, &imageIndex); VkResult result = vkAcquireNextImageKHR(instance.GetDevice(), handle, UINT64_MAX, signalSemaphore, VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) if (result == VK_ERROR_OUT_OF_DATE_KHR)
{ {
@@ -103,10 +105,10 @@ bool SwapChain::BeginPresent(VkSemaphore signalSemaphore)
return false; return false;
} }
return true; return true;
} }
void SwapChain::EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized) void SwapChain::EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized)
{ {
VkPresentInfoKHR presentInfo{}; VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1; presentInfo.waitSemaphoreCount = 1;
@@ -121,10 +123,10 @@ void SwapChain::EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, boo
{ {
Recreate(); Recreate();
} }
} }
void SwapChain::Recreate() void SwapChain::Recreate()
{ {
int width = 0; int width = 0;
int height = 0; int height = 0;
glfwGetFramebufferSize(instance.GetWindow(), &width, &height); glfwGetFramebufferSize(instance.GetWindow(), &width, &height);
@@ -142,10 +144,10 @@ void SwapChain::Recreate()
InitializeImageViews(); InitializeImageViews();
InitializeDepthBuffer(); InitializeDepthBuffer();
InitializeFramebuffers(); InitializeFramebuffers();
} }
void SwapChain::Initialize() void SwapChain::Initialize()
{ {
SwapChainSupportDetails swapChainSupport{instance.GetSurface(), instance.GetPhysicalDevice()}; SwapChainSupportDetails swapChainSupport{instance.GetSurface(), instance.GetPhysicalDevice()};
VkSurfaceFormatKHR format = SelectSwapSurfaceFormat(swapChainSupport.formats); VkSurfaceFormatKHR format = SelectSwapSurfaceFormat(swapChainSupport.formats);
@@ -193,24 +195,24 @@ void SwapChain::Initialize()
vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, nullptr); vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, nullptr);
images.resize(imageCount); images.resize(imageCount);
vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, images.data()); vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, images.data());
} }
void SwapChain::InitializeImageViews() void SwapChain::InitializeImageViews()
{ {
imageViews.resize(images.size()); imageViews.resize(images.size());
for (size_t i = 0; i < images.size(); i++) for (size_t i = 0; i < images.size(); i++)
{ {
imageViews[i] = Image::InitializeImageView(instance, images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT); imageViews[i] = Image::InitializeImageView(instance, images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
} }
} }
void SwapChain::InitializeDepthBuffer() void SwapChain::InitializeDepthBuffer()
{ {
depthImage = std::make_unique<Texture2D>(instance, extent.width, extent.height, Texture2D::Type::Static, Texture2D::Format::Depth); depthImage = std::make_unique<Texture2D>(instance, extent.width, extent.height, Texture2D::Type::Static, Texture2D::Format::Depth);
} }
void SwapChain::InitializeRenderPass() void SwapChain::InitializeRenderPass()
{ {
VkAttachmentDescription colorAttachment{}; VkAttachmentDescription colorAttachment{};
colorAttachment.format = imageFormat; colorAttachment.format = imageFormat;
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
@@ -264,10 +266,10 @@ void SwapChain::InitializeRenderPass()
renderPassCreateInfo.pDependencies = &dependency; renderPassCreateInfo.pDependencies = &dependency;
CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "Failed to initialze render pass"); CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "Failed to initialze render pass");
} }
void SwapChain::InitializeFramebuffers() void SwapChain::InitializeFramebuffers()
{ {
framebuffers.resize(images.size()); framebuffers.resize(images.size());
for (size_t i = 0; i < imageViews.size(); ++i) for (size_t i = 0; i < imageViews.size(); ++i)
@@ -285,10 +287,10 @@ void SwapChain::InitializeFramebuffers()
CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "Failed to initialize swap chain framebuffer"); CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "Failed to initialize swap chain framebuffer");
} }
} }
void SwapChain::Destroy() void SwapChain::Destroy()
{ {
for (auto&& framebuffer : framebuffers) for (auto&& framebuffer : framebuffers)
{ {
vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr);
@@ -298,10 +300,10 @@ void SwapChain::Destroy()
vkDestroyImageView(instance.GetDevice(), swapChainImageView, nullptr); vkDestroyImageView(instance.GetDevice(), swapChainImageView, nullptr);
} }
vkDestroySwapchainKHR(instance.GetDevice(), handle, nullptr); vkDestroySwapchainKHR(instance.GetDevice(), handle, nullptr);
} }
VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
{ {
for (auto&& availableFormat : availableFormats) for (auto&& availableFormat : availableFormats)
{ {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
@@ -310,10 +312,10 @@ VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector<VkSurfac
} }
} }
return availableFormats[0]; return availableFormats[0];
} }
VkPresentModeKHR SwapChain::SelectSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) VkPresentModeKHR SwapChain::SelectSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes)
{ {
return VK_PRESENT_MODE_FIFO_KHR; return VK_PRESENT_MODE_FIFO_KHR;
for (auto&& availablePresentMode : availablePresentModes) for (auto&& availablePresentMode : availablePresentModes)
{ {
@@ -325,10 +327,10 @@ VkPresentModeKHR SwapChain::SelectSwapPresentMode(const std::vector<VkPresentMod
// VK_PRESENT_MODE_FIFO_KHR is guaranteed to be present // VK_PRESENT_MODE_FIFO_KHR is guaranteed to be present
return VK_PRESENT_MODE_FIFO_KHR; return VK_PRESENT_MODE_FIFO_KHR;
} }
VkExtent2D SwapChain::SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities) VkExtent2D SwapChain::SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities)
{ {
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
return capabilities.currentExtent; return capabilities.currentExtent;
@@ -339,4 +341,5 @@ VkExtent2D SwapChain::SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabi
extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
return extent; return extent;
}
} }
+15 -12
View File
@@ -6,24 +6,26 @@
#include <vector> #include <vector>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
class Instance; namespace Copium
class CommandBuffer;
class Texture2D;
struct SwapChainSupportDetails
{ {
class Instance;
class CommandBuffer;
class Texture2D;
struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities; VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats; std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes; std::vector<VkPresentModeKHR> presentModes;
SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice); SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice);
bool Valid(); bool Valid();
}; };
class SwapChain final class SwapChain final
{ {
CP_DELETE_COPY_AND_MOVE_CTOR(SwapChain); CP_DELETE_COPY_AND_MOVE_CTOR(SwapChain);
private: private:
Instance& instance; Instance& instance;
VkSwapchainKHR handle; VkSwapchainKHR handle;
@@ -36,7 +38,7 @@ private:
std::vector<VkFramebuffer> framebuffers; std::vector<VkFramebuffer> framebuffers;
uint32_t imageIndex; uint32_t imageIndex;
public: public:
SwapChain(Instance& instance); SwapChain(Instance& instance);
~SwapChain(); ~SwapChain();
@@ -51,7 +53,7 @@ public:
void Recreate(); void Recreate();
private: private:
void Initialize(); void Initialize();
void InitializeImageViews(); void InitializeImageViews();
void InitializeDepthBuffer(); void InitializeDepthBuffer();
@@ -62,4 +64,5 @@ private:
VkSurfaceFormatKHR SelectSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats); VkSurfaceFormatKHR SelectSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
VkPresentModeKHR SelectSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes); VkPresentModeKHR SelectSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
VkExtent2D SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities); VkExtent2D SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities);
}; };
}
+32 -29
View File
@@ -3,33 +3,35 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h> #include <stb/stb_image.h>
Texture2D::Texture2D(Instance& instance, const std::string& filename) namespace Copium
: instance{instance}, type{Type::Static}, format{Format::Image}
{ {
Texture2D::Texture2D(Instance& instance, const std::string& filename)
: instance{instance}, type{Type::Static}, format{Format::Image}
{
InitializeTextureImage(filename); InitializeTextureImage(filename);
InitializeSampler(); InitializeSampler();
} }
Texture2D::Texture2D(Instance& instance, int width, int height, Type type, Format format) Texture2D::Texture2D(Instance& instance, int width, int height, Type type, Format format)
: instance{instance}, type{type}, format{format} : instance{instance}, type{type}, format{format}
{ {
InitializeTexture(width, height); InitializeTexture(width, height);
InitializeSampler(); InitializeSampler();
} }
Texture2D::~Texture2D() Texture2D::~Texture2D()
{ {
for(auto&& image : images) for (auto&& image : images)
vkDestroyImage(instance.GetDevice(), image, nullptr); vkDestroyImage(instance.GetDevice(), image, nullptr);
for(auto&& imageMemory : imageMemories) for (auto&& imageMemory : imageMemories)
vkFreeMemory(instance.GetDevice(), imageMemory, nullptr); vkFreeMemory(instance.GetDevice(), imageMemory, nullptr);
for(auto&& imageView : imageViews) for (auto&& imageView : imageViews)
vkDestroyImageView(instance.GetDevice(), imageView, nullptr); vkDestroyImageView(instance.GetDevice(), imageView, nullptr);
vkDestroySampler(instance.GetDevice(), sampler, nullptr); vkDestroySampler(instance.GetDevice(), sampler, nullptr);
} }
VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const
{ {
VkDescriptorImageInfo imageInfo{}; VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.sampler = sampler; imageInfo.sampler = sampler;
@@ -47,22 +49,22 @@ VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const
} }
return imageInfo; return imageInfo;
} }
VkImageView Texture2D::GetImageView() const VkImageView Texture2D::GetImageView() const
{ {
CP_ASSERT(type == Type::Static, "GetImageView : Texture2D is not static"); CP_ASSERT(type == Type::Static, "GetImageView : Texture2D is not static");
return imageViews.front(); return imageViews.front();
} }
VkImageView Texture2D::GetImageView(int index) VkImageView Texture2D::GetImageView(int index)
{ {
CP_ASSERT(type == Type::Dynamic && index >= 0 && index < imageViews.size(), "GetImageView : Texture2D is not dynamic or index out of bound for SystemTexture"); CP_ASSERT(type == Type::Dynamic && index >= 0 && index < imageViews.size(), "GetImageView : Texture2D is not dynamic or index out of bound for SystemTexture");
return imageViews[index]; return imageViews[index];
} }
void Texture2D::InitializeTextureImage(const std::string& filename) void Texture2D::InitializeTextureImage(const std::string& filename)
{ {
int texWidth; int texWidth;
int texHeight; int texHeight;
int texChannels; int texChannels;
@@ -85,10 +87,10 @@ void Texture2D::InitializeTextureImage(const std::string& filename)
Image::CopyBufferToImage(instance, stagingBuffer, images.front(), texWidth, texHeight); Image::CopyBufferToImage(instance, stagingBuffer, images.front(), texWidth, texHeight);
Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
imageViews[0] = Image::InitializeImageView(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); imageViews[0] = Image::InitializeImageView(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
} }
void Texture2D::InitializeTexture(int width, int height) void Texture2D::InitializeTexture(int width, int height)
{ {
int count = 1; int count = 1;
if (type == Type::Dynamic) if (type == Type::Dynamic)
count = instance.GetMaxFramesInFlight(); count = instance.GetMaxFramesInFlight();
@@ -122,10 +124,10 @@ void Texture2D::InitializeTexture(int width, int height)
CP_ABORT("InitializeTexture : Unreachable switch case"); CP_ABORT("InitializeTexture : Unreachable switch case");
} }
} }
} }
void Texture2D::InitializeSampler() void Texture2D::InitializeSampler()
{ {
VkPhysicalDeviceProperties properties{}; VkPhysicalDeviceProperties properties{};
vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties); vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties);
@@ -147,4 +149,5 @@ void Texture2D::InitializeSampler()
createInfo.maxLod = 0.0f; createInfo.maxLod = 0.0f;
CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler"); CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler");
}
} }
+10 -8
View File
@@ -6,11 +6,13 @@
#include "Image.h" #include "Image.h"
#include "Instance.h" #include "Instance.h"
// TODO: Separate Texture2D and Framebuffer Attachments namespace Copium
class Texture2D
{ {
// TODO: Separate Texture2D and Framebuffer Attachments
class Texture2D
{
CP_DELETE_COPY_AND_MOVE_CTOR(Texture2D); CP_DELETE_COPY_AND_MOVE_CTOR(Texture2D);
public: public:
enum class Type enum class Type
{ {
Static, Dynamic Static, Dynamic
@@ -20,7 +22,7 @@ public:
{ {
Image, Color, Depth Image, Color, Depth
}; };
private: private:
Instance& instance; Instance& instance;
std::vector<VkImage> images; std::vector<VkImage> images;
@@ -29,7 +31,7 @@ private:
VkSampler sampler; VkSampler sampler;
Type type; Type type;
Format format; Format format;
public: public:
Texture2D(Instance& instance, const std::string& filename); Texture2D(Instance& instance, const std::string& filename);
Texture2D(Instance& instance, int width, int height, Type type, Format format); Texture2D(Instance& instance, int width, int height, Type type, Format format);
~Texture2D(); ~Texture2D();
@@ -37,9 +39,9 @@ public:
VkDescriptorImageInfo GetDescriptorImageInfo(int index) const; VkDescriptorImageInfo GetDescriptorImageInfo(int index) const;
VkImageView GetImageView() const; VkImageView GetImageView() const;
VkImageView GetImageView(int index); VkImageView GetImageView(int index);
private: private:
void InitializeTextureImage(const std::string& filename); void InitializeTextureImage(const std::string& filename);
void InitializeTexture(int width, int height); void InitializeTexture(int width, int height);
void InitializeSampler(); void InitializeSampler();
}; };
}
+7 -4
View File
@@ -2,11 +2,13 @@
#include <chrono> #include <chrono>
class Timer namespace Copium
{ {
private: class Timer
{
private:
std::chrono::time_point<std::chrono::steady_clock> startTime; std::chrono::time_point<std::chrono::steady_clock> startTime;
public: public:
Timer() Timer()
: startTime{std::chrono::steady_clock::now()} : startTime{std::chrono::steady_clock::now()}
{} {}
@@ -20,4 +22,5 @@ public:
{ {
return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - startTime).count(); return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - startTime).count();
} }
}; };
}
+6 -3
View File
@@ -4,11 +4,13 @@
#include "Buffer.h" #include "Buffer.h"
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
class UniformBuffer : public Buffer namespace Copium
{ {
class UniformBuffer : public Buffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(UniformBuffer); CP_DELETE_COPY_AND_MOVE_CTOR(UniformBuffer);
public: public:
UniformBuffer(Instance& instance, VkDeviceSize size) UniformBuffer(Instance& instance, VkDeviceSize size)
: Buffer{instance, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, instance.GetMaxFramesInFlight()} : Buffer{instance, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, instance.GetMaxFramesInFlight()}
{} {}
@@ -28,4 +30,5 @@ public:
bufferInfo.range = size; bufferInfo.range = size;
return bufferInfo; return bufferInfo;
} }
}; };
}
+5 -2
View File
@@ -4,7 +4,9 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "VertexDescriptor.h" #include "VertexDescriptor.h"
struct Vertex { namespace Copium
{
struct Vertex {
glm::vec3 pos; glm::vec3 pos;
glm::vec3 color; glm::vec3 color;
glm::vec2 texCoord; glm::vec2 texCoord;
@@ -17,5 +19,6 @@ struct Vertex {
descriptor.AddAttribute<Vertex>(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoord)); descriptor.AddAttribute<Vertex>(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoord));
return descriptor; return descriptor;
} }
}; };
}
+7 -4
View File
@@ -3,13 +3,15 @@
#include "Buffer.h" #include "Buffer.h"
#include "VertexDescriptor.h" #include "VertexDescriptor.h"
class VertexBuffer : public Buffer namespace Copium
{ {
class VertexBuffer : public Buffer
{
CP_DELETE_COPY_AND_MOVE_CTOR(VertexBuffer); CP_DELETE_COPY_AND_MOVE_CTOR(VertexBuffer);
private: private:
std::vector<VkDeviceSize> bindingOffsets; std::vector<VkDeviceSize> bindingOffsets;
std::vector<VkDeviceSize> bindingSizes; std::vector<VkDeviceSize> bindingSizes;
public: public:
VertexBuffer(Instance& instance, const VertexDescriptor& descriptor, int vertexCount) VertexBuffer(Instance& instance, const VertexDescriptor& descriptor, int vertexCount)
: Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, descriptor.GetVertexSize() * vertexCount, 1} : Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, descriptor.GetVertexSize() * vertexCount, 1}
{ {
@@ -32,4 +34,5 @@ public:
{ {
UpdateStaging(data, bindingOffsets[binding], bindingSizes[binding]); UpdateStaging(data, bindingOffsets[binding], bindingSizes[binding]);
} }
}; };
}
+8 -6
View File
@@ -2,15 +2,16 @@
#include <map> #include <map>
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
namespace Copium
class VertexDescriptor
{ {
private: class VertexDescriptor
{
private:
uint32_t bindingIndex = 0; uint32_t bindingIndex = 0;
std::vector<VkVertexInputBindingDescription> bindings; std::vector<VkVertexInputBindingDescription> bindings;
std::vector<VkVertexInputAttributeDescription> attributes; std::vector<VkVertexInputAttributeDescription> attributes;
public: public:
template <typename T> template <typename T>
void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset) void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset)
{ {
@@ -47,7 +48,7 @@ public:
return bindings; return bindings;
} }
private: private:
uint32_t AddLayout(uint32_t binding, uint32_t size) uint32_t AddLayout(uint32_t binding, uint32_t size)
{ {
VkVertexInputBindingDescription description{}; VkVertexInputBindingDescription description{};
@@ -57,4 +58,5 @@ private:
bindings.emplace_back(description); bindings.emplace_back(description);
return description.binding; return description.binding;
} }
}; };
}
+6 -3
View File
@@ -4,13 +4,16 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "VertexDescriptor.h" #include "VertexDescriptor.h"
struct VertexPassthrough { namespace Copium
{
struct VertexPassthrough {
glm::vec2 texCoord; glm::vec2 texCoord;
static VertexDescriptor GetDescriptor() static VertexDescriptor GetDescriptor()
{ {
VertexDescriptor descriptor{}; VertexDescriptor descriptor{};
descriptor.AddAttribute<VertexPassthrough>(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough , texCoord)); descriptor.AddAttribute<VertexPassthrough>(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough, texCoord));
return descriptor; return descriptor;
} }
}; };
}
+6 -3
View File
@@ -2,10 +2,13 @@
#include <stdexcept> #include <stdexcept>
class VulkanException : public std::runtime_error namespace Copium
{ {
public: class VulkanException : public std::runtime_error
{
public:
VulkanException(const std::string& str) VulkanException(const std::string& str)
: runtime_error{str.c_str()} : runtime_error{str.c_str()}
{} {}
}; };
}
-6
View File
@@ -1,6 +0,0 @@
#pragma once
class Window
{
};
+4 -239
View File
@@ -1,250 +1,15 @@
#include "Buffer.h" #include "Application.h"
#include "DescriptorPool.h" #include "Common.h"
#include "DescriptorSet.h"
#include "Framebuffer.h"
#include "IndexBuffer.h"
#include "Instance.h"
#include "Pipeline.h"
#include "Texture2D.h"
#include "Timer.h" #include "Timer.h"
#include "UniformBuffer.h"
#include "Vertex.h"
#include "VertexBuffer.h"
#include "VertexPassthrough.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <chrono>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include <optional>
#include <set>
#include <vector>
const std::vector<Vertex> vertices = {
Vertex{{-0.5f, 0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
Vertex{{ 0.5f, 0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
Vertex{{ 0.5f, 0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
Vertex{{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
Vertex{{-0.5f, 0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
Vertex{{ 0.5f, 0.0f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
Vertex{{ 0.5f, 0.0f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
Vertex{{-0.5f, 0.0f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
};
const std::vector<uint16_t> indices = {
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
};
const std::vector<VertexPassthrough> verticesPassthrough = {
VertexPassthrough{{-1.0f, -1.0f}},
VertexPassthrough{{ 1.0f, -1.0f}},
VertexPassthrough{{ 1.0f, 1.0f}},
VertexPassthrough{{-1.0f, 1.0f}},
};
const std::vector<uint16_t> indicesPassthrough = {
0, 1, 2, 2, 3, 0,
};
struct alignas(64) ShaderUniform
{
alignas(16) glm::mat4 projection;
alignas(16) glm::mat4 view;
alignas(16) glm::mat4 model;
alignas(16) glm::vec3 lightPos;
};
class Application final
{
private:
std::unique_ptr<Instance> instance;
std::unique_ptr<Pipeline> graphicsPipeline;
std::unique_ptr<Texture2D> texture2D;
std::unique_ptr<UniformBuffer> shaderUniformBuffer;
std::unique_ptr<DescriptorPool> descriptorPool;
std::unique_ptr<DescriptorSet> descriptorSet;
std::unique_ptr<VertexBuffer> vertexBuffer;
std::unique_ptr<IndexBuffer> indexBuffer;
std::unique_ptr<CommandBuffer> commandBuffer;
std::unique_ptr<Framebuffer> framebuffer;
std::unique_ptr<Pipeline> graphicsPipelinePassthrough;
std::unique_ptr<VertexBuffer> vertexBufferPassthrough;
std::unique_ptr<IndexBuffer> indexBufferPassthrough;
std::unique_ptr<DescriptorSet> descriptorSetPassthrough;
public:
Application()
{
InitializeInstance();
InitializeFrameBuffer();
InitializeGraphicsPipeline();
InitializeTextureSampler();
InitializeUniformBuffer();
InitializeDescriptorSets();
InitializeVertexBuffer();
InitializeIndexBuffer();
InitializeCommandBuffer();
}
~Application()
{
vkDeviceWaitIdle(instance->GetDevice());
}
Application(Application&&) = delete;
Application(const Application&) = delete;
Application& operator=(Application&&) = delete;
Application& operator=(const Application&) = delete;
bool Update()
{
if (!instance->BeginPresent())
return true;
RecordCommandBuffer();
commandBuffer->SubmitAsGraphicsQueue();
return instance->EndPresent();
}
private:
void InitializeInstance()
{
instance = std::make_unique<Instance>("Copium Engine");
}
void InitializeFrameBuffer()
{
framebuffer = std::make_unique<Framebuffer>(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height);
}
void InitializeTextureSampler()
{
texture2D = std::make_unique<Texture2D>(*instance, "res/textures/texture.png");
}
void InitializeUniformBuffer()
{
shaderUniformBuffer = std::make_unique<UniformBuffer>(*instance, sizeof(ShaderUniform));
}
void InitializeDescriptorSets()
{
descriptorPool = std::make_unique<DescriptorPool>(*instance);
descriptorSet = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
descriptorSet->AddUniform(*shaderUniformBuffer, 0);
descriptorSet->AddTexture2D(*texture2D, 1);
descriptorSetPassthrough = std::make_unique<DescriptorSet>(*instance, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0));
descriptorSetPassthrough->AddTexture2D(framebuffer->GetTexture2D(), 0);
}
void InitializeGraphicsPipeline()
{
PipelineCreator creator{framebuffer->GetRenderPass(), "res/shaders/shader.vert", "res/shaders/shader.frag"};
creator.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
creator.AddDescriptorSetLayoutBinding(0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creator.SetVertexDescriptor(Vertex::GetDescriptor());
creator.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipeline = std::make_unique<Pipeline>(*instance, creator);
PipelineCreator creatorPassthrough{instance->GetSwapChain().GetRenderPass(), "res/shaders/passthrough.vert", "res/shaders/passthrough.frag"};
creatorPassthrough.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
creatorPassthrough.SetVertexDescriptor(VertexPassthrough::GetDescriptor());
creatorPassthrough.SetCullMode(VK_CULL_MODE_NONE);
graphicsPipelinePassthrough = std::make_unique<Pipeline>(*instance, creatorPassthrough);
}
void InitializeVertexBuffer()
{
vertexBuffer = std::make_unique<VertexBuffer>(*instance, Vertex::GetDescriptor(), vertices.size());
vertexBuffer->Update(0, (void*)vertices.data());
vertexBufferPassthrough = std::make_unique<VertexBuffer>(*instance, VertexPassthrough::GetDescriptor(), verticesPassthrough.size());
vertexBufferPassthrough->Update(0, (void*)verticesPassthrough.data());
}
void InitializeIndexBuffer()
{
indexBuffer = std::make_unique<IndexBuffer>(*instance, indices.size());
indexBuffer->UpdateStaging((void*)indices.data());
indexBufferPassthrough = std::make_unique<IndexBuffer>(*instance, indicesPassthrough.size());
indexBufferPassthrough->UpdateStaging((void*)indicesPassthrough.data());
}
void InitializeCommandBuffer()
{
commandBuffer = std::make_unique<CommandBuffer>(*instance, CommandBufferType::Dynamic);
}
void RecordCommandBuffer()
{
commandBuffer->Begin();
std::vector<VkClearValue> clearValues{2};
clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
clearValues[1].depthStencil = {1.0f, 0};
framebuffer->Bind(*commandBuffer);
graphicsPipeline->Bind(*commandBuffer);
UpdateUniformBuffer();
vertexBuffer->Bind(*commandBuffer);
indexBuffer->Bind(*commandBuffer);
graphicsPipeline->SetDescriptorSet(0, *descriptorSet);
graphicsPipeline->BindDescriptorSets(commandBuffer->GetHandle());
indexBuffer->Draw(*commandBuffer);
framebuffer->Unbind(*commandBuffer);
instance->GetSwapChain().BeginFrameBuffer(*commandBuffer);
graphicsPipelinePassthrough->Bind(*commandBuffer);
graphicsPipelinePassthrough->SetDescriptorSet(0, *descriptorSetPassthrough);
graphicsPipelinePassthrough->BindDescriptorSets(commandBuffer->GetHandle());
vertexBufferPassthrough->Bind(*commandBuffer);
indexBufferPassthrough->Bind(*commandBuffer);
indexBufferPassthrough->Draw(*commandBuffer);
instance->GetSwapChain().EndFrameBuffer(*commandBuffer);
commandBuffer->End();
}
void UpdateUniformBuffer()
{
static Timer startTimer;
float time = startTimer.Elapsed();
ShaderUniform shaderUniform;
shaderUniform.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
shaderUniform.projection = glm::perspective(glm::radians(45.0f), instance->GetSwapChain().GetExtent().width / (float)instance->GetSwapChain().GetExtent().height, 0.1f, 10.0f);
shaderUniform.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f));
shaderUniform.projection[1][1] *= -1;
shaderUniform.lightPos = glm::rotate(glm::mat4{1.0f}, time * glm::radians(45.0f), glm::vec3(0, 1, 0)) * glm::vec4{0.3, 0.1, 0, 1};
shaderUniformBuffer->Update(shaderUniform);
}
};
void func(const int* ptr) {
*const_cast<int*>(ptr) = 20;
}
int main() int main()
{ {
CP_ASSERT(glfwInit() == GLFW_TRUE, "main : Failed to initialize the glfw context"); CP_ASSERT(glfwInit() == GLFW_TRUE, "main : Failed to initialize the glfw context");
{ {
Application application; Copium::Application application;
Timer timer; Copium::Timer timer;
int frames = 0; int frames = 0;
while (application.Update()) while (application.Update())
{ {