From 88979a5ab9755245d7afe2fc6235fa81afef6bba Mon Sep 17 00:00:00 2001 From: Thraix Date: Sun, 5 Feb 2023 10:52:27 +0100 Subject: [PATCH] Add namespace to all classes --- Vulkan/Vulkan.vcxproj | 1 - Vulkan/Vulkan.vcxproj.filters | 3 - Vulkan/src/Application.h | 239 ++++++++++ Vulkan/src/Buffer.h | 281 +++++------ Vulkan/src/CommandBuffer.h | 165 +++---- Vulkan/src/CommandBufferScoped.h | 29 +- Vulkan/src/Common.h | 40 +- Vulkan/src/DebugMessenger.h | 153 +++--- Vulkan/src/DescriptorPool.h | 93 ++-- Vulkan/src/DescriptorSet.h | 115 ++--- Vulkan/src/FileSystem.h | 97 ++-- Vulkan/src/Framebuffer.h | 321 ++++++------- Vulkan/src/Image.h | 339 ++++++------- Vulkan/src/IndexBuffer.h | 37 +- Vulkan/src/Instance.h | 787 ++++++++++++++++--------------- Vulkan/src/Pipeline.h | 422 ++++++++--------- Vulkan/src/PipelineCreator.h | 101 ++-- Vulkan/src/QueueFamilies.h | 57 +-- Vulkan/src/Shader.h | 258 +++++----- Vulkan/src/SwapChain.cpp | 615 ++++++++++++------------ Vulkan/src/SwapChain.h | 101 ++-- Vulkan/src/Texture2D.cpp | 277 +++++------ Vulkan/src/Texture2D.h | 70 +-- Vulkan/src/Timer.h | 35 +- Vulkan/src/UniformBuffer.h | 47 +- Vulkan/src/Vertex.h | 29 +- Vulkan/src/VertexBuffer.h | 51 +- Vulkan/src/VertexDescriptor.h | 98 ++-- Vulkan/src/VertexPassthrough.h | 21 +- Vulkan/src/VulkanException.h | 15 +- Vulkan/src/Window.h | 6 - Vulkan/src/main.cpp | 243 +--------- 32 files changed, 2611 insertions(+), 2535 deletions(-) create mode 100644 Vulkan/src/Application.h delete mode 100644 Vulkan/src/Window.h 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 - -class Pipeline +namespace Copium { - CP_DELETE_COPY_AND_MOVE_CTOR(Pipeline); -private: - Instance& instance; - - std::vector descriptorSetLayouts{}; - std::vector boundDescriptorSets; - VkPipelineLayout pipelineLayout; - VkPipeline graphicsPipeline; - -public: - Pipeline(Instance& instance, PipelineCreator creator) - : instance{instance} + class Pipeline { - InitializeDescriptorSetLayout(creator); - InitializePipeline(creator); - } + CP_DELETE_COPY_AND_MOVE_CTOR(Pipeline); + private: + Instance& instance; - ~Pipeline() - { - vkDestroyPipeline(instance.GetDevice(), graphicsPipeline, nullptr); - vkDestroyPipelineLayout(instance.GetDevice(), pipelineLayout, nullptr); - for (auto&& descriptorSetLayout : descriptorSetLayouts) + std::vector descriptorSetLayouts{}; + std::vector boundDescriptorSets; + VkPipelineLayout pipelineLayout; + VkPipeline graphicsPipeline; + + public: + Pipeline(Instance& instance, PipelineCreator creator) + : instance{instance} { - vkDestroyDescriptorSetLayout(instance.GetDevice(), descriptorSetLayout, nullptr); + InitializeDescriptorSetLayout(creator); + InitializePipeline(creator); } - } - void Bind(const CommandBuffer& commandBuffer) - { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = instance.GetSwapChain().GetExtent().width; - viewport.height = instance.GetSwapChain().GetExtent().height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = instance.GetSwapChain().GetExtent(); - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - } - - void SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet) - { - CP_ASSERT(setIndex < boundDescriptorSets.size(), "DescriptorSet index is out of bounds"); - boundDescriptorSets[setIndex] = descriptorSet.GetHandle(); - } - - void BindDescriptorSets(VkCommandBuffer commandBuffer) - { - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, boundDescriptorSets.size(), boundDescriptorSets.data(), 0, nullptr); - } - - VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t setIndex) const - { - return descriptorSetLayouts[setIndex]; - } - -private: - void InitializeDescriptorSetLayout(const PipelineCreator& creator) - { - boundDescriptorSets.resize(creator.descriptorSetLayouts.size()); - descriptorSetLayouts.resize(creator.descriptorSetLayouts.size()); - int i = 0; - for (auto&& bindings : creator.descriptorSetLayouts) + ~Pipeline() { - std::vector layoutBindings{bindings.second.size()}; - int j = 0; - for (auto&& binding : bindings.second) + vkDestroyPipeline(instance.GetDevice(), graphicsPipeline, nullptr); + vkDestroyPipelineLayout(instance.GetDevice(), pipelineLayout, nullptr); + for (auto&& descriptorSetLayout : descriptorSetLayouts) { - layoutBindings[j].binding = binding.binding; - layoutBindings[j].descriptorType = binding.type; - layoutBindings[j].descriptorCount = binding.count; - layoutBindings[j].stageFlags = binding.flags; - layoutBindings[j].pImmutableSamplers = nullptr; - j++; + vkDestroyDescriptorSetLayout(instance.GetDevice(), descriptorSetLayout, nullptr); } - - VkDescriptorSetLayoutCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - createInfo.bindingCount = layoutBindings.size(); - createInfo.pBindings = layoutBindings.data(); - - CP_VK_ASSERT(vkCreateDescriptorSetLayout(instance.GetDevice(), &createInfo, nullptr, &descriptorSetLayouts[i++]), "Failed to initialize descriptor set layout"); } - } - void InitializePipeline(const PipelineCreator& creator) - { - Shader shader{instance, ShaderType::GlslFile, creator.vertexShader, creator.fragmentShader}; + void Bind(const CommandBuffer& commandBuffer) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); - VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo{}; - vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputCreateInfo.vertexBindingDescriptionCount = creator.vertexDescriptor.GetBindings().size(); - vertexInputCreateInfo.pVertexBindingDescriptions = creator.vertexDescriptor.GetBindings().data(); - vertexInputCreateInfo.vertexAttributeDescriptionCount = creator.vertexDescriptor.GetAttributes().size(); - vertexInputCreateInfo.pVertexAttributeDescriptions = creator.vertexDescriptor.GetAttributes().data(); + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = instance.GetSwapChain().GetExtent().width; + viewport.height = instance.GetSwapChain().GetExtent().height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = instance.GetSwapChain().GetExtent(); + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + } - VkPipelineInputAssemblyStateCreateInfo inputAssemblyCreateInfo{}; - inputAssemblyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssemblyCreateInfo.topology = creator.topology; - inputAssemblyCreateInfo.primitiveRestartEnable = VK_FALSE; + void SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet) + { + CP_ASSERT(setIndex < boundDescriptorSets.size(), "DescriptorSet index is out of bounds"); + boundDescriptorSets[setIndex] = descriptorSet.GetHandle(); + } - VkViewport viewport{}; - viewport.x = 0; - viewport.y = 0; - viewport.width = instance.GetSwapChain().GetExtent().width; - viewport.height = instance.GetSwapChain().GetExtent().height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; + void BindDescriptorSets(VkCommandBuffer commandBuffer) + { + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, boundDescriptorSets.size(), boundDescriptorSets.data(), 0, nullptr); + } - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = instance.GetSwapChain().GetExtent(); + VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t setIndex) const + { + return descriptorSetLayouts[setIndex]; + } - std::vector dynamicStates = { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR - }; + private: + void InitializeDescriptorSetLayout(const PipelineCreator& creator) + { + boundDescriptorSets.resize(creator.descriptorSetLayouts.size()); + descriptorSetLayouts.resize(creator.descriptorSetLayouts.size()); + int i = 0; + for (auto&& bindings : creator.descriptorSetLayouts) + { + std::vector layoutBindings{bindings.second.size()}; + int j = 0; + for (auto&& binding : bindings.second) + { + layoutBindings[j].binding = binding.binding; + layoutBindings[j].descriptorType = binding.type; + layoutBindings[j].descriptorCount = binding.count; + layoutBindings[j].stageFlags = binding.flags; + layoutBindings[j].pImmutableSamplers = nullptr; + j++; + } - VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{}; - dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynamicStateCreateInfo.dynamicStateCount = dynamicStates.size(); - dynamicStateCreateInfo.pDynamicStates = dynamicStates.data(); + VkDescriptorSetLayoutCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + createInfo.bindingCount = layoutBindings.size(); + createInfo.pBindings = layoutBindings.data(); - VkPipelineViewportStateCreateInfo viewportStateCreateInfo{}; - viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportStateCreateInfo.viewportCount = 1; - viewportStateCreateInfo.pViewports = &viewport; - viewportStateCreateInfo.scissorCount = 1; - viewportStateCreateInfo.pScissors = &scissor; + CP_VK_ASSERT(vkCreateDescriptorSetLayout(instance.GetDevice(), &createInfo, nullptr, &descriptorSetLayouts[i++]), "Failed to initialize descriptor set layout"); + } + } - VkPipelineRasterizationStateCreateInfo rasterizerCreateInfo{}; - rasterizerCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizerCreateInfo.depthClampEnable = VK_FALSE; - rasterizerCreateInfo.rasterizerDiscardEnable = VK_FALSE; - rasterizerCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; - rasterizerCreateInfo.lineWidth = 1.0f; - rasterizerCreateInfo.cullMode = creator.cullMode; - rasterizerCreateInfo.frontFace = creator.frontFace; + void InitializePipeline(const PipelineCreator& creator) + { + Shader shader{instance, Shader::Type::GlslFile, creator.vertexShader, creator.fragmentShader}; - rasterizerCreateInfo.depthBiasEnable = VK_FALSE; - rasterizerCreateInfo.depthBiasConstantFactor = 0.0f; - rasterizerCreateInfo.depthBiasClamp = 0.0f; - rasterizerCreateInfo.depthBiasSlopeFactor = 0.0f; + VkPipelineVertexInputStateCreateInfo vertexInputCreateInfo{}; + vertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputCreateInfo.vertexBindingDescriptionCount = creator.vertexDescriptor.GetBindings().size(); + vertexInputCreateInfo.pVertexBindingDescriptions = creator.vertexDescriptor.GetBindings().data(); + vertexInputCreateInfo.vertexAttributeDescriptionCount = creator.vertexDescriptor.GetAttributes().size(); + vertexInputCreateInfo.pVertexAttributeDescriptions = creator.vertexDescriptor.GetAttributes().data(); - VkPipelineMultisampleStateCreateInfo multisampleCreateInfo{}; - multisampleCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampleCreateInfo.sampleShadingEnable = VK_FALSE; - multisampleCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - multisampleCreateInfo.minSampleShading = 1.0f; - multisampleCreateInfo.pSampleMask = nullptr; - multisampleCreateInfo.alphaToCoverageEnable = VK_FALSE; - multisampleCreateInfo.alphaToOneEnable = VK_FALSE; + VkPipelineInputAssemblyStateCreateInfo inputAssemblyCreateInfo{}; + inputAssemblyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssemblyCreateInfo.topology = creator.topology; + inputAssemblyCreateInfo.primitiveRestartEnable = VK_FALSE; - VkPipelineDepthStencilStateCreateInfo depthStencilCreateInfo{}; - depthStencilCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencilCreateInfo.depthTestEnable = VK_TRUE; - depthStencilCreateInfo.depthWriteEnable = VK_TRUE; - depthStencilCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS; - depthStencilCreateInfo.depthBoundsTestEnable = VK_FALSE; - depthStencilCreateInfo.minDepthBounds = 0.0f; - depthStencilCreateInfo.maxDepthBounds = 1.0f; - depthStencilCreateInfo.stencilTestEnable = VK_FALSE; - depthStencilCreateInfo.front = {}; - depthStencilCreateInfo.back = {}; + VkViewport viewport{}; + viewport.x = 0; + viewport.y = 0; + viewport.width = instance.GetSwapChain().GetExtent().width; + viewport.height = instance.GetSwapChain().GetExtent().height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = instance.GetSwapChain().GetExtent(); + + std::vector dynamicStates = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{}; + dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicStateCreateInfo.dynamicStateCount = dynamicStates.size(); + dynamicStateCreateInfo.pDynamicStates = dynamicStates.data(); + + VkPipelineViewportStateCreateInfo viewportStateCreateInfo{}; + viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportStateCreateInfo.viewportCount = 1; + viewportStateCreateInfo.pViewports = &viewport; + viewportStateCreateInfo.scissorCount = 1; + viewportStateCreateInfo.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizerCreateInfo{}; + rasterizerCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizerCreateInfo.depthClampEnable = VK_FALSE; + rasterizerCreateInfo.rasterizerDiscardEnable = VK_FALSE; + rasterizerCreateInfo.polygonMode = VK_POLYGON_MODE_FILL; + rasterizerCreateInfo.lineWidth = 1.0f; + rasterizerCreateInfo.cullMode = creator.cullMode; + rasterizerCreateInfo.frontFace = creator.frontFace; + + rasterizerCreateInfo.depthBiasEnable = VK_FALSE; + rasterizerCreateInfo.depthBiasConstantFactor = 0.0f; + rasterizerCreateInfo.depthBiasClamp = 0.0f; + rasterizerCreateInfo.depthBiasSlopeFactor = 0.0f; + + VkPipelineMultisampleStateCreateInfo multisampleCreateInfo{}; + multisampleCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampleCreateInfo.sampleShadingEnable = VK_FALSE; + multisampleCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampleCreateInfo.minSampleShading = 1.0f; + multisampleCreateInfo.pSampleMask = nullptr; + multisampleCreateInfo.alphaToCoverageEnable = VK_FALSE; + multisampleCreateInfo.alphaToOneEnable = VK_FALSE; + + VkPipelineDepthStencilStateCreateInfo depthStencilCreateInfo{}; + depthStencilCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencilCreateInfo.depthTestEnable = VK_TRUE; + depthStencilCreateInfo.depthWriteEnable = VK_TRUE; + depthStencilCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS; + depthStencilCreateInfo.depthBoundsTestEnable = VK_FALSE; + depthStencilCreateInfo.minDepthBounds = 0.0f; + depthStencilCreateInfo.maxDepthBounds = 1.0f; + depthStencilCreateInfo.stencilTestEnable = VK_FALSE; + depthStencilCreateInfo.front = {}; + depthStencilCreateInfo.back = {}; - VkPipelineColorBlendAttachmentState colorBlendAttachment{}; // TODO: Add to PipelineCreator - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; - colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; // TODO: Add to PipelineCreator + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_FALSE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - VkPipelineColorBlendStateCreateInfo colorBlendCreateInfo{}; - colorBlendCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlendCreateInfo.logicOpEnable = VK_FALSE; - colorBlendCreateInfo.logicOp = VK_LOGIC_OP_COPY; - colorBlendCreateInfo.attachmentCount = 1; - colorBlendCreateInfo.pAttachments = &colorBlendAttachment; - colorBlendCreateInfo.blendConstants[0] = 0.0f; - colorBlendCreateInfo.blendConstants[1] = 0.0f; - colorBlendCreateInfo.blendConstants[2] = 0.0f; - colorBlendCreateInfo.blendConstants[3] = 0.0f; + VkPipelineColorBlendStateCreateInfo colorBlendCreateInfo{}; + colorBlendCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlendCreateInfo.logicOpEnable = VK_FALSE; + colorBlendCreateInfo.logicOp = VK_LOGIC_OP_COPY; + colorBlendCreateInfo.attachmentCount = 1; + colorBlendCreateInfo.pAttachments = &colorBlendAttachment; + colorBlendCreateInfo.blendConstants[0] = 0.0f; + colorBlendCreateInfo.blendConstants[1] = 0.0f; + colorBlendCreateInfo.blendConstants[2] = 0.0f; + colorBlendCreateInfo.blendConstants[3] = 0.0f; - VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{}; - pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutCreateInfo.setLayoutCount = descriptorSetLayouts.size(); - pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts.data(); - pipelineLayoutCreateInfo.pushConstantRangeCount = 0; - pipelineLayoutCreateInfo.pPushConstantRanges = nullptr; + VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{}; + pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutCreateInfo.setLayoutCount = descriptorSetLayouts.size(); + pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts.data(); + pipelineLayoutCreateInfo.pushConstantRangeCount = 0; + pipelineLayoutCreateInfo.pPushConstantRanges = nullptr; - CP_VK_ASSERT(vkCreatePipelineLayout(instance.GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout), "Failed to initialize pipeline layout"); + CP_VK_ASSERT(vkCreatePipelineLayout(instance.GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout), "Failed to initialize pipeline layout"); - const std::vector& shaderStages = shader.GetShaderStages(); - VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo{}; - graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - graphicsPipelineCreateInfo.stageCount = shaderStages.size(); - graphicsPipelineCreateInfo.pStages = shaderStages.data(); - graphicsPipelineCreateInfo.pVertexInputState = &vertexInputCreateInfo; - graphicsPipelineCreateInfo.pInputAssemblyState = &inputAssemblyCreateInfo; - graphicsPipelineCreateInfo.pViewportState = &viewportStateCreateInfo; - graphicsPipelineCreateInfo.pRasterizationState = &rasterizerCreateInfo; - graphicsPipelineCreateInfo.pMultisampleState = &multisampleCreateInfo; - graphicsPipelineCreateInfo.pDepthStencilState = &depthStencilCreateInfo; - graphicsPipelineCreateInfo.pColorBlendState = &colorBlendCreateInfo; - graphicsPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo; - graphicsPipelineCreateInfo.layout = pipelineLayout; - graphicsPipelineCreateInfo.renderPass = creator.renderPass; - graphicsPipelineCreateInfo.subpass = 0; - graphicsPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE; - graphicsPipelineCreateInfo.basePipelineIndex = -1; + const std::vector& shaderStages = shader.GetShaderStages(); + VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo{}; + graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + graphicsPipelineCreateInfo.stageCount = shaderStages.size(); + graphicsPipelineCreateInfo.pStages = shaderStages.data(); + graphicsPipelineCreateInfo.pVertexInputState = &vertexInputCreateInfo; + graphicsPipelineCreateInfo.pInputAssemblyState = &inputAssemblyCreateInfo; + graphicsPipelineCreateInfo.pViewportState = &viewportStateCreateInfo; + graphicsPipelineCreateInfo.pRasterizationState = &rasterizerCreateInfo; + graphicsPipelineCreateInfo.pMultisampleState = &multisampleCreateInfo; + graphicsPipelineCreateInfo.pDepthStencilState = &depthStencilCreateInfo; + graphicsPipelineCreateInfo.pColorBlendState = &colorBlendCreateInfo; + graphicsPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo; + graphicsPipelineCreateInfo.layout = pipelineLayout; + graphicsPipelineCreateInfo.renderPass = creator.renderPass; + graphicsPipelineCreateInfo.subpass = 0; + graphicsPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE; + graphicsPipelineCreateInfo.basePipelineIndex = -1; - CP_VK_ASSERT(vkCreateGraphicsPipelines(instance.GetDevice(), VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &graphicsPipeline), "Failed to initialize graphics pipeline"); - } + CP_VK_ASSERT(vkCreateGraphicsPipelines(instance.GetDevice(), VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &graphicsPipeline), "Failed to initialize graphics pipeline"); + } - VkShaderModule InitializeShaderModule(const std::vector& code) - { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = code.size(); - createInfo.pCode = reinterpret_cast(code.data()); + VkShaderModule InitializeShaderModule(const std::vector& code) + { + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = code.size(); + createInfo.pCode = reinterpret_cast(code.data()); - VkShaderModule shaderModule; - CP_VK_ASSERT(vkCreateShaderModule(instance.GetDevice(), &createInfo, nullptr, &shaderModule), "Failed to initialize shader module"); + VkShaderModule shaderModule; + CP_VK_ASSERT(vkCreateShaderModule(instance.GetDevice(), &createInfo, nullptr, &shaderModule), "Failed to initialize shader module"); - return shaderModule; - } + return shaderModule; + } -}; \ No newline at end of file + }; +} \ No newline at end of file diff --git a/Vulkan/src/PipelineCreator.h b/Vulkan/src/PipelineCreator.h index e5b584c..6083e2b 100644 --- a/Vulkan/src/PipelineCreator.h +++ b/Vulkan/src/PipelineCreator.h @@ -6,55 +6,58 @@ #include #include -class PipelineCreator +namespace Copium { - struct DescriptorSetBinding + class PipelineCreator { - uint32_t binding; - VkDescriptorType type; - uint32_t count; - VkShaderStageFlags flags; + struct DescriptorSetBinding + { + uint32_t binding; + VkDescriptorType type; + uint32_t count; + VkShaderStageFlags flags; + }; + friend class Pipeline; + private: + std::map> descriptorSetLayouts{}; + + std::string vertexShader; + std::string fragmentShader; + VertexDescriptor vertexDescriptor{}; + VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; + VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; + VkRenderPass renderPass = VK_NULL_HANDLE; + + public: + PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader) + : vertexShader{vertexShader}, fragmentShader{fragmentShader}, renderPass{renderPass} + {} + + void SetVertexDescriptor(const VertexDescriptor& descriptor) + { + vertexDescriptor = descriptor; + } + + void AddDescriptorSetLayoutBinding(uint32_t set, uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stageFlags) + { + CP_ASSERT(set <= descriptorSetLayouts.size(), "AddDescriptorSetLayoutBinding : Cannot add descriptor set with set number greater than the current set count"); + descriptorSetLayouts[set].emplace_back(DescriptorSetBinding{binding, type, count, stageFlags}); + } + + void SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology) + { + topology = primitiveTopology; + } + + void SetCullMode(VkCullModeFlags flags) + { + cullMode = flags; + } + + void SetCullFrontFace(VkFrontFace cullFrontFace) + { + frontFace = cullFrontFace; + } }; - friend class Pipeline; -private: - std::map> descriptorSetLayouts{}; - - std::string vertexShader; - std::string fragmentShader; - VertexDescriptor vertexDescriptor{}; - VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; - VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; - VkRenderPass renderPass = VK_NULL_HANDLE; - -public: - PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader) - : vertexShader{vertexShader}, fragmentShader{fragmentShader}, renderPass{renderPass} - {} - - void SetVertexDescriptor(const VertexDescriptor& descriptor) - { - vertexDescriptor = descriptor; - } - - void AddDescriptorSetLayoutBinding(uint32_t set, uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stageFlags) - { - CP_ASSERT(set <= descriptorSetLayouts.size(), "AddDescriptorSetLayoutBinding : Cannot add descriptor set with set number greater than the current set count"); - descriptorSetLayouts[set].emplace_back(DescriptorSetBinding{binding, type, count, stageFlags}); - } - - void SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology) - { - topology = primitiveTopology; - } - - void SetCullMode(VkCullModeFlags flags) - { - cullMode = flags; - } - - void SetCullFrontFace(VkFrontFace cullFrontFace) - { - frontFace = cullFrontFace; - } -}; +} diff --git a/Vulkan/src/QueueFamilies.h b/Vulkan/src/QueueFamilies.h index 9c35953..1318891 100644 --- a/Vulkan/src/QueueFamilies.h +++ b/Vulkan/src/QueueFamilies.h @@ -4,38 +4,41 @@ #include #include -struct QueueFamiliesQuery +namespace Copium { - std::optional graphicsFamily; - std::optional presentFamily; - - QueueFamiliesQuery(VkSurfaceKHR surface, VkPhysicalDevice device) + struct QueueFamiliesQuery { - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); + std::optional graphicsFamily; + std::optional presentFamily; - int i = 0; - for (auto&& queueFamily : queueFamilies) + QueueFamiliesQuery(VkSurfaceKHR surface, VkPhysicalDevice device) { - if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); + std::vector queueFamilies(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); + + int i = 0; + for (auto&& queueFamily : queueFamilies) { - graphicsFamily = i; + if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + graphicsFamily = i; + } + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); + if (presentSupport) + { + presentFamily = i; + } + i++; } - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); - if (presentSupport) - { - presentFamily = i; - } - i++; + } - } - - bool AllRequiredFamiliesSupported() - { - return graphicsFamily.has_value() && presentFamily.has_value(); - } -}; + bool AllRequiredFamiliesSupported() + { + return graphicsFamily.has_value() && presentFamily.has_value(); + } + }; +} diff --git a/Vulkan/src/Shader.h b/Vulkan/src/Shader.h index 836618d..430044c 100644 --- a/Vulkan/src/Shader.h +++ b/Vulkan/src/Shader.h @@ -6,146 +6,150 @@ #include "Common.h" #include "Instance.h" -enum class ShaderType +namespace Copium { - GlslFile, GlslCode, SpvFile, SpvCode -}; - -class Shader -{ - CP_DELETE_COPY_AND_MOVE_CTOR(Shader); -private: - Instance& instance; - - VkShaderModule vertShaderModule; - VkShaderModule fragShaderModule; - std::vector shaderStages; -public: - Shader(Instance& instance, ShaderType shaderType, const std::string& vertexInput, const std::string& fragmentInput) - : instance{instance} + class Shader { - switch (shaderType) + CP_DELETE_COPY_AND_MOVE_CTOR(Shader); + public: + enum class Type { - case ShaderType::GlslCode: - vertShaderModule = InitializeShaderModuleFromGlslCode(vertexInput, shaderc_vertex_shader); - fragShaderModule = InitializeShaderModuleFromGlslCode(fragmentInput, shaderc_fragment_shader); - break; - case ShaderType::GlslFile: - vertShaderModule = InitializeShaderModuleFromGlslFile(vertexInput, shaderc_vertex_shader); - fragShaderModule = InitializeShaderModuleFromGlslFile(fragmentInput, shaderc_fragment_shader); - break; - case ShaderType::SpvCode: - vertShaderModule = InitializeShaderModule(vertexInput); - fragShaderModule = InitializeShaderModule(fragmentInput); - break; - case ShaderType::SpvFile: - vertShaderModule = InitializeShaderModule(FileSystem::ReadFile(vertexInput)); - fragShaderModule = InitializeShaderModule(FileSystem::ReadFile(fragmentInput)); - break; - default: - CP_ASSERT(false, "Unreachable switch case %d", (int)shaderType); + GlslFile, GlslCode, SpvFile, SpvCode + }; + + private: + Instance& instance; + + VkShaderModule vertShaderModule; + VkShaderModule fragShaderModule; + std::vector shaderStages; + public: + Shader(Instance& instance, Type type, const std::string& vertexInput, const std::string& fragmentInput) + : instance{instance} + { + switch (type) + { + case Type::GlslCode: + vertShaderModule = InitializeShaderModuleFromGlslCode(vertexInput, shaderc_vertex_shader); + fragShaderModule = InitializeShaderModuleFromGlslCode(fragmentInput, shaderc_fragment_shader); + break; + case Type::GlslFile: + vertShaderModule = InitializeShaderModuleFromGlslFile(vertexInput, shaderc_vertex_shader); + fragShaderModule = InitializeShaderModuleFromGlslFile(fragmentInput, shaderc_fragment_shader); + break; + case Type::SpvCode: + vertShaderModule = InitializeShaderModule(vertexInput); + fragShaderModule = InitializeShaderModule(fragmentInput); + break; + case Type::SpvFile: + vertShaderModule = InitializeShaderModule(FileSystem::ReadFile(vertexInput)); + fragShaderModule = InitializeShaderModule(FileSystem::ReadFile(fragmentInput)); + break; + default: + CP_ASSERT(false, "Unreachable switch case %d", (int)type); + } + + shaderStages.resize(2); + shaderStages[0] = {}; + shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + shaderStages[0].module = vertShaderModule; + shaderStages[0].pName = "main"; + + shaderStages[1] = {}; + shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + shaderStages[1].module = fragShaderModule; + shaderStages[1].pName = "main"; } - shaderStages.resize(2); - shaderStages[0] = {}; - shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].module = vertShaderModule; - shaderStages[0].pName = "main"; - - shaderStages[1] = {}; - shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStages[1].module = fragShaderModule; - shaderStages[1].pName = "main"; - } - - ~Shader() - { - vkDestroyShaderModule(instance.GetDevice(), vertShaderModule, nullptr); - vkDestroyShaderModule(instance.GetDevice(), fragShaderModule, nullptr); - } - - const std::vector GetShaderStages() const - { - return shaderStages; - } - -private: - VkShaderModule InitializeShaderModule(const std::vector& codeSpv) - { - return InitializeShaderModule(codeSpv.data(), codeSpv.size() * sizeof(uint32_t)); - } - - VkShaderModule InitializeShaderModule(const std::string& codeSpv) - { - return InitializeShaderModule(reinterpret_cast(codeSpv.data()), codeSpv.size()); - } - - VkShaderModule InitializeShaderModule(const std::vector& codeSpv) - { - return InitializeShaderModule(reinterpret_cast(codeSpv.data()), codeSpv.size()); - } - - VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind shaderType) - { - std::string spvFilename = ".cache/" + filename + ".spv"; - try + ~Shader() { - if (FileSystem::FileExists(spvFilename)) + vkDestroyShaderModule(instance.GetDevice(), vertShaderModule, nullptr); + vkDestroyShaderModule(instance.GetDevice(), fragShaderModule, nullptr); + } + + const std::vector GetShaderStages() const + { + return shaderStages; + } + + private: + VkShaderModule InitializeShaderModule(const std::vector& codeSpv) + { + return InitializeShaderModule(codeSpv.data(), codeSpv.size() * sizeof(uint32_t)); + } + + VkShaderModule InitializeShaderModule(const std::string& codeSpv) + { + return InitializeShaderModule(reinterpret_cast(codeSpv.data()), codeSpv.size()); + } + + VkShaderModule InitializeShaderModule(const std::vector& codeSpv) + { + return InitializeShaderModule(reinterpret_cast(codeSpv.data()), codeSpv.size()); + } + + VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind type) + { + std::string spvFilename = ".cache/" + filename + ".spv"; + try { - if (FileSystem::DateModified(filename) < FileSystem::DateModified(spvFilename)) + if (FileSystem::FileExists(spvFilename)) { - CP_DEBUG("Loading cached shader file: %s", filename.c_str()); - std::vector data = FileSystem::ReadFile(spvFilename); - CP_ASSERT(data.size() % 4 == 0, "Spv data size is not a factor of 4"); - return InitializeShaderModule((const uint32_t*)data.data(), data.size()); + if (FileSystem::DateModified(filename) < FileSystem::DateModified(spvFilename)) + { + CP_DEBUG("Loading cached shader file: %s", filename.c_str()); + std::vector data = FileSystem::ReadFile(spvFilename); + CP_ASSERT(data.size() % 4 == 0, "Spv data size is not a factor of 4"); + return InitializeShaderModule((const uint32_t*)data.data(), data.size()); + } } } + catch (const std::runtime_error& e) + { + CP_WARN("Cached shader file is invalid, recreating it"); + } + CP_DEBUG("Compiling shader file: %s", filename.c_str()); + shaderc::Compiler compiler; + shaderc::CompileOptions options; + + options.SetOptimizationLevel(shaderc_optimization_level_size); + + std::vector glslCode = FileSystem::ReadFile(filename); + shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(glslCode.data(), glslCode.size(), type, filename.c_str(), options); + CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile shader: %s\n%s", filename.c_str(), result.GetErrorMessage().c_str()); + + std::vector data{result.cbegin(), result.cend()}; + FileSystem::WriteFile(spvFilename, (const char*)data.data(), data.size() * sizeof(uint32_t)); + return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t)); } - catch (const std::runtime_error& e) + + VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type) { - CP_WARN("Cached shader file is invalid, recreating it"); + shaderc::Compiler compiler; + shaderc::CompileOptions options; + + options.SetOptimizationLevel(shaderc_optimization_level_size); + + shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(code.data(), type, "inline_shader_code", options); + CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile inline shader code: %s", result.GetErrorMessage()); + + std::vector data{result.cbegin(), result.cend()}; + return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t)); } - CP_DEBUG("Compiling shader file: %s", filename.c_str()); - shaderc::Compiler compiler; - shaderc::CompileOptions options; - options.SetOptimizationLevel(shaderc_optimization_level_size); + VkShaderModule InitializeShaderModule(const uint32_t* data, size_t size) + { + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = size; + createInfo.pCode = data; - std::vector glslCode = FileSystem::ReadFile(filename); - shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(glslCode.data(), glslCode.size(), shaderType, filename.c_str(), options); - CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile shader: %s\n%s", filename.c_str(), result.GetErrorMessage().c_str()); + VkShaderModule shaderModule; + CP_VK_ASSERT(vkCreateShaderModule(instance.GetDevice(), &createInfo, nullptr, &shaderModule), "Failed to initialize shader module"); - std::vector data{result.cbegin(), result.cend()}; - FileSystem::WriteFile(spvFilename, (const char*)data.data(), data.size() * sizeof(uint32_t)); - return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t)); - } - - VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind shaderType) - { - shaderc::Compiler compiler; - shaderc::CompileOptions options; - - options.SetOptimizationLevel(shaderc_optimization_level_size); - - shaderc::SpvCompilationResult result = compiler.CompileGlslToSpv(code.data(), shaderType, "inline_shader_code", options); - CP_ASSERT(result.GetCompilationStatus() == shaderc_compilation_status_success, "Failed to compile inline shader code: %s", result.GetErrorMessage()); - - std::vector data{result.cbegin(), result.cend()}; - return InitializeShaderModule(data.data(), data.size() * sizeof(uint32_t)); - } - - VkShaderModule InitializeShaderModule(const uint32_t* data, size_t size) - { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = size; - createInfo.pCode = data; - - VkShaderModule shaderModule; - CP_VK_ASSERT(vkCreateShaderModule(instance.GetDevice(), &createInfo, nullptr, &shaderModule), "Failed to initialize shader module"); - - return shaderModule; - } -}; + return shaderModule; + } + }; +} diff --git a/Vulkan/src/SwapChain.cpp b/Vulkan/src/SwapChain.cpp index 0392d22..bda9332 100644 --- a/Vulkan/src/SwapChain.cpp +++ b/Vulkan/src/SwapChain.cpp @@ -10,333 +10,336 @@ #include #include -SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice) +namespace Copium { - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities); - - uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr); - if (formatCount != 0) + SwapChainSupportDetails::SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice) { - formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, formats.data()); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities); + + uint32_t formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr); + if (formatCount != 0) + { + formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, formats.data()); + } + + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr); + if (presentModeCount != 0) + { + presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data()); + } } - uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr); - if (presentModeCount != 0) + bool SwapChainSupportDetails::Valid() { - presentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data()); + return !formats.empty() && !presentModes.empty(); } -} -bool SwapChainSupportDetails::Valid() -{ - return !formats.empty() && !presentModes.empty(); -} - -SwapChain::SwapChain(Instance& instance) - : instance{instance} -{ - Initialize(); - InitializeImageViews(); - InitializeDepthBuffer(); - InitializeRenderPass(); - InitializeFramebuffers(); -} - -SwapChain::~SwapChain() -{ - Destroy(); - vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr); -} - -void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const -{ - std::vector clearValues{2}; - clearValues[0].color = {{0.02f, 0.02f, 0.02f, 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[imageIndex]; - renderPassBeginInfo.renderArea.offset = {0, 0}; - renderPassBeginInfo.renderArea.extent = extent; - renderPassBeginInfo.clearValueCount = clearValues.size(); - renderPassBeginInfo.pClearValues = clearValues.data(); - vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); -} - -void SwapChain::EndFrameBuffer(const CommandBuffer& commandBuffer) const -{ - vkCmdEndRenderPass(commandBuffer); -} - -VkSwapchainKHR SwapChain::GetHandle() const -{ - return handle; -} - -VkRenderPass SwapChain::GetRenderPass() const -{ - return renderPass; -} - -VkExtent2D SwapChain::GetExtent() const -{ - return extent; -} - -VkFramebuffer SwapChain::GetFramebuffer() const -{ - return framebuffers[imageIndex]; -} - -bool SwapChain::BeginPresent(VkSemaphore signalSemaphore) -{ - VkResult result = vkAcquireNextImageKHR(instance.GetDevice(), handle, UINT64_MAX, signalSemaphore, VK_NULL_HANDLE, &imageIndex); - if (result == VK_ERROR_OUT_OF_DATE_KHR) + SwapChain::SwapChain(Instance& instance) + : instance{instance} { - Recreate(); - return false; + Initialize(); + InitializeImageViews(); + InitializeDepthBuffer(); + InitializeRenderPass(); + InitializeFramebuffers(); } - return true; -} -void SwapChain::EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized) -{ - VkPresentInfoKHR presentInfo{}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = waitSemaphore; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &handle; - presentInfo.pImageIndices = &imageIndex; - presentInfo.pResults = nullptr; - - VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) + SwapChain::~SwapChain() { - Recreate(); + Destroy(); + vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr); } -} -void SwapChain::Recreate() -{ - int width = 0; - int height = 0; - glfwGetFramebufferSize(instance.GetWindow(), &width, &height); - while (width == 0 || height == 0) + void SwapChain::BeginFrameBuffer(const CommandBuffer& commandBuffer) const { + std::vector clearValues{2}; + clearValues[0].color = {{0.02f, 0.02f, 0.02f, 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[imageIndex]; + renderPassBeginInfo.renderArea.offset = {0, 0}; + renderPassBeginInfo.renderArea.extent = extent; + renderPassBeginInfo.clearValueCount = clearValues.size(); + renderPassBeginInfo.pClearValues = clearValues.data(); + vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + } + + void SwapChain::EndFrameBuffer(const CommandBuffer& commandBuffer) const + { + vkCmdEndRenderPass(commandBuffer); + } + + VkSwapchainKHR SwapChain::GetHandle() const + { + return handle; + } + + VkRenderPass SwapChain::GetRenderPass() const + { + return renderPass; + } + + VkExtent2D SwapChain::GetExtent() const + { + return extent; + } + + VkFramebuffer SwapChain::GetFramebuffer() const + { + return framebuffers[imageIndex]; + } + + bool SwapChain::BeginPresent(VkSemaphore signalSemaphore) + { + VkResult result = vkAcquireNextImageKHR(instance.GetDevice(), handle, UINT64_MAX, signalSemaphore, VK_NULL_HANDLE, &imageIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR) + { + Recreate(); + return false; + } + return true; + } + + void SwapChain::EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized) + { + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = waitSemaphore; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &handle; + presentInfo.pImageIndices = &imageIndex; + presentInfo.pResults = nullptr; + + VkResult result = vkQueuePresentKHR(presentQueue, &presentInfo); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) + { + Recreate(); + } + } + + void SwapChain::Recreate() + { + int width = 0; + int height = 0; glfwGetFramebufferSize(instance.GetWindow(), &width, &height); - glfwWaitEvents(); - } - - vkDeviceWaitIdle(instance.GetDevice()); - - Destroy(); - - Initialize(); - InitializeImageViews(); - InitializeDepthBuffer(); - InitializeFramebuffers(); -} - -void SwapChain::Initialize() -{ - SwapChainSupportDetails swapChainSupport{instance.GetSurface(), instance.GetPhysicalDevice()}; - - VkSurfaceFormatKHR format = SelectSwapSurfaceFormat(swapChainSupport.formats); - VkPresentModeKHR presentMode = SelectSwapPresentMode(swapChainSupport.presentModes); - extent = SelectSwapExtent(instance.GetWindow(), swapChainSupport.capabilities); - imageFormat = format.format; - uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; - if (swapChainSupport.capabilities.maxImageCount != 0) - { - imageCount = std::min(imageCount, swapChainSupport.capabilities.maxImageCount); - } - - QueueFamiliesQuery queueFamilies{instance.GetSurface(), instance.GetPhysicalDevice()}; - std::vector queueFamilyIndices{queueFamilies.graphicsFamily.value(), queueFamilies.presentFamily.value()}; - - VkSwapchainCreateInfoKHR createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = instance.GetSurface(); - createInfo.minImageCount = imageCount; - createInfo.imageFormat = format.format; - createInfo.imageColorSpace = format.colorSpace; - createInfo.imageExtent = extent; - createInfo.imageArrayLayers = 1; - createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - createInfo.preTransform = swapChainSupport.capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - createInfo.presentMode = presentMode; - createInfo.clipped = VK_TRUE; - createInfo.oldSwapchain = VK_NULL_HANDLE; - if (queueFamilies.graphicsFamily != queueFamilies.presentFamily) - { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices.data(); - } - else - { - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.queueFamilyIndexCount = 0; - createInfo.pQueueFamilyIndices = nullptr; - } - - CP_VK_ASSERT(vkCreateSwapchainKHR(instance.GetDevice(), &createInfo, nullptr, &handle), "Failed to initialize the swapchain"); - - vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, nullptr); - images.resize(imageCount); - vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, images.data()); -} - -void SwapChain::InitializeImageViews() -{ - imageViews.resize(images.size()); - for (size_t i = 0; i < images.size(); i++) - { - imageViews[i] = Image::InitializeImageView(instance, images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT); - } -} - -void SwapChain::InitializeDepthBuffer() -{ - depthImage = std::make_unique(instance, extent.width, extent.height, Texture2D::Type::Static, Texture2D::Format::Depth); -} - -void SwapChain::InitializeRenderPass() -{ - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = imageFormat; - 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_PRESENT_SRC_KHR; - - 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; - - VkSubpassDependency dependency{}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.srcAccessMask = 0; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_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 = 1; - renderPassCreateInfo.pDependencies = &dependency; - - CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "Failed to initialze render pass"); -} - -void SwapChain::InitializeFramebuffers() -{ - framebuffers.resize(images.size()); - - for (size_t i = 0; i < imageViews.size(); ++i) - { - std::vector attachments{imageViews[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 = extent.width; - createInfo.height = extent.height; - createInfo.layers = 1; - - CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "Failed to initialize swap chain framebuffer"); - } -} - -void SwapChain::Destroy() -{ - for (auto&& framebuffer : framebuffers) - { - vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); - } - for (auto&& swapChainImageView : imageViews) - { - vkDestroyImageView(instance.GetDevice(), swapChainImageView, nullptr); - } - vkDestroySwapchainKHR(instance.GetDevice(), handle, nullptr); -} - -VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector& availableFormats) -{ - for (auto&& availableFormat : availableFormats) - { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + while (width == 0 || height == 0) { - return availableFormat; + glfwGetFramebufferSize(instance.GetWindow(), &width, &height); + glfwWaitEvents(); } - } - return availableFormats[0]; -} -VkPresentModeKHR SwapChain::SelectSwapPresentMode(const std::vector& availablePresentModes) -{ - return VK_PRESENT_MODE_FIFO_KHR; - for (auto&& availablePresentMode : availablePresentModes) + vkDeviceWaitIdle(instance.GetDevice()); + + Destroy(); + + Initialize(); + InitializeImageViews(); + InitializeDepthBuffer(); + InitializeFramebuffers(); + } + + void SwapChain::Initialize() { - if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) + SwapChainSupportDetails swapChainSupport{instance.GetSurface(), instance.GetPhysicalDevice()}; + + VkSurfaceFormatKHR format = SelectSwapSurfaceFormat(swapChainSupport.formats); + VkPresentModeKHR presentMode = SelectSwapPresentMode(swapChainSupport.presentModes); + extent = SelectSwapExtent(instance.GetWindow(), swapChainSupport.capabilities); + imageFormat = format.format; + uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; + if (swapChainSupport.capabilities.maxImageCount != 0) { - return availablePresentMode; + imageCount = std::min(imageCount, swapChainSupport.capabilities.maxImageCount); + } + + QueueFamiliesQuery queueFamilies{instance.GetSurface(), instance.GetPhysicalDevice()}; + std::vector queueFamilyIndices{queueFamilies.graphicsFamily.value(), queueFamilies.presentFamily.value()}; + + VkSwapchainCreateInfoKHR createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = instance.GetSurface(); + createInfo.minImageCount = imageCount; + createInfo.imageFormat = format.format; + createInfo.imageColorSpace = format.colorSpace; + createInfo.imageExtent = extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = VK_NULL_HANDLE; + if (queueFamilies.graphicsFamily != queueFamilies.presentFamily) + { + createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + createInfo.queueFamilyIndexCount = 2; + createInfo.pQueueFamilyIndices = queueFamilyIndices.data(); + } + else + { + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.queueFamilyIndexCount = 0; + createInfo.pQueueFamilyIndices = nullptr; + } + + CP_VK_ASSERT(vkCreateSwapchainKHR(instance.GetDevice(), &createInfo, nullptr, &handle), "Failed to initialize the swapchain"); + + vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, nullptr); + images.resize(imageCount); + vkGetSwapchainImagesKHR(instance.GetDevice(), handle, &imageCount, images.data()); + } + + void SwapChain::InitializeImageViews() + { + imageViews.resize(images.size()); + for (size_t i = 0; i < images.size(); i++) + { + imageViews[i] = Image::InitializeImageView(instance, images[i], imageFormat, VK_IMAGE_ASPECT_COLOR_BIT); } } - // VK_PRESENT_MODE_FIFO_KHR is guaranteed to be present - return VK_PRESENT_MODE_FIFO_KHR; -} - -VkExtent2D SwapChain::SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities) -{ - if (capabilities.currentExtent.width != std::numeric_limits::max()) - return capabilities.currentExtent; - - int width, height; - glfwGetFramebufferSize(window, &width, &height); - - VkExtent2D extent{width, height}; - extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); - extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); - return extent; + void SwapChain::InitializeDepthBuffer() + { + depthImage = std::make_unique(instance, extent.width, extent.height, Texture2D::Type::Static, Texture2D::Format::Depth); + } + + void SwapChain::InitializeRenderPass() + { + VkAttachmentDescription colorAttachment{}; + colorAttachment.format = imageFormat; + 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_PRESENT_SRC_KHR; + + 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; + + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = 0; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_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 = 1; + renderPassCreateInfo.pDependencies = &dependency; + + CP_VK_ASSERT(vkCreateRenderPass(instance.GetDevice(), &renderPassCreateInfo, nullptr, &renderPass), "Failed to initialze render pass"); + } + + void SwapChain::InitializeFramebuffers() + { + framebuffers.resize(images.size()); + + for (size_t i = 0; i < imageViews.size(); ++i) + { + std::vector attachments{imageViews[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 = extent.width; + createInfo.height = extent.height; + createInfo.layers = 1; + + CP_VK_ASSERT(vkCreateFramebuffer(instance.GetDevice(), &createInfo, nullptr, &framebuffers[i]), "Failed to initialize swap chain framebuffer"); + } + } + + void SwapChain::Destroy() + { + for (auto&& framebuffer : framebuffers) + { + vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); + } + for (auto&& swapChainImageView : imageViews) + { + vkDestroyImageView(instance.GetDevice(), swapChainImageView, nullptr); + } + vkDestroySwapchainKHR(instance.GetDevice(), handle, nullptr); + } + + VkSurfaceFormatKHR SwapChain::SelectSwapSurfaceFormat(const std::vector& availableFormats) + { + for (auto&& availableFormat : availableFormats) + { + if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + return availableFormat; + } + } + return availableFormats[0]; + } + + VkPresentModeKHR SwapChain::SelectSwapPresentMode(const std::vector& availablePresentModes) + { + return VK_PRESENT_MODE_FIFO_KHR; + for (auto&& availablePresentMode : availablePresentModes) + { + if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) + { + return availablePresentMode; + } + } + + // VK_PRESENT_MODE_FIFO_KHR is guaranteed to be present + return VK_PRESENT_MODE_FIFO_KHR; + } + + VkExtent2D SwapChain::SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities) + { + if (capabilities.currentExtent.width != std::numeric_limits::max()) + return capabilities.currentExtent; + + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + VkExtent2D extent{width, height}; + extent.width = std::clamp(extent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); + return extent; + } } diff --git a/Vulkan/src/SwapChain.h b/Vulkan/src/SwapChain.h index 7b4364c..6173129 100644 --- a/Vulkan/src/SwapChain.h +++ b/Vulkan/src/SwapChain.h @@ -6,60 +6,63 @@ #include #include -class Instance; -class CommandBuffer; -class Texture2D; - -struct SwapChainSupportDetails +namespace Copium { - VkSurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector presentModes; + class Instance; + class CommandBuffer; + class Texture2D; - SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice); - bool Valid(); -}; + struct SwapChainSupportDetails + { + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector presentModes; -class SwapChain final -{ - CP_DELETE_COPY_AND_MOVE_CTOR(SwapChain); -private: - Instance& instance; + SwapChainSupportDetails(VkSurfaceKHR surface, VkPhysicalDevice physicalDevice); + bool Valid(); + }; - VkSwapchainKHR handle; - VkRenderPass renderPass; - VkFormat imageFormat; - VkExtent2D extent; - std::unique_ptr depthImage; - std::vector imageViews; - std::vector images; - std::vector framebuffers; - uint32_t imageIndex; + class SwapChain final + { + CP_DELETE_COPY_AND_MOVE_CTOR(SwapChain); + private: + Instance& instance; -public: - SwapChain(Instance& instance); - ~SwapChain(); + VkSwapchainKHR handle; + VkRenderPass renderPass; + VkFormat imageFormat; + VkExtent2D extent; + std::unique_ptr depthImage; + std::vector imageViews; + std::vector images; + std::vector framebuffers; + uint32_t imageIndex; - void BeginFrameBuffer(const CommandBuffer& commandBuffer) const; - void EndFrameBuffer(const CommandBuffer& commandBuffer) const; - VkSwapchainKHR GetHandle() const; - VkRenderPass GetRenderPass() const; - VkExtent2D GetExtent() const; - VkFramebuffer GetFramebuffer() const; - bool BeginPresent(VkSemaphore signalSemaphore); - void EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized); - void Recreate(); - + public: + SwapChain(Instance& instance); + ~SwapChain(); -private: - void Initialize(); - void InitializeImageViews(); - void InitializeDepthBuffer(); - void InitializeRenderPass(); - void InitializeFramebuffers(); - void Destroy(); + void BeginFrameBuffer(const CommandBuffer& commandBuffer) const; + void EndFrameBuffer(const CommandBuffer& commandBuffer) const; + VkSwapchainKHR GetHandle() const; + VkRenderPass GetRenderPass() const; + VkExtent2D GetExtent() const; + VkFramebuffer GetFramebuffer() const; + bool BeginPresent(VkSemaphore signalSemaphore); + void EndPresent(VkQueue presentQueue, VkSemaphore* waitSemaphore, bool framebufferResized); + void Recreate(); - VkSurfaceFormatKHR SelectSwapSurfaceFormat(const std::vector& availableFormats); - VkPresentModeKHR SelectSwapPresentMode(const std::vector& availablePresentModes); - VkExtent2D SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities); -}; + + private: + void Initialize(); + void InitializeImageViews(); + void InitializeDepthBuffer(); + void InitializeRenderPass(); + void InitializeFramebuffers(); + void Destroy(); + + VkSurfaceFormatKHR SelectSwapSurfaceFormat(const std::vector& availableFormats); + VkPresentModeKHR SelectSwapPresentMode(const std::vector& availablePresentModes); + VkExtent2D SelectSwapExtent(GLFWwindow* window, const VkSurfaceCapabilitiesKHR& capabilities); + }; +} diff --git a/Vulkan/src/Texture2D.cpp b/Vulkan/src/Texture2D.cpp index 5b89074..e75e31a 100644 --- a/Vulkan/src/Texture2D.cpp +++ b/Vulkan/src/Texture2D.cpp @@ -3,148 +3,151 @@ #define STB_IMAGE_IMPLEMENTATION #include -Texture2D::Texture2D(Instance& instance, const std::string& filename) - : instance{instance}, type{Type::Static}, format{Format::Image} +namespace Copium { - InitializeTextureImage(filename); - InitializeSampler(); -} - -Texture2D::Texture2D(Instance& instance, int width, int height, Type type, Format format) - : instance{instance}, type{type}, format{format} -{ - InitializeTexture(width, height); - InitializeSampler(); -} - -Texture2D::~Texture2D() -{ - for(auto&& image : images) - vkDestroyImage(instance.GetDevice(), image, nullptr); - for(auto&& imageMemory : imageMemories) - vkFreeMemory(instance.GetDevice(), imageMemory, nullptr); - for(auto&& imageView : imageViews) - vkDestroyImageView(instance.GetDevice(), imageView, nullptr); - vkDestroySampler(instance.GetDevice(), sampler, nullptr); -} - -VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const -{ - VkDescriptorImageInfo imageInfo{}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.sampler = sampler; - - switch (type) { - case Type::Static: - imageInfo.imageView = imageViews.front(); - break; - case Type::Dynamic: - CP_ASSERT(index >= 0 && index < imageViews.size(), "GetDescriptorImageInfo : index out of bound for dynamic texture"); - imageInfo.imageView = imageViews[index]; - break; - default: - CP_ABORT("GetDescriptorImageInfo : Unreachable switch case"); - } - - return imageInfo; -} - -VkImageView Texture2D::GetImageView() const -{ - CP_ASSERT(type == Type::Static, "GetImageView : Texture2D is not static"); - return imageViews.front(); -} - -VkImageView Texture2D::GetImageView(int index) -{ - CP_ASSERT(type == Type::Dynamic && index >= 0 && index < imageViews.size(), "GetImageView : Texture2D is not dynamic or index out of bound for SystemTexture"); - return imageViews[index]; -} - -void Texture2D::InitializeTextureImage(const std::string& filename) -{ - int texWidth; - int texHeight; - int texChannels; - stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); - - CP_ASSERT(pixels, "InitializeTextureImage : Failed to load texture image"); - - VkDeviceSize bufferSize = texWidth * texHeight * 4; - Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1}; - void* data = stagingBuffer.Map(); - memcpy(data, pixels, bufferSize); - stagingBuffer.Unmap(); - stbi_image_free(pixels); - - images.resize(1); - imageMemories.resize(1); - imageViews.resize(1); - Image::InitializeImage(instance, texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images.front(), &imageMemories.front()); - Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - Image::CopyBufferToImage(instance, stagingBuffer, images.front(), texWidth, texHeight); - Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageViews[0] = Image::InitializeImageView(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); -} - -void Texture2D::InitializeTexture(int width, int height) -{ - int count = 1; - if (type == Type::Dynamic) - count = instance.GetMaxFramesInFlight(); - images.resize(count); - imageMemories.resize(count); - imageViews.resize(count); - for (size_t i = 0; i < images.size(); i++) + Texture2D::Texture2D(Instance& instance, const std::string& filename) + : instance{instance}, type{Type::Static}, format{Format::Image} { - switch (format) - { - case Format::Color: - { - Image::InitializeImage(instance, width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]); - // Image::TransitionImageLayout(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - imageViews[i] = Image::InitializeImageView(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); + InitializeTextureImage(filename); + InitializeSampler(); + } + + Texture2D::Texture2D(Instance& instance, int width, int height, Type type, Format format) + : instance{instance}, type{type}, format{format} + { + InitializeTexture(width, height); + InitializeSampler(); + } + + Texture2D::~Texture2D() + { + for (auto&& image : images) + vkDestroyImage(instance.GetDevice(), image, nullptr); + for (auto&& imageMemory : imageMemories) + vkFreeMemory(instance.GetDevice(), imageMemory, nullptr); + for (auto&& imageView : imageViews) + vkDestroyImageView(instance.GetDevice(), imageView, nullptr); + vkDestroySampler(instance.GetDevice(), sampler, nullptr); + } + + VkDescriptorImageInfo Texture2D::GetDescriptorImageInfo(int index) const + { + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.sampler = sampler; + + switch (type) { + case Type::Static: + imageInfo.imageView = imageViews.front(); break; - } - case Format::Depth: - { - VkFormat depthFormat = Image::SelectDepthFormat(instance); - Image::InitializeImage(instance, width, height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]); - // Image::TransitionImageLayout(instance, images[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - imageViews[i] = Image::InitializeImageView(instance, images[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + case Type::Dynamic: + CP_ASSERT(index >= 0 && index < imageViews.size(), "GetDescriptorImageInfo : index out of bound for dynamic texture"); + imageInfo.imageView = imageViews[index]; break; - } - case Format::Image: - { - CP_ABORT("InitializeTexture : Image format currently not supported"); - } default: - CP_ABORT("InitializeTexture : Unreachable switch case"); + CP_ABORT("GetDescriptorImageInfo : Unreachable switch case"); + } + + return imageInfo; + } + + VkImageView Texture2D::GetImageView() const + { + CP_ASSERT(type == Type::Static, "GetImageView : Texture2D is not static"); + return imageViews.front(); + } + + VkImageView Texture2D::GetImageView(int index) + { + CP_ASSERT(type == Type::Dynamic && index >= 0 && index < imageViews.size(), "GetImageView : Texture2D is not dynamic or index out of bound for SystemTexture"); + return imageViews[index]; + } + + void Texture2D::InitializeTextureImage(const std::string& filename) + { + int texWidth; + int texHeight; + int texChannels; + stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); + + CP_ASSERT(pixels, "InitializeTextureImage : Failed to load texture image"); + + VkDeviceSize bufferSize = texWidth * texHeight * 4; + Buffer stagingBuffer{instance, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1}; + void* data = stagingBuffer.Map(); + memcpy(data, pixels, bufferSize); + stagingBuffer.Unmap(); + stbi_image_free(pixels); + + images.resize(1); + imageMemories.resize(1); + imageViews.resize(1); + Image::InitializeImage(instance, texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images.front(), &imageMemories.front()); + Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + Image::CopyBufferToImage(instance, stagingBuffer, images.front(), texWidth, texHeight); + Image::TransitionImageLayout(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + imageViews[0] = Image::InitializeImageView(instance, images.front(), VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); + } + + void Texture2D::InitializeTexture(int width, int height) + { + int count = 1; + if (type == Type::Dynamic) + count = instance.GetMaxFramesInFlight(); + images.resize(count); + imageMemories.resize(count); + imageViews.resize(count); + for (size_t i = 0; i < images.size(); i++) + { + switch (format) + { + case Format::Color: + { + Image::InitializeImage(instance, width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]); + // Image::TransitionImageLayout(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + imageViews[i] = Image::InitializeImageView(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); + break; + } + case Format::Depth: + { + VkFormat depthFormat = Image::SelectDepthFormat(instance); + Image::InitializeImage(instance, width, height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &images[i], &imageMemories[i]); + // Image::TransitionImageLayout(instance, images[i], depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + imageViews[i] = Image::InitializeImageView(instance, images[i], depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + break; + } + case Format::Image: + { + CP_ABORT("InitializeTexture : Image format currently not supported"); + } + default: + CP_ABORT("InitializeTexture : Unreachable switch case"); + } } } -} - -void Texture2D::InitializeSampler() -{ - VkPhysicalDeviceProperties properties{}; - vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties); - - VkSamplerCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - createInfo.magFilter = VK_FILTER_LINEAR; - createInfo.minFilter = VK_FILTER_LINEAR; - createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - createInfo.anisotropyEnable = VK_TRUE; - createInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; - createInfo.unnormalizedCoordinates = VK_FALSE; - createInfo.compareEnable = VK_FALSE; - createInfo.compareOp = VK_COMPARE_OP_ALWAYS; - createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - createInfo.mipLodBias = 0.0f; - createInfo.minLod = 0.0f; - createInfo.maxLod = 0.0f; - - CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler"); + + void Texture2D::InitializeSampler() + { + VkPhysicalDeviceProperties properties{}; + vkGetPhysicalDeviceProperties(instance.GetPhysicalDevice(), &properties); + + VkSamplerCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + createInfo.magFilter = VK_FILTER_LINEAR; + createInfo.minFilter = VK_FILTER_LINEAR; + createInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + createInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + createInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + createInfo.anisotropyEnable = VK_TRUE; + createInfo.maxAnisotropy = properties.limits.maxSamplerAnisotropy; + createInfo.unnormalizedCoordinates = VK_FALSE; + createInfo.compareEnable = VK_FALSE; + createInfo.compareOp = VK_COMPARE_OP_ALWAYS; + createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + createInfo.mipLodBias = 0.0f; + createInfo.minLod = 0.0f; + createInfo.maxLod = 0.0f; + + CP_VK_ASSERT(vkCreateSampler(instance.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler"); + } } diff --git a/Vulkan/src/Texture2D.h b/Vulkan/src/Texture2D.h index b512619..049072d 100644 --- a/Vulkan/src/Texture2D.h +++ b/Vulkan/src/Texture2D.h @@ -6,40 +6,42 @@ #include "Image.h" #include "Instance.h" -// TODO: Separate Texture2D and Framebuffer Attachments -class Texture2D +namespace Copium { - CP_DELETE_COPY_AND_MOVE_CTOR(Texture2D); -public: - enum class Type + // TODO: Separate Texture2D and Framebuffer Attachments + class Texture2D { - Static, Dynamic + CP_DELETE_COPY_AND_MOVE_CTOR(Texture2D); + public: + enum class Type + { + Static, Dynamic + }; + + enum class Format + { + Image, Color, Depth + }; + private: + Instance& instance; + + std::vector images; + std::vector imageMemories; + std::vector imageViews; + VkSampler sampler; + Type type; + Format format; + public: + Texture2D(Instance& instance, const std::string& filename); + Texture2D(Instance& instance, int width, int height, Type type, Format format); + ~Texture2D(); + + VkDescriptorImageInfo GetDescriptorImageInfo(int index) const; + VkImageView GetImageView() const; + VkImageView GetImageView(int index); + private: + void InitializeTextureImage(const std::string& filename); + void InitializeTexture(int width, int height); + void InitializeSampler(); }; - - enum class Format - { - Image, Color, Depth - }; -private: - Instance& instance; - - std::vector images; - std::vector imageMemories; - std::vector imageViews; - VkSampler sampler; - Type type; - Format format; -public: - Texture2D(Instance& instance, const std::string& filename); - Texture2D(Instance& instance, int width, int height, Type type, Format format); - ~Texture2D(); - - VkDescriptorImageInfo GetDescriptorImageInfo(int index) const; - VkImageView GetImageView() const; - VkImageView GetImageView(int index); -private: - void InitializeTextureImage(const std::string& filename); - void InitializeTexture(int width, int height); - void InitializeSampler(); -}; - +} diff --git a/Vulkan/src/Timer.h b/Vulkan/src/Timer.h index b1d0e11..058d523 100644 --- a/Vulkan/src/Timer.h +++ b/Vulkan/src/Timer.h @@ -2,22 +2,25 @@ #include -class Timer +namespace Copium { -private: - std::chrono::time_point startTime; -public: - Timer() - : startTime{std::chrono::steady_clock::now()} - {} + class Timer + { + private: + std::chrono::time_point startTime; + public: + Timer() + : startTime{std::chrono::steady_clock::now()} + {} - void Start() - { - startTime = std::chrono::steady_clock::now(); - } + void Start() + { + startTime = std::chrono::steady_clock::now(); + } - double Elapsed() - { - return std::chrono::duration(std::chrono::high_resolution_clock::now() - startTime).count(); - } -}; + double Elapsed() + { + return std::chrono::duration(std::chrono::high_resolution_clock::now() - startTime).count(); + } + }; +} diff --git a/Vulkan/src/UniformBuffer.h b/Vulkan/src/UniformBuffer.h index 544b62d..413c808 100644 --- a/Vulkan/src/UniformBuffer.h +++ b/Vulkan/src/UniformBuffer.h @@ -4,28 +4,31 @@ #include "Buffer.h" #include -class UniformBuffer : public Buffer +namespace Copium { - CP_DELETE_COPY_AND_MOVE_CTOR(UniformBuffer); - -public: - UniformBuffer(Instance& instance, VkDeviceSize size) - : Buffer{instance, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, instance.GetMaxFramesInFlight()} - {} - - template - void Update(const T& t) + class UniformBuffer : public Buffer { - CP_ASSERT(sizeof(T) == Buffer::GetSize(), "Template size is not the same as buffer size %u != %u", sizeof(T), Buffer::GetSize()); - Buffer::Update((void*)&t, instance.GetFlightIndex()); - } + CP_DELETE_COPY_AND_MOVE_CTOR(UniformBuffer); - VkDescriptorBufferInfo GetDescriptorBufferInfo(int index) const - { - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = handle; - bufferInfo.offset = (VkDeviceSize)index * size; - bufferInfo.range = size; - return bufferInfo; - } -}; + public: + UniformBuffer(Instance& instance, VkDeviceSize size) + : Buffer{instance, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, size, instance.GetMaxFramesInFlight()} + {} + + template + void Update(const T& t) + { + CP_ASSERT(sizeof(T) == Buffer::GetSize(), "Template size is not the same as buffer size %u != %u", sizeof(T), Buffer::GetSize()); + Buffer::Update((void*)&t, instance.GetFlightIndex()); + } + + VkDescriptorBufferInfo GetDescriptorBufferInfo(int index) const + { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = handle; + bufferInfo.offset = (VkDeviceSize)index * size; + bufferInfo.range = size; + return bufferInfo; + } + }; +} diff --git a/Vulkan/src/Vertex.h b/Vulkan/src/Vertex.h index ae15341..0dc096a 100644 --- a/Vulkan/src/Vertex.h +++ b/Vulkan/src/Vertex.h @@ -4,18 +4,21 @@ #include #include "VertexDescriptor.h" -struct Vertex { - glm::vec3 pos; - glm::vec3 color; - glm::vec2 texCoord; +namespace Copium +{ + struct Vertex { + glm::vec3 pos; + glm::vec3 color; + glm::vec2 texCoord; - static VertexDescriptor GetDescriptor() - { - VertexDescriptor descriptor{}; - descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)); - descriptor.AddAttribute(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)); - descriptor.AddAttribute(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoord)); - return descriptor; - } -}; + static VertexDescriptor GetDescriptor() + { + VertexDescriptor descriptor{}; + descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos)); + descriptor.AddAttribute(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)); + descriptor.AddAttribute(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoord)); + return descriptor; + } + }; +} diff --git a/Vulkan/src/VertexBuffer.h b/Vulkan/src/VertexBuffer.h index 902170e..f237d0e 100644 --- a/Vulkan/src/VertexBuffer.h +++ b/Vulkan/src/VertexBuffer.h @@ -3,33 +3,36 @@ #include "Buffer.h" #include "VertexDescriptor.h" -class VertexBuffer : public Buffer +namespace Copium { - CP_DELETE_COPY_AND_MOVE_CTOR(VertexBuffer); -private: - std::vector bindingOffsets; - std::vector bindingSizes; -public: - VertexBuffer(Instance& instance, const VertexDescriptor& descriptor, int vertexCount) - : Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, descriptor.GetVertexSize() * vertexCount, 1} + class VertexBuffer : public Buffer { - VkDeviceSize offset = 0; - for (auto&& binding : descriptor.GetBindings()) + CP_DELETE_COPY_AND_MOVE_CTOR(VertexBuffer); + private: + std::vector bindingOffsets; + std::vector bindingSizes; + public: + VertexBuffer(Instance& instance, const VertexDescriptor& descriptor, int vertexCount) + : Buffer{instance, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, descriptor.GetVertexSize() * vertexCount, 1} { - bindingOffsets.emplace_back(offset); - bindingSizes.emplace_back(binding.stride * vertexCount); - offset += binding.stride * vertexCount; + VkDeviceSize offset = 0; + for (auto&& binding : descriptor.GetBindings()) + { + bindingOffsets.emplace_back(offset); + bindingSizes.emplace_back(binding.stride * vertexCount); + offset += binding.stride * vertexCount; + } } - } - void Bind(const CommandBuffer& commandBuffer) override - { - std::vector buffers{bindingOffsets.size(), handle}; - vkCmdBindVertexBuffers(commandBuffer, 0, bindingOffsets.size(), buffers.data(), bindingOffsets.data()); - } + void Bind(const CommandBuffer& commandBuffer) override + { + std::vector buffers{bindingOffsets.size(), handle}; + vkCmdBindVertexBuffers(commandBuffer, 0, bindingOffsets.size(), buffers.data(), bindingOffsets.data()); + } - void Update(uint32_t binding, void* data) - { - UpdateStaging(data, bindingOffsets[binding], bindingSizes[binding]); - } -}; + void Update(uint32_t binding, void* data) + { + UpdateStaging(data, bindingOffsets[binding], bindingSizes[binding]); + } + }; +} diff --git a/Vulkan/src/VertexDescriptor.h b/Vulkan/src/VertexDescriptor.h index 79aef91..218ef1d 100644 --- a/Vulkan/src/VertexDescriptor.h +++ b/Vulkan/src/VertexDescriptor.h @@ -2,59 +2,61 @@ #include #include - -class VertexDescriptor +namespace Copium { -private: - uint32_t bindingIndex = 0; - std::vector bindings; - std::vector attributes; - -public: - template - void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset) + class VertexDescriptor { - CP_ASSERT(binding <= bindings.size(), "Attribute binding must less than or be equal to the amount of current bindings"); + private: + uint32_t bindingIndex = 0; + std::vector bindings; + std::vector attributes; - if (binding == bindings.size()) - AddLayout(binding, sizeof(T)); - - VkVertexInputAttributeDescription description{}; - description.binding = binding; - description.location = location; - description.format = format; - description.offset = offset; - attributes.emplace_back(description); - } - - VkDeviceSize GetVertexSize() const - { - VkDeviceSize bufferSize = 0; - for (auto&& binding : bindings) + public: + template + void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset) { - bufferSize += binding.stride; + CP_ASSERT(binding <= bindings.size(), "Attribute binding must less than or be equal to the amount of current bindings"); + + if (binding == bindings.size()) + AddLayout(binding, sizeof(T)); + + VkVertexInputAttributeDescription description{}; + description.binding = binding; + description.location = location; + description.format = format; + description.offset = offset; + attributes.emplace_back(description); } - return bufferSize; - } - const std::vector& GetAttributes() const - { - return attributes; - } + VkDeviceSize GetVertexSize() const + { + VkDeviceSize bufferSize = 0; + for (auto&& binding : bindings) + { + bufferSize += binding.stride; + } + return bufferSize; + } - const std::vector& GetBindings() const - { - return bindings; - } + const std::vector& GetAttributes() const + { + return attributes; + } -private: - uint32_t AddLayout(uint32_t binding, uint32_t size) - { - VkVertexInputBindingDescription description{}; - description.binding = binding; - description.stride = size; - description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - bindings.emplace_back(description); - return description.binding; - } -}; + const std::vector& GetBindings() const + { + return bindings; + } + + private: + uint32_t AddLayout(uint32_t binding, uint32_t size) + { + VkVertexInputBindingDescription description{}; + description.binding = binding; + description.stride = size; + description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + bindings.emplace_back(description); + return description.binding; + } + }; +} diff --git a/Vulkan/src/VertexPassthrough.h b/Vulkan/src/VertexPassthrough.h index e47c549..d9aefad 100644 --- a/Vulkan/src/VertexPassthrough.h +++ b/Vulkan/src/VertexPassthrough.h @@ -4,13 +4,16 @@ #include #include "VertexDescriptor.h" -struct VertexPassthrough { - glm::vec2 texCoord; +namespace Copium +{ + struct VertexPassthrough { + glm::vec2 texCoord; - static VertexDescriptor GetDescriptor() - { - VertexDescriptor descriptor{}; - descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough , texCoord)); - return descriptor; - } -}; + static VertexDescriptor GetDescriptor() + { + VertexDescriptor descriptor{}; + descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough, texCoord)); + return descriptor; + } + }; +} diff --git a/Vulkan/src/VulkanException.h b/Vulkan/src/VulkanException.h index 1e32957..018874c 100644 --- a/Vulkan/src/VulkanException.h +++ b/Vulkan/src/VulkanException.h @@ -2,10 +2,13 @@ #include -class VulkanException : public std::runtime_error +namespace Copium { -public: - VulkanException(const std::string& str) - : runtime_error{str.c_str()} - {} -}; + class VulkanException : public std::runtime_error + { + public: + VulkanException(const std::string& str) + : runtime_error{str.c_str()} + {} + }; +} diff --git a/Vulkan/src/Window.h b/Vulkan/src/Window.h deleted file mode 100644 index a27107a..0000000 --- a/Vulkan/src/Window.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -class Window -{ - -}; diff --git a/Vulkan/src/main.cpp b/Vulkan/src/main.cpp index 1685def..f3906e9 100644 --- a/Vulkan/src/main.cpp +++ b/Vulkan/src/main.cpp @@ -1,250 +1,15 @@ -#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 "Application.h" +#include "Common.h" #include "Timer.h" -#include "UniformBuffer.h" -#include "Vertex.h" -#include "VertexBuffer.h" -#include "VertexPassthrough.h" #include -#include -#include -#include -#include -#include -#include -#include - -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, CommandBufferType::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); - } -}; - -void func(const int* ptr) { - *const_cast(ptr) = 20; -} int main() { CP_ASSERT(glfwInit() == GLFW_TRUE, "main : Failed to initialize the glfw context"); { - Application application; - Timer timer; + Copium::Application application; + Copium::Timer timer; int frames = 0; while (application.Update()) {