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:
parent
f8bd7fdf3b
commit
d5190c8207
BIN
.cache/clangd/index/agnosiaimgui.cpp.D917B7EB41E8A56F.idx
Normal file
BIN
.cache/clangd/index/agnosiaimgui.cpp.D917B7EB41E8A56F.idx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.cache/clangd/index/types.h.2A872A9A515562E6.idx
Normal file
BIN
.cache/clangd/index/types.h.2A872A9A515562E6.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/vk_mem_alloc.h.F667345C57A24872.idx
Normal file
BIN
.cache/clangd/index/vk_mem_alloc.h.F667345C57A24872.idx
Normal file
Binary file not shown.
1
Makefile
1
Makefile
@ -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")
|
||||
|
12
assets/models/untitled.mtl
Normal file
12
assets/models/untitled.mtl
Normal 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
|
30
assets/models/untitled.obj
Normal file
30
assets/models/untitled.obj
Normal 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
BIN
assets/textures/aza.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 578 KiB |
@ -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
18676
lib/vk_mem_alloc.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
class EntryApp {
|
||||
public:
|
||||
static EntryApp &getInstance();
|
||||
|
@ -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; }
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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(
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "entrypoint.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define VOLK_IMPLEMENTATION
|
||||
|
@ -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
64
src/types.h
Normal 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;
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user