Changeset 909b51a in opengl-game


Ignore:
Timestamp:
Jul 8, 2019, 7:47:23 PM (5 years ago)
Author:
Dmitry Portnoy <dmitry.portnoy@…>
Branches:
feature/imgui-sdl, master, points-test
Children:
b3671b5
Parents:
80de39d
Message:

Select a physical device and create a logical device for it

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vulkan-game.cpp

    r80de39d r909b51a  
    1515#include <stdexcept>
    1616#include <cstdlib>
     17#include <optional>
    1718
    1819#include "game-gui-sdl.hpp"
     
    3334   const bool enableValidationLayers = true;
    3435#endif
     36
     37struct QueueFamilyIndices {
     38    optional<uint32_t> graphicsFamily;
     39
     40    bool isComplete() {
     41        return graphicsFamily.has_value();
     42    }
     43};
    3544
    3645static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
     
    8594      VkInstance instance;
    8695      VkDebugUtilsMessengerEXT debugMessenger;
     96      VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
     97      VkDevice device;
     98      VkQueue graphicsQueue;
    8799
    88100      // both SDL and GLFW create window functions return NULL on failure
     
    113125         createInstance();
    114126         setupDebugMessenger();
     127         pickPhysicalDevice();
     128         createLogicalDevice();
    115129      }
    116130
     
    154168      }
    155169
     170      void setupDebugMessenger() {
     171         if (!enableValidationLayers) return;
     172
     173         VkDebugUtilsMessengerCreateInfoEXT createInfo;
     174         populateDebugMessengerCreateInfo(createInfo);
     175
     176         if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
     177            throw runtime_error("failed to setup debug messenger!");
     178         }
     179      }
     180
     181      void pickPhysicalDevice() {
     182         uint32_t deviceCount = 0;
     183         vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
     184
     185         if (deviceCount == 0) {
     186            throw runtime_error("failed to find GPUs with Vulkan support!");
     187         }
     188
     189         vector<VkPhysicalDevice> devices(deviceCount);
     190         vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
     191
     192         cout << endl << "Graphics cards:" << endl;
     193         for (const VkPhysicalDevice& device : devices) {
     194            if (isDeviceSuitable(device)) {
     195               physicalDevice = device;
     196               break;
     197            }
     198         }
     199         cout << endl;
     200
     201         if (physicalDevice == VK_NULL_HANDLE) {
     202            throw runtime_error("failed to find a suitable GPU!");
     203         }
     204      }
     205
     206      bool isDeviceSuitable(VkPhysicalDevice device) {
     207         VkPhysicalDeviceProperties deviceProperties;
     208         VkPhysicalDeviceFeatures deviceFeatures;
     209
     210         vkGetPhysicalDeviceProperties(device, &deviceProperties);
     211         vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
     212
     213         cout << "Device: " << deviceProperties.deviceName << endl;
     214
     215         QueueFamilyIndices indices = findQueueFamilies(device);
     216
     217         return indices.isComplete();
     218      }
     219
     220      void createLogicalDevice() {
     221         QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
     222
     223         VkDeviceQueueCreateInfo queueCreateInfo = {};
     224         queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
     225         queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
     226         queueCreateInfo.queueCount = 1;
     227
     228         float queuePriority = 1.0f;
     229         queueCreateInfo.pQueuePriorities = &queuePriority;
     230
     231         VkPhysicalDeviceFeatures deviceFeatures = {};
     232
     233         VkDeviceCreateInfo createInfo = {};
     234         createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
     235
     236         createInfo.pQueueCreateInfos = &queueCreateInfo;
     237         createInfo.queueCreateInfoCount = 1;
     238
     239         createInfo.pEnabledFeatures = &deviceFeatures;
     240
     241         createInfo.enabledExtensionCount = 0;
     242
     243         // These fields are ignored  by up-to-date Vulkan implementations,
     244         // but it's a good idea to set them for backwards compatibility
     245         if (enableValidationLayers) {
     246            createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
     247            createInfo.ppEnabledLayerNames = validationLayers.data();
     248         } else {
     249            createInfo.enabledLayerCount = 0;
     250         }
     251
     252         if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
     253            throw runtime_error("failed to create logical device!");
     254         }
     255
     256         vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);
     257      }
     258
     259      bool checkValidationLayerSupport() {
     260         uint32_t layerCount;
     261         vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
     262
     263         vector<VkLayerProperties> availableLayers(layerCount);
     264         vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
     265
     266         for (const char* layerName : validationLayers) {
     267            bool layerFound = false;
     268
     269            for (const auto& layerProperties : availableLayers) {
     270               if (strcmp(layerName, layerProperties.layerName) == 0) {
     271                  layerFound = true;
     272                  break;
     273               }
     274            }
     275
     276            if (!layerFound) {
     277               return false;
     278            }
     279         }
     280
     281         return true;
     282      }
     283
     284      QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
     285         QueueFamilyIndices indices;
     286
     287         uint32_t queueFamilyCount = 0;
     288         vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
     289
     290         vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
     291         vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
     292
     293         int i = 0;
     294         for (const auto& queueFamily : queueFamilies) {
     295            if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
     296               indices.graphicsFamily = i;
     297            }
     298
     299            if (indices.isComplete()) {
     300               break;
     301            }
     302
     303            i++;
     304         }
     305
     306         return indices;
     307      }
     308
    156309      void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) {
    157310         createInfo = {};
     
    160313         createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
    161314         createInfo.pfnUserCallback = debugCallback;
    162       }
    163 
    164       void setupDebugMessenger() {
    165          if (!enableValidationLayers) return;
    166 
    167          VkDebugUtilsMessengerCreateInfoEXT createInfo;
    168          populateDebugMessengerCreateInfo(createInfo);
    169 
    170          if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
    171             throw runtime_error("failed to setup debug messenger!");
    172          }
    173       }
    174 
    175       bool checkValidationLayerSupport() {
    176          uint32_t layerCount;
    177          vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
    178 
    179          vector<VkLayerProperties> availableLayers(layerCount);
    180          vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
    181 
    182          for (const char* layerName : validationLayers) {
    183             bool layerFound = false;
    184 
    185             for (const auto& layerProperties : availableLayers) {
    186                if (strcmp(layerName, layerProperties.layerName) == 0) {
    187                   layerFound = true;
    188                   break;
    189                }
    190             }
    191 
    192             if (!layerFound) {
    193                return false;
    194             }
    195          }
    196 
    197          return true;
    198315      }
    199316
     
    252369
    253370      void cleanup() {
     371         vkDestroyDevice(device, nullptr);
     372
    254373         if (enableValidationLayers) {
    255374            DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
Note: See TracChangeset for help on using the changeset viewer.