uniform buffer object

main
Benjamin Kraft 2 weeks ago
parent f12a9bf441
commit 9e0b0af5e8
  1. 8
      shaders/shader.vert
  2. 1
      src/main.cpp
  3. 127
      src/vulkan/application.cpp
  4. 10
      src/vulkan/application.hpp
  5. 76
      src/vulkan/pipeline.cpp
  6. 22
      src/vulkan/pipeline.hpp
  7. 26
      src/vulkan/vertex.cpp
  8. 25
      src/vulkan/vertex.hpp

@ -5,7 +5,13 @@ layout (location = 1) in vec3 inColor;
layout (location = 0) out vec3 fragColor;
layout (binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 projection;
} ubo;
void main() {
gl_Position = vec4(inPosition, 0.0, 1.0);
gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
fragColor = inColor;
}

@ -4,4 +4,5 @@
int main() {
Application application;
application.mainLoop();
}

@ -19,6 +19,14 @@ Application::Application() {
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
uniformBuffer = new Buffer(instance, bufferSize,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkMapMemory(instance->device, uniformBuffer->memory, 0, bufferSize, 0, &uniformBufferMapped);
pipeline->createDescriptorSet(uniformBuffer);
commandPool = new CommandPool(instance);
stagedVertexBuffer->copyTo(vertexBuffer, commandPool);
@ -28,16 +36,68 @@ Application::Application() {
delete stagedIndexBuffer;
createSyncObjects();
}
void Application::updateUniformBuffer() {
static float elapsed = 0;
mainLoop();
elapsed += 0.007;
UniformBufferObject ubo {};
ubo.model = glm::rotate(glm::mat4(1), elapsed * glm::radians(90.f), glm::vec3(0, 0, 1));
ubo.view = glm::lookAt(glm::vec3(2), glm::vec3(0), glm::vec3(0, 0, 1));
ubo.projection = glm::perspective(glm::radians(45.f),
static_cast<float>(swapchain->extent.width) / static_cast<float>(swapchain->extent.height),
0.1f, 10.f);
ubo.projection[1][1] *= -1;
memcpy(uniformBufferMapped, &ubo, sizeof(UniformBufferObject));
}
void Application::mainLoop() {
while (!glfwWindowShouldClose(instance->window)){
glfwPollEvents();
drawFrame();
}
vkDeviceWaitIdle(instance->device);
void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkRenderPassBeginInfo renderPassInfo {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = swapchain->renderPass;
renderPassInfo.framebuffer = swapchain->frameBuffers[imageIndex];
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapchain->extent;
VkClearValue clearColor = {{{0, 0, 0, 1}}};
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle);
VkViewport viewport {};
viewport.x = 0;
viewport.y = 0;
viewport.width = static_cast<float>(swapchain->extent.width);
viewport.height = static_cast<float>(swapchain->extent.height);
viewport.minDepth = 0;
viewport.maxDepth = 1;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor {};
scissor.offset = {0, 0};
scissor.extent = swapchain->extent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
VkBuffer buffers[] = {vertexBuffer->handle};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->handle, 0, VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->layout, 0, 1, &pipeline->descriptorSet, 0, nullptr);
vkCmdDrawIndexed(commandBuffer, indices.size(), 1, 0, 0, 0);
vkCmdEndRenderPass(commandBuffer);
vkEndCommandBuffer(commandBuffer);
}
void Application::drawFrame() {
@ -55,6 +115,8 @@ void Application::drawFrame() {
vkResetCommandBuffer(commandPool->buffers[currentFrame], 0);
recordCommandBuffer(commandPool->buffers[currentFrame], imageIndex);
updateUniformBuffer();
VkSubmitInfo submitInfo {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@ -110,50 +172,12 @@ void Application::createSyncObjects() {
}
}
void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkRenderPassBeginInfo renderPassInfo {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = swapchain->renderPass;
renderPassInfo.framebuffer = swapchain->frameBuffers[imageIndex];
renderPassInfo.renderArea.offset = {0, 0};
renderPassInfo.renderArea.extent = swapchain->extent;
VkClearValue clearColor = {{{0, 0, 0, 1}}};
renderPassInfo.clearValueCount = 1;
renderPassInfo.pClearValues = &clearColor;
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->graphicsPipeline);
VkViewport viewport {};
viewport.x = 0;
viewport.y = 0;
viewport.width = static_cast<float>(swapchain->extent.width);
viewport.height = static_cast<float>(swapchain->extent.height);
viewport.minDepth = 0;
viewport.maxDepth = 1;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor {};
scissor.offset = {0, 0};
scissor.extent = swapchain->extent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
VkBuffer buffers[] = {vertexBuffer->handle};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer->handle, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(commandBuffer, indices.size(), 1, 0, 0, 0);
vkCmdEndRenderPass(commandBuffer);
vkEndCommandBuffer(commandBuffer);
void Application::mainLoop() {
while (!glfwWindowShouldClose(instance->window)){
glfwPollEvents();
drawFrame();
}
vkDeviceWaitIdle(instance->device);
}
Application::~Application() {
@ -166,6 +190,7 @@ Application::~Application() {
delete commandPool;
delete vertexBuffer;
delete indexBuffer;
delete uniformBuffer;
delete pipeline;
delete instance;
}

@ -22,7 +22,7 @@ class Pipeline;
class Buffer;
class CommandPool;
constexpr int MAX_FRAMES_IN_FLIGHT = 2;
constexpr int MAX_FRAMES_IN_FLIGHT = 1;
class Timer {
public:
@ -40,6 +40,7 @@ private:
class Application {
public:
explicit Application();
void mainLoop();
~Application();
private:
Instance* instance = nullptr;
@ -47,8 +48,13 @@ private:
Pipeline* pipeline = nullptr;
Buffer* vertexBuffer = nullptr;
Buffer* indexBuffer = nullptr;
Buffer* uniformBuffer = nullptr;
CommandPool* commandPool = nullptr;
void* uniformBufferMapped = nullptr;
void updateUniformBuffer();
void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex);
std::vector<VkSemaphore> imageAvailableSemaphores;
@ -59,6 +65,4 @@ private:
void drawFrame();
void createSyncObjects();
void mainLoop();
};

@ -3,6 +3,7 @@
#include "pipeline.hpp"
#include "vertex.hpp"
#include "instance.hpp"
#include "buffer.hpp"
std::vector<char> readFile(const std::string& fileName){
std::ifstream file(fileName, std::ios::ate | std::ios::binary);
@ -22,6 +23,9 @@ std::vector<char> readFile(const std::string& fileName){
}
Pipeline::Pipeline(Instance* instance, VkRenderPass renderPass) : instance(instance) {
createDescriptorSetLayout();
createDescriptorPool();
auto vertShaderCode = readFile("shaders/vert.spv");
auto fragShaderCode = readFile("shaders/frag.spv");
@ -80,7 +84,7 @@ Pipeline::Pipeline(Instance* instance, VkRenderPass renderPass) : instance(insta
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
rasterizer.lineWidth = 1;
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizer.depthBiasClamp = VK_FALSE;
VkPipelineMultisampleStateCreateInfo multisample {};
@ -100,8 +104,10 @@ Pipeline::Pipeline(Instance* instance, VkRenderPass renderPass) : instance(insta
VkPipelineLayoutCreateInfo pipelineLayoutInfo {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
vkCreatePipelineLayout(instance->device, &pipelineLayoutInfo, nullptr, &pipelineLayout);
vkCreatePipelineLayout(instance->device, &pipelineLayoutInfo, nullptr, &layout);
VkGraphicsPipelineCreateInfo pipelineInfo {};
{
@ -118,13 +124,13 @@ Pipeline::Pipeline(Instance* instance, VkRenderPass renderPass) : instance(insta
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicState;
pipelineInfo.layout = pipelineLayout;
pipelineInfo.layout = layout;
pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;
}
vkCreateGraphicsPipelines(instance->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline);
vkCreateGraphicsPipelines(instance->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &handle);
vkDestroyShaderModule(instance->device, vertShaderModule, nullptr);
vkDestroyShaderModule(instance->device, fragShaderModule, nullptr);
@ -142,9 +148,65 @@ VkShaderModule Pipeline::createShaderModule(const std::vector<char> &code) {
return shaderModule;
}
Pipeline::~Pipeline() {
vkDestroyPipeline(instance->device, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(instance->device, pipelineLayout, nullptr);
vkDestroyDescriptorPool(instance->device, descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(instance->device, descriptorSetLayout, nullptr);
vkDestroyPipeline(instance->device, handle, nullptr);
vkDestroyPipelineLayout(instance->device, layout, nullptr);
}
void Pipeline::createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding {};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkDescriptorSetLayoutCreateInfo layoutCreateInfo {};
layoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutCreateInfo.bindingCount = 1;
layoutCreateInfo.pBindings = &uboLayoutBinding;
vkCreateDescriptorSetLayout(instance->device, &layoutCreateInfo, nullptr, &descriptorSetLayout);
}
void Pipeline::createDescriptorPool() {
VkDescriptorPoolSize poolSize {};
poolSize.descriptorCount = 1;
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
VkDescriptorPoolCreateInfo poolInfo {};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.pPoolSizes = &poolSize;
poolInfo.poolSizeCount = 1;
poolInfo.maxSets = 1;
vkCreateDescriptorPool(instance->device, &poolInfo, nullptr, &descriptorPool);
}
void Pipeline::createDescriptorSet(Buffer *buffer) {
VkDescriptorSetAllocateInfo allocateInfo {};
allocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocateInfo.descriptorPool = descriptorPool;
allocateInfo.descriptorSetCount = 1;
allocateInfo.pSetLayouts = &descriptorSetLayout;
vkAllocateDescriptorSets(instance->device, &allocateInfo, &descriptorSet);
VkDescriptorBufferInfo bufferInfo {};
bufferInfo.buffer = buffer->handle;
bufferInfo.offset = 0;
bufferInfo.range = sizeof(UniformBufferObject);
VkWriteDescriptorSet descriptorWrite {};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSet;
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
vkUpdateDescriptorSets(instance->device, 1, &descriptorWrite, 0, nullptr);
}

@ -1,16 +1,34 @@
#pragma once
#include <vulkan/vulkan.h>
#include <glm/gtc/matrix_transform.hpp>
class Instance;
class Buffer;
struct UniformBufferObject {
alignas(16) glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
};
class Pipeline {
public:
explicit Pipeline(Instance* instance, VkRenderPass renderPass);
~Pipeline();
VkPipeline graphicsPipeline = VK_NULL_HANDLE;
VkPipeline handle = VK_NULL_HANDLE;
VkPipelineLayout layout = VK_NULL_HANDLE;
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
void createDescriptorSet(Buffer* buffer);
private:
VkShaderModule createShaderModule(const std::vector<char> &code);
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
Instance* instance = nullptr;
void createDescriptorSetLayout();
void createDescriptorPool();
};

@ -1 +1,25 @@
#include "vertex.hpp"
#include "vertex.hpp"
VkVertexInputBindingDescription Vertex::getBindingDescription() {
VkVertexInputBindingDescription bindingDescription {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescription;
}
std::array<VkVertexInputAttributeDescription, 2> Vertex::getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions {};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);
return attributeDescriptions;
}

@ -1,5 +1,6 @@
#pragma once
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <vulkan/vulkan.h>
#include <array>
@ -8,27 +9,7 @@ struct Vertex {
glm::vec2 pos;
glm::vec3 color;
static VkVertexInputBindingDescription getBindingDescription(){
VkVertexInputBindingDescription bindingDescription {};
bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return bindingDescription;
}
static VkVertexInputBindingDescription getBindingDescription();
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions(){
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions {};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);
return attributeDescriptions;
}
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions();
};
Loading…
Cancel
Save