diff --git a/shaders/shader.vert b/shaders/shader.vert index e516f41..2c1b47f 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -1,21 +1,12 @@ #version 450 #extension GL_ARB_separate_shader_objects : enable +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; } diff --git a/src/HelloTriangleApplication.cpp b/src/HelloTriangleApplication.cpp index 6dad478..486ea25 100644 --- a/src/HelloTriangleApplication.cpp +++ b/src/HelloTriangleApplication.cpp @@ -7,14 +7,49 @@ #include #include #include +#include +#include #define GLFW_INCLUDE_VULKAN #include #include +#include #include "queues.h" #include "util.h" +struct Vertex { + glm::vec2 pos; + glm::vec3 color; + + static VkVertexInputBindingDescription getBindingDescription() { + VkVertexInputBindingDescription bindingDescription{ + .binding = 0, + .stride = sizeof(Vertex), + .inputRate = VK_VERTEX_INPUT_RATE_VERTEX, + }; + return bindingDescription; + } + static std::array getAttributeDescription() { + std::array attributeDescriptions{}; + attributeDescriptions[0].binding = 0; + attributeDescriptions[0].location = 0; + attributeDescriptions[0].format = VK_FORMAT_R32G32_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); + return attributeDescriptions; + } +}; + +const std::vector 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}}, +}; + VkShaderModule HelloTriangleApplication::createShaderModule(const std::vector &code) { VkShaderModuleCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; @@ -179,12 +214,15 @@ void HelloTriangleApplication::createGraphicsPipeline() { VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; + auto bindingDescription = Vertex::getBindingDescription(); + auto attributeDescriptions = Vertex::getAttributeDescription(); + VkPipelineVertexInputStateCreateInfo vertexInputInfo{ .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 0, - .pVertexBindingDescriptions = nullptr, - .vertexAttributeDescriptionCount = 0, - .pVertexAttributeDescriptions = nullptr, + .vertexBindingDescriptionCount = 1, + .pVertexBindingDescriptions = &bindingDescription, + .vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()), + .pVertexAttributeDescriptions = attributeDescriptions.data(), }; VkPipelineInputAssemblyStateCreateInfo inputAssembly{ @@ -338,6 +376,38 @@ void HelloTriangleApplication::createFrameBuffers() { } } +void HelloTriangleApplication::createVertexBuffer() { + VkBufferCreateInfo bufferCreateInfo { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = sizeof(vertices[0]) * vertices.size(), + .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + }; + + if (vkCreateBuffer(myVkInstance->device, &bufferCreateInfo, nullptr, &vertexBuffer) != VK_SUCCESS) { + throw std::runtime_error("Failed to create vertex buffer"); + } + + VkMemoryRequirements memoryRequirements; + vkGetBufferMemoryRequirements(myVkInstance->device, vertexBuffer, &memoryRequirements); + + VkMemoryAllocateInfo allocateInfo{ + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memoryRequirements.size, + .memoryTypeIndex = myVkInstance->findMemoryType(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), + }; + + if (vkAllocateMemory(myVkInstance->device, &allocateInfo, nullptr, &vertexBufferMemory) != VK_SUCCESS) { + throw std::runtime_error("Failed to allocate vertex buffer memory"); + } + vkBindBufferMemory(myVkInstance->device, vertexBuffer, vertexBufferMemory, 0); + + void* data; + vkMapMemory(myVkInstance->device, vertexBufferMemory, 0, bufferCreateInfo.size, 0, &data); + memcpy(data, vertices.data(), (size_t)bufferCreateInfo.size); + vkUnmapMemory(myVkInstance->device, vertexBufferMemory); +} + void HelloTriangleApplication::createCommandPool() { VkCommandPoolCreateInfo poolInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -386,7 +456,10 @@ void HelloTriangleApplication::createCommandBuffers() { renderPassInfo.pClearValues = &clearColor; vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); - vkCmdDraw(commandBuffers[i], 3, 1, 0, 0); + VkBuffer vertexBuffers[] = {vertexBuffer}; + VkDeviceSize offset[] = {0}; + vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offset); + vkCmdDraw(commandBuffers[i], static_cast(vertices.size()), 1, 0, 0); vkCmdEndRenderPass(commandBuffers[i]); if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) { throw std::runtime_error{"Failed to record command buffer"}; @@ -423,6 +496,7 @@ void HelloTriangleApplication::initVulkan() { createGraphicsPipeline(); createFrameBuffers(); createCommandPool(); + createVertexBuffer(); createCommandBuffers(); createSyncObjects(); } @@ -546,6 +620,9 @@ void HelloTriangleApplication::drawFrame() { void HelloTriangleApplication::cleanup() { cleanupSwapChain(); + vkDestroyBuffer(myVkInstance->device, vertexBuffer, nullptr); + vkFreeMemory(myVkInstance->device, vertexBufferMemory, nullptr); + for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) { vkDestroySemaphore(myVkInstance->device, renderFinishedSemaphores[i], nullptr); vkDestroySemaphore(myVkInstance->device, imageAvailableSemaphores[i], nullptr); diff --git a/src/HelloTriangleApplication.h b/src/HelloTriangleApplication.h index af5ca22..1696be7 100644 --- a/src/HelloTriangleApplication.h +++ b/src/HelloTriangleApplication.h @@ -30,6 +30,8 @@ private: VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; std::vector swapChainFrameBuffers; + VkBuffer vertexBuffer; + VkDeviceMemory vertexBufferMemory; VkCommandPool commandPool; std::vector commandBuffers; @@ -47,6 +49,7 @@ private: void createGraphicsPipeline(); void createFrameBuffers(); void createCommandPool(); + void createVertexBuffer(); void createCommandBuffers(); void createSyncObjects(); void initVulkan(); diff --git a/src/MyVkInstance.cpp b/src/MyVkInstance.cpp index b1dc578..69bdced 100644 --- a/src/MyVkInstance.cpp +++ b/src/MyVkInstance.cpp @@ -219,3 +219,15 @@ void MyVkInstance::registerResizeCallback(void* thisValue, void (*callback)(void void MyVkInstance::waitEvents() { glfwWaitEvents(); } + +uint32_t MyVkInstance::findMemoryType(uint32_t typeFiltr, VkMemoryPropertyFlags properties) { + VkPhysicalDeviceMemoryProperties memoryProperties; + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) { + if (typeFiltr & (1u << i) && (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { + return i; + } + } + throw std::runtime_error("Failed to find suitable memory type"); +} + diff --git a/src/MyVkInstance.h b/src/MyVkInstance.h index d8c17d7..fef8a92 100644 --- a/src/MyVkInstance.h +++ b/src/MyVkInstance.h @@ -35,6 +35,8 @@ public: static void waitEvents(); + uint32_t findMemoryType(uint32_t typeFiltr, VkMemoryPropertyFlags properties); + private: int width{}; int height{};