Skip to content
Snippets Groups Projects
Commit fe9d5779 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Merge branch '33-pipeline-buffer-input' into 'develop'

Resolve "Pipeline Buffer Input"

Closes #33

See merge request !29
parents f05dcda6 04cc44e1
No related branches found
No related tags found
1 merge request!29Resolve "Pipeline Buffer Input"
Pipeline #25285 passed
Showing
with 195 additions and 88 deletions
......@@ -53,7 +53,7 @@ set(vkcv_sources
${vkcv_source}/vkcv/Framebuffer.hpp
${vkcv_source}/vkcv/Framebuffer.cpp
${vkcv_include}/vkcv/VertexLayout.hpp
${vkcv_source}/vkcv/VertexLayout.cpp
......
......@@ -186,8 +186,9 @@ namespace vkcv
/**
* @brief render a beautiful triangle
*/
void renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle,
const int width, const int height, const size_t pushConstantSize, const void* pushConstantData);
void renderMesh(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle,
const int width, const int height, const size_t pushConstantSize, const void* pushConstantData,
const BufferHandle vertexBuffer, const BufferHandle indexBuffer, const size_t indexCount);
/**
* @brief end recording and present image
......
#pragma once
/**
* @authors Mara Vogt, Mark Mints
* @file src/vkcv/Pipeline.hpp
* @brief Pipeline class to handle shader stages
*/
#ifndef VKCV_PIPELINECONFIG_HPP
#define VKCV_PIPELINECONFIG_HPP
#include <vector>
#include <cstdint>
#include "vkcv/Handles.hpp"
......@@ -39,5 +37,4 @@ namespace vkcv {
PassHandle m_PassHandle;
};
}
#endif //VKCV_PIPELINECONFIG_HPP
}
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include <unordered_map>
#include <vector>
#include <iostream>
#include <vulkan/vulkan.hpp>
namespace vkcv{
enum class VertexFormat{
......@@ -33,5 +34,6 @@ namespace vkcv{
uint32_t stride;
};
// currently assuming default 32 bit formats, no lower precision or normalized variants supported
vk::Format vertexFormatToVulkanFormat(const VertexFormat format);
}
\ No newline at end of file
......@@ -22,7 +22,7 @@ if(MSVC)
endif()
# including headers of dependencies and the VkCV framework
target_include_directories(first_mesh SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include})
target_include_directories(first_mesh SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include})
# linking with libraries from all dependencies and the VkCV framework
target_link_libraries(first_mesh vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries})
target_link_libraries(first_mesh vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera)
%VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv
%VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv
pause
\ No newline at end of file
File added
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}
\ No newline at end of file
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec3 position;
layout(location = 0) out vec3 fragColor;
layout( push_constant ) uniform constants{
mat4 mvp;
};
void main() {
vec3 positions[3] = {
vec3(-0.5, 0.5, -1),
vec3( 0.5, 0.5, -1),
vec3(0, -0.5, -1)
};
vec3 colors[3] = {
vec3(1, 0, 0),
vec3(0, 1, 0),
vec3(0, 0, 1)
};
gl_Position = mvp * vec4(position, 1.0);
fragColor = colors[gl_VertexIndex % 3];
}
\ No newline at end of file
File added
#include <iostream>
#include <stdio.h>
#include <vkcv/Core.hpp>
#include <GLFW/glfw3.h>
#include <vkcv/camera/CameraManager.hpp>
#include <chrono>
#include <vkcv/asset/asset_loader.hpp>
int main(int argc, const char** argv) {
const char* applicationName = "First Mesh";
const int windowWidth = 800;
const int windowHeight = 600;
vkcv::Window window = vkcv::Window::create(
applicationName,
windowWidth,
windowHeight,
false
);
vkcv::CameraManager cameraManager(window, windowWidth, windowHeight);
window.initEvents();
vkcv::Core core = vkcv::Core::create(
window,
applicationName,
VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
{},
{ "VK_KHR_swapchain" }
);
vkcv::asset::Mesh mesh;
const char *path = argc > 1 ? argv[1] : "resources/cube/cube.gltf";
const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf";
int result = vkcv::asset::loadMesh(path, mesh);
if (result == 1) {
std::cout << "Mesh loading successful!" << std::endl;
} else {
}
else {
std::cout << "Mesh loading failed: " << result << std::endl;
return 1;
}
/* Demonstration of how to use the vkcv::asset::Mesh struct. */
const char *primitive_modes[] = {
"points", "lines", "line loop", "line strip", "triangles",
"triangle strip", "triangle fan"
};
const char *primitive_types[] = {
"unknown", "position", "normal", "texcoord0"
};
printf("Mesh %s (%s) has %lu vertex group(s) and %lu material(s):\n",
mesh.name.c_str(), path, mesh.vertexGroups.size(),
mesh.materials.size());
for (size_t i = 0; i < mesh.vertexGroups.size(); i++) {
printf("--- vertex group %lu ---\n", i);
const auto &vg = mesh.vertexGroups[i];
printf("primitive mode: %d (%s)\n", vg.mode,
primitive_modes[vg.mode]);
printf("index buffer: %lu bytes for %lu indices ",
vg.indexBuffer.data.size(), vg.numIndices);
const auto itype = vg.indexBuffer.type;
printf("(%s @ %p)\n",
itype == vkcv::asset::UINT32 ? "UINT32" :
itype == vkcv::asset::UINT16 ? "UINT16" :
"UINT8", vg.indexBuffer.data.data());
printf("\tindices: ");
const size_t n = vg.numIndices;
if (vg.indexBuffer.type == vkcv::asset::UINT32) {
uint32_t *idx = (uint32_t*)vg.indexBuffer.data.data();
for (size_t j = 0; j < n; j++) printf("%u ", idx[j]);
} else
if (vg.indexBuffer.type == vkcv::asset::UINT16) {
uint16_t *idx = (uint16_t*)vg.indexBuffer.data.data();
for (size_t j = 0; j < n; j++) printf("%u ", idx[j]);
} else
if (vg.indexBuffer.type == vkcv::asset::UINT8) {
uint8_t *idx = (uint8_t*)vg.indexBuffer.data.data();
for (size_t j = 0; j < n; j++) printf("%u ", idx[j]);
} else {
fprintf(stderr, "ERROR Invalid IndexType: %d\n",
vg.indexBuffer.type);
return 0;
}
printf("\n");
printf("vertex buffer: %lu bytes for %lu vertices with %lu "
"attributes (starting at %p)\n",
vg.vertexBuffer.data.size(), vg.numVertices,
vg.vertexBuffer.attributes.size(),
vg.vertexBuffer.data.data());
printf("attributes:\toffset\tlength\tstride\tcomponents\n");
for (const auto att : vg.vertexBuffer.attributes) {
printf("%11s\t%u\t%u\t%u\t%hhux%hu\n",
primitive_types[att.type],
att.offset, att.length, att.stride,
att.componentCount, att.componentType);
}
assert(mesh.vertexGroups.size() > 0);
const size_t vertexBufferSize = mesh.vertexGroups[0].vertexBuffer.data.size();
auto vertexBuffer = core.createBuffer<uint8_t>(vkcv::BufferType::VERTEX, vertexBufferSize, vkcv::BufferMemoryType::DEVICE_LOCAL);
vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data.data(), vertexBufferSize);
const size_t indexBufferSize = mesh.vertexGroups[0].indexBuffer.data.size();
auto indexBuffer = core.createBuffer<uint8_t>(vkcv::BufferType::INDEX, indexBufferSize, vkcv::BufferMemoryType::DEVICE_LOCAL);
indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data.data(), indexBufferSize);
// an example attachment for passes that output to the window
const vkcv::AttachmentDescription present_color_attachment(
vkcv::AttachmentLayout::UNDEFINED,
vkcv::AttachmentLayout::COLOR_ATTACHMENT,
vkcv::AttachmentLayout::PRESENTATION,
vkcv::AttachmentOperation::STORE,
vkcv::AttachmentOperation::CLEAR,
core.getSwapchainImageFormat());
vkcv::PassConfig trianglePassDefinition({ present_color_attachment });
vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
if (!trianglePass) {
std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
return EXIT_FAILURE;
}
vkcv::ShaderProgram triangleShaderProgram{};
triangleShaderProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/vert.spv"));
triangleShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/frag.spv"));
triangleShaderProgram.reflectShader(vkcv::ShaderStage::VERTEX);
triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT);
const vkcv::PipelineConfig trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass);
vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
if (!trianglePipeline) {
std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
return EXIT_FAILURE;
}
auto start = std::chrono::system_clock::now();
while (window.isWindowOpen()) {
core.beginFrame();
window.pollEvents();
auto end = std::chrono::system_clock::now();
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(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, vertexBuffer.getHandle(), indexBuffer.getHandle(), mesh.vertexGroups[0].numIndices);
core.endFrame();
}
return 0;
}
......@@ -40,15 +40,19 @@ int main(int argc, const char** argv) {
const size_t n = 5027;
auto buffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL);
vec3 vec_data [n];
auto testBuffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL);
vec3 vec_data[n];
for (size_t i = 0; i < n; i++) {
vec_data[i] = { 42, static_cast<float>(i), 7 };
}
buffer.fill(vec_data);
testBuffer.fill(vec_data);
auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL);
uint16_t indices[3] = { 0, 1, 2 };
triangleIndexBuffer.fill(&indices[0], sizeof(indices));
/*vec3* m = buffer.map();
m[0] = { 0, 0, 0 };
m[1] = { 0, 0, 0 };
......@@ -143,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.renderTriangle(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp);
core.renderMesh(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, testBuffer.getHandle(), triangleIndexBuffer.getHandle(), 3);
core.endFrame();
}
return 0;
......
......@@ -69,6 +69,9 @@ namespace vkcv {
case BufferType::STAGING:
usageFlags = vk::BufferUsageFlagBits::eTransferSrc;
break;
case BufferType::INDEX:
usageFlags = vk::BufferUsageFlagBits::eIndexBuffer;
break;
default:
// TODO: maybe an issue
break;
......
......@@ -162,8 +162,9 @@ namespace vkcv
destroyTemporaryFramebuffers();
}
void Core::renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle,
const int width, const int height, const size_t pushConstantSize, const void *pushConstantData) {
void Core::renderMesh(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle,
const int width, const int height, const size_t pushConstantSize, const void *pushConstantData,
const BufferHandle vertexBuffer, const BufferHandle indexBuffer, const size_t indexCount) {
if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
return;
......@@ -174,6 +175,8 @@ namespace vkcv
const vk::Pipeline pipeline = m_PipelineManager->getVkPipeline(pipelineHandle);
const vk::PipelineLayout pipelineLayout = m_PipelineManager->getVkPipelineLayout(pipelineHandle);
const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height));
const vk::Buffer vulkanVertexBuffer = m_BufferManager->getBuffer(vertexBuffer);
const vk::Buffer vulkanIndexBuffer = m_BufferManager->getBuffer(indexBuffer);
const vk::Framebuffer framebuffer = createFramebuffer(m_Context.getDevice(), renderpass, width, height, imageView);
m_TemporaryFramebuffers.push_back(framebuffer);
......@@ -181,7 +184,8 @@ namespace vkcv
SubmitInfo submitInfo;
submitInfo.queueType = QueueType::Graphics;
submitInfo.signalSemaphores = { m_SyncResources.renderFinished };
submitCommands(submitInfo, [renderpass, renderArea, imageView, framebuffer, pipeline, pipelineLayout, pushConstantSize, pushConstantData](const vk::CommandBuffer& cmdBuffer) {
submitCommands(submitInfo, [renderpass, renderArea, imageView, framebuffer, pipeline, pipelineLayout,
pushConstantSize, pushConstantData, vulkanVertexBuffer, indexCount, vulkanIndexBuffer](const vk::CommandBuffer& cmdBuffer) {
const std::array<float, 4> clearColor = { 0.f, 0.f, 0.f, 1.f };
const vk::ClearValue clearValues(clearColor);
......@@ -191,8 +195,11 @@ namespace vkcv
cmdBuffer.beginRenderPass(beginInfo, subpassContents, {});
cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {});
cmdBuffer.bindVertexBuffers(0, (vulkanVertexBuffer), { 0 });
cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size
cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData);
cmdBuffer.draw(3, 1, 0, 0, {});
cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {});
cmdBuffer.endRenderPass();
}, nullptr);
}
......
......@@ -67,15 +67,30 @@ namespace vkcv
);
// vertex input state
vk::VertexInputBindingDescription vertexInputBindingDescription(0, 12, vk::VertexInputRate::eVertex);
vk::VertexInputAttributeDescription vertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32Sfloat, 0);
// Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers
std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions;
std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions;
VertexLayout layout = config.m_ShaderProgram.getVertexLayout();
std::unordered_map<uint32_t, VertexInputAttachment> attachments = layout.attachmentMap;
for (auto& attachment: attachments) {
uint32_t location = attachment.second.location;
uint32_t binding = attachment.second.binding;
uint32_t offset = attachment.second.offset;
vk::Format vertexFormat = vertexFormatToVulkanFormat(attachment.second.format);
vertexBindingDescriptions.push_back({binding, layout.stride, vk::VertexInputRate::eVertex}); // TODO: What's about the input rate?
vertexAttributeDescriptions.push_back({location, binding, vk::Format::eR32G32B32Sfloat, offset});
}
// Handover Containers to PipelineVertexInputStateCreateIngo Struct
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
{}, // no vertex input until vertex buffer is implemented
0, // 1,
nullptr, // &vertexInputBindingDescription,
0, // 1,
nullptr // &vertexInputAttributeDescription
{},
vertexBindingDescriptions.size(),
vertexBindingDescriptions.data(),
vertexAttributeDescriptions.size(),
vertexAttributeDescriptions.data()
);
// input assembly state
......
......@@ -50,4 +50,18 @@ namespace vkcv {
}
}
vk::Format vertexFormatToVulkanFormat(const VertexFormat format) {
switch (format) {
case VertexFormat::FLOAT : return vk::Format::eR32Sfloat;
case VertexFormat::FLOAT2 : return vk::Format::eR32G32Sfloat;
case VertexFormat::FLOAT3 : return vk::Format::eR32G32B32Sfloat;
case VertexFormat::FLOAT4 : return vk::Format::eR32G32B32A32Sfloat;
case VertexFormat::INT : return vk::Format::eR32Sint;
case VertexFormat::INT2 : return vk::Format::eR32G32Sint;
case VertexFormat::INT3 : return vk::Format::eR32G32B32Sint;
case VertexFormat::INT4 : return vk::Format::eR32G32B32A32Sint;
default: std::cerr << "Warning: Unknown vertex format" << std::endl; return vk::Format::eUndefined;
}
}
}
\ 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