Change vertex buffer handling

Previously vertex data was only in shaders. I have removed it from there
and put hardcoded vertex data into cpp source code.
This commit is contained in:
Piotr Krygier committed 2022-12-14 14:16:30 +01:00
1 parent e7b9d4a32f
commit 34665e1c2e
5 files changed
+177 -29

No files matched your search

+150 -14
View File
@@ -33,6 +33,8 @@
#include "logger.hpp"
#include "window.hpp"
#include <glm/glm.hpp>
#include <vector>
#include <string>
#include <fstream>
@@ -66,6 +68,8 @@ enum VULKAN_ERROR
VULKAN_ERROR_DEVICE_CREATION_FAILED,
VULKAN_ERROR_ALLOCATOR_CREATION_FAILED,
VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED,
VULKAN_ERROR_VERTEX_BUFFER_CREATION_FAILED,
VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED,
VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED,
VULKAN_ERROR_SURFACE_CREATION_FAILED,
VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED,
@@ -86,6 +90,60 @@ enum class ShaderStage
FRAGMENTS
};
/**
* @brief Represents single vertex on the screen
*
*/
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; /* inPosition in shader.vert */
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1; /* inColor in shader.vert */
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);
return attributeDescriptions;
}
};
/**
* @brief Wrapper for Vulan buffer. Holds allocation data;
*
*/
struct Buffer
{
VkBuffer buffer;
VmaAllocation allocation;
};
// FIXME: Temporary array of vertices, for testing purposes
const std::vector<Vertex> vertices = {
{{0.0f, -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}}
};
/* Define Validation Layers for debug build */
#ifndef NDEBUG
const std::vector<const char*> gEnabledInstanceLayersNames = {"VK_LAYER_KHRONOS_validation"};
@@ -143,6 +201,7 @@ std::vector<VkFramebuffer> gSwapchainFramebuffers;
std::vector<VkSemaphore> gImageAvailableSemaphores;
std::vector<VkSemaphore> gRenderFinishedSemaphores;
std::vector<VkFence> gInFlightFences;
Buffer gVertexBuffer;
/**
@@ -201,6 +260,15 @@ static uint8_t createMemoryAllocator();
*/
static uint8_t createCommandPools();
/**
* @brief Create a buffer holding all vertex data
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_VERTEX_BUFFER_CREATION_FAILED
* VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED
*/
static uint8_t createVertexBuffer();
/**
* @brief Allocate Command Buffers
*
@@ -326,7 +394,10 @@ static uint8_t createGraphicsPipeline();
*/
static uint8_t createFrambuffers();
/**
* @brief Recreate swapchain
*
*/
static void recreateSwapchain();
@@ -595,7 +666,7 @@ static uint8_t createMemoryAllocator()
vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
VmaAllocatorCreateInfo allocatorCreateInfo = {0};
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_3;
allocatorCreateInfo.physicalDevice = gPhysicalDevice;
allocatorCreateInfo.device = gDevice;
allocatorCreateInfo.instance = gVulkanInstance;
@@ -626,6 +697,53 @@ static uint8_t createCommandPools()
return VULKAN_ERROR_NO_ERROR;
}
static uint8_t createVertexBuffer()
{
VkBufferCreateInfo vertexBufferInfo;
VmaAllocationCreateInfo allocInfo;
void* mappedData;
vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
vertexBufferInfo.pNext = nullptr;
vertexBufferInfo.flags = 0U;
vertexBufferInfo.size = sizeof(vertices[0]) * vertices.size(); // FIXME: Harcoded for now
vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
vertexBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
vertexBufferInfo.queueFamilyIndexCount = 0U;
vertexBufferInfo.pQueueFamilyIndices = nullptr;
/* Disalows random access to memory. TODO: Consider changing to VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT? */
allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
allocInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocInfo.memoryTypeBits = 0U;
allocInfo.requiredFlags = 0U;
allocInfo.preferredFlags = 0U;
allocInfo.pool = VK_NULL_HANDLE;
allocInfo.pUserData = VK_NULL_HANDLE;
allocInfo.priority = 0.0f;
if (VK_SUCCESS != vmaCreateBuffer(gAllocator,
&vertexBufferInfo,
&allocInfo,
&gVertexBuffer.buffer,
&gVertexBuffer.allocation,
nullptr)) {
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_CREATION_FAILED];
return VULKAN_ERROR_VERTEX_BUFFER_CREATION_FAILED;
}
/* Fill vertex buffer */
if (VK_SUCCESS != vmaMapMemory(gAllocator, gVertexBuffer.allocation, &mappedData))
{
LOGF << vulkanErrorMesssages[VULKAN_VERTEX_BUFFER_MAPPING_FAILED];
return VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED;
}
memcpy(mappedData, vertices.data(), sizeof(Vertex) * vertices.size());
vmaUnmapMemory(gAllocator, gVertexBuffer.allocation);
return VULKAN_ERROR_NO_ERROR;
}
static uint8_t allocateCommandBuffers()
{
VkCommandBufferAllocateInfo allocateInfo;
@@ -807,7 +925,6 @@ static uint8_t fillShaderStages(std::vector<VkPipelineShaderStageCreateInfo>* sh
shaderStages->push_back(vertShaderStageInfo);
shaderStages->push_back(fragShaderStageInfo);
// FIXME: Actually use those shader stages
gShaderModules.push_back(std::move(vertexShaderModule.value()));
gShaderModules.push_back(std::move(fragmentsShaderModule.value()));
@@ -846,15 +963,26 @@ static void freeDynamicPipelineStateInfo(VkPipelineDynamicStateCreateInfo* dynam
static void fillVertexInputInfo(VkPipelineVertexInputStateCreateInfo* vertexInputInfo)
{
auto bindingDescription = Vertex::getBindingDescription();
auto attributeDescriptions = Vertex::getAttributeDescriptions();
vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo->pNext = nullptr;
vertexInputInfo->flags = 0U;
vertexInputInfo->vertexBindingDescriptionCount = 0U;
vertexInputInfo->pVertexBindingDescriptions = nullptr;
vertexInputInfo->vertexAttributeDescriptionCount = 0U;
vertexInputInfo->pVertexAttributeDescriptions = nullptr;
vertexInputInfo->vertexBindingDescriptionCount = 1U;
vertexInputInfo->pVertexBindingDescriptions = new VkVertexInputBindingDescription(bindingDescription);
vertexInputInfo->vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
// FIXME: Shaders have hardcoded vertices for now. Change this later
VkVertexInputAttributeDescription* tmp = new VkVertexInputAttributeDescription[attributeDescriptions.size()];
std::copy(attributeDescriptions.begin(), attributeDescriptions.end(), tmp);
vertexInputInfo->pVertexAttributeDescriptions = tmp;
}
static void freeVertexInputInfo(VkPipelineVertexInputStateCreateInfo* vertexInputInfo)
{
delete vertexInputInfo->pVertexBindingDescriptions;
delete[] vertexInputInfo->pVertexAttributeDescriptions;
}
static void fillInputAssemblyInfo(VkPipelineInputAssemblyStateCreateInfo* inputAssembly)
@@ -1072,8 +1200,9 @@ static uint8_t createGraphicsPipeline()
}
freeDynamicPipelineStateInfo(&dynamicState);
freeViewportInfo(&viewportState);
freeColorBlendInfo(&colorBlending);
freeViewportInfo(&viewportState);
freeVertexInputInfo(&vertexInputInfo);
return status;
}
@@ -1108,6 +1237,13 @@ static uint8_t createFrambuffers()
static uint8_t recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex)
{
VkCommandBufferBeginInfo beginInfo{};
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
VkRenderPassBeginInfo renderPassInfo{};
VkViewport viewport{};
VkRect2D scissor{};
VkBuffer vertexBuffers[] = {gVertexBuffer.buffer};
VkDeviceSize offsets[] = {0};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0; // Optional
beginInfo.pInheritanceInfo = nullptr; // Optional
@@ -1116,8 +1252,6 @@ static uint8_t recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t image
throw std::runtime_error("failed to begin recording command buffer!");
}
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = gRenderPass;
renderPassInfo.framebuffer = gSwapchainFramebuffers[imageIndex];
@@ -1129,7 +1263,7 @@ static uint8_t recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t image
vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, gGraphicsPipeline);
VkViewport viewport{};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = static_cast<float>(gSwapchainExtent.width);
@@ -1138,12 +1272,12 @@ static uint8_t recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t image
viewport.maxDepth = 1.0f;
vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
VkRect2D scissor{};
scissor.offset = {0, 0};
scissor.extent = gSwapchainExtent;
vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
vkCmdDraw(commandBuffer, 3, 1, 0, 0);
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets);
vkCmdDraw(commandBuffer, static_cast<uint32_t>(vertices.size()), 1, 0, 0);
vkCmdEndRenderPass(commandBuffer);
@@ -1216,6 +1350,7 @@ uint8_t initVulkan()
STATUS_CHECK(createDevice());
STATUS_CHECK(createMemoryAllocator());
STATUS_CHECK(createCommandPools());
STATUS_CHECK(createVertexBuffer());
STATUS_CHECK(allocateCommandBuffers());
STATUS_CHECK(createSwapchain());
STATUS_CHECK(createSwapchainImageViews());
@@ -1290,6 +1425,7 @@ void deinitVulkan()
{
cleanupSwapchain();
vmaDestroyBuffer(gAllocator, gVertexBuffer.buffer, gVertexBuffer.allocation);
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
vkDestroySemaphore(gDevice, gImageAvailableSemaphores[i], nullptr);
vkDestroySemaphore(gDevice, gRenderFinishedSemaphores[i], nullptr);