diff --git a/shaders/shader.vert b/shaders/shader.vert index dfdb555..68096b8 100644 --- a/shaders/shader.vert +++ b/shaders/shader.vert @@ -1,5 +1,11 @@ #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; @@ -22,6 +28,7 @@ vec3 colors[3] = vec3[]( void main(){ // gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); // fragColor = colors[gl_VertexIndex]; - gl_Position = vec4(inPosition, 0.0, 1.0); + // gl_Position = vec4(inPosition, 0.0, 1.0); + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); fragColor = inColor; } diff --git a/vulkan/vulkan_app.cpp b/vulkan/vulkan_app.cpp index 6f6b83c..a5038ca 100644 --- a/vulkan/vulkan_app.cpp +++ b/vulkan/vulkan_app.cpp @@ -433,6 +433,23 @@ namespace vapp{ } } + void Vulkan::createDescriptorSetLayout(){ + VkDescriptorSetLayoutBinding uboLayoutBinding{}; + uboLayoutBinding.binding = 0; + uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uboLayoutBinding.descriptorCount = 1; + uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + + 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("Func: createDescriptorSetLayout\nError: Failed to create Descriptor Set Layout!\n"); + } + } + void Vulkan::createGraphicsPipeline(){ // TODO: find solution for file location std::vector vertShaderCode; @@ -520,7 +537,8 @@ namespace vapp{ rasterizer.polygonMode = VK_POLYGON_MODE_FILL; // INFO: Other render effects rasterizer.lineWidth = 1.0f; rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + // rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; with descriptor sets this causes backface culling to occure + rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_FALSE; VkPipelineMultisampleStateCreateInfo multisampling{}; @@ -549,6 +567,8 @@ namespace vapp{ 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("Func; createGraphicsPipeline\nError: Failed to create pipeline layout!\n"); @@ -787,6 +807,71 @@ namespace vapp{ vkFreeMemory(device, stagingBufferMemory, nullptr); } + void Vulkan::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 Vulkan::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("Func: createDescriptorPool\nError: Failed to create Descriptor Pool!\n"); + } + } + + void Vulkan::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("Func: createDescriptorSets\nError: Failed to allocate Descriptor Sets!\n"); + } + + 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; + + vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr); + } + } + void Vulkan::createCommandBuffers(){ commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); @@ -843,6 +928,8 @@ namespace vapp{ scissor.extent = swapChainExtent; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSets[currentFrame], 0, nullptr); + // vkCmdDraw(commandBuffer, static_cast(vertices.size()), 1, 0, 0); // -> goto indexed draw vkCmdDrawIndexed(commandBuffer, static_cast(indices.size()), 1, 0, 0, 0); @@ -874,6 +961,24 @@ namespace vapp{ } } + void Vulkan::updateUniformBuffer(uint32_t currentFrame){ + 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{}; + // INFO: Change here for other angles + ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.2f, 0.2f, 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); + + // removing this line results in the image rendering upside down + ubo.proj[1][1] *= -1; + + memcpy(uniformBuffersMapped[currentFrame], &ubo, sizeof(ubo)); + } + void Vulkan::drawFrame(){ vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); vkResetFences(device, 1, &inFlightFences[currentFrame]); @@ -887,6 +992,8 @@ namespace vapp{ vkResetCommandBuffer(commandBuffers[currentFrame], 0); recordCommandBuffer(commandBuffers[currentFrame], imageIndex); + updateUniformBuffer(currentFrame); + VkSubmitInfo submitInfo{}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -979,11 +1086,15 @@ namespace vapp{ createSwapChain(); createImageViews(); createRenderPass(); + createDescriptorSetLayout(); createGraphicsPipeline(); createFrameBuffers(); createCommandPool(); createVertexBuffer(); createIndexBuffer(); + createUniformBuffers(); + createDescriptorPool(); + createDescriptorSets(); createCommandBuffers(); createSyncObjects(); } @@ -1001,6 +1112,15 @@ namespace vapp{ // Vulkan 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, indexBufferMemory, nullptr); diff --git a/vulkan/vulkan_app.hpp b/vulkan/vulkan_app.hpp index fb0c61c..97d1436 100644 --- a/vulkan/vulkan_app.hpp +++ b/vulkan/vulkan_app.hpp @@ -8,6 +8,10 @@ #define GLFW_INCLUDE_VULKAN #include +#define GLM_FORCE_RADIANS +#include +#include + #include #include #include @@ -19,8 +23,8 @@ #include #include #include -#include #include +#include namespace vapp{ // Change here for other presentMode @@ -60,13 +64,19 @@ namespace vapp{ {{-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, 1.0f, 0.0f}}, -{{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} +{{-0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}} }; // uint16_t also possible -> change in vkCmdBindIndexBuffer also const std::vector indices = { 0, 1, 2, 2, 3, 0 }; // END Remove + struct UniformBufferObject{ + glm::mat4 model; + glm::mat4 view; + glm::mat4 proj; + }; + struct QueueFamilyIndices{ std::optional graphicsFamily; std::optional presentFamily; @@ -111,6 +121,7 @@ namespace vapp{ std::vector swapChainImageViews; VkRenderPass renderPass; + VkDescriptorSetLayout descriptorSetLayout; VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; @@ -130,6 +141,13 @@ namespace vapp{ VkDeviceMemory vertexBufferMemory; VkBuffer indexBuffer; VkDeviceMemory indexBufferMemory; + + std::vector uniformBuffers; + std::vector uniformBuffersMemory; + std::vector uniformBuffersMapped; + + VkDescriptorPool descriptorPool; + std::vector descriptorSets; #pragma endregion bool checkValidationLayerSupport(); @@ -149,6 +167,7 @@ namespace vapp{ VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); void createSwapChain(); void createImageViews(); + void createDescriptorSetLayout(); void createGraphicsPipeline(); VkShaderModule createShaderModule(const std::vector& code); void createRenderPass(); @@ -159,9 +178,13 @@ namespace vapp{ void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); void createVertexBuffer(); void createIndexBuffer(); + void createUniformBuffers(); + void createDescriptorPool(); + void createDescriptorSets(); void createCommandBuffers(); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void createSyncObjects(); + void updateUniformBuffer(uint32_t currentFrame); void drawFrame(); void cleanupSwapChain(); void recreateSwapChain();