Uniform buffer creation, set up rudimentary MVP matrix
This commit is contained in:
parent
6b8b24da65
commit
086adae47a
@ -1,5 +1,5 @@
|
||||
#include "entrypoint.h"
|
||||
#include "graphics/buffers.h"
|
||||
#include "global.h"
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
Debug::vulkandebuglibs debugController;
|
||||
Graphics::graphicspipeline graphicsPipeline;
|
||||
@ -59,11 +59,15 @@ void initVulkan() {
|
||||
deviceLibs.createSwapChain(Global::window);
|
||||
deviceLibs.createImageViews();
|
||||
graphicsPipeline.createRenderPass();
|
||||
buffers.createDescriptorSetLayout();
|
||||
graphicsPipeline.createGraphicsPipeline();
|
||||
graphicsPipeline.createFramebuffers();
|
||||
graphicsPipeline.createCommandPool();
|
||||
buffers.createVertexBuffer();
|
||||
buffers.createIndexBuffer();
|
||||
buffers.createUniformBuffers();
|
||||
buffers.createDescriptorPool();
|
||||
buffers.createDescriptorSets();
|
||||
graphicsPipeline.createCommandBuffer();
|
||||
renderPresentation.createSyncObject();
|
||||
}
|
||||
@ -78,6 +82,9 @@ void mainLoop() { // This loop jus
|
||||
|
||||
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
|
||||
renderPresentation.cleanupSwapChain();
|
||||
buffers.destroyUniformBuffer();
|
||||
buffers.destroyDescriptorPool();
|
||||
vkDestroyDescriptorSetLayout(Global::device, Global::descriptorSetLayout, nullptr);
|
||||
graphicsPipeline.destroyGraphicsPipeline();
|
||||
graphicsPipeline.destroyRenderPass();
|
||||
|
||||
|
@ -21,7 +21,9 @@ namespace Global {
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
GLFWwindow* window;
|
||||
|
||||
VkDescriptorSetLayout descriptorSetLayout;
|
||||
std::vector<VkDescriptorSet> descriptorSets;
|
||||
uint32_t currentFrame = 0;
|
||||
|
||||
Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
|
||||
// First we feed in a integer we want to use to hold the number of queued items, that fills it, then we create that amount of default constructed *VkQueueFamilyProperties* structs.
|
||||
|
10
src/global.h
10
src/global.h
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <glm/detail/qualifier.hpp>
|
||||
#include <glm/ext/vector_float2.hpp>
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
@ -7,6 +8,7 @@
|
||||
#include <optional>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include "debug/vulkandebuglibs.h"
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <array>
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
@ -24,7 +26,15 @@ namespace Global {
|
||||
extern VkQueue presentQueue;
|
||||
const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||
extern GLFWwindow* window;
|
||||
extern VkDescriptorSetLayout descriptorSetLayout;
|
||||
extern uint32_t currentFrame;
|
||||
extern std::vector<VkDescriptorSet> descriptorSets;
|
||||
|
||||
struct UniformBufferObject {
|
||||
glm::mat4 model;
|
||||
glm::mat4 view;
|
||||
glm::mat4 proj;
|
||||
};
|
||||
struct Vertex {
|
||||
glm::vec2 pos;
|
||||
glm::vec3 color;
|
||||
|
@ -1,14 +1,24 @@
|
||||
#include "buffers.h"
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include "../devicelibrary.h"
|
||||
|
||||
VkBuffer vertexBuffer;
|
||||
VkDeviceMemory vertexBufferMemory;
|
||||
VkBuffer indexBuffer;
|
||||
VkDeviceMemory indexBufferMemory;
|
||||
VkDescriptorPool descriptorPool;
|
||||
DeviceControl::devicelibrary deviceLibrary;
|
||||
|
||||
std::vector<VkBuffer> uniformBuffers;
|
||||
std::vector<VkDeviceMemory> uniformBuffersMemory;
|
||||
std::vector<void*> uniformBuffersMapped;
|
||||
|
||||
|
||||
namespace Buffers {
|
||||
|
||||
|
||||
const std::vector<Global::Vertex> vertices = {
|
||||
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
||||
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
|
||||
@ -155,4 +165,119 @@ namespace Buffers {
|
||||
std::vector<uint16_t> bufferslibrary::getIndices() {
|
||||
return indices;
|
||||
}
|
||||
|
||||
void bufferslibrary::createDescriptorSetLayout() {
|
||||
// Create a table of pointers to data, a Descriptor Set!
|
||||
VkDescriptorSetLayoutBinding uboLayoutBinding{};
|
||||
uboLayoutBinding.binding = 0;
|
||||
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
// Model-View-Projection matrix is in a single uniform buffer, so just 1 descriptor.
|
||||
uboLayoutBinding.descriptorCount = 1;
|
||||
// We are only using this buffer in the vertex shader, so set the flags thus.
|
||||
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
// Immutable Samplers is relevant for image sampling.
|
||||
uboLayoutBinding.pImmutableSamplers = nullptr;
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo layoutInfo{};
|
||||
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
layoutInfo.bindingCount = 1;
|
||||
layoutInfo.pBindings = &uboLayoutBinding;
|
||||
|
||||
if(vkCreateDescriptorSetLayout(Global::device, &layoutInfo, nullptr, &Global::descriptorSetLayout) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create descriptor set layout!");
|
||||
}
|
||||
}
|
||||
//void createMVPDescriptor() {
|
||||
|
||||
//}
|
||||
void bufferslibrary::createUniformBuffers() {
|
||||
VkDeviceSize bufferSize = sizeof(Global::UniformBufferObject);
|
||||
|
||||
uniformBuffers.resize(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
uniformBuffersMemory.resize(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
uniformBuffersMapped.resize(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
for(size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; 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]);
|
||||
vkMapMemory(Global::device, uniformBuffersMemory[i], 0, bufferSize, 0, &uniformBuffersMapped[i]);
|
||||
}
|
||||
}
|
||||
void bufferslibrary::updateUniformBuffer(uint32_t currentImage) {
|
||||
static auto startTime = std::chrono::high_resolution_clock::now();
|
||||
// Calculate the time in seconds since rendering has began to floating point precision.
|
||||
auto currentTime = std::chrono::high_resolution_clock::now();
|
||||
float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
|
||||
|
||||
Global::UniformBufferObject ubo{};
|
||||
// Modify the model projection transformation to rotate around the Z over time.
|
||||
ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
// Modify the view transformation to look at the object from above at a 45 degree angle.
|
||||
// This takes the eye position, center position, and the up direction.
|
||||
ubo.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));
|
||||
// 45 degree field of view, set aspect ratio, and near and far clipping range.
|
||||
ubo.proj = glm::perspective(glm::radians(45.0f), deviceLibrary.getSwapChainExtent().width / (float) deviceLibrary.getSwapChainExtent().height, 0.1f, 10.0f);
|
||||
|
||||
// GLM was created for OpenGL, where the Y coordinate was inverted. This simply flips the sign.
|
||||
ubo.proj[1][1] *= -1;
|
||||
|
||||
memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo));
|
||||
}
|
||||
void bufferslibrary::destroyUniformBuffer() {
|
||||
for(size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
vkDestroyBuffer(Global::device, uniformBuffers[i],nullptr);
|
||||
vkFreeMemory(Global::device, uniformBuffersMemory[i], nullptr);
|
||||
}
|
||||
}
|
||||
void bufferslibrary::createDescriptorPool() {
|
||||
VkDescriptorPoolSize poolSize{};
|
||||
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
poolSize.descriptorCount = static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
VkDescriptorPoolCreateInfo poolInfo{};
|
||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
poolInfo.poolSizeCount = 1;
|
||||
poolInfo.pPoolSizes = &poolSize;
|
||||
poolInfo.maxSets = static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
|
||||
if (vkCreateDescriptorPool(Global::device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to create descriptor pool!");
|
||||
}
|
||||
}
|
||||
void bufferslibrary::createDescriptorSets() {
|
||||
std::vector<VkDescriptorSetLayout> layouts(Global::MAX_FRAMES_IN_FLIGHT, Global::descriptorSetLayout);
|
||||
VkDescriptorSetAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
allocInfo.descriptorPool = descriptorPool;
|
||||
allocInfo.descriptorSetCount = static_cast<uint32_t>(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
allocInfo.pSetLayouts = layouts.data();
|
||||
|
||||
Global::descriptorSets.resize(Global::MAX_FRAMES_IN_FLIGHT);
|
||||
if (vkAllocateDescriptorSets(Global::device, &allocInfo, Global::descriptorSets.data()) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to allocate descriptor sets!");
|
||||
}
|
||||
for(size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
VkDescriptorBufferInfo bufferInfo{};
|
||||
bufferInfo.buffer = uniformBuffers[i];
|
||||
bufferInfo.offset = 0;
|
||||
bufferInfo.range = sizeof(Global::UniformBufferObject);
|
||||
|
||||
VkWriteDescriptorSet descriptorWrite{};
|
||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptorWrite.dstSet = Global::descriptorSets[i];
|
||||
descriptorWrite.dstBinding = 0;
|
||||
descriptorWrite.dstArrayElement = 0;
|
||||
|
||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
descriptorWrite.descriptorCount = 1;
|
||||
|
||||
descriptorWrite.pBufferInfo = &bufferInfo;
|
||||
descriptorWrite.pImageInfo = nullptr; // Optional
|
||||
descriptorWrite.pTexelBufferView = nullptr; // Optional
|
||||
|
||||
vkUpdateDescriptorSets(Global::device, 1, &descriptorWrite, 0, nullptr);
|
||||
}
|
||||
}
|
||||
void bufferslibrary::destroyDescriptorPool() {
|
||||
vkDestroyDescriptorPool(Global::device, descriptorPool, nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "../global.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace Buffers {
|
||||
class bufferslibrary {
|
||||
@ -11,5 +12,12 @@ namespace Buffers {
|
||||
VkBuffer getIndexBuffer();
|
||||
std::vector<Global::Vertex> getVertices();
|
||||
std::vector<uint16_t> getIndices();
|
||||
void createDescriptorSetLayout();
|
||||
void createUniformBuffers();
|
||||
void updateUniformBuffer(uint32_t currentImage);
|
||||
void destroyUniformBuffer();
|
||||
void createDescriptorPool();
|
||||
void createDescriptorSets();
|
||||
void destroyDescriptorPool();
|
||||
};
|
||||
}
|
||||
|
@ -96,11 +96,11 @@ namespace Graphics {
|
||||
rasterizer.depthClampEnable = VK_FALSE;
|
||||
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||
// MODE_FILL, fill polygons, MODE_LINE, draw wireframe, MODE_POINT, draw vertices. Anything other than fill requires GPU feature *fillModeNonSolid*
|
||||
rasterizer.polygonMode = VK_POLYGON_MODE_LINE;
|
||||
rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
rasterizer.lineWidth = 2.0f;
|
||||
// How to cull the faces, right here we cull the back faces and tell the rasterizer front facing vertices are ordered clockwise.
|
||||
rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
// Whether or not to add depth values. e.x. for shadow maps.
|
||||
rasterizer.depthBiasEnable = VK_FALSE;
|
||||
|
||||
@ -147,8 +147,8 @@ namespace Graphics {
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayoutInfo.setLayoutCount = 0;
|
||||
pipelineLayoutInfo.pushConstantRangeCount = 0;
|
||||
pipelineLayoutInfo.setLayoutCount = 1;
|
||||
pipelineLayoutInfo.pSetLayouts = &Global::descriptorSetLayout;
|
||||
|
||||
if (vkCreatePipelineLayout(Global::device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to create pipeline layout!");
|
||||
@ -309,6 +309,8 @@ namespace Graphics {
|
||||
VkDeviceSize offsets[] = {0};
|
||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||
vkCmdBindIndexBuffer(commandBuffer, buffers.getIndexBuffer(), 0, VK_INDEX_TYPE_UINT16);
|
||||
|
||||
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &Global::descriptorSets[Global::currentFrame], 0, nullptr);
|
||||
|
||||
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(buffers.getIndices().size()), 1, 0, 0, 0);
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
@ -9,7 +9,7 @@ namespace RenderPresent {
|
||||
std::vector<VkFence> inFlightFences;
|
||||
Graphics::graphicspipeline pipeline;
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
uint32_t currentFrame = 0;
|
||||
Buffers::bufferslibrary buffers;
|
||||
|
||||
void recreateSwapChain() {
|
||||
int width = 0, height = 0;
|
||||
@ -38,39 +38,42 @@ namespace RenderPresent {
|
||||
// submit the recorded command buffer and present the image!
|
||||
void render::drawFrame() {
|
||||
|
||||
vkWaitForFences(Global::device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(Global::device, 1, &inFlightFences[currentFrame]);
|
||||
vkWaitForFences(Global::device, 1, &inFlightFences[Global::currentFrame], VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]);
|
||||
|
||||
uint32_t imageIndex;
|
||||
VkResult result = vkAcquireNextImageKHR(Global::device, Global::swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||
VkResult result = vkAcquireNextImageKHR(Global::device, Global::swapChain, UINT64_MAX, imageAvailableSemaphores[Global::currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
recreateSwapChain();
|
||||
return;
|
||||
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||
throw std::runtime_error("failed to acquire swap chain image!");
|
||||
}
|
||||
vkResetFences(Global::device, 1, &inFlightFences[currentFrame]);
|
||||
|
||||
vkResetCommandBuffer(Global::commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||
pipeline.recordCommandBuffer(Global::commandBuffers[currentFrame], imageIndex);
|
||||
buffers.updateUniformBuffer(Global::currentFrame);
|
||||
|
||||
vkResetFences(Global::device, 1, &inFlightFences[Global::currentFrame]);
|
||||
|
||||
vkResetCommandBuffer(Global::commandBuffers[Global::currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||
pipeline.recordCommandBuffer(Global::commandBuffers[Global::currentFrame], imageIndex);
|
||||
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
|
||||
VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[Global::currentFrame]};
|
||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||
submitInfo.pWaitDstStageMask = waitStages;
|
||||
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &Global::commandBuffers[currentFrame];
|
||||
submitInfo.pCommandBuffers = &Global::commandBuffers[Global::currentFrame];
|
||||
|
||||
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
|
||||
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[Global::currentFrame]};
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||
|
||||
if (vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
|
||||
if (vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, inFlightFences[Global::currentFrame]) != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to submit draw command buffer!");
|
||||
}
|
||||
|
||||
@ -93,7 +96,7 @@ namespace RenderPresent {
|
||||
} else if (result != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to present swap chain image!");
|
||||
}
|
||||
currentFrame = (currentFrame + 1) % Global::MAX_FRAMES_IN_FLIGHT;
|
||||
Global::currentFrame = (Global::currentFrame + 1) % Global::MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
#pragma info
|
||||
// SEMAPHORES
|
||||
|
@ -1,4 +1,10 @@
|
||||
#version 450
|
||||
|
||||
layout(binding = 0) uniform UniformBufferObject {
|
||||
mat4 model;
|
||||
mat4 view;
|
||||
mat4 proj;
|
||||
} ubo;
|
||||
// inPosition and inColor are vertex attributes, per-vertex properties defined in the vertex buffer!
|
||||
// Layout assigns indices to access these inputs, dvec3 takes 2 slots so we must index it at 2. https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
@ -7,6 +13,7 @@ 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user