Replaced Index and Vertex buffer descriptions using descriptor sets with the VMA Library, massively simplifying the creation of the Vertex and Index buffer, and uses push constants

This commit is contained in:
Lillian Salehi 2024-11-27 15:54:35 -06:00
parent f8bd7fdf3b
commit d5190c8207
36 changed files with 19001 additions and 154 deletions

Binary file not shown.

View File

@ -2,7 +2,6 @@ CPPFLAGS=-std=c++23 -g
CFLAGS = -g
LDFLAGS=-lglfw -Ilib -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi -ltinyobjloader -Ilib/imgui -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES
MAKEFLAGS += -j16
SRC = $(shell find . -name "*.cpp")
CSRC = $(shell find . -name "*.c")
SHDRSRC = $(shell find . -name "*.frag" -o -name "*vert")

View File

@ -0,0 +1,12 @@
# Blender 4.2.3 LTS MTL File: 'None'
# www.blender.org
newmtl Material
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd /home/lillian/Downloads/d41777258e68c9d7046fc03c4d1d1e89.png

View File

@ -0,0 +1,30 @@
# Blender 4.2.3 LTS
# www.blender.org
mtllib untitled.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vn -0.0000 1.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vt 1.000000 -0.000021
vt 1.000057 1.000011
vt -0.000000 1.000005
vt 0.000022 -0.000026
s 0
usemtl Material
f 1/1/1 5/2/1 7/3/1 3/4/1
f 4/2/2 3/3/2 7/4/2 8/1/2
f 8/2/3 7/3/3 5/4/3 6/1/3
f 6/1/4 2/2/4 4/3/4 8/4/4
f 2/2/5 1/3/5 3/4/5 4/1/5
f 6/2/6 5/3/6 1/4/6 2/1/6

BIN
assets/textures/aza.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

View File

@ -3,6 +3,6 @@ Pos=60,60
Size=400,400
[Window][Agnosia Debug]
Pos=194,438
Size=583,225
Pos=522,0
Size=583,202

18676
lib/vk_mem_alloc.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -300,14 +300,19 @@ void DeviceControl::createLogicalDevice() {
queueCreateSingularInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateSingularInfo);
}
VkPhysicalDeviceVulkan12Features features12{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.pNext = nullptr,
.bufferDeviceAddress = true,
};
VkPhysicalDeviceVulkan13Features features13{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
.pNext = nullptr,
.pNext = &features12,
.synchronization2 = true,
.dynamicRendering = true,
};
VkPhysicalDeviceFeatures featuresBase{
.robustBufferAccess = true,
.sampleRateShading = true,
.samplerAnisotropy = true,
};

View File

@ -21,6 +21,7 @@ VkInstance vulkaninstance;
GLFWwindow *window;
const uint32_t WIDTH = 800;
const uint32_t HEIGHT = 600;
// Getters and Setters!
void EntryApp::setFramebufferResized(bool setter) {
framebufferResized = setter;
@ -76,12 +77,8 @@ void createInstance() {
glfwExtensions + glfwExtensionCount);
VkInstanceCreateInfo createInfo{}; // Define parameters of new vulkan instance
createInfo.sType =
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info
// structure
createInfo.pApplicationInfo =
&appInfo; // We just created a new appInfo structure, so we pass the
// pointer to it.
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
@ -101,6 +98,7 @@ void initVulkan() {
DeviceControl::createLogicalDevice();
volkLoadDevice(DeviceControl::getDevice());
DeviceControl::createSwapChain(window);
Buffers::createMemoryAllocator(vulkaninstance);
DeviceControl::createImageViews();
Buffers::createDescriptorSetLayout();
Graphics::createGraphicsPipeline();
@ -110,14 +108,13 @@ void initVulkan() {
Texture::createTextureImage();
Texture::createTextureImageView();
Texture::createTextureSampler();
Model::loadModel();
Buffers::createVertexBuffer();
Buffers::createIndexBuffer();
Model::loadModel(glm::vec3(0.0, 0.0, 0.0));
Buffers::createUniformBuffers();
Buffers::createDescriptorPool();
Buffers::createDescriptorSets();
Graphics::createCommandBuffer();
Render::createSyncObject();
Gui::initImgui(vulkaninstance);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <GLFW/glfw3.h>
class EntryApp {
public:
static EntryApp &getInstance();

View File

@ -1,21 +1,34 @@
#include "../devicelibrary.h"
#include "../types.h"
#include "buffers.h"
#include "texture.h"
#include <chrono>
#include <cstdint>
#include <cstring>
#include <functional>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <stdexcept>
#include <vulkan/vulkan_core.h>
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"
VkBuffer vertexBuffer;
VkDeviceMemory vertexBufferMemory;
VkBuffer indexBuffer;
VkDeviceMemory indexBufferMemory;
std::vector<Buffers::Vertex> vertices;
std::vector<Agnosia_T::Vertex> vertices;
// Index buffer definition, showing which points to reuse.
std::vector<uint32_t> indices;
VmaAllocator _allocator;
Agnosia_T::GPUPushConstants pushConstants;
VkDescriptorPool descriptorPool;
VkDescriptorSetLayout descriptorSetLayout;
std::vector<VkDescriptorSet> descriptorSets;
@ -60,6 +73,40 @@ uint32_t Buffers::findMemoryType(uint32_t typeFilter,
throw std::runtime_error("failed to find suitable memory type!");
}
void immediate_submit(std::function<void(VkCommandBuffer cmd)> &&function) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = commandPool;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer;
vkAllocateCommandBuffers(DeviceControl::getDevice(), &allocInfo,
&commandBuffer);
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(commandBuffer, &beginInfo);
function(commandBuffer);
vkEndCommandBuffer(commandBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(DeviceControl::getGraphicsQueue(), 1, &submitInfo,
VK_NULL_HANDLE);
vkQueueWaitIdle(DeviceControl::getGraphicsQueue());
vkFreeCommandBuffers(DeviceControl::getDevice(), commandPool, 1,
&commandBuffer);
}
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
@ -95,6 +142,101 @@ void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
vkFreeCommandBuffers(DeviceControl::getDevice(), commandPool, 1,
&commandBuffer);
}
void Buffers::createMemoryAllocator(VkInstance vkInstance) {
VmaVulkanFunctions vulkanFuncs{
.vkGetInstanceProcAddr = vkGetInstanceProcAddr,
.vkGetDeviceProcAddr = vkGetDeviceProcAddr,
};
VmaAllocatorCreateInfo allocInfo{
.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT,
.physicalDevice = DeviceControl::getPhysicalDevice(),
.device = DeviceControl::getDevice(),
.pVulkanFunctions = &vulkanFuncs,
.instance = vkInstance,
.vulkanApiVersion = VK_API_VERSION_1_3,
};
vmaCreateAllocator(&allocInfo, &_allocator);
}
Agnosia_T::AllocatedBuffer Buffers::createBuffer(size_t allocSize,
VkBufferUsageFlags usage,
VmaMemoryUsage memUsage) {
// Allocate the buffer we will use for Device Addresses
VkBufferCreateInfo bufferInfo{.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.size = allocSize,
.usage = usage};
VmaAllocationCreateInfo vmaAllocInfo{
.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT, .usage = memUsage};
Agnosia_T::AllocatedBuffer newBuffer;
if (vmaCreateBuffer(_allocator, &bufferInfo, &vmaAllocInfo, &newBuffer.buffer,
&newBuffer.allocation, &newBuffer.info) != VK_SUCCESS) {
throw std::runtime_error("Failed to allocate a buffer using VMA!");
}
return newBuffer;
}
Agnosia_T::GPUMeshBuffers
Buffers::sendMesh(std::span<uint32_t> indices,
std::span<Agnosia_T::Vertex> vertices) {
const size_t vertexBufferSize = vertices.size() * sizeof(Agnosia_T::Vertex);
const size_t indexBufferSize = indices.size() * sizeof(uint32_t);
Agnosia_T::GPUMeshBuffers newSurface;
// Create a Vertex Buffer here, infinitely easier than the old Vulkan method!
newSurface.vertexBuffer = createBuffer(
vertexBufferSize,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
// Find the address of the vertex buffer!
VkBufferDeviceAddressInfo deviceAddressInfo{
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
.buffer = newSurface.vertexBuffer.buffer,
};
newSurface.vertexBufferAddress =
vkGetBufferDeviceAddress(DeviceControl::getDevice(), &deviceAddressInfo);
// Create the index buffer to iterate over and check for duplicate vertices
newSurface.indexBuffer = createBuffer(indexBufferSize,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
Agnosia_T::AllocatedBuffer stagingBuffer =
createBuffer(vertexBufferSize + indexBufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
void *data = stagingBuffer.allocation->GetMappedData();
// Copy the vertex buffer
memcpy(data, vertices.data(), vertexBufferSize);
// Copy the index buffer
memcpy((char *)data + vertexBufferSize, indices.data(), indexBufferSize);
immediate_submit([&](VkCommandBuffer cmd) {
VkBufferCopy vertexCopy{0};
vertexCopy.dstOffset = 0;
vertexCopy.srcOffset = 0;
vertexCopy.size = vertexBufferSize;
vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.vertexBuffer.buffer,
1, &vertexCopy);
VkBufferCopy indexCopy{0};
indexCopy.dstOffset = 0;
indexCopy.srcOffset = vertexBufferSize;
indexCopy.size = indexBufferSize;
vkCmdCopyBuffer(cmd, stagingBuffer.buffer, newSurface.indexBuffer.buffer, 1,
&indexCopy);
});
vmaDestroyBuffer(_allocator, stagingBuffer.buffer, stagingBuffer.allocation);
return newSurface;
}
void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties, VkBuffer &buffer,
@ -128,68 +270,6 @@ void Buffers::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
vkBindBufferMemory(DeviceControl::getDevice(), buffer, bufferMemory, 0);
}
void Buffers::createIndexBuffer() {
VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
stagingBuffer, stagingBufferMemory);
void *data;
vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, bufferSize, 0,
&data);
memcpy(data, indices.data(), (size_t)bufferSize);
vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory);
createBuffer(
bufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
copyBuffer(stagingBuffer, indexBuffer, bufferSize);
vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr);
vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr);
}
void Buffers::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.
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(bufferSize,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
stagingBuffer, stagingBufferMemory);
void *data;
vkMapMemory(DeviceControl::getDevice(), stagingBufferMemory, 0, bufferSize, 0,
&data);
memcpy(data, vertices.data(), (size_t)bufferSize);
vkUnmapMemory(DeviceControl::getDevice(), stagingBufferMemory);
createBuffer(
bufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
vkDestroyBuffer(DeviceControl::getDevice(), stagingBuffer, nullptr);
vkFreeMemory(DeviceControl::getDevice(), stagingBufferMemory, nullptr);
}
void Buffers::destroyBuffers() {
vkDestroyBuffer(DeviceControl::getDevice(), indexBuffer, nullptr);
vkFreeMemory(DeviceControl::getDevice(), indexBufferMemory, nullptr);
@ -373,8 +453,6 @@ void Buffers::createDescriptorSets() {
void Buffers::destroyDescriptorPool() {
vkDestroyDescriptorPool(DeviceControl::getDevice(), descriptorPool, nullptr);
}
VkBuffer &Buffers::getVertexBuffer() { return vertexBuffer; }
VkBuffer &Buffers::getIndexBuffer() { return indexBuffer; }
VkDescriptorPool &Buffers::getDescriptorPool() { return descriptorPool; }
std::vector<VkDescriptorSet> &Buffers::getDescriptorSets() {
return descriptorSets;
@ -397,5 +475,5 @@ VkCommandPool &Buffers::getCommandPool() { return commandPool; }
VkDescriptorSetLayout &Buffers::getDescriptorSetLayout() {
return descriptorSetLayout;
}
std::vector<Buffers::Vertex> &Buffers::getVertices() { return vertices; }
std::vector<Agnosia_T::Vertex> &Buffers::getVertices() { return vertices; }
std::vector<uint32_t> &Buffers::getIndices() { return indices; }

View File

@ -1,68 +1,29 @@
#pragma once
#include <cstdint>
#include <span>
#define VK_NO_PROTOTYPES
#include "../types.h"
#include "volk.h"
#include <vector>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#include <array>
class Buffers {
public:
struct Vertex {
// This defines what a vertex is!
// We control the position, color and texture coordinate here!
glm::vec3 pos;
glm::vec3 color;
glm::vec2 texCoord;
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, 3>
getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_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);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
return attributeDescriptions;
}
bool operator==(const Vertex &other) const {
return pos == other.pos && color == other.color &&
texCoord == other.texCoord;
}
};
static Agnosia_T::AllocatedBuffer createBuffer(size_t allocSize,
VkBufferUsageFlags usage,
VmaMemoryUsage memUsage);
static void createMemoryAllocator(VkInstance vkInstance);
static Agnosia_T::GPUMeshBuffers
sendMesh(std::span<uint32_t> indices, std::span<Agnosia_T::Vertex> vertices);
static void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags props, VkBuffer &buffer,
VkDeviceMemory &bufferMemory);
static uint32_t findMemoryType(uint32_t typeFilter,
VkMemoryPropertyFlags flags);
static void createIndexBuffer();
static void createVertexBuffer();
static void destroyBuffers();
static VkBuffer &getVertexBuffer();
static VkBuffer &getIndexBuffer();
static void createDescriptorSetLayout();
static void createUniformBuffers();
static void updateUniformBuffer(uint32_t currentImage);
@ -85,6 +46,6 @@ public:
static std::vector<VkBuffer> &getUniformBuffers();
static std::vector<VkDeviceMemory> &getUniformBuffersMemory();
static VkCommandPool &getCommandPool();
static std::vector<Vertex> &getVertices();
static std::vector<Agnosia_T::Vertex> &getVertices();
static std::vector<uint32_t> &getIndices();
};

View File

@ -6,6 +6,7 @@
#include "render.h"
#include "texture.h"
#include <fstream>
#include <iostream>
std::vector<VkDynamicState> dynamicStates = {VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR};
@ -83,8 +84,8 @@ void Graphics::createGraphicsPipeline() {
vertexInputInfo.sType =
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
auto bindingDescription = Buffers::Vertex::getBindingDescription();
auto attributeDescriptions = Buffers::Vertex::getAttributeDescriptions();
auto bindingDescription = Agnosia_T::Vertex::getBindingDescription();
auto attributeDescriptions = Agnosia_T::Vertex::getAttributeDescriptions();
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
@ -174,10 +175,18 @@ void Graphics::createGraphicsPipeline() {
dynamicState.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
dynamicState.pDynamicStates = dynamicStates.data();
VkPushConstantRange pushConstant{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(Agnosia_T::GPUPushConstants),
};
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &Buffers::getDescriptorSetLayout();
pipelineLayoutInfo.pPushConstantRanges = &pushConstant;
pipelineLayoutInfo.pushConstantRangeCount = 1;
if (vkCreatePipelineLayout(DeviceControl::getDevice(), &pipelineLayoutInfo,
nullptr, &pipelineLayout) != VK_SUCCESS) {
@ -256,7 +265,6 @@ void Graphics::createCommandBuffer() {
throw std::runtime_error("Failed to allocate command buffers");
}
}
void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
uint32_t imageIndex) {
VkCommandBufferBeginInfo beginInfo{};
@ -344,10 +352,15 @@ void Graphics::recordCommandBuffer(VkCommandBuffer commandBuffer,
scissor.extent = DeviceControl::getSwapChainExtent();
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
VkBuffer vertexBuffers[] = {Buffers::getVertexBuffer()};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdBindIndexBuffer(commandBuffer, Buffers::getIndexBuffer(), 0,
Agnosia_T::GPUMeshBuffers Model =
Buffers::sendMesh(Buffers::getIndices(), Buffers::getVertices());
Agnosia_T::GPUPushConstants pushConsts;
pushConsts.vertexBuffer = Model.vertexBufferAddress;
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof(Agnosia_T::GPUPushConstants), &pushConsts);
vkCmdBindIndexBuffer(commandBuffer, Model.indexBuffer.buffer, 0,
VK_INDEX_TYPE_UINT32);
vkCmdBindDescriptorSets(

View File

@ -9,8 +9,8 @@
#include <glm/gtx/hash.hpp>
namespace std {
template <> struct hash<Buffers::Vertex> {
size_t operator()(Buffers::Vertex const &vertex) const {
template <> struct hash<Agnosia_T::Vertex> {
size_t operator()(Agnosia_T::Vertex const &vertex) const {
return ((hash<glm::vec3>()(vertex.pos) ^
(hash<glm::vec3>()(vertex.color) << 1)) >>
1) ^
@ -21,7 +21,7 @@ template <> struct hash<Buffers::Vertex> {
const std::string MODEL_PATH = "assets/models/viking_room.obj";
void Model::loadModel() {
void Model::loadModel(glm::vec3 position) {
tinyobj::ObjReaderConfig readerConfig;
tinyobj::ObjReader reader;
@ -38,15 +38,15 @@ void Model::loadModel() {
auto &attrib = reader.GetAttrib();
auto &shapes = reader.GetShapes();
auto &materials = reader.GetMaterials();
std::unordered_map<Buffers::Vertex, uint32_t> uniqueVertices{};
std::unordered_map<Agnosia_T::Vertex, uint32_t> uniqueVertices{};
for (const auto &shape : shapes) {
for (const auto &index : shape.mesh.indices) {
Buffers::Vertex vertex{};
Agnosia_T::Vertex vertex{};
vertex.pos = {attrib.vertices[3 * index.vertex_index + 0],
attrib.vertices[3 * index.vertex_index + 1],
attrib.vertices[3 * index.vertex_index + 2]};
vertex.pos = {attrib.vertices[3 * index.vertex_index + 0] + position.x,
attrib.vertices[3 * index.vertex_index + 1] + position.y,
attrib.vertices[3 * index.vertex_index + 2] + position.z};
// TODO: Small fix here, handle if there are no UV's unwrapped for the
// model.

View File

@ -1,6 +1,8 @@
#pragma once
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
class Model {
public:
static void loadModel();
static void loadModel(glm::vec3 position);
};

View File

@ -45,6 +45,7 @@ void recreateSwapChain() {
void Render::drawFrame() {
vkWaitForFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame],
VK_TRUE, UINT64_MAX);
vkResetFences(DeviceControl::getDevice(), 1, &inFlightFences[currentFrame]);
uint32_t imageIndex;

View File

@ -1,4 +1,5 @@
#include "entrypoint.h"
#include <iostream>
#define VOLK_IMPLEMENTATION

View File

@ -1,4 +1,5 @@
#version 450
#extension GL_EXT_buffer_reference : require
layout(binding = 0) uniform UniformBufferObject {
float time;
@ -6,20 +7,26 @@ layout(binding = 0) uniform UniformBufferObject {
mat4 view;
mat4 proj;
} ubo;
struct Vertex {
// 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)
vec3 pos;
vec3 color;
vec2 texCoord;
};
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(buffer_reference, std430) readonly buffer VertexBuffer{
Vertex vertices[];
};
layout( push_constant ) uniform constants {
VertexBuffer vertBuffer;
}PushConstants;
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
void main() {
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragColor = inColor;
fragTexCoord = inTexCoord;
Vertex v = PushConstants.vertBuffer.vertices[gl_VertexIndex];
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(v.pos, 1.0f);
fragColor = v.color.xyz;
fragTexCoord = v.texCoord;
}

64
src/types.h Normal file
View File

@ -0,0 +1,64 @@
#pragma once
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include "vk_mem_alloc.h"
#include <array>
#include <glm/glm.hpp>
class Agnosia_T {
public:
struct Vertex {
// This defines what a vertex is!
// We control the position, color and texture coordinate here!
alignas(16) glm::vec3 pos;
alignas(16) glm::vec3 color;
alignas(8) glm::vec2 texCoord;
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, 3>
getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_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);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
return attributeDescriptions;
}
bool operator==(const Vertex &other) const {
return pos == other.pos && color == other.color &&
texCoord == other.texCoord;
}
};
struct AllocatedBuffer {
VkBuffer buffer;
VmaAllocation allocation;
VmaAllocationInfo info;
};
struct GPUMeshBuffers {
AllocatedBuffer indexBuffer;
AllocatedBuffer vertexBuffer;
VkDeviceAddress vertexBufferAddress;
};
struct GPUPushConstants {
VkDeviceAddress vertexBuffer;
};
};