feat: added uniform buffers

This commit is contained in:
2020-12-02 21:36:01 +01:00
parent df42db1cbe
commit ed93111f64
3 changed files with 155 additions and 8 deletions

View File

@@ -1,12 +1,18 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor;
void main() {
gl_Position = vec4(inPosition, 0.0, 1.0);
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
fragColor = inColor;
}

View File

@@ -8,7 +8,11 @@
#include <optional>
#include <vector>
#include <array>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <chrono>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
@@ -43,6 +47,12 @@ struct Vertex {
}
};
struct UniformBufferObject {
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
};
//const std::vector<Vertex> vertices = {
// {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}},
// {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}},
@@ -197,6 +207,78 @@ void HelloTriangleApplication::createRenderPass() {
}
}
void HelloTriangleApplication::createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.pImmutableSamplers = nullptr,
};
VkDescriptorSetLayoutCreateInfo layoutCreateInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.pBindings = &uboLayoutBinding,
};
if (vkCreateDescriptorSetLayout(myVkInstance->device, &layoutCreateInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS ) {
throw std::runtime_error("Failed to create descriptor set layout!");
}
}
void HelloTriangleApplication::createDescriptorPool() {
VkDescriptorPoolSize poolSize {
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = static_cast<uint32_t>(swapChainImages.size()),
};
VkDescriptorPoolCreateInfo poolCreateInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.maxSets = static_cast<uint32_t>(swapChainImages.size()),
.poolSizeCount = 1,
.pPoolSizes = &poolSize,
};
if ((vkCreateDescriptorPool(myVkInstance->device, &poolCreateInfo, nullptr, &descriptorPool) != VK_SUCCESS)) {
throw std::runtime_error("Failed to create descriptor pool");
}
}
void HelloTriangleApplication::createDescriptorSets() {
std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), descriptorSetLayout);
VkDescriptorSetAllocateInfo allocateInfo {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = descriptorPool,
.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size()),
.pSetLayouts = layouts.data(),
};
descriptorSets.resize(swapChainImages.size());
if (vkAllocateDescriptorSets(myVkInstance->device, &allocateInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("Failed to allocate descriptor sets");
}
for (size_t i = 0; i < swapChainImages.size(); ++i) {
VkDescriptorBufferInfo bufferInfo {
.buffer = uniformBuffers[i],
.offset = 0,
.range = sizeof(UniformBufferObject)
};
VkWriteDescriptorSet descriptorWrite {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptorSets[i],
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pImageInfo = nullptr,
.pBufferInfo = &bufferInfo,
.pTexelBufferView = nullptr,
};
vkUpdateDescriptorSets(myVkInstance->device, 1, &descriptorWrite, 0, nullptr);
}
}
void HelloTriangleApplication::createGraphicsPipeline() {
std::vector<char> vertShaderCode;
std::vector<char> fragShaderCode;
@@ -268,7 +350,8 @@ void HelloTriangleApplication::createGraphicsPipeline() {
.rasterizerDiscardEnable = VK_FALSE,
.polygonMode = VK_POLYGON_MODE_FILL,
.cullMode = VK_CULL_MODE_BACK_BIT,
.frontFace = VK_FRONT_FACE_CLOCKWISE,
// .frontFace = VK_FRONT_FACE_CLOCKWISE,
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = VK_FALSE,
.depthBiasConstantFactor = 0.0f,
.depthBiasClamp = 0.0f,
@@ -327,8 +410,8 @@ void HelloTriangleApplication::createGraphicsPipeline() {
};
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 0,
.pSetLayouts = nullptr,
.setLayoutCount = 1,
.pSetLayouts = &descriptorSetLayout,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
@@ -497,6 +580,17 @@ void HelloTriangleApplication::createCommandPool() {
}
}
void HelloTriangleApplication::createUniformBuffers() {
VkDeviceSize bufferSize = sizeof(UniformBufferObject);
uniformBuffers.resize(swapChainImages.size());
uniformBuffersMemory.resize(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); ++i) {
createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]);
}
}
void HelloTriangleApplication::createCommandBuffers() {
commandBuffers.resize(swapChainFrameBuffers.size());
@@ -537,6 +631,7 @@ void HelloTriangleApplication::createCommandBuffers() {
VkDeviceSize offset[] = {0};
vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offset);
vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr);
vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
vkCmdEndRenderPass(commandBuffers[i]);
if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
@@ -571,11 +666,15 @@ void HelloTriangleApplication::initVulkan() {
createSwapChain();
createImageViews();
createRenderPass();
createDescriptorSetLayout();
createGraphicsPipeline();
createFrameBuffers();
createCommandPool();
createVertexBuffer();
createIndexBuffer();
createUniformBuffers();
createDescriptorPool();
createDescriptorSets();
createCommandBuffers();
createSyncObjects();
}
@@ -597,6 +696,9 @@ void HelloTriangleApplication::recreateSwapChain() {
createRenderPass();
createGraphicsPipeline();
createFrameBuffers();
createUniformBuffers();
createDescriptorPool();
createDescriptorSets();
createCommandBuffers();
}
@@ -616,6 +718,13 @@ void HelloTriangleApplication::cleanupSwapChain() {
}
vkDestroySwapchainKHR(myVkInstance->device, swapChain, nullptr);
for (size_t i = 0; i < swapChainImages.size(); ++i) {
vkDestroyBuffer(myVkInstance->device, uniformBuffers[i], nullptr);
vkFreeMemory(myVkInstance->device, uniformBuffersMemory[i], nullptr);
}
vkDestroyDescriptorPool(myVkInstance->device, descriptorPool, nullptr);
}
void HelloTriangleApplication::mainLoop() {
@@ -629,9 +738,8 @@ void HelloTriangleApplication::mainLoop() {
void HelloTriangleApplication::drawFrame() {
vkWaitForFences(myVkInstance->device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
uint32_t imageIndex;
VkResult acquireNextImageResult = vkAcquireNextImageKHR(myVkInstance->device, swapChain, UINT64_MAX,
imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
switch (acquireNextImageResult) {
VkResult result = vkAcquireNextImageKHR(myVkInstance->device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
switch (result) {
case VK_ERROR_OUT_OF_DATE_KHR:
recreateSwapChain();
return;
@@ -642,6 +750,8 @@ void HelloTriangleApplication::drawFrame() {
throw std::runtime_error("Failed to acquire swap chain image!");
}
updateUniformBuffer(imageIndex);
if (imagesInFlight[currentFrame] != VK_NULL_HANDLE) {
vkWaitForFences(myVkInstance->device, 1, &imagesInFlight[currentFrame], VK_TRUE, UINT64_MAX);
}
@@ -696,9 +806,29 @@ void HelloTriangleApplication::drawFrame() {
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
void HelloTriangleApplication::updateUniformBuffer(uint32_t imageIndex) {
static auto startTime = std::chrono::high_resolution_clock::now();
auto currentTime = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
UniformBufferObject ubo{
.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f,0.0f,0.0f), glm::vec3(0.0f,0.0f,1.0f)),
.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 10.f),
};
ubo.proj[1][1] *= -1;
void *data;
vkMapMemory(myVkInstance->device, uniformBuffersMemory[imageIndex], 0, sizeof(ubo), 0, &data);
memcpy(data, &ubo, sizeof(ubo));
vkUnmapMemory(myVkInstance->device, uniformBuffersMemory[imageIndex]);
}
void HelloTriangleApplication::cleanup() {
cleanupSwapChain();
vkDestroyDescriptorSetLayout(myVkInstance->device, descriptorSetLayout, nullptr);
vkDestroyBuffer(myVkInstance->device, vertexBuffer, nullptr);
vkFreeMemory(myVkInstance->device, vertexBufferMemory, nullptr);

View File

@@ -27,6 +27,9 @@ private:
VkFormat swapChainImageFormat;
VkExtent2D swapChainExtent;
VkRenderPass renderPass;
VkDescriptorPool descriptorPool;
std::vector<VkDescriptorSet> descriptorSets;
VkDescriptorSetLayout descriptorSetLayout;
VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline;
std::vector<VkFramebuffer> swapChainFrameBuffers;
@@ -34,6 +37,10 @@ private:
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
std::vector<VkBuffer> uniformBuffers;
std::vector<VkDeviceMemory> uniformBuffersMemory;
VkCommandPool commandPool;
std::vector<VkCommandBuffer> commandBuffers;
@@ -48,11 +55,15 @@ private:
void createSwapChain();
void createImageViews();
void createRenderPass();
void createDescriptorSetLayout();
void createDescriptorPool();
void createDescriptorSets();
void createGraphicsPipeline();
void createFrameBuffers();
void createCommandPool();
void createVertexBuffer();
void createIndexBuffer();
void createUniformBuffers();
void createCommandBuffers();
void createSyncObjects();
void initVulkan();
@@ -63,6 +74,7 @@ private:
// main loop
void mainLoop();
void drawFrame();
void updateUniformBuffer(uint32_t imageIndex);
// clean up
void cleanup();
@@ -77,7 +89,6 @@ private:
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
};