RickIsGone

Untitled

Nov 3rd, 2024
11
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.23 KB | Source Code | 0 0
  1. module;
  2. #include <cstring>
  3. #include <format>
  4. #include <set>
  5. #include <vector>
  6. #include <unordered_set>
  7.  
  8. // #include "engineDevice.hpp"
  9. #include "engineWindow.hpp"
  10. #include "logger.hpp"
  11. export module engineDevice;
  12.  
  13. namespace gears {
  14.    export struct SwapChainSupportDetails {
  15.       VkSurfaceCapabilitiesKHR capabilities;
  16.       std::vector<VkSurfaceFormatKHR> formats;
  17.       std::vector<VkPresentModeKHR> presentModes;
  18.    };
  19.  
  20.    export struct QueueFamilyIndices {
  21.       uint32_t graphicsFamily;
  22.       uint32_t presentFamily;
  23.       bool graphicsFamilyHasValue = false;
  24.       bool presentFamilyHasValue = false;
  25.       bool isComplete() { return graphicsFamilyHasValue && presentFamilyHasValue; }
  26.    };
  27.  
  28.    export class PhysicalDevice {
  29.    public:
  30. #ifdef GRS_DEBUG
  31.       const bool enableValidationLayers = true;
  32. #else
  33.       const bool enableValidationLayers = false;
  34. #endif // GRS_DEBUG
  35.  
  36.       PhysicalDevice(Window& window);
  37.       ~PhysicalDevice();
  38.  
  39.       // Not copyable or movable
  40.       PhysicalDevice(const PhysicalDevice&) = delete;
  41.       PhysicalDevice& operator=(const PhysicalDevice&) = delete;
  42.       PhysicalDevice(PhysicalDevice&&) = delete;
  43.       PhysicalDevice& operator=(PhysicalDevice&&) = delete;
  44.  
  45.       VkCommandPool getCommandPool() { return _commandPool; }
  46.       VkDevice device() { return _device; }
  47.       VkSurfaceKHR surface() { return _surface; }
  48.       VkQueue graphicsQueue() { return _graphicsQueue; }
  49.       VkQueue presentQueue() { return _presentQueue; }
  50.  
  51.       SwapChainSupportDetails getSwapChainSupport() { return _querySwapChainSupport(_physicalDevice); }
  52.       uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
  53.       QueueFamilyIndices findPhysicalQueueFamilies() { return _findQueueFamilies(_physicalDevice); }
  54.       VkFormat findSupportedFormat(const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features);
  55.  
  56.       // Buffer Helper Functions
  57.       void createBuffer(
  58.           VkDeviceSize size,
  59.           VkBufferUsageFlags usage,
  60.           VkMemoryPropertyFlags properties,
  61.           VkBuffer& buffer,
  62.           VkDeviceMemory& bufferMemory);
  63.       VkCommandBuffer beginSingleTimeCommands();
  64.       void endSingleTimeCommands(VkCommandBuffer commandBuffer);
  65.       void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
  66.       void copyBufferToImage(
  67.           VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount);
  68.  
  69.       void createImageWithInfo(
  70.           const VkImageCreateInfo& imageInfo,
  71.           VkMemoryPropertyFlags properties,
  72.           VkImage& image,
  73.           VkDeviceMemory& imageMemory);
  74.  
  75.       VkPhysicalDeviceProperties properties;
  76.  
  77.    private:
  78.       void _createInstance();
  79.       void _setupDebugMessenger();
  80.       void _createSurface();
  81.       void _pickPhysicalDevice();
  82.       void _createLogicalDevice();
  83.       void _createCommandPool();
  84.  
  85.       // helper functions
  86.       bool _isDeviceSuitable(VkPhysicalDevice device);
  87.       std::vector<const char*> _getRequiredExtensions();
  88.       bool _checkValidationLayerSupport();
  89.       QueueFamilyIndices _findQueueFamilies(VkPhysicalDevice device);
  90.       void _populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo);
  91.       void _hasGflwRequiredInstanceExtensions();
  92.       bool _checkDeviceExtensionSupport(VkPhysicalDevice device);
  93.       SwapChainSupportDetails _querySwapChainSupport(VkPhysicalDevice device);
  94.  
  95.       VkInstance _instance;
  96.       VkDebugUtilsMessengerEXT _debugMessenger;
  97.       VkPhysicalDevice _physicalDevice = VK_NULL_HANDLE;
  98.       Window& _window;
  99.       VkCommandPool _commandPool;
  100.  
  101.       VkDevice _device;
  102.       VkSurfaceKHR _surface;
  103.       VkQueue _graphicsQueue;
  104.       VkQueue _presentQueue;
  105.  
  106.       const std::vector<const char*> _validationLayers = {"VK_LAYER_KHRONOS_validation"};
  107.       const std::vector<const char*> _deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
  108.    };
  109.    // local callback functions
  110.    static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
  111.        VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
  112.        VkDebugUtilsMessageTypeFlagsEXT messageType,
  113.        const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
  114.        void* pUserData) {
  115.       logger->warn(std::format("validation layer: {}", pCallbackData->pMessage));
  116.  
  117.       return VK_FALSE;
  118.    }
  119.  
  120.    VkResult CreateDebugUtilsMessengerEXT(
  121.        VkInstance instance,
  122.        const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
  123.        const VkAllocationCallbacks* pAllocator,
  124.        VkDebugUtilsMessengerEXT* pDebugMessenger) {
  125.       auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
  126.           instance,
  127.           "vkCreateDebugUtilsMessengerEXT");
  128.       if (func != nullptr) {
  129.          return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
  130.       } else {
  131.          return VK_ERROR_EXTENSION_NOT_PRESENT;
  132.       }
  133.    }
  134.  
  135.    void DestroyDebugUtilsMessengerEXT(
  136.        VkInstance instance,
  137.        VkDebugUtilsMessengerEXT _debugMessenger,
  138.        const VkAllocationCallbacks* pAllocator) {
  139.       auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
  140.           instance,
  141.           "vkDestroyDebugUtilsMessengerEXT");
  142.       if (func != nullptr) {
  143.          func(instance, _debugMessenger, pAllocator);
  144.       }
  145.    }
  146.  
  147.    // class member functions
  148.    PhysicalDevice::PhysicalDevice(Window& window) : _window{window} {
  149.       _createInstance();
  150.       _setupDebugMessenger();
  151.       _createSurface();
  152.       _pickPhysicalDevice();
  153.       _createLogicalDevice();
  154.       _createCommandPool();
  155.    }
  156.  
  157.    PhysicalDevice::~PhysicalDevice() {
  158.       vkDestroyCommandPool(_device, _commandPool, nullptr);
  159.       vkDestroyDevice(_device, nullptr);
  160.  
  161.       if (enableValidationLayers) {
  162.          DestroyDebugUtilsMessengerEXT(_instance, _debugMessenger, nullptr);
  163.       }
  164.  
  165.       vkDestroySurfaceKHR(_instance, _surface, nullptr);
  166.       vkDestroyInstance(_instance, nullptr);
  167.    }
  168.  
  169.    void PhysicalDevice::_createInstance() {
  170.       if (enableValidationLayers && !_checkValidationLayerSupport()) {
  171.          throw Logger::Exception("validation layers requested, but not available!");
  172.       }
  173.  
  174.       VkApplicationInfo appInfo = {};
  175.       appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  176.       appInfo.pApplicationName = "Gears game engine";
  177.       appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
  178.       appInfo.pEngineName = "Gears";
  179.       appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
  180.       appInfo.apiVersion = VK_API_VERSION_1_0;
  181.  
  182.       VkInstanceCreateInfo createInfo = {};
  183.       createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  184.       createInfo.pApplicationInfo = &appInfo;
  185.  
  186.       auto extensions = _getRequiredExtensions();
  187.       createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
  188.       createInfo.ppEnabledExtensionNames = extensions.data();
  189.  
  190.       VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
  191.       if (enableValidationLayers) {
  192.          createInfo.enabledLayerCount = static_cast<uint32_t>(_validationLayers.size());
  193.          createInfo.ppEnabledLayerNames = _validationLayers.data();
  194.  
  195.          _populateDebugMessengerCreateInfo(debugCreateInfo);
  196.          createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
  197.       } else {
  198.          createInfo.enabledLayerCount = 0;
  199.          createInfo.pNext = nullptr;
  200.       }
  201.  
  202.       if (vkCreateInstance(&createInfo, nullptr, &_instance) != VK_SUCCESS) {
  203.          throw Logger::Exception("failed to create instance!");
  204.       }
  205.  
  206.       _hasGflwRequiredInstanceExtensions();
  207.    }
  208.  
  209.    void PhysicalDevice::_pickPhysicalDevice() {
  210.       uint32_t deviceCount = 0;
  211.       vkEnumeratePhysicalDevices(_instance, &deviceCount, nullptr);
  212.       if (deviceCount == 0) {
  213.          throw Logger::Exception("failed to find GPUs with Vulkan support!");
  214.       }
  215.  
  216.       logger->logTrace(std::format("device count: {}", deviceCount));
  217.       std::vector<VkPhysicalDevice> devices(deviceCount);
  218.       vkEnumeratePhysicalDevices(_instance, &deviceCount, devices.data());
  219.  
  220.  
  221.       for (const auto& device : devices) {
  222.          if (_isDeviceSuitable(device)) {
  223.             _physicalDevice = device;
  224.             break;
  225.          }
  226.       }
  227.  
  228.       if (_physicalDevice == VK_NULL_HANDLE) {
  229.          throw Logger::Exception("failed to find a suitable GPU!");
  230.       }
  231.  
  232.       logger->logTrace("suitable devices available:");
  233.       for (const auto& device : devices) {
  234.          if (_isDeviceSuitable(device)) {
  235.             VkPhysicalDeviceProperties prop;
  236.             vkGetPhysicalDeviceProperties(device, &prop);
  237.             logger->logNoLevel(std::format("\t{}", prop.deviceName));
  238.          }
  239.       }
  240.  
  241.       vkGetPhysicalDeviceProperties(_physicalDevice, &properties);
  242.       logger->logTrace(std::format("physical device: {}", properties.deviceName));
  243.    }
  244.  
  245.    void PhysicalDevice::_createLogicalDevice() {
  246.       QueueFamilyIndices indices = _findQueueFamilies(_physicalDevice);
  247.  
  248.       std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  249.       std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily};
  250.  
  251.       float queuePriority = 1.0f;
  252.       for (uint32_t queueFamily : uniqueQueueFamilies) {
  253.          VkDeviceQueueCreateInfo queueCreateInfo = {};
  254.          queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  255.          queueCreateInfo.queueFamilyIndex = queueFamily;
  256.          queueCreateInfo.queueCount = 1;
  257.          queueCreateInfo.pQueuePriorities = &queuePriority;
  258.          queueCreateInfos.push_back(queueCreateInfo);
  259.       }
  260.  
  261.       VkPhysicalDeviceFeatures deviceFeatures = {};
  262.       deviceFeatures.samplerAnisotropy = VK_TRUE;
  263.  
  264.       VkDeviceCreateInfo createInfo = {};
  265.       createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  266.  
  267.       createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
  268.       createInfo.pQueueCreateInfos = queueCreateInfos.data();
  269.  
  270.       createInfo.pEnabledFeatures = &deviceFeatures;
  271.       createInfo.enabledExtensionCount = static_cast<uint32_t>(_deviceExtensions.size());
  272.       createInfo.ppEnabledExtensionNames = _deviceExtensions.data();
  273.  
  274.       // might not really be necessary anymore because device specific validation layers
  275.       // have been deprecated
  276.       if (enableValidationLayers) {
  277.          createInfo.enabledLayerCount = static_cast<uint32_t>(_validationLayers.size());
  278.          createInfo.ppEnabledLayerNames = _validationLayers.data();
  279.       } else {
  280.          createInfo.enabledLayerCount = 0;
  281.       }
  282.  
  283.       if (vkCreateDevice(_physicalDevice, &createInfo, nullptr, &_device) != VK_SUCCESS) {
  284.          throw Logger::Exception("failed to create logical device!");
  285.       }
  286.  
  287.       vkGetDeviceQueue(_device, indices.graphicsFamily, 0, &_graphicsQueue);
  288.       vkGetDeviceQueue(_device, indices.presentFamily, 0, &_presentQueue);
  289.    }
  290.  
  291.    void PhysicalDevice::_createCommandPool() {
  292.       QueueFamilyIndices queueFamilyIndices = findPhysicalQueueFamilies();
  293.  
  294.       VkCommandPoolCreateInfo poolInfo = {};
  295.       poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  296.       poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;
  297.       poolInfo.flags =
  298.           VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  299.  
  300.       if (vkCreateCommandPool(_device, &poolInfo, nullptr, &_commandPool) != VK_SUCCESS) {
  301.          throw Logger::Exception("failed to create command pool!");
  302.       }
  303.    }
  304.  
  305.    void PhysicalDevice::_createSurface() { _window.createWindowSurface(_instance, &_surface); }
  306.  
  307.    bool PhysicalDevice::_isDeviceSuitable(VkPhysicalDevice device) {
  308.       QueueFamilyIndices indices = _findQueueFamilies(device);
  309.  
  310.       bool extensionsSupported = _checkDeviceExtensionSupport(device);
  311.  
  312.       bool swapChainAdequate = false;
  313.       if (extensionsSupported) {
  314.          SwapChainSupportDetails swapChainSupport = _querySwapChainSupport(device);
  315.          swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
  316.       }
  317.  
  318.       VkPhysicalDeviceFeatures supportedFeatures;
  319.       vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
  320.  
  321.       return indices.isComplete() && extensionsSupported && swapChainAdequate &&
  322.           supportedFeatures.samplerAnisotropy;
  323.    }
  324.  
  325.    void PhysicalDevice::_populateDebugMessengerCreateInfo(
  326.        VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
  327.       createInfo = {};
  328.       createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  329.       createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
  330.           VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  331.       createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
  332.           VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
  333.           VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  334.       createInfo.pfnUserCallback = debugCallback;
  335.       createInfo.pUserData = nullptr; // Optional
  336.    }
  337.  
  338.    void PhysicalDevice::_setupDebugMessenger() {
  339.       if (!enableValidationLayers) return;
  340.       VkDebugUtilsMessengerCreateInfoEXT createInfo;
  341.       _populateDebugMessengerCreateInfo(createInfo);
  342.       if (CreateDebugUtilsMessengerEXT(_instance, &createInfo, nullptr, &_debugMessenger) != VK_SUCCESS) {
  343.          throw Logger::Exception("failed to set up debug messenger!");
  344.       }
  345.    }
  346.  
  347.    bool PhysicalDevice::_checkValidationLayerSupport() {
  348.       uint32_t layerCount;
  349.       vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
  350.  
  351.       std::vector<VkLayerProperties> availableLayers(layerCount);
  352.       vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
  353.  
  354.       for (const char* layerName : _validationLayers) {
  355.          bool layerFound = false;
  356.  
  357.          for (const auto& layerProperties : availableLayers) {
  358.             if (strcmp(layerName, layerProperties.layerName) == 0) {
  359.                layerFound = true;
  360.                break;
  361.             }
  362.          }
  363.  
  364.          if (!layerFound) {
  365.             return false;
  366.          }
  367.       }
  368.  
  369.       return true;
  370.    }
  371.  
  372.    std::vector<const char*> PhysicalDevice::_getRequiredExtensions() {
  373.       uint32_t glfwExtensionCount = 0;
  374.       const char** glfwExtensions;
  375.       glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
  376.  
  377.       std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
  378.  
  379.       if (enableValidationLayers) {
  380.          extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  381.       }
  382.  
  383.       return extensions;
  384.    }
  385.  
  386.    void PhysicalDevice::_hasGflwRequiredInstanceExtensions() {
  387.       uint32_t extensionCount = 0;
  388.       vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
  389.       std::vector<VkExtensionProperties> extensions(extensionCount);
  390.       vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
  391.  
  392.       logger->logTrace("available extensions:");
  393.       std::unordered_set<std::string> available;
  394.       for (const auto& extension : extensions) {
  395.          logger->logNoLevel(std::format("\t{}", extension.extensionName));
  396.          available.insert(extension.extensionName);
  397.       }
  398.  
  399.       logger->logTrace("required extensions:");
  400.       auto requiredExtensions = _getRequiredExtensions();
  401.       for (const auto& required : requiredExtensions) {
  402.          logger->logNoLevel(std::format("\t{}", required));
  403.          if (available.find(required) == available.end()) {
  404.             throw Logger::Exception("Missing required glfw extension");
  405.          }
  406.       }
  407.    }
  408.  
  409.    bool PhysicalDevice::_checkDeviceExtensionSupport(VkPhysicalDevice device) {
  410.       uint32_t extensionCount;
  411.       vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
  412.  
  413.       std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  414.       vkEnumerateDeviceExtensionProperties(
  415.           device,
  416.           nullptr,
  417.           &extensionCount,
  418.           availableExtensions.data());
  419.  
  420.       std::set<std::string> requiredExtensions(_deviceExtensions.begin(), _deviceExtensions.end());
  421.  
  422.       for (const auto& extension : availableExtensions) {
  423.          requiredExtensions.erase(extension.extensionName);
  424.       }
  425.  
  426.       return requiredExtensions.empty();
  427.    }
  428.  
  429.    QueueFamilyIndices PhysicalDevice::_findQueueFamilies(VkPhysicalDevice device) {
  430.       QueueFamilyIndices indices;
  431.  
  432.       uint32_t queueFamilyCount = 0;
  433.       vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
  434.  
  435.       std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
  436.       vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
  437.  
  438.       int i = 0;
  439.       for (const auto& queueFamily : queueFamilies) {
  440.          if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  441.             indices.graphicsFamily = i;
  442.             indices.graphicsFamilyHasValue = true;
  443.          }
  444.          VkBool32 presentSupport = false;
  445.          vkGetPhysicalDeviceSurfaceSupportKHR(device, i, _surface, &presentSupport);
  446.          if (queueFamily.queueCount > 0 && presentSupport) {
  447.             indices.presentFamily = i;
  448.             indices.presentFamilyHasValue = true;
  449.          }
  450.          if (indices.isComplete()) {
  451.             break;
  452.          }
  453.  
  454.          i++;
  455.       }
  456.  
  457.       return indices;
  458.    }
  459.  
  460.    SwapChainSupportDetails PhysicalDevice::_querySwapChainSupport(VkPhysicalDevice device) {
  461.       SwapChainSupportDetails details;
  462.       vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, _surface, &details.capabilities);
  463.  
  464.       uint32_t formatCount;
  465.       vkGetPhysicalDeviceSurfaceFormatsKHR(device, _surface, &formatCount, nullptr);
  466.  
  467.       if (formatCount != 0) {
  468.          details.formats.resize(formatCount);
  469.          vkGetPhysicalDeviceSurfaceFormatsKHR(device, _surface, &formatCount, details.formats.data());
  470.       }
  471.  
  472.       uint32_t presentModeCount;
  473.       vkGetPhysicalDeviceSurfacePresentModesKHR(device, _surface, &presentModeCount, nullptr);
  474.  
  475.       if (presentModeCount != 0) {
  476.          details.presentModes.resize(presentModeCount);
  477.          vkGetPhysicalDeviceSurfacePresentModesKHR(
  478.              device,
  479.              _surface,
  480.              &presentModeCount,
  481.              details.presentModes.data());
  482.       }
  483.       return details;
  484.    }
  485.  
  486.    VkFormat PhysicalDevice::findSupportedFormat(
  487.        const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {
  488.       for (VkFormat format : candidates) {
  489.          VkFormatProperties props;
  490.          vkGetPhysicalDeviceFormatProperties(_physicalDevice, format, &props);
  491.  
  492.          if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
  493.             return format;
  494.          } else if (
  495.              tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
  496.             return format;
  497.          }
  498.       }
  499.       throw Logger::Exception("failed to find supported format!");
  500.    }
  501.  
  502.    uint32_t PhysicalDevice::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
  503.       VkPhysicalDeviceMemoryProperties memProperties;
  504.       vkGetPhysicalDeviceMemoryProperties(_physicalDevice, &memProperties);
  505.       for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
  506.          if ((typeFilter & (1 << i)) &&
  507.              (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
  508.             return i;
  509.          }
  510.       }
  511.  
  512.       throw Logger::Exception("failed to find suitable memory type!");
  513.    }
  514.  
  515.    void PhysicalDevice::createBuffer(
  516.        VkDeviceSize size,
  517.        VkBufferUsageFlags usage,
  518.        VkMemoryPropertyFlags properties,
  519.        VkBuffer& buffer,
  520.        VkDeviceMemory& bufferMemory) {
  521.       VkBufferCreateInfo bufferInfo{};
  522.       bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  523.       bufferInfo.size = size;
  524.       bufferInfo.usage = usage;
  525.       bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  526.  
  527.       if (vkCreateBuffer(_device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
  528.          throw Logger::Exception("failed to create vertex buffer!");
  529.       }
  530.  
  531.       VkMemoryRequirements memRequirements;
  532.       vkGetBufferMemoryRequirements(_device, buffer, &memRequirements);
  533.  
  534.       VkMemoryAllocateInfo allocInfo{};
  535.       allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  536.       allocInfo.allocationSize = memRequirements.size;
  537.       allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
  538.  
  539.       if (vkAllocateMemory(_device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
  540.          throw Logger::Exception("failed to allocate vertex buffer memory!");
  541.       }
  542.  
  543.       vkBindBufferMemory(_device, buffer, bufferMemory, 0);
  544.    }
  545.  
  546.    VkCommandBuffer PhysicalDevice::beginSingleTimeCommands() {
  547.       VkCommandBufferAllocateInfo allocInfo{};
  548.       allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  549.       allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  550.       allocInfo.commandPool = _commandPool;
  551.       allocInfo.commandBufferCount = 1;
  552.  
  553.       VkCommandBuffer commandBuffer;
  554.       vkAllocateCommandBuffers(_device, &allocInfo, &commandBuffer);
  555.  
  556.       VkCommandBufferBeginInfo beginInfo{};
  557.       beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  558.       beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  559.  
  560.       vkBeginCommandBuffer(commandBuffer, &beginInfo);
  561.       return commandBuffer;
  562.    }
  563.  
  564.    void PhysicalDevice::endSingleTimeCommands(VkCommandBuffer commandBuffer) {
  565.       vkEndCommandBuffer(commandBuffer);
  566.  
  567.       VkSubmitInfo submitInfo{};
  568.       submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  569.       submitInfo.commandBufferCount = 1;
  570.       submitInfo.pCommandBuffers = &commandBuffer;
  571.  
  572.       vkQueueSubmit(_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
  573.       vkQueueWaitIdle(_graphicsQueue);
  574.  
  575.       vkFreeCommandBuffers(_device, _commandPool, 1, &commandBuffer);
  576.    }
  577.  
  578.    void PhysicalDevice::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
  579.       VkCommandBuffer commandBuffer = beginSingleTimeCommands();
  580.  
  581.       VkBufferCopy copyRegion{};
  582.       copyRegion.srcOffset = 0; // Optional
  583.       copyRegion.dstOffset = 0; // Optional
  584.       copyRegion.size = size;
  585.       vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
  586.  
  587.       endSingleTimeCommands(commandBuffer);
  588.    }
  589.  
  590.    void PhysicalDevice::copyBufferToImage(
  591.        VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount) {
  592.       VkCommandBuffer commandBuffer = beginSingleTimeCommands();
  593.  
  594.       VkBufferImageCopy region{};
  595.       region.bufferOffset = 0;
  596.       region.bufferRowLength = 0;
  597.       region.bufferImageHeight = 0;
  598.  
  599.       region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  600.       region.imageSubresource.mipLevel = 0;
  601.       region.imageSubresource.baseArrayLayer = 0;
  602.       region.imageSubresource.layerCount = layerCount;
  603.  
  604.       region.imageOffset = {0, 0, 0};
  605.       region.imageExtent = {width, height, 1};
  606.  
  607.       vkCmdCopyBufferToImage(
  608.           commandBuffer,
  609.           buffer,
  610.           image,
  611.           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  612.           1,
  613.           &region);
  614.       endSingleTimeCommands(commandBuffer);
  615.    }
  616.  
  617.    void PhysicalDevice::createImageWithInfo(
  618.        const VkImageCreateInfo& imageInfo,
  619.        VkMemoryPropertyFlags properties,
  620.        VkImage& image,
  621.        VkDeviceMemory& imageMemory) {
  622.       if (vkCreateImage(_device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
  623.          throw Logger::Exception("failed to create image!");
  624.       }
  625.  
  626.       VkMemoryRequirements memRequirements;
  627.       vkGetImageMemoryRequirements(_device, image, &memRequirements);
  628.  
  629.       VkMemoryAllocateInfo allocInfo{};
  630.       allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  631.       allocInfo.allocationSize = memRequirements.size;
  632.       allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
  633.  
  634.       if (vkAllocateMemory(_device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
  635.          throw Logger::Exception("failed to allocate image memory!");
  636.       }
  637.  
  638.       if (vkBindImageMemory(_device, image, imageMemory, 0) != VK_SUCCESS) {
  639.          throw Logger::Exception("failed to bind image memory!");
  640.       }
  641.    }
  642.  
  643. } // namespace gears
Advertisement
Add Comment
Please, Sign In to add comment