Skip to content

Commit

Permalink
Added perspective camera as uniform buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
tstullich committed Sep 16, 2020
1 parent 9abcc32 commit 0276356
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 5 deletions.
8 changes: 7 additions & 1 deletion shaders/shader.vert
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform Camera {
mat4 model;
mat4 view;
mat4 projection;
} cam;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;

layout(location = 0) out vec3 fragColor;

void main() {
gl_Position = vec4(inPosition, 1.0f);
gl_Position = cam.projection * cam.view * cam.model * vec4(inPosition, 1.0f);
fragColor = inColor;
}
6 changes: 6 additions & 0 deletions src/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,9 @@ void IndexBuffer::create(const BufferContext &ctx, const std::vector<uint32_t> &
vkFreeMemory(ctx.logicalDevice, stagingMemory, nullptr);
}

void UniformBuffer::create(const BufferContext &ctx, const Camera &camera) {
VkDeviceSize bufferSize = sizeof(Camera);

init(ctx, bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, buffer, deviceMemory);
}
10 changes: 10 additions & 0 deletions src/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <vulkan/vulkan.h>

#include "camera.h"
#include "vertex.h"

// TODO Templatize this logic since vertex and index buffer creation is almost identical
Expand All @@ -21,6 +22,8 @@ class Buffer {

void cleanup(VkDevice logicalDevice);

inline VkDeviceMemory getDeviceMemory() const { return deviceMemory; }

inline VkBuffer getBuffer() const { return buffer; }

protected:
Expand Down Expand Up @@ -48,4 +51,11 @@ class IndexBuffer : public Buffer {
IndexBuffer() = default;

void create(const BufferContext &ctx, const std::vector<uint32_t> &vertIndices);
};

class UniformBuffer : public Buffer {
public:
UniformBuffer() = default;

void create(const BufferContext &ctx, const Camera &camera);
};
9 changes: 9 additions & 0 deletions src/camera.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <glm/glm.hpp>

struct Camera {
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
};
105 changes: 101 additions & 4 deletions src/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ Renderer::~Renderer() {
vertexBuffer.cleanup(logicalDevice);
vertIndexBuffer.cleanup(logicalDevice);

for (auto& uniformBuffer : uniformBuffers) {
uniformBuffer.cleanup(logicalDevice);
}

vkDestroyDescriptorPool(logicalDevice, descriptorPool, nullptr);
vkDestroyDescriptorSetLayout(logicalDevice, descriptorSetLayout, nullptr);

for (uint32_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
vkDestroySemaphore(logicalDevice, imageAvailableSemaphores[i], nullptr);
Expand Down Expand Up @@ -86,13 +91,16 @@ bool Renderer::checkValidationLayerSupport() {

// Destroys all the resources associated with swapchain recreation
void Renderer::cleanupSwapchain() {
for (size_t i = 0; i < swapchain.getImagesSize(); ++i) {
uniformBuffers[i].cleanup(logicalDevice);
}

vkFreeCommandBuffers(logicalDevice, commandPool, static_cast<uint32_t>(commandBuffers.size()),
commandBuffers.data());
commandBuffers.data());

vkDestroyPipeline(logicalDevice, graphicsPipeline, nullptr);
vkDestroyPipelineLayout(logicalDevice, graphicsPipelineLayout, nullptr);
vkDestroyRenderPass(logicalDevice, renderPass, nullptr);

swapchain.cleanup();
}

Expand Down Expand Up @@ -151,6 +159,8 @@ void Renderer::createCommandBuffers() {

vkCmdBindIndexBuffer(commandBuffers[i], vertIndexBuffer.getBuffer(), 0, VK_INDEX_TYPE_UINT32);

vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout, 0, 1, &descriptorSets[i], 0, nullptr);

vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(vertIndices.size()), 1, 0, 0, 0);
vkCmdEndRenderPass(commandBuffers[i]);

Expand All @@ -170,6 +180,7 @@ void Renderer::createCommandPool() {
}
}

// TODO Check if this is used by Dear IMGUI and how to move it
void Renderer::createDescriptorPool() {
VkDescriptorPoolSize poolSize = {};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
Expand All @@ -186,6 +197,55 @@ void Renderer::createDescriptorPool() {
}
}

void Renderer::createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.binding = 0;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutBinding.descriptorCount = 1;
layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;

VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {};
layoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutCreateInfo.bindingCount = 1;
layoutCreateInfo.pBindings = &layoutBinding;

if (vkCreateDescriptorSetLayout(logicalDevice, &layoutCreateInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("Unable to create descriptor set layouts!");
}
}

void Renderer::createDescriptorSets() {
std::vector<VkDescriptorSetLayout> layouts(swapchain.getImagesSize(), descriptorSetLayout);
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = static_cast<uint32_t>(swapchain.getImagesSize());
allocInfo.pSetLayouts = layouts.data();

descriptorSets.resize(swapchain.getImagesSize());
if (vkAllocateDescriptorSets(logicalDevice, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("Unable to allocate descriptor sets!");
}

for (size_t i = 0; i < swapchain.getImagesSize(); ++i) {
VkDescriptorBufferInfo bufferInfo = {};
bufferInfo.buffer = uniformBuffers[i].getBuffer();
bufferInfo.offset = 0;
bufferInfo.range = sizeof(Camera);

VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;

vkUpdateDescriptorSets(logicalDevice, 1, &descriptorWrite, 0, nullptr);
}
}

void Renderer::createGraphicsPipeline() {
// Load our shader modules in from disk
auto vertShaderCode = ShaderLoader::load("shaders/vert.spv");
Expand Down Expand Up @@ -256,7 +316,7 @@ void Renderer::createGraphicsPipeline() {
rasterizerCreateInfo.rasterizerDiscardEnable = VK_FALSE;
rasterizerCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
rasterizerCreateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
rasterizerCreateInfo.frontFace = VK_FRONT_FACE_CLOCKWISE;
rasterizerCreateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rasterizerCreateInfo.lineWidth = 1.0f;
rasterizerCreateInfo.depthBiasEnable = VK_FALSE;
rasterizerCreateInfo.depthBiasConstantFactor = 0.0f;
Expand Down Expand Up @@ -294,6 +354,8 @@ void Renderer::createGraphicsPipeline() {
// Create a pipeline layout
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {};
pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutCreateInfo.setLayoutCount = 1;
pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout;

if (vkCreatePipelineLayout(logicalDevice, &pipelineLayoutCreateInfo, nullptr,
&graphicsPipelineLayout) != VK_SUCCESS) {
Expand Down Expand Up @@ -543,6 +605,14 @@ UserInterface::UIContext Renderer::createUIContext() {
return context;
}

void Renderer::createUniformBuffers() {
Camera cam{};
uniformBuffers.resize(swapchain.getImagesSize());
for (size_t i = 0; i < swapchain.getImagesSize(); ++i) {
uniformBuffers[i].create(createBufferContext(), cam);
}
}

void Renderer::createVertexBuffer() {
auto ctx = createBufferContext();
vertexBuffer.create(ctx, vertices);
Expand Down Expand Up @@ -576,6 +646,8 @@ void Renderer::drawFrame() {
// Record UI draw data
auto uiCommandBuffer = ui.recordCommands(imageIndex, swapchain.getExtent());

updateUniformBuffer(imageIndex);

VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

Expand Down Expand Up @@ -677,14 +749,17 @@ void Renderer::initVulkan() {
createLogicalDevice();
createSwapchain();
createRenderPass();
createDescriptorSetLayout();
createGraphicsPipeline();
swapchain.initFramebuffers(renderPass);
createCommandPool();
createVertexBuffer();
createIndexBuffer();
createUniformBuffers();
createDescriptorPool();
createDescriptorSets();
createCommandBuffers();
createSyncObjects();
createDescriptorPool();
}

void Renderer::initWindow() {
Expand Down Expand Up @@ -788,6 +863,9 @@ void Renderer::recreateSwapchain() {
createGraphicsPipeline();
swapchain.initFramebuffers(renderPass);
createDescriptorPool();
createUniformBuffers();
createDescriptorPool();
createDescriptorSets();
createCommandBuffers();

// We also need to take care of the UI
Expand Down Expand Up @@ -817,4 +895,23 @@ void Renderer::setupDebugMessenger() {
if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
throw std::runtime_error("Failed to setup debug messenger!");
}
}

void Renderer::updateUniformBuffer(size_t bufferIdx) {
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();

Camera cam{};
auto extent = swapchain.getExtent();
cam.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
cam.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));
cam.proj = glm::perspective(glm::radians(45.0f), extent.width / (float) extent.height, 0.1f, 10.0f);
cam.proj[1][1] *= -1;

void* data;
vkMapMemory(logicalDevice, uniformBuffers[bufferIdx].getDeviceMemory(), 0, sizeof(cam), 0, &data);
memcpy(data, &cam, sizeof(cam));
vkUnmapMemory(logicalDevice, uniformBuffers[bufferIdx].getDeviceMemory());
}
17 changes: 17 additions & 0 deletions src/renderer.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <array>
#include <chrono>
#include <cstring>
#include <iostream>
#include <unordered_map>
Expand All @@ -11,6 +12,10 @@
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "buffer.h"
#include "gltfloader.h"
#include "shaderloader.h"
Expand Down Expand Up @@ -95,6 +100,10 @@ class Renderer {

void createDescriptorPool();

void createDescriptorSetLayout();

void createDescriptorSets();

void createGraphicsPipeline();

void createIndexBuffer();
Expand All @@ -117,6 +126,8 @@ class Renderer {

UserInterface::UIContext createUIContext();

void createUniformBuffers();

void createVertexBuffer();

void drawFrame();
Expand All @@ -139,6 +150,8 @@ class Renderer {

void setupDebugMessenger();

void updateUniformBuffer(size_t bufferIdx);

uint32_t windowWidth = 1920;
uint32_t windowHeight = 1080;

Expand All @@ -156,6 +169,8 @@ class Renderer {
VertexBuffer vertexBuffer;
IndexBuffer vertIndexBuffer;

std::vector<UniformBuffer> uniformBuffers;

VkRenderPass renderPass = {};

VkPipeline graphicsPipeline = {};
Expand All @@ -172,6 +187,8 @@ class Renderer {
std::vector<VkFence> imagesInFlight;

VkDescriptorPool descriptorPool = {};
VkDescriptorSetLayout descriptorSetLayout = {};
std::vector<VkDescriptorSet> descriptorSets = {};

Swapchain swapchain;

Expand Down

0 comments on commit 0276356

Please sign in to comment.