diff --git a/docs/lectures/02/index.md b/docs/lectures/02/index.md index 37a1566cf18c30187ebbbdc4053535aeeaddc5aa..ea0bf473af27a285909a00d01e756a3ee125426e 100644 --- a/docs/lectures/02/index.md +++ b/docs/lectures/02/index.md @@ -413,3 +413,152 @@ Renderer::Renderer(const Window& window) ) } {} ``` + +### Támogatás + +A szemfüles olvasóknak feltűnhetett, hogy a `VK_KHR_SWAPCHAIN` bővítményt még nem engedélyeztük. +Illetve egy másik fontos dolog - hogyha használni is akarjuk a swapchain-t, akkor biztosra kell mennünk, hogy olyan queue-t választunk, ami támogat megjelenítést. +Gyorsan adjuk hozzá ezeket a setup-unkhoz. + +!!! tip "" + + A következő kód részek másolása jóval könnyebb lesz `lecture_02-final` branch-ből. + Érdemes innentől inkább csak olvasni. + +#### Enable extension + +A `VK_KHR_SWAPCHAIN` egy *device extension*, tehát *device* szinten kell engedélyezni. +Ehhez első lépés, hogy olyan physical_device-t válasszunk, ami támogatja ezt. + +??? example "Code snippets (*Renderer.cpp*)" + + ```cpp + const std::vector<const char*> g_device_extensions{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }; + ``` + + ```cpp + [[nodiscard]] + static auto supports_required_extensions(const vk::PhysicalDevice physical_device) -> bool + { + const auto properties{ physical_device.enumerateDeviceExtensionProperties() }; + + return std::ranges::all_of(g_device_extensions, [&](const char* extension_name) { + return std::ranges::find_if( + properties, + [extension_name](const char* property_extension_name) { + return std::strcmp(extension_name, property_extension_name) == 0; + }, + [](const vk::ExtensionProperties& extension_properties + ) -> const char* { return extension_properties.extensionName; } + ) + != std::end(properties); + }); + } + ``` + + ```cpp + [[nodiscard]] + static auto choose_physical_device(const vk::Instance instance) -> vk::PhysicalDevice + { + std::vector<vk::PhysicalDevice> physical_devices{}; + std::ranges::remove_copy_if( + instance.enumeratePhysicalDevices(), + std::back_inserter(physical_devices), + [surface](vk::PhysicalDevice physical_device) { + return !( + supports_required_extensions(physical_device) + && find_queue_family_index(physical_device).has_value() + ); + } + ); + // ... + ``` + + ```cpp + [[nodiscard]] + static auto create_device(const vk::PhysicalDevice physical_device) -> vk::UniqueDevice + { + // ... + const vk::DeviceCreateInfo device_create_info{ + // ... + .enabledExtensionCount = static_cast<uint32_t>(g_device_extensions.size()), + .ppEnabledExtensionNames = g_device_extensions.data(), + }; + ``` + +#### Queue választás + +??? example "Code snippets (*Renderer.cpp*)" + + ```cpp + [[nodiscard]] + static auto find_queue_family_index( + const vk::PhysicalDevice physical_device, + const vk::SurfaceKHR surface + ) -> std::optional<uint32_t> + { + uint32_t index{}; + for (const auto& properties : physical_device.getQueueFamilyProperties()) { + if (properties.queueFlags & vk::QueueFlagBits::eGraphics + && physical_device.getSurfaceSupportKHR(index, surface)) + { + return index; + } + index++; + } + return std::nullopt; + } + ``` + + ```cpp + [[nodiscard]] + static auto + choose_physical_device(const vk::Instance instance, const vk::SurfaceKHR surface) + -> vk::PhysicalDevice + { + std::vector<vk::PhysicalDevice> physical_devices{}; + std::ranges::remove_copy_if( + instance.enumeratePhysicalDevices(), + std::back_inserter(physical_devices), + [surface](vk::PhysicalDevice physical_device) { + return !( + supports_required_extensions(physical_device) + && find_queue_family_index(physical_device, surface).has_value() + ); + } + ); + // ... + ``` + + ```cpp + [[nodiscard]] + static auto + create_device(const vk::PhysicalDevice physical_device, const vk::SurfaceKHR surface) + -> vk::UniqueDevice + { + // ... + const vk::DeviceQueueCreateInfo queue_create_info{ + .queueFamilyIndex = find_queue_family_index(physical_device, surface).value(), + // ... + }; + ``` + + ```cpp + Renderer::Renderer(const Window& window) + : m_instance{ create_instance() }, + m_surface{ window.create_vulkan_surface(m_instance.get()) }, + m_physical_device{ choose_physical_device(m_instance.get(), m_surface.get()) }, + m_queue_family_index{ + find_queue_family_index(m_physical_device, m_surface.get()).value() + }, + m_device{ create_device(m_physical_device, m_surface.get()) }, + m_queue{ m_device->getQueue(m_queue_family_index, 0) }, + m_swapchain{ Swapchain::create( + m_surface.get(), + m_physical_device, + m_queue_family_index, + m_device.get(), + window.framebuffer_size() + ) } + {} + ```