/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include "Device.hpp" #include "Image.hpp" #include "FrameBuffer.hpp" #include "Base/UI/IWindow.hpp" #include "Base/Logger.hpp" #include namespace OpenVulkano { namespace Vulkan { struct SwapChainImage : public IImage { vk::Image image; vk::ImageView view; vk::Fence fence; vk::Image GetImage() override { return image; } vk::ImageView GetView() override { return view; } }; class SwapChain final : public FrameBuffer { vk::SurfaceKHR surface; std::vector images; Device* device = nullptr; IVulkanWindow* window = nullptr; vk::SurfaceFormatKHR surfaceFormat; vk::PresentModeKHR presentMode; vk::Viewport fullscreenViewport; vk::Rect2D fullscreenScissor; std::vector imageAvailableSemaphores; uint32_t currentSemaphoreId = 0; bool useVsync = false; #ifdef __APPLE__ uint32_t preferredImageCount = 3; //TODO add option #else uint32_t preferredImageCount = 2; //TODO add option #endif vk::Extent2D size{0,0}; public: vk::SwapchainKHR swapChain; SwapChain() = default; ~SwapChain() override { if (device) SwapChain::Close(); } void Init(Device* device, vk::SurfaceKHR surface, IVulkanWindow* window); void Close() override; void Resize(uint32_t newWidth, uint32_t newHeight); [[nodiscard]] vk::Extent2D GetSize() const { return size; } [[nodiscard]] const vk::Viewport& GetFullscreenViewport() const { return fullscreenViewport; } [[nodiscard]] const vk::Rect2D& GetFullscreenScissor() const { return fullscreenScissor; } uint32_t AcquireNextImage(const vk::Fence& fence = vk::Fence()); vk::Fence& GetCurrentSubmitFence() { return images[currentFrameBufferId].fence; } void Present(vk::Queue& queue ,std::vector& semaphores) const { const vk::Result result = queue.presentKHR(vk::PresentInfoKHR(semaphores.size(), semaphores.data(), 1, &swapChain, ¤tFrameBufferId)); if (result != vk::Result::eSuccess) [[unlikely]] { Logger::RENDER->error("Failed to preset swap chain image: {}", to_string(result)); } } [[nodiscard]] bool UseVsync() const { return useVsync; } void SetVsync(bool vsync) { //TODO change swap chain this->useVsync = vsync; } [[nodiscard]] uint32_t GetImageCount() const { return images.size(); } vk::Semaphore& GetCurrentSemaphore() { return imageAvailableSemaphores[currentSemaphoreId]; } private: void CreateSwapChain(vk::Extent2D size); void CreateSwapChainImages(); void DestroySwapChain(); protected: vk::Format FindColorFormat() override { return surfaceFormat.format; } virtual vk::PresentModeKHR ChosePresentMode(); virtual vk::SurfaceFormatKHR ChoseSurfaceFormat(); public: std::vector GetImages() override; }; } }