From 43821b0cffc5aa419c0218992f06f8962ae54a13 Mon Sep 17 00:00:00 2001 From: Frederico Linhares Date: Wed, 8 May 2024 17:56:29 -0300 Subject: refa Rename graphical engine to BluCat --- src/blucat/swapchain.cpp | 204 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 src/blucat/swapchain.cpp (limited to 'src/blucat/swapchain.cpp') diff --git a/src/blucat/swapchain.cpp b/src/blucat/swapchain.cpp new file mode 100644 index 0000000..1e521e4 --- /dev/null +++ b/src/blucat/swapchain.cpp @@ -0,0 +1,204 @@ +/* + * Copyright 2022-2024 Frederico de Oliveira Linhares + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "swapchain.hpp" + +#include "../core.hpp" + +#include + +namespace +{ + +void +load_swapchain(void *obj) +{ + auto self = static_cast(obj); + + // Surface formats. + uint32_t vk_surface_format_count; + std::vector vk_surface_formats; + vkGetPhysicalDeviceSurfaceFormatsKHR( + cg_core.vk_device_with_swapchain->physical_device, cg_core.window_surface, + &vk_surface_format_count, nullptr); + vk_surface_formats.resize(vk_surface_format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR( + cg_core.vk_device_with_swapchain->physical_device, cg_core.window_surface, + &vk_surface_format_count, vk_surface_formats.data()); + + VkSwapchainCreateInfoKHR swapchain_create_info = {}; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_create_info.pNext = nullptr; + swapchain_create_info.flags = 0; + swapchain_create_info.surface = cg_core.window_surface; + swapchain_create_info.minImageCount = 3; // triple buffering. + + self->image_format = vk_surface_formats[0].format; + swapchain_create_info.imageFormat = self->image_format; + swapchain_create_info.imageColorSpace = vk_surface_formats[0].colorSpace; + + swapchain_create_info.imageExtent = { + cg_core.display_width, cg_core.display_height}; + swapchain_create_info.imageArrayLayers = 1; + swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_create_info.queueFamilyIndexCount = 0; + swapchain_create_info.pQueueFamilyIndices = nullptr; + swapchain_create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; + swapchain_create_info.clipped = VK_FALSE; + swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; + + if(vkCreateSwapchainKHR( + cg_core.vk_device_with_swapchain->device, &swapchain_create_info, + nullptr, &self->swapchain) != VK_SUCCESS) + throw CommandError{"Vulkan failed to create swapchain."}; + + vkGetSwapchainImagesKHR( + cg_core.vk_device_with_swapchain->device, self->swapchain, + &self->images_count, nullptr); + self->images = new VkImage[self->images_count]; + vkGetSwapchainImagesKHR( + cg_core.vk_device_with_swapchain->device, self->swapchain, + &self->images_count, self->images); +} + +void +unload_swapchain(void *obj) +{ + auto self = static_cast(obj); + + delete[] self->images; + vkDestroySwapchainKHR( + cg_core.vk_device_with_swapchain->device, self->swapchain, nullptr); +} + +void +load_image_view(void *obj) +{ + auto self = static_cast(obj); + + self->image_views = new VkImageView[self->images_count]; + for(auto i{0}; i < self->images_count; i++) + { + VkImageViewCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.image = self->images[i]; + create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + create_info.format = self->image_format; + create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + create_info.subresourceRange.baseMipLevel = 0; + create_info.subresourceRange.levelCount = 1; + create_info.subresourceRange.baseArrayLayer = 0; + create_info.subresourceRange.layerCount = 1; + + if(vkCreateImageView( + cg_core.vk_device_with_swapchain->device, &create_info, nullptr, + &self->image_views[i])) + throw CommandError{"Could no create Image View for swapchain."}; + } +} + +void +unload_image_view(void *obj) +{ + auto self = static_cast(obj); + + for(auto i{0}; i < self->images_count; i++) + vkDestroyImageView( + cg_core.vk_device_with_swapchain->device, self->image_views[i], nullptr); +} + +void +load_frame_sync(void *obj) +{ + auto self = static_cast(obj); + + self->image_available_semaphores.resize(self->max_frames_in_flight); + self->render_finished_semaphores.resize(self->max_frames_in_flight); + self->in_flight_fences.resize(self->max_frames_in_flight); + + VkSemaphoreCreateInfo semaphore_info = {}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + semaphore_info.pNext = nullptr; + semaphore_info.flags = 0; + + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.pNext = nullptr; + fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + // FIXME: if this loop fails, it will not destroy the semaphores. + for(auto i{0}; i < self->max_frames_in_flight; i++) + { + if(vkCreateSemaphore( + cg_core.vk_device_with_swapchain->device, &semaphore_info, + nullptr, &self->image_available_semaphores[i]) != VK_SUCCESS || + vkCreateSemaphore( + cg_core.vk_device_with_swapchain->device, &semaphore_info, + nullptr, &self->render_finished_semaphores[i]) != VK_SUCCESS || + vkCreateFence(cg_core.vk_device_with_swapchain->device, &fence_info, + nullptr, &self->in_flight_fences[i]) != VK_SUCCESS) + throw CommandError{"Failed to create semaphores."}; + } +} + +void +unload_frame_sync(void *obj) +{ + auto self = static_cast(obj); + + vkDeviceWaitIdle(cg_core.vk_device_with_swapchain->device); + + for(auto i{0}; i < self->max_frames_in_flight; i++) + { + vkDestroySemaphore(cg_core.vk_device_with_swapchain->device, + self->render_finished_semaphores[i], nullptr); + vkDestroySemaphore(cg_core.vk_device_with_swapchain->device, + self->image_available_semaphores[i], nullptr); + vkDestroyFence(cg_core.vk_device_with_swapchain->device, + self->in_flight_fences[i], nullptr); + } +} + +const CommandChain loader{ + {&load_swapchain, &unload_swapchain}, + {&load_image_view, &unload_image_view}, + {&load_frame_sync, &unload_frame_sync} +}; + +} + +namespace BluCat +{ + +Swapchain::Swapchain(): + current_frame{0} +{ + loader.execute(this); +} + +Swapchain::~Swapchain() +{ + loader.revert(this); +} + +} -- cgit v1.2.3