From 487e487fb345f8c1c7a5a23f65be08d8935eb459 Mon Sep 17 00:00:00 2001 From: Nigel Barink Date: Mon, 25 Dec 2023 13:41:18 +0100 Subject: [PATCH] GOING 3D Adding Descriptor Layout & Buffers, Creating Descriptor pools and sets --- Hello_triangle/main.cpp | 148 ++++++++++++++++++++++++++++- Hello_triangle/shaders/shader.vert | 8 +- 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/Hello_triangle/main.cpp b/Hello_triangle/main.cpp index cc281a1..e9363b2 100644 --- a/Hello_triangle/main.cpp +++ b/Hello_triangle/main.cpp @@ -1,11 +1,15 @@ /* Following the vulkan tutorial on : - https://vulkan-tutorial.com/en/Vertex_buffers/Index_buffer + https://vulkan-tutorial.com/Texture_mapping/Images */ #define GLFW_INCLUDE_VULKAN +#define GLM_FORCE_RADIANS #include #include +#include + +#include #include #include #include @@ -67,6 +71,11 @@ const std::vector deviceExtensions = { } }; + struct UniformBufferObject { + alignas(16) glm::mat4 model; + alignas(16) glm::mat4 view; + alignas(16) glm::mat4 proj; + }; const std::vector vertices = { {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, @@ -103,16 +112,24 @@ const std::vector deviceExtensions = { VkExtent2D swapChainExtent; std::vector swapChainImageViews; VkRenderPass renderPass; + VkDescriptorSetLayout descriptorSetLayout; VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; std::vector swapchainFrameBuffers; VkCommandPool commandPool; + VkDescriptorPool descriptorPool; + std::vector descriptorSets; + VkBuffer vertexBuffer; VkDeviceMemory vertexBufferMemory; VkBuffer indexBuffer; VkDeviceMemory indexBufferMemory; + std::vector uniformBuffers; + std::vector uniformBuffersMemory; + std::vector uniformBuffersMapped; + std::vector commandBuffers; std::vector imageAvailableSemaphores; @@ -154,15 +171,108 @@ const std::vector deviceExtensions = { createSwapChain(); createImageViews(); createRenderPass(); + createDescriptorSetLayout(); createGraphicsPipeline(); createFramebuffers(); createCommandPool(); createVertexBuffer(); createIndexBuffer(); + createUniformBuffers(); + createDescriptorPool(); + createDescriptorSets(); createCommandBuffers(); createSyncObjects(); } + void createDescriptorSets() { + std::vector layouts(MAX_FRAMES_IN_FLIGHT, descriptorSetLayout); + VkDescriptorSetAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = descriptorPool; + allocInfo.descriptorSetCount = static_cast(MAX_FRAMES_IN_FLIGHT); + allocInfo.pSetLayouts = layouts.data(); + + descriptorSets.resize(MAX_FRAMES_IN_FLIGHT); + if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) { + throw std::runtime_error("failed to allocate descriptor sets!"); + } + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + VkDescriptorBufferInfo bufferInfo{}; + bufferInfo.buffer = uniformBuffers[i]; + bufferInfo.offset = 0; + bufferInfo.range = sizeof(UniformBufferObject); + + VkWriteDescriptorSet descriptorWrite{}; + descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrite.dstSet = descriptorSets[i]; + descriptorWrite.dstBinding = 0; + descriptorWrite.dstArrayElement = 0; + descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorWrite.descriptorCount = 1; + descriptorWrite.pBufferInfo = &bufferInfo; + descriptorWrite.pImageInfo = nullptr; // Optional + descriptorWrite.pTexelBufferView = nullptr; // Optional + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + + } + + } + + void createDescriptorPool() { + VkDescriptorPoolSize poolSize{}; + poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + poolSize.descriptorCount = static_cast (MAX_FRAMES_IN_FLIGHT); + + VkDescriptorPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolInfo.poolSizeCount = 1; + poolInfo.pPoolSizes = &poolSize; + poolInfo.maxSets = static_cast(MAX_FRAMES_IN_FLIGHT); + + if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) { + throw std::runtime_error("failed to create descriptor pool!"); + } + + } + + + void createUniformBuffers() { + VkDeviceSize buffersize = sizeof(UniformBufferObject); + + uniformBuffers.resize(MAX_FRAMES_IN_FLIGHT); + uniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT); + uniformBuffersMapped.resize(MAX_FRAMES_IN_FLIGHT); + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + CreateBuffer(buffersize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]); + + vkMapMemory(device, uniformBuffersMemory[i], 0, buffersize, 0, &uniformBuffersMapped[i]); + } + } + + void createDescriptorSetLayout() { + VkDescriptorSetLayoutBinding uboLayoutBinding{}; + uboLayoutBinding.binding = 0; + uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uboLayoutBinding.descriptorCount = 1; + + uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + uboLayoutBinding.pImmutableSamplers = nullptr; // Optional + + VkDescriptorSetLayoutCreateInfo layoutInfo{}; + layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layoutInfo.bindingCount = 1; + layoutInfo.pBindings = &uboLayoutBinding; + + if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) { + throw std::runtime_error("failed to create descriptor set layout!"); + } + + } + + uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { VkPhysicalDeviceMemoryProperties memProperties; vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); @@ -391,6 +501,8 @@ const std::vector deviceExtensions = { scissor.extent = swapChainExtent; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[currentFrame], 0, nullptr); + vkCmdDrawIndexed(commandBuffer, static_cast(indices.size()), 1, 0, 0, 0); vkCmdEndRenderPass(commandBuffer); @@ -672,7 +784,7 @@ const std::vector deviceExtensions = { rasterizer.polygonMode = VK_POLYGON_MODE_FILL; rasterizer.lineWidth = 1.0f; rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_FALSE; @@ -694,6 +806,8 @@ const std::vector deviceExtensions = { VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 1; + pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout; if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { throw std::runtime_error("failed to create pipeline layout!"); @@ -1099,6 +1213,8 @@ const std::vector deviceExtensions = { uint32_t imageIndex; VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) { recreateSwapChain(); return; @@ -1107,8 +1223,11 @@ const std::vector deviceExtensions = { throw std::runtime_error("failed to acquire swap chain image!"); } + updateUniformBuffer(currentFrame); + vkResetFences(device, 1, &inFlightFences[currentFrame]); + vkResetCommandBuffer(commandBuffers[currentFrame], 0); recordCommandBuffer(commandBuffers[currentFrame], imageIndex); @@ -1156,9 +1275,34 @@ const std::vector deviceExtensions = { currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; } + void updateUniformBuffer(uint32_t currentImage) { + static auto startTime = std::chrono::high_resolution_clock::now(); + + auto currentTime = std::chrono::high_resolution_clock::now(); + float time = std::chrono::duration(currentTime - startTime).count(); + + UniformBufferObject ubo{}; + ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); + ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float)swapChainExtent.height, 0.1f, 10.0f); + ubo.proj[1][1] *= -1; // Invert Y to correct for left or right handedness + + memcpy(uniformBuffersMapped[currentImage], &ubo, sizeof(ubo)); + } + + + void cleanup(){ cleanupSwapChain(); + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + vkDestroyBuffer(device, uniformBuffers[i], nullptr); + vkFreeMemory(device, uniformBuffersMemory[i], nullptr); + } + vkDestroyDescriptorPool(device, descriptorPool, nullptr); + + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + vkDestroyBuffer(device, indexBuffer, nullptr); vkFreeMemory(device, vertexBufferMemory, nullptr); diff --git a/Hello_triangle/shaders/shader.vert b/Hello_triangle/shaders/shader.vert index 6f63881..92e085b 100644 --- a/Hello_triangle/shaders/shader.vert +++ b/Hello_triangle/shaders/shader.vert @@ -1,11 +1,17 @@ #version 450 +layout(binding = 0) uniform UniformBufferObject { + mat4 model; + mat4 view; + mat4 proj; +} ubo; + layout(location = 0) in vec2 inPosition; layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; void main() { - gl_Position = vec4(inPosition, 0.0 , 1.0); + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0 , 1.0); fragColor = inColor; } \ No newline at end of file