Guest User

fullprogram

a guest
Aug 13th, 2019
452
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 23.81 KB | None | 0 0
  1. #include <vulkan/vulkan.hpp>
  2. #include <GLFW/glfw3.h>
  3.  
  4. #include <iostream>
  5. #include <fstream>
  6. #include <set>
  7.  
  8. #define HEIGHT 480
  9. #define WIDTH 640
  10. #define MAX_FRAMES_IN_FLIGHT 2
  11.  
  12. class ComputeRayTracing {
  13. public:
  14.     void run() {
  15.         initWindow();
  16.         initVulkan();
  17.         mainLoop();
  18.         cleanup();
  19.     }
  20.  
  21. private:
  22.     GLFWwindow* window;
  23.  
  24.     vk::UniqueInstance instance;
  25.     vk::DispatchLoaderDynamic dispatchLoaderDynamic;
  26.     vk::DebugUtilsMessengerEXT debugMessenger;
  27.     vk::UniqueSurfaceKHR surface;
  28.  
  29.     vk::PhysicalDevice physicalDevice;
  30.     vk::UniqueDevice device;
  31.  
  32.     vk::Queue computeQueue;
  33.  
  34.     vk::UniqueSwapchainKHR swapchain;
  35.     std::vector<vk::Image> swapchainImages;
  36.     vk::Format swapchainImageFormat;
  37.     vk::Extent2D swapchainExtent;
  38.  
  39.     std::vector<vk::UniqueImageView> swapchainImageViews;
  40.  
  41.     vk::UniquePipelineLayout pipelineLayout;
  42.     vk::UniquePipeline pipeline;
  43.  
  44.     std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
  45.     vk::UniqueDescriptorPool descriptorPool;
  46.     std::vector<vk::DescriptorSet> descriptorSets;
  47.  
  48.     vk::UniqueCommandPool commandPool;
  49.     std::vector<vk::UniqueCommandBuffer> commandBuffers;
  50.  
  51.     std::vector<vk::UniqueSemaphore> imageAvailableSemaphores;
  52.     std::vector<vk::UniqueSemaphore> renderFinishedSemaphores;
  53.     std::vector<vk::UniqueFence> inFlightFences;
  54.     size_t currentFrame = 0;
  55.  
  56.     bool framebufferResized = false;
  57.  
  58.     struct PhysicalDeviceProperties {
  59.         int queueFamilyIndex;
  60.         bool extensionsSupported;
  61.         vk::SurfaceCapabilitiesKHR surfaceCapabilities;
  62.         std::vector<vk::SurfaceFormatKHR> surfaceFormats;
  63.         std::vector<vk::PresentModeKHR> presentModes;
  64.     } deviceProperties;
  65.  
  66. #ifdef NDEBUG
  67.     const bool enableValidationLayers = false;
  68. #else
  69.     const bool enableValidationLayers = true;
  70. #endif
  71.  
  72.     const std::vector<const char*> validationLayers = {
  73.         "VK_LAYER_LUNARG_standard_validation"
  74.     };
  75.  
  76.     const std::vector<const char*> deviceExtensions = {
  77.         VK_KHR_SWAPCHAIN_EXTENSION_NAME
  78.     };
  79.  
  80.     void initWindow() {
  81.         glfwInit();
  82.  
  83.         glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  84.  
  85.         window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
  86.         glfwSetWindowUserPointer(window, this);
  87.         glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
  88.     }
  89.  
  90.     static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
  91.         auto app = reinterpret_cast<ComputeRayTracing*>(glfwGetWindowUserPointer(window));
  92.         app->framebufferResized = true;
  93.     }
  94.  
  95.     void initVulkan() {
  96.         createInstance();
  97.         setupDebugMessenger();
  98.         createSurface();
  99.  
  100.         pickPhysicalDevice();
  101.         createLogicalDevice();
  102.  
  103.         createSwapchain();
  104.         createImageViews();
  105.  
  106.         createDescriptorSetLayout();
  107.         createDescriptorSet();
  108.  
  109.         createComputePipeline();
  110.  
  111.         createCommandPool();
  112.         createCommandBuffers();
  113.  
  114.         createSyncObjects();
  115.     }
  116.  
  117.     void createInstance() {
  118.         if (enableValidationLayers && !checkValidationLayerSupport(validationLayers)) {
  119.             throw std::runtime_error("validation layers requested, but not available!");
  120.         }
  121.  
  122.         vk::ApplicationInfo appInfo = vk::ApplicationInfo();
  123.         appInfo.pApplicationName = "Compute Ray Tracing";
  124.         appInfo.applicationVersion = VK_MAKE_VERSION(1, 1, 101);
  125.         appInfo.pEngineName = "No Engine";
  126.         appInfo.engineVersion = VK_MAKE_VERSION(1, 1, 101);
  127.         appInfo.apiVersion = VK_API_VERSION_1_1;
  128.  
  129.         std::vector<const char *> extensions = getRequiredExtensions();
  130.         extensions.push_back("VK_EXT_debug_utils");
  131.         extensions.push_back("VK_EXT_debug_report");
  132.  
  133.         vk::InstanceCreateInfo instanceCreateInfo = {};
  134.         instanceCreateInfo.pApplicationInfo = &appInfo;
  135.         instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
  136.         instanceCreateInfo.ppEnabledExtensionNames = extensions.data();
  137.  
  138.         if (enableValidationLayers) {
  139.             instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  140.             instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
  141.         }
  142.  
  143.         instance = vk::createInstanceUnique(instanceCreateInfo);
  144.     }
  145.  
  146.     bool checkValidationLayerSupport(const std::vector<const char*>& validationLayers) const {
  147.         const std::vector<vk::LayerProperties> availableLayers = vk::enumerateInstanceLayerProperties();
  148.  
  149.         for (const char* layerName : validationLayers) {
  150.             bool layerFound = false;
  151.  
  152.             for (const auto& layerProperties : availableLayers) {
  153.                 if (strcmp(layerName, layerProperties.layerName) == 0) {
  154.                     layerFound = true;
  155.                     break;
  156.                 }
  157.             }
  158.  
  159.             if (!layerFound) {
  160.                 return false;
  161.             }
  162.         }
  163.  
  164.         return true;
  165.     }
  166.  
  167.     std::vector<const char*> getRequiredExtensions() {
  168.         uint32_t glfwExtensionCount = 0;
  169.         const char** glfwExtensions;
  170.         glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
  171.  
  172.         std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
  173.  
  174.         if (enableValidationLayers) {
  175.             extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  176.         }
  177.  
  178.         return extensions;
  179.     }
  180.  
  181.     void setupDebugMessenger() {
  182.         if (!enableValidationLayers) {
  183.             return;
  184.         }
  185.  
  186.         dispatchLoaderDynamic = vk::DispatchLoaderDynamic(*instance, vkGetInstanceProcAddr);
  187.         vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT = {};
  188.         debugUtilsMessengerCreateInfoEXT.messageSeverity =
  189.             vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo
  190.             | vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose
  191.             | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning
  192.             | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
  193.         debugUtilsMessengerCreateInfoEXT.messageType =
  194.             vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral
  195.             | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation
  196.             | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
  197.         debugUtilsMessengerCreateInfoEXT.pfnUserCallback = debugCallback;
  198.  
  199.         debugMessenger = instance->createDebugUtilsMessengerEXT(
  200.             debugUtilsMessengerCreateInfoEXT,
  201.             nullptr,
  202.             dispatchLoaderDynamic);
  203.     }
  204.  
  205.     static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
  206.         VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
  207.         VkDebugUtilsMessageTypeFlagsEXT messageType,
  208.         const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
  209.         void* pUserData) {
  210.        
  211.         std::cerr << "Validation layer: " << pCallbackData->pMessage << std::endl;
  212.  
  213.         return VK_FALSE;
  214.     }
  215.  
  216.     void createSurface() {
  217.         VkSurfaceKHR windowSurface;
  218.         if (glfwCreateWindowSurface(*instance, window, nullptr, &windowSurface) != VK_SUCCESS) {
  219.             throw std::runtime_error("Failed to create window surface!");
  220.         }
  221.         vk::ObjectDestroy<vk::Instance, vk::DispatchLoaderStatic> surfaceDeleter(*instance);
  222.         surface = vk::UniqueSurfaceKHR(windowSurface, surfaceDeleter);
  223.     }
  224.  
  225.     void pickPhysicalDevice() {
  226.         std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
  227.  
  228.         if (physicalDevices.size() == 0) {
  229.             throw std::runtime_error("Failed to find GPUs with Vulkan support!");
  230.         }
  231.  
  232.         for (const vk::PhysicalDevice& device : physicalDevices) {
  233.             if (isDeviceSuitable(device)) {
  234.                 physicalDevice = device;
  235.                 return;
  236.             }
  237.         }
  238.  
  239.         throw std::runtime_error("Failed to find a suitable GPU!");
  240.     }
  241.  
  242.     PhysicalDeviceProperties getPhysicalDeviceProperties(const vk::PhysicalDevice &physicalDevice) {
  243.         PhysicalDeviceProperties deviceProperties;
  244.  
  245.         deviceProperties.queueFamilyIndex = getQueueFamilyIndex(physicalDevice);
  246.         deviceProperties.extensionsSupported = checkDeviceExtensionSupport(physicalDevice);
  247.         deviceProperties.surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(*surface);
  248.         deviceProperties.surfaceFormats = physicalDevice.getSurfaceFormatsKHR(*surface);
  249.         deviceProperties.presentModes = physicalDevice.getSurfacePresentModesKHR(*surface);
  250.  
  251.         return deviceProperties;
  252.     }
  253.  
  254.     bool isDeviceSuitable(const vk::PhysicalDevice &physicalDevice) {
  255.         deviceProperties = getPhysicalDeviceProperties(physicalDevice);
  256.         if (deviceProperties.queueFamilyIndex != -1
  257.             && deviceProperties.extensionsSupported
  258.             && deviceProperties.surfaceCapabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst
  259.             && !deviceProperties.surfaceFormats.empty()
  260.             && !deviceProperties.presentModes.empty()) {
  261.            
  262.             return true;
  263.         }
  264.  
  265.         return false;
  266.     }
  267.  
  268.     int getQueueFamilyIndex(const vk::PhysicalDevice& physicalDevice) {
  269.         std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
  270.  
  271.         int i = 0;
  272.         for (const auto& queueFamilyProperty : queueFamilyProperties) {
  273.             if (queueFamilyProperty.queueCount > 0
  274.                 && queueFamilyProperty.queueFlags & vk::QueueFlagBits::eCompute) {
  275.  
  276.                 vk::Bool32 presentSupport;
  277.                 physicalDevice.getSurfaceSupportKHR(i, *surface, &presentSupport);
  278.                
  279.                 if (presentSupport) {
  280.                     return i;
  281.                 }
  282.  
  283.                 ++i;
  284.             }
  285.         }
  286.  
  287.         return -1;
  288.     }
  289.  
  290.     bool checkDeviceExtensionSupport(const vk::PhysicalDevice &physicalDevice) {
  291.         std::vector<vk::ExtensionProperties> availableExtensions = physicalDevice.enumerateDeviceExtensionProperties();
  292.  
  293.         std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
  294.  
  295.         for (const auto& extension : availableExtensions) {
  296.             requiredExtensions.erase(extension.extensionName);
  297.         }
  298.  
  299.         return requiredExtensions.empty();
  300.     }
  301.  
  302.     void createLogicalDevice() {
  303.         std::vector<vk::DeviceQueueCreateInfo> deviceQueueCreateInfos;
  304.         std::set<uint32_t> uniqueQueueFamilies = { static_cast<uint32_t>(deviceProperties.queueFamilyIndex) };
  305.  
  306.         const float queuePriority = 1.0f;
  307.         for (uint32_t queueFamily : uniqueQueueFamilies) {
  308.             vk::DeviceQueueCreateInfo deviceQueueCreateInfo = {};
  309.             deviceQueueCreateInfo.queueFamilyIndex = queueFamily;
  310.             deviceQueueCreateInfo.queueCount = 1;
  311.             deviceQueueCreateInfo.pQueuePriorities = &queuePriority;
  312.             deviceQueueCreateInfos.push_back(deviceQueueCreateInfo);
  313.         }
  314.  
  315.         vk::PhysicalDeviceFeatures deviceFeatures;
  316.         vk::DeviceCreateInfo deviceCreateInfo = {};
  317.         deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(deviceQueueCreateInfos.size());
  318.         deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfos.data();
  319.  
  320.         deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
  321.  
  322.         deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
  323.         deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
  324.  
  325.         if (enableValidationLayers) {
  326.             deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  327.             deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
  328.         }
  329.  
  330.         device = physicalDevice.createDeviceUnique(deviceCreateInfo);
  331.  
  332.         computeQueue = device->getQueue(deviceProperties.queueFamilyIndex, 0);
  333.     }
  334.  
  335.     void createSwapchain() {
  336.         vk::SurfaceCapabilitiesKHR surfaceCapabilities = deviceProperties.surfaceCapabilities;
  337.         vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(deviceProperties.surfaceFormats);
  338.         vk::PresentModeKHR presentMode = chooseSwapPresentMode(deviceProperties.presentModes);
  339.         vk::Extent2D extent = chooseSwapExtent(surfaceCapabilities);
  340.  
  341.         uint32_t imageCount = surfaceCapabilities.minImageCount + 1;
  342.         if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) {
  343.             imageCount = surfaceCapabilities.maxImageCount;
  344.         }
  345.  
  346.         vk::SwapchainCreateInfoKHR swapchainCreateInfo = {};
  347.         swapchainCreateInfo.surface = *surface;
  348.         swapchainCreateInfo.minImageCount = imageCount;
  349.         swapchainCreateInfo.imageFormat = surfaceFormat.format;
  350.         swapchainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
  351.         swapchainCreateInfo.imageExtent = extent;
  352.         swapchainCreateInfo.imageArrayLayers = 1;
  353.         swapchainCreateInfo.imageUsage = vk::ImageUsageFlagBits::eStorage;
  354.         swapchainCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
  355.         swapchainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
  356.         swapchainCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
  357.         swapchainCreateInfo.presentMode = presentMode;
  358.         swapchainCreateInfo.clipped = VK_TRUE;
  359.  
  360.         swapchainCreateInfo.oldSwapchain = vk::SwapchainKHR();
  361.  
  362.         swapchain.reset();
  363.         swapchain = device->createSwapchainKHRUnique(swapchainCreateInfo);
  364.  
  365.         swapchainImages = device->getSwapchainImagesKHR(*swapchain);
  366.         swapchainImageFormat = surfaceFormat.format;
  367.         swapchainExtent = extent;
  368.     }
  369.  
  370.     vk::SurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats) {
  371.         if (availableFormats.size() == 1 && availableFormats[0].format == vk::Format::eUndefined) {
  372.             return { vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear };
  373.         }
  374.  
  375.         for (const auto& availableFormat : availableFormats) {
  376.             if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
  377.                 return availableFormat;
  378.             }
  379.         }
  380.  
  381.         return availableFormats[0];
  382.     }
  383.  
  384.     vk::PresentModeKHR chooseSwapPresentMode(const std::vector<vk::PresentModeKHR> availablePresentModes) {
  385.         vk::PresentModeKHR bestMode = vk::PresentModeKHR::eFifo;
  386.  
  387.         for (const auto& availablePresentMode : availablePresentModes) {
  388.             if (availablePresentMode == vk::PresentModeKHR::eMailbox) {
  389.                 return availablePresentMode;
  390.             }
  391.             else if (availablePresentMode == vk::PresentModeKHR::eImmediate) {
  392.                 bestMode = availablePresentMode;
  393.             }
  394.         }
  395.  
  396.         return bestMode;
  397.     }
  398.  
  399.     vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities) {
  400.         if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
  401.             return capabilities.currentExtent;
  402.         }
  403.         else {
  404.             int width;
  405.             int height;
  406.             glfwGetFramebufferSize(window, &width, &height);
  407.  
  408.             vk::Extent2D actualExtent = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
  409.  
  410.             actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
  411.             actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));
  412.  
  413.             return actualExtent;
  414.         }
  415.     }
  416.  
  417.     void createImageViews() {
  418.         swapchainImageViews.resize(swapchainImages.size());
  419.  
  420.         for (size_t i = 0; i < swapchainImages.size(); i++) {
  421.             vk::ImageViewCreateInfo imageViewCreateInfo = {};
  422.             imageViewCreateInfo.image = swapchainImages[i];
  423.             imageViewCreateInfo.viewType = vk::ImageViewType::e2D;
  424.             imageViewCreateInfo.format = swapchainImageFormat;
  425.             imageViewCreateInfo.components.r = vk::ComponentSwizzle::eIdentity;
  426.             imageViewCreateInfo.components.g = vk::ComponentSwizzle::eIdentity;;
  427.             imageViewCreateInfo.components.b = vk::ComponentSwizzle::eIdentity;;
  428.             imageViewCreateInfo.components.a = vk::ComponentSwizzle::eIdentity;;
  429.             imageViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
  430.             imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
  431.             imageViewCreateInfo.subresourceRange.levelCount = 1;
  432.             imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
  433.             imageViewCreateInfo.subresourceRange.layerCount = 1;
  434.  
  435.             swapchainImageViews[i] = device->createImageViewUnique(imageViewCreateInfo);
  436.         }
  437.     }
  438.  
  439.     void createDescriptorSetLayout() {
  440.         vk::DescriptorSetLayoutBinding binding = {};
  441.         binding.binding = 0;
  442.         binding.descriptorType = vk::DescriptorType::eStorageImage;
  443.         binding.descriptorCount = 1;
  444.         binding.stageFlags = vk::ShaderStageFlagBits::eCompute;
  445.  
  446.         vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {};
  447.         descriptorSetLayoutCreateInfo.bindingCount = 1;
  448.         descriptorSetLayoutCreateInfo.pBindings = &binding;
  449.         descriptorSetLayouts.push_back(device->createDescriptorSetLayout(descriptorSetLayoutCreateInfo));
  450.         descriptorSetLayouts.push_back(descriptorSetLayouts.front());
  451.         descriptorSetLayouts.push_back(descriptorSetLayouts.front());
  452.     }
  453.  
  454.     void createDescriptorSet() {
  455.         vk::DescriptorPoolSize descriptorPoolSize = {};
  456.         descriptorPoolSize.descriptorCount = 1;
  457.  
  458.         vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {};
  459.         descriptorPoolCreateInfo.maxSets = 3;
  460.         descriptorPoolCreateInfo.poolSizeCount = 1;
  461.         descriptorPoolCreateInfo.pPoolSizes = &descriptorPoolSize;
  462.  
  463.         descriptorPool = device->createDescriptorPoolUnique(descriptorPoolCreateInfo);
  464.  
  465.         vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {};
  466.         descriptorSetAllocateInfo.descriptorPool = *descriptorPool;
  467.         descriptorSetAllocateInfo.descriptorSetCount = 3;
  468.         descriptorSetAllocateInfo.pSetLayouts = &descriptorSetLayouts[0];
  469.  
  470.         descriptorSets = device->allocateDescriptorSets(descriptorSetAllocateInfo);
  471.  
  472.         std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
  473.  
  474.         for (int i = 0; i < 3; ++i) {
  475.             vk::DescriptorImageInfo descriptorImageInfo = {};
  476.             descriptorImageInfo.imageView = *swapchainImageViews[i];
  477.             descriptorImageInfo.imageLayout = vk::ImageLayout::eGeneral;
  478.  
  479.             vk::WriteDescriptorSet writeDescriptorSet = {};
  480.             writeDescriptorSet.dstSet = descriptorSets[i];
  481.             writeDescriptorSet.dstBinding = 0;
  482.             writeDescriptorSet.descriptorCount = 1;
  483.             writeDescriptorSet.descriptorType = vk::DescriptorType::eStorageImage;
  484.             writeDescriptorSet.pImageInfo = &descriptorImageInfo;
  485.             writeDescriptorSets.push_back(writeDescriptorSet);
  486.         }
  487.  
  488.         device->updateDescriptorSets(3, writeDescriptorSets.data(), 0, nullptr);
  489.     }
  490.  
  491.     void createComputePipeline() {
  492.         vk::UniqueShaderModule computeShaderModule = createShaderModule(readFile("shaders/comp.spv"));
  493.  
  494.         vk::PipelineShaderStageCreateInfo computeShaderStageInfo = {};
  495.         computeShaderStageInfo.stage = vk::ShaderStageFlagBits::eCompute;
  496.         computeShaderStageInfo.module = computeShaderModule.get();
  497.         computeShaderStageInfo.pName = "main";
  498.  
  499.         vk::PipelineLayoutCreateInfo pipelineLayoutInfo = {};
  500.         pipelineLayoutInfo.setLayoutCount = 1;
  501.         pipelineLayoutInfo.pSetLayouts = &descriptorSetLayouts[0];
  502.         pipelineLayoutInfo.pushConstantRangeCount = 0;
  503.  
  504.         pipelineLayout = device->createPipelineLayoutUnique(pipelineLayoutInfo);
  505.  
  506.         vk::ComputePipelineCreateInfo pipelineInfo = {};
  507.         pipelineInfo.stage = computeShaderStageInfo;
  508.         pipelineInfo.layout = pipelineLayout.get();
  509.  
  510.         pipeline = device->createComputePipelineUnique({}, pipelineInfo);
  511.     }
  512.  
  513.     static std::vector<char> readFile(const std::string& filename) {
  514.         std::ifstream file(filename, std::ios::ate | std::ios::binary);
  515.  
  516.         if (!file.is_open()) {
  517.             throw std::runtime_error("Failed to open file!");
  518.         }
  519.  
  520.         size_t fileSize = (size_t)file.tellg();
  521.         std::vector<char> buffer(fileSize);
  522.  
  523.         file.seekg(0);
  524.         file.read(buffer.data(), fileSize);
  525.  
  526.         file.close();
  527.  
  528.         return buffer;
  529.     }
  530.  
  531.     vk::UniqueShaderModule createShaderModule(const std::vector<char>& code) {
  532.         vk::ShaderModuleCreateInfo shaderModuleCreateInfo = {};
  533.         shaderModuleCreateInfo.codeSize = code.size();
  534.         shaderModuleCreateInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
  535.  
  536.         return device->createShaderModuleUnique(shaderModuleCreateInfo);
  537.     }
  538.  
  539.     void createCommandPool() {
  540.         vk::CommandPoolCreateInfo poolInfo = {};
  541.         poolInfo.queueFamilyIndex = deviceProperties.queueFamilyIndex;
  542.  
  543.         commandPool = device->createCommandPoolUnique(poolInfo);
  544.     }
  545.  
  546.     void createCommandBuffers() {
  547.         commandBuffers.resize(swapchainImages.size());
  548.  
  549.         vk::CommandBufferAllocateInfo allocInfo = {};
  550.         allocInfo.commandPool = commandPool.get();
  551.         allocInfo.level = vk::CommandBufferLevel::ePrimary;
  552.         allocInfo.commandBufferCount = commandBuffers.size();
  553.  
  554.         commandBuffers = device->allocateCommandBuffersUnique(allocInfo);
  555.  
  556.         for (size_t i = 0; i < commandBuffers.size(); ++i) {
  557.             vk::CommandBufferBeginInfo beginInfo = {};
  558.             beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;
  559.  
  560.             commandBuffers[i]->begin(beginInfo);
  561.  
  562.             commandBuffers[i]->bindPipeline(vk::PipelineBindPoint::eCompute, *pipeline);
  563.             commandBuffers[i]->bindDescriptorSets(vk::PipelineBindPoint::eCompute, *pipelineLayout, 0, descriptorSets[i], nullptr);
  564.  
  565.             vk::ImageMemoryBarrier imageMemoryBarrier = {};
  566.             imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;
  567.             imageMemoryBarrier.newLayout = vk::ImageLayout::eGeneral;
  568.             imageMemoryBarrier.image = swapchainImages[i];
  569.  
  570.             commandBuffers[i]->pipelineBarrier(
  571.                 vk::PipelineStageFlagBits::eTopOfPipe,
  572.                 vk::PipelineStageFlagBits::eComputeShader,
  573.                 vk::DependencyFlagBits::eByRegion,
  574.                 nullptr,
  575.                 nullptr,
  576.                 imageMemoryBarrier);
  577.  
  578.             commandBuffers[i]->dispatch(WIDTH, HEIGHT, 1);
  579.  
  580.             imageMemoryBarrier = {};
  581.             imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;
  582.             imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
  583.             imageMemoryBarrier.image = swapchainImages[i];
  584.  
  585.             commandBuffers[i]->pipelineBarrier(
  586.                 vk::PipelineStageFlagBits::eComputeShader,
  587.                 vk::PipelineStageFlagBits::eBottomOfPipe,
  588.                 vk::DependencyFlagBits::eByRegion,
  589.                 nullptr,
  590.                 nullptr,
  591.                 imageMemoryBarrier);
  592.  
  593.             commandBuffers[i]->end();
  594.         }
  595.     }
  596.  
  597.     void createSyncObjects() {
  598.         imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  599.         renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
  600.         inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
  601.  
  602.         vk::SemaphoreCreateInfo semaphoreInfo = {};
  603.  
  604.         vk::FenceCreateInfo fenceInfo = {};
  605.         fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled;
  606.  
  607.         for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
  608.             imageAvailableSemaphores[i] = device->createSemaphoreUnique(semaphoreInfo);
  609.             renderFinishedSemaphores[i] = device->createSemaphoreUnique(semaphoreInfo);
  610.             inFlightFences[i] = device->createFenceUnique(fenceInfo);
  611.         }
  612.     }
  613.  
  614.     void drawFrame() {
  615.         device->waitForFences(*inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
  616.  
  617.         uint32_t imageIndex;
  618.  
  619.         try {
  620.             device->acquireNextImageKHR(*swapchain, std::numeric_limits<uint64_t>::max(), *imageAvailableSemaphores[currentFrame], {}, &imageIndex);
  621.         }
  622.         catch (vk::OutOfDateKHRError) {
  623.             recreateSwapchain();
  624.             return;
  625.         }
  626.  
  627.         vk::SubmitInfo submitInfo = {};
  628.  
  629.         vk::Semaphore waitSemaphores[] = { *imageAvailableSemaphores[currentFrame] };
  630.         submitInfo.waitSemaphoreCount = 1;
  631.         submitInfo.pWaitSemaphores = &waitSemaphores[0];
  632.  
  633.         submitInfo.commandBufferCount = 1;
  634.         submitInfo.pCommandBuffers = &*commandBuffers[imageIndex];
  635.  
  636.         vk::Semaphore signalSemaphores[] = { *renderFinishedSemaphores[currentFrame] };
  637.         submitInfo.signalSemaphoreCount = 1;
  638.         submitInfo.pSignalSemaphores = &signalSemaphores[0];
  639.        
  640.         vk::PipelineStageFlags waitStages[] = { vk::PipelineStageFlagBits::eTopOfPipe };
  641.         submitInfo.pWaitDstStageMask = waitStages;
  642.  
  643.         computeQueue.submit(submitInfo, *inFlightFences[currentFrame]);
  644.  
  645.         vk::PresentInfoKHR presentInfo = {};
  646.         presentInfo.waitSemaphoreCount = 1;
  647.         presentInfo.pWaitSemaphores = &signalSemaphores[0];
  648.  
  649.         vk::SwapchainKHR swapchains[] = { *swapchain };
  650.         presentInfo.swapchainCount = 1;
  651.         presentInfo.pSwapchains = swapchains;
  652.         presentInfo.pImageIndices = &imageIndex;
  653.  
  654.         try {
  655.             vk::Result result = computeQueue.presentKHR(presentInfo);
  656.             if (result == vk::Result::eSuboptimalKHR || framebufferResized) {
  657.                 framebufferResized = false;
  658.                 recreateSwapchain();
  659.             }
  660.         }
  661.         catch (vk::OutOfDateKHRError) {
  662.             framebufferResized = false;
  663.             recreateSwapchain();
  664.         }
  665.  
  666.         currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
  667.     }
  668.  
  669.     void recreateSwapchain() {
  670.         int width = 0;
  671.         int height = 0;
  672.         while (width == 0 || height == 0) {
  673.             glfwGetFramebufferSize(window, &width, &height);
  674.             glfwWaitEvents();
  675.         }
  676.  
  677.         device->waitIdle();
  678.  
  679.         createSwapchain();
  680.         createImageViews();
  681.         createComputePipeline();
  682.         createCommandBuffers();
  683.     }
  684.  
  685.     void mainLoop() {
  686.         while (!glfwWindowShouldClose(window)) {
  687.             glfwPollEvents();
  688.             drawFrame();
  689.         }
  690.  
  691.         device->waitIdle();
  692.     }
  693.  
  694.     void cleanup() {
  695.         device->destroyDescriptorSetLayout(descriptorSetLayouts[0]);
  696.  
  697.         if (enableValidationLayers) {
  698.             // Commented to verify all objects are destroyed upon exiting main.
  699.             // instance->destroyDebugUtilsMessengerEXT(debugMessenger, nullptr, dispatchLoaderDynamic);
  700.         }
  701.  
  702.         glfwDestroyWindow(window);
  703.         glfwTerminate();
  704.     }
  705. };
  706.  
  707. int main() {
  708.     ComputeRayTracing computeRayTracing;
  709.  
  710.     try {
  711.         computeRayTracing.run();
  712.     }
  713.     catch (const std::exception& e) {
  714.         std::cout << e.what() << std::endl;
  715.         return EXIT_FAILURE;
  716.     }
  717.  
  718.     return EXIT_SUCCESS;
  719. }
Advertisement
Add Comment
Please, Sign In to add comment