feat: added uniform buffers
This commit is contained in:
@@ -1,12 +1,18 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_ARB_separate_shader_objects : enable
|
#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 = 0) in vec2 inPosition;
|
||||||
layout(location = 1) in vec3 inColor;
|
layout(location = 1) in vec3 inColor;
|
||||||
|
|
||||||
layout(location = 0) out vec3 fragColor;
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
void main() {
|
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;
|
fragColor = inColor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,11 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
#define GLFW_INCLUDE_VULKAN
|
||||||
#include <GLFW/glfw3.h>
|
#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 = {
|
//const std::vector<Vertex> vertices = {
|
||||||
// {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
// {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||||
// {{0.5f, 0.5f}, {0.0f, 1.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() {
|
void HelloTriangleApplication::createGraphicsPipeline() {
|
||||||
std::vector<char> vertShaderCode;
|
std::vector<char> vertShaderCode;
|
||||||
std::vector<char> fragShaderCode;
|
std::vector<char> fragShaderCode;
|
||||||
@@ -268,7 +350,8 @@ void HelloTriangleApplication::createGraphicsPipeline() {
|
|||||||
.rasterizerDiscardEnable = VK_FALSE,
|
.rasterizerDiscardEnable = VK_FALSE,
|
||||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
||||||
.cullMode = VK_CULL_MODE_BACK_BIT,
|
.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,
|
.depthBiasEnable = VK_FALSE,
|
||||||
.depthBiasConstantFactor = 0.0f,
|
.depthBiasConstantFactor = 0.0f,
|
||||||
.depthBiasClamp = 0.0f,
|
.depthBiasClamp = 0.0f,
|
||||||
@@ -327,8 +410,8 @@ void HelloTriangleApplication::createGraphicsPipeline() {
|
|||||||
};
|
};
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
.setLayoutCount = 0,
|
.setLayoutCount = 1,
|
||||||
.pSetLayouts = nullptr,
|
.pSetLayouts = &descriptorSetLayout,
|
||||||
.pushConstantRangeCount = 0,
|
.pushConstantRangeCount = 0,
|
||||||
.pPushConstantRanges = nullptr,
|
.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() {
|
void HelloTriangleApplication::createCommandBuffers() {
|
||||||
commandBuffers.resize(swapChainFrameBuffers.size());
|
commandBuffers.resize(swapChainFrameBuffers.size());
|
||||||
|
|
||||||
@@ -537,6 +631,7 @@ void HelloTriangleApplication::createCommandBuffers() {
|
|||||||
VkDeviceSize offset[] = {0};
|
VkDeviceSize offset[] = {0};
|
||||||
vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offset);
|
vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offset);
|
||||||
vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16);
|
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);
|
vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
|
||||||
vkCmdEndRenderPass(commandBuffers[i]);
|
vkCmdEndRenderPass(commandBuffers[i]);
|
||||||
if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
|
||||||
@@ -571,11 +666,15 @@ void HelloTriangleApplication::initVulkan() {
|
|||||||
createSwapChain();
|
createSwapChain();
|
||||||
createImageViews();
|
createImageViews();
|
||||||
createRenderPass();
|
createRenderPass();
|
||||||
|
createDescriptorSetLayout();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
createFrameBuffers();
|
createFrameBuffers();
|
||||||
createCommandPool();
|
createCommandPool();
|
||||||
createVertexBuffer();
|
createVertexBuffer();
|
||||||
createIndexBuffer();
|
createIndexBuffer();
|
||||||
|
createUniformBuffers();
|
||||||
|
createDescriptorPool();
|
||||||
|
createDescriptorSets();
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
createSyncObjects();
|
createSyncObjects();
|
||||||
}
|
}
|
||||||
@@ -597,6 +696,9 @@ void HelloTriangleApplication::recreateSwapChain() {
|
|||||||
createRenderPass();
|
createRenderPass();
|
||||||
createGraphicsPipeline();
|
createGraphicsPipeline();
|
||||||
createFrameBuffers();
|
createFrameBuffers();
|
||||||
|
createUniformBuffers();
|
||||||
|
createDescriptorPool();
|
||||||
|
createDescriptorSets();
|
||||||
createCommandBuffers();
|
createCommandBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,6 +718,13 @@ void HelloTriangleApplication::cleanupSwapChain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vkDestroySwapchainKHR(myVkInstance->device, swapChain, nullptr);
|
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() {
|
void HelloTriangleApplication::mainLoop() {
|
||||||
@@ -629,9 +738,8 @@ void HelloTriangleApplication::mainLoop() {
|
|||||||
void HelloTriangleApplication::drawFrame() {
|
void HelloTriangleApplication::drawFrame() {
|
||||||
vkWaitForFences(myVkInstance->device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(myVkInstance->device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
uint32_t imageIndex;
|
uint32_t imageIndex;
|
||||||
VkResult acquireNextImageResult = vkAcquireNextImageKHR(myVkInstance->device, swapChain, UINT64_MAX,
|
VkResult result = vkAcquireNextImageKHR(myVkInstance->device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||||
imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
switch (result) {
|
||||||
switch (acquireNextImageResult) {
|
|
||||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
return;
|
return;
|
||||||
@@ -642,6 +750,8 @@ void HelloTriangleApplication::drawFrame() {
|
|||||||
throw std::runtime_error("Failed to acquire swap chain image!");
|
throw std::runtime_error("Failed to acquire swap chain image!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateUniformBuffer(imageIndex);
|
||||||
|
|
||||||
if (imagesInFlight[currentFrame] != VK_NULL_HANDLE) {
|
if (imagesInFlight[currentFrame] != VK_NULL_HANDLE) {
|
||||||
vkWaitForFences(myVkInstance->device, 1, &imagesInFlight[currentFrame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(myVkInstance->device, 1, &imagesInFlight[currentFrame], VK_TRUE, UINT64_MAX);
|
||||||
}
|
}
|
||||||
@@ -696,9 +806,29 @@ void HelloTriangleApplication::drawFrame() {
|
|||||||
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
|
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() {
|
void HelloTriangleApplication::cleanup() {
|
||||||
cleanupSwapChain();
|
cleanupSwapChain();
|
||||||
|
|
||||||
|
vkDestroyDescriptorSetLayout(myVkInstance->device, descriptorSetLayout, nullptr);
|
||||||
|
|
||||||
vkDestroyBuffer(myVkInstance->device, vertexBuffer, nullptr);
|
vkDestroyBuffer(myVkInstance->device, vertexBuffer, nullptr);
|
||||||
vkFreeMemory(myVkInstance->device, vertexBufferMemory, nullptr);
|
vkFreeMemory(myVkInstance->device, vertexBufferMemory, nullptr);
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ private:
|
|||||||
VkFormat swapChainImageFormat;
|
VkFormat swapChainImageFormat;
|
||||||
VkExtent2D swapChainExtent;
|
VkExtent2D swapChainExtent;
|
||||||
VkRenderPass renderPass;
|
VkRenderPass renderPass;
|
||||||
|
VkDescriptorPool descriptorPool;
|
||||||
|
std::vector<VkDescriptorSet> descriptorSets;
|
||||||
|
VkDescriptorSetLayout descriptorSetLayout;
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
VkPipeline graphicsPipeline;
|
VkPipeline graphicsPipeline;
|
||||||
std::vector<VkFramebuffer> swapChainFrameBuffers;
|
std::vector<VkFramebuffer> swapChainFrameBuffers;
|
||||||
@@ -34,6 +37,10 @@ private:
|
|||||||
VkDeviceMemory vertexBufferMemory;
|
VkDeviceMemory vertexBufferMemory;
|
||||||
VkBuffer indexBuffer;
|
VkBuffer indexBuffer;
|
||||||
VkDeviceMemory indexBufferMemory;
|
VkDeviceMemory indexBufferMemory;
|
||||||
|
|
||||||
|
std::vector<VkBuffer> uniformBuffers;
|
||||||
|
std::vector<VkDeviceMemory> uniformBuffersMemory;
|
||||||
|
|
||||||
VkCommandPool commandPool;
|
VkCommandPool commandPool;
|
||||||
std::vector<VkCommandBuffer> commandBuffers;
|
std::vector<VkCommandBuffer> commandBuffers;
|
||||||
|
|
||||||
@@ -48,11 +55,15 @@ private:
|
|||||||
void createSwapChain();
|
void createSwapChain();
|
||||||
void createImageViews();
|
void createImageViews();
|
||||||
void createRenderPass();
|
void createRenderPass();
|
||||||
|
void createDescriptorSetLayout();
|
||||||
|
void createDescriptorPool();
|
||||||
|
void createDescriptorSets();
|
||||||
void createGraphicsPipeline();
|
void createGraphicsPipeline();
|
||||||
void createFrameBuffers();
|
void createFrameBuffers();
|
||||||
void createCommandPool();
|
void createCommandPool();
|
||||||
void createVertexBuffer();
|
void createVertexBuffer();
|
||||||
void createIndexBuffer();
|
void createIndexBuffer();
|
||||||
|
void createUniformBuffers();
|
||||||
void createCommandBuffers();
|
void createCommandBuffers();
|
||||||
void createSyncObjects();
|
void createSyncObjects();
|
||||||
void initVulkan();
|
void initVulkan();
|
||||||
@@ -63,6 +74,7 @@ private:
|
|||||||
// main loop
|
// main loop
|
||||||
void mainLoop();
|
void mainLoop();
|
||||||
void drawFrame();
|
void drawFrame();
|
||||||
|
void updateUniformBuffer(uint32_t imageIndex);
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
void cleanup();
|
void cleanup();
|
||||||
@@ -77,7 +89,6 @@ private:
|
|||||||
|
|
||||||
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user