diff options
Diffstat (limited to 'src/blu_cat/gra/framebuffer.cpp')
-rw-r--r-- | src/blu_cat/gra/framebuffer.cpp | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/blu_cat/gra/framebuffer.cpp b/src/blu_cat/gra/framebuffer.cpp new file mode 100644 index 0000000..e2d0b7c --- /dev/null +++ b/src/blu_cat/gra/framebuffer.cpp @@ -0,0 +1,200 @@ +/* + * 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 "../com/command.hpp" +#include "../int/core.hpp" +#include "image.hpp" + +namespace +{ +void +load_depth_image(void *obj) +{ + auto self = static_cast<BluCat::GRA::Framebuffer*>(obj); + + VkExtent3D extent3d{}; + extent3d.width = BluCat::INT::core.display_width; + extent3d.height = BluCat::INT::core.display_height; + extent3d.depth = 1; + + try + { + BluCat::GRA::Image::create( + BluCat::INT::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::GRA::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<BluCat::GRA::Framebuffer*>(obj); + + vkDestroyImage( + BluCat::INT::core.vk_device_with_swapchain->device, self->depth_image, + nullptr); + vkFreeMemory( + BluCat::INT::core.vk_device_with_swapchain->device, + self->depth_image_memory, nullptr); +} + +void +load_depth_image_view(void *obj) +{ + auto self = static_cast<BluCat::GRA::Framebuffer*>(obj); + + try + { + BluCat::GRA::Image::create_view( + BluCat::INT::core.vk_device_with_swapchain, &self->depth_image_view, + self->depth_image, + VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT); + } + catch(BluCat::GRA::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<BluCat::GRA::Framebuffer*>(obj); + + vkDestroyImageView( + BluCat::INT::core.vk_device_with_swapchain->device, self->depth_image_view, + nullptr); +} + +void +load_3d(void *obj) +{ + auto self = static_cast<BluCat::GRA::Framebuffer*>(obj); + + self->pipeline_3d.resize(BluCat::INT::core.vk_swapchain->images_count); + for (auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + { + std::array<VkImageView, 2> attachments = { + BluCat::INT::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 = BluCat::INT::core.vk_render_pass->pipeline_3d; + framebuffer_info.attachmentCount = attachments.size(); + framebuffer_info.pAttachments = attachments.data(); + framebuffer_info.width = BluCat::INT::core.display_width; + framebuffer_info.height = BluCat::INT::core.display_height; + + framebuffer_info.layers = 1; + + if(vkCreateFramebuffer( + BluCat::INT::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<BluCat::GRA::Framebuffer*>(obj); + + for(auto framebuffer: self->pipeline_3d) + vkDestroyFramebuffer( + BluCat::INT::core.vk_device_with_swapchain->device, framebuffer, nullptr); +} + +void +load_2d(void *obj) +{ + auto self = static_cast<BluCat::GRA::Framebuffer*>(obj); + + self->pipeline_2d.resize(BluCat::INT::core.vk_swapchain->images_count); + for (auto i{0}; i < BluCat::INT::core.vk_swapchain->images_count; i++) + { + std::array<VkImageView, 1> attachments = { + BluCat::INT::core.vk_swapchain->image_views[i] + }; + + VkFramebufferCreateInfo framebuffer_info{}; + framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebuffer_info.renderPass = BluCat::INT::core.vk_render_pass->pipeline_2d; + framebuffer_info.attachmentCount = attachments.size(); + framebuffer_info.pAttachments = attachments.data(); + framebuffer_info.width = BluCat::INT::core.display_width; + framebuffer_info.height = BluCat::INT::core.display_height; + framebuffer_info.layers = 1; + + if(vkCreateFramebuffer( + BluCat::INT::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<BluCat::GRA::Framebuffer*>(obj); + + for(auto framebuffer: self->pipeline_2d) + vkDestroyFramebuffer( + BluCat::INT::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::GRA +{ + +Framebuffer::Framebuffer() +{ + loader.execute(this); +} + +Framebuffer::~Framebuffer() +{ + loader.revert(this); +} + +} |