diff --git a/include/gfx_device.hpp b/include/gfx_device.hpp index c184583..cdb4bd6 100644 --- a/include/gfx_device.hpp +++ b/include/gfx_device.hpp @@ -19,10 +19,9 @@ namespace engine { GFXDevice& operator=(const GFXDevice&) = delete; ~GFXDevice(); - // adds a vertex buffer draw call to the queue - void drawBuffer(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, uint32_t count); - - void drawIndexed(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t indexCount); + // adds a draw call to the queue + // vertexBuffer is required. indexBuffer and uniformData can be NULL + void draw(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count, const void* uniformData); // Call once per frame. Executes all queued draw calls and renders to the screen. void renderFrame(); diff --git a/src/engine.cpp b/src/engine.cpp index cf6c14d..ce9763b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -6,6 +6,13 @@ #include "log.hpp" #include +#include + +struct UBO { + glm::mat4 model{}; + glm::mat4 view{}; + glm::mat4 proj{}; +}; static engine::gfx::Pipeline* pipeline; static engine::gfx::Buffer* vb; @@ -29,11 +36,7 @@ namespace engine { }; vertFormat.attributeDescriptions.push_back({0, gfx::VertexAttribFormat::VEC2, 0}); vertFormat.attributeDescriptions.push_back({1, gfx::VertexAttribFormat::VEC3, offsetof(Vertex, col)}); - struct UBO { - glm::mat4 model{}; - glm::mat4 view{}; - glm::mat4 proj{}; - }; + pipeline = m_gfx->createPipeline(resMan.getFilePath("shader.vert.spv").string().c_str(), resMan.getFilePath("shader.frag.spv").string().c_str(), vertFormat, sizeof(UBO)); const std::vector vertices = { @@ -48,9 +51,6 @@ namespace engine { }; ib = m_gfx->createBuffer(gfx::BufferType::INDEX, sizeof(uint32_t) * indices.size(), indices.data()); - UBO initialUbo{}; -// ub = m_gfx->createBuffer(gfx::BufferType::UNIFORM, sizeof(UBO), &initialUbo); - } Application::~Application() @@ -89,8 +89,13 @@ namespace engine { } /* draw */ - - m_gfx->drawIndexed(pipeline, vb, ib, 6); + UBO initialUbo{ + .model = glm::mat4{1.0f}, + .view = glm::mat4{1.0f}, + .proj = glm::mat4{1.0f} + }; + initialUbo.model = glm::scale(glm::mat4{ 1.0f }, glm::vec3{ 0.5f, 0.5f, 1.0f }); + m_gfx->draw(pipeline, vb, ib, 6, &initialUbo); m_gfx->renderFrame(); diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index 2b9f138..bdfd434 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -94,6 +94,8 @@ namespace engine { VkPipelineLayout layout = VK_NULL_HANDLE; VkPipeline handle = VK_NULL_HANDLE; std::vector uniformBuffers{}; + VkDescriptorPool descriptorPool = VK_NULL_HANDLE; + std::array descriptorSets{}; }; @@ -1070,29 +1072,32 @@ namespace engine { vkDestroyInstance(pimpl->instance, nullptr); } - void GFXDevice::drawBuffer(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, uint32_t count) + void GFXDevice::draw(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count, const void* uniformData) { assert(vertexBuffer->type == gfx::BufferType::VERTEX); + assert(vertexBuffer != nullptr); + assert(indexBuffer == nullptr || indexBuffer->type == gfx::BufferType::INDEX); + + VkResult res; DrawCall call{ .vertexBuffer = vertexBuffer, - .indexBuffer = nullptr, // don't use indexed drawing + .indexBuffer = indexBuffer, // will be ignored if nullptr .count = count, }; - pimpl->drawQueues[pipeline].push(call); - } + if (uniformData != nullptr) { + uint32_t frameIndex = pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT; - void GFXDevice::drawIndexed(const gfx::Pipeline* pipeline, const gfx::Buffer* vertexBuffer, const gfx::Buffer* indexBuffer, uint32_t count) - { - assert(vertexBuffer->type == gfx::BufferType::VERTEX); - assert(indexBuffer->type == gfx::BufferType::INDEX); + void* dest; + res = vmaMapMemory(pimpl->allocator, pipeline->uniformBuffers[frameIndex]->allocation, &dest); + assert(res == VK_SUCCESS); - DrawCall call{ - .vertexBuffer = vertexBuffer, - .indexBuffer = indexBuffer, // don't use indexed drawing - .count = count, - }; + memcpy(dest, uniformData, pipeline->uniformBuffers[frameIndex]->size); + + vmaUnmapMemory(pimpl->allocator, pipeline->uniformBuffers[frameIndex]->allocation); + + } pimpl->drawQueues[pipeline].push(call); } @@ -1163,9 +1168,11 @@ namespace engine { for (auto& [pipeline, queue] : pimpl->drawQueues) { vkCmdBindPipeline(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); + vkCmdBindDescriptorSets(pimpl->commandBuffers[frameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, 0, 1, &pipeline->descriptorSets[frameIndex], 0, nullptr); while (queue.empty() == false) { DrawCall call = queue.front(); vkCmdBindVertexBuffers(pimpl->commandBuffers[frameIndex], 0, 1, &call.vertexBuffer->buffer, offsets); + if (call.indexBuffer == nullptr) { // do a simple draw call vkCmdDraw(pimpl->commandBuffers[frameIndex], call.count, 1, 0, 0); @@ -1252,6 +1259,46 @@ namespace engine { pipeline->uniformBuffers[i] = buf; } + // create descriptor pool for uniform buffers + VkDescriptorPoolSize poolSize{}; + poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + poolSize.descriptorCount = FRAMES_IN_FLIGHT; + VkDescriptorPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.poolSizeCount = 1; + poolInfo.pPoolSizes = &poolSize; + poolInfo.maxSets = FRAMES_IN_FLIGHT; + res = vkCreateDescriptorPool(pimpl->device, &poolInfo, nullptr, &pipeline->descriptorPool); + assert(res == VK_SUCCESS); + + std::array layouts; + layouts.fill(pimpl->uboLayout); + VkDescriptorSetAllocateInfo dSetAllocInfo{}; + dSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + dSetAllocInfo.descriptorPool = pipeline->descriptorPool; + dSetAllocInfo.descriptorSetCount = FRAMES_IN_FLIGHT; + dSetAllocInfo.pSetLayouts = layouts.data(); + res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, pipeline->descriptorSets.data()); + + for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = pipeline->uniformBuffers[i]->buffer; + bufferInfo.offset = 0; + bufferInfo.range = uniformBufferSize; + VkWriteDescriptorSet descriptorWrite{}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = pipeline->descriptorSets[i]; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = &bufferInfo; + descriptorWrite.pImageInfo = nullptr; + descriptorWrite.pTexelBufferView = nullptr; + + vkUpdateDescriptorSets(pimpl->device, 1, &descriptorWrite, 0, nullptr); + } + // get vertex attrib layout: VkVertexInputBindingDescription bindingDescription{ }; bindingDescription.binding = 0; @@ -1423,6 +1470,8 @@ namespace engine { vkDestroyPipeline(pimpl->device, pipeline->handle, nullptr); vkDestroyPipelineLayout(pimpl->device, pipeline->layout, nullptr); + vkDestroyDescriptorPool(pimpl->device, pipeline->descriptorPool, nullptr); + for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { destroyBuffer(pipeline->uniformBuffers[i]); } diff --git a/src/resources/mesh.cpp b/src/resources/mesh.cpp index 9633493..81e96f5 100644 --- a/src/resources/mesh.cpp +++ b/src/resources/mesh.cpp @@ -42,7 +42,7 @@ void Mesh::initMesh() void Mesh::drawMesh(const gfx::Pipeline* pipeline) { - gfx->drawIndexed(pipeline, vb, ib, m_indices.size()); + gfx->draw(pipeline, vb, ib, m_indices.size(), nullptr); } Mesh::Mesh(GFXDevice* gfx, const std::vector& vertices) : Resource("", "mesh"), gfx(gfx)