From 82ac1567a8b564765ac5d41d98b8eab7b93957f4 Mon Sep 17 00:00:00 2001 From: Nigel Barink Date: Thu, 18 May 2023 16:35:03 +0200 Subject: [PATCH] Rendering from vertex buffer --- Hello_triangle/main.cpp | 112 +++++++++++++++++++++++++++-- Hello_triangle/shaders/shader.vert | 21 ++---- 2 files changed, 110 insertions(+), 23 deletions(-) diff --git a/Hello_triangle/main.cpp b/Hello_triangle/main.cpp index 50ac839..cc599b5 100644 --- a/Hello_triangle/main.cpp +++ b/Hello_triangle/main.cpp @@ -1,10 +1,11 @@ /* Following the vulkan tutorial on : - https://vulkan-tutorial.com/en/Drawing_a_triangle/Drawing/Frames_in_flight + https://vulkan-tutorial.com/Vertex_buffers/Staging_buffer */ #define GLFW_INCLUDE_VULKAN #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include #include const uint32_t WIDTH = 800; @@ -34,8 +36,43 @@ const std::vector deviceExtensions = { # else const bool enableValidationLayers = true; #endif + 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 getAttributeDescriptions() { + std::array attributeDescription{}; + + attributeDescription[0].binding = 0; + attributeDescription[0].location = 0; + attributeDescription[0].format = VK_FORMAT_R32G32_SFLOAT; + attributeDescription[0].offset = offsetof(Vertex, pos); + attributeDescription[1].binding = 0; + attributeDescription[1].location = 1; + attributeDescription[1].format = VK_FORMAT_R32G32B32_SFLOAT; + attributeDescription[1].offset = offsetof(Vertex, color); + + return attributeDescription; + } + }; + + + const std::vector vertices = { + {{0.0f, -0.5f}, {1.0f,1.0f, 1.0f}}, + {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, + {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} + }; class HelloTriangleApplication { public: @@ -65,6 +102,8 @@ const std::vector deviceExtensions = { VkPipeline graphicsPipeline; std::vector swapchainFrameBuffers; VkCommandPool commandPool; + VkBuffer vertexBuffer; + VkDeviceMemory vertexBufferMemory; std::vector commandBuffers; std::vector imageAvailableSemaphores; std::vector renderFinishedSemaphores; @@ -109,10 +148,56 @@ const std::vector deviceExtensions = { createGraphicsPipeline(); createFramebuffers(); createCommandPool(); + createVertexBuffer(); createCommandBuffers(); createSyncObjects(); } + uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { + VkPhysicalDeviceMemoryProperties memProperties; + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); + + 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 createVertexBuffer() { + 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; + + if (vkCreateBuffer(device, &bufferInfo, nullptr, &vertexBuffer)!= VK_SUCCESS) { + throw std::runtime_error("failed to create vertex buffer!"); + } + + VkMemoryRequirements memRequirements; + vkGetBufferMemoryRequirements(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(device, &allocInfo, nullptr, &vertexBufferMemory)!= VK_SUCCESS) { + throw std::runtime_error("failed to allocate vertex buffer memory!"); + } + vkBindBufferMemory(device, vertexBuffer, vertexBufferMemory, 0); + + void* data; + vkMapMemory(device, vertexBufferMemory, 0, bufferInfo.size, 0, &data); + memcpy(data, vertices.data(), (size_t)bufferInfo.size); + vkUnmapMemory(device, vertexBufferMemory); + + + } + void recreateSwapChain() { int width = 0, height = 0; @@ -198,6 +283,10 @@ const std::vector deviceExtensions = { vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + VkBuffer vertexBuffers[] = { vertexBuffer }; + VkDeviceSize offsets[] = { 0 }; + vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); + VkViewport viewport{}; viewport.x = 0.0f; viewport.y = 0.0f; @@ -212,7 +301,10 @@ const std::vector deviceExtensions = { scissor.extent = swapChainExtent; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - vkCmdDraw(commandBuffer, 3, 1, 0, 0); + + + + vkCmdDraw(commandBuffer, static_cast(vertices.size()), 1, 0, 0); vkCmdEndRenderPass(commandBuffer); @@ -450,12 +542,17 @@ const std::vector deviceExtensions = { VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo }; + + auto bindingDescription = Vertex::getBindingDescription(); + auto attributeDescriptions = Vertex::getAttributeDescriptions(); + + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 0; - vertexInputInfo.pVertexBindingDescriptions = nullptr; - vertexInputInfo.vertexAttributeDescriptionCount = 0; - vertexInputInfo.pVertexAttributeDescriptions = nullptr; + vertexInputInfo.vertexBindingDescriptionCount = 1; + vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; + vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); + vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; @@ -975,7 +1072,8 @@ const std::vector deviceExtensions = { void cleanup(){ cleanupSwapChain(); - + vkDestroyBuffer(device, vertexBuffer, nullptr); + vkFreeMemory(device, vertexBufferMemory, nullptr); vkDestroyPipeline(device, graphicsPipeline, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyRenderPass(device, renderPass, nullptr); diff --git a/Hello_triangle/shaders/shader.vert b/Hello_triangle/shaders/shader.vert index 8cf3ae9..6f63881 100644 --- a/Hello_triangle/shaders/shader.vert +++ b/Hello_triangle/shaders/shader.vert @@ -1,22 +1,11 @@ #version 450 +layout(location = 0) in vec2 inPosition; +layout(location = 1) in vec3 inColor; + 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() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - fragColor = colors[gl_VertexIndex]; + gl_Position = vec4(inPosition, 0.0 , 1.0); + fragColor = inColor; } \ No newline at end of file