/* * 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 "framebuffer.hpp" #include "../core.hpp" #include "image.hpp" namespace { void load_depth_image(void *obj) { auto self = static_cast(obj); VkExtent3D extent3d{}; extent3d.width = cg_core.display_width; extent3d.height = cg_core.display_height; extent3d.depth = 1; try { BluCat::Image::create( cg_core.vk_device_with_swapchain, &self->depth_image, &self->depth_image_memory, VK_FORMAT_D32_SFLOAT, extent3d, 1, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ); } catch(BluCat::Image::Error error) { std::string error_message{"Failed to create depth image → "}; error_message += error.what(); throw CommandError{error_message}; } } void unload_depth_image(void *obj) { auto self = static_cast(obj); vkDestroyImage( cg_core.vk_device_with_swapchain->device, self->depth_image, nullptr); vkFreeMemory( cg_core.vk_device_with_swapchain->device, self->depth_image_memory, nullptr); } void load_depth_image_view(void *obj) { auto self = static_cast(obj); try { BluCat::Image::create_view( cg_core.vk_device_with_swapchain, &self->depth_image_view, self->depth_image, VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT); } catch(BluCat::Image::Error error) { std::string error_message{"Failed to create depth image view → "}; error_message += error.what(); throw CommandError{error_message}; } } void unload_depth_image_view(void *obj) { auto self = static_cast(obj); vkDestroyImageView( cg_core.vk_device_with_swapchain->device, self->depth_image_view, nullptr); } void load_3d(void *obj) { auto self = static_cast(obj); self->pipeline_3d.resize(cg_core.vk_swapchain->images_count); for (auto i{0}; i < cg_core.vk_swapchain->images_count; i++) { std::array attachments = { cg_core.vk_swapchain->image_views[i], self->depth_image_view }; VkFramebufferCreateInfo framebuffer_info{}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = cg_core.vk_render_pass->pipeline_3d; framebuffer_info.attachmentCount = attachments.size(); framebuffer_info.pAttachments = attachments.data(); framebuffer_info.width = cg_core.display_width; framebuffer_info.height = cg_core.display_height; framebuffer_info.layers = 1; if(vkCreateFramebuffer( cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr, &self->pipeline_3d[i]) != VK_SUCCESS) throw CommandError{"Failed to create Vulkan Framebuffer."}; } } void unload_3d(void *obj) { auto self = static_cast(obj); for(auto framebuffer: self->pipeline_3d) vkDestroyFramebuffer( cg_core.vk_device_with_swapchain->device, framebuffer, nullptr); } void load_2d(void *obj) { auto self = static_cast(obj); self->pipeline_2d.resize(cg_core.vk_swapchain->images_count); for (auto i{0}; i < cg_core.vk_swapchain->images_count; i++) { std::array attachments = { cg_core.vk_swapchain->image_views[i] }; VkFramebufferCreateInfo framebuffer_info{}; framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebuffer_info.renderPass = cg_core.vk_render_pass->pipeline_2d; framebuffer_info.attachmentCount = attachments.size(); framebuffer_info.pAttachments = attachments.data(); framebuffer_info.width = cg_core.display_width; framebuffer_info.height = cg_core.display_height; framebuffer_info.layers = 1; if(vkCreateFramebuffer( cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr, &self->pipeline_2d[i]) != VK_SUCCESS) throw CommandError{"Failed to create Vulkan Framebuffer."}; } } void unload_2d(void *obj) { auto self = static_cast(obj); for(auto framebuffer: self->pipeline_2d) vkDestroyFramebuffer( cg_core.vk_device_with_swapchain->device, framebuffer, nullptr); } const CommandChain loader{ {&load_depth_image, &unload_depth_image}, {&load_depth_image_view, &unload_depth_image_view}, {&load_3d, &unload_3d}, {&load_2d, &unload_2d} }; } namespace BluCat { Framebuffer::Framebuffer() { loader.execute(this); } Framebuffer::~Framebuffer() { loader.revert(this); } }