Index buffer support to allow for reusing of the same vertices. Next commits will be refactors and documentation, graphs and flows of execution
This commit is contained in:
parent
7e625a3db5
commit
edfbddea55
@ -269,7 +269,7 @@ namespace DeviceControl {
|
|||||||
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
|
||||||
// require you to recreate it and reference the old one specified here, will revisit in a few days.
|
// require you to recreate it and reference the old one specified here, will revisit in a few days.
|
||||||
createSwapChainInfo.oldSwapchain = VK_NULL_HANDLE;
|
//createSwapChainInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if(vkCreateSwapchainKHR(Global::device, &createSwapChainInfo, nullptr, &Global::swapChain) != VK_SUCCESS) {
|
if(vkCreateSwapchainKHR(Global::device, &createSwapChainInfo, nullptr, &Global::swapChain) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("Failed to create the swap chain!!");
|
throw std::runtime_error("Failed to create the swap chain!!");
|
||||||
|
@ -16,15 +16,13 @@ bool EntryApp::getFramebufferResized() const {
|
|||||||
}
|
}
|
||||||
static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
|
static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
|
||||||
auto app = reinterpret_cast<EntryApp*>(glfwGetWindowUserPointer(window));
|
auto app = reinterpret_cast<EntryApp*>(glfwGetWindowUserPointer(window));
|
||||||
app->EntryApp::getInstance().setFramebufferResized(true);
|
app->setFramebufferResized(true);
|
||||||
}
|
}
|
||||||
// Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for
|
// Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for
|
||||||
// now, and create window.
|
// now, and create window.
|
||||||
void initWindow() {
|
void initWindow() {
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
|
||||||
|
|
||||||
// Settings for the window are set, create window reference.
|
// Settings for the window are set, create window reference.
|
||||||
Global::window = glfwCreateWindow(Global::WIDTH, Global::HEIGHT, "Vulkan", nullptr, nullptr);
|
Global::window = glfwCreateWindow(Global::WIDTH, Global::HEIGHT, "Vulkan", nullptr, nullptr);
|
||||||
glfwSetWindowUserPointer(Global::window, &EntryApp::getInstance());
|
glfwSetWindowUserPointer(Global::window, &EntryApp::getInstance());
|
||||||
@ -65,6 +63,7 @@ void initVulkan() {
|
|||||||
graphicsPipeline.createFramebuffers();
|
graphicsPipeline.createFramebuffers();
|
||||||
graphicsPipeline.createCommandPool();
|
graphicsPipeline.createCommandPool();
|
||||||
buffers.createVertexBuffer();
|
buffers.createVertexBuffer();
|
||||||
|
buffers.createIndexBuffer();
|
||||||
graphicsPipeline.createCommandBuffer();
|
graphicsPipeline.createCommandBuffer();
|
||||||
renderPresentation.createSyncObject();
|
renderPresentation.createSyncObject();
|
||||||
}
|
}
|
||||||
@ -79,9 +78,10 @@ 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();
|
||||||
|
|
||||||
|
buffers.destroyBuffers();
|
||||||
renderPresentation.destroyFenceSemaphores();
|
renderPresentation.destroyFenceSemaphores();
|
||||||
graphicsPipeline.destroyCommandPool();
|
graphicsPipeline.destroyCommandPool();
|
||||||
|
|
||||||
|
@ -1,16 +1,26 @@
|
|||||||
#include "buffers.h"
|
#include "buffers.h"
|
||||||
#include <iostream>
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
VkBuffer vertexBuffer;
|
VkBuffer vertexBuffer;
|
||||||
VkDeviceMemory vertexBufferMemory;
|
VkDeviceMemory vertexBufferMemory;
|
||||||
|
VkBuffer indexBuffer;
|
||||||
|
VkDeviceMemory indexBufferMemory;
|
||||||
|
|
||||||
namespace Buffers {
|
namespace Buffers {
|
||||||
|
|
||||||
const std::vector<Global::Vertex> vertices = {
|
const std::vector<Global::Vertex> vertices = {
|
||||||
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
|
{{-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, 1.0f, 0.0f}},
|
||||||
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}
|
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
|
||||||
|
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}}
|
||||||
|
};
|
||||||
|
// Index buffer definition, showing which points to reuse.
|
||||||
|
const std::vector<uint16_t> indices = {
|
||||||
|
0, 1, 2, 2, 3, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
|
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.
|
// 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.
|
// Query the available types of memory to iterate over.
|
||||||
@ -25,47 +35,125 @@ namespace Buffers {
|
|||||||
throw std::runtime_error("failed to find suitable memory type!");
|
throw std::runtime_error("failed to find suitable memory type!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
|
||||||
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
|
allocInfo.commandPool = Global::commandPool;
|
||||||
|
allocInfo.commandBufferCount = 1;
|
||||||
|
|
||||||
|
VkCommandBuffer commandBuffer;
|
||||||
|
vkAllocateCommandBuffers(Global::device, &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);
|
||||||
|
|
||||||
|
VkBufferCopy copyRegion{};
|
||||||
|
copyRegion.size = size;
|
||||||
|
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
|
||||||
|
|
||||||
|
vkEndCommandBuffer(commandBuffer);
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo{};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &commandBuffer;
|
||||||
|
|
||||||
|
vkQueueSubmit(Global::graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
|
vkQueueWaitIdle(Global::graphicsQueue);
|
||||||
|
|
||||||
|
vkFreeCommandBuffers(Global::device, Global::commandPool, 1, &commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
|
||||||
|
VkBufferCreateInfo bufferInfo{};
|
||||||
|
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
bufferInfo.size = size;
|
||||||
|
bufferInfo.usage = usage;
|
||||||
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
|
if (vkCreateBuffer(Global::device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to create buffer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryRequirements memRequirements;
|
||||||
|
vkGetBufferMemoryRequirements(Global::device, buffer, &memRequirements);
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo allocInfo{};
|
||||||
|
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
allocInfo.allocationSize = memRequirements.size;
|
||||||
|
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
|
||||||
|
|
||||||
|
if (vkAllocateMemory(Global::device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to allocate buffer memory!");
|
||||||
|
}
|
||||||
|
|
||||||
|
vkBindBufferMemory(Global::device, buffer, bufferMemory, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bufferslibrary::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(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data);
|
||||||
|
memcpy(data, indices.data(), (size_t) bufferSize);
|
||||||
|
vkUnmapMemory(Global::device, 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(Global::device, stagingBuffer, nullptr);
|
||||||
|
vkFreeMemory(Global::device, stagingBufferMemory, nullptr);
|
||||||
|
}
|
||||||
void bufferslibrary::createVertexBuffer() {
|
void bufferslibrary::createVertexBuffer() {
|
||||||
// Create a Vertex Buffer to hold the vertex information in memory so it doesn't have to be hardcoded!
|
// 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.
|
// 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.
|
// 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;
|
VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
|
||||||
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
||||||
bufferInfo.size = sizeof(vertices[0]) * vertices.size();
|
VkBuffer stagingBuffer;
|
||||||
bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
VkDeviceMemory stagingBufferMemory;
|
||||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
createBuffer(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
|
||||||
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;
|
void* data;
|
||||||
vkMapMemory(Global::device, vertexBufferMemory, 0, bufferInfo.size, 0, &data);
|
vkMapMemory(Global::device, stagingBufferMemory, 0, bufferSize, 0, &data);
|
||||||
memcpy(data, vertices.data(), (size_t) bufferInfo.size);
|
memcpy(data, vertices.data(), (size_t) bufferSize);
|
||||||
vkUnmapMemory(Global::device, vertexBufferMemory);
|
vkUnmapMemory(Global::device, 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(Global::device, stagingBuffer, nullptr);
|
||||||
|
vkFreeMemory(Global::device, stagingBufferMemory, nullptr);
|
||||||
}
|
}
|
||||||
void bufferslibrary::destroyVertexBuffer() {
|
|
||||||
|
void bufferslibrary::destroyBuffers() {
|
||||||
|
vkDestroyBuffer(Global::device, indexBuffer, nullptr);
|
||||||
|
vkFreeMemory(Global::device, indexBufferMemory, nullptr);
|
||||||
|
|
||||||
vkDestroyBuffer(Global::device, vertexBuffer, nullptr);
|
vkDestroyBuffer(Global::device, vertexBuffer, nullptr);
|
||||||
vkFreeMemory(Global::device, vertexBufferMemory, nullptr);
|
vkFreeMemory(Global::device, vertexBufferMemory, nullptr);
|
||||||
}
|
}
|
||||||
VkBuffer bufferslibrary::getVertexBuffer() {
|
VkBuffer bufferslibrary::getVertexBuffer() {
|
||||||
return vertexBuffer;
|
return vertexBuffer;
|
||||||
}
|
}
|
||||||
|
VkBuffer bufferslibrary::getIndexBuffer() {
|
||||||
|
return indexBuffer;
|
||||||
|
}
|
||||||
std::vector<Global::Vertex> bufferslibrary::getVertices() {
|
std::vector<Global::Vertex> bufferslibrary::getVertices() {
|
||||||
return vertices;
|
return vertices;
|
||||||
}
|
}
|
||||||
|
std::vector<uint16_t> bufferslibrary::getIndices() {
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,12 @@
|
|||||||
namespace Buffers {
|
namespace Buffers {
|
||||||
class bufferslibrary {
|
class bufferslibrary {
|
||||||
public:
|
public:
|
||||||
|
void createIndexBuffer();
|
||||||
void createVertexBuffer();
|
void createVertexBuffer();
|
||||||
void destroyVertexBuffer();
|
void destroyBuffers();
|
||||||
VkBuffer getVertexBuffer();
|
VkBuffer getVertexBuffer();
|
||||||
|
VkBuffer getIndexBuffer();
|
||||||
std::vector<Global::Vertex> getVertices();
|
std::vector<Global::Vertex> getVertices();
|
||||||
|
std::vector<uint16_t> getIndices();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,8 @@ namespace Graphics {
|
|||||||
rasterizer.depthClampEnable = VK_FALSE;
|
rasterizer.depthClampEnable = VK_FALSE;
|
||||||
rasterizer.rasterizerDiscardEnable = 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*
|
// 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_FILL;
|
rasterizer.polygonMode = VK_POLYGON_MODE_LINE;
|
||||||
rasterizer.lineWidth = 1.0f;
|
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.
|
// 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.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||||
@ -308,8 +308,9 @@ namespace Graphics {
|
|||||||
VkBuffer vertexBuffers[] = {buffers.getVertexBuffer()};
|
VkBuffer vertexBuffers[] = {buffers.getVertexBuffer()};
|
||||||
VkDeviceSize offsets[] = {0};
|
VkDeviceSize offsets[] = {0};
|
||||||
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
|
||||||
|
vkCmdBindIndexBuffer(commandBuffer, buffers.getIndexBuffer(), 0, VK_INDEX_TYPE_UINT16);
|
||||||
|
|
||||||
vkCmdDraw(commandBuffer, static_cast<uint32_t>(buffers.getVertices().size()), 1, 0, 0);
|
vkCmdDrawIndexed(commandBuffer, static_cast<uint32_t>(buffers.getIndices().size()), 1, 0, 0, 0);
|
||||||
vkCmdEndRenderPass(commandBuffer);
|
vkCmdEndRenderPass(commandBuffer);
|
||||||
|
|
||||||
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
||||||
|
@ -144,8 +144,8 @@ namespace RenderPresent {
|
|||||||
}
|
}
|
||||||
void render::destroyFenceSemaphores() {
|
void render::destroyFenceSemaphores() {
|
||||||
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) {
|
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) {
|
||||||
vkDestroySemaphore(Global::device, imageAvailableSemaphores[i], nullptr);
|
|
||||||
vkDestroySemaphore(Global::device, renderFinishedSemaphores[i], nullptr);
|
vkDestroySemaphore(Global::device, renderFinishedSemaphores[i], nullptr);
|
||||||
|
vkDestroySemaphore(Global::device, imageAvailableSemaphores[i], nullptr);
|
||||||
vkDestroyFence(Global::device, inFlightFences[i], nullptr);
|
vkDestroyFence(Global::device, inFlightFences[i], nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
src/shaders/fragment.spv
Normal file
BIN
src/shaders/fragment.spv
Normal file
Binary file not shown.
BIN
src/shaders/vertex.spv
Normal file
BIN
src/shaders/vertex.spv
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user