diff --git a/Vulkan/Vulkan.vcxproj b/Vulkan/Vulkan.vcxproj
index 8b10657..d5c896f 100644
--- a/Vulkan/Vulkan.vcxproj
+++ b/Vulkan/Vulkan.vcxproj
@@ -192,7 +192,6 @@
-
diff --git a/Vulkan/Vulkan.vcxproj.filters b/Vulkan/Vulkan.vcxproj.filters
index b63afde..be9d5e2 100644
--- a/Vulkan/Vulkan.vcxproj.filters
+++ b/Vulkan/Vulkan.vcxproj.filters
@@ -50,9 +50,6 @@
Header Files
-
- Header Files
-
Header Files
diff --git a/Vulkan/src/Application.h b/Vulkan/src/Application.h
new file mode 100644
index 0000000..8ec7f40
--- /dev/null
+++ b/Vulkan/src/Application.h
@@ -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
+#include
+#include
+#include
+#include
+#include
+
+namespace Copium
+{
+ const std::vector 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 indices = {
+ 0, 1, 2, 2, 3, 0,
+ 4, 5, 6, 6, 7, 4
+ };
+
+ const std::vector verticesPassthrough = {
+ VertexPassthrough{{-1.0f, -1.0f}},
+ VertexPassthrough{{ 1.0f, -1.0f}},
+ VertexPassthrough{{ 1.0f, 1.0f}},
+ VertexPassthrough{{-1.0f, 1.0f}},
+ };
+
+ const std::vector 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;
+ std::unique_ptr graphicsPipeline;
+ std::unique_ptr texture2D;
+ std::unique_ptr shaderUniformBuffer;
+ std::unique_ptr descriptorPool;
+ std::unique_ptr descriptorSet;
+ std::unique_ptr vertexBuffer;
+ std::unique_ptr indexBuffer;
+ std::unique_ptr commandBuffer;
+
+ std::unique_ptr framebuffer;
+ std::unique_ptr graphicsPipelinePassthrough;
+ std::unique_ptr vertexBufferPassthrough;
+ std::unique_ptr indexBufferPassthrough;
+ std::unique_ptr 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("Copium Engine");
+ }
+
+ void InitializeFrameBuffer()
+ {
+ framebuffer = std::make_unique(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height);
+ }
+
+ void InitializeTextureSampler()
+ {
+ texture2D = std::make_unique(*instance, "res/textures/texture.png");
+ }
+
+ void InitializeUniformBuffer()
+ {
+ shaderUniformBuffer = std::make_unique(*instance, sizeof(ShaderUniform));
+ }
+
+ void InitializeDescriptorSets()
+ {
+ descriptorPool = std::make_unique(*instance);
+
+ descriptorSet = std::make_unique(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0));
+ descriptorSet->AddUniform(*shaderUniformBuffer, 0);
+ descriptorSet->AddTexture2D(*texture2D, 1);
+
+ descriptorSetPassthrough = std::make_unique(*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(*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(*instance, creatorPassthrough);
+ }
+
+ void InitializeVertexBuffer()
+ {
+ vertexBuffer = std::make_unique(*instance, Vertex::GetDescriptor(), vertices.size());
+ vertexBuffer->Update(0, (void*)vertices.data());
+
+ vertexBufferPassthrough = std::make_unique(*instance, VertexPassthrough::GetDescriptor(), verticesPassthrough.size());
+ vertexBufferPassthrough->Update(0, (void*)verticesPassthrough.data());
+ }
+
+ void InitializeIndexBuffer()
+ {
+ indexBuffer = std::make_unique(*instance, indices.size());
+ indexBuffer->UpdateStaging((void*)indices.data());
+
+ indexBufferPassthrough = std::make_unique(*instance, indicesPassthrough.size());
+ indexBufferPassthrough->UpdateStaging((void*)indicesPassthrough.data());
+ }
+
+ void InitializeCommandBuffer()
+ {
+ commandBuffer = std::make_unique(*instance, CommandBuffer::Type::Dynamic);
+ }
+
+ void RecordCommandBuffer()
+ {
+ commandBuffer->Begin();
+ std::vector 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);
+ }
+ };
+}
diff --git a/Vulkan/src/Buffer.h b/Vulkan/src/Buffer.h
index b6252ef..99cdd9d 100644
--- a/Vulkan/src/Buffer.h
+++ b/Vulkan/src/Buffer.h
@@ -5,166 +5,169 @@
#include
#include
-class Buffer
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(Buffer);
-protected:
- Instance& instance;
-
- VkDeviceMemory memory;
- VkBuffer handle;
- VkDeviceSize size;
- int count;
-
- void* mappedData = nullptr;
-
-public:
- Buffer(Instance& instance, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkDeviceSize size, int count)
- : instance{instance}, size{size}, count{count}
- {
- VkBufferCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- createInfo.size = size * (VkDeviceSize)count;
- createInfo.usage = usage;
- createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
-
- CP_VK_ASSERT(vkCreateBuffer(instance.GetDevice(), &createInfo, nullptr, &handle), "Failed to initialize buffer");
-
- VkMemoryRequirements memoryRequirements;
- vkGetBufferMemoryRequirements(instance.GetDevice(), handle, &memoryRequirements);
-
- VkMemoryAllocateInfo allocateInfo{};
- allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- allocateInfo.allocationSize = memoryRequirements.size;
- allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties);
-
- CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, &memory), "Failed to allocate buffer memory");
-
- vkBindBufferMemory(instance.GetDevice(), handle, memory, 0);
- }
-
- virtual ~Buffer()
+ class Buffer
{
- vkFreeMemory(instance.GetDevice(), memory, nullptr);
- vkDestroyBuffer(instance.GetDevice(), handle, nullptr);
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(Buffer);
+ protected:
+ Instance& instance;
- void Update(void* indexData, int index)
- {
- CP_ASSERT(index >= 0 && index < count, "index is outside of the buffer");
+ VkDeviceMemory memory;
+ VkBuffer handle;
+ VkDeviceSize size;
+ int count;
- if (mappedData == nullptr)
+ void* mappedData = nullptr;
+
+ public:
+ Buffer(Instance& instance, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkDeviceSize size, int count)
+ : instance{instance}, size{size}, count{count}
{
- void* data;
- vkMapMemory(instance.GetDevice(), memory, index * size, size, 0, &data);
- memcpy(data, indexData, size);
+ VkBufferCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ createInfo.size = size * (VkDeviceSize)count;
+ createInfo.usage = usage;
+ createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+ CP_VK_ASSERT(vkCreateBuffer(instance.GetDevice(), &createInfo, nullptr, &handle), "Failed to initialize buffer");
+
+ VkMemoryRequirements memoryRequirements;
+ vkGetBufferMemoryRequirements(instance.GetDevice(), handle, &memoryRequirements);
+
+ VkMemoryAllocateInfo allocateInfo{};
+ allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocateInfo.allocationSize = memoryRequirements.size;
+ allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties);
+
+ CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, &memory), "Failed to allocate buffer memory");
+
+ vkBindBufferMemory(instance.GetDevice(), handle, memory, 0);
+ }
+
+ virtual ~Buffer()
+ {
+ vkFreeMemory(instance.GetDevice(), memory, nullptr);
+ vkDestroyBuffer(instance.GetDevice(), handle, nullptr);
+ }
+
+ void Update(void* indexData, int index)
+ {
+ CP_ASSERT(index >= 0 && index < count, "index is outside of the buffer");
+
+ if (mappedData == nullptr)
+ {
+ void* data;
+ vkMapMemory(instance.GetDevice(), memory, index * size, size, 0, &data);
+ memcpy(data, indexData, size);
+ vkUnmapMemory(instance.GetDevice(), memory);
+ }
+ else
+ {
+ memcpy((char*)mappedData + index * size, indexData, size);
+ }
+ }
+
+ void UpdateStaging(void* data)
+ {
+ VkDeviceSize bufferSize = size * count;
+ Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
+
+ stagingBuffer.Update(data, 0);
+
+ CopyBuffer(instance, stagingBuffer, *this, 0, bufferSize);
+ }
+
+ void UpdateStaging(void* data, VkDeviceSize offset, VkDeviceSize size)
+ {
+ Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, 1};
+
+ stagingBuffer.Update(data, 0);
+
+ CopyBuffer(instance, stagingBuffer, *this, offset, size);
+ }
+
+ void* Map()
+ {
+ CP_ASSERT(mappedData == nullptr, "Mapping an already mapped buffer");
+ vkMapMemory(instance.GetDevice(), memory, 0, size * count, 0, &mappedData);
+ return mappedData;
+ }
+
+ void Unmap()
+ {
+ CP_ASSERT(mappedData != nullptr, "Unmapping an already unmapped buffer");
+
vkUnmapMemory(instance.GetDevice(), memory);
+ mappedData = nullptr;
}
- else
+
+ virtual void Bind(const CommandBuffer& commandBuffer) { CP_UNIMPLEMENTED(); };
+
+ void BindAsVertexBuffer(VkCommandBuffer commandBuffer)
{
- memcpy((char*)mappedData + index * size, indexData, size);
+ VkDeviceSize offset = 0;
+ vkCmdBindVertexBuffers(commandBuffer, 0, 1, &handle, &offset);
}
- }
- void UpdateStaging(void* data)
- {
- VkDeviceSize bufferSize = size * count;
- Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
+ void BindAsIndexBuffer(VkCommandBuffer commandBuffer)
+ {
+ // TODO: Maybe don't assume that indices are uint16?
+ vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16);
+ }
- stagingBuffer.Update(data, 0);
+ VkBuffer GetHandle() const
+ {
+ return handle;
+ }
- CopyBuffer(instance, stagingBuffer, *this, 0, bufferSize);
- }
+ VkDeviceSize GetSize() const
+ {
+ return size;
+ }
- void UpdateStaging(void* data, VkDeviceSize offset, VkDeviceSize size)
- {
- Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, 1};
+ VkDeviceSize GetPosition(int index) const
+ {
+ CP_ASSERT(index >= 0 && index < count, "index is outside of the buffer");
+ return size * (VkDeviceSize)index;
+ }
- stagingBuffer.Update(data, 0);
+ static void CopyBuffer(Instance& instance, const Buffer& srcBuffer, const Buffer& dstBuffer, VkDeviceSize offset, VkDeviceSize size)
+ {
+ VkCommandBufferAllocateInfo allocateInfo{};
- CopyBuffer(instance, stagingBuffer, *this, offset, size);
- }
+ allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocateInfo.commandPool = instance.GetCommandPool();
+ allocateInfo.commandBufferCount = 1;
- void* Map()
- {
- CP_ASSERT(mappedData == nullptr, "Mapping an already mapped buffer");
- vkMapMemory(instance.GetDevice(), memory, 0, size * count, 0, &mappedData);
- return mappedData;
- }
+ VkCommandBuffer commandBuffer;
+ CP_VK_ASSERT(vkAllocateCommandBuffers(instance.GetDevice(), &allocateInfo, &commandBuffer), "Failed to initialize command buffer");
- void Unmap()
- {
- CP_ASSERT(mappedData != nullptr, "Unmapping an already unmapped buffer");
+ VkCommandBufferBeginInfo beginInfo{};
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- vkUnmapMemory(instance.GetDevice(), memory);
- mappedData = nullptr;
- }
+ vkBeginCommandBuffer(commandBuffer, &beginInfo);
- virtual void Bind(const CommandBuffer& commandBuffer) { CP_UNIMPLEMENTED(); };
+ VkBufferCopy bufferCopy{};
+ bufferCopy.dstOffset = offset;
+ bufferCopy.srcOffset = 0;
+ bufferCopy.size = size;
- void BindAsVertexBuffer(VkCommandBuffer commandBuffer)
- {
- VkDeviceSize offset = 0;
- vkCmdBindVertexBuffers(commandBuffer, 0, 1, &handle, &offset);
- }
+ vkCmdCopyBuffer(commandBuffer, srcBuffer.GetHandle(), dstBuffer.GetHandle(), 1, &bufferCopy);
- void BindAsIndexBuffer(VkCommandBuffer commandBuffer)
- {
- // TODO: Maybe don't assume that indices are uint16?
- vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16);
- }
+ vkEndCommandBuffer(commandBuffer);
- VkBuffer GetHandle() const
- {
- return handle;
- }
+ VkSubmitInfo submitInfo{};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &commandBuffer;
- VkDeviceSize GetSize() const
- {
- return size;
- }
+ vkQueueSubmit(instance.GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
+ vkQueueWaitIdle(instance.GetGraphicsQueue());
- VkDeviceSize GetPosition(int index) const
- {
- CP_ASSERT(index >= 0 && index < count, "index is outside of the buffer");
- return size * (VkDeviceSize)index;
- }
-
- static void CopyBuffer(Instance& instance, const Buffer& srcBuffer, const Buffer& dstBuffer, VkDeviceSize offset, VkDeviceSize size)
- {
- VkCommandBufferAllocateInfo allocateInfo{};
-
- allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- allocateInfo.commandPool = instance.GetCommandPool();
- allocateInfo.commandBufferCount = 1;
-
- VkCommandBuffer commandBuffer;
- CP_VK_ASSERT(vkAllocateCommandBuffers(instance.GetDevice(), &allocateInfo, &commandBuffer), "Failed to initialize command buffer");
-
- VkCommandBufferBeginInfo beginInfo{};
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
-
- vkBeginCommandBuffer(commandBuffer, &beginInfo);
-
- VkBufferCopy bufferCopy{};
- bufferCopy.dstOffset = offset;
- bufferCopy.srcOffset = 0;
- bufferCopy.size = size;
-
- vkCmdCopyBuffer(commandBuffer, srcBuffer.GetHandle(), dstBuffer.GetHandle(), 1, &bufferCopy);
-
- vkEndCommandBuffer(commandBuffer);
-
- VkSubmitInfo submitInfo{};
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &commandBuffer;
-
- vkQueueSubmit(instance.GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
- vkQueueWaitIdle(instance.GetGraphicsQueue());
-
- vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), 1, &commandBuffer);
- }
-};
+ vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), 1, &commandBuffer);
+ }
+ };
+}
diff --git a/Vulkan/src/CommandBuffer.h b/Vulkan/src/CommandBuffer.h
index 1050e4d..b7aa988 100644
--- a/Vulkan/src/CommandBuffer.h
+++ b/Vulkan/src/CommandBuffer.h
@@ -4,96 +4,99 @@
#include "Instance.h"
#include
-enum class CommandBufferType
+namespace Copium
{
- SingleUse, Dynamic
-};
-
-class CommandBuffer
-{
- CP_DELETE_COPY_AND_MOVE_CTOR(CommandBuffer);
-private:
- Instance& instance;
-
- std::vector commandBuffers;
- const CommandBufferType type;
- VkCommandBuffer currentCommandBuffer{VK_NULL_HANDLE};
-
-public:
- CommandBuffer(Instance& instance, CommandBufferType type)
- : instance{instance}, type{type}
+ class CommandBuffer
{
- if (type == CommandBufferType::Dynamic)
- commandBuffers.resize(instance.GetMaxFramesInFlight());
- else
- commandBuffers.resize(1);
+ CP_DELETE_COPY_AND_MOVE_CTOR(CommandBuffer);
+ public:
+ enum class Type
+ {
+ SingleUse, Dynamic
+ };
+ private:
+ Instance& instance;
- VkCommandBufferAllocateInfo allocateInfo{};
- allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- allocateInfo.commandPool = instance.GetCommandPool();
- allocateInfo.commandBufferCount = commandBuffers.size();
- CP_VK_ASSERT(vkAllocateCommandBuffers(instance.GetDevice(), &allocateInfo, commandBuffers.data()), "Failed to allocate CommandBuffer");
- }
+ std::vector commandBuffers;
+ const Type type;
+ VkCommandBuffer currentCommandBuffer{VK_NULL_HANDLE};
- ~CommandBuffer()
- {
- vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), commandBuffers.size(), commandBuffers.data());
- }
+ public:
+ CommandBuffer(Instance& instance, Type type)
+ : instance{instance}, type{type}
+ {
+ if (type == Type::Dynamic)
+ commandBuffers.resize(instance.GetMaxFramesInFlight());
+ else
+ commandBuffers.resize(1);
- operator VkCommandBuffer() const
- {
- return currentCommandBuffer;
- }
-
- // TODO: Test as constexpr function to see if it avoids the switch case
- void Begin()
- {
- VkCommandBufferBeginInfo beginInfo{};
- beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- beginInfo.flags = 0;
- beginInfo.pInheritanceInfo = nullptr;
- switch(type)
- {
- case CommandBufferType::SingleUse:
- beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- currentCommandBuffer = commandBuffers.front();
- break;
- case CommandBufferType::Dynamic:
- currentCommandBuffer = commandBuffers[instance.GetFlightIndex()];
- break;
- default:
- CP_WARN("Unhandled enum case: %d", (int)type);
+ VkCommandBufferAllocateInfo allocateInfo{};
+ allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ allocateInfo.commandPool = instance.GetCommandPool();
+ allocateInfo.commandBufferCount = commandBuffers.size();
+ CP_VK_ASSERT(vkAllocateCommandBuffers(instance.GetDevice(), &allocateInfo, commandBuffers.data()), "Failed to allocate CommandBuffer");
}
- vkResetCommandBuffer(currentCommandBuffer, 0);
- CP_VK_ASSERT(vkBeginCommandBuffer(currentCommandBuffer, &beginInfo), "Failed to begin command buffer");
- }
+ ~CommandBuffer()
+ {
+ vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), commandBuffers.size(), commandBuffers.data());
+ }
- void End()
- {
- vkEndCommandBuffer(currentCommandBuffer);
- }
+ operator VkCommandBuffer() const
+ {
+ return currentCommandBuffer;
+ }
- void Submit()
- {
- VkSubmitInfo submitInfo{};
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = ¤tCommandBuffer;
+ // TODO: Test as constexpr function to see if it avoids the switch case
+ void Begin()
+ {
+ VkCommandBufferBeginInfo beginInfo{};
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.flags = 0;
+ beginInfo.pInheritanceInfo = nullptr;
+ switch (type)
+ {
+ case Type::SingleUse:
+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ currentCommandBuffer = commandBuffers.front();
+ break;
+ case Type::Dynamic:
+ currentCommandBuffer = commandBuffers[instance.GetFlightIndex()];
+ break;
+ default:
+ CP_WARN("Unhandled enum case: %d", (int)type);
+ }
- vkQueueSubmit(instance.GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
- // TODO: if singleUse?
- vkQueueWaitIdle(instance.GetGraphicsQueue());
- }
+ vkResetCommandBuffer(currentCommandBuffer, 0);
+ CP_VK_ASSERT(vkBeginCommandBuffer(currentCommandBuffer, &beginInfo), "Failed to begin command buffer");
+ }
- void SubmitAsGraphicsQueue()
- {
- instance.SubmitGraphicsQueue({currentCommandBuffer});
- }
+ void End()
+ {
+ vkEndCommandBuffer(currentCommandBuffer);
+ }
- VkCommandBuffer GetHandle() const
- {
- return currentCommandBuffer;
- }
-};
+ void Submit()
+ {
+ VkSubmitInfo submitInfo{};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = ¤tCommandBuffer;
+
+ vkQueueSubmit(instance.GetGraphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE);
+ // TODO: if singleUse?
+ vkQueueWaitIdle(instance.GetGraphicsQueue());
+ }
+
+ void SubmitAsGraphicsQueue()
+ {
+ instance.SubmitGraphicsQueue({currentCommandBuffer});
+ }
+
+ VkCommandBuffer GetHandle() const
+ {
+ return currentCommandBuffer;
+ }
+ };
+}
diff --git a/Vulkan/src/CommandBufferScoped.h b/Vulkan/src/CommandBufferScoped.h
index 7461755..4422404 100644
--- a/Vulkan/src/CommandBufferScoped.h
+++ b/Vulkan/src/CommandBufferScoped.h
@@ -3,19 +3,22 @@
#include "Common.h"
#include "CommandBuffer.h"
-class CommandBufferScoped : public CommandBuffer
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(CommandBufferScoped);
-public:
- CommandBufferScoped(Instance& instance)
- : CommandBuffer{instance, CommandBufferType::SingleUse}
+ class CommandBufferScoped : public CommandBuffer
{
- CommandBuffer::Begin();
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(CommandBufferScoped);
+ public:
+ CommandBufferScoped(Instance& instance)
+ : CommandBuffer{instance, Type::SingleUse}
+ {
+ CommandBuffer::Begin();
+ }
- ~CommandBufferScoped()
- {
- CommandBuffer::End();
- CommandBuffer::Submit();
- }
-};
+ ~CommandBufferScoped()
+ {
+ CommandBuffer::End();
+ CommandBuffer::Submit();
+ }
+ };
+}
diff --git a/Vulkan/src/Common.h b/Vulkan/src/Common.h
index c98a280..7fd0759 100644
--- a/Vulkan/src/Common.h
+++ b/Vulkan/src/Common.h
@@ -3,29 +3,29 @@
#include "VulkanException.h"
#include
-#define TERM_RED "\x1B[31m"
-#define TERM_GREEN "\x1B[32m"
-#define TERM_YELLOW "\x1B[33m"
-#define TERM_GRAY "\x1B[90m"
-#define TERM_CLEAR "\033[0m"
+#define CP_TERM_RED "\x1B[31m"
+#define CP_TERM_GREEN "\x1B[32m"
+#define CP_TERM_YELLOW "\x1B[33m"
+#define CP_TERM_GRAY "\x1B[90m"
+#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_INFO(format, ...) std::cout << "[INF] " << 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_ERR(format, ...) std::cout << TERM_RED << "[ERR] " << 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] " << Copium::StringFormat(format, __VA_ARGS__) << 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 << 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
-#define CP_DEBUG_CONT(format, ...) std::cout << TERM_GRAY << " " << StringFormat(format, __VA_ARGS__) << TERM_CLEAR << std::endl
-#define CP_INFO_CONT(format, ...) std::cout << " " << 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_ERR_CONT(format, ...) std::cout << TERM_RED << " " << 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 << " " << Copium::StringFormat(format, __VA_ARGS__) << 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 << CP_TERM_RED << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl
#define CP_UNIMPLEMENTED() CP_WARN("%s is unimplemented", __FUNCTION__)
#define CP_ABORT(format, ...) \
do \
{ \
CP_ERR(format, __VA_ARGS__); \
- throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \
+ throw std::runtime_error(Copium::StringFormat(format, __VA_ARGS__)); \
} while(false)
#define CP_ASSERT(Function, format, ...) \
do \
@@ -33,7 +33,7 @@
if(!(Function)) \
{ \
CP_ERR(format, __VA_ARGS__); \
- throw std::runtime_error(StringFormat(format, __VA_ARGS__)); \
+ throw std::runtime_error(Copium::StringFormat(format, __VA_ARGS__)); \
} \
} while(false)
#define CP_VK_ASSERT(Function, format, ...) \
@@ -42,7 +42,7 @@
if(Function != VK_SUCCESS) \
{ \
CP_ERR(format, __VA_ARGS__); \
- throw VulkanException(StringFormat(format, __VA_ARGS__)); \
+ throw VulkanException(Copium::StringFormat(format, __VA_ARGS__)); \
} \
} while(false)
#define CP_DELETE_COPY_AND_MOVE_CTOR(ClassName) \
@@ -51,13 +51,15 @@
ClassName& operator=(ClassName&&) = delete; \
ClassName& operator=(const ClassName&) = delete
-template
-std::string StringFormat(const std::string& format, Args... args)
+namespace Copium
{
+ template
+ std::string StringFormat(const std::string& format, Args... args)
+ {
int size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
CP_ASSERT(size > 0, "Error during formatting");
std::unique_ptr buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1);
+ }
}
-
diff --git a/Vulkan/src/DebugMessenger.h b/Vulkan/src/DebugMessenger.h
index 7cb3a54..7ec21b7 100644
--- a/Vulkan/src/DebugMessenger.h
+++ b/Vulkan/src/DebugMessenger.h
@@ -1,88 +1,91 @@
#pragma once
#include "Common.h"
-
-class DebugMessenger
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger);
-public:
- VkInstance instance;
- VkDebugUtilsMessengerEXT debugMessenger;
- DebugMessenger(VkInstance instance)
- : instance{instance}
+ class DebugMessenger
{
-#ifndef NDEBUG
- VkDebugUtilsMessengerCreateInfoEXT createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
- createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
- createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
- createInfo.pfnUserCallback = DebugCallback;
- createInfo.pUserData = nullptr;
- CP_VK_ASSERT(vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger), "Failed to initialze debug messenger");
-#endif
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger);
+ public:
+ VkInstance instance;
+ VkDebugUtilsMessengerEXT debugMessenger;
- ~DebugMessenger()
- {
-#ifndef NDEBUG
- vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
-#endif
- }
-
- static void AddRequiredExtensions(std::vector* extensions)
- {
-#ifndef NDEBUG
- extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
-#endif
- }
-
- static void AddRequiredLayers(std::vector* layers)
- {
-#ifndef NDEBUG
- layers->emplace_back("VK_LAYER_KHRONOS_validation");
-#endif
- }
-
-private:
- static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
- VkDebugUtilsMessageTypeFlagsEXT messageType,
- const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
- void* pUserData)
- {
- if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
+ DebugMessenger(VkInstance instance)
+ : instance{instance}
{
- if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
+ #ifndef NDEBUG
+ VkDebugUtilsMessengerCreateInfoEXT createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ createInfo.pfnUserCallback = DebugCallback;
+ createInfo.pUserData = nullptr;
+ CP_VK_ASSERT(vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger), "Failed to initialze debug messenger");
+ #endif
+ }
+
+ ~DebugMessenger()
+ {
+ #ifndef NDEBUG
+ vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
+ #endif
+ }
+
+ static void AddRequiredExtensions(std::vector* extensions)
+ {
+ #ifndef NDEBUG
+ extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ #endif
+ }
+
+ static void AddRequiredLayers(std::vector* layers)
+ {
+ #ifndef NDEBUG
+ layers->emplace_back("VK_LAYER_KHRONOS_validation");
+ #endif
+ }
+
+ private:
+ static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageType,
+ const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
+ void* pUserData)
+ {
+ if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
{
- CP_ERR(pCallbackData->pMessage);
- throw VulkanException(pCallbackData->pMessage);
+ if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
+ {
+ CP_ERR(pCallbackData->pMessage);
+ throw VulkanException(pCallbackData->pMessage);
+ }
+ CP_WARN(pCallbackData->pMessage);
}
- CP_WARN(pCallbackData->pMessage);
+ return VK_FALSE;
}
- return VK_FALSE;
- }
- static VkResult vkCreateDebugUtilsMessengerEXT(VkInstance instance,
- const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
- const VkAllocationCallbacks* pAllocator,
- VkDebugUtilsMessengerEXT* pDebugMessenger)
- {
- auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
- if (func != nullptr)
- return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
- return VK_ERROR_EXTENSION_NOT_PRESENT;
- }
-
- static void vkDestroyDebugUtilsMessengerEXT(VkInstance instance,
- VkDebugUtilsMessengerEXT debugMessenger,
- const VkAllocationCallbacks* pAllocator) {
- auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
- if (func != nullptr) {
- func(instance, debugMessenger, pAllocator);
+ static VkResult vkCreateDebugUtilsMessengerEXT(VkInstance instance,
+ const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDebugUtilsMessengerEXT* pDebugMessenger)
+ {
+ auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
+ if (func != nullptr)
+ return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
- }
-};
+
+ static void vkDestroyDebugUtilsMessengerEXT(VkInstance instance,
+ VkDebugUtilsMessengerEXT debugMessenger,
+ const VkAllocationCallbacks* pAllocator) {
+ auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
+ if (func != nullptr) {
+ func(instance, debugMessenger, pAllocator);
+ }
+ }
+ };
+}
diff --git a/Vulkan/src/DescriptorPool.h b/Vulkan/src/DescriptorPool.h
index b35c19e..7ae6cbb 100644
--- a/Vulkan/src/DescriptorPool.h
+++ b/Vulkan/src/DescriptorPool.h
@@ -4,58 +4,61 @@
#include "Instance.h"
#include
-class DescriptorPool final
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorPool);
-private:
- Instance& instance;
-
- VkDescriptorPool descriptorPool;
- static const int DESCRIPTOR_SET_COUNT = 100;
-public:
- DescriptorPool(Instance& instance)
- : instance{instance}
+ class DescriptorPool final
{
- std::vector poolSizes{2};
- poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- poolSizes[0].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
+ CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorPool);
+ private:
+ Instance& instance;
- poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
- poolSizes[1].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
+ VkDescriptorPool descriptorPool;
+ static const int DESCRIPTOR_SET_COUNT = 100;
+ public:
+ DescriptorPool(Instance& instance)
+ : instance{instance}
+ {
+ std::vector poolSizes{2};
+ poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ poolSizes[0].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
- VkDescriptorPoolCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
- createInfo.poolSizeCount = poolSizes.size();
- createInfo.pPoolSizes = poolSizes.data();
- createInfo.maxSets = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight();
- createInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+ poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER;
+ poolSizes[1].descriptorCount = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight(); // TODO: how should this actually be determined?
- CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "Failed to initialize descriptor pool");
- }
+ VkDescriptorPoolCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ createInfo.poolSizeCount = poolSizes.size();
+ createInfo.pPoolSizes = poolSizes.data();
+ createInfo.maxSets = DESCRIPTOR_SET_COUNT * instance.GetMaxFramesInFlight();
+ createInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
- ~DescriptorPool()
- {
- vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr);
- }
+ CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "Failed to initialize descriptor pool");
+ }
- std::vector AllocateDescriptorSets(VkDescriptorSetLayout descriptorSetLayout)
- {
- std::vector descriptorSets;
- std::vector layouts{static_cast(instance.GetMaxFramesInFlight()), descriptorSetLayout};
- VkDescriptorSetAllocateInfo allocateInfo{};
- allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- allocateInfo.descriptorPool = descriptorPool;
- allocateInfo.descriptorSetCount = instance.GetMaxFramesInFlight();
- allocateInfo.pSetLayouts = layouts.data();
+ ~DescriptorPool()
+ {
+ vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr);
+ }
- descriptorSets.resize(instance.GetMaxFramesInFlight());
- CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "Failed to allocate descriptor sets");
+ std::vector AllocateDescriptorSets(VkDescriptorSetLayout descriptorSetLayout)
+ {
+ std::vector descriptorSets;
+ std::vector layouts{static_cast(instance.GetMaxFramesInFlight()), descriptorSetLayout};
+ VkDescriptorSetAllocateInfo allocateInfo{};
+ allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ allocateInfo.descriptorPool = descriptorPool;
+ allocateInfo.descriptorSetCount = instance.GetMaxFramesInFlight();
+ allocateInfo.pSetLayouts = layouts.data();
- return descriptorSets;
- }
+ descriptorSets.resize(instance.GetMaxFramesInFlight());
+ CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "Failed to allocate descriptor sets");
- void FreeDescriptorSets(const std::vector& descriptorSets)
- {
- vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data());
- }
-};
+ return descriptorSets;
+ }
+
+ void FreeDescriptorSets(const std::vector& descriptorSets)
+ {
+ vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data());
+ }
+ };
+}
diff --git a/Vulkan/src/DescriptorSet.h b/Vulkan/src/DescriptorSet.h
index 8d12ac7..075157f 100644
--- a/Vulkan/src/DescriptorSet.h
+++ b/Vulkan/src/DescriptorSet.h
@@ -6,67 +6,70 @@
#include "UniformBuffer.h"
#include
-class DescriptorSet final
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet);
-private:
- Instance& instance;
- DescriptorPool& descriptorPool;
- VkDescriptorSetLayout descriptorSetLayout;
-
- std::vector descriptorSets;
-
-public:
- DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout)
- : instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}
+ class DescriptorSet final
{
- descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout);
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(DescriptorSet);
+ private:
+ Instance& instance;
+ DescriptorPool& descriptorPool;
+ VkDescriptorSetLayout descriptorSetLayout;
- ~DescriptorSet()
- {
- descriptorPool.FreeDescriptorSets(descriptorSets);
- }
+ std::vector descriptorSets;
- void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding)
- {
- for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
- VkDescriptorBufferInfo bufferInfo = uniformBuffer.GetDescriptorBufferInfo(i);
-
- VkWriteDescriptorSet descriptorWrite{};
- descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- descriptorWrite.dstSet = descriptorSets[i];
- descriptorWrite.dstBinding = binding;
- descriptorWrite.dstArrayElement = 0;
- descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- descriptorWrite.descriptorCount = 1;
- descriptorWrite.pBufferInfo = &bufferInfo;
- descriptorWrite.pImageInfo = nullptr;
- descriptorWrite.pTexelBufferView = nullptr;
- vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
+ public:
+ DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout)
+ : instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout}
+ {
+ descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout);
}
- }
- void AddTexture2D(const Texture2D& texture2D, uint32_t binding)
- {
- for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
- VkDescriptorImageInfo imageInfo = texture2D.GetDescriptorImageInfo(i);
- VkWriteDescriptorSet descriptorWrite{};
- descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- descriptorWrite.dstSet = descriptorSets[i];
- descriptorWrite.dstBinding = binding;
- descriptorWrite.dstArrayElement = 0;
- descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- descriptorWrite.descriptorCount = 1;
- descriptorWrite.pBufferInfo = nullptr;
- descriptorWrite.pImageInfo = &imageInfo;
- descriptorWrite.pTexelBufferView = nullptr;
- vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
+ ~DescriptorSet()
+ {
+ descriptorPool.FreeDescriptorSets(descriptorSets);
}
- }
- VkDescriptorSet GetHandle() const
- {
- return descriptorSets[instance.GetFlightIndex()];
- }
-};
\ No newline at end of file
+ void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding)
+ {
+ for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
+ VkDescriptorBufferInfo bufferInfo = uniformBuffer.GetDescriptorBufferInfo(i);
+
+ VkWriteDescriptorSet descriptorWrite{};
+ descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descriptorWrite.dstSet = descriptorSets[i];
+ descriptorWrite.dstBinding = binding;
+ descriptorWrite.dstArrayElement = 0;
+ descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descriptorWrite.descriptorCount = 1;
+ descriptorWrite.pBufferInfo = &bufferInfo;
+ descriptorWrite.pImageInfo = nullptr;
+ descriptorWrite.pTexelBufferView = nullptr;
+ vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
+ }
+ }
+
+ void AddTexture2D(const Texture2D& texture2D, uint32_t binding)
+ {
+ for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) {
+ VkDescriptorImageInfo imageInfo = texture2D.GetDescriptorImageInfo(i);
+ VkWriteDescriptorSet descriptorWrite{};
+ descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descriptorWrite.dstSet = descriptorSets[i];
+ descriptorWrite.dstBinding = binding;
+ descriptorWrite.dstArrayElement = 0;
+ descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descriptorWrite.descriptorCount = 1;
+ descriptorWrite.pBufferInfo = nullptr;
+ descriptorWrite.pImageInfo = &imageInfo;
+ descriptorWrite.pTexelBufferView = nullptr;
+ vkUpdateDescriptorSets(instance.GetDevice(), 1, &descriptorWrite, 0, nullptr);
+ }
+ }
+
+ VkDescriptorSet GetHandle() const
+ {
+ return descriptorSets[instance.GetFlightIndex()];
+ }
+ };
+}
\ No newline at end of file
diff --git a/Vulkan/src/FileSystem.h b/Vulkan/src/FileSystem.h
index f5fb64e..305bbdb 100644
--- a/Vulkan/src/FileSystem.h
+++ b/Vulkan/src/FileSystem.h
@@ -8,65 +8,70 @@
#include
-namespace FileSystem
+namespace Copium
{
- static std::vector ReadFile(const std::string& filename)
+ class FileSystem
{
- std::ifstream file(filename, std::ios::ate | std::ios::binary);
- CP_ASSERT(file.is_open(), "Failed to open file");
+ FileSystem() = delete;
+ public:
+ static std::vector ReadFile(const std::string& filename)
+ {
+ std::ifstream file(filename, std::ios::ate | std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
- size_t fileSize = (size_t) file.tellg();
- std::vector buffer(fileSize);
+ size_t fileSize = (size_t)file.tellg();
+ std::vector buffer(fileSize);
- file.seekg(0);
- file.read(buffer.data(), fileSize);
+ file.seekg(0);
+ file.read(buffer.data(), fileSize);
- return buffer;
- }
+ return buffer;
+ }
- static std::string ReadFileStr(const std::string& filename)
- {
- std::ifstream file(filename, std::ios::ate | std::ios::binary);
- CP_ASSERT(file.is_open(), "Failed to open file");
+ static std::string ReadFileStr(const std::string& filename)
+ {
+ std::ifstream file(filename, std::ios::ate | std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
- size_t fileSize = (size_t) file.tellg();
- std::string buffer;
- buffer.resize(fileSize);
+ size_t fileSize = (size_t)file.tellg();
+ std::string buffer;
+ buffer.resize(fileSize);
- file.seekg(0);
- file.read(buffer.data(), fileSize);
+ file.seekg(0);
+ file.read(buffer.data(), fileSize);
- return buffer;
- }
+ return buffer;
+ }
- static void WriteFile(const std::string& filename, const std::string& data)
- {
- std::ofstream file(filename, std::ios::binary);
- CP_ASSERT(file.is_open(), "Failed to open file");
+ static void WriteFile(const std::string& filename, const std::string& data)
+ {
+ std::ofstream file(filename, std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
- file.write(data.c_str(), data.size());
- }
+ file.write(data.c_str(), data.size());
+ }
- static void WriteFile(const std::string& filename, const char* data, size_t size)
- {
- std::filesystem::path path{filename};
- std::filesystem::create_directories(path.parent_path());
- std::ofstream file(filename, std::ios::binary);
- CP_ASSERT(file.is_open(), "Failed to open file");
+ static void WriteFile(const std::string& filename, const char* data, size_t size)
+ {
+ std::filesystem::path path{filename};
+ std::filesystem::create_directories(path.parent_path());
+ std::ofstream file(filename, std::ios::binary);
+ CP_ASSERT(file.is_open(), "Failed to open file");
- file.write(data, size);
- }
+ file.write(data, size);
+ }
- static bool FileExists(const std::string& filename)
- {
- std::ifstream file(filename);
- return file.good();
- }
+ static bool FileExists(const std::string& filename)
+ {
+ std::ifstream file(filename);
+ return file.good();
+ }
- static int64_t DateModified(const std::string& filename)
- {
- struct stat result;
- CP_ASSERT(stat(filename.c_str(), &result) == 0, "Cannot stat file %s", filename.c_str());
- return (int64_t)result.st_mtime;
- }
+ static int64_t DateModified(const std::string& filename)
+ {
+ struct stat result;
+ CP_ASSERT(stat(filename.c_str(), &result) == 0, "Cannot stat file %s", filename.c_str());
+ return (int64_t)result.st_mtime;
+ }
+ };
}
\ No newline at end of file
diff --git a/Vulkan/src/Framebuffer.h b/Vulkan/src/Framebuffer.h
index b9c7a06..f91943f 100644
--- a/Vulkan/src/Framebuffer.h
+++ b/Vulkan/src/Framebuffer.h
@@ -7,168 +7,171 @@
#include
-// TODO: Add resizing (recreate image, depthImage, framebuffers)
-class Framebuffer
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer);
-private:
- Instance& instance;
-
- std::unique_ptr image;
- std::unique_ptr depthImage;
- std::vector framebuffers;
- VkRenderPass renderPass;
-
- uint32_t width;
- uint32_t height;
-public:
- Framebuffer(Instance& instance, uint32_t width, uint32_t height)
- : instance{instance}, width{width}, height{height}
+ // TODO: Add resizing (recreate image, depthImage, framebuffers)
+ class Framebuffer
{
- InitializeImages();
- InitializeDepthBuffer();
- InitializeRenderPass();
- InitializeFramebuffers();
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer);
+ private:
+ Instance& instance;
- ~Framebuffer()
- {
- for (auto& framebuffer : framebuffers)
- vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr);
- vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
- }
+ std::unique_ptr image;
+ std::unique_ptr depthImage;
+ std::vector framebuffers;
+ VkRenderPass renderPass;
- void Bind(const CommandBuffer& commandBuffer)
- {
- std::vector clearValues{2};
- clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
- clearValues[1].depthStencil = {1.0f, 0};
-
- VkRenderPassBeginInfo renderPassBeginInfo{};
- renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- renderPassBeginInfo.renderPass = renderPass;
- renderPassBeginInfo.framebuffer = framebuffers[instance.GetFlightIndex()];
- renderPassBeginInfo.renderArea.offset = {0, 0};
- renderPassBeginInfo.renderArea.extent = {width, height};
- renderPassBeginInfo.clearValueCount = clearValues.size();
- renderPassBeginInfo.pClearValues = clearValues.data();
- vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
- }
-
- void Unbind(const CommandBuffer& commandBuffer)
- {
- vkCmdEndRenderPass(commandBuffer);
- }
-
- VkRenderPass GetRenderPass() const
- {
- return renderPass;
- }
-
- VkFramebuffer GetFramebuffer() const
- {
- return framebuffers[instance.GetFlightIndex()];
- }
-
- const Texture2D& GetTexture2D() const
- {
- return *image;
- }
-
-private:
-
- void InitializeImages()
- {
- image = std::make_unique(instance, width, height, Texture2D::Type::Dynamic, Texture2D::Format::Color);
- }
-
- void InitializeDepthBuffer()
- {
- depthImage = std::make_unique(instance, width, height, Texture2D::Type::Static, Texture2D::Format::Depth);
- }
-
- void InitializeRenderPass()
- {
- VkAttachmentDescription colorAttachment{};
- colorAttachment.format = VK_FORMAT_R8G8B8A8_SRGB;
- colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
- colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
-
- VkAttachmentDescription depthAttachment{};
- depthAttachment.format = Image::SelectDepthFormat(instance);
- depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
- depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
- depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- VkAttachmentReference colorAttachmentRef{};
- colorAttachmentRef.attachment = 0;
- colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
-
- VkAttachmentReference depthAttachmentRef{};
- depthAttachmentRef.attachment = 1;
- depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-
- VkSubpassDescription subpass{};
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.colorAttachmentCount = 1;
- subpass.pColorAttachments = &colorAttachmentRef;
- subpass.pDepthStencilAttachment = &depthAttachmentRef;
-
- std::vector dependencies{2};
- dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
- dependencies[0].dstSubpass = 0;
- dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
- dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- dependencies[1].srcSubpass = 0;
- dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
- dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
-
- std::vector attachments{colorAttachment, depthAttachment};
- VkRenderPassCreateInfo renderPassCreateInfo{};
- renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- renderPassCreateInfo.attachmentCount = attachments.size();
- renderPassCreateInfo.pAttachments = attachments.data();
- renderPassCreateInfo.subpassCount = 1;
- renderPassCreateInfo.pSubpasses = &subpass;
- renderPassCreateInfo.dependencyCount = dependencies.size();
- renderPassCreateInfo.pDependencies = dependencies.data();
-
- CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "InitializeRenderPass : Failed to initialze render pass");
- }
-
- void InitializeFramebuffers()
- {
- framebuffers.resize(instance.GetMaxFramesInFlight());
-
- for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i)
+ uint32_t width;
+ uint32_t height;
+ public:
+ Framebuffer(Instance& instance, uint32_t width, uint32_t height)
+ : instance{instance}, width{width}, height{height}
{
- std::vector attachments{image->GetImageView(i), depthImage->GetImageView()};
-
- VkFramebufferCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- createInfo.renderPass = renderPass;
- createInfo.attachmentCount = attachments.size();
- createInfo.pAttachments = attachments.data();
- createInfo.width = width;
- createInfo.height = height;
- createInfo.layers = 1;
-
- CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer");
+ InitializeImages();
+ InitializeDepthBuffer();
+ InitializeRenderPass();
+ InitializeFramebuffers();
}
- }
-};
\ No newline at end of file
+
+ ~Framebuffer()
+ {
+ for (auto& framebuffer : framebuffers)
+ vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr);
+ vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr);
+ }
+
+ void Bind(const CommandBuffer& commandBuffer)
+ {
+ std::vector clearValues{2};
+ clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}};
+ clearValues[1].depthStencil = {1.0f, 0};
+
+ VkRenderPassBeginInfo renderPassBeginInfo{};
+ renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ renderPassBeginInfo.renderPass = renderPass;
+ renderPassBeginInfo.framebuffer = framebuffers[instance.GetFlightIndex()];
+ renderPassBeginInfo.renderArea.offset = {0, 0};
+ renderPassBeginInfo.renderArea.extent = {width, height};
+ renderPassBeginInfo.clearValueCount = clearValues.size();
+ renderPassBeginInfo.pClearValues = clearValues.data();
+ vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ void Unbind(const CommandBuffer& commandBuffer)
+ {
+ vkCmdEndRenderPass(commandBuffer);
+ }
+
+ VkRenderPass GetRenderPass() const
+ {
+ return renderPass;
+ }
+
+ VkFramebuffer GetFramebuffer() const
+ {
+ return framebuffers[instance.GetFlightIndex()];
+ }
+
+ const Texture2D& GetTexture2D() const
+ {
+ return *image;
+ }
+
+ private:
+
+ void InitializeImages()
+ {
+ image = std::make_unique(instance, width, height, Texture2D::Type::Dynamic, Texture2D::Format::Color);
+ }
+
+ void InitializeDepthBuffer()
+ {
+ depthImage = std::make_unique(instance, width, height, Texture2D::Type::Static, Texture2D::Format::Depth);
+ }
+
+ void InitializeRenderPass()
+ {
+ VkAttachmentDescription colorAttachment{};
+ colorAttachment.format = VK_FORMAT_R8G8B8A8_SRGB;
+ colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ colorAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ VkAttachmentDescription depthAttachment{};
+ depthAttachment.format = Image::SelectDepthFormat(instance);
+ depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference colorAttachmentRef{};
+ colorAttachmentRef.attachment = 0;
+ colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference depthAttachmentRef{};
+ depthAttachmentRef.attachment = 1;
+ depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription subpass{};
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &colorAttachmentRef;
+ subpass.pDepthStencilAttachment = &depthAttachmentRef;
+
+ std::vector dependencies{2};
+ dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependencies[0].dstSubpass = 0;
+ dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ dependencies[1].srcSubpass = 0;
+ dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
+ dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ std::vector attachments{colorAttachment, depthAttachment};
+ VkRenderPassCreateInfo renderPassCreateInfo{};
+ renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ renderPassCreateInfo.attachmentCount = attachments.size();
+ renderPassCreateInfo.pAttachments = attachments.data();
+ renderPassCreateInfo.subpassCount = 1;
+ renderPassCreateInfo.pSubpasses = &subpass;
+ renderPassCreateInfo.dependencyCount = dependencies.size();
+ renderPassCreateInfo.pDependencies = dependencies.data();
+
+ CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "InitializeRenderPass : Failed to initialze render pass");
+ }
+
+ void InitializeFramebuffers()
+ {
+ framebuffers.resize(instance.GetMaxFramesInFlight());
+
+ for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i)
+ {
+ std::vector attachments{image->GetImageView(i), depthImage->GetImageView()};
+
+ VkFramebufferCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ createInfo.renderPass = renderPass;
+ createInfo.attachmentCount = attachments.size();
+ createInfo.pAttachments = attachments.data();
+ createInfo.width = width;
+ createInfo.height = height;
+ createInfo.layers = 1;
+
+ CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "InitializeFramebuffers : Failed to initialize swap chain framebuffer");
+ }
+ }
+ };
+}
\ No newline at end of file
diff --git a/Vulkan/src/Image.h b/Vulkan/src/Image.h
index a4a9963..1aa669e 100644
--- a/Vulkan/src/Image.h
+++ b/Vulkan/src/Image.h
@@ -6,177 +6,182 @@
#include "CommandBufferScoped.h"
#include "Instance.h"
-class Image
+namespace Copium
{
- Image() = delete;
-public:
- static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory)
+ class Image
{
- VkImageCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- createInfo.imageType = VK_IMAGE_TYPE_2D;
- createInfo.extent.width = width;
- createInfo.extent.height = height;
- createInfo.extent.depth = 1;
- createInfo.mipLevels = 1;
- createInfo.arrayLayers = 1;
- createInfo.format = format;
- createInfo.tiling = tiling;
- createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- createInfo.usage = usage;
- createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
- createInfo.flags = 0;
-
- CP_VK_ASSERT(vkCreateImage(instance.GetDevice(), &createInfo, nullptr, image), "InitializeImage : Failed to initialize image");
-
- VkMemoryRequirements memoryRequirements;
- vkGetImageMemoryRequirements(instance.GetDevice(), *image, &memoryRequirements);
-
- VkMemoryAllocateInfo allocateInfo{};
- allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- allocateInfo.allocationSize = memoryRequirements.size;
- allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties);
-
- CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, imageMemory), "InitializeImage : Failed to initiallizse image memory");
-
- vkBindImageMemory(instance.GetDevice(), *image, *imageMemory, 0);
- }
-
- static VkImageView InitializeImageView(Instance& instance, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
- {
- VkImageView imageView;
- VkImageViewCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- createInfo.image = image;
- createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- createInfo.format = format;
- createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
- createInfo.subresourceRange.aspectMask = aspectFlags;
- createInfo.subresourceRange.baseMipLevel = 0;
- createInfo.subresourceRange.levelCount = 1;
- createInfo.subresourceRange.baseArrayLayer = 0;
- createInfo.subresourceRange.layerCount = 1;
- CP_VK_ASSERT(vkCreateImageView(instance.GetDevice(), &createInfo, nullptr, &imageView), "InitializeImageView : Failed to initialize image view");
- return imageView;
- }
-
- static void TransitionImageLayout(Instance& instance, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
- {
- CommandBufferScoped commandBuffer{instance};
-
- VkImageMemoryBarrier barrier{};
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.oldLayout = oldLayout;
- barrier.newLayout = newLayout;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.image = image;
- barrier.subresourceRange.baseMipLevel = 0;
- barrier.subresourceRange.levelCount = 1;
- barrier.subresourceRange.baseArrayLayer = 0;
- barrier.subresourceRange.layerCount = 1;
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = 0;
-
- VkPipelineStageFlags srcStage;
- VkPipelineStageFlags dstStage;
-
- if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
-
- if (HasStencilComponent(format)) {
- barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- } else {
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- }
-
- if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
-
- srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
- } 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.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
-
- srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
- dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- }
- else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
-
- srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
- }
- else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
- barrier.srcAccessMask = 0;
- barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- }
- else
+ Image() = delete;
+ public:
+ static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory)
{
- CP_ABORT("TransitioinImageLayout : Unsupported layout transition");
+ VkImageCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ createInfo.imageType = VK_IMAGE_TYPE_2D;
+ createInfo.extent.width = width;
+ createInfo.extent.height = height;
+ createInfo.extent.depth = 1;
+ createInfo.mipLevels = 1;
+ createInfo.arrayLayers = 1;
+ createInfo.format = format;
+ createInfo.tiling = tiling;
+ createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ createInfo.usage = usage;
+ createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ createInfo.flags = 0;
+
+ CP_VK_ASSERT(vkCreateImage(instance.GetDevice(), &createInfo, nullptr, image), "InitializeImage : Failed to initialize image");
+
+ VkMemoryRequirements memoryRequirements;
+ vkGetImageMemoryRequirements(instance.GetDevice(), *image, &memoryRequirements);
+
+ VkMemoryAllocateInfo allocateInfo{};
+ allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocateInfo.allocationSize = memoryRequirements.size;
+ allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties);
+
+ CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, imageMemory), "InitializeImage : Failed to initiallizse image memory");
+
+ vkBindImageMemory(instance.GetDevice(), *image, *imageMemory, 0);
}
- vkCmdPipelineBarrier(commandBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
- }
-
- static void CopyBufferToImage(Instance& instance, const Buffer& buffer, VkImage image, uint32_t width, uint32_t height)
- {
- CommandBufferScoped commandBuffer{instance};
-
- VkBufferImageCopy region{};
- region.bufferOffset = 0;
- region.bufferRowLength = 0;
- region.bufferImageHeight = 0;
-
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.mipLevel = 0;
- region.imageSubresource.baseArrayLayer = 0;
- region.imageSubresource.layerCount = 1;
-
- region.imageOffset = {0, 0, 0};
- region.imageExtent = {width, height, 1};
-
- vkCmdCopyBufferToImage(commandBuffer, buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
- }
-
-
- static VkFormat SelectDepthFormat(Instance& instance)
- {
- 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:
- static bool HasStencilComponent(VkFormat format)
- {
- return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
- }
-
- static VkFormat SelectSupportedFormat(Instance& instance, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
- {
- for (VkFormat format : candidates)
+ static VkImageView InitializeImageView(Instance& instance, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
{
- VkFormatProperties properties;
- vkGetPhysicalDeviceFormatProperties(instance.GetPhysicalDevice(), format, &properties);
- if(tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features)
- {
- return format;
- }
- else if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features)
- {
- return format;
- }
+ VkImageView imageView;
+ VkImageViewCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ createInfo.image = image;
+ createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ createInfo.format = format;
+ createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+ createInfo.subresourceRange.aspectMask = aspectFlags;
+ createInfo.subresourceRange.baseMipLevel = 0;
+ createInfo.subresourceRange.levelCount = 1;
+ createInfo.subresourceRange.baseArrayLayer = 0;
+ createInfo.subresourceRange.layerCount = 1;
+ CP_VK_ASSERT(vkCreateImageView(instance.GetDevice(), &createInfo, nullptr, &imageView), "InitializeImageView : Failed to initialize image view");
+ return imageView;
}
- CP_ABORT("SelectSupportedFormat : Failed to select supported format");
- }
-};
\ No newline at end of file
+
+ static void TransitionImageLayout(Instance& instance, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout)
+ {
+ CommandBufferScoped commandBuffer{instance};
+
+ VkImageMemoryBarrier barrier{};
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.oldLayout = oldLayout;
+ barrier.newLayout = newLayout;
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.image = image;
+ barrier.subresourceRange.baseMipLevel = 0;
+ barrier.subresourceRange.levelCount = 1;
+ barrier.subresourceRange.baseArrayLayer = 0;
+ barrier.subresourceRange.layerCount = 1;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = 0;
+
+ VkPipelineStageFlags srcStage;
+ VkPipelineStageFlags dstStage;
+
+ if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+
+ if (HasStencilComponent(format)) {
+ barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ }
+ }
+ else {
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+
+ if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ }
+ 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.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+ dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ }
+ else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dstStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
+ }
+ else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ }
+ else
+ {
+ CP_ABORT("TransitioinImageLayout : Unsupported layout transition");
+ }
+
+ vkCmdPipelineBarrier(commandBuffer, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
+ }
+
+ static void CopyBufferToImage(Instance& instance, const Buffer& buffer, VkImage image, uint32_t width, uint32_t height)
+ {
+ CommandBufferScoped commandBuffer{instance};
+
+ VkBufferImageCopy region{};
+ region.bufferOffset = 0;
+ region.bufferRowLength = 0;
+ region.bufferImageHeight = 0;
+
+ region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.imageSubresource.mipLevel = 0;
+ region.imageSubresource.baseArrayLayer = 0;
+ region.imageSubresource.layerCount = 1;
+
+ region.imageOffset = {0, 0, 0};
+ region.imageExtent = {width, height, 1};
+
+ vkCmdCopyBufferToImage(commandBuffer, buffer.GetHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ }
+
+
+ static VkFormat SelectDepthFormat(Instance& instance)
+ {
+ 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:
+ static bool HasStencilComponent(VkFormat format)
+ {
+ return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
+ }
+
+ static VkFormat SelectSupportedFormat(Instance& instance, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features)
+ {
+ for (VkFormat format : candidates)
+ {
+ VkFormatProperties properties;
+ vkGetPhysicalDeviceFormatProperties(instance.GetPhysicalDevice(), format, &properties);
+ if (tiling == VK_IMAGE_TILING_LINEAR && (properties.linearTilingFeatures & features) == features)
+ {
+ return format;
+ }
+ else if (tiling == VK_IMAGE_TILING_OPTIMAL && (properties.optimalTilingFeatures & features) == features)
+ {
+ return format;
+ }
+ }
+ CP_ABORT("SelectSupportedFormat : Failed to select supported format");
+ }
+ };
+}
\ No newline at end of file
diff --git a/Vulkan/src/IndexBuffer.h b/Vulkan/src/IndexBuffer.h
index b626cb4..0fcbced 100644
--- a/Vulkan/src/IndexBuffer.h
+++ b/Vulkan/src/IndexBuffer.h
@@ -2,23 +2,26 @@
#include "Buffer.h"
-class IndexBuffer : public Buffer
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(IndexBuffer);
-private:
- int indexCount;
-public:
- 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}
- {}
-
- void Bind(const CommandBuffer& commandBuffer) override
+ class IndexBuffer : public Buffer
{
- vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16);
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(IndexBuffer);
+ private:
+ int indexCount;
+ public:
+ 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}
+ {}
- void Draw(const CommandBuffer& commandBuffer)
- {
- vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
- }
-};
\ No newline at end of file
+ void Bind(const CommandBuffer& commandBuffer) override
+ {
+ vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16);
+ }
+
+ void Draw(const CommandBuffer& commandBuffer)
+ {
+ vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0);
+ }
+ };
+}
\ No newline at end of file
diff --git a/Vulkan/src/Instance.h b/Vulkan/src/Instance.h
index 177693c..4c5dd34 100644
--- a/Vulkan/src/Instance.h
+++ b/Vulkan/src/Instance.h
@@ -9,439 +9,442 @@
#include "SwapChain.h"
#include "Timer.h"
-class Instance final
+namespace Copium
{
- CP_DELETE_COPY_AND_MOVE_CTOR(Instance);
-private:
- static const int MAX_FRAMES_IN_FLIGHT = 2;
- static const int WINDOW_WIDTH = 1920;
- static const int WINDOW_HEIGHT = 1080;
-
- VkInstance instance;
- GLFWwindow* window;
- VkSurfaceKHR surface;
- std::unique_ptr debugMessenger;
- VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
- VkDevice device;
- uint32_t graphicsQueueIndex;
- uint32_t presentQueueIndex;
- VkQueue graphicsQueue;
- VkQueue presentQueue;
- std::unique_ptr swapChain;
- int flightIndex;
- std::vector imageAvailableSemaphores;
- std::vector renderFinishedSemaphores;
- std::vector inFlightFences;
- VkCommandPool commandPool;
- bool framebufferResized = false;
-
- int frameCount = 0;
- Timer timer;
-
-public:
- Instance(const std::string& applicationName)
+ class Instance final
{
- timer.Start();
- InitializeWindow(applicationName);
- InitializeInstance(applicationName);
- InitializeDebugMessenger();
- InitializeSurface();
- SelectPhysicalDevice();
- InitializeLogicalDevice();
- InitializeCommandPool();
- InitializeSwapChain();
- InitializeSyncObjects();
- CP_INFO("Initialized Vulkan in %f seconds", timer.Elapsed());
- }
+ CP_DELETE_COPY_AND_MOVE_CTOR(Instance);
+ private:
+ static const int MAX_FRAMES_IN_FLIGHT = 2;
+ static const int WINDOW_WIDTH = 1920;
+ static const int WINDOW_HEIGHT = 1080;
- ~Instance()
- {
- for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
+ VkInstance instance;
+ GLFWwindow* window;
+ VkSurfaceKHR surface;
+ std::unique_ptr debugMessenger;
+ VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
+ VkDevice device;
+ uint32_t graphicsQueueIndex;
+ uint32_t presentQueueIndex;
+ VkQueue graphicsQueue;
+ VkQueue presentQueue;
+ std::unique_ptr swapChain;
+ int flightIndex;
+ std::vector imageAvailableSemaphores;
+ std::vector renderFinishedSemaphores;
+ std::vector inFlightFences;
+ VkCommandPool commandPool;
+ bool framebufferResized = false;
+
+ int frameCount = 0;
+ Timer timer;
+
+ public:
+ Instance(const std::string& applicationName)
{
- vkDestroyFence(device, inFlightFences[i], nullptr);
- vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
- vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
+ timer.Start();
+ InitializeWindow(applicationName);
+ InitializeInstance(applicationName);
+ InitializeDebugMessenger();
+ InitializeSurface();
+ SelectPhysicalDevice();
+ InitializeLogicalDevice();
+ InitializeCommandPool();
+ InitializeSwapChain();
+ InitializeSyncObjects();
+ CP_INFO("Initialized Vulkan in %f seconds", timer.Elapsed());
}
- vkDestroyCommandPool(device, commandPool, nullptr);
- swapChain.reset();
- vkDestroyDevice(device, nullptr);
- vkDestroySurfaceKHR(instance, surface, nullptr);
- debugMessenger.reset();
- vkDestroyInstance(instance, nullptr);
- glfwDestroyWindow(window);
- }
- bool BeginPresent()
- {
- vkWaitForFences(device, 1, &inFlightFences[flightIndex], VK_TRUE, UINT64_MAX);
-
- if (!swapChain->BeginPresent(imageAvailableSemaphores[flightIndex]))
- return false;
-
- vkResetFences(device, 1, &inFlightFences[flightIndex]);
- return true;
- }
-
- bool EndPresent()
- {
- swapChain->EndPresent(presentQueue, &renderFinishedSemaphores[flightIndex], framebufferResized);
-
- framebufferResized = false;
- flightIndex = (flightIndex + 1) % MAX_FRAMES_IN_FLIGHT;
- return !glfwWindowShouldClose(window);
- }
-
- void SubmitGraphicsQueue(const std::vector& commandBuffers)
- {
- VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
- VkSubmitInfo submitInfo{};
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 1;
- submitInfo.pWaitSemaphores = &imageAvailableSemaphores[flightIndex];
- submitInfo.pWaitDstStageMask = waitStages;
- submitInfo.commandBufferCount = commandBuffers.size();
- submitInfo.pCommandBuffers = commandBuffers.data();
- submitInfo.signalSemaphoreCount = 1;
- submitInfo.pSignalSemaphores = &renderFinishedSemaphores[flightIndex];
-
- CP_VK_ASSERT(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[flightIndex]), "Failed to submit command buffer");
- }
-
- VkInstance GetInstance() const
- {
- return instance;
- }
-
- GLFWwindow* GetWindow() const
- {
- return window;
- }
-
- VkSurfaceKHR GetSurface() const
- {
- return surface;
- }
-
- VkPhysicalDevice GetPhysicalDevice() const
- {
- return physicalDevice;
- }
-
- VkDevice GetDevice() const
- {
- return device;
- }
-
- VkCommandPool GetCommandPool() const
- {
- return commandPool;
- }
-
- VkQueue GetGraphicsQueue() const
- {
- return graphicsQueue;
- }
-
- int GetFlightIndex() const
- {
- return flightIndex;
- }
-
- int GetMaxFramesInFlight() const
- {
- return MAX_FRAMES_IN_FLIGHT;
- }
-
- const SwapChain& GetSwapChain() const
- {
- return *swapChain;
- }
-
- // TODO: Create Device class and move this there
- uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
- {
- VkPhysicalDeviceMemoryProperties memoryProperties;
- vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
- for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
+ ~Instance()
{
- if ((typeFilter & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
- return i;
+ for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
+ {
+ vkDestroyFence(device, inFlightFences[i], nullptr);
+ vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr);
+ vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr);
+ }
+ vkDestroyCommandPool(device, commandPool, nullptr);
+ swapChain.reset();
+ vkDestroyDevice(device, nullptr);
+ vkDestroySurfaceKHR(instance, surface, nullptr);
+ debugMessenger.reset();
+ vkDestroyInstance(instance, nullptr);
+ glfwDestroyWindow(window);
}
- throw std::runtime_error("Failed to find suitable memory type");
- }
-private:
- void InitializeWindow(const std::string& applicationName)
- {
- glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
-
+ bool BeginPresent()
+ {
+ vkWaitForFences(device, 1, &inFlightFences[flightIndex], VK_TRUE, UINT64_MAX);
+
+ if (!swapChain->BeginPresent(imageAvailableSemaphores[flightIndex]))
+ return false;
+
+ vkResetFences(device, 1, &inFlightFences[flightIndex]);
+ return true;
+ }
+
+ bool EndPresent()
+ {
+ swapChain->EndPresent(presentQueue, &renderFinishedSemaphores[flightIndex], framebufferResized);
+
+ framebufferResized = false;
+ flightIndex = (flightIndex + 1) % MAX_FRAMES_IN_FLIGHT;
+ return !glfwWindowShouldClose(window);
+ }
+
+ void SubmitGraphicsQueue(const std::vector& commandBuffers)
+ {
+ VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
+ VkSubmitInfo submitInfo{};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = &imageAvailableSemaphores[flightIndex];
+ submitInfo.pWaitDstStageMask = waitStages;
+ submitInfo.commandBufferCount = commandBuffers.size();
+ submitInfo.pCommandBuffers = commandBuffers.data();
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = &renderFinishedSemaphores[flightIndex];
+
+ CP_VK_ASSERT(vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[flightIndex]), "Failed to submit command buffer");
+ }
+
+ VkInstance GetInstance() const
+ {
+ return instance;
+ }
+
+ GLFWwindow* GetWindow() const
+ {
+ return window;
+ }
+
+ VkSurfaceKHR GetSurface() const
+ {
+ return surface;
+ }
+
+ VkPhysicalDevice GetPhysicalDevice() const
+ {
+ return physicalDevice;
+ }
+
+ VkDevice GetDevice() const
+ {
+ return device;
+ }
+
+ VkCommandPool GetCommandPool() const
+ {
+ return commandPool;
+ }
+
+ VkQueue GetGraphicsQueue() const
+ {
+ return graphicsQueue;
+ }
+
+ int GetFlightIndex() const
+ {
+ return flightIndex;
+ }
+
+ int GetMaxFramesInFlight() const
+ {
+ return MAX_FRAMES_IN_FLIGHT;
+ }
+
+ const SwapChain& GetSwapChain() const
+ {
+ return *swapChain;
+ }
+
+ // TODO: Create Device class and move this there
+ uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
+ {
+ VkPhysicalDeviceMemoryProperties memoryProperties;
+ vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
+ for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i)
+ {
+ if ((typeFilter & (1 << i)) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
+ return i;
+ }
+ throw std::runtime_error("Failed to find suitable memory type");
+ }
+
+ private:
+ void InitializeWindow(const std::string& applicationName)
+ {
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+
#if defined(FULLSCREEN)
- GLFWmonitor* monitor = glfwGetPrimaryMonitor();
- const GLFWvidmode* mode = glfwGetVideoMode(monitor);
- window = glfwCreateWindow(mode->width, mode->height, applicationName.c_str(), glfwGetPrimaryMonitor(), nullptr);
+ GLFWmonitor* monitor = glfwGetPrimaryMonitor();
+ const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+ window = glfwCreateWindow(mode->width, mode->height, applicationName.c_str(), glfwGetPrimaryMonitor(), nullptr);
#elif defined(BORDERLESS_WINDOWED)
- GLFWmonitor* monitor = glfwGetPrimaryMonitor();
- const GLFWvidmode* mode = glfwGetVideoMode(monitor);
- window = glfwCreateWindow(mode->width, mode->height, applicationName.c_str(), nullptr, nullptr);
- glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
+ GLFWmonitor* monitor = glfwGetPrimaryMonitor();
+ const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+ window = glfwCreateWindow(mode->width, mode->height, applicationName.c_str(), nullptr, nullptr);
+ glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
#else
- window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, applicationName.c_str(), nullptr, nullptr);
+ window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, applicationName.c_str(), nullptr, nullptr);
#endif
- CP_ASSERT(window, "Failed to initialize glfw window");
+ CP_ASSERT(window, "Failed to initialize glfw window");
- glfwSetWindowUserPointer(window, this);
- glfwSetFramebufferSizeCallback(window, FramebufferResizeCallback);
- }
-
- void InitializeInstance(const std::string& applicationName)
- {
- VkApplicationInfo appInfo{};
- appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- appInfo.pApplicationName = applicationName.c_str();
- appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
- appInfo.pEngineName = "Copium Engine";
- appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
- appInfo.apiVersion = VK_API_VERSION_1_1;
-
- std::vector requiredExtensions = GetRequiredExtensions();
-
- uint32_t extensionCount;
- vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
- std::vector extensions{extensionCount};
- vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
-
- CP_INFO("Supported Extensions:");
- for (auto&& extension : extensions)
- {
- CP_INFO_CONT("\t%s", extension.extensionName);
+ glfwSetWindowUserPointer(window, this);
+ glfwSetFramebufferSizeCallback(window, FramebufferResizeCallback);
}
- std::vector layers{};
- DebugMessenger::AddRequiredLayers(&layers);
- CP_ASSERT(CheckLayerSupport(layers), "Some required layers are not supported");
-
- VkInstanceCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- createInfo.pApplicationInfo = &appInfo;
- createInfo.enabledExtensionCount = requiredExtensions.size();
- createInfo.ppEnabledExtensionNames = requiredExtensions.data();
- createInfo.enabledLayerCount = layers.size();
- createInfo.ppEnabledLayerNames = layers.data();
- CP_VK_ASSERT(vkCreateInstance(&createInfo, nullptr, &instance), "Failed to create instance");
- }
-
- void InitializeDebugMessenger()
- {
- debugMessenger = std::make_unique(instance);
- }
-
- void InitializeSurface()
- {
- CP_VK_ASSERT(glfwCreateWindowSurface(instance, window, nullptr, &surface), "Failed to create Vulkan surface");
- }
-
- void SelectPhysicalDevice()
- {
- uint32_t deviceCount;
- vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
- CP_ASSERT(deviceCount != 0, "No available devices support Vulkan");
-
- std::vector devices(deviceCount);
- vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
- CP_INFO("Available devices:");
- for (auto&& device : devices)
+ void InitializeInstance(const std::string& applicationName)
{
- VkPhysicalDeviceProperties deviceProperties;
- vkGetPhysicalDeviceProperties(device, &deviceProperties);
- CP_INFO_CONT("\t%s", deviceProperties.deviceName);
+ VkApplicationInfo appInfo{};
+ appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ appInfo.pApplicationName = applicationName.c_str();
+ appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
+ appInfo.pEngineName = "Copium Engine";
+ appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
+ appInfo.apiVersion = VK_API_VERSION_1_1;
+
+ std::vector requiredExtensions = GetRequiredExtensions();
+
+ uint32_t extensionCount;
+ vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
+ std::vector extensions{extensionCount};
+ vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
+
+ CP_INFO("Supported Extensions:");
+ for (auto&& extension : extensions)
+ {
+ CP_INFO_CONT("\t%s", extension.extensionName);
+ }
+
+ std::vector layers{};
+ DebugMessenger::AddRequiredLayers(&layers);
+ CP_ASSERT(CheckLayerSupport(layers), "Some required layers are not supported");
+
+ VkInstanceCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ createInfo.pApplicationInfo = &appInfo;
+ createInfo.enabledExtensionCount = requiredExtensions.size();
+ createInfo.ppEnabledExtensionNames = requiredExtensions.data();
+ createInfo.enabledLayerCount = layers.size();
+ createInfo.ppEnabledLayerNames = layers.data();
+ CP_VK_ASSERT(vkCreateInstance(&createInfo, nullptr, &instance), "Failed to create instance");
}
- for (auto&& device : devices)
+
+ void InitializeDebugMessenger()
{
- if (IsPhysicalDeviceSuitable(device))
+ debugMessenger = std::make_unique(instance);
+ }
+
+ void InitializeSurface()
+ {
+ CP_VK_ASSERT(glfwCreateWindowSurface(instance, window, nullptr, &surface), "Failed to create Vulkan surface");
+ }
+
+ void SelectPhysicalDevice()
+ {
+ uint32_t deviceCount;
+ vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
+ CP_ASSERT(deviceCount != 0, "No available devices support Vulkan");
+
+ std::vector devices(deviceCount);
+ vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
+ CP_INFO("Available devices:");
+ for (auto&& device : devices)
{
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
- physicalDevice = device;
- CP_INFO("Selecting device: %s", deviceProperties.deviceName);
- break;
+ CP_INFO_CONT("\t%s", deviceProperties.deviceName);
+ }
+ for (auto&& device : devices)
+ {
+ if (IsPhysicalDeviceSuitable(device))
+ {
+ VkPhysicalDeviceProperties deviceProperties;
+ vkGetPhysicalDeviceProperties(device, &deviceProperties);
+ physicalDevice = device;
+ CP_INFO("Selecting device: %s", deviceProperties.deviceName);
+ break;
+ }
+ }
+ CP_ASSERT(physicalDevice != VK_NULL_HANDLE, "Failed to find suitable GPU");
+ }
+
+ void InitializeLogicalDevice()
+ {
+ QueueFamiliesQuery query{surface, physicalDevice};
+
+ float queuePriority = 1.0f;
+
+ std::vector queueCreateInfos{};
+ std::set uniqueQueueFamilies{query.graphicsFamily.value(), query.presentFamily.value()};
+ for (auto&& queueFamily : uniqueQueueFamilies)
+ {
+ VkDeviceQueueCreateInfo queueCreateInfo{};
+ queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueCreateInfo.queueFamilyIndex = queueFamily;
+ queueCreateInfo.queueCount = 1;
+ queueCreateInfo.pQueuePriorities = &queuePriority;
+ queueCreateInfos.emplace_back(queueCreateInfo);
+ }
+ std::vector deviceExtensions = GetRequiredDeviceExtensions();
+ VkPhysicalDeviceFeatures deviceFeatures{};
+ deviceFeatures.fillModeNonSolid = VK_TRUE;
+ deviceFeatures.samplerAnisotropy = VK_TRUE;
+ VkDeviceCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ createInfo.pQueueCreateInfos = queueCreateInfos.data();
+ createInfo.queueCreateInfoCount = queueCreateInfos.size();
+ createInfo.pEnabledFeatures = &deviceFeatures;
+ createInfo.ppEnabledExtensionNames = deviceExtensions.data();
+ createInfo.enabledExtensionCount = deviceExtensions.size();
+
+ CP_VK_ASSERT(vkCreateDevice(physicalDevice, &createInfo, nullptr, &device), "Failed to initialize logical device");
+
+ graphicsQueueIndex = query.graphicsFamily.value();
+ presentQueueIndex = query.presentFamily.value();
+ vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue);
+ vkGetDeviceQueue(device, presentQueueIndex, 0, &presentQueue);
+ }
+
+ void InitializeSwapChain()
+ {
+ swapChain = std::make_unique(*this);
+ }
+
+ void InitializeCommandPool()
+ {
+ VkCommandPoolCreateInfo createInfo{};
+ createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ createInfo.queueFamilyIndex = graphicsQueueIndex;
+ CP_VK_ASSERT(vkCreateCommandPool(device, &createInfo, nullptr, &commandPool), "Failed to initialize command pool");
+ }
+
+ void InitializeSyncObjects()
+ {
+ imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
+ renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
+ inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
+ VkSemaphoreCreateInfo semaphoreCreateInfo{};
+ semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
+ {
+ CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &imageAvailableSemaphores[i]), "Failed to initialize available image semaphore");
+ CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]), "Failed to initialize render finished semaphore");
+
+ VkFenceCreateInfo fenceCreateInfo{};
+ fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ CP_VK_ASSERT(vkCreateFence(device, &fenceCreateInfo, nullptr, &inFlightFences[i]), "Failed to initialize in flight fence");
}
}
- CP_ASSERT(physicalDevice != VK_NULL_HANDLE, "Failed to find suitable GPU");
- }
- void InitializeLogicalDevice()
- {
- QueueFamiliesQuery query{surface, physicalDevice};
-
- float queuePriority = 1.0f;
-
- std::vector queueCreateInfos{};
- std::set uniqueQueueFamilies{query.graphicsFamily.value(), query.presentFamily.value()};
- for(auto&& queueFamily : uniqueQueueFamilies)
+ std::vector GetRequiredExtensions()
{
- VkDeviceQueueCreateInfo queueCreateInfo{};
- queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- queueCreateInfo.queueFamilyIndex = queueFamily;
- queueCreateInfo.queueCount = 1;
- queueCreateInfo.pQueuePriorities = &queuePriority;
- queueCreateInfos.emplace_back(queueCreateInfo);
- }
- std::vector deviceExtensions = GetRequiredDeviceExtensions();
- VkPhysicalDeviceFeatures deviceFeatures{};
- deviceFeatures.fillModeNonSolid = VK_TRUE;
- deviceFeatures.samplerAnisotropy = VK_TRUE;
- VkDeviceCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- createInfo.pQueueCreateInfos = queueCreateInfos.data();
- createInfo.queueCreateInfoCount = queueCreateInfos.size();
- createInfo.pEnabledFeatures = &deviceFeatures;
- createInfo.ppEnabledExtensionNames = deviceExtensions.data();
- createInfo.enabledExtensionCount = deviceExtensions.size();
+ uint32_t glfwExtensionCount;
+ const char** glfwExtensions;
+ glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
- CP_VK_ASSERT(vkCreateDevice(physicalDevice, &createInfo, nullptr, &device), "Failed to initialize logical device");
+ std::vector extensions{glfwExtensions, glfwExtensions + glfwExtensionCount};
- graphicsQueueIndex = query.graphicsFamily.value();
- presentQueueIndex = query.presentFamily.value();
- vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue);
- vkGetDeviceQueue(device, presentQueueIndex , 0, &presentQueue);
- }
+ debugMessenger->AddRequiredExtensions(&extensions);
- void InitializeSwapChain()
- {
- swapChain = std::make_unique(*this);
- }
-
- void InitializeCommandPool()
- {
- VkCommandPoolCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- createInfo.queueFamilyIndex = graphicsQueueIndex;
- CP_VK_ASSERT(vkCreateCommandPool(device, &createInfo, nullptr, &commandPool), "Failed to initialize command pool");
- }
-
- void InitializeSyncObjects()
- {
- imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
- renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
- inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
- VkSemaphoreCreateInfo semaphoreCreateInfo{};
- semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i)
- {
- CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &imageAvailableSemaphores[i]), "Failed to initialize available image semaphore");
- CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]), "Failed to initialize render finished semaphore");
-
- VkFenceCreateInfo fenceCreateInfo{};
- fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- CP_VK_ASSERT(vkCreateFence(device, &fenceCreateInfo, nullptr, &inFlightFences[i]), "Failed to initialize in flight fence");
- }
- }
-
- std::vector GetRequiredExtensions()
- {
- uint32_t glfwExtensionCount;
- const char** glfwExtensions;
- glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
-
- std::vector extensions{glfwExtensions, glfwExtensions + glfwExtensionCount};
-
- debugMessenger->AddRequiredExtensions(&extensions);
-
- return extensions;
- }
-
- bool CheckLayerSupport(const std::vector& layers)
- {
- uint32_t layerCount;
- vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
-
- std::vector availableLayers(layerCount);
- vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
-
- CP_INFO("Supported Layers:");
- for (auto&& availableLayer : availableLayers)
- {
- CP_INFO_CONT("\t%s", availableLayer.layerName);
+ return extensions;
}
- for (auto&& layer : layers)
+ bool CheckLayerSupport(const std::vector& layers)
{
- bool layerFound = false;
+ uint32_t layerCount;
+ vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
+
+ std::vector availableLayers(layerCount);
+ vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
+
+ CP_INFO("Supported Layers:");
for (auto&& availableLayer : availableLayers)
{
- if (std::strcmp(layer, availableLayer.layerName) == 0)
- {
- layerFound = true;
- break;
- }
+ CP_INFO_CONT("\t%s", availableLayer.layerName);
}
- if (!layerFound)
- return false;
- }
- return true;
- }
- bool IsPhysicalDeviceSuitable(VkPhysicalDevice device)
- {
- VkPhysicalDeviceProperties deviceProperties;
- vkGetPhysicalDeviceProperties(device, &deviceProperties);
- if (deviceProperties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
- return false;
-
- VkPhysicalDeviceFeatures deviceFeatures;
- vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
- if (!deviceFeatures.fillModeNonSolid || !deviceFeatures.samplerAnisotropy)
- return false;
-
- QueueFamiliesQuery query{surface, device};
- if (!query.AllRequiredFamiliesSupported())
- return false;
-
- if (!CheckDeviceExtensionSupport(device))
- return false;
- SwapChainSupportDetails details{surface, device};
- if (!details.Valid())
- return false;
-
- return true;
- }
-
- bool CheckDeviceExtensionSupport(VkPhysicalDevice device)
- {
- uint32_t extensionCount;
- vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
- std::vector extensions{extensionCount};
- vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data());
-
- for (auto&& requiredExtension : GetRequiredDeviceExtensions())
- {
- bool found = false;
- for (auto&& extension : extensions)
+ for (auto&& layer : layers)
{
- if (std::strcmp(requiredExtension, extension.extensionName) == 0)
+ bool layerFound = false;
+ for (auto&& availableLayer : availableLayers)
{
- found = true;
- break;
+ if (std::strcmp(layer, availableLayer.layerName) == 0)
+ {
+ layerFound = true;
+ break;
+ }
}
+ if (!layerFound)
+ return false;
}
- if (!found)
- return false;
+ return true;
}
- return true;
- }
- std::vector GetRequiredDeviceExtensions()
- {
- return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
- }
+ bool IsPhysicalDeviceSuitable(VkPhysicalDevice device)
+ {
+ VkPhysicalDeviceProperties deviceProperties;
+ vkGetPhysicalDeviceProperties(device, &deviceProperties);
+ if (deviceProperties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+ return false;
- static void FramebufferResizeCallback(GLFWwindow* window, int width, int height)
- {
- Instance* instance = static_cast(glfwGetWindowUserPointer(window));
- instance->framebufferResized = true;
- }
-};
+ VkPhysicalDeviceFeatures deviceFeatures;
+ vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
+ if (!deviceFeatures.fillModeNonSolid || !deviceFeatures.samplerAnisotropy)
+ return false;
+
+ QueueFamiliesQuery query{surface, device};
+ if (!query.AllRequiredFamiliesSupported())
+ return false;
+
+ if (!CheckDeviceExtensionSupport(device))
+ return false;
+ SwapChainSupportDetails details{surface, device};
+ if (!details.Valid())
+ return false;
+
+ return true;
+ }
+
+ bool CheckDeviceExtensionSupport(VkPhysicalDevice device)
+ {
+ uint32_t extensionCount;
+ vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
+ std::vector extensions{extensionCount};
+ vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data());
+
+ for (auto&& requiredExtension : GetRequiredDeviceExtensions())
+ {
+ bool found = false;
+ for (auto&& extension : extensions)
+ {
+ if (std::strcmp(requiredExtension, extension.extensionName) == 0)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ }
+ return true;
+ }
+
+ std::vector GetRequiredDeviceExtensions()
+ {
+ return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
+ }
+
+ static void FramebufferResizeCallback(GLFWwindow* window, int width, int height)
+ {
+ Instance* instance = static_cast(glfwGetWindowUserPointer(window));
+ instance->framebufferResized = true;
+ }
+ };
+}
diff --git a/Vulkan/src/Pipeline.h b/Vulkan/src/Pipeline.h
index 8d0a25c..62cfe91 100644
--- a/Vulkan/src/Pipeline.h
+++ b/Vulkan/src/Pipeline.h
@@ -11,246 +11,248 @@
#include
#include