Set up Vertex Buffer

This commit is contained in:
Lillian Salehi 2024-10-09 06:14:01 -05:00
parent 0fefb85d0a
commit 7e625a3db5
10 changed files with 146 additions and 27 deletions

View File

@ -6,7 +6,7 @@ SRC = $(shell find . -name "*.cpp")
SHDRSRC = $(shell find . -name "*.frag" -o -name "*vert") SHDRSRC = $(shell find . -name "*.frag" -o -name "*vert")
SPV = $(SHDRSRC:%.vert=%.spv) $(SHDRSRC:%.frag=%.spv) SPV = $(SHDRSRC:%.vert=%.spv) $(SHDRSRC:%.frag=%.spv)
OBJ = $(SRC:%.cpp=%.o) OBJ = $(SRC:%.cpp=%.o)
MAKEFLAGS += -j16
BIN=build/agnosiaengine BIN=build/agnosiaengine
.PHONY: all .PHONY: all

View File

@ -264,7 +264,7 @@ namespace DeviceControl {
// Do NOT blend with other windows on the system. // Do NOT blend with other windows on the system.
createSwapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; createSwapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createSwapChainInfo.presentMode = presentMode; createSwapChainInfo.presentMode = presentMode;
// This is interesting, clip pixels that are obscured for performance, but that means you wont be able to reaf them reliably.. // This is interesting, clip pixels that are obscured for performance, but that means you wont be able to read them reliably..
// I am curious if this would affect screen-space rendering techniques, may be something to note. // I am curious if this would affect screen-space rendering techniques, may be something to note.
createSwapChainInfo.clipped = VK_TRUE; createSwapChainInfo.clipped = VK_TRUE;
// This is something that needs to be implemented later, operations like resizing the window invalidate the swap chain and // This is something that needs to be implemented later, operations like resizing the window invalidate the swap chain and

View File

@ -1,8 +1,10 @@
#include "entrypoint.h" #include "entrypoint.h"
#include "graphics/buffers.h"
DeviceControl::devicelibrary deviceLibs; DeviceControl::devicelibrary deviceLibs;
Debug::vulkandebuglibs debugController; Debug::vulkandebuglibs debugController;
Graphics::graphicspipeline graphicsPipeline; Graphics::graphicspipeline graphicsPipeline;
RenderPresent::render renderPresentation; RenderPresent::render renderPresentation;
Buffers::bufferslibrary buffers;
VkInstance vulkaninstance; VkInstance vulkaninstance;
// Getters and Setters! // Getters and Setters!
@ -40,7 +42,7 @@ void createInstance() {
appInfo.applicationVersion = VK_MAKE_VERSION(1,0,0); // Create a Major Minor Patch version number for the application! appInfo.applicationVersion = VK_MAKE_VERSION(1,0,0); // Create a Major Minor Patch version number for the application!
appInfo.pEngineName = "Agnosia Engine"; // Give an internal name for the engine running appInfo.pEngineName = "Agnosia Engine"; // Give an internal name for the engine running
appInfo.engineVersion = VK_MAKE_VERSION(1,0,0); // Similar to the App version, give vulkan an *engine* version appInfo.engineVersion = VK_MAKE_VERSION(1,0,0); // Similar to the App version, give vulkan an *engine* version
appInfo.apiVersion = VK_API_VERSION_1_1; // Tell vulkan what the highest API version we will allow this program to run on appInfo.apiVersion = VK_API_VERSION_1_3; // Tell vulkan what the highest API version we will allow this program to run on
VkInstanceCreateInfo createInfo{}; // Define parameters of new vulkan instance VkInstanceCreateInfo createInfo{}; // Define parameters of new vulkan instance
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info structure createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info structure
@ -52,7 +54,7 @@ void createInstance() {
void initVulkan() { void initVulkan() {
createInstance(); createInstance();
debugController.setupDebugMessenger(vulkaninstance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DNDEBUG flag (as per the makefile) debugController.setupDebugMessenger(vulkaninstance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DDEBUG flag (as per the makefile)
deviceLibs.createSurface(vulkaninstance, Global::window); deviceLibs.createSurface(vulkaninstance, Global::window);
deviceLibs.pickPhysicalDevice(vulkaninstance); deviceLibs.pickPhysicalDevice(vulkaninstance);
deviceLibs.createLogicalDevice(); deviceLibs.createLogicalDevice();
@ -62,6 +64,7 @@ void initVulkan() {
graphicsPipeline.createGraphicsPipeline(); graphicsPipeline.createGraphicsPipeline();
graphicsPipeline.createFramebuffers(); graphicsPipeline.createFramebuffers();
graphicsPipeline.createCommandPool(); graphicsPipeline.createCommandPool();
buffers.createVertexBuffer();
graphicsPipeline.createCommandBuffer(); graphicsPipeline.createCommandBuffer();
renderPresentation.createSyncObject(); renderPresentation.createSyncObject();
} }
@ -76,6 +79,7 @@ void mainLoop() { // This loop jus
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library! void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
renderPresentation.cleanupSwapChain(); renderPresentation.cleanupSwapChain();
buffers.destroyVertexBuffer();
graphicsPipeline.destroyGraphicsPipeline(); graphicsPipeline.destroyGraphicsPipeline();
graphicsPipeline.destroyRenderPass(); graphicsPipeline.destroyRenderPass();
renderPresentation.destroyFenceSemaphores(); renderPresentation.destroyFenceSemaphores();

View File

@ -21,6 +21,7 @@ namespace Global {
VkQueue graphicsQueue; VkQueue graphicsQueue;
VkQueue presentQueue; VkQueue presentQueue;
GLFWwindow* window; GLFWwindow* window;
Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { 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. // 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.

View File

@ -1,10 +1,13 @@
#pragma once #pragma once
#include <glm/ext/vector_float2.hpp>
#include <glm/ext/vector_float3.hpp>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <optional> #include <optional>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "debug/vulkandebuglibs.h" #include "debug/vulkandebuglibs.h"
#include <array>
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -21,6 +24,34 @@ namespace Global {
const int MAX_FRAMES_IN_FLIGHT = 2; const int MAX_FRAMES_IN_FLIGHT = 2;
extern GLFWwindow* window; extern GLFWwindow* window;
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 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;
}
};
const uint32_t WIDTH = 800; const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600; const uint32_t HEIGHT = 600;

71
src/graphics/buffers.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "buffers.h"
#include <iostream>
#include <vulkan/vulkan_core.h>
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
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}},
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}
};
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
// Graphics cards offer different types of memory to allocate from, here we query to find the right type of memory for our needs.
// Query the available types of memory to iterate over.
VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(Global::physicalDevice, &memProperties);
// iterate over and see if any of the memory types match our needs, in this case, HOST_VISIBLE and HOST_COHERENT. These will be explained shortly.
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
return i;
}
}
throw std::runtime_error("failed to find suitable memory type!");
}
void bufferslibrary::createVertexBuffer() {
// Create a Vertex Buffer to hold the vertex information in memory so it doesn't have to be hardcoded!
// Size denotes the size of the buffer in bytes, usage in this case is the buffer behaviour, using a bitwise OR.
// Sharing mode denostes the same as the images in the swap chain! in this case, only the graphics queue uses this buffer, so we make it exclusive.
VkBufferCreateInfo bufferInfo;
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(vertices[0]) * vertices.size();
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferInfo.pNext = NULL;
std::cerr << &bufferInfo << " " << &vertexBuffer << "\n";
if (vkCreateBuffer(Global::device, &bufferInfo, nullptr, &vertexBuffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create vertex buffer!");
}
// Query the memory requirements of the buffer.
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(Global::device, vertexBuffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &vertexBufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate vertex buffer memory!");
}
vkBindBufferMemory(Global::device, vertexBuffer, vertexBufferMemory, 0);
void* data;
vkMapMemory(Global::device, vertexBufferMemory, 0, bufferInfo.size, 0, &data);
memcpy(data, vertices.data(), (size_t) bufferInfo.size);
vkUnmapMemory(Global::device, vertexBufferMemory);
}
void bufferslibrary::destroyVertexBuffer() {
vkDestroyBuffer(Global::device, vertexBuffer, nullptr);
vkFreeMemory(Global::device, vertexBufferMemory, nullptr);
}
VkBuffer bufferslibrary::getVertexBuffer() {
return vertexBuffer;
}
std::vector<Global::Vertex> bufferslibrary::getVertices() {
return vertices;
}
}

12
src/graphics/buffers.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include "../global.h"
namespace Buffers {
class bufferslibrary {
public:
void createVertexBuffer();
void destroyVertexBuffer();
VkBuffer getVertexBuffer();
std::vector<Global::Vertex> getVertices();
};
}

View File

@ -1,5 +1,7 @@
#include "graphicspipeline.h" #include "graphicspipeline.h"
#include "buffers.h"
#include <vector>
namespace Graphics { namespace Graphics {
std::vector<VkDynamicState> dynamicStates = { std::vector<VkDynamicState> dynamicStates = {
VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_VIEWPORT,
@ -11,6 +13,7 @@ namespace Graphics {
VkPipelineLayout pipelineLayout; VkPipelineLayout pipelineLayout;
VkPipeline graphicsPipeline; VkPipeline graphicsPipeline;
DeviceControl::devicelibrary deviceLibs; DeviceControl::devicelibrary deviceLibs;
Buffers::bufferslibrary buffers;
std::vector<VkFramebuffer> swapChainFramebuffers; std::vector<VkFramebuffer> swapChainFramebuffers;
@ -75,10 +78,14 @@ namespace Graphics {
vertShaderStageInfo.pName = "main"; vertShaderStageInfo.pName = "main";
VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; VkPipelineVertexInputStateCreateInfo vertexInputInfo{};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 0;
vertexInputInfo.pVertexBindingDescriptions = nullptr; auto bindingDescription = Global::Vertex::getBindingDescription();
vertexInputInfo.vertexAttributeDescriptionCount = 0; auto attributeDescriptions = Global::Vertex::getAttributeDescriptions();
vertexInputInfo.pVertexAttributeDescriptions = nullptr;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
// ------------------- STAGE 5 - RASTERIZATION ----------------- // // ------------------- STAGE 5 - RASTERIZATION ----------------- //
// Take Vertex shader vertices and fragmentize them for the frament shader. The rasterizer also can perform depth testing, face culling, and scissor testing. // Take Vertex shader vertices and fragmentize them for the frament shader. The rasterizer also can perform depth testing, face culling, and scissor testing.
@ -265,8 +272,6 @@ namespace Graphics {
void graphicspipeline::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { void graphicspipeline::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0; // Optional
beginInfo.pInheritanceInfo = nullptr; // Optional
if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) { if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
throw std::runtime_error("failed to begin recording command buffer!"); throw std::runtime_error("failed to begin recording command buffer!");
@ -286,7 +291,6 @@ namespace Graphics {
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
VkViewport viewport{}; VkViewport viewport{};
viewport.x = 0.0f; viewport.x = 0.0f;
viewport.y = 0.0f; viewport.y = 0.0f;
@ -299,10 +303,13 @@ namespace Graphics {
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = {0, 0}; scissor.offset = {0, 0};
scissor.extent = deviceLibs.getSwapChainExtent(); scissor.extent = deviceLibs.getSwapChainExtent();
vkCmdSetScissor(commandBuffer, 0, 1, &scissor); vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdDraw(commandBuffer, 3, 1, 0, 0); VkBuffer vertexBuffers[] = {buffers.getVertexBuffer()};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdDraw(commandBuffer, static_cast<uint32_t>(buffers.getVertices().size()), 1, 0, 0);
vkCmdEndRenderPass(commandBuffer); vkCmdEndRenderPass(commandBuffer);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../global.h" #include "../global.h"
#include "../devicelibrary.h" #include "../devicelibrary.h"
#include "buffers.h"
#include <fstream> #include <fstream>
namespace Graphics { namespace Graphics {
class graphicspipeline { class graphicspipeline {

View File

@ -1,20 +1,12 @@
#version 450 #version 450
// 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;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor; layout(location = 0) out vec3 fragColor;
vec2 positions[3] = vec2[](
vec2(0.0, -0.5),
vec2(0.5, 0.5),
vec2(-0.5, 0.5)
);
vec3 colors[3] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 0.0, 1.0)
);
void main() { void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); gl_Position = vec4(inPosition, 0.0, 1.0);
fragColor = colors[gl_VertexIndex]; fragColor = inColor;
} }