diff options
Diffstat (limited to 'src/vk/render_pass.cpp')
| -rw-r--r-- | src/vk/render_pass.cpp | 203 | 
1 files changed, 203 insertions, 0 deletions
| diff --git a/src/vk/render_pass.cpp b/src/vk/render_pass.cpp new file mode 100644 index 0000000..799cde4 --- /dev/null +++ b/src/vk/render_pass.cpp @@ -0,0 +1,203 @@ +/* + * Copyright 2022-2023 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 "render_pass.hpp" + +#include <array> + +#include "../core.hpp" + +namespace +{ + +void +load_3d(void *obj) +{ +  auto self = static_cast<VK::RenderPass*>(obj); + +  std::array<VkAttachmentDescription, 2> attachments{}; +  // Color attachment. +  attachments[0].flags = 0; +  attachments[0].format = cg_core.vk_swapchain->image_format; +  attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; +  attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; +  attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; +  attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; +  attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; +  attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +  attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +  // Depth attachment. +  attachments[1].flags = 0; +  attachments[1].format = VK_FORMAT_D32_SFLOAT; +  attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; +  attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; +  attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; +  attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; +  attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; +  attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +  attachments[1].finalLayout = +      VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + +  VkAttachmentReference color_attachment_ref{}; +  color_attachment_ref.attachment = 0; +  color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +  VkAttachmentReference depth_attachment_ref{}; +  depth_attachment_ref.attachment = 1; +  depth_attachment_ref.layout = +    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + +  VkSubpassDescription subpass = {}; +  subpass.flags = 0; +  subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; +  subpass.inputAttachmentCount = 0; +  subpass.pInputAttachments = nullptr; +  subpass.colorAttachmentCount = 1; +  subpass.pColorAttachments = &color_attachment_ref; +  subpass.pResolveAttachments = nullptr; +  subpass.pDepthStencilAttachment = &depth_attachment_ref; +  subpass.preserveAttachmentCount = 0; +  subpass.pPreserveAttachments = nullptr; + +  VkSubpassDependency dependency = {}; +  dependency.srcSubpass = VK_SUBPASS_EXTERNAL; +  dependency.dstSubpass = 0; +  dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | +    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; +  dependency.srcAccessMask = 0; +  dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | +    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; +  dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | +    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | +    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + +  VkRenderPassCreateInfo render_pass_info{}; +  render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; +  render_pass_info.pNext = nullptr; +  render_pass_info.flags = 0; +  render_pass_info.attachmentCount = attachments.size(); +  render_pass_info.pAttachments = attachments.data(); +  render_pass_info.subpassCount = 1; +  render_pass_info.pSubpasses = &subpass; +  render_pass_info.dependencyCount = 1; +  render_pass_info.pDependencies = &dependency; + +  if(vkCreateRenderPass( +       cg_core.vk_device_with_swapchain->device, &render_pass_info, nullptr, +       &self->pipeline_3d) != VK_SUCCESS) +    throw CommandError{"Failed to create Vulkan Render Pass 3D."}; +} + +void +unload_3d(void *obj) +{ +  auto self = static_cast<VK::RenderPass*>(obj); + +  vkDestroyRenderPass( +    cg_core.vk_device_with_swapchain->device, self->pipeline_3d, nullptr); +} + +void +load_2d(void *obj) +{ +  auto self = static_cast<VK::RenderPass*>(obj); + +  std::array<VkAttachmentDescription, 1> attachments{}; +  // Color attachment. +  attachments[0].flags = 0; +  attachments[0].format = cg_core.vk_swapchain->image_format; +  attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; +  attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; +  attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; +  attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; +  attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; +  attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; +  attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + +  VkAttachmentReference color_attachment_ref{}; +  color_attachment_ref.attachment = 0; +  color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + +  VkSubpassDescription subpass{}; +  subpass.flags = 0; +  subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; +  subpass.inputAttachmentCount = 0; +  subpass.pInputAttachments = nullptr; +  subpass.colorAttachmentCount = 1; +  subpass.pColorAttachments = &color_attachment_ref; +  subpass.pResolveAttachments = nullptr; +  subpass.pDepthStencilAttachment = nullptr; +  subpass.preserveAttachmentCount = 0; +  subpass.pPreserveAttachments = nullptr; + +  VkSubpassDependency dependency{}; +  dependency.srcSubpass = VK_SUBPASS_EXTERNAL; +  dependency.dstSubpass = 0; +  dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | +    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; +  dependency.srcAccessMask = 0; +  dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | +    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; +  dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | +    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | +    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + +  VkRenderPassCreateInfo render_pass_info{}; +  render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; +  render_pass_info.pNext = nullptr; +  render_pass_info.flags = 0; +  render_pass_info.attachmentCount = attachments.size(); +  render_pass_info.pAttachments = attachments.data(); +  render_pass_info.subpassCount = 1; +  render_pass_info.pSubpasses = &subpass; +  render_pass_info.dependencyCount = 1; +  render_pass_info.pDependencies = &dependency; + +  if(vkCreateRenderPass( +       cg_core.vk_device_with_swapchain->device, &render_pass_info, +       nullptr, &self->pipeline_2d) != VK_SUCCESS) +    throw CommandError{"Failed to create Vulkan Render Pass 2D."}; +} + +void +unload_2d(void *obj) +{ +  auto self = static_cast<VK::RenderPass*>(obj); + +  vkDestroyRenderPass( +    cg_core.vk_device_with_swapchain->device, self->pipeline_2d, nullptr); +} + +const CommandChain loader{ +  {&load_3d, &unload_3d}, +  {&load_2d, &unload_2d} +}; + +} + +namespace VK +{ + +RenderPass::RenderPass() +{ +  loader.execute(this); +} + +RenderPass::~RenderPass() +{ +  loader.revert(this); +} + +} | 
