diff options
author | Frederico Linhares <fred@linhares.blue> | 2024-12-31 12:32:36 -0300 |
---|---|---|
committer | Frederico Linhares <fred@linhares.blue> | 2024-12-31 19:03:51 -0300 |
commit | 736637680ac7b2cd0d0b878401a7e044fde0ee6a (patch) | |
tree | bf4feaf3f3f0e48207bf7a31ad8bcbff0f244091 /src/blu_cat/gra/swapchain.cpp | |
parent | 083e64da1d4b5b68579288bc1690ca90d3f0a2c0 (diff) |
Diffstat (limited to 'src/blu_cat/gra/swapchain.cpp')
-rw-r--r-- | src/blu_cat/gra/swapchain.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/blu_cat/gra/swapchain.cpp b/src/blu_cat/gra/swapchain.cpp new file mode 100644 index 0000000..f57e3c2 --- /dev/null +++ b/src/blu_cat/gra/swapchain.cpp @@ -0,0 +1,207 @@ +/* + * 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 "../int/core.hpp" + +#include <vector> + +namespace +{ + +void +load_swapchain(void *obj) +{ + auto self = static_cast<BluCat::GRA::Swapchain*>(obj); + + // Surface formats. + uint32_t vk_surface_format_count; + std::vector<VkSurfaceFormatKHR> vk_surface_formats; + vkGetPhysicalDeviceSurfaceFormatsKHR( + BluCat::INT::core.vk_device_with_swapchain->physical_device, + BluCat::INT::core.window_surface, &vk_surface_format_count, nullptr); + vk_surface_formats.resize(vk_surface_format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR( + BluCat::INT::core.vk_device_with_swapchain->physical_device, + BluCat::INT::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 = BluCat::INT::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 = { + BluCat::INT::core.display_width, BluCat::INT::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( + BluCat::INT::core.vk_device_with_swapchain->device, &swapchain_create_info, + nullptr, &self->swapchain) != VK_SUCCESS) + throw CommandError{"Vulkan failed to create swapchain."}; + + vkGetSwapchainImagesKHR( + BluCat::INT::core.vk_device_with_swapchain->device, self->swapchain, + &self->images_count, nullptr); + self->images = new VkImage[self->images_count]; + vkGetSwapchainImagesKHR( + BluCat::INT::core.vk_device_with_swapchain->device, self->swapchain, + &self->images_count, self->images); +} + +void +unload_swapchain(void *obj) +{ + auto self = static_cast<BluCat::GRA::Swapchain*>(obj); + + delete[] self->images; + vkDestroySwapchainKHR( + BluCat::INT::core.vk_device_with_swapchain->device, self->swapchain, nullptr); +} + +void +load_image_view(void *obj) +{ + auto self = static_cast<BluCat::GRA::Swapchain*>(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( + BluCat::INT::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<BluCat::GRA::Swapchain*>(obj); + + for(auto i{0}; i < self->images_count; i++) + vkDestroyImageView( + BluCat::INT::core.vk_device_with_swapchain->device, self->image_views[i], + nullptr); +} + +void +load_frame_sync(void *obj) +{ + auto self = static_cast<BluCat::GRA::Swapchain*>(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( + BluCat::INT::core.vk_device_with_swapchain->device, &semaphore_info, + nullptr, &self->image_available_semaphores[i]) != VK_SUCCESS || + vkCreateSemaphore( + BluCat::INT::core.vk_device_with_swapchain->device, &semaphore_info, + nullptr, &self->render_finished_semaphores[i]) != VK_SUCCESS || + vkCreateFence( + BluCat::INT::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<BluCat::GRA::Swapchain*>(obj); + + vkDeviceWaitIdle(BluCat::INT::core.vk_device_with_swapchain->device); + + for(auto i{0}; i < self->max_frames_in_flight; i++) + { + vkDestroySemaphore(BluCat::INT::core.vk_device_with_swapchain->device, + self->render_finished_semaphores[i], nullptr); + vkDestroySemaphore(BluCat::INT::core.vk_device_with_swapchain->device, + self->image_available_semaphores[i], nullptr); + vkDestroyFence(BluCat::INT::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::GRA +{ + +Swapchain::Swapchain(): + current_frame{0} +{ + loader.execute(this); +} + +Swapchain::~Swapchain() +{ + loader.revert(this); +} + +} |