#include "PhysicalDevice.hpp" #include #include "Surface.hpp" #include "Instance.hpp" #include "DeviceFunctions/DeviceFunctions.hpp" #include "Log/Log.hpp" #include #include VkObjects::PhysicalDevice::QueueFamilyIndices VkObjects::PhysicalDevice::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface, const std::vector& device_extensions) { VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties(device, &device_properties); vkGetPhysicalDeviceFeatures(device, &device_features); if(check_device_extensions_support(device, device_extensions) == false) throw std::runtime_error("Device not supported"); return find_queue_family_indices(device, surface); } bool VkObjects::PhysicalDevice::check_device_extensions_support(VkPhysicalDevice device, const std::vector& device_extensions) { uint32_t extension_count; VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr)) std::vector available_extensions(extension_count); VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data())) for (const auto& extension : device_extensions) { bool isFind = false; for (const auto& i : available_extensions) { if (std::strcmp(i.extensionName, extension) == 0) { isFind = true; break; } } if (!isFind) return false; } return true; } VkObjects::PhysicalDevice::QueueFamilyIndices VkObjects::PhysicalDevice::find_queue_family_indices( VkPhysicalDevice physical_device, VkSurfaceKHR surface) { QueueFamilyIndices queue_family_indices; uint32_t queueFamilyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, nullptr); std::vector family_properties(queueFamilyCount); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, family_properties.data()); // Find graphics bool is_find_graphics_family = false; for(uint32_t i = 0; i < family_properties.size(); ++i) { if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { queue_family_indices.graphics_family = i; is_find_graphics_family = true; break; } } if (is_find_graphics_family == false) throw std::runtime_error("Failed to find a graphics queue family"); // Find present VkBool32 present_support = false; VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family, surface, &present_support)) // Если графическая очередь поддерживет презентацию кадров, то используем её bool is_find_present_family = false; if (present_support == VK_TRUE) { queue_family_indices.present_family = queue_family_indices.graphics_family; is_find_present_family = true; } // иначе ищем другую подходящую очередь else { for(uint32_t i = 0; i < family_properties.size(); ++i) { present_support = false; VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support)) if (present_support == VK_TRUE) { queue_family_indices.present_family = i; is_find_present_family = true; break; } } } if (is_find_present_family == false) throw std::runtime_error("Failed to find a present queue family"); // С начала пытаемся найти очередь специалезированную // для копирования отличную от графической bool is_find_transfer_family = false; for(uint32_t i = 0; i < family_properties.size(); ++i) { if (i == queue_family_indices.graphics_family) continue; if (family_properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) { queue_family_indices.transfer_family = i; is_find_transfer_family = true; } } // Если не находим, то используем графическую if (is_find_transfer_family == false) { queue_family_indices.transfer_family = queue_family_indices.graphics_family; } return queue_family_indices; } VkObjects::PhysicalDevice::PhysicalDevice(const Instance& instance, const Surface& surface, const std::vector& device_extensions) { uint32_t device_count = 0; std::vector devices; VK_CHECK(vkEnumeratePhysicalDevices(instance.get_native(), &device_count, nullptr)) devices.resize(device_count); VK_CHECK(vkEnumeratePhysicalDevices(instance.get_native(), &device_count, devices.data())) for (const auto& device : devices) { try { queue_family_indices_ = is_device_suitable(device, surface.get_native(), device_extensions); physical_device_ = device; VkPhysicalDeviceProperties device_properties; vkGetPhysicalDeviceProperties(physical_device_, &device_properties); Loging::Log("Using device: " + std::string(device_properties.deviceName)); break; } catch(...) { } } if (VK_NULL_HANDLE == physical_device_) throw std::runtime_error("No suitable device found"); } std::vector VkObjects::PhysicalDevice::get_unique_family_indices() const { std::set set_indices = {queue_family_indices_.graphics_family, queue_family_indices_.present_family, queue_family_indices_.transfer_family}; std::vector arr_indices; arr_indices.reserve(set_indices.size()); for (auto& i : set_indices) arr_indices.push_back(i); return arr_indices; }