Skip to content
Snippets Groups Projects
Commit 9651c69a authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#66] Implement support for multiple meshes

parent 3042e8c1
No related branches found
No related tags found
1 merge request!54Resolve "Cmd/Sync-Rework"
Pipeline #25436 failed
This commit is part of merge request !54. Comments created here will be created in the context of that merge request.
......@@ -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
)
......@@ -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));
......
......@@ -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
......
......@@ -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
*/
......
#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
......@@ -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();
}
......
......@@ -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),
......
......@@ -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),
......
......@@ -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();
};
......
#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,
......
#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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment