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);
+ }
+ };
}