diff --git a/CopiumEngine/CopiumEngine.vcxproj b/CopiumEngine/CopiumEngine.vcxproj index aaa0fb3..399412a 100644 --- a/CopiumEngine/CopiumEngine.vcxproj +++ b/CopiumEngine/CopiumEngine.vcxproj @@ -164,13 +164,16 @@ + + + @@ -199,11 +202,14 @@ + + + diff --git a/CopiumEngine/CopiumEngine.vcxproj.filters b/CopiumEngine/CopiumEngine.vcxproj.filters index 31b7952..a2f227f 100644 --- a/CopiumEngine/CopiumEngine.vcxproj.filters +++ b/CopiumEngine/CopiumEngine.vcxproj.filters @@ -114,6 +114,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -218,6 +227,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + diff --git a/CopiumEngine/src/copium/buffer/IndexBuffer.cpp b/CopiumEngine/src/copium/buffer/IndexBuffer.cpp index 13bb7e5..9f1cd96 100644 --- a/CopiumEngine/src/copium/buffer/IndexBuffer.cpp +++ b/CopiumEngine/src/copium/buffer/IndexBuffer.cpp @@ -21,7 +21,7 @@ namespace Copium void IndexBuffer::Draw(const CommandBuffer& commandBuffer, int indices) { - CP_ASSERT(indices >= 0 && indices < indexCount, "Draw : amount of indices is out of range"); + CP_ASSERT(indices > 0 && indices <= indexCount, "Draw : amount of indices is out of range"); vkCmdDrawIndexed(commandBuffer, indices, 1, 0, 0, 0); } } \ No newline at end of file diff --git a/CopiumEngine/src/copium/buffer/RendererVertexBuffer.cpp b/CopiumEngine/src/copium/buffer/RendererVertexBuffer.cpp new file mode 100644 index 0000000..ca7a39b --- /dev/null +++ b/CopiumEngine/src/copium/buffer/RendererVertexBuffer.cpp @@ -0,0 +1,17 @@ +#include "copium/buffer/RendererVertexBuffer.h" + +#include "copium/core/SwapChain.h" + +namespace Copium +{ + + RendererVertexBuffer::RendererVertexBuffer(Vulkan& vulkan, const VertexDescriptor& descriptor, int vertexCount) + : Buffer{vulkan, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, descriptor.GetVertexSize() * vertexCount, SwapChain::MAX_FRAMES_IN_FLIGHT} + {} + + void RendererVertexBuffer::Bind(const CommandBuffer& commandBuffer) + { + VkDeviceSize offset = GetPosition(vulkan.GetSwapChain().GetFlightIndex()); + vkCmdBindVertexBuffers(commandBuffer, 0, 1, &handle, &offset); + } +} diff --git a/CopiumEngine/src/copium/buffer/RendererVertexBuffer.h b/CopiumEngine/src/copium/buffer/RendererVertexBuffer.h new file mode 100644 index 0000000..5781ca7 --- /dev/null +++ b/CopiumEngine/src/copium/buffer/RendererVertexBuffer.h @@ -0,0 +1,18 @@ +#pragma once + +#include "copium/buffer/Buffer.h" +#include "copium/buffer/CommandBuffer.h" +#include "copium/core/Vulkan.h" +#include "copium/pipeline/VertexDescriptor.h" + +namespace Copium +{ + class RendererVertexBuffer : public Buffer + { + CP_DELETE_COPY_AND_MOVE_CTOR(RendererVertexBuffer); + public: + RendererVertexBuffer(Vulkan& vulkan, const VertexDescriptor& descriptor, int vertexCount); + + void Bind(const CommandBuffer& commandBuffer); + }; +} diff --git a/CopiumEngine/src/copium/core/Application.cpp b/CopiumEngine/src/copium/core/Application.cpp index 37b9540..58c4e5f 100644 --- a/CopiumEngine/src/copium/core/Application.cpp +++ b/CopiumEngine/src/copium/core/Application.cpp @@ -172,11 +172,11 @@ namespace Copium { for (int x = 0; x < 10; x++) { - renderer->Quad(glm::vec2(-1 + x * 0.2, -1 + y * 0.2), glm::vec2(-1 + (x + 0.5) * 0.2, -1 + (y + 0.5) * 0.2), glm::vec3{x * 0.1, y * 0.1, 1.0}); + renderer->Quad(glm::vec2{-1 + x * 0.2, -1 + y * 0.2}, glm::vec2{-1 + (x + 0.5) * 0.2, -1 + (y + 0.5) * 0.2}, glm::vec3{x * 0.1, y * 0.1, 1.0}); } } - renderer->Quad(glm::vec2(-0.5, -0.5), glm::vec2{-0.1, 0.5}, *texture2D); - renderer->Quad(glm::vec2(0.1, -0.5), glm::vec2{0.5, 0.5}, *texture2D2); + renderer->Quad(glm::vec2{-0.5, -0.5}, glm::vec2{-0.1, 0.5}, *texture2D); + renderer->Quad(glm::vec2{0.1, -0.5}, glm::vec2{0.5, 0.5}, *texture2D2); renderer->End(); framebuffer->Unbind(*commandBuffer); diff --git a/CopiumEngine/src/copium/renderer/DrawCall.cpp b/CopiumEngine/src/copium/renderer/DrawCall.cpp new file mode 100644 index 0000000..3e6ff9f --- /dev/null +++ b/CopiumEngine/src/copium/renderer/DrawCall.cpp @@ -0,0 +1,25 @@ +#include "copium/renderer/DrawCall.h" + +#include "copium/renderer/RendererVertex.h" + +namespace Copium +{ + DrawCall::DrawCall(Vulkan& vulkan, Pipeline& pipeline, DescriptorPool& descriptorPool, int vertexCount, const std::vector samplers) + : vulkan{vulkan}, + pipeline{pipeline}, + vertexBuffer{vulkan, RendererVertex::GetDescriptor(), vertexCount}, + descriptorSet{vulkan, descriptorPool, pipeline.GetDescriptorSetLayout(0)} + { + descriptorSet.AddSamplers(samplers, 0); + } + + RendererVertexBuffer& DrawCall::GetVertexBuffer() + { + return vertexBuffer; + } + + DescriptorSet& DrawCall::GetDescriptorSet() + { + return descriptorSet; + } +} diff --git a/CopiumEngine/src/copium/renderer/DrawCall.h b/CopiumEngine/src/copium/renderer/DrawCall.h new file mode 100644 index 0000000..937581c --- /dev/null +++ b/CopiumEngine/src/copium/renderer/DrawCall.h @@ -0,0 +1,24 @@ +#pragma once + +#include "copium/buffer/RendererVertexBuffer.h" +#include "copium/pipeline/DescriptorSet.h" +#include "copium/pipeline/Pipeline.h" +#include "copium/sampler/Sampler.h" + +namespace Copium +{ + class DrawCall + { + CP_DELETE_COPY_AND_MOVE_CTOR(DrawCall); + private: + Vulkan& vulkan; + Pipeline& pipeline; + + RendererVertexBuffer vertexBuffer; + DescriptorSet descriptorSet; + public: + DrawCall(Vulkan& vulkan, Pipeline& pipeline, DescriptorPool& descriptorPool, int vertexCount, const std::vector samplers); + RendererVertexBuffer& GetVertexBuffer(); + DescriptorSet& GetDescriptorSet(); + }; +} diff --git a/CopiumEngine/src/copium/renderer/Renderer.cpp b/CopiumEngine/src/copium/renderer/Renderer.cpp index 2fdc7c5..55b8399 100644 --- a/CopiumEngine/src/copium/renderer/Renderer.cpp +++ b/CopiumEngine/src/copium/renderer/Renderer.cpp @@ -1,41 +1,25 @@ #include "copium/renderer/Renderer.h" #include "copium/core/SwapChain.h" +#include "copium/pipeline/PipelineCreator.h" +#include "copium/renderer/RendererVertex.h" namespace Copium { - static constexpr int QUAD_COUNT = 10000; - static constexpr int MAX_NUM_VERTICES = 4 * QUAD_COUNT; - static constexpr int MAX_NUM_INDICES = 6 * QUAD_COUNT; + static constexpr int MAX_NUM_QUADS = 10000; + static constexpr int MAX_NUM_VERTICES = 4 * MAX_NUM_QUADS; + static constexpr int MAX_NUM_INDICES = 6 * MAX_NUM_QUADS; static constexpr int MAX_NUM_TEXTURES = 32; Renderer::Renderer(Vulkan& vulkan, VkRenderPass renderPass, DescriptorPool& descriptorPool) : vulkan{vulkan}, descriptorPool{vulkan}, ibo{vulkan, MAX_NUM_INDICES}, - emptyTexture{vulkan, {0, 0, 0, 0}, 1, 1}, + emptyTexture{vulkan, {1, 0, 0, 0}, 1, 1}, samplers{MAX_NUM_TEXTURES, &emptyTexture} { - CP_ASSERT(MAX_NUM_INDICES < std::numeric_limits::max(), "Renderer : Maximum number of indices too big"); - - - std::vector indices; - indices.resize(MAX_NUM_INDICES); - for (int i = 0; i < QUAD_COUNT; i++) - { - indices[i * 6] = i * 4; - indices[i * 6 + 1] = i * 4 + 1; - indices[i * 6 + 2] = i * 4 + 2; - indices[i * 6 + 3] = i * 4; - indices[i * 6 + 4] = i * 4 + 2; - indices[i * 6 + 5] = i * 4 + 3; - } - ibo.UpdateStaging(indices.data()); - PipelineCreator creator{renderPass, "res/shaders/renderer.vert", "res/shaders/renderer.frag"}; - creator.SetVertexDescriptor(Vertex::GetDescriptor()); - creator.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_NUM_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT); - creator.SetDepthTest(false); - graphicsPipeline = std::make_unique(vulkan, creator); + InitializeIndexBuffer(); + InitializeGraphicsPipeline(renderPass); } void Renderer::Quad(const glm::vec2& from, const glm::vec2& to, const glm::vec3& color) @@ -53,27 +37,27 @@ namespace Copium AllocateQuad(); int texIndex = AllocateSampler(sampler); AddVertex(from, glm::vec3{1,1,1}, texIndex, texCoord1); - AddVertex(glm::vec2{to.x, from.y}, glm::vec3{1,1,1}, texIndex, glm::vec2{texCoord2.x, texCoord1.y}); + AddVertex(glm::vec2{to.x, from.y}, glm::vec3{1, 1, 1}, texIndex, glm::vec2{texCoord2.x, texCoord1.y}); AddVertex(to, glm::vec3{1,1,1}, texIndex, texCoord2); - AddVertex(glm::vec2{from.x, to.y}, glm::vec3{1,1,1}, texIndex, glm::vec2{texCoord1.x, texCoord2.y}); + AddVertex(glm::vec2{from.x, to.y}, glm::vec3{1, 1, 1}, texIndex, glm::vec2{texCoord1.x, texCoord2.y}); } void Renderer::AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord) { - Vertex* vertex = (Vertex*)mappedVertexBuffer; + RendererVertex* vertex = (RendererVertex*)mappedVertexBuffer; vertex->position = position; vertex->color = color; vertex->texCoord = texCoord; vertex->texIndex = texindex; - mappedVertexBuffer = (Vertex*)mappedVertexBuffer + 1; + mappedVertexBuffer = (RendererVertex*)mappedVertexBuffer + 1; } void Renderer::Begin(CommandBuffer& commandBuffer) { graphicsPipeline->Bind(commandBuffer); ibo.Bind(commandBuffer); - vboIndex = -1; - NextVertexBuffer(); + drawCallIndex = -1; + NextDrawCall(); currentCommandBuffer = &commandBuffer; } @@ -82,63 +66,83 @@ namespace Copium Flush(); } + void Renderer::InitializeIndexBuffer() + { + CP_ASSERT(MAX_NUM_INDICES < std::numeric_limits::max(), "Renderer : Maximum number of indices too big"); + + std::vector indices; + indices.resize(MAX_NUM_INDICES); + for (int i = 0; i < MAX_NUM_QUADS; i++) + { + indices[i * 6] = i * 4; + indices[i * 6 + 1] = i * 4 + 1; + indices[i * 6 + 2] = i * 4 + 2; + indices[i * 6 + 3] = i * 4; + indices[i * 6 + 4] = i * 4 + 2; + indices[i * 6 + 5] = i * 4 + 3; + } + ibo.UpdateStaging(indices.data()); + } + + void Renderer::InitializeGraphicsPipeline(VkRenderPass renderPass) + { + PipelineCreator creator{renderPass, "res/shaders/renderer.vert", "res/shaders/renderer.frag"}; + creator.SetVertexDescriptor(RendererVertex::GetDescriptor()); + creator.AddDescriptorSetLayoutBinding(0, 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_NUM_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT); + creator.SetDepthTest(false); + graphicsPipeline = std::make_unique(vulkan, creator); + } + int Renderer::AllocateSampler(const Sampler& sampler) { - for (size_t i = 0; i < texturesUsed; i++) + for (size_t i = 0; i < textureCount; i++) { if (*samplers[i] == sampler) { return i; } } - if (texturesUsed == MAX_NUM_TEXTURES) + if (textureCount == MAX_NUM_TEXTURES) { Flush(); - NextVertexBuffer(); + NextDrawCall(); } - currentDescriptorSet->AddSampler(sampler, 0, vulkan.GetSwapChain().GetFlightIndex(), texturesUsed); - samplers[texturesUsed] = &sampler; - texturesUsed++; - return texturesUsed - 1; + currentDrawCall->GetDescriptorSet().AddSampler(sampler, 0, vulkan.GetSwapChain().GetFlightIndex(), textureCount); + samplers[textureCount] = &sampler; + textureCount++; + return textureCount - 1; } void Renderer::AllocateQuad() { - if (vertexCount + 4 > MAX_NUM_VERTICES) + if (quadCount + 1 > MAX_NUM_QUADS) { + CP_INFO("Flush"); Flush(); - NextVertexBuffer(); + NextDrawCall(); } - vertexCount += 4; - indexCount += 6; + quadCount++; } void Renderer::Flush() { - currentVertexBuffer->Unmap(); - VkBuffer buffer = *currentVertexBuffer; - VkDeviceSize offset = currentVertexBuffer->GetPosition(vulkan.GetSwapChain().GetFlightIndex()); - vkCmdBindVertexBuffers(*currentCommandBuffer, 0, 1, &buffer, &offset); - graphicsPipeline->SetDescriptorSet(0, *currentDescriptorSet); + currentDrawCall->GetVertexBuffer().Unmap(); + currentDrawCall->GetVertexBuffer().Bind(*currentCommandBuffer); + graphicsPipeline->SetDescriptorSet(0, currentDrawCall->GetDescriptorSet()); graphicsPipeline->BindDescriptorSets(*currentCommandBuffer); - ibo.Draw(*currentCommandBuffer, indexCount); + ibo.Draw(*currentCommandBuffer, quadCount * 6); } - void Renderer::NextVertexBuffer() + void Renderer::NextDrawCall() { - vboIndex++; - if (vboIndex >= vbos.size()) + drawCallIndex++; + if (drawCallIndex >= drawCalls.size()) { - // Allocate new buffer since all existing buffers are full - vbos.emplace_back(std::make_unique(vulkan, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeof(Vertex) * MAX_NUM_VERTICES, SwapChain::MAX_FRAMES_IN_FLIGHT)); - descriptorSets.emplace_back(std::make_unique(vulkan, descriptorPool, graphicsPipeline->GetDescriptorSetLayout(0))); - descriptorSets.back()->AddSamplers(samplers, 0); + drawCalls.emplace_back(std::make_unique(vulkan, *graphicsPipeline, descriptorPool, MAX_NUM_VERTICES, samplers)); } - currentVertexBuffer = vbos[vboIndex].get(); - currentDescriptorSet = descriptorSets[vboIndex].get(); - mappedVertexBuffer = (char*)currentVertexBuffer->Map() + currentVertexBuffer->GetPosition(vulkan.GetSwapChain().GetFlightIndex()); - vertexCount = 0; - indexCount = 0; - texturesUsed = 0; + currentDrawCall = drawCalls[drawCallIndex].get(); + mappedVertexBuffer = (char*)currentDrawCall->GetVertexBuffer().Map() + currentDrawCall->GetVertexBuffer().GetPosition(vulkan.GetSwapChain().GetFlightIndex()); + quadCount = 0; + textureCount = 0; } } \ No newline at end of file diff --git a/CopiumEngine/src/copium/renderer/Renderer.h b/CopiumEngine/src/copium/renderer/Renderer.h index 8b6a9c0..360e83a 100644 --- a/CopiumEngine/src/copium/renderer/Renderer.h +++ b/CopiumEngine/src/copium/renderer/Renderer.h @@ -2,10 +2,10 @@ #include "copium/buffer/CommandBuffer.h" #include "copium/buffer/IndexBuffer.h" -#include "copium/buffer/VertexBuffer.h" +#include "copium/buffer/RendererVertexBuffer.h" #include "copium/core/Vulkan.h" #include "copium/pipeline/Pipeline.h" -#include "copium/pipeline/PipelineCreator.h" +#include "copium/renderer/DrawCall.h" #include "copium/sampler/Texture2D.h" #include "copium/util/Common.h" @@ -17,25 +17,6 @@ namespace Copium class Renderer { CP_DELETE_COPY_AND_MOVE_CTOR(Renderer); - - struct Vertex - { - glm::vec2 position; - glm::vec3 color; - glm::vec2 texCoord; - int8_t texIndex; - - static VertexDescriptor GetDescriptor() - { - VertexDescriptor descriptor{}; - descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, position), 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)); - descriptor.AddAttribute(0, 3, VK_FORMAT_R8_SINT, offsetof(Vertex, texIndex), sizeof(Vertex)); - return descriptor; - } - }; - private: Vulkan& vulkan; @@ -43,19 +24,16 @@ namespace Copium IndexBuffer ibo; Texture2D emptyTexture; std::unique_ptr graphicsPipeline; - std::vector> vbos; - std::vector> descriptorSets; + std::vector> drawCalls; // Temporary data during a render CommandBuffer* currentCommandBuffer; - Buffer* currentVertexBuffer; - DescriptorSet* currentDescriptorSet; + DrawCall* currentDrawCall; std::vector samplers; - int vboIndex; - int vertexCount; - int indexCount; + int drawCallIndex; + int quadCount; + int textureCount; void* mappedVertexBuffer; - int texturesUsed; public: Renderer(Vulkan& vulkan, VkRenderPass renderPass, DescriptorPool& descriptorPool); @@ -65,11 +43,13 @@ namespace Copium void Begin(CommandBuffer& commandBuffer); void End(); private: + void InitializeIndexBuffer(); + void InitializeGraphicsPipeline(VkRenderPass renderPass); int AllocateSampler(const Sampler& sampler); void AllocateQuad(); void Flush(); - void NextVertexBuffer(); + void NextDrawCall(); void AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord); }; diff --git a/CopiumEngine/src/copium/renderer/RendererVertex.cpp b/CopiumEngine/src/copium/renderer/RendererVertex.cpp new file mode 100644 index 0000000..39641f7 --- /dev/null +++ b/CopiumEngine/src/copium/renderer/RendererVertex.cpp @@ -0,0 +1,14 @@ +#include "copium/renderer/RendererVertex.h" + +namespace Copium +{ + VertexDescriptor RendererVertex::GetDescriptor() + { + VertexDescriptor descriptor{}; + descriptor.AddAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(RendererVertex, position), sizeof(RendererVertex)); + descriptor.AddAttribute(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(RendererVertex, color), sizeof(RendererVertex)); + descriptor.AddAttribute(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(RendererVertex, texCoord), sizeof(RendererVertex)); + descriptor.AddAttribute(0, 3, VK_FORMAT_R8_SINT, offsetof(RendererVertex, texIndex), sizeof(RendererVertex)); + return descriptor; + } +} \ No newline at end of file diff --git a/CopiumEngine/src/copium/renderer/RendererVertex.h b/CopiumEngine/src/copium/renderer/RendererVertex.h new file mode 100644 index 0000000..235294a --- /dev/null +++ b/CopiumEngine/src/copium/renderer/RendererVertex.h @@ -0,0 +1,18 @@ +#pragma once + +#include "copium/pipeline/VertexDescriptor.h" + +#include + +namespace Copium +{ + struct RendererVertex + { + glm::vec2 position; + glm::vec3 color; + glm::vec2 texCoord; + int8_t texIndex; + + static VertexDescriptor GetDescriptor(); + }; +}