Guest User

Application.cpp

a guest
Mar 16th, 2019
248
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 50.00 KB | None | 0 0
  1. #include "Application.h"
  2.  
  3. bool requiredExtensionsAvailable(std::vector<const char*> requiredExtensions, std::vector<VkExtensionProperties> availableExtensions);
  4.  
  5. Application::Application() {};
  6. Application::~Application() {};
  7.  
  8. // *************************************************************
  9. // ***************  Uniform Descriptor  ************************
  10. // *************************************************************
  11.  
  12. void Application::createDescriptorSetLayout()
  13. {
  14.     VkDescriptorSetLayoutBinding uboLayoutBinding = {};
  15.     uboLayoutBinding.binding = 0;
  16.     uboLayoutBinding.descriptorCount = 1;
  17.     uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  18.     uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  19.     uboLayoutBinding.pImmutableSamplers = nullptr;
  20.  
  21.     VkDescriptorSetLayoutCreateInfo layoutInfo = {};
  22.     layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  23.     layoutInfo.bindingCount = 1;
  24.     layoutInfo.pBindings = &uboLayoutBinding;
  25.  
  26.     VkResult result = vkCreateDescriptorSetLayout(m_device, &layoutInfo, nullptr, &m_descriptorSetLayout);
  27.     if (result != VK_SUCCESS)
  28.         throw std::runtime_error("Failed to create descriptor set layout!");
  29. }
  30.  
  31. void Application::createDescriptorPool()
  32. {
  33.     VkDescriptorPoolSize poolSize = {};
  34.     poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  35.     poolSize.descriptorCount = static_cast<uint32_t>(m_swapChainImages.size());
  36.  
  37.     VkDescriptorPoolCreateInfo poolInfo = {};
  38.     poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  39.     poolInfo.poolSizeCount = 1;
  40.     poolInfo.pPoolSizes = &poolSize;
  41.     poolInfo.maxSets = static_cast<uint32_t>(m_swapChainImages.size());
  42.     poolInfo.flags = 0;
  43.  
  44.     VkResult result = vkCreateDescriptorPool(m_device, &poolInfo, nullptr, &m_descriptorPool);
  45.     if (result != VK_SUCCESS)
  46.         throw std::runtime_error("Failed to create descriptor pool!");
  47. }
  48.  
  49. void Application::createDescriptorSets()
  50. {
  51.     std::vector<VkDescriptorSetLayout> layouts(m_swapChainImages.size(), m_descriptorSetLayout);
  52.  
  53.     VkDescriptorSetAllocateInfo allocInfo = {};
  54.     allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  55.     allocInfo.descriptorPool = m_descriptorPool;
  56.     allocInfo.descriptorSetCount = static_cast<uint32_t>(m_swapChainImages.size());
  57.     allocInfo.pSetLayouts = layouts.data();
  58.  
  59.     m_descriptorSets.resize(m_swapChainImages.size());
  60.  
  61.     VkResult result = vkAllocateDescriptorSets(m_device, &allocInfo, m_descriptorSets.data());
  62.     if (result != VK_SUCCESS)
  63.         throw std::runtime_error("Failed to allocate descriptor sets!");
  64.  
  65.     for (size_t i = 0; i < m_swapChainImages.size(); i++)
  66.     {
  67.         VkDescriptorBufferInfo bufferInfo = {};
  68.         bufferInfo.buffer = m_uniformBuffers[i];
  69.         bufferInfo.offset = 0;
  70.         bufferInfo.range = sizeof(UniformBufferObject);
  71.  
  72.         VkWriteDescriptorSet descriptorWrite = {};
  73.         descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  74.         descriptorWrite.dstSet = m_descriptorSets[i];
  75.         descriptorWrite.dstBinding = 0;
  76.         descriptorWrite.dstArrayElement = 0;
  77.         descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  78.         descriptorWrite.descriptorCount = 1;
  79.         descriptorWrite.pBufferInfo = &bufferInfo;
  80.         descriptorWrite.pImageInfo = nullptr;
  81.         descriptorWrite.pTexelBufferView = nullptr;
  82.  
  83.         vkUpdateDescriptorSets(m_device, 1, &descriptorWrite, 0, nullptr);
  84.     }
  85. }
  86.  
  87. // *************************************************************
  88. // ***************  Buffers             ************************
  89. // *************************************************************
  90.  
  91. void Application::createFramebuffers()
  92. {
  93.     m_swapChainFramebuffers.resize(m_swapChainImageViews.size());
  94.  
  95.     for (size_t i = 0; i < m_swapChainImageViews.size(); i++)
  96.     {
  97.         VkImageView attachments[] =
  98.         {
  99.             m_swapChainImageViews[i]
  100.         };
  101.  
  102.         VkFramebufferCreateInfo framebufferInfo = {};
  103.         framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  104.         framebufferInfo.renderPass = m_renderPass;
  105.         framebufferInfo.attachmentCount = 1;
  106.         framebufferInfo.pAttachments = attachments;
  107.         framebufferInfo.width = m_swapChainExtent.width;
  108.         framebufferInfo.height = m_swapChainExtent.height;
  109.         framebufferInfo.layers = 1;
  110.  
  111.         VkResult result = vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_swapChainFramebuffers[i]);
  112.         if (result != VK_SUCCESS)
  113.             throw std::runtime_error("Failed to create framebuffer!");
  114.     }
  115.  
  116. #ifndef NDEBUG
  117.     if (!m_recreatingSwapChain)
  118.         spdlog::info("Successfully created framebuffers.");
  119. #endif
  120. }
  121.  
  122. void Application::createVertexBuffers()
  123. {
  124.     VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
  125.     VkBuffer stagingBuffer;
  126.     VkDeviceMemory stagingBufferMemory;
  127.  
  128.     createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
  129.  
  130.     void* data;
  131.     vkMapMemory(m_device, stagingBufferMemory, 0, bufferSize, 0, &data);
  132.     memcpy(data, vertices.data(), (size_t)bufferSize);
  133.     vkUnmapMemory(m_device, stagingBufferMemory);
  134.  
  135.     createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_vertexBuffer, m_vertexBufferMemory);
  136.     copyBuffer(stagingBuffer, m_vertexBuffer, bufferSize);
  137.  
  138.     vkDestroyBuffer(m_device, stagingBuffer, nullptr);
  139.     vkFreeMemory(m_device, stagingBufferMemory, nullptr);
  140.  
  141. #ifndef NDEBUG
  142.     spdlog::info("Successfully created vertex buffer.");
  143. #endif
  144. }
  145.  
  146. void Application::createIndexBuffer()
  147. {
  148.     VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
  149.     VkBuffer stagingBuffer;
  150.     VkDeviceMemory stagingBufferMemory;
  151.  
  152.     createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
  153.  
  154.     void* data;
  155.     vkMapMemory(m_device, stagingBufferMemory, 0, bufferSize, 0, &data);
  156.     memcpy(data, indices.data(), (size_t)bufferSize);
  157.     vkUnmapMemory(m_device, stagingBufferMemory);
  158.  
  159.     createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, m_indexBuffer, m_indexBufferMemory);
  160.  
  161.     copyBuffer(stagingBuffer, m_indexBuffer, bufferSize);
  162.  
  163.     vkDestroyBuffer(m_device, stagingBuffer, nullptr);
  164.     vkFreeMemory(m_device, stagingBufferMemory, nullptr);
  165.  
  166. #ifndef NDEBUG
  167.     spdlog::info("Successfully created index buffer.");
  168. #endif
  169. }
  170.  
  171. void Application::createUniformBuffers()
  172. {
  173.     VkDeviceSize bufferSize = sizeof(UniformBufferObject);
  174.  
  175.     m_uniformBuffers.resize(m_swapChainImages.size());
  176.     m_uniformBuffersMemory.resize(m_swapChainImages.size());
  177.  
  178.     for (size_t i = 0; i < m_swapChainImages.size(); i++)
  179.     {
  180.         createBuffer(
  181.             bufferSize,
  182.             VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
  183.             VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  184.             VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  185.             m_uniformBuffers[i],
  186.             m_uniformBuffersMemory[i]
  187.         );
  188.     }
  189. }
  190.  
  191. void Application::updateUniformBuffers(uint32_t currentImage)
  192. {
  193.     static auto startTime = std::chrono::high_resolution_clock::now();
  194.  
  195.     auto currentTime = std::chrono::high_resolution_clock::now();
  196.     float time = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - startTime).count();
  197.  
  198.     UniformBufferObject ubo = {};
  199.     ubo.model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
  200.     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));
  201.     ubo.proj = glm::perspective(glm::radians(45.0f), m_swapChainExtent.width / (float)m_swapChainExtent.height, 0.1f, 10.0f);
  202.  
  203.     // Flip the Y-axis coordinates, because glm is designed for OpenGL
  204.     ubo.proj[1][1] *= -1;
  205.  
  206.     void* data;
  207.     vkMapMemory(m_device, m_uniformBuffersMemory[currentImage], 0, sizeof(ubo), 0, &data);
  208.     memcpy(data, &ubo, sizeof(ubo));
  209.     vkUnmapMemory(m_device, m_uniformBuffersMemory[currentImage]);
  210. }
  211.  
  212. void Application::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory)
  213. {
  214.     VkBufferCreateInfo bufferInfo = {};
  215.     bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  216.     bufferInfo.size = size;
  217.     bufferInfo.usage = usage;
  218.     bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  219.  
  220.     VkResult result = vkCreateBuffer(m_device, &bufferInfo, nullptr, &buffer);
  221.     if (result != VK_SUCCESS)
  222.         throw std::runtime_error("Failed to create buffer!");
  223.  
  224.     VkMemoryRequirements memRequirements;
  225.     vkGetBufferMemoryRequirements(m_device, buffer, &memRequirements);
  226.  
  227.     VkMemoryAllocateInfo allocInfo = {};
  228.     allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  229.     allocInfo.allocationSize = memRequirements.size;
  230.     allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
  231.  
  232.     if (vkAllocateMemory(m_device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS)
  233.         throw std::runtime_error("Failed to allocate buffer memory");
  234.  
  235.     vkBindBufferMemory(m_device, buffer, bufferMemory, 0);
  236. }
  237.  
  238. void Application::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
  239. {
  240.     VkCommandBufferAllocateInfo allocInfo = {};
  241.     allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  242.     allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  243.     allocInfo.commandPool = m_tempCommandPool;
  244.     allocInfo.commandBufferCount = 1;
  245.  
  246.     VkCommandBuffer commandBuffer;
  247.     vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer);
  248.  
  249.     VkCommandBufferBeginInfo beginInfo = {};
  250.     beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  251.     beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  252.  
  253.     vkBeginCommandBuffer(commandBuffer, &beginInfo);
  254.  
  255.     VkBufferCopy copyRegion = {};
  256.     copyRegion.srcOffset = 0;
  257.     copyRegion.dstOffset = 0;
  258.     copyRegion.size = size;
  259.     vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
  260.  
  261.     vkEndCommandBuffer(commandBuffer);
  262.  
  263.     VkSubmitInfo submitInfo = {};
  264.     submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  265.     submitInfo.commandBufferCount = 1;
  266.     submitInfo.pCommandBuffers = &commandBuffer;
  267.  
  268.     vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
  269.     vkQueueWaitIdle(m_graphicsQueue);
  270.  
  271.     vkFreeCommandBuffers(m_device, m_tempCommandPool, 1, &commandBuffer);
  272. }
  273.  
  274. uint32_t Application::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
  275. {
  276.     VkPhysicalDeviceMemoryProperties memProperties;
  277.     vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memProperties);
  278.  
  279.     for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
  280.     {
  281.         if (typeFilter & (1 << i) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
  282.             return i;
  283.     }
  284.  
  285.     throw std::runtime_error("Failed to find suitable memory type!");
  286. }
  287.  
  288. // *************************************************************
  289. // ***************  Swapchain           ************************
  290. // *************************************************************
  291.  
  292. void Application::createSwapChain()
  293. {
  294.     SwapChainSupportDetails swapChainSupport = querySwapChainSupport(m_physicalDevice);
  295.  
  296.     VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
  297.     VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
  298.     VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
  299.  
  300.     uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
  301.  
  302.     if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
  303.         imageCount = swapChainSupport.capabilities.maxImageCount;
  304.  
  305.     VkSwapchainCreateInfoKHR createInfo = {};
  306.     createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  307.     createInfo.surface = m_surface;
  308.     createInfo.minImageCount = imageCount;
  309.     createInfo.imageFormat = surfaceFormat.format;
  310.     createInfo.imageColorSpace = surfaceFormat.colorSpace;
  311.     createInfo.imageExtent = extent;
  312.     createInfo.imageArrayLayers = 1;
  313.     createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  314.  
  315.     uint32_t queueFamilyIndices[] = { m_indices.graphicsFamily.value(), m_indices.presentFamily.value() };
  316.  
  317.     if (m_indices.graphicsFamily != m_indices.presentFamily)
  318.     {
  319.         createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  320.         createInfo.queueFamilyIndexCount = 2;
  321.         createInfo.pQueueFamilyIndices = queueFamilyIndices;
  322.     }
  323.     else
  324.     {
  325.         createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  326.         createInfo.queueFamilyIndexCount = 0;
  327.         createInfo.pQueueFamilyIndices = nullptr;
  328.     }
  329.  
  330.     createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
  331.     createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  332.     createInfo.presentMode = presentMode;
  333.     createInfo.clipped = VK_TRUE;
  334.     createInfo.oldSwapchain = VK_NULL_HANDLE;
  335.  
  336.     VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapChain);
  337.     if (result != VK_SUCCESS)
  338.         throw std::runtime_error("Failed to create swapchain!");
  339.  
  340.     vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, nullptr);
  341.     m_swapChainImages.resize(imageCount);
  342.     vkGetSwapchainImagesKHR(m_device, m_swapChain, &imageCount, m_swapChainImages.data());
  343.  
  344.     m_swapChainImageFormat = surfaceFormat.format;
  345.     m_swapChainExtent = extent;
  346.  
  347. #ifndef NDEBUG
  348.     if (!m_recreatingSwapChain)
  349.         spdlog::info("Successfully created swapchain.");
  350. #endif
  351. }
  352.  
  353. void Application::cleanupSwapChain()
  354. {
  355.     // Framebuffers
  356.     for (auto framebuffer : m_swapChainFramebuffers)
  357.         vkDestroyFramebuffer(m_device, framebuffer, nullptr);
  358.  
  359.     // Command buffers
  360.     vkFreeCommandBuffers(m_device, m_commandPool, static_cast<uint32_t>(m_commandBuffers.size()), m_commandBuffers.data());
  361.  
  362.     // Graphics pipeline
  363.     vkDestroyPipeline(m_device, m_graphicsPipeline, nullptr);
  364.     vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr);
  365.     vkDestroyRenderPass(m_device, m_renderPass, nullptr);
  366.  
  367.     // Image views
  368.     for (auto imageView : m_swapChainImageViews)
  369.         vkDestroyImageView(m_device, imageView, nullptr);
  370.  
  371.     // Swapchain
  372.     vkDestroySwapchainKHR(m_device, m_swapChain, nullptr);
  373. }
  374.  
  375. void Application::recreateSwapChain()
  376. {
  377.     m_recreatingSwapChain = true;
  378.  
  379.     while (m_framebufferWidth == 0 || m_framebufferHeight == 0)
  380.     {
  381.         glfwGetFramebufferSize(m_window, &m_framebufferWidth, &m_framebufferHeight);
  382.         glfwWaitEvents();
  383.     }
  384.  
  385.     vkDeviceWaitIdle(m_device);
  386.  
  387.     cleanupSwapChain();
  388.  
  389.     createSwapChain();
  390.     createImageViews();
  391.     createRenderPass();
  392.     createGraphicsPipeline();
  393.     createFramebuffers();
  394.     createCommandBuffers();
  395.  
  396.     m_recreatingSwapChain = false;
  397. }
  398.  
  399. SwapChainSupportDetails Application::querySwapChainSupport(VkPhysicalDevice device)
  400. {
  401.     SwapChainSupportDetails details;
  402.  
  403.     vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_surface, &details.capabilities);
  404.  
  405.     uint32_t formatCount;
  406.     vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, nullptr);
  407.  
  408.     if (formatCount != 0)
  409.     {
  410.         details.formats.resize(formatCount);
  411.         vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_surface, &formatCount, details.formats.data());
  412.     }
  413.  
  414.     uint32_t presentModeCount;
  415.     vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, nullptr);
  416.  
  417.     if (presentModeCount != 0)
  418.     {
  419.         details.presentModes.resize(presentModeCount);
  420.         vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_surface, &presentModeCount, details.presentModes.data());
  421.     }
  422.  
  423.     return details;
  424. }
  425.  
  426. VkSurfaceFormatKHR Application::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
  427. {
  428.     if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED)
  429.         return { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
  430.  
  431.     for (const auto& availableFormat : availableFormats)
  432.     {
  433.         if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
  434.             return availableFormat;
  435.     }
  436.  
  437.     return availableFormats[0];
  438. }
  439.  
  440. VkPresentModeKHR Application::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes)
  441. {
  442.     VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR;
  443.  
  444.     for (const auto& availablePresentMode : availablePresentModes)
  445.     {
  446.         if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
  447.             return availablePresentMode;
  448.         else if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR)
  449.             bestMode = availablePresentMode;
  450.     }
  451.  
  452.     return bestMode;
  453. }
  454.  
  455. VkExtent2D Application::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities)
  456. {
  457.     if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
  458.         return capabilities.currentExtent;
  459.     else
  460.     {
  461.         int width, height;
  462.         glfwGetFramebufferSize(m_window, &width, &height);
  463.  
  464.         VkExtent2D actualExtent =
  465.         {
  466.             static_cast<uint32_t>(width),
  467.             static_cast<uint32_t>(height)
  468.         };
  469.  
  470.         return actualExtent;
  471.     }
  472. }
  473.  
  474. // *************************************************************
  475. // ***************  Instance            ************************
  476. // *************************************************************
  477.  
  478. void Application::createInstance()
  479. {
  480.     if (enableValidationLayers && !checkValidationLayerSupport())
  481.         throw std::runtime_error("Validation layers requested, but not available!");
  482.  
  483.     // Application Info
  484.     VkApplicationInfo appInfo = {};
  485.     appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  486.     appInfo.pApplicationName = "Volcanic Engine";
  487.     appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
  488.     appInfo.pEngineName = "Volcanic Engine";
  489.     appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
  490.     appInfo.apiVersion = VK_API_VERSION_1_0;
  491.  
  492.     // Instance Create Info
  493.     VkInstanceCreateInfo createInfo = {};
  494.     createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  495.     createInfo.pApplicationInfo = &appInfo;
  496.  
  497.     auto requiredExtensions = getRequiredExtensions();
  498.     createInfo.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size());
  499.     createInfo.ppEnabledExtensionNames = requiredExtensions.data();
  500.  
  501.     if (enableValidationLayers)
  502.     {
  503.         createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  504.         createInfo.ppEnabledLayerNames = validationLayers.data();
  505.     }
  506.     else
  507.     {
  508.         createInfo.enabledLayerCount = 0;
  509.     }
  510.  
  511.     VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
  512.     if (result != VK_SUCCESS)
  513.         throw std::runtime_error("Failed to create instance!");
  514.  
  515.     uint32_t extensionCount;
  516.     vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
  517.  
  518.     std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  519.     vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, availableExtensions.data());
  520.  
  521. #if LOGEXTENSIONS
  522.     std::cout << "Available extensions" << std::endl;
  523.  
  524.     for (const auto& extension : availableExtensions)
  525.         std::cout << "\t" << extension.extensionName << std::endl;
  526. #endif
  527.  
  528.     if (requiredExtensionsAvailable(requiredExtensions, availableExtensions))
  529.     {
  530. #ifndef NDEBUG
  531.         spdlog::info("All required extensions available.");
  532. #endif
  533.     }
  534.     else
  535.         spdlog::error("Not all required extensions are available!");
  536.  
  537. #ifndef NDEBUG
  538.     spdlog::info("Successfully created instance.");
  539. #endif
  540. }
  541.  
  542. bool Application::checkValidationLayerSupport()
  543. {
  544.     uint32_t layerCount;
  545.     vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
  546.  
  547.     std::vector<VkLayerProperties> availableLayers(layerCount);
  548.     vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
  549.  
  550.     for (const char* layerName : validationLayers)
  551.     {
  552.         bool layerFound;
  553.  
  554.         for (const auto& layerProperties : availableLayers)
  555.         {
  556.             if (strcmp(layerName, layerProperties.layerName) == 0)
  557.             {
  558.                 layerFound = true;
  559.                 break;
  560.             }
  561.         }
  562.  
  563.         if (!layerFound)
  564.             return false;
  565.     }
  566.  
  567.     return true;
  568. }
  569.  
  570. std::vector<const char*> Application::getRequiredExtensions()
  571. {
  572.     uint32_t glfwExtensionCount = 0;
  573.     const char** glfwExtensions;
  574.     glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
  575.  
  576.     std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
  577.  
  578.     if (enableValidationLayers)
  579.         extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  580.  
  581. #if LOGEXTENSIONS
  582.     std::cout << "Required extensions:" << std::endl;
  583.     for (const auto& extension : extensions)
  584.         std::cout << "\t" << extension << std::endl;
  585. #endif
  586.  
  587.     return extensions;
  588. }
  589.  
  590. bool requiredExtensionsAvailable(std::vector<const char*> requiredExtensions, std::vector<VkExtensionProperties> availableExtensions)
  591. {
  592.     for (const char* requiredExtension : requiredExtensions)
  593.     {
  594.         bool found = false;
  595.  
  596.         for (const auto& availableExtension : availableExtensions)
  597.         {
  598.             if (strcmp(requiredExtension, availableExtension.extensionName))
  599.                 found = true;
  600.         }
  601.  
  602.         if (!found)
  603.             return false;
  604.     }
  605.     return true;
  606. }
  607.  
  608. // *************************************************************
  609. // ***************  Surface             ************************
  610. // *************************************************************
  611.  
  612. void Application::createSurface()
  613. {
  614.     VkResult result = glfwCreateWindowSurface(m_instance, m_window, nullptr, &m_surface);
  615.     if (result != VK_SUCCESS)
  616.         throw std::runtime_error("Failed to create window surface!");
  617. #ifndef NDEBUG
  618.     spdlog::info("Successfully created window surface.");
  619. #endif
  620. }
  621.  
  622. void Application::createImageViews()
  623. {
  624.     m_swapChainImageViews.resize(m_swapChainImages.size());
  625.  
  626.     for (size_t i = 0; i < m_swapChainImages.size(); i++)
  627.     {
  628.         VkImageViewCreateInfo createInfo = {};
  629.         createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  630.         createInfo.image = m_swapChainImages[i];
  631.         createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  632.         createInfo.format = m_swapChainImageFormat;
  633.  
  634.         createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  635.         createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  636.         createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  637.         createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  638.  
  639.         createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  640.         createInfo.subresourceRange.baseMipLevel = 0;
  641.         createInfo.subresourceRange.levelCount = 1;
  642.         createInfo.subresourceRange.baseArrayLayer = 0;
  643.         createInfo.subresourceRange.layerCount = 1;
  644.  
  645.         VkResult result = vkCreateImageView(m_device, &createInfo, nullptr, &m_swapChainImageViews[i]);
  646.         if (result != VK_SUCCESS)
  647.             throw std::runtime_error("Failed to create image views!");
  648.     }
  649.  
  650. #ifndef NDEBUG
  651.     if (!m_recreatingSwapChain)
  652.         spdlog::info("Successfully created image views.");
  653. #endif
  654. }
  655.  
  656. // *************************************************************
  657. // ***************  Pipeline            ************************
  658. // *************************************************************
  659.  
  660. void Application::createRenderPass()
  661. {
  662.     VkAttachmentDescription colorAttachment = {};
  663.     colorAttachment.format = m_swapChainImageFormat;
  664.     colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
  665.     colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  666.     colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  667.     colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  668.     colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  669.     colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  670.     colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  671.  
  672.     VkAttachmentReference colorAttachmentRef = {};
  673.     colorAttachmentRef.attachment = 0;
  674.     colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  675.  
  676.     VkSubpassDescription subpass = {};
  677.     subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  678.     subpass.colorAttachmentCount = 1;
  679.     subpass.pColorAttachments = &colorAttachmentRef;
  680.  
  681.     VkSubpassDependency dependency = {};
  682.     dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  683.     dependency.dstSubpass = 0;
  684.     dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  685.     dependency.srcAccessMask = 0;
  686.     dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  687.     dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
  688.         | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  689.  
  690.     VkRenderPassCreateInfo renderPassInfo = {};
  691.     renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  692.     renderPassInfo.attachmentCount = 1;
  693.     renderPassInfo.pAttachments = &colorAttachment;
  694.     renderPassInfo.subpassCount = 1;
  695.     renderPassInfo.pSubpasses = &subpass;
  696.     renderPassInfo.dependencyCount = 1;
  697.     renderPassInfo.pDependencies = &dependency;
  698.  
  699.     VkResult result = vkCreateRenderPass(m_device, &renderPassInfo, nullptr, &m_renderPass);
  700.     if (result != VK_SUCCESS)
  701.         throw std::runtime_error("Failed to create render pass!");
  702.  
  703. #ifndef NDEBUG
  704.     if (!m_recreatingSwapChain)
  705.         spdlog::info("Successfully created render pass.");
  706. #endif
  707. }
  708.  
  709. void Application::compileShaders(const char* vertPath, const char* fragPath)
  710. {
  711.     // TODO: Automatically compile shaders.
  712. }
  713.  
  714. void Application::createGraphicsPipeline()
  715. {
  716.     std::vector<char> vertShaderCode = readFile("shaders/vert.spv");
  717.     std::vector<char> fragShaderCode = readFile("shaders/frag.spv");
  718.  
  719.     VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
  720.     VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
  721.  
  722.     std::vector<char>().swap(vertShaderCode);
  723.     std::vector<char>().swap(fragShaderCode);
  724.  
  725.     VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
  726.     vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  727.     vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
  728.     vertShaderStageInfo.module = vertShaderModule;
  729.     vertShaderStageInfo.pName = "main";
  730.  
  731.     VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
  732.     fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  733.     fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  734.     fragShaderStageInfo.module = fragShaderModule;
  735.     fragShaderStageInfo.pName = "main";
  736.  
  737.     VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
  738.  
  739.     // Get vertex data
  740.     auto bindingDescription = Vertex::getBindingDescription();
  741.     auto attributeDescriptions = Vertex::getAttributeDescriptions();
  742.  
  743.     VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
  744.     vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  745.     vertexInputInfo.vertexBindingDescriptionCount = 1;
  746.     vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
  747.     vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
  748.     vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
  749.  
  750.     // Set vertex input assembly to draw a triangle from every 3 vertices without reuse
  751.     VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
  752.     inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  753.     inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  754.     inputAssembly.primitiveRestartEnable = VK_FALSE;
  755.  
  756.     // The viewport specifies what region of the framebuffer to render to.
  757.     VkViewport viewport = {};
  758.     viewport.x = 0.0f;
  759.     viewport.y = 0.0f;
  760.     viewport.width = (float)m_swapChainExtent.width;
  761.     viewport.height = (float)m_swapChainExtent.height;
  762.     viewport.minDepth = 0.0f;
  763.     viewport.maxDepth = 1.0f;
  764.  
  765.     // Scissor around the entire framebuffer
  766.     VkRect2D scissor = {};
  767.     scissor.offset = { 0, 0 };
  768.     scissor.extent = m_swapChainExtent;
  769.  
  770.     VkPipelineViewportStateCreateInfo viewportState = {};
  771.     viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  772.     viewportState.viewportCount = 1;
  773.     viewportState.pViewports = &viewport;
  774.     viewportState.scissorCount = 1;
  775.     viewportState.pScissors = &scissor;
  776.  
  777.     VkPipelineRasterizationStateCreateInfo rasterizer = {};
  778.     rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  779.     rasterizer.depthClampEnable = VK_FALSE;
  780.     rasterizer.rasterizerDiscardEnable = VK_FALSE;
  781.     rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
  782.     rasterizer.lineWidth = 1.0f;
  783.     rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
  784.     rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
  785.     rasterizer.depthBiasEnable = VK_FALSE;
  786.     rasterizer.depthBiasConstantFactor = 0.0f;
  787.     rasterizer.depthBiasClamp = 0.0f;
  788.     rasterizer.depthBiasSlopeFactor = 0.0f;
  789.  
  790.     // For anti-aliasing
  791.     VkPipelineMultisampleStateCreateInfo multisampling = {};
  792.     multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  793.     multisampling.sampleShadingEnable = VK_FALSE;
  794.     multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  795.     multisampling.minSampleShading = 1.0f;
  796.     multisampling.pSampleMask = nullptr;
  797.     multisampling.alphaToCoverageEnable = VK_FALSE;
  798.     multisampling.alphaToOneEnable = VK_FALSE;
  799.  
  800.     VkPipelineColorBlendAttachmentState colorBlendAttachment = {};
  801.     colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT
  802.         | VK_COLOR_COMPONENT_G_BIT
  803.         | VK_COLOR_COMPONENT_B_BIT
  804.         | VK_COLOR_COMPONENT_A_BIT;
  805.     colorBlendAttachment.blendEnable = VK_FALSE;
  806.     colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
  807.     colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
  808.     colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
  809.     colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
  810.     colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
  811.     colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
  812.  
  813.     VkPipelineColorBlendStateCreateInfo colorBlending = {};
  814.     colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  815.     colorBlending.logicOpEnable = VK_FALSE;
  816.     colorBlending.logicOp = VK_LOGIC_OP_COPY;
  817.     colorBlending.attachmentCount = 1;
  818.     colorBlending.pAttachments = &colorBlendAttachment;
  819.     colorBlending.blendConstants[0] = 0.0f;
  820.     colorBlending.blendConstants[1] = 0.0f;
  821.     colorBlending.blendConstants[2] = 0.0f;
  822.     colorBlending.blendConstants[3] = 0.0f;
  823.  
  824.     VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
  825.     pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  826.     pipelineLayoutInfo.setLayoutCount = 1;
  827.     pipelineLayoutInfo.pSetLayouts = &m_descriptorSetLayout;
  828.     pipelineLayoutInfo.pushConstantRangeCount = 0;
  829.     pipelineLayoutInfo.pPushConstantRanges = nullptr;
  830.  
  831.     VkResult result = vkCreatePipelineLayout(m_device, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
  832.     if (result != VK_SUCCESS)
  833.         throw std::runtime_error("Failed to create pipeline layout!");
  834.  
  835. #ifndef NDEBUG
  836.     if (!m_recreatingSwapChain)
  837.         spdlog::info("Successfully created pipeline layout.");
  838. #endif
  839.  
  840.     VkGraphicsPipelineCreateInfo pipelineInfo = {};
  841.     pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  842.     pipelineInfo.stageCount = 2;
  843.     pipelineInfo.pStages = shaderStages;
  844.     pipelineInfo.pVertexInputState = &vertexInputInfo;
  845.     pipelineInfo.pInputAssemblyState = &inputAssembly;
  846.     pipelineInfo.pViewportState = &viewportState;
  847.     pipelineInfo.pRasterizationState = &rasterizer;
  848.     pipelineInfo.pMultisampleState = &multisampling;
  849.     pipelineInfo.pDepthStencilState = nullptr;
  850.     pipelineInfo.pColorBlendState = &colorBlending;
  851.     pipelineInfo.pDynamicState = nullptr;
  852.     pipelineInfo.layout = m_pipelineLayout;
  853.     pipelineInfo.renderPass = m_renderPass;
  854.     pipelineInfo.subpass = 0;
  855.     pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  856.     pipelineInfo.basePipelineIndex = -1;
  857.  
  858.     result = vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &m_graphicsPipeline);
  859.     if (result != VK_SUCCESS)
  860.         throw std::runtime_error("Failed to create graphics pipeline!");
  861.  
  862. #ifndef NDEBUG
  863.     if (!m_recreatingSwapChain)
  864.         spdlog::info("Successfully created graphics pipeline.");
  865. #endif
  866.  
  867.     vkDestroyShaderModule(m_device, vertShaderModule, nullptr);
  868.     vkDestroyShaderModule(m_device, fragShaderModule, nullptr);
  869. }
  870.  
  871. VkShaderModule Application::createShaderModule(const std::vector<char>& code)
  872. {
  873.     VkShaderModuleCreateInfo createInfo = {};
  874.     createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  875.     createInfo.codeSize = code.size();
  876.     createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
  877.  
  878.     VkShaderModule shaderModule;
  879.     VkResult result = vkCreateShaderModule(m_device, &createInfo, nullptr, &shaderModule);
  880.     if (result != VK_SUCCESS)
  881.         throw std::runtime_error("Failed to create shader module!");
  882.  
  883. #ifndef NDEBUG
  884.     if (!m_recreatingSwapChain)
  885.         spdlog::info("Successfully created shader module.");
  886. #endif
  887.  
  888.     return shaderModule;
  889. }
  890.  
  891. // *************************************************************
  892. // ***************  Commands            ************************
  893. // *************************************************************
  894.  
  895. void Application::createCommandPools()
  896. {
  897.     VkCommandPoolCreateInfo poolInfo = {};
  898.     poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  899.     poolInfo.queueFamilyIndex = m_indices.graphicsFamily.value();
  900.     poolInfo.flags = 0;
  901.  
  902.     VkCommandPoolCreateInfo tempPoolInfo = {};
  903.     tempPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  904.     tempPoolInfo.queueFamilyIndex = m_indices.graphicsFamily.value();
  905.     tempPoolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
  906.  
  907.     VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool);
  908.     if (result != VK_SUCCESS)
  909.         throw std::runtime_error("Failed to create command pool!");
  910.  
  911.     result = vkCreateCommandPool(m_device, &tempPoolInfo, nullptr, &m_tempCommandPool);
  912.     if (result != VK_SUCCESS)
  913.         throw std::runtime_error("Failed to create temp command pool!");
  914.  
  915. #ifndef NDEBUG
  916.     spdlog::info("Successfully created command pools.");
  917. #endif
  918. }
  919.  
  920. void Application::createCommandBuffers()
  921. {
  922.     m_commandBuffers.resize(m_swapChainFramebuffers.size());
  923.  
  924.     VkCommandBufferAllocateInfo allocInfo = {};
  925.     allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  926.     allocInfo.commandPool = m_commandPool;
  927.     allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  928.     allocInfo.commandBufferCount = (uint32_t)m_commandBuffers.size();
  929.  
  930.     VkResult result = vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data());
  931.     if (result != VK_SUCCESS)
  932.         throw std::runtime_error("Failed to begin allocate command buffers!");
  933.  
  934. #ifndef NDEBUG
  935.     if (!m_recreatingSwapChain)
  936.         spdlog::info("Successfully allocated command buffers.");
  937. #endif
  938.  
  939.     for (size_t i = 0; i < m_commandBuffers.size(); i++)
  940.     {
  941.         VkCommandBufferBeginInfo beginInfo = {};
  942.         beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  943.         beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
  944.         beginInfo.pInheritanceInfo = nullptr;
  945.  
  946.         result = vkBeginCommandBuffer(m_commandBuffers[i], &beginInfo);
  947.         if (result != VK_SUCCESS)
  948.             throw std::runtime_error("Failed to begin recording command buffer!");
  949.  
  950.         VkClearValue clearColor = { 0.0f, 0.0f, 0.0f, 1.0f };
  951.  
  952.         VkRenderPassBeginInfo renderPassInfo = {};
  953.         renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  954.         renderPassInfo.renderPass = m_renderPass;
  955.         renderPassInfo.framebuffer = m_swapChainFramebuffers[i];
  956.         renderPassInfo.renderArea.offset = { 0, 0 };
  957.         renderPassInfo.renderArea.extent = m_swapChainExtent;
  958.         renderPassInfo.clearValueCount = 1;
  959.         renderPassInfo.pClearValues = &clearColor;
  960.  
  961.         vkCmdBeginRenderPass(m_commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
  962.         vkCmdBindPipeline(m_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline);
  963.  
  964.         VkBuffer vertexBuffers[] = { m_vertexBuffer };
  965.         VkDeviceSize offsets[] = { 0 };
  966.  
  967.         vkCmdBindVertexBuffers(m_commandBuffers[i], 0, 1, vertexBuffers, offsets);
  968.         vkCmdBindIndexBuffer(m_commandBuffers[i], m_indexBuffer, 0, VK_INDEX_TYPE_UINT16);
  969.         vkCmdBindDescriptorSets(m_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, &m_descriptorSets[i], 0, nullptr);
  970.  
  971.         vkCmdDrawIndexed(m_commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
  972.  
  973.         vkCmdEndRenderPass(m_commandBuffers[i]);
  974.  
  975.         VkResult result = vkEndCommandBuffer(m_commandBuffers[i]);
  976.         if (result != VK_SUCCESS)
  977.             throw std::runtime_error("Failed to record command buffer!");
  978.  
  979.     }
  980. #ifndef NDEBUG
  981.     if (!m_recreatingSwapChain)
  982.         spdlog::info("Successfully recorded command buffers.");
  983. #endif
  984. }
  985.  
  986. void Application::createSyncObjects()
  987. {
  988.     m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  989.     m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  990.     m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
  991.  
  992.     VkSemaphoreCreateInfo semaphoreInfo = {};
  993.     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  994.  
  995.     VkFenceCreateInfo fenceInfo = {};
  996.     fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  997.     fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  998.  
  999.     for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  1000.     {
  1001.         VkResult result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]);
  1002.         if (result != VK_SUCCESS)
  1003.             throw std::runtime_error("Failed to create imageavailable semaphore for a frame!");
  1004.  
  1005.         result = vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]);
  1006.         if (result != VK_SUCCESS)
  1007.             throw std::runtime_error("Failed to create renderfinished semaphore for a frame!");
  1008.  
  1009.         result = vkCreateFence(m_device, &fenceInfo, nullptr, &m_inFlightFences[i]);
  1010.         if (result != VK_SUCCESS)
  1011.             throw std::runtime_error("Failed to create fence for a frame!");
  1012.     }
  1013. #ifndef NDEBUG
  1014.     spdlog::info("Successfully created sync objects.");
  1015. #endif
  1016. }
  1017.  
  1018. // *************************************************************
  1019. // ***************  Device creations    ************************
  1020. // *************************************************************
  1021.  
  1022.  
  1023. void Application::pickPhysicalDevice()
  1024. {
  1025.     uint32_t deviceCount = 0;
  1026.     vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
  1027.  
  1028.     if (deviceCount == 0)
  1029.         throw std::runtime_error("Failed to find GPUs with Vulkan support!");
  1030.  
  1031.     std::vector<VkPhysicalDevice> devices(deviceCount);
  1032.     vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
  1033.  
  1034. #if MANUALPHYSICALDEVICE
  1035.     // Let the user pick the device
  1036.     std::cout << std::endl << "Pick a device:" << std::endl;
  1037.     int i = 0;
  1038.     for (const auto& device : devices)
  1039.     {
  1040.         VkPhysicalDeviceProperties deviceProperties;
  1041.         vkGetPhysicalDeviceProperties(device, &deviceProperties);
  1042.  
  1043.         std::cout << i + 1 << ". " << deviceProperties.deviceName << std::endl;
  1044.         i++;
  1045.     }
  1046.  
  1047.     int picked;
  1048.     std::cin >> picked;
  1049.     while (!isDeviceSuitable(devices.at(picked - 1)))
  1050.         throw std::runtime_error("The picked device is not suitable!");
  1051.     m_physicalDevice = devices.at(picked - 1);
  1052. #else
  1053.     // Automatically pick the first device
  1054.     if (isDeviceSuitable(devices.at(0)))
  1055.         m_physicalDevice = devices.at(0);
  1056.     else
  1057.         throw std::runtime_error("The automatically picked device is not suitable!");
  1058. #endif
  1059.  
  1060.     if (m_physicalDevice == VK_NULL_HANDLE)
  1061.         throw std::runtime_error("None of the found GPUs were suitable!");
  1062.  
  1063.     m_indices = findQueueFamilies(m_physicalDevice);
  1064.  
  1065. #ifndef NDEBUG
  1066.     VkPhysicalDeviceProperties deviceProperties;
  1067.     vkGetPhysicalDeviceProperties(m_physicalDevice, &deviceProperties);
  1068.     spdlog::info("Successfully picked physical device: {}", deviceProperties.deviceName);
  1069. #endif
  1070. }
  1071.  
  1072. void Application::createLogicalDevice()
  1073. {
  1074.     // Info for specified queue families
  1075.  
  1076.     std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  1077.     std::set<uint32_t> uniqueQueueFamilies = { m_indices.graphicsFamily.value(), m_indices.presentFamily.value() };
  1078.  
  1079.     float queuePriority = 1.0f;
  1080.     for (uint32_t queueFamily : uniqueQueueFamilies)
  1081.     {
  1082.         VkDeviceQueueCreateInfo queueCreateInfo = {};
  1083.         queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  1084.         queueCreateInfo.queueFamilyIndex = queueFamily;
  1085.         queueCreateInfo.queueCount = 1;
  1086.         queueCreateInfo.pQueuePriorities = &queuePriority;
  1087.         queueCreateInfos.push_back(queueCreateInfo);
  1088.     }
  1089.  
  1090.     // All features set to VK_FALSE
  1091.     VkPhysicalDeviceFeatures deviceFeatures = {};
  1092.  
  1093.     // Info for creating logical device
  1094.     VkDeviceCreateInfo createInfo = {};
  1095.     createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  1096.     createInfo.pQueueCreateInfos = queueCreateInfos.data();
  1097.     createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
  1098.     createInfo.pEnabledFeatures = &deviceFeatures;
  1099.     createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
  1100.     createInfo.ppEnabledExtensionNames = deviceExtensions.data();
  1101.  
  1102.     if (enableValidationLayers)
  1103.     {
  1104.         createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  1105.         createInfo.ppEnabledLayerNames = validationLayers.data();
  1106.     }
  1107.     else
  1108.         createInfo.enabledLayerCount = 0;
  1109.  
  1110.     // Create logical device
  1111.     VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
  1112.     // Throw if failed
  1113.     if (result != VK_SUCCESS)
  1114.         throw std::runtime_error("Failed to create logical device!");
  1115.  
  1116.     // Create handle for interaction with the graphics queue
  1117.     vkGetDeviceQueue(m_device, m_indices.graphicsFamily.value(), 0, &m_graphicsQueue);
  1118.     vkGetDeviceQueue(m_device, m_indices.presentFamily.value(), 0, &m_presentQueue);
  1119.  
  1120. #ifndef NDEBUG
  1121.     spdlog::info("Successfully created logical device.");
  1122. #endif
  1123. }
  1124.  
  1125. bool Application::isDeviceSuitable(VkPhysicalDevice device)
  1126. {
  1127.     QueueFamilyIndices indices = findQueueFamilies(device);
  1128.  
  1129.     bool extensionsSupported = checkDeviceExtensionSupport(device);
  1130.  
  1131.     bool swapChainAdequate = false;
  1132.     if (extensionsSupported)
  1133.     {
  1134.         SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);
  1135.         swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
  1136.     }
  1137.  
  1138.     return indices.isComplete() && extensionsSupported && swapChainAdequate;
  1139. }
  1140.  
  1141. bool Application::checkDeviceExtensionSupport(VkPhysicalDevice device)
  1142. {
  1143.     uint32_t extensionCount;
  1144.     vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
  1145.  
  1146.     std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  1147.     vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
  1148.  
  1149.     return requiredExtensionsAvailable(deviceExtensions, availableExtensions);
  1150. }
  1151.  
  1152. QueueFamilyIndices Application::findQueueFamilies(VkPhysicalDevice device)
  1153. {
  1154.     QueueFamilyIndices indices;
  1155.  
  1156.     uint32_t queueFamilyCount = 0;
  1157.     vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
  1158.  
  1159.     std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
  1160.     vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
  1161.  
  1162.     int i = 0;
  1163.     for (const auto& queueFamily : queueFamilies)
  1164.     {
  1165.         if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
  1166.             indices.graphicsFamily = i;
  1167.  
  1168.         VkBool32 presentSupport = false;
  1169.         vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_surface, &presentSupport);
  1170.  
  1171.         if (queueFamily.queueCount > 0 && presentSupport)
  1172.             indices.presentFamily = i;
  1173.  
  1174.         if (indices.isComplete())
  1175.             break;
  1176.  
  1177.         i++;
  1178.     }
  1179.  
  1180.     return indices;
  1181. }
  1182.  
  1183. // *************************************************************
  1184. // ***************  Application core    ************************
  1185. // *************************************************************
  1186.  
  1187. void Application::mainLoop()
  1188. {
  1189.     Timer* t = new Timer();
  1190.     double time = 1.0;
  1191.     int frames = 0;
  1192.     while (!glfwWindowShouldClose(m_window))
  1193.     {
  1194.         glfwPollEvents();
  1195.         drawFrame();
  1196.  
  1197.         // FPS Counter
  1198.         if (t->elapsed() > time)
  1199.         {
  1200.             time++;
  1201.             std::cout << frames << " FPS" << std::endl;
  1202.             frames = 0;
  1203.         }
  1204.         frames++;
  1205.     }
  1206.     vkDeviceWaitIdle(m_device);
  1207. }
  1208.  
  1209. void Application::drawFrame()
  1210. {
  1211.     vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
  1212.     vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]);
  1213.  
  1214.     uint32_t imageIndex;
  1215.     VkResult result = vkAcquireNextImageKHR(m_device, m_swapChain, std::numeric_limits<uint64_t>::max(), m_imageAvailableSemaphores[m_currentFrame], VK_NULL_HANDLE, &imageIndex);
  1216.  
  1217.     if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
  1218.     {
  1219.         recreateSwapChain();
  1220.         return;
  1221.     }
  1222.     else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
  1223.     {
  1224.         throw std::runtime_error("Failed to acquire swap chain image!");
  1225.     }
  1226.  
  1227.     updateUniformBuffers(imageIndex);
  1228.  
  1229.     VkSemaphore waitSemaphores[] = { m_imageAvailableSemaphores[m_currentFrame] };
  1230.     VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
  1231.     VkSemaphore signalSemaphores[] = { m_renderFinishedSemaphores[m_currentFrame] };
  1232.  
  1233.     VkSubmitInfo submitInfo = {};
  1234.     submitInfo.sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1235.     submitInfo.waitSemaphoreCount   = 1;
  1236.     submitInfo.pWaitSemaphores      = waitSemaphores;
  1237.     submitInfo.pWaitDstStageMask    = waitStages;
  1238.     submitInfo.commandBufferCount   = 1;
  1239.     submitInfo.pCommandBuffers      = &m_commandBuffers[imageIndex];
  1240.     submitInfo.signalSemaphoreCount = 1;
  1241.     submitInfo.pSignalSemaphores    = signalSemaphores;
  1242.  
  1243.     vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]);
  1244.  
  1245.     result = vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_inFlightFences[m_currentFrame]);
  1246.     if (result != VK_SUCCESS)
  1247.         throw std::runtime_error("Failed to submit draw command buffer!");
  1248.  
  1249.     VkSwapchainKHR swapChains[] = { m_swapChain };
  1250.  
  1251.     VkPresentInfoKHR presentInfo = {};
  1252.     presentInfo.sType               = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  1253.     presentInfo.waitSemaphoreCount  = 1;
  1254.     presentInfo.pWaitSemaphores     = signalSemaphores;
  1255.     presentInfo.swapchainCount      = 1;
  1256.     presentInfo.pSwapchains         = swapChains;
  1257.     presentInfo.pImageIndices       = &imageIndex;
  1258.     presentInfo.pResults            = nullptr;
  1259.  
  1260.     result = vkQueuePresentKHR(m_presentQueue, &presentInfo);
  1261.  
  1262.     if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_framebufferResized)
  1263.     {
  1264.         m_framebufferResized = false;
  1265.         recreateSwapChain();
  1266.     }
  1267.     else if (result != VK_SUCCESS)
  1268.     {
  1269.         throw std::runtime_error("Failed to present swap chain image!");
  1270.     }
  1271.  
  1272.     m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
  1273. }
  1274.  
  1275. void Application::cleanup()
  1276. {
  1277.     cleanupSwapChain();
  1278.  
  1279.     //Descriptor Pool
  1280.     vkDestroyDescriptorPool(m_device, m_descriptorPool, nullptr);
  1281.  
  1282.     // Desciptor Set Layout
  1283.     vkDestroyDescriptorSetLayout(m_device, m_descriptorSetLayout, nullptr);
  1284.  
  1285.     // Uniform Buffers
  1286.     for (size_t i = 0; i < m_swapChainImages.size(); i++)
  1287.     {
  1288.         vkDestroyBuffer(m_device, m_uniformBuffers[i], nullptr);
  1289.         vkFreeMemory(m_device, m_uniformBuffersMemory[i], nullptr);
  1290.     }
  1291.  
  1292.     // Vertex buffer
  1293.     vkDestroyBuffer(m_device, m_vertexBuffer, nullptr);
  1294.     vkFreeMemory(m_device, m_vertexBufferMemory, nullptr);
  1295.     // Index Buffer
  1296.     vkDestroyBuffer(m_device, m_indexBuffer, nullptr);
  1297.     vkFreeMemory(m_device, m_indexBufferMemory, nullptr);
  1298.  
  1299.     // Semaphores
  1300.     for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
  1301.     {
  1302.         vkDestroySemaphore(m_device, m_imageAvailableSemaphores[i], nullptr);
  1303.         vkDestroySemaphore(m_device, m_renderFinishedSemaphores[i], nullptr);
  1304.         vkDestroyFence(m_device, m_inFlightFences[i], nullptr);
  1305.     }
  1306.  
  1307.     // Command pool
  1308.     vkDestroyCommandPool(m_device, m_commandPool, nullptr);
  1309.     vkDestroyCommandPool(m_device, m_tempCommandPool, nullptr);
  1310.  
  1311.     // Device
  1312.     vkDestroyDevice(m_device, nullptr);
  1313.  
  1314.     // Debug messenger
  1315.     if (enableValidationLayers)
  1316.         DestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr);
  1317.  
  1318.     // Surface
  1319.     vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
  1320.  
  1321.     // Instance
  1322.     vkDestroyInstance(m_instance, nullptr);
  1323.  
  1324.     // GLFW
  1325.     glfwDestroyWindow(m_window);
  1326.     glfwTerminate();
  1327. }
  1328.  
  1329. void Application::init()
  1330. {
  1331.     initWindow();
  1332.     initVulkan();
  1333. }
  1334.  
  1335. void Application::run()
  1336. {
  1337.     // Run
  1338.     mainLoop();
  1339.     // Exit
  1340.     cleanup();
  1341. }
  1342.  
  1343. void Application::initWindow()
  1344. {
  1345.     glfwInit();
  1346.  
  1347.     glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  1348.     glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
  1349.  
  1350.     m_window = glfwCreateWindow(WIDTH, HEIGHT, "Volcanic Engine", nullptr, nullptr);
  1351.     glfwSetWindowUserPointer(m_window, this);
  1352.     glfwSetFramebufferSizeCallback(m_window, framebufferResizeCallback);
  1353. }
  1354.  
  1355. void Application::initVulkan()
  1356. {
  1357.     createInstance();
  1358.     setupDebugMessenger();
  1359.     createSurface();
  1360.     pickPhysicalDevice();
  1361.     createLogicalDevice();
  1362.     createSwapChain();
  1363.     createImageViews();
  1364.     createRenderPass();
  1365.     createDescriptorSetLayout();
  1366.     createGraphicsPipeline();
  1367.     createFramebuffers();
  1368.     createCommandPools();
  1369.     createVertexBuffers();
  1370.     createIndexBuffer();
  1371.     createUniformBuffers();
  1372.     createDescriptorPool();
  1373.     createDescriptorSets();
  1374.     createCommandBuffers();
  1375.     createSyncObjects();
  1376. }
  1377.  
  1378. // *************************************************************
  1379. // ***************  Callbacks           ************************
  1380. // *************************************************************
  1381.  
  1382. void Application::setupDebugMessenger()
  1383. {
  1384.     if (!enableValidationLayers) return;
  1385.  
  1386.     VkDebugUtilsMessengerCreateInfoEXT createInfo = {};
  1387.     createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  1388.     createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
  1389.         | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
  1390.         | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  1391.     createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
  1392.         | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
  1393.         | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  1394.     createInfo.pfnUserCallback = debugCallback;
  1395.     createInfo.pUserData = nullptr;
  1396.  
  1397.     if (CreateDebugUtilsMessengerEXT(m_instance, &createInfo, nullptr, &m_debugMessenger) != VK_SUCCESS)
  1398.         throw std::runtime_error("Failed to set up debug messenger!");
  1399.  
  1400. #ifndef NDEBUG
  1401.     spdlog::info("Successfully created debug callback.");
  1402. #endif
  1403. }
  1404.  
  1405. VkResult Application::CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger)
  1406. {
  1407.     auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
  1408.     if (func != nullptr)
  1409.         return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
  1410.     else
  1411.         return VK_ERROR_EXTENSION_NOT_PRESENT;
  1412. }
  1413.  
  1414. void Application::DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator)
  1415. {
  1416.     auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
  1417.     if (func != nullptr)
  1418.         func(instance, debugMessenger, pAllocator);
  1419. }
  1420.  
  1421. VKAPI_ATTR VkBool32 VKAPI_CALL Application::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData, void * pUserData)
  1422. {
  1423.     switch (messageSeverity)
  1424.     {
  1425.     case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
  1426.         spdlog::info("Validation layer: {}", pCallbackData->pMessage);
  1427.         break;
  1428.     case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
  1429.         spdlog::warn("Validation layer: {}", pCallbackData->pMessage);
  1430.         break;
  1431.     case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
  1432.         spdlog::error("Validation layer: {}", pCallbackData->pMessage);
  1433.         break;
  1434.     }
  1435.  
  1436.     return VK_FALSE;
  1437. }
  1438.  
  1439. void Application::framebufferResizeCallback(GLFWwindow * window, int width, int height)
  1440. {
  1441.     auto app = reinterpret_cast<Application*>(glfwGetWindowUserPointer(window));
  1442.  
  1443.     app->m_framebufferResized = true;
  1444.     app->m_framebufferWidth = width;
  1445.     app->m_framebufferHeight = height;
  1446. }
Add Comment
Please, Sign In to add comment