diff --git a/config/Sources.cmake b/config/Sources.cmake index 6fc477cc9552d0a9a8921151ca4435b894630755..e3f5c950ce0d7e5e7e697bda0047ec3da7a15e18 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -69,4 +69,7 @@ set(vkcv_sources ${vkcv_source}/vkcv/SamplerManager.cpp ${vkcv_include}/vkcv/DescriptorWrites.hpp + + ${vkcv_include}/vkcv/DrawcallRecording.hpp + ${vkcv_source}/vkcv/DrawcallRecording.cpp ) diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp index d327067ce409e845bcac5e4c9f56e7de59df89c2..ae935ba9501d4d7776cad7e3ba190a2dd02e5e38 100644 --- a/include/vkcv/Buffer.hpp +++ b/include/vkcv/Buffer.hpp @@ -37,6 +37,11 @@ namespace vkcv { size_t getSize() const { return m_count * sizeof(T); } + + [[nodiscard]] + const vk::Buffer getVulkanHandle() const { + return m_manager->getBuffer(m_handle); + } void fill(const T* data, size_t count = 0, size_t offset = 0) { m_manager->fillBuffer(m_handle, data, count * sizeof(T), offset * sizeof(T)); diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 3071286eea20b57c0fc909716ed933a968e01197..02a58ae875f4a9341268e97e53530f9b2b34b446 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -22,28 +22,11 @@ #include "Sampler.hpp" #include "DescriptorWrites.hpp" #include "Event.hpp" +#include "DrawcallRecording.hpp" namespace vkcv { - struct VertexBufferBinding { - vk::DeviceSize offset; - BufferHandle buffer; - }; - - struct Mesh { - std::vector<VertexBufferBinding> vertexBufferBindings; - BufferHandle indexBuffer; - size_t indexCount; - }; - - struct PushConstantData { - inline PushConstantData(void* data, size_t sizePerDrawcall) : data(data), sizePerDrawcall(sizePerDrawcall){} - - void* data; - size_t sizePerDrawcall; - }; - // forward declarations class PassManager; class PipelineManager; @@ -236,13 +219,12 @@ namespace vkcv /** * @brief render a beautiful triangle */ - void renderMesh( - const PassHandle renderpassHandle, - const PipelineHandle pipelineHandle, - const PushConstantData &pushConstantData, - const Mesh &mesh, - const std::vector<DescriptorSetUsage> &descriptorSets, - const std::vector<ImageHandle> &renderTargets); + void recordDrawcalls( + const PassHandle renderpassHandle, + const PipelineHandle pipelineHandle, + const PushConstantData &pushConstantData, + const std::vector<DrawcallInfo> &drawcalls, + const std::vector<ImageHandle> &renderTargets); /** * @brief end recording and present image diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp index 15083e8c9863ac2e8d44bbe174e0d7f40bf27dfc..86c2e20eb37633e4519749bef507161133e57425 100644 --- a/include/vkcv/DescriptorConfig.hpp +++ b/include/vkcv/DescriptorConfig.hpp @@ -11,13 +11,6 @@ namespace vkcv vk::DescriptorSetLayout layout; }; - struct DescriptorSetUsage { - DescriptorSetUsage(uint32_t setLocation, DescriptorSetHandle handle) noexcept; - - const uint32_t setLocation; - const DescriptorSetHandle handle; - }; - /* * All the types of descriptors (resources) that can be retrieved by the shaders */ diff --git a/include/vkcv/DrawcallRecording.hpp b/include/vkcv/DrawcallRecording.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0929ad038fb95ec1573e7c76e5ce13adb84ab760 --- /dev/null +++ b/include/vkcv/DrawcallRecording.hpp @@ -0,0 +1,54 @@ +#pragma once +#include <vulkan/vulkan.hpp> +#include <vkcv/Handles.hpp> +#include <vkcv/DescriptorConfig.hpp> + +namespace vkcv { + struct VertexBufferBinding { + inline VertexBufferBinding(vk::DeviceSize offset, vk::Buffer buffer) noexcept + : offset(offset), buffer(buffer) {} + + vk::DeviceSize offset; + vk::Buffer buffer; + }; + + struct DescriptorSetUsage { + inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle) noexcept + : setLocation(setLocation), vulkanHandle(vulkanHandle) {} + + const uint32_t setLocation; + const vk::DescriptorSet vulkanHandle; + }; + + struct Mesh { + inline Mesh(std::vector<VertexBufferBinding> vertexBufferBindings, vk::Buffer indexBuffer, size_t indexCount) noexcept + : vertexBufferBindings(vertexBufferBindings), indexBuffer(indexBuffer), indexCount(indexCount){} + + std::vector<VertexBufferBinding> vertexBufferBindings; + vk::Buffer indexBuffer; + size_t indexCount; + }; + + struct PushConstantData { + inline PushConstantData(void* data, size_t sizePerDrawcall) : data(data), sizePerDrawcall(sizePerDrawcall) {} + + void* data; + size_t sizePerDrawcall; + }; + + struct DrawcallInfo { + inline DrawcallInfo(const Mesh& mesh, const std::vector<DescriptorSetUsage>& descriptorSets) + : mesh(mesh), descriptorSets(descriptorSets) {} + + Mesh mesh; + std::vector<DescriptorSetUsage> descriptorSets; + }; + + void recordDrawcall( + const DrawcallInfo &drawcall, + vk::CommandBuffer cmdBuffer, + vk::PipelineLayout pipelineLayout, + const PushConstantData &pushConstantData, + const size_t drawcallIndex); + +} \ No newline at end of file diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp index e1bbdf3bda378119a3d90688a2e6a7786f16acfe..7c2a5b5e1417b07064cd09feb733e0d0dc54482a 100644 --- a/projects/cmd_sync_test/src/main.cpp +++ b/projects/cmd_sync_test/src/main.cpp @@ -18,6 +18,7 @@ int main(int argc, const char** argv) { ); vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); + cameraManager.getCamera().setPosition(glm::vec3(0.f, 0.f, 3.f)); window.initEvents(); @@ -60,14 +61,12 @@ int main(int argc, const char** argv) { indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data); - vkcv::Mesh boxMesh; - boxMesh.indexBuffer = indexBuffer.getHandle(); - boxMesh.vertexBufferBindings = { - { mesh.vertexGroups[0].vertexBuffer.attributes[0].offset, vertexBuffer.getHandle() }, - { mesh.vertexGroups[0].vertexBuffer.attributes[1].offset, vertexBuffer.getHandle() }, - { mesh.vertexGroups[0].vertexBuffer.attributes[2].offset, vertexBuffer.getHandle() } - }; - boxMesh.indexCount = mesh.vertexGroups[0].numIndices; + const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = { + vkcv::VertexBufferBinding(mesh.vertexGroups[0].vertexBuffer.attributes[0].offset, vertexBuffer.getVulkanHandle()), + vkcv::VertexBufferBinding(mesh.vertexGroups[0].vertexBuffer.attributes[1].offset, vertexBuffer.getVulkanHandle()), + vkcv::VertexBufferBinding(mesh.vertexGroups[0].vertexBuffer.attributes[2].offset, vertexBuffer.getVulkanHandle()) }; + + const vkcv::Mesh loadedMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices); // an example attachment for passes that output to the window const vkcv::AttachmentDescription present_color_attachment( @@ -150,6 +149,25 @@ int main(int argc, const char** argv) { }); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); + const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; + + const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); + + const std::vector<glm::vec3> instancePositions = { + glm::vec3( 0.f, -2.f, 0.f), + glm::vec3( 3.f, 0.f, 0.f), + glm::vec3(-3.f, 0.f, 0.f), + glm::vec3( 0.f, 2.f, 0.f) + }; + + std::vector<glm::mat4> modelMatrices; + std::vector<vkcv::DrawcallInfo> drawcalls; + for (const auto& position : instancePositions) { + modelMatrices.push_back(glm::translate(glm::mat4(1.f), position)); + drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage })); + } + + std::vector<glm::mat4> mvpMatrices; auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { @@ -159,15 +177,20 @@ int main(int argc, const char** argv) { auto deltatime = end - start; start = end; cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); - const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - core.renderMesh( + const glm::mat4 viewProjection = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); + mvpMatrices.clear(); + for (const auto& m : modelMatrices) { + mvpMatrices.push_back(viewProjection * m); + } + vkcv::PushConstantData pushConstantData((void*)mvpMatrices.data(), sizeof(glm::mat4)); + + core.recordDrawcalls( trianglePass, trianglePipeline, - vkcv::PushConstantData((void*) &mvp, sizeof(mvp)), - boxMesh, - { vkcv::DescriptorSetUsage(0, descriptorSet) }, - { swapchainInput, depthBuffer }); + pushConstantData, + drawcalls, + renderTargets); core.endFrame(); } diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index bc832b91df1a4b2cf65bdcb11d771abc4a6bf3c1..bf728391d090e44b441c3ee12b3c2a26f6dca60e 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -170,7 +170,7 @@ int main(int argc, const char** argv) { cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - core.renderMesh( + core.recordDrawcalls( trianglePass, trianglePipeline, sizeof(mvp), diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 24aaa9ef45713e1a1d24e079d29f9279f49386d1..649a3f8748be1e05c2c5ee79b3734f5e6387dfc5 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -147,7 +147,7 @@ int main(int argc, const char** argv) { cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - core.renderMesh( + core.recordDrawcalls( trianglePass, trianglePipeline, sizeof(mvp), diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 96fb0f1e9d1287c0df0b9e63196c516bea716f57..08189af15111128aa51cd8619f0ba092d653eb17 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -141,13 +141,12 @@ namespace vkcv m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but its getting late - Alex } - void Core::renderMesh( - const PassHandle renderpassHandle, - const PipelineHandle pipelineHandle, - const PushConstantData &pushConstantData, - const Mesh &mesh, - const std::vector<DescriptorSetUsage> &descriptorSets, - const std::vector<ImageHandle> &renderTargets) { + void Core::recordDrawcalls( + const PassHandle renderpassHandle, + const PipelineHandle pipelineHandle, + const PushConstantData &pushConstantData, + const std::vector<DrawcallInfo> &drawcalls, + const std::vector<ImageHandle> &renderTargets) { if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; @@ -254,33 +253,10 @@ namespace vkcv cmdBuffer.setScissor(0, 1, &dynamicScissor); } - for (uint32_t i = 0; i < mesh.vertexBufferBindings.size(); i++) { - const auto &vertexBinding = mesh.vertexBufferBindings[i]; - const auto vertexBuffer = bufferManager->getBuffer(vertexBinding.buffer); - cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset)); + for (int i = 0; i < drawcalls.size(); i++) { + recordDrawcall(drawcalls[i], cmdBuffer, pipelineLayout, pushConstantData, i); } - for (const auto &descriptorUsage : descriptorSets) { - cmdBuffer.bindDescriptorSets( - vk::PipelineBindPoint::eGraphics, - pipelineLayout, - descriptorUsage.setLocation, - m_DescriptorManager->getDescriptorSet(descriptorUsage.handle).vulkanHandle, - nullptr); - } - - const vk::Buffer indexBuffer = m_BufferManager->getBuffer(mesh.indexBuffer); - - cmdBuffer.bindIndexBuffer(indexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size - - cmdBuffer.pushConstants( - pipelineLayout, - vk::ShaderStageFlagBits::eAll, - 0, - pushConstantData.sizePerDrawcall, - pushConstantData.data); - - cmdBuffer.drawIndexed(mesh.indexCount, 1, 0, 0, {}); cmdBuffer.endRenderPass(); }; diff --git a/src/vkcv/DescriptorConfig.cpp b/src/vkcv/DescriptorConfig.cpp index 122d29fe76a6c9a1c933e40c21486f975fd286ce..be6cfc9b40baad6636e6bc6a2b6e803aacd7ddc0 100644 --- a/src/vkcv/DescriptorConfig.cpp +++ b/src/vkcv/DescriptorConfig.cpp @@ -1,10 +1,6 @@ #include "vkcv/DescriptorConfig.hpp" namespace vkcv { - - DescriptorSetUsage::DescriptorSetUsage(uint32_t setLocation, DescriptorSetHandle handle) noexcept - : setLocation(setLocation), handle(handle) {} - DescriptorBinding::DescriptorBinding( DescriptorType descriptorType, uint32_t descriptorCount, diff --git a/src/vkcv/DrawcallRecording.cpp b/src/vkcv/DrawcallRecording.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85b6eeb5fa413223b7b7f10f77b868252912041b --- /dev/null +++ b/src/vkcv/DrawcallRecording.cpp @@ -0,0 +1,41 @@ +#include <vkcv/DrawcallRecording.hpp> + +namespace vkcv { + + void recordDrawcall( + const DrawcallInfo &drawcall, + vk::CommandBuffer cmdBuffer, + vk::PipelineLayout pipelineLayout, + const PushConstantData &pushConstantData, + const size_t drawcallIndex) { + + for (uint32_t i = 0; i < drawcall.mesh.vertexBufferBindings.size(); i++) { + const auto& vertexBinding = drawcall.mesh.vertexBufferBindings[i]; + cmdBuffer.bindVertexBuffers(i, vertexBinding.buffer, vertexBinding.offset); + } + + for (const auto& descriptorUsage : drawcall.descriptorSets) { + cmdBuffer.bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, + pipelineLayout, + descriptorUsage.setLocation, + descriptorUsage.vulkanHandle, + nullptr); + } + + cmdBuffer.bindIndexBuffer(drawcall.mesh.indexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size + + const size_t drawcallPushConstantOffset = drawcallIndex * pushConstantData.sizePerDrawcall; + // char* cast because void* does not support pointer arithmetic + const void* drawcallPushConstantData = drawcallPushConstantOffset + (char*)pushConstantData.data; + + cmdBuffer.pushConstants( + pipelineLayout, + vk::ShaderStageFlagBits::eAll, + 0, + pushConstantData.sizePerDrawcall, + drawcallPushConstantData); + + cmdBuffer.drawIndexed(drawcall.mesh.indexCount, 1, 0, 0, {}); + } +} \ No newline at end of file