diff --git a/CopiumEngine/CopiumEngine.vcxproj b/CopiumEngine/CopiumEngine.vcxproj index 2fdeb30..aaa0fb3 100644 --- a/CopiumEngine/CopiumEngine.vcxproj +++ b/CopiumEngine/CopiumEngine.vcxproj @@ -170,6 +170,7 @@ + @@ -198,11 +199,11 @@ - + @@ -236,6 +237,8 @@ + + diff --git a/CopiumEngine/CopiumEngine.vcxproj.filters b/CopiumEngine/CopiumEngine.vcxproj.filters index 861af70..31b7952 100644 --- a/CopiumEngine/CopiumEngine.vcxproj.filters +++ b/CopiumEngine/CopiumEngine.vcxproj.filters @@ -111,6 +111,9 @@ Source Files + + Source Files + @@ -212,7 +215,7 @@ Header Files - + Header Files @@ -221,5 +224,7 @@ + + \ No newline at end of file diff --git a/CopiumEngine/res/shaders/renderer.frag b/CopiumEngine/res/shaders/renderer.frag new file mode 100644 index 0000000..841cf80 --- /dev/null +++ b/CopiumEngine/res/shaders/renderer.frag @@ -0,0 +1,52 @@ +#version 450 + +layout(set = 0, binding = 0) uniform sampler2D texSamplers[32]; + +layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec2 fragTexCoord; +layout(location = 2) in flat int fragTexIndex; + +layout(location = 0) out vec4 outColor; + +vec4 TextureColor() +{ + if(fragTexIndex == 0) return texture(texSamplers[0], fragTexCoord); + if(fragTexIndex == 1) return texture(texSamplers[1], fragTexCoord); + if(fragTexIndex == 2) return texture(texSamplers[2], fragTexCoord); + if(fragTexIndex == 3) return texture(texSamplers[3], fragTexCoord); + if(fragTexIndex == 4) return texture(texSamplers[4], fragTexCoord); + if(fragTexIndex == 5) return texture(texSamplers[5], fragTexCoord); + if(fragTexIndex == 6) return texture(texSamplers[6], fragTexCoord); + if(fragTexIndex == 7) return texture(texSamplers[7], fragTexCoord); + if(fragTexIndex == 8) return texture(texSamplers[8], fragTexCoord); + if(fragTexIndex == 9) return texture(texSamplers[9], fragTexCoord); + if(fragTexIndex == 10) return texture(texSamplers[10], fragTexCoord); + if(fragTexIndex == 11) return texture(texSamplers[11], fragTexCoord); + if(fragTexIndex == 12) return texture(texSamplers[12], fragTexCoord); + if(fragTexIndex == 13) return texture(texSamplers[13], fragTexCoord); + if(fragTexIndex == 14) return texture(texSamplers[14], fragTexCoord); + if(fragTexIndex == 15) return texture(texSamplers[15], fragTexCoord); + if(fragTexIndex == 16) return texture(texSamplers[16], fragTexCoord); + if(fragTexIndex == 17) return texture(texSamplers[17], fragTexCoord); + if(fragTexIndex == 18) return texture(texSamplers[18], fragTexCoord); + if(fragTexIndex == 19) return texture(texSamplers[19], fragTexCoord); + if(fragTexIndex == 20) return texture(texSamplers[20], fragTexCoord); + if(fragTexIndex == 21) return texture(texSamplers[21], fragTexCoord); + if(fragTexIndex == 22) return texture(texSamplers[22], fragTexCoord); + if(fragTexIndex == 23) return texture(texSamplers[23], fragTexCoord); + if(fragTexIndex == 24) return texture(texSamplers[24], fragTexCoord); + if(fragTexIndex == 25) return texture(texSamplers[25], fragTexCoord); + if(fragTexIndex == 26) return texture(texSamplers[26], fragTexCoord); + if(fragTexIndex == 27) return texture(texSamplers[27], fragTexCoord); + if(fragTexIndex == 28) return texture(texSamplers[28], fragTexCoord); + if(fragTexIndex == 29) return texture(texSamplers[29], fragTexCoord); + if(fragTexIndex == 30) return texture(texSamplers[30], fragTexCoord); + if(fragTexIndex == 31) return texture(texSamplers[31], fragTexCoord); + return vec4(1, 1, 1, 1); +} + + +void main() { + outColor = vec4(fragColor, 1.0) * TextureColor(); + // outColor = vec4(fragTexCoord, 0.0, 1.0); +} diff --git a/CopiumEngine/res/shaders/renderer.vert b/CopiumEngine/res/shaders/renderer.vert new file mode 100644 index 0000000..bd7ec17 --- /dev/null +++ b/CopiumEngine/res/shaders/renderer.vert @@ -0,0 +1,17 @@ +#version 450 + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inColor; +layout(location = 2) in vec2 inTexCoord; +layout(location = 3) in int inTexIndex; + +layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec2 fragTexCoord; +layout(location = 2) out int fragTexIndex; + +void main() { + gl_Position = vec4(inPosition, 1.0); + fragColor = inColor; + fragTexCoord = inTexCoord; + fragTexIndex = inTexIndex; +} diff --git a/CopiumEngine/res/textures/texture2.png b/CopiumEngine/res/textures/texture2.png new file mode 100644 index 0000000..c2f4aa3 Binary files /dev/null and b/CopiumEngine/res/textures/texture2.png differ diff --git a/CopiumEngine/src/copium/buffer/IndexBuffer.cpp b/CopiumEngine/src/copium/buffer/IndexBuffer.cpp index 4cf94b1..13bb7e5 100644 --- a/CopiumEngine/src/copium/buffer/IndexBuffer.cpp +++ b/CopiumEngine/src/copium/buffer/IndexBuffer.cpp @@ -18,4 +18,10 @@ namespace Copium { vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); } + + void IndexBuffer::Draw(const CommandBuffer& commandBuffer, int indices) + { + 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/IndexBuffer.h b/CopiumEngine/src/copium/buffer/IndexBuffer.h index e157d05..ef6454b 100644 --- a/CopiumEngine/src/copium/buffer/IndexBuffer.h +++ b/CopiumEngine/src/copium/buffer/IndexBuffer.h @@ -17,5 +17,6 @@ namespace Copium void Bind(const CommandBuffer& commandBuffer); void Draw(const CommandBuffer& commandBuffer); + void Draw(const CommandBuffer& commandBuffer, int indices); }; } \ No newline at end of file diff --git a/CopiumEngine/src/copium/core/Application.cpp b/CopiumEngine/src/copium/core/Application.cpp index fa04805..37b9540 100644 --- a/CopiumEngine/src/copium/core/Application.cpp +++ b/CopiumEngine/src/copium/core/Application.cpp @@ -56,6 +56,7 @@ namespace Copium InitializeDescriptorSets(); InitializeMesh(); InitializeCommandBuffer(); + InitializeRenderer(); } Application::~Application() @@ -99,6 +100,7 @@ namespace Copium void Application::InitializeTextureSampler() { texture2D = std::make_unique(*vulkan, "res/textures/texture.png"); + texture2D2 = std::make_unique(*vulkan, "res/textures/texture2.png"); } void Application::InitializeUniformBuffer() @@ -145,6 +147,11 @@ namespace Copium commandBuffer = std::make_unique(*vulkan, CommandBuffer::Type::Dynamic); } + void Application::InitializeRenderer() + { + renderer = std::make_unique(*vulkan, framebuffer->GetRenderPass(), *descriptorPool); + } + void Application::RecordCommandBuffer() { commandBuffer->Begin(); @@ -160,6 +167,18 @@ namespace Copium mesh->Bind(*commandBuffer); mesh->Render(*commandBuffer); + renderer->Begin(*commandBuffer); + for (int y = 0; y < 10; y++) + { + 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(-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); vulkan->GetSwapChain().BeginFrameBuffer(*commandBuffer); diff --git a/CopiumEngine/src/copium/core/Application.h b/CopiumEngine/src/copium/core/Application.h index 0a18aa1..00deeea 100644 --- a/CopiumEngine/src/copium/core/Application.h +++ b/CopiumEngine/src/copium/core/Application.h @@ -12,6 +12,7 @@ #include "copium/pipeline/DescriptorSet.h" #include "copium/pipeline/Pipeline.h" #include "copium/sampler/Texture2D.h" +#include "copium/renderer/Renderer.h" namespace Copium { @@ -23,6 +24,7 @@ namespace Copium std::unique_ptr instance; std::unique_ptr framebuffer; std::unique_ptr texture2D; + std::unique_ptr texture2D2; std::unique_ptr shaderUniformBuffer; std::unique_ptr descriptorPool; std::unique_ptr descriptorSet; @@ -32,6 +34,7 @@ namespace Copium std::unique_ptr mesh; std::unique_ptr meshPassthrough; std::unique_ptr commandBuffer; + std::unique_ptr renderer; public: Application(); @@ -47,6 +50,7 @@ namespace Copium void InitializeGraphicsPipeline(); void InitializeMesh(); void InitializeCommandBuffer(); + void InitializeRenderer(); void RecordCommandBuffer(); void UpdateUniformBuffer(); diff --git a/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp b/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp index 23baa99..bb5178d 100644 --- a/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp +++ b/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp @@ -35,21 +35,49 @@ namespace Copium } } - void DescriptorSet::AddSampler(const Sampler& sampler, uint32_t binding) + void DescriptorSet::AddSampler(const Sampler& sampler, uint32_t binding, int arrayIndex) + { + for (size_t i = 0; i < descriptorSets.size(); ++i) + { + AddSampler(sampler, binding, i, arrayIndex); + } + } + + void DescriptorSet::AddSampler(const Sampler& sampler, uint32_t binding, int index, int arrayIndex) + { + CP_ASSERT(index >= 0 && index < descriptorSets.size(), "AddSampler : index is out of range"); + VkDescriptorImageInfo imageInfo = sampler.GetDescriptorImageInfo(index); + VkWriteDescriptorSet descriptorWrite{}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSets[index]; + descriptorWrite.dstBinding = binding; + descriptorWrite.dstArrayElement = arrayIndex; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = nullptr; + descriptorWrite.pImageInfo = &imageInfo; + descriptorWrite.pTexelBufferView = nullptr; + vkUpdateDescriptorSets(vulkan.GetDevice(), 1, &descriptorWrite, 0, nullptr); + } + + void DescriptorSet::AddSamplers(const std::vector& samplers, uint32_t binding) { for (size_t i = 0; i < descriptorSets.size(); ++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(vulkan.GetDevice(), 1, &descriptorWrite, 0, nullptr); + std::vector descriptorWrites{samplers.size()}; + for (size_t j = 0; j < samplers.size(); j++) + { + VkDescriptorImageInfo imageInfo = samplers[j]->GetDescriptorImageInfo(i); + descriptorWrites[j].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[j].dstSet = descriptorSets[i]; + descriptorWrites[j].dstBinding = binding; + descriptorWrites[j].dstArrayElement = j; + descriptorWrites[j].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrites[j].descriptorCount = 1; + descriptorWrites[j].pBufferInfo = nullptr; + descriptorWrites[j].pImageInfo = &imageInfo; + descriptorWrites[j].pTexelBufferView = nullptr; + } + vkUpdateDescriptorSets(vulkan.GetDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr); } } diff --git a/CopiumEngine/src/copium/pipeline/DescriptorSet.h b/CopiumEngine/src/copium/pipeline/DescriptorSet.h index 70a7b53..3901315 100644 --- a/CopiumEngine/src/copium/pipeline/DescriptorSet.h +++ b/CopiumEngine/src/copium/pipeline/DescriptorSet.h @@ -24,7 +24,9 @@ namespace Copium ~DescriptorSet(); void AddUniform(const UniformBuffer& uniformBuffer, uint32_t binding); - void AddSampler(const Sampler& sampler, uint32_t binding); + void AddSampler(const Sampler& sampler, uint32_t binding, int arrayIndex = 0); + void AddSampler(const Sampler& sampler, uint32_t binding, int index, int arrayIndex = 0); + void AddSamplers(const std::vector& sampler, uint32_t binding); operator VkDescriptorSet() const; }; } \ No newline at end of file diff --git a/CopiumEngine/src/copium/pipeline/Pipeline.cpp b/CopiumEngine/src/copium/pipeline/Pipeline.cpp index 4d67cc4..bfc0973 100644 --- a/CopiumEngine/src/copium/pipeline/Pipeline.cpp +++ b/CopiumEngine/src/copium/pipeline/Pipeline.cpp @@ -142,8 +142,8 @@ namespace Copium VkPipelineDepthStencilStateCreateInfo depthStencilCreateInfo{}; depthStencilCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - depthStencilCreateInfo.depthTestEnable = VK_TRUE; - depthStencilCreateInfo.depthWriteEnable = VK_TRUE; + depthStencilCreateInfo.depthTestEnable = creator.depthTest ? VK_TRUE : VK_FALSE; + depthStencilCreateInfo.depthWriteEnable = creator.depthTest ? VK_TRUE : VK_FALSE; depthStencilCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS; depthStencilCreateInfo.depthBoundsTestEnable = VK_FALSE; depthStencilCreateInfo.minDepthBounds = 0.0f; @@ -155,9 +155,9 @@ namespace Copium 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; + 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; diff --git a/CopiumEngine/src/copium/pipeline/PipelineCreator.cpp b/CopiumEngine/src/copium/pipeline/PipelineCreator.cpp index 86e9710..5daeb2f 100644 --- a/CopiumEngine/src/copium/pipeline/PipelineCreator.cpp +++ b/CopiumEngine/src/copium/pipeline/PipelineCreator.cpp @@ -35,4 +35,9 @@ namespace Copium { frontFace = cullFrontFace; } + + void PipelineCreator::SetDepthTest(bool depthTest) + { + this->depthTest = depthTest; + } } \ No newline at end of file diff --git a/CopiumEngine/src/copium/pipeline/PipelineCreator.h b/CopiumEngine/src/copium/pipeline/PipelineCreator.h index 54a0e96..4e29e1c 100644 --- a/CopiumEngine/src/copium/pipeline/PipelineCreator.h +++ b/CopiumEngine/src/copium/pipeline/PipelineCreator.h @@ -28,6 +28,7 @@ namespace Copium VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE; VkRenderPass renderPass = VK_NULL_HANDLE; + bool depthTest = true; public: PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader); @@ -37,5 +38,6 @@ namespace Copium void SetPrimitiveTopology(VkPrimitiveTopology primitiveTopology); void SetCullMode(VkCullModeFlags flags); void SetCullFrontFace(VkFrontFace cullFrontFace); + void SetDepthTest(bool depthTest); }; } diff --git a/CopiumEngine/src/copium/renderer/Renderer.cpp b/CopiumEngine/src/copium/renderer/Renderer.cpp new file mode 100644 index 0000000..2fdc7c5 --- /dev/null +++ b/CopiumEngine/src/copium/renderer/Renderer.cpp @@ -0,0 +1,144 @@ +#include "copium/renderer/Renderer.h" + +#include "copium/core/SwapChain.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_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}, + 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); + } + + void Renderer::Quad(const glm::vec2& from, const glm::vec2& to, const glm::vec3& color) + { + AllocateQuad(); + AddVertex(from, color, -1, glm::vec2{0, 0}); + AddVertex(glm::vec2{to.x, from.y}, color, -1, glm::vec2{0, 0}); + AddVertex(to, color, -1, glm::vec2{0, 0}); + AddVertex(glm::vec2{from.x, to.y}, color, -1, glm::vec2{0, 0}); + } + + + void Renderer::Quad(const glm::vec2& from, const glm::vec2& to, const Sampler& sampler, const glm::vec2& texCoord1, const glm::vec2& texCoord2) + { + 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(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}); + } + + void Renderer::AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord) + { + Vertex* vertex = (Vertex*)mappedVertexBuffer; + vertex->position = position; + vertex->color = color; + vertex->texCoord = texCoord; + vertex->texIndex = texindex; + mappedVertexBuffer = (Vertex*)mappedVertexBuffer + 1; + } + + void Renderer::Begin(CommandBuffer& commandBuffer) + { + graphicsPipeline->Bind(commandBuffer); + ibo.Bind(commandBuffer); + vboIndex = -1; + NextVertexBuffer(); + currentCommandBuffer = &commandBuffer; + } + + void Renderer::End() + { + Flush(); + } + + int Renderer::AllocateSampler(const Sampler& sampler) + { + for (size_t i = 0; i < texturesUsed; i++) + { + if (*samplers[i] == sampler) + { + return i; + } + } + if (texturesUsed == MAX_NUM_TEXTURES) + { + Flush(); + NextVertexBuffer(); + } + currentDescriptorSet->AddSampler(sampler, 0, vulkan.GetSwapChain().GetFlightIndex(), texturesUsed); + samplers[texturesUsed] = &sampler; + texturesUsed++; + return texturesUsed - 1; + } + + void Renderer::AllocateQuad() + { + if (vertexCount + 4 > MAX_NUM_VERTICES) + { + Flush(); + NextVertexBuffer(); + } + vertexCount += 4; + indexCount += 6; + } + + 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); + graphicsPipeline->BindDescriptorSets(*currentCommandBuffer); + ibo.Draw(*currentCommandBuffer, indexCount); + } + + void Renderer::NextVertexBuffer() + { + vboIndex++; + if (vboIndex >= vbos.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); + } + currentVertexBuffer = vbos[vboIndex].get(); + currentDescriptorSet = descriptorSets[vboIndex].get(); + mappedVertexBuffer = (char*)currentVertexBuffer->Map() + currentVertexBuffer->GetPosition(vulkan.GetSwapChain().GetFlightIndex()); + vertexCount = 0; + indexCount = 0; + texturesUsed = 0; + } +} \ No newline at end of file diff --git a/CopiumEngine/src/copium/renderer/Renderer.h b/CopiumEngine/src/copium/renderer/Renderer.h new file mode 100644 index 0000000..8b6a9c0 --- /dev/null +++ b/CopiumEngine/src/copium/renderer/Renderer.h @@ -0,0 +1,76 @@ +#pragma once + +#include "copium/buffer/CommandBuffer.h" +#include "copium/buffer/IndexBuffer.h" +#include "copium/buffer/VertexBuffer.h" +#include "copium/core/Vulkan.h" +#include "copium/pipeline/Pipeline.h" +#include "copium/pipeline/PipelineCreator.h" +#include "copium/sampler/Texture2D.h" +#include "copium/util/Common.h" + +#include +#include + +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; + + DescriptorPool descriptorPool; + IndexBuffer ibo; + Texture2D emptyTexture; + std::unique_ptr graphicsPipeline; + std::vector> vbos; + std::vector> descriptorSets; + + // Temporary data during a render + CommandBuffer* currentCommandBuffer; + Buffer* currentVertexBuffer; + DescriptorSet* currentDescriptorSet; + std::vector samplers; + int vboIndex; + int vertexCount; + int indexCount; + void* mappedVertexBuffer; + int texturesUsed; + public: + Renderer(Vulkan& vulkan, VkRenderPass renderPass, DescriptorPool& descriptorPool); + + void Quad(const glm::vec2& from, const glm::vec2& to, const glm::vec3& color = glm::vec3{1, 1, 1}); + void Quad(const glm::vec2& from, const glm::vec2& to, const Sampler& sampler, const glm::vec2& texCoord1 = glm::vec2{0, 0}, const glm::vec2& texCoord2 = glm::vec2{1, 1}); + + void Begin(CommandBuffer& commandBuffer); + void End(); + private: + + int AllocateSampler(const Sampler& sampler); + void AllocateQuad(); + void Flush(); + void NextVertexBuffer(); + + void AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord); + }; +} diff --git a/CopiumEngine/src/copium/sampler/Sampler.cpp b/CopiumEngine/src/copium/sampler/Sampler.cpp index 976ad0e..a9b7390 100644 --- a/CopiumEngine/src/copium/sampler/Sampler.cpp +++ b/CopiumEngine/src/copium/sampler/Sampler.cpp @@ -39,4 +39,9 @@ namespace Copium CP_VK_ASSERT(vkCreateSampler(vulkan.GetDevice(), &createInfo, nullptr, &sampler), "InitializeSampler : Failed to initialize texture sampler"); } + + Sampler::operator VkSampler() const + { + return sampler; + } } \ No newline at end of file diff --git a/CopiumEngine/src/copium/sampler/Sampler.h b/CopiumEngine/src/copium/sampler/Sampler.h index 19a1470..34b08f8 100644 --- a/CopiumEngine/src/copium/sampler/Sampler.h +++ b/CopiumEngine/src/copium/sampler/Sampler.h @@ -18,6 +18,7 @@ namespace Copium virtual ~Sampler(); virtual VkDescriptorImageInfo GetDescriptorImageInfo(int index) const = 0; + operator VkSampler() const; private: void InitializeSampler(); }; diff --git a/CopiumEngine/src/copium/sampler/Texture2D.cpp b/CopiumEngine/src/copium/sampler/Texture2D.cpp index c93b04f..a19f1e2 100644 --- a/CopiumEngine/src/copium/sampler/Texture2D.cpp +++ b/CopiumEngine/src/copium/sampler/Texture2D.cpp @@ -10,7 +10,15 @@ namespace Copium Texture2D::Texture2D(Vulkan& vulkan, const std::string& filename) : Sampler{vulkan} { - InitializeTextureImage(filename); + CP_DEBUG("Texture2D : Loading texture file: %s", filename.c_str()); + InitializeTextureImageFromFile(filename); + } + + Texture2D::Texture2D(Vulkan& vulkan, const std::vector& rgbaData, int width, int height) + : Sampler{vulkan} + { + CP_ASSERT(rgbaData.size() == width * height * 4, "rgbaData has invalid size, should be equal to width * height * 4 (%d) actually is %d", width * height * 4, rgbaData.size()); + InitializeTextureImageFromData((void*)rgbaData.data(), width, height); } Texture2D::~Texture2D() @@ -30,7 +38,7 @@ namespace Copium return imageInfo; } - void Texture2D::InitializeTextureImage(const std::string& filename) + void Texture2D::InitializeTextureImageFromFile(const std::string& filename) { int texWidth; int texHeight; @@ -39,16 +47,22 @@ namespace Copium CP_ASSERT(pixels, "InitializeTextureImage : Failed to load texture image"); - VkDeviceSize bufferSize = texWidth * texHeight * 4; + InitializeTextureImageFromData((void*)pixels, texWidth, texHeight); + + stbi_image_free(pixels); + } + + void Texture2D::InitializeTextureImageFromData(void* rgbaData, int width, int height) + { + VkDeviceSize bufferSize = width * height * 4; Buffer stagingBuffer{vulkan, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1}; void* data = stagingBuffer.Map(); - memcpy(data, pixels, bufferSize); + memcpy(data, rgbaData, bufferSize); stagingBuffer.Unmap(); - stbi_image_free(pixels); - Image::InitializeImage(vulkan, texWidth, texHeight, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory); + Image::InitializeImage(vulkan, width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory); Image::TransitionImageLayout(vulkan, image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - Image::CopyBufferToImage(vulkan, stagingBuffer, image, texWidth, texHeight); + Image::CopyBufferToImage(vulkan, stagingBuffer, image, width, height); Image::TransitionImageLayout(vulkan, image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); imageView = Image::InitializeImageView(vulkan, image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); } diff --git a/CopiumEngine/src/copium/sampler/Texture2D.h b/CopiumEngine/src/copium/sampler/Texture2D.h index 6fec95e..11775ea 100644 --- a/CopiumEngine/src/copium/sampler/Texture2D.h +++ b/CopiumEngine/src/copium/sampler/Texture2D.h @@ -19,10 +19,12 @@ namespace Copium VkImageView imageView; public: Texture2D(Vulkan& vulkan, const std::string& filename); + Texture2D(Vulkan& vulkan, const std::vector& rgbaData, int width, int height); ~Texture2D() override; VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override; private: - void InitializeTextureImage(const std::string& filename); + void InitializeTextureImageFromFile(const std::string& filename); + void InitializeTextureImageFromData(void* rgbaData, int width, int height); }; } diff --git a/CopiumEngine/src/copium/util/Common.h b/CopiumEngine/src/copium/util/Common.h index 701f32b..0769fd8 100644 --- a/CopiumEngine/src/copium/util/Common.h +++ b/CopiumEngine/src/copium/util/Common.h @@ -10,23 +10,23 @@ #define CP_TERM_GRAY "\x1B[90m" #define CP_TERM_CLEAR "\033[0m" -#define CP_DEBUG(format, ...) std::cout << CP_TERM_GRAY << "[DBG] " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl -#define CP_INFO(format, ...) std::cout << "[INF] " << Copium::StringFormat(format, __VA_ARGS__) << std::endl -#define CP_WARN(format, ...) std::cout << CP_TERM_YELLOW << "[WRN] " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl -#define CP_ERR(format, ...) std::cout << CP_TERM_RED << "[ERR] " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl +#define CP_DEBUG(format, ...) std::cout << CP_TERM_GRAY << "[DBG] " << Copium::String::Format(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl +#define CP_INFO(format, ...) std::cout << "[INF] " << Copium::String::Format(format, __VA_ARGS__) << std::endl +#define CP_WARN(format, ...) std::cout << CP_TERM_YELLOW << "[WRN] " << Copium::String::Format(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl +#define CP_ERR(format, ...) std::cout << CP_TERM_RED << "[ERR] " << Copium::String::Format(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl // Continue traces, will not print the [XXX] tag before the log -#define CP_DEBUG_CONT(format, ...) std::cout << CP_TERM_GRAY << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl -#define CP_INFO_CONT(format, ...) std::cout << " " << Copium::StringFormat(format, __VA_ARGS__) << std::endl -#define CP_WARN_CONT(format, ...) std::cout << CP_TERM_YELLOW << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl -#define CP_ERR_CONT(format, ...) std::cout << CP_TERM_RED << " " << Copium::StringFormat(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl +#define CP_DEBUG_CONT(format, ...) std::cout << CP_TERM_GRAY << " " << Copium::String::Format(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl +#define CP_INFO_CONT(format, ...) std::cout << " " << Copium::String::Format(format, __VA_ARGS__) << std::endl +#define CP_WARN_CONT(format, ...) std::cout << CP_TERM_YELLOW << " " << Copium::String::Format(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl +#define CP_ERR_CONT(format, ...) std::cout << CP_TERM_RED << " " << Copium::String::Format(format, __VA_ARGS__) << CP_TERM_CLEAR << std::endl #define CP_UNIMPLEMENTED() CP_WARN("%s is unimplemented", __FUNCTION__) #define CP_ABORT(format, ...) \ do \ { \ CP_ERR(format, __VA_ARGS__); \ - throw std::runtime_error(Copium::StringFormat(format, __VA_ARGS__)); \ + throw std::runtime_error(Copium::String::Format(format, __VA_ARGS__)); \ } while(false) #define CP_ASSERT(Function, format, ...) \ do \ @@ -34,7 +34,7 @@ if(!(Function)) \ { \ CP_ERR(format, __VA_ARGS__); \ - throw std::runtime_error(Copium::StringFormat(format, __VA_ARGS__)); \ + throw std::runtime_error(Copium::String::Format(format, __VA_ARGS__)); \ } \ } while(false) #define CP_VK_ASSERT(Function, format, ...) \ @@ -43,7 +43,7 @@ if(Function != VK_SUCCESS) \ { \ CP_ERR(format, __VA_ARGS__); \ - throw VulkanException(Copium::StringFormat(format, __VA_ARGS__)); \ + throw VulkanException(Copium::String::Format(format, __VA_ARGS__)); \ } \ } while(false) @@ -57,13 +57,18 @@ namespace Copium { - template - std::string StringFormat(const std::string& format, Args... args) + class String { - int size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; - CP_ASSERT(size > 0, "StringFormat : Error during formatting"); - std::unique_ptr buf(new char[size]); - std::snprintf(buf.get(), size, format.c_str(), args...); - return std::string(buf.get(), buf.get() + size - 1); - } + CP_STATIC_CLASS(String); + public: + template + static std::string Format(const std::string& format, Args... args) + { + int size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; + CP_ASSERT(size > 0, "Format : Error during formatting"); + std::unique_ptr buf(new char[size]); + std::snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); + } + }; }