Some checks failed
		
		
	
	continuous-integration/drone/push Build is failing
				
			Reviewed-on: #57 Co-authored-by: light7734 <light7734@tuta.io> Co-committed-by: light7734 <light7734@tuta.io>
		
			
				
	
	
		
			155 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <ranges>
 | |
| #include <renderer/backend/vk/context/device.hpp>
 | |
| #include <renderer/backend/vk/context/gpu.hpp>
 | |
| #include <renderer/backend/vk/context/instance.hpp>
 | |
| #include <renderer/backend/vk/context/surface.hpp>
 | |
| #include <renderer/backend/vk/context/swapchain.hpp>
 | |
| #include <renderer/backend/vk/utils.hpp>
 | |
| 
 | |
| namespace lt::renderer::vk {
 | |
| 
 | |
| Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
 | |
|     : m_surface(static_cast<Surface *>(surface))
 | |
|     , m_gpu(static_cast<Gpu *>(gpu))
 | |
|     , m_device(static_cast<Device *>(device))
 | |
| {
 | |
| 	static auto idx = 0u;
 | |
| 
 | |
| 	const auto capabilities = m_gpu->get_surface_capabilities(m_surface->vk());
 | |
| 	const auto formats = m_gpu->get_surface_formats(m_surface->vk());
 | |
| 
 | |
| 	// TODO(Light): parameterize
 | |
| 	constexpr auto desired_image_count = uint32_t { 3 };
 | |
| 	const auto surface_format = formats.front();
 | |
| 	const auto queue_indices = m_device->get_family_indices();
 | |
| 	m_format = surface_format.format;
 | |
| 
 | |
| 	m_swapchain = m_device->create_swapchain(
 | |
| 	    VkSwapchainCreateInfoKHR {
 | |
| 	        .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
 | |
| 	        .surface = m_surface->vk(),
 | |
| 	        .minImageCount = get_optimal_image_count(capabilities, desired_image_count),
 | |
| 	        .imageFormat = surface_format.format,
 | |
| 	        .imageColorSpace = surface_format.colorSpace,
 | |
| 	        .imageExtent = capabilities.currentExtent,
 | |
| 	        .imageArrayLayers = 1u,
 | |
| 	        .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
 | |
| 	        .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
 | |
| 	        .queueFamilyIndexCount = queue_indices.size(),
 | |
| 	        .pQueueFamilyIndices = queue_indices.data(),
 | |
| 	        .preTransform = capabilities.currentTransform,
 | |
| 	        .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
 | |
| 	        .presentMode = VK_PRESENT_MODE_FIFO_KHR, // TODO(Light): parameterize
 | |
| 	        .clipped = VK_TRUE,
 | |
| 	        .oldSwapchain = nullptr,
 | |
| 	    }
 | |
| 	);
 | |
| 	m_resolution = capabilities.currentExtent;
 | |
| 	m_device->name(m_swapchain, "swapchain {}", idx++);
 | |
| 	m_device->wait_idle();
 | |
| 
 | |
| 
 | |
| 	m_images = m_device->get_swapchain_images(m_swapchain);
 | |
| 	m_image_views.resize(m_images.size());
 | |
| 	for (auto idx = 0u; auto [image, view] : std::views::zip(m_images, m_image_views))
 | |
| 	{
 | |
| 		view = m_device->create_image_view(VkImageViewCreateInfo {
 | |
| 			.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
 | |
| 			.image = image,
 | |
| 			.viewType = VK_IMAGE_VIEW_TYPE_2D,
 | |
| 			.format = surface_format.format,
 | |
|             .components = VkComponentMapping {
 | |
|                 .r = VK_COMPONENT_SWIZZLE_IDENTITY,
 | |
|                 .g = VK_COMPONENT_SWIZZLE_IDENTITY,
 | |
|                 .b = VK_COMPONENT_SWIZZLE_IDENTITY,
 | |
|                 .a = VK_COMPONENT_SWIZZLE_IDENTITY,
 | |
|             },
 | |
|             .subresourceRange = VkImageSubresourceRange {
 | |
|                 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
 | |
|                 .baseMipLevel = 0u,
 | |
|                 .levelCount = 1u,
 | |
|                 .baseArrayLayer = 0u,
 | |
|                 .layerCount = 1u,
 | |
|             }
 | |
| 		});
 | |
| 
 | |
| 		m_device->name(image, "swapchain image {}", idx++);
 | |
| 		m_device->name(view, "swapchain image view {}", idx++);
 | |
| 	}
 | |
| 	m_device->wait_idle();
 | |
| }
 | |
| 
 | |
| Swapchain::~Swapchain()
 | |
| {
 | |
| 	if (!m_surface)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	try
 | |
| 	{
 | |
| 		m_device->wait_idle();
 | |
| 		m_device->destroy_image_views(m_image_views);
 | |
| 		m_device->destroy_swapchain(m_swapchain);
 | |
| 		m_device->wait_idle();
 | |
| 	}
 | |
| 	catch (const std::exception &exp)
 | |
| 	{
 | |
| 		log_err("Failed to destroy swapchain:");
 | |
| 		log_err("\twhat: {}", exp.what());
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| [[nodiscard]] auto Swapchain::create_framebuffers_for_pass(VkRenderPass pass) const
 | |
|     -> std::vector<VkFramebuffer>
 | |
| {
 | |
| 	auto framebuffers = std::vector<VkFramebuffer>(m_image_views.size());
 | |
| 
 | |
| 	for (auto idx = 0u; auto &framebuffer : framebuffers)
 | |
| 	{
 | |
| 		framebuffer = m_device->create_framebuffer(
 | |
| 		    VkFramebufferCreateInfo {
 | |
| 		        .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
 | |
| 		        .renderPass = pass,
 | |
| 		        .attachmentCount = 1u,
 | |
| 		        .pAttachments = &m_image_views[idx++],
 | |
| 		        .width = m_resolution.width,
 | |
| 		        .height = m_resolution.height,
 | |
| 		        .layers = 1u,
 | |
| 		    }
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	return framebuffers;
 | |
| }
 | |
| 
 | |
| [[nodiscard]] auto Swapchain::get_optimal_image_count(
 | |
|     VkSurfaceCapabilitiesKHR capabilities,
 | |
|     uint32_t desired_image_count
 | |
| ) const -> uint32_t
 | |
| {
 | |
| 	const auto min_image_count = capabilities.minImageCount;
 | |
| 	const auto max_image_count = capabilities.maxImageCount;
 | |
| 
 | |
| 	const auto has_max_limit = max_image_count != 0;
 | |
| 
 | |
| 	// Desired image count is in range
 | |
| 	if ((!has_max_limit || max_image_count >= desired_image_count)
 | |
| 	    && min_image_count <= desired_image_count)
 | |
| 	{
 | |
| 		return desired_image_count;
 | |
| 	}
 | |
| 
 | |
| 	// Fall-back to 2 if in ange
 | |
| 	if (min_image_count <= 2 && max_image_count >= 2)
 | |
| 	{
 | |
| 		return 2;
 | |
| 	}
 | |
| 
 | |
| 	// Fall-back to min_image_count
 | |
| 	return min_image_count;
 | |
| }
 | |
| 
 | |
| 
 | |
| } // namespace lt::renderer::vk
 |