From ef4eb7dd2f0d11a1c47c60ff93bb3bc9f9238901 Mon Sep 17 00:00:00 2001 From: Thraix Date: Tue, 7 Feb 2023 20:58:58 +0100 Subject: [PATCH] Add cpp file for all classes --- Vulkan/Vulkan.vcxproj | 25 ++ Vulkan/src/Application.cpp | 197 +++++++++++++ Vulkan/src/Application.h | 218 +-------------- Vulkan/src/Buffer.cpp | 139 ++++++++++ Vulkan/src/Buffer.h | 157 +---------- Vulkan/src/ColorAttachment.cpp | 52 ++++ Vulkan/src/ColorAttachment.h | 53 +--- Vulkan/src/CommandBuffer.cpp | 76 +++++ Vulkan/src/CommandBuffer.h | 81 +----- Vulkan/src/CommandBufferScoped.cpp | 16 ++ Vulkan/src/CommandBufferScoped.h | 14 +- Vulkan/src/Common.h | 3 + Vulkan/src/DebugMessenger.cpp | 86 ++++++ Vulkan/src/DebugMessenger.h | 76 +---- Vulkan/src/DepthAttachment.cpp | 40 +++ Vulkan/src/DepthAttachment.h | 42 +-- Vulkan/src/DescriptorPool.cpp | 50 ++++ Vulkan/src/DescriptorPool.h | 49 +--- Vulkan/src/DescriptorSet.cpp | 57 ++++ Vulkan/src/DescriptorSet.h | 56 +--- Vulkan/src/FileSystem.cpp | 66 +++++ Vulkan/src/FileSystem.h | 69 +---- Vulkan/src/Framebuffer.cpp | 192 +++++++++++++ Vulkan/src/Framebuffer.h | 199 +------------ Vulkan/src/Image.cpp | 177 ++++++++++++ Vulkan/src/Image.h | 182 +----------- Vulkan/src/IndexBuffer.cpp | 23 ++ Vulkan/src/IndexBuffer.h | 19 +- Vulkan/src/Instance.cpp | 408 +++++++++++++++++++++++++++ Vulkan/src/Instance.h | 432 +++-------------------------- Vulkan/src/Pipeline.cpp | 209 ++++++++++++++ Vulkan/src/Pipeline.h | 218 +-------------- Vulkan/src/PipelineCreator.cpp | 38 +++ Vulkan/src/PipelineCreator.h | 38 +-- Vulkan/src/QueueFamilies.cpp | 35 +++ Vulkan/src/QueueFamilies.h | 32 +-- Vulkan/src/Sampler.cpp | 40 +++ Vulkan/src/Sampler.h | 39 +-- Vulkan/src/Shader.cpp | 133 +++++++++ Vulkan/src/Shader.h | 137 +-------- Vulkan/src/Texture2D.h | 2 +- Vulkan/src/Timer.cpp | 18 ++ Vulkan/src/Timer.h | 15 +- Vulkan/src/UniformBuffer.cpp | 17 ++ Vulkan/src/UniformBuffer.h | 33 +-- Vulkan/src/Vertex.cpp | 13 + Vulkan/src/Vertex.h | 13 +- Vulkan/src/VertexBuffer.cpp | 27 ++ Vulkan/src/VertexBuffer.h | 31 +-- Vulkan/src/VertexDescriptor.cpp | 51 ++++ Vulkan/src/VertexDescriptor.h | 52 +--- Vulkan/src/VertexPassthrough.cpp | 11 + Vulkan/src/VertexPassthrough.h | 11 +- 53 files changed, 2424 insertions(+), 2043 deletions(-) create mode 100644 Vulkan/src/Application.cpp create mode 100644 Vulkan/src/Buffer.cpp create mode 100644 Vulkan/src/ColorAttachment.cpp create mode 100644 Vulkan/src/CommandBuffer.cpp create mode 100644 Vulkan/src/CommandBufferScoped.cpp create mode 100644 Vulkan/src/DebugMessenger.cpp create mode 100644 Vulkan/src/DepthAttachment.cpp create mode 100644 Vulkan/src/DescriptorPool.cpp create mode 100644 Vulkan/src/DescriptorSet.cpp create mode 100644 Vulkan/src/FileSystem.cpp create mode 100644 Vulkan/src/Framebuffer.cpp create mode 100644 Vulkan/src/Image.cpp create mode 100644 Vulkan/src/IndexBuffer.cpp create mode 100644 Vulkan/src/Instance.cpp create mode 100644 Vulkan/src/Pipeline.cpp create mode 100644 Vulkan/src/PipelineCreator.cpp create mode 100644 Vulkan/src/QueueFamilies.cpp create mode 100644 Vulkan/src/Sampler.cpp create mode 100644 Vulkan/src/Shader.cpp create mode 100644 Vulkan/src/Timer.cpp create mode 100644 Vulkan/src/UniformBuffer.cpp create mode 100644 Vulkan/src/Vertex.cpp create mode 100644 Vulkan/src/VertexBuffer.cpp create mode 100644 Vulkan/src/VertexDescriptor.cpp create mode 100644 Vulkan/src/VertexPassthrough.cpp diff --git a/Vulkan/Vulkan.vcxproj b/Vulkan/Vulkan.vcxproj index 08b5691..79956fb 100644 --- a/Vulkan/Vulkan.vcxproj +++ b/Vulkan/Vulkan.vcxproj @@ -163,9 +163,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Vulkan/src/Application.cpp b/Vulkan/src/Application.cpp new file mode 100644 index 0000000..dbc7483 --- /dev/null +++ b/Vulkan/src/Application.cpp @@ -0,0 +1,197 @@ +#include "Application.h" + +#include "Vertex.h" +#include "VertexPassthrough.h" + +#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; + }; + + Application::Application() + { + InitializeInstance(); + InitializeFrameBuffer(); + InitializeGraphicsPipeline(); + InitializeTextureSampler(); + InitializeUniformBuffer(); + InitializeDescriptorSets(); + InitializeVertexBuffer(); + InitializeIndexBuffer(); + InitializeCommandBuffer(); + } + + Application::~Application() + { + vkDeviceWaitIdle(instance->GetDevice()); + } + + bool Application::Update() + { + if (framebuffer->GetWidth() != instance->GetSwapChain().GetExtent().width || framebuffer->GetHeight() != instance->GetSwapChain().GetExtent().height) + { + framebuffer->Resize(instance->GetSwapChain().GetExtent().width / 8, instance->GetSwapChain().GetExtent().height / 8); + descriptorSetPassthrough->AddSampler(framebuffer->GetColorAttachment(), 0); + } + if (!instance->BeginPresent()) + { + return true; + } + + RecordCommandBuffer(); + commandBuffer->SubmitAsGraphicsQueue(); + + return instance->EndPresent(); + } + + void Application::InitializeInstance() + { + instance = std::make_unique("Copium Engine"); + } + + void Application::InitializeFrameBuffer() + { + framebuffer = std::make_unique(*instance, instance->GetSwapChain().GetExtent().width, instance->GetSwapChain().GetExtent().height); + } + + void Application::InitializeTextureSampler() + { + texture2D = std::make_unique(*instance, "res/textures/texture.png"); + } + + void Application::InitializeUniformBuffer() + { + shaderUniformBuffer = std::make_unique(*instance, sizeof(ShaderUniform)); + } + + void Application::InitializeDescriptorSets() + { + descriptorPool = std::make_unique(*instance); + + descriptorSet = std::make_unique(*instance, *descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0)); + descriptorSet->AddUniform(*shaderUniformBuffer, 0); + descriptorSet->AddSampler(*texture2D, 1); + + descriptorSetPassthrough = std::make_unique(*instance, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0)); + descriptorSetPassthrough->AddSampler(framebuffer->GetColorAttachment(), 0); + } + + void Application::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 Application::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 Application::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 Application::InitializeCommandBuffer() + { + commandBuffer = std::make_unique(*instance, CommandBuffer::Type::Dynamic); + } + + void Application::RecordCommandBuffer() + { + commandBuffer->Begin(); + + framebuffer->Bind(*commandBuffer); + graphicsPipeline->Bind(*commandBuffer); + + UpdateUniformBuffer(); + + vertexBuffer->Bind(*commandBuffer); + indexBuffer->Bind(*commandBuffer); + + graphicsPipeline->SetDescriptorSet(0, *descriptorSet); + graphicsPipeline->BindDescriptorSets(*commandBuffer); + + indexBuffer->Draw(*commandBuffer); + framebuffer->Unbind(*commandBuffer); + + instance->GetSwapChain().BeginFrameBuffer(*commandBuffer); + + graphicsPipelinePassthrough->Bind(*commandBuffer); + graphicsPipelinePassthrough->SetDescriptorSet(0, *descriptorSetPassthrough); + graphicsPipelinePassthrough->BindDescriptorSets(*commandBuffer); + vertexBufferPassthrough->Bind(*commandBuffer); + indexBufferPassthrough->Bind(*commandBuffer); + indexBufferPassthrough->Draw(*commandBuffer); + + instance->GetSwapChain().EndFrameBuffer(*commandBuffer); + commandBuffer->End(); + } + + void Application::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), framebuffer->GetWidth() / (float)framebuffer->GetHeight(), 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); + } +} \ No newline at end of file diff --git a/Vulkan/src/Application.h b/Vulkan/src/Application.h index 02187c2..ef3eac1 100644 --- a/Vulkan/src/Application.h +++ b/Vulkan/src/Application.h @@ -1,6 +1,5 @@ #pragma once -#include "Buffer.h" #include "DescriptorPool.h" #include "DescriptorSet.h" #include "Framebuffer.h" @@ -8,58 +7,14 @@ #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 { + CP_DELETE_COPY_AND_MOVE_CTOR(Application); private: std::unique_ptr instance; std::unique_ptr graphicsPipeline; @@ -78,164 +33,21 @@ namespace Copium 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 (framebuffer->GetWidth() != instance->GetSwapChain().GetExtent().width || framebuffer->GetHeight() != instance->GetSwapChain().GetExtent().height) - { - framebuffer->Resize(instance->GetSwapChain().GetExtent().width / 8, instance->GetSwapChain().GetExtent().height / 8); - descriptorSetPassthrough->AddSampler(framebuffer->GetColorAttachment(), 0); - } - if (!instance->BeginPresent()) - { - return true; - } - - RecordCommandBuffer(); - commandBuffer->SubmitAsGraphicsQueue(); - - return instance->EndPresent(); - } + Application(); + ~Application(); + bool Update(); 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->AddSampler(*texture2D, 1); - - descriptorSetPassthrough = std::make_unique(*instance, *descriptorPool, graphicsPipelinePassthrough->GetDescriptorSetLayout(0)); - descriptorSetPassthrough->AddSampler(framebuffer->GetColorAttachment(), 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(); - - 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), framebuffer->GetWidth() / (float)framebuffer->GetHeight(), 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 InitializeInstance(); + void InitializeFrameBuffer(); + void InitializeTextureSampler(); + void InitializeUniformBuffer(); + void InitializeDescriptorSets(); + void InitializeGraphicsPipeline(); + void InitializeVertexBuffer(); + void InitializeIndexBuffer(); + void InitializeCommandBuffer(); + void RecordCommandBuffer(); + void UpdateUniformBuffer(); }; } diff --git a/Vulkan/src/Buffer.cpp b/Vulkan/src/Buffer.cpp new file mode 100644 index 0000000..391561f --- /dev/null +++ b/Vulkan/src/Buffer.cpp @@ -0,0 +1,139 @@ +#include "Buffer.h" + +namespace Copium +{ + Buffer::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), "Buffer : 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), "Buffer : Failed to allocate buffer memory"); + + vkBindBufferMemory(instance.GetDevice(), handle, memory, 0); + } + + Buffer::~Buffer() + { + vkFreeMemory(instance.GetDevice(), memory, nullptr); + vkDestroyBuffer(instance.GetDevice(), handle, nullptr); + } + + void Buffer::Update(void* indexData, int index) + { + CP_ASSERT(index >= 0 && index < count, "Update : 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 Buffer::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 Buffer::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* Buffer::Map() + { + CP_ASSERT(mappedData == nullptr, "Map : Mapping an already mapped buffer"); + vkMapMemory(instance.GetDevice(), memory, 0, size * count, 0, &mappedData); + return mappedData; + } + + void Buffer::Unmap() + { + CP_ASSERT(mappedData != nullptr, "Unmap : Unmapping an already unmapped buffer"); + + vkUnmapMemory(instance.GetDevice(), memory); + mappedData = nullptr; + } + + Buffer::operator VkBuffer() const + { + return handle; + } + + VkDeviceSize Buffer::GetSize() const + { + return size; + } + + VkDeviceSize Buffer::GetPosition(int index) const + { + CP_ASSERT(index >= 0 && index < count, "GetPosition : Index is outside of the buffer"); + return size * (VkDeviceSize)index; + } + + void Buffer::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), "CopyBuffer : 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, dstBuffer, 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); + } +} diff --git a/Vulkan/src/Buffer.h b/Vulkan/src/Buffer.h index 4d8fd83..b265ac5 100644 --- a/Vulkan/src/Buffer.h +++ b/Vulkan/src/Buffer.h @@ -2,7 +2,7 @@ #include "Common.h" #include "Instance.h" -#include + #include namespace Copium @@ -21,153 +21,20 @@ namespace Copium 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; + Buffer(Instance& instance, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkDeviceSize size, int count); + virtual ~Buffer(); - CP_VK_ASSERT(vkCreateBuffer(instance.GetDevice(), &createInfo, nullptr, &handle), "Buffer : Failed to initialize buffer"); + void Update(void* indexData, int index); + void UpdateStaging(void* data); + void UpdateStaging(void* data, VkDeviceSize offset, VkDeviceSize size); - VkMemoryRequirements memoryRequirements; - vkGetBufferMemoryRequirements(instance.GetDevice(), handle, &memoryRequirements); + void* Map(); + void Unmap(); - VkMemoryAllocateInfo allocateInfo{}; - allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocateInfo.allocationSize = memoryRequirements.size; - allocateInfo.memoryTypeIndex = instance.FindMemoryType(memoryRequirements.memoryTypeBits, properties); + operator VkBuffer() const; + VkDeviceSize GetSize() const; + VkDeviceSize GetPosition(int index) const; - CP_VK_ASSERT(vkAllocateMemory(instance.GetDevice(), &allocateInfo, nullptr, &memory), "Buffer : 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, "Update : 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, "Map : Mapping an already mapped buffer"); - vkMapMemory(instance.GetDevice(), memory, 0, size * count, 0, &mappedData); - return mappedData; - } - - void Unmap() - { - CP_ASSERT(mappedData != nullptr, "Unmap : Unmapping an already unmapped buffer"); - - vkUnmapMemory(instance.GetDevice(), memory); - mappedData = nullptr; - } - - virtual void Bind(const CommandBuffer& commandBuffer) { CP_UNIMPLEMENTED(); }; - - void BindAsVertexBuffer(VkCommandBuffer commandBuffer) - { - VkDeviceSize offset = 0; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, &handle, &offset); - } - - void BindAsIndexBuffer(VkCommandBuffer commandBuffer) - { - // TODO: Maybe don't assume that indices are uint16? - vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16); - } - - VkBuffer GetHandle() const - { - return handle; - } - - VkDeviceSize GetSize() const - { - return size; - } - - VkDeviceSize GetPosition(int index) const - { - CP_ASSERT(index >= 0 && index < count, "GetPosition : 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), "CopyBuffer : 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); - } + static void CopyBuffer(Instance& instance, const Buffer& srcBuffer, const Buffer& dstBuffer, VkDeviceSize offset, VkDeviceSize size); }; } diff --git a/Vulkan/src/ColorAttachment.cpp b/Vulkan/src/ColorAttachment.cpp new file mode 100644 index 0000000..9e3e349 --- /dev/null +++ b/Vulkan/src/ColorAttachment.cpp @@ -0,0 +1,52 @@ +#include "ColorAttachment.h" + +#include "Image.h" + +namespace Copium +{ + ColorAttachment::ColorAttachment(Instance& instance, int width, int height) + : Sampler{instance} + { + InitializeColorAttachment(width, height); + } + + ColorAttachment::~ColorAttachment() + { + 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); + } + + VkDescriptorImageInfo ColorAttachment::GetDescriptorImageInfo(int index) const + { + CP_ASSERT(index >= 0 && index < imageViews.size(), "GetDescriptorImageInfo : index out of bound for color attachment"); + + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.sampler = sampler; + imageInfo.imageView = imageViews[index]; + return imageInfo; + } + + VkImageView ColorAttachment::GetImageView(int index) + { + CP_ASSERT(index >= 0 && index < imageViews.size(), "GetImageView : Index out of bound"); + + return imageViews[index]; + } + + void ColorAttachment::InitializeColorAttachment(int width, int height) + { + images.resize(instance.GetMaxFramesInFlight()); + imageMemories.resize(instance.GetMaxFramesInFlight()); + imageViews.resize(instance.GetMaxFramesInFlight()); + for (size_t i = 0; i < images.size(); i++) + { + 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]); + imageViews[i] = Image::InitializeImageView(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); + } + } +} diff --git a/Vulkan/src/ColorAttachment.h b/Vulkan/src/ColorAttachment.h index dbebede..08fe257 100644 --- a/Vulkan/src/ColorAttachment.h +++ b/Vulkan/src/ColorAttachment.h @@ -2,12 +2,13 @@ #include "Common.h" #include "Instance.h" -#include "Image.h" #include "Sampler.h" +#include + namespace Copium { - class ColorAttachment : public Sampler + class ColorAttachment final : public Sampler { CP_DELETE_COPY_AND_MOVE_CTOR(ColorAttachment); private: @@ -15,51 +16,13 @@ namespace Copium std::vector imageMemories; std::vector imageViews; public: - ColorAttachment(Instance& instance, int width, int height) - : Sampler{instance} - { - InitializeColorAttachment(width, height); - } + ColorAttachment(Instance& instance, int width, int height); + ~ColorAttachment() override; - ~ColorAttachment() override - { - 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); - } - - VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override - { - CP_ASSERT(index >= 0 && index < imageViews.size(), "GetDescriptorImageInfo : index out of bound for color attachment"); - - VkDescriptorImageInfo imageInfo{}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.sampler = sampler; - imageInfo.imageView = imageViews[index]; - return imageInfo; - } - - VkImageView GetImageView(int index) - { - CP_ASSERT(index >= 0 && index < imageViews.size(), "GetImageView : Index out of bound"); - - return imageViews[index]; - } + VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override; + VkImageView GetImageView(int index); private: - void InitializeColorAttachment(int width, int height) - { - images.resize(instance.GetMaxFramesInFlight()); - imageMemories.resize(instance.GetMaxFramesInFlight()); - imageViews.resize(instance.GetMaxFramesInFlight()); - for (size_t i = 0; i < images.size(); i++) - { - 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]); - imageViews[i] = Image::InitializeImageView(instance, images[i], VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); - } - } + void InitializeColorAttachment(int width, int height); }; } diff --git a/Vulkan/src/CommandBuffer.cpp b/Vulkan/src/CommandBuffer.cpp new file mode 100644 index 0000000..ccc35a5 --- /dev/null +++ b/Vulkan/src/CommandBuffer.cpp @@ -0,0 +1,76 @@ +#include "CommandBuffer.h" + +namespace Copium +{ + CommandBuffer::CommandBuffer(Instance& instance, Type type) + : instance{instance}, type{type} + { + if (type == Type::Dynamic) + commandBuffers.resize(instance.GetMaxFramesInFlight()); + else + commandBuffers.resize(1); + + 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()), "CommandBuffer : Failed to allocate CommandBuffer"); + } + + CommandBuffer::~CommandBuffer() + { + vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), commandBuffers.size(), commandBuffers.data()); + } + + // TODO: Test as constexpr function to see if it avoids the switch case + void CommandBuffer::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_ABORT("Begin : Unreachable switch case"); + } + + vkResetCommandBuffer(currentCommandBuffer, 0); + CP_VK_ASSERT(vkBeginCommandBuffer(currentCommandBuffer, &beginInfo), "Begin : Failed to begin command buffer"); + } + + void CommandBuffer::End() + { + vkEndCommandBuffer(currentCommandBuffer); + } + + void CommandBuffer::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 CommandBuffer::SubmitAsGraphicsQueue() + { + instance.SubmitGraphicsQueue({currentCommandBuffer}); + } + + CommandBuffer::operator VkCommandBuffer() const + { + return currentCommandBuffer; + } +} \ No newline at end of file diff --git a/Vulkan/src/CommandBuffer.h b/Vulkan/src/CommandBuffer.h index f4a78dc..f73240d 100644 --- a/Vulkan/src/CommandBuffer.h +++ b/Vulkan/src/CommandBuffer.h @@ -2,6 +2,7 @@ #include "Common.h" #include "Instance.h" + #include namespace Copium @@ -22,81 +23,15 @@ namespace Copium VkCommandBuffer currentCommandBuffer{VK_NULL_HANDLE}; public: - CommandBuffer(Instance& instance, Type type) - : instance{instance}, type{type} - { - if (type == Type::Dynamic) - commandBuffers.resize(instance.GetMaxFramesInFlight()); - else - commandBuffers.resize(1); + CommandBuffer(Instance& instance, Type 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()), "CommandBuffer : Failed to allocate CommandBuffer"); - } + virtual ~CommandBuffer(); - ~CommandBuffer() - { - vkFreeCommandBuffers(instance.GetDevice(), instance.GetCommandPool(), commandBuffers.size(), commandBuffers.data()); - } + void Begin(); + void End(); + void Submit(); + void SubmitAsGraphicsQueue(); - 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 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_ABORT("Begin : Unreachable switch case"); - } - - vkResetCommandBuffer(currentCommandBuffer, 0); - CP_VK_ASSERT(vkBeginCommandBuffer(currentCommandBuffer, &beginInfo), "Begin : Failed to begin command buffer"); - } - - void End() - { - vkEndCommandBuffer(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; - } + operator VkCommandBuffer() const; }; } diff --git a/Vulkan/src/CommandBufferScoped.cpp b/Vulkan/src/CommandBufferScoped.cpp new file mode 100644 index 0000000..e3c9b98 --- /dev/null +++ b/Vulkan/src/CommandBufferScoped.cpp @@ -0,0 +1,16 @@ +#include "CommandBufferScoped.h" + +namespace Copium +{ + CommandBufferScoped::CommandBufferScoped(Instance& instance) + : CommandBuffer{instance, Type::SingleUse} + { + CommandBuffer::Begin(); + } + + CommandBufferScoped::~CommandBufferScoped() + { + CommandBuffer::End(); + CommandBuffer::Submit(); + } +} diff --git a/Vulkan/src/CommandBufferScoped.h b/Vulkan/src/CommandBufferScoped.h index 4422404..35d432e 100644 --- a/Vulkan/src/CommandBufferScoped.h +++ b/Vulkan/src/CommandBufferScoped.h @@ -5,20 +5,12 @@ namespace Copium { - class CommandBufferScoped : public CommandBuffer + class CommandBufferScoped final : public CommandBuffer { CP_DELETE_COPY_AND_MOVE_CTOR(CommandBufferScoped); public: - CommandBufferScoped(Instance& instance) - : CommandBuffer{instance, Type::SingleUse} - { - CommandBuffer::Begin(); - } + CommandBufferScoped(Instance& instance); - ~CommandBufferScoped() - { - CommandBuffer::End(); - CommandBuffer::Submit(); - } + ~CommandBufferScoped() override; }; } diff --git a/Vulkan/src/Common.h b/Vulkan/src/Common.h index 881dafa..52c429f 100644 --- a/Vulkan/src/Common.h +++ b/Vulkan/src/Common.h @@ -45,6 +45,9 @@ throw VulkanException(Copium::StringFormat(format, __VA_ARGS__)); \ } \ } while(false) + +#define CP_STATIC_CLASS(ClassName)\ + ClassName() = delete #define CP_DELETE_COPY_AND_MOVE_CTOR(ClassName) \ ClassName(ClassName&&) = delete; \ ClassName(const ClassName&) = delete; \ diff --git a/Vulkan/src/DebugMessenger.cpp b/Vulkan/src/DebugMessenger.cpp new file mode 100644 index 0000000..fb69295 --- /dev/null +++ b/Vulkan/src/DebugMessenger.cpp @@ -0,0 +1,86 @@ +#include "DebugMessenger.h" + +namespace Copium +{ +#ifndef NDEBUG + DebugMessenger::DebugMessenger(VkInstance instance) + : instance{instance} + { + 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), "DebugMessenger : Failed to initialze debug messenger"); + } + + DebugMessenger::~DebugMessenger() + { + vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + } + + void DebugMessenger::AddRequiredExtensions(std::vector* extensions) + { + extensions->emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + + void DebugMessenger::AddRequiredLayers(std::vector* layers) + { + layers->emplace_back("VK_LAYER_KHRONOS_validation"); + } +#else + DebugMessenger::DebugMessenger(VkInstance instance) + : instance{instance} + {} + + DebugMessenger::~DebugMessenger() + {} + + void DebugMessenger::AddRequiredExtensions(std::vector* extensions) + {} + + void DebugMessenger::AddRequiredLayers(std::vector* layers) + {} +#endif + + VKAPI_ATTR VkBool32 VKAPI_CALL DebugMessenger::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) + { + if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) + { + if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + CP_ABORT("DebugCallback : %s", pCallbackData->pMessage); + else + CP_WARN("DebugCallback : %s", pCallbackData->pMessage); + } + return VK_FALSE; + } + + VkResult DebugMessenger::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; + } + + void DebugMessenger::vkDestroyDebugUtilsMessengerEXT(VkInstance instance, + VkDebugUtilsMessengerEXT debugMessenger, + const VkAllocationCallbacks* pAllocator) { + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + if (func != nullptr) { + func(instance, debugMessenger, pAllocator); + } + } + +} \ No newline at end of file diff --git a/Vulkan/src/DebugMessenger.h b/Vulkan/src/DebugMessenger.h index 0156c95..abf772a 100644 --- a/Vulkan/src/DebugMessenger.h +++ b/Vulkan/src/DebugMessenger.h @@ -1,89 +1,41 @@ #pragma once #include "Common.h" + +#include + namespace Copium { - class DebugMessenger + class DebugMessenger final { CP_DELETE_COPY_AND_MOVE_CTOR(DebugMessenger); public: VkInstance instance; VkDebugUtilsMessengerEXT debugMessenger; - DebugMessenger(VkInstance instance) - : instance{instance} - { - #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), "DebugMessenger : Failed to initialze debug messenger"); - #endif - } + DebugMessenger(VkInstance instance); + ~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 - } + static void AddRequiredExtensions(std::vector* extensions); + static void AddRequiredLayers(std::vector* layers); + 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) - { - if (messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) - CP_ABORT("DebugCallback : %s", pCallbackData->pMessage); - else - CP_WARN("DebugCallback : %s", pCallbackData->pMessage); - } - return VK_FALSE; - } + void* pUserData); + 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; - } + VkDebugUtilsMessengerEXT* pDebugMessenger); + static void vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, - const VkAllocationCallbacks* pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != nullptr) { - func(instance, debugMessenger, pAllocator); - } - } + const VkAllocationCallbacks* pAllocator); }; } diff --git a/Vulkan/src/DepthAttachment.cpp b/Vulkan/src/DepthAttachment.cpp new file mode 100644 index 0000000..d4cff2d --- /dev/null +++ b/Vulkan/src/DepthAttachment.cpp @@ -0,0 +1,40 @@ +#include "DepthAttachment.h" + +#include "Image.h" + +namespace Copium +{ + DepthAttachment::DepthAttachment(Instance& instance, int width, int height) + : Sampler{instance} + { + InitializeDepthAttachment(width, height); + } + + DepthAttachment::~DepthAttachment() + { + vkDestroyImage(instance.GetDevice(), image, nullptr); + vkFreeMemory(instance.GetDevice(), imageMemory, nullptr); + vkDestroyImageView(instance.GetDevice(), imageView, nullptr); + } + + VkDescriptorImageInfo DepthAttachment::GetDescriptorImageInfo(int index) const + { + VkDescriptorImageInfo imageInfo{}; + imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfo.sampler = sampler; + imageInfo.imageView = imageView; + return imageInfo; + } + + VkImageView DepthAttachment::GetImageView() const + { + return imageView; + } + + void DepthAttachment::InitializeDepthAttachment(int width, int height) + { + VkFormat depthFormat = Image::SelectDepthFormat(instance); + Image::InitializeImage(instance, width, height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory); + imageView = Image::InitializeImageView(instance, image, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + } +} \ No newline at end of file diff --git a/Vulkan/src/DepthAttachment.h b/Vulkan/src/DepthAttachment.h index bc08d31..61ae094 100644 --- a/Vulkan/src/DepthAttachment.h +++ b/Vulkan/src/DepthAttachment.h @@ -2,12 +2,13 @@ #include "Common.h" #include "Instance.h" -#include "Image.h" #include "Sampler.h" +#include + namespace Copium { - class DepthAttachment : public Sampler + class DepthAttachment final : public Sampler { CP_DELETE_COPY_AND_MOVE_CTOR(DepthAttachment); private: @@ -15,39 +16,14 @@ namespace Copium VkDeviceMemory imageMemory; VkImageView imageView; public: - DepthAttachment(Instance& instance, int width, int height) - : Sampler{instance} - { - InitializeDepthAttachment(width, height); - } + DepthAttachment(Instance& instance, int width, int height); + ~DepthAttachment() override; - ~DepthAttachment() override - { - vkDestroyImage(instance.GetDevice(), image, nullptr); - vkFreeMemory(instance.GetDevice(), imageMemory, nullptr); - vkDestroyImageView(instance.GetDevice(), imageView, nullptr); - } - - VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override - { - VkDescriptorImageInfo imageInfo{}; - imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - imageInfo.sampler = sampler; - imageInfo.imageView = imageView; - return imageInfo; - } - - VkImageView GetImageView() const - { - return imageView; - } + VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override; + VkImageView GetImageView() const; private: - void InitializeDepthAttachment(int width, int height) - { - VkFormat depthFormat = Image::SelectDepthFormat(instance); - Image::InitializeImage(instance, width, height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory); - imageView = Image::InitializeImageView(instance, image, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); - } + void InitializeDepthAttachment(int width, int height); + }; } diff --git a/Vulkan/src/DescriptorPool.cpp b/Vulkan/src/DescriptorPool.cpp new file mode 100644 index 0000000..7fcb6ec --- /dev/null +++ b/Vulkan/src/DescriptorPool.cpp @@ -0,0 +1,50 @@ +#include "DescriptorPool.h" + +namespace Copium +{ + DescriptorPool::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? + + poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER; + poolSizes[1].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; + + CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "DescriptorPool : Failed to initialize descriptor pool"); + } + + DescriptorPool::~DescriptorPool() + { + vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr); + } + + std::vector DescriptorPool::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(); + + descriptorSets.resize(instance.GetMaxFramesInFlight()); + CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "AllocateDescriptorSets : Failed to allocate descriptor sets"); + + return descriptorSets; + } + + void DescriptorPool::FreeDescriptorSets(const std::vector& descriptorSets) + { + vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data()); + } +} \ No newline at end of file diff --git a/Vulkan/src/DescriptorPool.h b/Vulkan/src/DescriptorPool.h index ea2ec78..998df55 100644 --- a/Vulkan/src/DescriptorPool.h +++ b/Vulkan/src/DescriptorPool.h @@ -2,6 +2,7 @@ #include "Common.h" #include "Instance.h" + #include namespace Copium @@ -15,50 +16,10 @@ namespace Copium 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? + DescriptorPool(Instance& instance); + ~DescriptorPool(); - poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLER; - poolSizes[1].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; - - CP_VK_ASSERT(vkCreateDescriptorPool(instance.GetDevice(), &createInfo, nullptr, &descriptorPool), "DescriptorPool : Failed to initialize descriptor pool"); - } - - ~DescriptorPool() - { - vkDestroyDescriptorPool(instance.GetDevice(), descriptorPool, nullptr); - } - - 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(); - - descriptorSets.resize(instance.GetMaxFramesInFlight()); - CP_VK_ASSERT(vkAllocateDescriptorSets(instance.GetDevice(), &allocateInfo, descriptorSets.data()), "AllocateDescriptorSets : Failed to allocate descriptor sets"); - - return descriptorSets; - } - - void FreeDescriptorSets(const std::vector& descriptorSets) - { - vkFreeDescriptorSets(instance.GetDevice(), descriptorPool, descriptorSets.size(), descriptorSets.data()); - } + std::vector AllocateDescriptorSets(VkDescriptorSetLayout descriptorSetLayout); + void FreeDescriptorSets(const std::vector& descriptorSets); }; } diff --git a/Vulkan/src/DescriptorSet.cpp b/Vulkan/src/DescriptorSet.cpp new file mode 100644 index 0000000..8ab50d4 --- /dev/null +++ b/Vulkan/src/DescriptorSet.cpp @@ -0,0 +1,57 @@ +#include "DescriptorSet.h" + +namespace Copium +{ + DescriptorSet::DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout) + : instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout} + { + descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout); + } + + DescriptorSet::~DescriptorSet() + { + descriptorPool.FreeDescriptorSets(descriptorSets); + } + + void DescriptorSet::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 DescriptorSet::AddSampler(const Sampler& sampler, uint32_t binding) + { + for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) { + VkDescriptorImageInfo imageInfo = sampler.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::operator VkDescriptorSet() const + { + return descriptorSets[instance.GetFlightIndex()]; + } +} \ No newline at end of file diff --git a/Vulkan/src/DescriptorSet.h b/Vulkan/src/DescriptorSet.h index b548a12..14cadf2 100644 --- a/Vulkan/src/DescriptorSet.h +++ b/Vulkan/src/DescriptorSet.h @@ -20,57 +20,11 @@ namespace Copium std::vector descriptorSets; public: - DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout) - : instance{instance}, descriptorPool{descriptorPool}, descriptorSetLayout{descriptorSetLayout} - { - descriptorSets = descriptorPool.AllocateDescriptorSets(descriptorSetLayout); - } + DescriptorSet(Instance& instance, DescriptorPool& descriptorPool, VkDescriptorSetLayout descriptorSetLayout); + ~DescriptorSet(); - ~DescriptorSet() - { - descriptorPool.FreeDescriptorSets(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); - } - } - - void AddSampler(const Sampler& sampler, uint32_t binding) - { - for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) { - VkDescriptorImageInfo imageInfo = sampler.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()]; - } + void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding); + void AddSampler(const Sampler& sampler, uint32_t binding); + operator VkDescriptorSet() const; }; } \ No newline at end of file diff --git a/Vulkan/src/FileSystem.cpp b/Vulkan/src/FileSystem.cpp new file mode 100644 index 0000000..88db09f --- /dev/null +++ b/Vulkan/src/FileSystem.cpp @@ -0,0 +1,66 @@ +#include "FileSystem.h" + +namespace Copium +{ + std::vector FileSystem::ReadFile(const std::string& filename) + { + std::ifstream file(filename, std::ios::ate | std::ios::binary); + CP_ASSERT(file.is_open(), "ReadFile : Failed to open file"); + + size_t fileSize = (size_t)file.tellg(); + std::vector buffer(fileSize); + + file.seekg(0); + file.read(buffer.data(), fileSize); + + return buffer; + } + + std::string FileSystem::ReadFileStr(const std::string& filename) + { + std::ifstream file(filename, std::ios::ate | std::ios::binary); + CP_ASSERT(file.is_open(), "ReadFileStr : Failed to open file"); + + size_t fileSize = (size_t)file.tellg(); + std::string buffer; + buffer.resize(fileSize); + + file.seekg(0); + file.read(buffer.data(), fileSize); + + return buffer; + } + + void FileSystem::WriteFile(const std::string& filename, const std::string& data) + { + std::filesystem::path path{filename}; + std::filesystem::create_directories(path.parent_path()); + std::ofstream file(filename, std::ios::binary); + CP_ASSERT(file.is_open(), "WriteFile : Failed to open file"); + + file.write(data.c_str(), data.size()); + } + + void FileSystem::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(), "WriteFile : Failed to open file"); + + file.write(data, size); + } + + bool FileSystem::FileExists(const std::string& filename) + { + std::ifstream file(filename); + return file.good(); + } + + int64_t FileSystem::DateModified(const std::string& filename) + { + struct stat result; + CP_ASSERT(stat(filename.c_str(), &result) == 0, "DataModified : Cannot stat file %s", filename.c_str()); + return (int64_t)result.st_mtime; + } +} \ No newline at end of file diff --git a/Vulkan/src/FileSystem.h b/Vulkan/src/FileSystem.h index 11fb42a..db0b8bc 100644 --- a/Vulkan/src/FileSystem.h +++ b/Vulkan/src/FileSystem.h @@ -12,68 +12,13 @@ namespace Copium { class FileSystem { - FileSystem() = delete; + CP_STATIC_CLASS(FileSystem); public: - static std::vector ReadFile(const std::string& filename) - { - std::ifstream file(filename, std::ios::ate | std::ios::binary); - CP_ASSERT(file.is_open(), "ReadFile : Failed to open file"); - - size_t fileSize = (size_t)file.tellg(); - std::vector buffer(fileSize); - - file.seekg(0); - file.read(buffer.data(), fileSize); - - 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(), "ReadFileStr : Failed to open file"); - - size_t fileSize = (size_t)file.tellg(); - std::string buffer; - buffer.resize(fileSize); - - file.seekg(0); - file.read(buffer.data(), fileSize); - - return buffer; - } - - static void WriteFile(const std::string& filename, const std::string& data) - { - std::filesystem::path path{filename}; - std::filesystem::create_directories(path.parent_path()); - std::ofstream file(filename, std::ios::binary); - CP_ASSERT(file.is_open(), "WriteFile : Failed to open file"); - - 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(), "WriteFile : Failed to open file"); - - file.write(data, size); - } - - 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, "DataModified : Cannot stat file %s", filename.c_str()); - return (int64_t)result.st_mtime; - } + static std::vector ReadFile(const std::string& filename); + static std::string ReadFileStr(const std::string& filename); + static void WriteFile(const std::string& filename, const std::string& data); + static void WriteFile(const std::string& filename, const char* data, size_t size); + static bool FileExists(const std::string& filename); + static int64_t DateModified(const std::string& filename); }; } \ No newline at end of file diff --git a/Vulkan/src/Framebuffer.cpp b/Vulkan/src/Framebuffer.cpp new file mode 100644 index 0000000..e430219 --- /dev/null +++ b/Vulkan/src/Framebuffer.cpp @@ -0,0 +1,192 @@ +#include "Framebuffer.h" + +#include "CommandBuffer.h" +#include "Image.h" + +namespace Copium +{ + Framebuffer::Framebuffer(Instance& instance, uint32_t width, uint32_t height) + : instance{instance}, width{width}, height{height} + { + InitializeImage(); + InitializeDepthBuffer(); + InitializeRenderPass(); + InitializeFramebuffers(); + } + + Framebuffer::~Framebuffer() + { + for (auto& framebuffer : framebuffers) + vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); + vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr); + } + + void Framebuffer::Resize(uint32_t width, uint32_t height) + { + vkDeviceWaitIdle(instance.GetDevice()); + this->width = width; + this->height = height; + colorAttachment.reset(); + depthAttachment.reset(); + for (auto&& framebuffer : framebuffers) + vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); + InitializeImage(); + InitializeDepthBuffer(); + InitializeFramebuffers(); + } + + void Framebuffer::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); + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = width; + viewport.height = height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = {width, height}; + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + } + + void Framebuffer::Unbind(const CommandBuffer& commandBuffer) + { + vkCmdEndRenderPass(commandBuffer); + } + + VkRenderPass Framebuffer::GetRenderPass() const + { + return renderPass; + } + + VkFramebuffer Framebuffer::GetFramebuffer() const + { + return framebuffers[instance.GetFlightIndex()]; + } + + const ColorAttachment& Framebuffer::GetColorAttachment() const + { + return *colorAttachment; + } + + uint32_t Framebuffer::GetWidth() const + { + return width; + } + + uint32_t Framebuffer::GetHeight() const + { + return height; + } + + void Framebuffer::InitializeImage() + { + colorAttachment = std::make_unique(instance, width, height); + } + + void Framebuffer::InitializeDepthBuffer() + { + depthAttachment = std::make_unique(instance, width, height); + } + + void Framebuffer::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 Framebuffer::InitializeFramebuffers() + { + framebuffers.resize(instance.GetMaxFramesInFlight()); + + for (size_t i = 0; i < instance.GetMaxFramesInFlight(); ++i) + { + std::vector attachments{colorAttachment->GetImageView(i), depthAttachment->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 framebuffer"); + } + } +} \ No newline at end of file diff --git a/Vulkan/src/Framebuffer.h b/Vulkan/src/Framebuffer.h index 4c446c7..408f861 100644 --- a/Vulkan/src/Framebuffer.h +++ b/Vulkan/src/Framebuffer.h @@ -1,7 +1,6 @@ #pragma once #include "Common.h" -#include "Image.h" #include "Instance.h" #include "ColorAttachment.h" #include "DepthAttachment.h" @@ -10,7 +9,7 @@ namespace Copium { - class Framebuffer + class Framebuffer final { CP_DELETE_COPY_AND_MOVE_CTOR(Framebuffer); private: @@ -24,191 +23,23 @@ namespace Copium uint32_t width; uint32_t height; public: - Framebuffer(Instance& instance, uint32_t width, uint32_t height) - : instance{instance}, width{width}, height{height} - { - InitializeImage(); - InitializeDepthBuffer(); - InitializeRenderPass(); - InitializeFramebuffers(); - } + Framebuffer(Instance& instance, uint32_t width, uint32_t height); + ~Framebuffer(); - ~Framebuffer() - { - for (auto& framebuffer : framebuffers) - vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); - vkDestroyRenderPass(instance.GetDevice(), renderPass, nullptr); - } + void Resize(uint32_t width, uint32_t height); + void Bind(const CommandBuffer& commandBuffer); + void Unbind(const CommandBuffer& commandBuffer); - void Resize(uint32_t width, uint32_t height) - { - vkDeviceWaitIdle(instance.GetDevice()); - this->width = width; - this->height = height; - colorAttachment.reset(); - depthAttachment.reset(); - for (auto&& framebuffer : framebuffers) - vkDestroyFramebuffer(instance.GetDevice(), framebuffer, nullptr); - InitializeImage(); - InitializeDepthBuffer(); - InitializeFramebuffers(); - } - - 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); - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = width; - viewport.height = height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = {width, height}; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - } - - void Unbind(const CommandBuffer& commandBuffer) - { - vkCmdEndRenderPass(commandBuffer); - } - - VkRenderPass GetRenderPass() const - { - return renderPass; - } - - VkFramebuffer GetFramebuffer() const - { - return framebuffers[instance.GetFlightIndex()]; - } - - const ColorAttachment& GetColorAttachment() const - { - return *colorAttachment; - } - - uint32_t GetWidth() const - { - return width; - } - - uint32_t GetHeight() const - { - return height; - } + VkRenderPass GetRenderPass() const; + VkFramebuffer GetFramebuffer() const; + const ColorAttachment& GetColorAttachment() const; + uint32_t GetWidth() const; + uint32_t GetHeight() const; private: - - void InitializeImage() - { - colorAttachment = std::make_unique(instance, width, height); - } - - void InitializeDepthBuffer() - { - depthAttachment = std::make_unique(instance, width, height); - } - - 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{colorAttachment->GetImageView(i), depthAttachment->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 framebuffer"); - } - } + void InitializeImage(); + void InitializeDepthBuffer(); + void InitializeRenderPass(); + void InitializeFramebuffers(); }; } \ No newline at end of file diff --git a/Vulkan/src/Image.cpp b/Vulkan/src/Image.cpp new file mode 100644 index 0000000..b8f93b3 --- /dev/null +++ b/Vulkan/src/Image.cpp @@ -0,0 +1,177 @@ +#include "Image.h" + +#include "CommandBufferScoped.h" + +namespace Copium +{ + void Image::InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory) + { + 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); + } + + VkImageView Image::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; + } + + void Image::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); + } + + void Image::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, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } + + + VkFormat Image::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); + } + + bool Image::HasStencilComponent(VkFormat format) + { + return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; + } + + VkFormat Image::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"); + } +} diff --git a/Vulkan/src/Image.h b/Vulkan/src/Image.h index 1aa669e..e78b57f 100644 --- a/Vulkan/src/Image.h +++ b/Vulkan/src/Image.h @@ -1,187 +1,25 @@ #pragma once -#include #include "Buffer.h" #include "Common.h" -#include "CommandBufferScoped.h" #include "Instance.h" +#include + namespace Copium { class Image { - Image() = delete; + CP_STATIC_CLASS(Image); public: - static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory) - { - VkImageCreateInfo createInfo{}; - 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 - { - 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); - } + static void InitializeImage(Instance& instance, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage* image, VkDeviceMemory* imageMemory); + static VkImageView InitializeImageView(Instance& instance, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags); + static void TransitionImageLayout(Instance& instance, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout); + static void CopyBufferToImage(Instance& instance, const Buffer& buffer, VkImage image, uint32_t width, uint32_t height); + static VkFormat SelectDepthFormat(Instance& instance); 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"); - } + static bool HasStencilComponent(VkFormat format); + static VkFormat SelectSupportedFormat(Instance& instance, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features); }; } \ No newline at end of file diff --git a/Vulkan/src/IndexBuffer.cpp b/Vulkan/src/IndexBuffer.cpp new file mode 100644 index 0000000..d90d4a0 --- /dev/null +++ b/Vulkan/src/IndexBuffer.cpp @@ -0,0 +1,23 @@ +#include "IndexBuffer.h" + +#include "CommandBuffer.h" + +#include + +namespace Copium +{ + IndexBuffer::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 IndexBuffer::Bind(const CommandBuffer& commandBuffer) + { + vkCmdBindIndexBuffer(commandBuffer, handle, 0, VK_INDEX_TYPE_UINT16); + } + + void IndexBuffer::Draw(const CommandBuffer& commandBuffer) + { + vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); + } +} \ No newline at end of file diff --git a/Vulkan/src/IndexBuffer.h b/Vulkan/src/IndexBuffer.h index 0fcbced..08e9bbe 100644 --- a/Vulkan/src/IndexBuffer.h +++ b/Vulkan/src/IndexBuffer.h @@ -1,27 +1,20 @@ #pragma once #include "Buffer.h" +#include "Common.h" +#include "Instance.h" namespace Copium { - class IndexBuffer : public Buffer + class IndexBuffer final : public Buffer { 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} - {} + IndexBuffer(Instance& instance, int indexCount); - 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); - } + void Bind(const CommandBuffer& commandBuffer); + void Draw(const CommandBuffer& commandBuffer); }; } \ No newline at end of file diff --git a/Vulkan/src/Instance.cpp b/Vulkan/src/Instance.cpp new file mode 100644 index 0000000..2c4426b --- /dev/null +++ b/Vulkan/src/Instance.cpp @@ -0,0 +1,408 @@ +#include "Instance.h" + +namespace Copium +{ + Instance::Instance(const std::string& applicationName) + { + timer.Start(); + InitializeWindow(applicationName); + InitializeInstance(applicationName); + InitializeDebugMessenger(); + InitializeSurface(); + SelectPhysicalDevice(); + InitializeLogicalDevice(); + InitializeCommandPool(); + InitializeSwapChain(); + InitializeSyncObjects(); + CP_INFO("Instance : Initialized Vulkan in %f seconds", timer.Elapsed()); + } + + Instance::~Instance() + { + 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); + } + + bool Instance::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 Instance::EndPresent() + { + swapChain->EndPresent(presentQueue, &renderFinishedSemaphores[flightIndex], framebufferResized); + + framebufferResized = false; + flightIndex = (flightIndex + 1) % MAX_FRAMES_IN_FLIGHT; + return !glfwWindowShouldClose(window); + } + + void Instance::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]), "SubmitGraphicsQueue : Failed to submit command buffer"); + } + + VkInstance Instance::GetInstance() const + { + return instance; + } + + GLFWwindow* Instance::GetWindow() const + { + return window; + } + + VkSurfaceKHR Instance::GetSurface() const + { + return surface; + } + + VkPhysicalDevice Instance::GetPhysicalDevice() const + { + return physicalDevice; + } + + VkDevice Instance::GetDevice() const + { + return device; + } + + VkCommandPool Instance::GetCommandPool() const + { + return commandPool; + } + + VkQueue Instance::GetGraphicsQueue() const + { + return graphicsQueue; + } + + int Instance::GetFlightIndex() const + { + return flightIndex; + } + + int Instance::GetMaxFramesInFlight() const + { + return MAX_FRAMES_IN_FLIGHT; + } + + const SwapChain& Instance::GetSwapChain() const + { + return *swapChain; + } + + uint32_t Instance::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; + } + CP_ABORT("FindMemoryType : Failed to find suitable memory type"); + } + + void Instance::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); +#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); +#else + window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, applicationName.c_str(), nullptr, nullptr); +#endif + CP_ASSERT(window, "InitializeWindow : Failed to initialize glfw window"); + + glfwSetWindowUserPointer(window, this); + glfwSetFramebufferSizeCallback(window, FramebufferResizeCallback); + } + + void Instance::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("InitiaizeInstace : Supported Extensions:"); + for (auto&& extension : extensions) + { + CP_INFO_CONT("\t%s", extension.extensionName); + } + + std::vector layers{}; + DebugMessenger::AddRequiredLayers(&layers); + CP_ASSERT(CheckLayerSupport(layers), "InitializeInstance : 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), "InitializeInstance : Failed to create instance"); + } + + void Instance::InitializeDebugMessenger() + { + debugMessenger = std::make_unique(instance); + } + + void Instance::InitializeSurface() + { + CP_VK_ASSERT(glfwCreateWindowSurface(instance, window, nullptr, &surface), "InitializeSurface : Failed to create Vulkan surface"); + } + + void Instance::SelectPhysicalDevice() + { + uint32_t deviceCount; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + CP_ASSERT(deviceCount != 0, "SelectPhysicaDevice : No available devices support Vulkan"); + + std::vector devices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + CP_INFO("SelectPhysicaDevice : Available devices:"); + for (auto&& device : devices) + { + VkPhysicalDeviceProperties deviceProperties; + vkGetPhysicalDeviceProperties(device, &deviceProperties); + CP_INFO_CONT("\t%s", deviceProperties.deviceName); + } + for (auto&& device : devices) + { + if (IsPhysicalDeviceSuitable(device)) + { + VkPhysicalDeviceProperties deviceProperties; + vkGetPhysicalDeviceProperties(device, &deviceProperties); + physicalDevice = device; + CP_INFO("SelectPhysicaDevice : Selecting device: %s", deviceProperties.deviceName); + break; + } + } + CP_ASSERT(physicalDevice != VK_NULL_HANDLE, "SelectPhysicaDevice : Failed to find suitable GPU"); + } + + void Instance::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), "InitializeLogicalDevice : Failed to initialize logical device"); + + graphicsQueueIndex = query.graphicsFamily.value(); + presentQueueIndex = query.presentFamily.value(); + vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue); + vkGetDeviceQueue(device, presentQueueIndex, 0, &presentQueue); + } + + void Instance::InitializeSwapChain() + { + swapChain = std::make_unique(*this); + } + + void Instance::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), "InitializeCommandPool : Failed to initialize command pool"); + } + + void Instance::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]), "InitializeSyncObjects : Failed to initialize available image semaphore"); + CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]), "InitializeSyncObjects : 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]), "InitializeSyncObjects : Failed to initialize in flight fence"); + } + } + + std::vector Instance::GetRequiredExtensions() + { + uint32_t glfwExtensionCount; + const char** glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + + std::vector extensions{glfwExtensions, glfwExtensions + glfwExtensionCount}; + + debugMessenger->AddRequiredExtensions(&extensions); + + return extensions; + } + + bool Instance::CheckLayerSupport(const std::vector& layers) + { + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + CP_INFO("CheckLayerSupport : Supported Layers:"); + for (auto&& availableLayer : availableLayers) + { + CP_INFO_CONT("\t%s", availableLayer.layerName); + } + + for (auto&& layer : layers) + { + bool layerFound = false; + for (auto&& availableLayer : availableLayers) + { + if (std::strcmp(layer, availableLayer.layerName) == 0) + { + layerFound = true; + break; + } + } + if (!layerFound) + return false; + } + return true; + } + + bool Instance::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 Instance::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 Instance::GetRequiredDeviceExtensions() + { + return {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; + } + + void Instance::FramebufferResizeCallback(GLFWwindow* window, int width, int height) + { + Instance* instance = static_cast(glfwGetWindowUserPointer(window)); + instance->framebufferResized = true; + } +} \ No newline at end of file diff --git a/Vulkan/src/Instance.h b/Vulkan/src/Instance.h index d42e944..4d241bd 100644 --- a/Vulkan/src/Instance.h +++ b/Vulkan/src/Instance.h @@ -41,410 +41,40 @@ namespace Copium Timer timer; public: - Instance(const std::string& applicationName) - { - timer.Start(); - InitializeWindow(applicationName); - InitializeInstance(applicationName); - InitializeDebugMessenger(); - InitializeSurface(); - SelectPhysicalDevice(); - InitializeLogicalDevice(); - InitializeCommandPool(); - InitializeSwapChain(); - InitializeSyncObjects(); - CP_INFO("Instance : Initialized Vulkan in %f seconds", timer.Elapsed()); - } - - ~Instance() - { - 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); - } - - 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]), "SubmitGraphicsQueue : 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; - } - + Instance(const std::string& applicationName); + ~Instance(); + bool BeginPresent(); + bool EndPresent(); + void SubmitGraphicsQueue(const std::vector& commandBuffers); + VkInstance GetInstance() const; + GLFWwindow* GetWindow() const; + VkSurfaceKHR GetSurface() const; + VkPhysicalDevice GetPhysicalDevice() const; + VkDevice GetDevice() const; + VkCommandPool GetCommandPool() const; + VkQueue GetGraphicsQueue() const; + int GetFlightIndex() const; + int GetMaxFramesInFlight() const; + const SwapChain& GetSwapChain() const; // 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; - } - CP_ABORT("FindMemoryType : Failed to find suitable memory type"); - } + uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); private: - void InitializeWindow(const std::string& applicationName) - { - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + void InitializeWindow(const std::string& applicationName); + void InitializeInstance(const std::string& applicationName); + void InitializeDebugMessenger(); + void InitializeSurface(); + void SelectPhysicalDevice(); + void InitializeLogicalDevice(); + void InitializeSwapChain(); + void InitializeCommandPool(); + void InitializeSyncObjects(); + std::vector GetRequiredExtensions(); + bool CheckLayerSupport(const std::vector& layers); + bool IsPhysicalDeviceSuitable(VkPhysicalDevice device); + bool CheckDeviceExtensionSupport(VkPhysicalDevice device); + std::vector GetRequiredDeviceExtensions(); + static void FramebufferResizeCallback(GLFWwindow* window, int width, int height); - -#if defined(FULLSCREEN) - 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); -#else - window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, applicationName.c_str(), nullptr, nullptr); -#endif - CP_ASSERT(window, "InitializeWindow : 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("InitiaizeInstace : Supported Extensions:"); - for (auto&& extension : extensions) - { - CP_INFO_CONT("\t%s", extension.extensionName); - } - - std::vector layers{}; - DebugMessenger::AddRequiredLayers(&layers); - CP_ASSERT(CheckLayerSupport(layers), "InitializeInstance : 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), "InitializeInstance : Failed to create instance"); - } - - void InitializeDebugMessenger() - { - debugMessenger = std::make_unique(instance); - } - - void InitializeSurface() - { - CP_VK_ASSERT(glfwCreateWindowSurface(instance, window, nullptr, &surface), "InitializeSurface : Failed to create Vulkan surface"); - } - - void SelectPhysicalDevice() - { - uint32_t deviceCount; - vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); - CP_ASSERT(deviceCount != 0, "SelectPhysicaDevice : No available devices support Vulkan"); - - std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); - CP_INFO("SelectPhysicaDevice : Available devices:"); - for (auto&& device : devices) - { - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(device, &deviceProperties); - CP_INFO_CONT("\t%s", deviceProperties.deviceName); - } - for (auto&& device : devices) - { - if (IsPhysicalDeviceSuitable(device)) - { - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(device, &deviceProperties); - physicalDevice = device; - CP_INFO("SelectPhysicaDevice : Selecting device: %s", deviceProperties.deviceName); - break; - } - } - CP_ASSERT(physicalDevice != VK_NULL_HANDLE, "SelectPhysicaDevice : 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), "InitializeLogicalDevice : 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), "InitializeCommandPool : 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]), "InitializeSyncObjects : Failed to initialize available image semaphore"); - CP_VK_ASSERT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &renderFinishedSemaphores[i]), "InitializeSyncObjects : 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]), "InitializeSyncObjects : 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("CheckLayerSupport : Supported Layers:"); - for (auto&& availableLayer : availableLayers) - { - CP_INFO_CONT("\t%s", availableLayer.layerName); - } - - for (auto&& layer : layers) - { - bool layerFound = false; - for (auto&& availableLayer : availableLayers) - { - if (std::strcmp(layer, availableLayer.layerName) == 0) - { - layerFound = true; - break; - } - } - 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) - { - 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.cpp b/Vulkan/src/Pipeline.cpp new file mode 100644 index 0000000..c832052 --- /dev/null +++ b/Vulkan/src/Pipeline.cpp @@ -0,0 +1,209 @@ +#include "Pipeline.h" + +#include "FileSystem.h" +#include "Shader.h" + +namespace Copium +{ + Pipeline::Pipeline(Instance& instance, PipelineCreator creator) + : instance{instance} + { + InitializeDescriptorSetLayout(creator); + InitializePipeline(creator); + } + + Pipeline::~Pipeline() + { + vkDestroyPipeline(instance.GetDevice(), graphicsPipeline, nullptr); + vkDestroyPipelineLayout(instance.GetDevice(), pipelineLayout, nullptr); + for (auto&& descriptorSetLayout : descriptorSetLayouts) + { + vkDestroyDescriptorSetLayout(instance.GetDevice(), descriptorSetLayout, nullptr); + } + } + + void Pipeline::Bind(const CommandBuffer& commandBuffer) + { + vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + } + + void Pipeline::SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet) + { + CP_ASSERT(setIndex < boundDescriptorSets.size(), "SetDescriptorSet : DescriptorSet index is out of bounds"); + boundDescriptorSets[setIndex] = descriptorSet; + } + + void Pipeline::BindDescriptorSets(const CommandBuffer& commandBuffer) + { + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, boundDescriptorSets.size(), boundDescriptorSets.data(), 0, nullptr); + } + + VkDescriptorSetLayout Pipeline::GetDescriptorSetLayout(uint32_t setIndex) const + { + return descriptorSetLayouts[setIndex]; + } + + void Pipeline::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++; + } + + 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++]), "InitializeDescriptorSetLayout : Failed to initialize descriptor set layout"); + } + } + + void Pipeline::InitializePipeline(const PipelineCreator& creator) + { + Shader shader{instance, Shader::Type::GlslFile, creator.vertexShader, creator.fragmentShader}; + + 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(); + + VkPipelineInputAssemblyStateCreateInfo inputAssemblyCreateInfo{}; + inputAssemblyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssemblyCreateInfo.topology = creator.topology; + inputAssemblyCreateInfo.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport{}; + viewport.x = 0; + viewport.y = 0; + viewport.width = 1; + viewport.height = 1; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = {1, 1}; + + 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; + + 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; + + CP_VK_ASSERT(vkCreatePipelineLayout(instance.GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout), "InitializePipeline : 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; + + CP_VK_ASSERT(vkCreateGraphicsPipelines(instance.GetDevice(), VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &graphicsPipeline), "InitializePipeline : Failed to initialize graphics pipeline"); + } +} \ No newline at end of file diff --git a/Vulkan/src/Pipeline.h b/Vulkan/src/Pipeline.h index 6b9f060..9691fd4 100644 --- a/Vulkan/src/Pipeline.h +++ b/Vulkan/src/Pipeline.h @@ -1,19 +1,17 @@ #pragma once -#include "Common.h" #include "CommandBuffer.h" -#include "Instance.h" -#include "FileSystem.h" +#include "Common.h" #include "DescriptorSet.h" +#include "Instance.h" #include "PipelineCreator.h" -#include "Shader.h" +#include #include -#include namespace Copium { - class Pipeline + class Pipeline final { CP_DELETE_COPY_AND_MOVE_CTOR(Pipeline); private: @@ -25,207 +23,15 @@ namespace Copium VkPipeline graphicsPipeline; public: - Pipeline(Instance& instance, PipelineCreator creator) - : instance{instance} - { - InitializeDescriptorSetLayout(creator); - InitializePipeline(creator); - } - - ~Pipeline() - { - vkDestroyPipeline(instance.GetDevice(), graphicsPipeline, nullptr); - vkDestroyPipelineLayout(instance.GetDevice(), pipelineLayout, nullptr); - for (auto&& descriptorSetLayout : descriptorSetLayouts) - { - vkDestroyDescriptorSetLayout(instance.GetDevice(), descriptorSetLayout, nullptr); - } - } - - void Bind(const CommandBuffer& commandBuffer) - { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); - } - - void SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet) - { - CP_ASSERT(setIndex < boundDescriptorSets.size(), "SetDescriptorSet : 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]; - } + Pipeline(Instance& instance, PipelineCreator creator); + ~Pipeline(); + void Bind(const CommandBuffer& commandBuffer); + void SetDescriptorSet(uint32_t setIndex, const DescriptorSet& descriptorSet); + void BindDescriptorSets(const CommandBuffer& commandBuffer); + VkDescriptorSetLayout GetDescriptorSetLayout(uint32_t setIndex) const; 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++; - } - - 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++]), "InitializeDescriptorSetLayout : Failed to initialize descriptor set layout"); - } - } - - void InitializePipeline(const PipelineCreator& creator) - { - Shader shader{instance, Shader::Type::GlslFile, creator.vertexShader, creator.fragmentShader}; - - 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(); - - VkPipelineInputAssemblyStateCreateInfo inputAssemblyCreateInfo{}; - inputAssemblyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssemblyCreateInfo.topology = creator.topology; - inputAssemblyCreateInfo.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport{}; - viewport.x = 0; - viewport.y = 0; - viewport.width = 1; - viewport.height = 1; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = {1, 1}; - - 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; - - 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; - - CP_VK_ASSERT(vkCreatePipelineLayout(instance.GetDevice(), &pipelineLayoutCreateInfo, nullptr, &pipelineLayout), "InitializePipeline : 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; - - CP_VK_ASSERT(vkCreateGraphicsPipelines(instance.GetDevice(), VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &graphicsPipeline), "InitializePipeline : Failed to initialize graphics pipeline"); - } + void InitializeDescriptorSetLayout(const PipelineCreator& creator); + void InitializePipeline(const PipelineCreator& creator); }; } \ No newline at end of file diff --git a/Vulkan/src/PipelineCreator.cpp b/Vulkan/src/PipelineCreator.cpp new file mode 100644 index 0000000..0b62362 --- /dev/null +++ b/Vulkan/src/PipelineCreator.cpp @@ -0,0 +1,38 @@ +#include "PipelineCreator.h" + +#include "Common.h" + +namespace Copium +{ + PipelineCreator::PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader) + : vertexShader{vertexShader}, + fragmentShader{fragmentShader}, + renderPass{renderPass} + {} + + void PipelineCreator::SetVertexDescriptor(const VertexDescriptor& descriptor) + { + vertexDescriptor = descriptor; + } + + void PipelineCreator::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 PipelineCreator::SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology) + { + topology = primitiveTopology; + } + + void PipelineCreator::SetCullMode(VkCullModeFlags flags) + { + cullMode = flags; + } + + void PipelineCreator::SetCullFrontFace(VkFrontFace cullFrontFace) + { + frontFace = cullFrontFace; + } +} \ No newline at end of file diff --git a/Vulkan/src/PipelineCreator.h b/Vulkan/src/PipelineCreator.h index 6083e2b..a477dd9 100644 --- a/Vulkan/src/PipelineCreator.h +++ b/Vulkan/src/PipelineCreator.h @@ -1,10 +1,10 @@ #pragma once -#include "Common.h" #include "VertexDescriptor.h" -#include #include +#include +#include namespace Copium { @@ -30,34 +30,12 @@ namespace Copium VkRenderPass renderPass = VK_NULL_HANDLE; public: - PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader) - : vertexShader{vertexShader}, fragmentShader{fragmentShader}, renderPass{renderPass} - {} + PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader); - 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; - } + void SetVertexDescriptor(const VertexDescriptor& descriptor); + void AddDescriptorSetLayoutBinding(uint32_t set, uint32_t binding, VkDescriptorType type, uint32_t count, VkShaderStageFlags stageFlags); + void SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology); + void SetCullMode(VkCullModeFlags flags); + void SetCullFrontFace(VkFrontFace cullFrontFace); }; } diff --git a/Vulkan/src/QueueFamilies.cpp b/Vulkan/src/QueueFamilies.cpp new file mode 100644 index 0000000..73936ff --- /dev/null +++ b/Vulkan/src/QueueFamilies.cpp @@ -0,0 +1,35 @@ +#include "QueueFamilies.h" + +#include + +namespace Copium +{ + QueueFamiliesQuery::QueueFamiliesQuery(VkSurfaceKHR surface, VkPhysicalDevice device) + { + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); + std::vector queueFamilies(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); + + int i = 0; + for (auto&& queueFamily : queueFamilies) + { + if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + graphicsFamily = i; + } + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); + if (presentSupport) + { + presentFamily = i; + } + i++; + } + } + + bool QueueFamiliesQuery::AllRequiredFamiliesSupported() + { + return graphicsFamily.has_value() && presentFamily.has_value(); + } +} \ No newline at end of file diff --git a/Vulkan/src/QueueFamilies.h b/Vulkan/src/QueueFamilies.h index 66efa98..2d546ec 100644 --- a/Vulkan/src/QueueFamilies.h +++ b/Vulkan/src/QueueFamilies.h @@ -1,8 +1,7 @@ #pragma once -#include #include -#include +#include namespace Copium { @@ -11,33 +10,8 @@ namespace Copium std::optional graphicsFamily; std::optional presentFamily; - QueueFamiliesQuery(VkSurfaceKHR surface, VkPhysicalDevice device) - { - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); + QueueFamiliesQuery(VkSurfaceKHR surface, VkPhysicalDevice device); - int i = 0; - for (auto&& queueFamily : queueFamilies) - { - if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - graphicsFamily = 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(); }; } diff --git a/Vulkan/src/Sampler.cpp b/Vulkan/src/Sampler.cpp new file mode 100644 index 0000000..c3ea2ea --- /dev/null +++ b/Vulkan/src/Sampler.cpp @@ -0,0 +1,40 @@ +#include "Sampler.h" + +namespace Copium +{ + Sampler::Sampler(Instance& instance) + : instance{instance} + { + InitializeSampler(); + } + + Sampler::~Sampler() + { + vkDestroySampler(instance.GetDevice(), sampler, nullptr); + } + + void Sampler::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"); + } +} \ No newline at end of file diff --git a/Vulkan/src/Sampler.h b/Vulkan/src/Sampler.h index 0ccf392..14d22a0 100644 --- a/Vulkan/src/Sampler.h +++ b/Vulkan/src/Sampler.h @@ -14,42 +14,11 @@ namespace Copium Instance& instance; VkSampler sampler; public: - Sampler(Instance& instance) - : instance{instance} - { - InitializeSampler(); - } - - virtual ~Sampler() - { - vkDestroySampler(instance.GetDevice(), sampler, nullptr); - } - - void 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"); - } + Sampler(Instance& instance); + virtual ~Sampler(); virtual VkDescriptorImageInfo GetDescriptorImageInfo(int index) const = 0; + private: + void InitializeSampler(); }; } diff --git a/Vulkan/src/Shader.cpp b/Vulkan/src/Shader.cpp new file mode 100644 index 0000000..44e341b --- /dev/null +++ b/Vulkan/src/Shader.cpp @@ -0,0 +1,133 @@ +#include "Shader.h" + +#include "FileSystem.h" + +namespace Copium +{ + Shader::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, "Shader : 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"; + } + + Shader::~Shader() + { + vkDestroyShaderModule(instance.GetDevice(), vertShaderModule, nullptr); + vkDestroyShaderModule(instance.GetDevice(), fragShaderModule, nullptr); + } + + const std::vector Shader::GetShaderStages() const + { + return shaderStages; + } + + VkShaderModule Shader::InitializeShaderModule(const std::vector& codeSpv) + { + return InitializeShaderModule(codeSpv.data(), codeSpv.size() * sizeof(uint32_t)); + } + + VkShaderModule Shader::InitializeShaderModule(const std::string& codeSpv) + { + return InitializeShaderModule(reinterpret_cast(codeSpv.data()), codeSpv.size()); + } + + VkShaderModule Shader::InitializeShaderModule(const std::vector& codeSpv) + { + return InitializeShaderModule(reinterpret_cast(codeSpv.data()), codeSpv.size()); + } + + VkShaderModule Shader::InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind type) + { + std::string spvFilename = ".cache/" + filename + ".spv"; + try + { + if (FileSystem::FileExists(spvFilename)) + { + if (FileSystem::DateModified(filename) < FileSystem::DateModified(spvFilename)) + { + CP_DEBUG("InitializeShaderModuleFromGlslFile : 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("InitializeShaderModuleFromGlslFile : Cached shader file is invalid, recreating it"); + } + CP_DEBUG("InitializeShaderModuleFromGlslFile : 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, "InitializeShaderModuleFromGlslFile : 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)); + } + + VkShaderModule Shader::InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type) + { + 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, "InitializeShaderModuleFromGlslCode : 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 Shader::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), "InitializeShaderModule : Failed to initialize shader module"); + + return shaderModule; + } +} diff --git a/Vulkan/src/Shader.h b/Vulkan/src/Shader.h index 04de51d..6d318db 100644 --- a/Vulkan/src/Shader.h +++ b/Vulkan/src/Shader.h @@ -2,13 +2,12 @@ #include -#include "FileSystem.h" #include "Common.h" #include "Instance.h" namespace Copium { - class Shader + class Shader final { CP_DELETE_COPY_AND_MOVE_CTOR(Shader); public: @@ -24,132 +23,16 @@ namespace Copium 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, "Shader : 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"; - } - - ~Shader() - { - vkDestroyShaderModule(instance.GetDevice(), vertShaderModule, nullptr); - vkDestroyShaderModule(instance.GetDevice(), fragShaderModule, nullptr); - } - - const std::vector GetShaderStages() const - { - return shaderStages; - } + Shader(Instance& instance, Type type, const std::string& vertexInput, const std::string& fragmentInput); + ~Shader(); + const std::vector GetShaderStages() const; 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::FileExists(spvFilename)) - { - if (FileSystem::DateModified(filename) < FileSystem::DateModified(spvFilename)) - { - CP_DEBUG("InitializeShaderModuleFromGlslFile : 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("InitializeShaderModuleFromGlslFile : Cached shader file is invalid, recreating it"); - } - CP_DEBUG("InitializeShaderModuleFromGlslFile : 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, "InitializeShaderModuleFromGlslFile : 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)); - } - - VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type) - { - 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, "InitializeShaderModuleFromGlslCode : 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), "InitializeShaderModule : Failed to initialize shader module"); - - return shaderModule; - } + VkShaderModule InitializeShaderModule(const std::vector& codeSpv); + VkShaderModule InitializeShaderModule(const std::string& codeSpv); + VkShaderModule InitializeShaderModule(const std::vector& codeSpv); + VkShaderModule InitializeShaderModuleFromGlslFile(const std::string& filename, shaderc_shader_kind type); + VkShaderModule InitializeShaderModuleFromGlslCode(const std::string& code, shaderc_shader_kind type); + VkShaderModule InitializeShaderModule(const uint32_t* data, size_t size); }; } diff --git a/Vulkan/src/Texture2D.h b/Vulkan/src/Texture2D.h index b488bee..0059087 100644 --- a/Vulkan/src/Texture2D.h +++ b/Vulkan/src/Texture2D.h @@ -9,7 +9,7 @@ namespace Copium { - class Texture2D : public Sampler + class Texture2D final : public Sampler { CP_DELETE_COPY_AND_MOVE_CTOR(Texture2D); private: diff --git a/Vulkan/src/Timer.cpp b/Vulkan/src/Timer.cpp new file mode 100644 index 0000000..1b93b1e --- /dev/null +++ b/Vulkan/src/Timer.cpp @@ -0,0 +1,18 @@ +#include "Timer.h" + +namespace Copium +{ + Timer::Timer() + : startTime{std::chrono::steady_clock::now()} + {} + + void Timer::Start() + { + startTime = std::chrono::steady_clock::now(); + } + + double Timer::Elapsed() + { + return std::chrono::duration(std::chrono::high_resolution_clock::now() - startTime).count(); + } +} diff --git a/Vulkan/src/Timer.h b/Vulkan/src/Timer.h index 058d523..0a3b4fc 100644 --- a/Vulkan/src/Timer.h +++ b/Vulkan/src/Timer.h @@ -9,18 +9,9 @@ namespace Copium private: std::chrono::time_point startTime; public: - Timer() - : startTime{std::chrono::steady_clock::now()} - {} + Timer(); - void Start() - { - startTime = std::chrono::steady_clock::now(); - } - - double Elapsed() - { - return std::chrono::duration(std::chrono::high_resolution_clock::now() - startTime).count(); - } + void Start(); + double Elapsed(); }; } diff --git a/Vulkan/src/UniformBuffer.cpp b/Vulkan/src/UniformBuffer.cpp new file mode 100644 index 0000000..08b8917 --- /dev/null +++ b/Vulkan/src/UniformBuffer.cpp @@ -0,0 +1,17 @@ +#include "UniformBuffer.h" + +namespace Copium +{ + UniformBuffer::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()} + {} + + VkDescriptorBufferInfo UniformBuffer::GetDescriptorBufferInfo(int index) const + { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = handle; + bufferInfo.offset = (VkDeviceSize)index * size; + bufferInfo.range = size; + return bufferInfo; + } +} \ No newline at end of file diff --git a/Vulkan/src/UniformBuffer.h b/Vulkan/src/UniformBuffer.h index 0094222..f13828e 100644 --- a/Vulkan/src/UniformBuffer.h +++ b/Vulkan/src/UniformBuffer.h @@ -1,34 +1,29 @@ #pragma once -#include "Common.h" #include "Buffer.h" +#include "Common.h" + #include namespace Copium { - class UniformBuffer : public Buffer + class UniformBuffer final : public Buffer { 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()} - {} + UniformBuffer(Instance& instance, VkDeviceSize size); + + VkDescriptorBufferInfo GetDescriptorBufferInfo(int index) const; template - void Update(const T& t) - { - CP_ASSERT(sizeof(T) == Buffer::GetSize(), "Update : 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; - } + void Update(const T& t); }; + + template + void UniformBuffer::Update(const T& t) + { + CP_ASSERT(sizeof(T) == Buffer::GetSize(), "Update : Template size is not the same as buffer size %u != %u", sizeof(T), Buffer::GetSize()); + Buffer::Update((void*)&t, instance.GetFlightIndex()); + } } diff --git a/Vulkan/src/Vertex.cpp b/Vulkan/src/Vertex.cpp new file mode 100644 index 0000000..216e66c --- /dev/null +++ b/Vulkan/src/Vertex.cpp @@ -0,0 +1,13 @@ +#include "Vertex.h" + +namespace Copium +{ + VertexDescriptor Vertex::GetDescriptor() + { + VertexDescriptor descriptor{}; + descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos), sizeof(Vertex)); + descriptor.AddAttribute(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color), sizeof(Vertex)); + descriptor.AddAttribute(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texCoord), sizeof(Vertex)); + return descriptor; + } +} \ No newline at end of file diff --git a/Vulkan/src/Vertex.h b/Vulkan/src/Vertex.h index 0dc096a..e3d270d 100644 --- a/Vulkan/src/Vertex.h +++ b/Vulkan/src/Vertex.h @@ -1,24 +1,17 @@ #pragma once #include -#include #include "VertexDescriptor.h" namespace Copium { - struct Vertex { + 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(); }; } diff --git a/Vulkan/src/VertexBuffer.cpp b/Vulkan/src/VertexBuffer.cpp new file mode 100644 index 0000000..17dc0dc --- /dev/null +++ b/Vulkan/src/VertexBuffer.cpp @@ -0,0 +1,27 @@ +#include "VertexBuffer.h" + +namespace Copium +{ + VertexBuffer::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} + { + VkDeviceSize offset = 0; + for (auto&& binding : descriptor.GetBindings()) + { + bindingOffsets.emplace_back(offset); + bindingSizes.emplace_back(binding.stride * vertexCount); + offset += binding.stride * vertexCount; + } + } + + void VertexBuffer::Bind(const CommandBuffer& commandBuffer) + { + std::vector buffers{bindingOffsets.size(), handle}; + vkCmdBindVertexBuffers(commandBuffer, 0, bindingOffsets.size(), buffers.data(), bindingOffsets.data()); + } + + void VertexBuffer::Update(uint32_t binding, void* data) + { + UpdateStaging(data, bindingOffsets[binding], bindingSizes[binding]); + } +} \ No newline at end of file diff --git a/Vulkan/src/VertexBuffer.h b/Vulkan/src/VertexBuffer.h index f237d0e..1ee31d6 100644 --- a/Vulkan/src/VertexBuffer.h +++ b/Vulkan/src/VertexBuffer.h @@ -1,38 +1,25 @@ #pragma once #include "Buffer.h" +#include "CommandBuffer.h" +#include "Instance.h" #include "VertexDescriptor.h" +#include +#include + namespace Copium { - class VertexBuffer : public Buffer + class VertexBuffer final : public Buffer { 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} - { - VkDeviceSize offset = 0; - for (auto&& binding : descriptor.GetBindings()) - { - bindingOffsets.emplace_back(offset); - bindingSizes.emplace_back(binding.stride * vertexCount); - offset += binding.stride * vertexCount; - } - } + VertexBuffer(Instance& instance, const VertexDescriptor& descriptor, int vertexCount); - 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 Bind(const CommandBuffer& commandBuffer); + void Update(uint32_t binding, void* data); }; } diff --git a/Vulkan/src/VertexDescriptor.cpp b/Vulkan/src/VertexDescriptor.cpp new file mode 100644 index 0000000..db0216f --- /dev/null +++ b/Vulkan/src/VertexDescriptor.cpp @@ -0,0 +1,51 @@ +#include "VertexDescriptor.h" + +#include "Common.h" + +namespace Copium +{ + void VertexDescriptor::AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset, uint32_t size) + { + CP_ASSERT(binding <= bindings.size(), "AddAttribute : Attribute binding must less than or be equal to the amount of current bindings"); + + if (binding == bindings.size()) + AddLayout(binding, size); + + VkVertexInputAttributeDescription description{}; + description.binding = binding; + description.location = location; + description.format = format; + description.offset = offset; + attributes.emplace_back(description); + } + + VkDeviceSize VertexDescriptor::GetVertexSize() const + { + VkDeviceSize bufferSize = 0; + for (auto&& binding : bindings) + { + bufferSize += binding.stride; + } + return bufferSize; + } + + const std::vector& VertexDescriptor::GetAttributes() const + { + return attributes; + } + + const std::vector& VertexDescriptor::GetBindings() const + { + return bindings; + } + + uint32_t VertexDescriptor::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; + } +} \ No newline at end of file diff --git a/Vulkan/src/VertexDescriptor.h b/Vulkan/src/VertexDescriptor.h index b989df4..e0d7484 100644 --- a/Vulkan/src/VertexDescriptor.h +++ b/Vulkan/src/VertexDescriptor.h @@ -1,7 +1,8 @@ #pragma once -#include +#include #include + namespace Copium { class VertexDescriptor @@ -12,51 +13,12 @@ namespace Copium std::vector attributes; public: - template - void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset) - { - CP_ASSERT(binding <= bindings.size(), "AddAttribute : 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); - } - - VkDeviceSize GetVertexSize() const - { - VkDeviceSize bufferSize = 0; - for (auto&& binding : bindings) - { - bufferSize += binding.stride; - } - return bufferSize; - } - - const std::vector& GetAttributes() const - { - return attributes; - } - - const std::vector& GetBindings() const - { - return bindings; - } + void AddAttribute(uint32_t binding, uint32_t location, VkFormat format, uint32_t offset, uint32_t size); + VkDeviceSize GetVertexSize() const; + const std::vector& GetAttributes() const; + const std::vector& GetBindings() const; 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; - } + uint32_t AddLayout(uint32_t binding, uint32_t size); }; } diff --git a/Vulkan/src/VertexPassthrough.cpp b/Vulkan/src/VertexPassthrough.cpp new file mode 100644 index 0000000..9739250 --- /dev/null +++ b/Vulkan/src/VertexPassthrough.cpp @@ -0,0 +1,11 @@ +#include "VertexPassthrough.h" + +namespace Copium +{ + VertexDescriptor VertexPassthrough::GetDescriptor() + { + VertexDescriptor descriptor{}; + descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(VertexPassthrough, texCoord), sizeof(VertexPassthrough)); + return descriptor; + } +} \ No newline at end of file diff --git a/Vulkan/src/VertexPassthrough.h b/Vulkan/src/VertexPassthrough.h index d9aefad..a68420a 100644 --- a/Vulkan/src/VertexPassthrough.h +++ b/Vulkan/src/VertexPassthrough.h @@ -1,19 +1,14 @@ #pragma once #include -#include #include "VertexDescriptor.h" namespace Copium { - struct VertexPassthrough { + 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(); }; }