Vulkan 创建 PhysicalDevice 和 Surface 的包装思路

看 Vulkan Sample 的话,创建 PhysicalDevice 和 Surface 的包装思路是

void VulkanRenderer::SelectPhysicalDeviceAndSurface()
{
    vk::raii::PhysicalDevices gpus(*m_vulkan_instance);
    
    bool found_graphics_queue_index = false;
    for (size_t i = 0; i < gpus.size() && !found_graphics_queue_index; i++)
    {
        std::vector<vk::QueueFamilyProperties> queue_family_properties = gpus[i].getQueueFamilyProperties();

        if (queue_family_properties.empty())
        {
            throw std::runtime_error("No queue family found.");
        }

        VkSurfaceKHR surface = m_window.lock()->CreateSurface((**m_vulkan_instance));
        if (!surface)
        {
            throw std::runtime_error("Failed to create window surface.");
        }

        // delete old surface if old surface exists
        m_surface.reset(new vk::raii::SurfaceKHR(*m_vulkan_instance, surface));

        for (uint32_t j = 0; j < queue_family_properties.size(); j++)
        {
            vk::Bool32 supports_present = gpus[i].getSurfaceSupportKHR(j, surface);

            // Find a queue family which supports graphics and presentation.
            if ((queue_family_properties[j].queueFlags & vk::QueueFlagBits::eGraphics) && supports_present)
            {
                m_graphics_queue_index     = j;
                found_graphics_queue_index = true;
                m_gpu                      = std::make_unique<vk::raii::PhysicalDevice>(gpus[i]);
                break;
            }
        }
    }

    if (!found_graphics_queue_index)
    {
        RUNTIME_ERROR("Did not find suitable queue which supports graphics and presentation.");
    }
}

主要就是找第一个支持 graphics 和 presentation queue family 的 device

另外一种方式是对每一个 device 评分,选择评分最高的那个 device

uint32_t ScorePhysicalDevice(const VkPhysicalDevice& device)
{
      uint32_t score = 0;

      // Checks if the requested extensions are supported.
      uint32_t extension_property_count;
      vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_property_count, nullptr);
      std::vector<VkExtensionProperties> extension_properties(extension_property_count);
      vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_property_count, extension_properties.data());

      // Iterates through all extensions requested.
      for (const char* currentExtension : LogicalDevice::DeviceExtensions)
      {
          bool extensionFound = false;

          // Checks if the extension is in the available extensions.
          for (const auto& extension : extension_properties)
          {
              if (strcmp(currentExtension, extension.extensionName) == 0)
              {
                  extensionFound = true;
                  break;
              }
          }

          // Returns a score of 0 if this device is missing a required extension.
          if (!extensionFound)
              return 0;
      }

      // Obtain the device features and properties of the current device being rateds.
      VkPhysicalDeviceProperties physical_device_properties;
      VkPhysicalDeviceFeatures   physical_device_features;
      vkGetPhysicalDeviceProperties(device, &physical_device_properties);
      vkGetPhysicalDeviceFeatures(device, &physical_device_features);

#ifdef MEOW_DEBUG
      LogVulkanDevice(physical_device_properties, extension_properties);
#endif

      // Adds a large score boost for discrete GPUs (dedicated graphics cards).
      if (physical_device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
          score += 1000;

      // Gives a higher score to devices with a higher maximum texture size.
      score += physical_device_properties.limits.maxImageDimension2D;
      return score;
  }

  void VulkanRenderer::CreatePhysicalDevice()
  {
      vk::raii::PhysicalDevices gpus(*m_vulkan_instance);

      // Maps to hold devices and sort by rank.
      std::multimap<uint32_t, vk::raii::PhysicalDevices> rankedDevices;
      auto                                               where = rankedDevices.end();

      // Iterates through all devices and rate their suitability.
      for (const auto& gpu : gpus)
          where = rankedDevices.insert(where, {ScorePhysicalDevice(*gpu), gpu});

      // Checks to make sure the best candidate scored higher than 0  rbegin points to last element of ranked
      // devices(highest rated), first is its rating.
      if (rankedDevices.rbegin()->first > 0)
          m_gpu = std::make_unique<vk::raii::PhysicalDevice>(rankedDevices.rbegin()->second);
  }

Surface 的话

你可能感兴趣的:(GameEngineDev,c++,vulkan)