Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vulkan/vulkan.hpp>
- #include <GLFW/glfw3.h>
- #include <iostream>
- #include <fstream>
- #include <set>
- #define HEIGHT 480
- #define WIDTH 640
- #define MAX_FRAMES_IN_FLIGHT 2
- class ComputeRayTracing {
- public:
- void run() {
- initWindow();
- initVulkan();
- mainLoop();
- cleanup();
- }
- private:
- GLFWwindow* window;
- vk::UniqueInstance instance;
- vk::DispatchLoaderDynamic dispatchLoaderDynamic;
- vk::DebugUtilsMessengerEXT debugMessenger;
- vk::UniqueSurfaceKHR surface;
- vk::PhysicalDevice physicalDevice;
- vk::UniqueDevice device;
- vk::Queue computeQueue;
- vk::UniqueSwapchainKHR swapchain;
- std::vector<vk::Image> swapchainImages;
- vk::Format swapchainImageFormat;
- vk::Extent2D swapchainExtent;
- std::vector<vk::UniqueImageView> swapchainImageViews;
- vk::UniquePipelineLayout pipelineLayout;
- vk::UniquePipeline pipeline;
- std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
- vk::UniqueDescriptorPool descriptorPool;
- std::vector<vk::DescriptorSet> descriptorSets;
- vk::UniqueCommandPool commandPool;
- std::vector<vk::UniqueCommandBuffer> commandBuffers;
- std::vector<vk::UniqueSemaphore> imageAvailableSemaphores;
- std::vector<vk::UniqueSemaphore> renderFinishedSemaphores;
- std::vector<vk::UniqueFence> inFlightFences;
- size_t currentFrame = 0;
- bool framebufferResized = false;
- struct PhysicalDeviceProperties {
- int queueFamilyIndex;
- bool extensionsSupported;
- vk::SurfaceCapabilitiesKHR surfaceCapabilities;
- std::vector<vk::SurfaceFormatKHR> surfaceFormats;
- std::vector<vk::PresentModeKHR> presentModes;
- } deviceProperties;
- #ifdef NDEBUG
- const bool enableValidationLayers = false;
- #else
- const bool enableValidationLayers = true;
- #endif
- const std::vector<const char*> validationLayers = {
- "VK_LAYER_LUNARG_standard_validation"
- };
- const std::vector<const char*> deviceExtensions = {
- VK_KHR_SWAPCHAIN_EXTENSION_NAME
- };
- void initWindow() {
- glfwInit();
- glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
- window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
- glfwSetWindowUserPointer(window, this);
- glfwSetFramebufferSizeCallback(window, framebufferResizeCallback);
- }
- static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
- auto app = reinterpret_cast<ComputeRayTracing*>(glfwGetWindowUserPointer(window));
- app->framebufferResized = true;
- }
- void initVulkan() {
- createInstance();
- setupDebugMessenger();
- createSurface();
- pickPhysicalDevice();
- createLogicalDevice();
- createSwapchain();
- createImageViews();
- createDescriptorSetLayout();
- createDescriptorSet();
- createComputePipeline();
- createCommandPool();
- createCommandBuffers();
- createSyncObjects();
- }
- void createInstance() {
- if (enableValidationLayers && !checkValidationLayerSupport(validationLayers)) {
- throw std::runtime_error("validation layers requested, but not available!");
- }
- vk::ApplicationInfo appInfo = vk::ApplicationInfo();
- appInfo.pApplicationName = "Compute Ray Tracing";
- appInfo.applicationVersion = VK_MAKE_VERSION(1, 1, 101);
- appInfo.pEngineName = "No Engine";
- appInfo.engineVersion = VK_MAKE_VERSION(1, 1, 101);
- appInfo.apiVersion = VK_API_VERSION_1_1;
- std::vector<const char *> extensions = getRequiredExtensions();
- extensions.push_back("VK_EXT_debug_utils");
- extensions.push_back("VK_EXT_debug_report");
- vk::InstanceCreateInfo instanceCreateInfo = {};
- instanceCreateInfo.pApplicationInfo = &appInfo;
- instanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
- instanceCreateInfo.ppEnabledExtensionNames = extensions.data();
- if (enableValidationLayers) {
- instanceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
- instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
- }
- instance = vk::createInstanceUnique(instanceCreateInfo);
- }
- bool checkValidationLayerSupport(const std::vector<const char*>& validationLayers) const {
- const std::vector<vk::LayerProperties> availableLayers = vk::enumerateInstanceLayerProperties();
- for (const char* layerName : validationLayers) {
- bool layerFound = false;
- for (const auto& layerProperties : availableLayers) {
- if (strcmp(layerName, layerProperties.layerName) == 0) {
- layerFound = true;
- break;
- }
- }
- if (!layerFound) {
- return false;
- }
- }
- return true;
- }
- std::vector<const char*> getRequiredExtensions() {
- uint32_t glfwExtensionCount = 0;
- const char** glfwExtensions;
- glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
- std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
- if (enableValidationLayers) {
- extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- }
- return extensions;
- }
- void setupDebugMessenger() {
- if (!enableValidationLayers) {
- return;
- }
- dispatchLoaderDynamic = vk::DispatchLoaderDynamic(*instance, vkGetInstanceProcAddr);
- vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCreateInfoEXT = {};
- debugUtilsMessengerCreateInfoEXT.messageSeverity =
- vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo
- | vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose
- | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning
- | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
- debugUtilsMessengerCreateInfoEXT.messageType =
- vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral
- | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation
- | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance;
- debugUtilsMessengerCreateInfoEXT.pfnUserCallback = debugCallback;
- debugMessenger = instance->createDebugUtilsMessengerEXT(
- debugUtilsMessengerCreateInfoEXT,
- nullptr,
- dispatchLoaderDynamic);
- }
- static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
- VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
- VkDebugUtilsMessageTypeFlagsEXT messageType,
- const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
- void* pUserData) {
- std::cerr << "Validation layer: " << pCallbackData->pMessage << std::endl;
- return VK_FALSE;
- }
- void createSurface() {
- VkSurfaceKHR windowSurface;
- if (glfwCreateWindowSurface(*instance, window, nullptr, &windowSurface) != VK_SUCCESS) {
- throw std::runtime_error("Failed to create window surface!");
- }
- vk::ObjectDestroy<vk::Instance, vk::DispatchLoaderStatic> surfaceDeleter(*instance);
- surface = vk::UniqueSurfaceKHR(windowSurface, surfaceDeleter);
- }
- void pickPhysicalDevice() {
- std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
- if (physicalDevices.size() == 0) {
- throw std::runtime_error("Failed to find GPUs with Vulkan support!");
- }
- for (const vk::PhysicalDevice& device : physicalDevices) {
- if (isDeviceSuitable(device)) {
- physicalDevice = device;
- return;
- }
- }
- throw std::runtime_error("Failed to find a suitable GPU!");
- }
- PhysicalDeviceProperties getPhysicalDeviceProperties(const vk::PhysicalDevice &physicalDevice) {
- PhysicalDeviceProperties deviceProperties;
- deviceProperties.queueFamilyIndex = getQueueFamilyIndex(physicalDevice);
- deviceProperties.extensionsSupported = checkDeviceExtensionSupport(physicalDevice);
- deviceProperties.surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(*surface);
- deviceProperties.surfaceFormats = physicalDevice.getSurfaceFormatsKHR(*surface);
- deviceProperties.presentModes = physicalDevice.getSurfacePresentModesKHR(*surface);
- return deviceProperties;
- }
- bool isDeviceSuitable(const vk::PhysicalDevice &physicalDevice) {
- deviceProperties = getPhysicalDeviceProperties(physicalDevice);
- if (deviceProperties.queueFamilyIndex != -1
- && deviceProperties.extensionsSupported
- && deviceProperties.surfaceCapabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst
- && !deviceProperties.surfaceFormats.empty()
- && !deviceProperties.presentModes.empty()) {
- return true;
- }
- return false;
- }
- int getQueueFamilyIndex(const vk::PhysicalDevice& physicalDevice) {
- std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
- int i = 0;
- for (const auto& queueFamilyProperty : queueFamilyProperties) {
- if (queueFamilyProperty.queueCount > 0
- && queueFamilyProperty.queueFlags & vk::QueueFlagBits::eCompute) {
- vk::Bool32 presentSupport;
- physicalDevice.getSurfaceSupportKHR(i, *surface, &presentSupport);
- if (presentSupport) {
- return i;
- }
- ++i;
- }
- }
- return -1;
- }
- bool checkDeviceExtensionSupport(const vk::PhysicalDevice &physicalDevice) {
- std::vector<vk::ExtensionProperties> availableExtensions = physicalDevice.enumerateDeviceExtensionProperties();
- std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
- for (const auto& extension : availableExtensions) {
- requiredExtensions.erase(extension.extensionName);
- }
- return requiredExtensions.empty();
- }
- void createLogicalDevice() {
- std::vector<vk::DeviceQueueCreateInfo> deviceQueueCreateInfos;
- std::set<uint32_t> uniqueQueueFamilies = { static_cast<uint32_t>(deviceProperties.queueFamilyIndex) };
- const float queuePriority = 1.0f;
- for (uint32_t queueFamily : uniqueQueueFamilies) {
- vk::DeviceQueueCreateInfo deviceQueueCreateInfo = {};
- deviceQueueCreateInfo.queueFamilyIndex = queueFamily;
- deviceQueueCreateInfo.queueCount = 1;
- deviceQueueCreateInfo.pQueuePriorities = &queuePriority;
- deviceQueueCreateInfos.push_back(deviceQueueCreateInfo);
- }
- vk::PhysicalDeviceFeatures deviceFeatures;
- vk::DeviceCreateInfo deviceCreateInfo = {};
- deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(deviceQueueCreateInfos.size());
- deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfos.data();
- deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
- deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
- deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
- if (enableValidationLayers) {
- deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
- deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
- }
- device = physicalDevice.createDeviceUnique(deviceCreateInfo);
- computeQueue = device->getQueue(deviceProperties.queueFamilyIndex, 0);
- }
- void createSwapchain() {
- vk::SurfaceCapabilitiesKHR surfaceCapabilities = deviceProperties.surfaceCapabilities;
- vk::SurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(deviceProperties.surfaceFormats);
- vk::PresentModeKHR presentMode = chooseSwapPresentMode(deviceProperties.presentModes);
- vk::Extent2D extent = chooseSwapExtent(surfaceCapabilities);
- uint32_t imageCount = surfaceCapabilities.minImageCount + 1;
- if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) {
- imageCount = surfaceCapabilities.maxImageCount;
- }
- vk::SwapchainCreateInfoKHR swapchainCreateInfo = {};
- swapchainCreateInfo.surface = *surface;
- swapchainCreateInfo.minImageCount = imageCount;
- swapchainCreateInfo.imageFormat = surfaceFormat.format;
- swapchainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
- swapchainCreateInfo.imageExtent = extent;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageUsage = vk::ImageUsageFlagBits::eStorage;
- swapchainCreateInfo.imageSharingMode = vk::SharingMode::eExclusive;
- swapchainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
- swapchainCreateInfo.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
- swapchainCreateInfo.presentMode = presentMode;
- swapchainCreateInfo.clipped = VK_TRUE;
- swapchainCreateInfo.oldSwapchain = vk::SwapchainKHR();
- swapchain.reset();
- swapchain = device->createSwapchainKHRUnique(swapchainCreateInfo);
- swapchainImages = device->getSwapchainImagesKHR(*swapchain);
- swapchainImageFormat = surfaceFormat.format;
- swapchainExtent = extent;
- }
- vk::SurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormatKHR>& availableFormats) {
- if (availableFormats.size() == 1 && availableFormats[0].format == vk::Format::eUndefined) {
- return { vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear };
- }
- for (const auto& availableFormat : availableFormats) {
- if (availableFormat.format == vk::Format::eB8G8R8A8Unorm && availableFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
- return availableFormat;
- }
- }
- return availableFormats[0];
- }
- vk::PresentModeKHR chooseSwapPresentMode(const std::vector<vk::PresentModeKHR> availablePresentModes) {
- vk::PresentModeKHR bestMode = vk::PresentModeKHR::eFifo;
- for (const auto& availablePresentMode : availablePresentModes) {
- if (availablePresentMode == vk::PresentModeKHR::eMailbox) {
- return availablePresentMode;
- }
- else if (availablePresentMode == vk::PresentModeKHR::eImmediate) {
- bestMode = availablePresentMode;
- }
- }
- return bestMode;
- }
- vk::Extent2D chooseSwapExtent(const vk::SurfaceCapabilitiesKHR& capabilities) {
- if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
- return capabilities.currentExtent;
- }
- else {
- int width;
- int height;
- glfwGetFramebufferSize(window, &width, &height);
- vk::Extent2D actualExtent = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
- actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
- actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));
- return actualExtent;
- }
- }
- void createImageViews() {
- swapchainImageViews.resize(swapchainImages.size());
- for (size_t i = 0; i < swapchainImages.size(); i++) {
- vk::ImageViewCreateInfo imageViewCreateInfo = {};
- imageViewCreateInfo.image = swapchainImages[i];
- imageViewCreateInfo.viewType = vk::ImageViewType::e2D;
- imageViewCreateInfo.format = swapchainImageFormat;
- imageViewCreateInfo.components.r = vk::ComponentSwizzle::eIdentity;
- imageViewCreateInfo.components.g = vk::ComponentSwizzle::eIdentity;;
- imageViewCreateInfo.components.b = vk::ComponentSwizzle::eIdentity;;
- imageViewCreateInfo.components.a = vk::ComponentSwizzle::eIdentity;;
- imageViewCreateInfo.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
- imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
- imageViewCreateInfo.subresourceRange.levelCount = 1;
- imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
- imageViewCreateInfo.subresourceRange.layerCount = 1;
- swapchainImageViews[i] = device->createImageViewUnique(imageViewCreateInfo);
- }
- }
- void createDescriptorSetLayout() {
- vk::DescriptorSetLayoutBinding binding = {};
- binding.binding = 0;
- binding.descriptorType = vk::DescriptorType::eStorageImage;
- binding.descriptorCount = 1;
- binding.stageFlags = vk::ShaderStageFlagBits::eCompute;
- vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {};
- descriptorSetLayoutCreateInfo.bindingCount = 1;
- descriptorSetLayoutCreateInfo.pBindings = &binding;
- descriptorSetLayouts.push_back(device->createDescriptorSetLayout(descriptorSetLayoutCreateInfo));
- descriptorSetLayouts.push_back(descriptorSetLayouts.front());
- descriptorSetLayouts.push_back(descriptorSetLayouts.front());
- }
- void createDescriptorSet() {
- vk::DescriptorPoolSize descriptorPoolSize = {};
- descriptorPoolSize.descriptorCount = 1;
- vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {};
- descriptorPoolCreateInfo.maxSets = 3;
- descriptorPoolCreateInfo.poolSizeCount = 1;
- descriptorPoolCreateInfo.pPoolSizes = &descriptorPoolSize;
- descriptorPool = device->createDescriptorPoolUnique(descriptorPoolCreateInfo);
- vk::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {};
- descriptorSetAllocateInfo.descriptorPool = *descriptorPool;
- descriptorSetAllocateInfo.descriptorSetCount = 3;
- descriptorSetAllocateInfo.pSetLayouts = &descriptorSetLayouts[0];
- descriptorSets = device->allocateDescriptorSets(descriptorSetAllocateInfo);
- std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
- for (int i = 0; i < 3; ++i) {
- vk::DescriptorImageInfo descriptorImageInfo = {};
- descriptorImageInfo.imageView = *swapchainImageViews[i];
- descriptorImageInfo.imageLayout = vk::ImageLayout::eGeneral;
- vk::WriteDescriptorSet writeDescriptorSet = {};
- writeDescriptorSet.dstSet = descriptorSets[i];
- writeDescriptorSet.dstBinding = 0;
- writeDescriptorSet.descriptorCount = 1;
- writeDescriptorSet.descriptorType = vk::DescriptorType::eStorageImage;
- writeDescriptorSet.pImageInfo = &descriptorImageInfo;
- writeDescriptorSets.push_back(writeDescriptorSet);
- }
- device->updateDescriptorSets(3, writeDescriptorSets.data(), 0, nullptr);
- }
- void createComputePipeline() {
- vk::UniqueShaderModule computeShaderModule = createShaderModule(readFile("shaders/comp.spv"));
- vk::PipelineShaderStageCreateInfo computeShaderStageInfo = {};
- computeShaderStageInfo.stage = vk::ShaderStageFlagBits::eCompute;
- computeShaderStageInfo.module = computeShaderModule.get();
- computeShaderStageInfo.pName = "main";
- vk::PipelineLayoutCreateInfo pipelineLayoutInfo = {};
- pipelineLayoutInfo.setLayoutCount = 1;
- pipelineLayoutInfo.pSetLayouts = &descriptorSetLayouts[0];
- pipelineLayoutInfo.pushConstantRangeCount = 0;
- pipelineLayout = device->createPipelineLayoutUnique(pipelineLayoutInfo);
- vk::ComputePipelineCreateInfo pipelineInfo = {};
- pipelineInfo.stage = computeShaderStageInfo;
- pipelineInfo.layout = pipelineLayout.get();
- pipeline = device->createComputePipelineUnique({}, pipelineInfo);
- }
- static std::vector<char> readFile(const std::string& filename) {
- std::ifstream file(filename, std::ios::ate | std::ios::binary);
- if (!file.is_open()) {
- throw std::runtime_error("Failed to open file!");
- }
- size_t fileSize = (size_t)file.tellg();
- std::vector<char> buffer(fileSize);
- file.seekg(0);
- file.read(buffer.data(), fileSize);
- file.close();
- return buffer;
- }
- vk::UniqueShaderModule createShaderModule(const std::vector<char>& code) {
- vk::ShaderModuleCreateInfo shaderModuleCreateInfo = {};
- shaderModuleCreateInfo.codeSize = code.size();
- shaderModuleCreateInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
- return device->createShaderModuleUnique(shaderModuleCreateInfo);
- }
- void createCommandPool() {
- vk::CommandPoolCreateInfo poolInfo = {};
- poolInfo.queueFamilyIndex = deviceProperties.queueFamilyIndex;
- commandPool = device->createCommandPoolUnique(poolInfo);
- }
- void createCommandBuffers() {
- commandBuffers.resize(swapchainImages.size());
- vk::CommandBufferAllocateInfo allocInfo = {};
- allocInfo.commandPool = commandPool.get();
- allocInfo.level = vk::CommandBufferLevel::ePrimary;
- allocInfo.commandBufferCount = commandBuffers.size();
- commandBuffers = device->allocateCommandBuffersUnique(allocInfo);
- for (size_t i = 0; i < commandBuffers.size(); ++i) {
- vk::CommandBufferBeginInfo beginInfo = {};
- beginInfo.flags = vk::CommandBufferUsageFlagBits::eSimultaneousUse;
- commandBuffers[i]->begin(beginInfo);
- commandBuffers[i]->bindPipeline(vk::PipelineBindPoint::eCompute, *pipeline);
- commandBuffers[i]->bindDescriptorSets(vk::PipelineBindPoint::eCompute, *pipelineLayout, 0, descriptorSets[i], nullptr);
- vk::ImageMemoryBarrier imageMemoryBarrier = {};
- imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;
- imageMemoryBarrier.newLayout = vk::ImageLayout::eGeneral;
- imageMemoryBarrier.image = swapchainImages[i];
- commandBuffers[i]->pipelineBarrier(
- vk::PipelineStageFlagBits::eTopOfPipe,
- vk::PipelineStageFlagBits::eComputeShader,
- vk::DependencyFlagBits::eByRegion,
- nullptr,
- nullptr,
- imageMemoryBarrier);
- commandBuffers[i]->dispatch(WIDTH, HEIGHT, 1);
- imageMemoryBarrier = {};
- imageMemoryBarrier.oldLayout = vk::ImageLayout::eUndefined;
- imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
- imageMemoryBarrier.image = swapchainImages[i];
- commandBuffers[i]->pipelineBarrier(
- vk::PipelineStageFlagBits::eComputeShader,
- vk::PipelineStageFlagBits::eBottomOfPipe,
- vk::DependencyFlagBits::eByRegion,
- nullptr,
- nullptr,
- imageMemoryBarrier);
- commandBuffers[i]->end();
- }
- }
- void createSyncObjects() {
- imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
- renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
- inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
- vk::SemaphoreCreateInfo semaphoreInfo = {};
- vk::FenceCreateInfo fenceInfo = {};
- fenceInfo.flags = vk::FenceCreateFlagBits::eSignaled;
- for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i) {
- imageAvailableSemaphores[i] = device->createSemaphoreUnique(semaphoreInfo);
- renderFinishedSemaphores[i] = device->createSemaphoreUnique(semaphoreInfo);
- inFlightFences[i] = device->createFenceUnique(fenceInfo);
- }
- }
- void drawFrame() {
- device->waitForFences(*inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
- uint32_t imageIndex;
- try {
- device->acquireNextImageKHR(*swapchain, std::numeric_limits<uint64_t>::max(), *imageAvailableSemaphores[currentFrame], {}, &imageIndex);
- }
- catch (vk::OutOfDateKHRError) {
- recreateSwapchain();
- return;
- }
- vk::SubmitInfo submitInfo = {};
- vk::Semaphore waitSemaphores[] = { *imageAvailableSemaphores[currentFrame] };
- submitInfo.waitSemaphoreCount = 1;
- submitInfo.pWaitSemaphores = &waitSemaphores[0];
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &*commandBuffers[imageIndex];
- vk::Semaphore signalSemaphores[] = { *renderFinishedSemaphores[currentFrame] };
- submitInfo.signalSemaphoreCount = 1;
- submitInfo.pSignalSemaphores = &signalSemaphores[0];
- vk::PipelineStageFlags waitStages[] = { vk::PipelineStageFlagBits::eTopOfPipe };
- submitInfo.pWaitDstStageMask = waitStages;
- computeQueue.submit(submitInfo, *inFlightFences[currentFrame]);
- vk::PresentInfoKHR presentInfo = {};
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.pWaitSemaphores = &signalSemaphores[0];
- vk::SwapchainKHR swapchains[] = { *swapchain };
- presentInfo.swapchainCount = 1;
- presentInfo.pSwapchains = swapchains;
- presentInfo.pImageIndices = &imageIndex;
- try {
- vk::Result result = computeQueue.presentKHR(presentInfo);
- if (result == vk::Result::eSuboptimalKHR || framebufferResized) {
- framebufferResized = false;
- recreateSwapchain();
- }
- }
- catch (vk::OutOfDateKHRError) {
- framebufferResized = false;
- recreateSwapchain();
- }
- currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
- }
- void recreateSwapchain() {
- int width = 0;
- int height = 0;
- while (width == 0 || height == 0) {
- glfwGetFramebufferSize(window, &width, &height);
- glfwWaitEvents();
- }
- device->waitIdle();
- createSwapchain();
- createImageViews();
- createComputePipeline();
- createCommandBuffers();
- }
- void mainLoop() {
- while (!glfwWindowShouldClose(window)) {
- glfwPollEvents();
- drawFrame();
- }
- device->waitIdle();
- }
- void cleanup() {
- device->destroyDescriptorSetLayout(descriptorSetLayouts[0]);
- if (enableValidationLayers) {
- // Commented to verify all objects are destroyed upon exiting main.
- // instance->destroyDebugUtilsMessengerEXT(debugMessenger, nullptr, dispatchLoaderDynamic);
- }
- glfwDestroyWindow(window);
- glfwTerminate();
- }
- };
- int main() {
- ComputeRayTracing computeRayTracing;
- try {
- computeRayTracing.run();
- }
- catch (const std::exception& e) {
- std::cout << e.what() << std::endl;
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment