#include "Renderer.hpp" #include <algorithm> #include <ranges> #include <vector> const std::vector<const char*> g_layers{ #ifdef ENGINE_VULKAN_DEBUG "VK_LAYER_KHRONOS_validation" #endif }; [[nodiscard]] static auto create_instance() -> vk::UniqueInstance { constexpr static vk::ApplicationInfo application_info{}; const vk::InstanceCreateInfo create_info{ .pApplicationInfo = &application_info, .enabledLayerCount = static_cast<uint32_t>(g_layers.size()), .ppEnabledLayerNames = g_layers.data(), }; return vk::createInstanceUnique(create_info); } [[nodiscard]] static auto choose_physical_device(const vk::Instance t_instance) -> vk::PhysicalDevice { const auto physical_devices{ t_instance.enumeratePhysicalDevices() }; if (std::ranges::empty(physical_devices)) { throw std::runtime_error{ "No Vulkan physical device is available." }; } auto ranked_devices_view{ physical_devices | std::views::transform([](vk::PhysicalDevice t_physical_device) { switch (t_physical_device.getProperties().deviceType) { case vk::PhysicalDeviceType::eDiscreteGpu: return std::make_pair(t_physical_device, 2); case vk::PhysicalDeviceType::eIntegratedGpu: return std::make_pair(t_physical_device, 1); default: return std::make_pair(t_physical_device, 0); } }) }; std::vector ranked_devices( ranked_devices_view.begin(), ranked_devices_view.end() ); std::ranges::sort( ranked_devices, std::ranges::greater{}, &std::pair<vk::PhysicalDevice, int>::second ); return ranked_devices.front().first; } [[nodiscard]] static auto find_graphics_queue_family( const vk::PhysicalDevice t_physical_device ) -> uint32_t { uint32_t index{}; for (const auto& properties : t_physical_device.getQueueFamilyProperties()) { if (properties.queueFlags & vk::QueueFlagBits::eGraphics) { return index; } index++; } throw std::runtime_error{ "Could not find graphics queue family" }; } [[nodiscard]] static auto create_device(const vk::PhysicalDevice t_physical_device) -> vk::UniqueDevice { const vk::DeviceQueueCreateInfo queue_create_info{ .queueFamilyIndex = find_graphics_queue_family(t_physical_device), .queueCount = 1, }; vk::DeviceCreateInfo device_create_info{ .queueCreateInfoCount = 1, .pQueueCreateInfos = &queue_create_info, }; return t_physical_device.createDeviceUnique(device_create_info); } Renderer::Renderer() : m_instance{ create_instance() }, m_physical_device{ choose_physical_device(*m_instance) }, m_graphics_queue_family{ find_graphics_queue_family(m_physical_device) }, m_device{ create_device(m_physical_device) }, m_graphics_queue{ m_device->getQueue(m_graphics_queue_family, 0) } {}