/**
 * @file vulkan_render_pass.c
 * @author Piotr Krygier (piotrkrygier@everyonecancode.xyz)
 * @brief
 * @version 0.1
 * @date 20-02-2025
 *
 * @copyright Copyright (c) 2025
 *
 */

#include "vulkan_render_pass.h"

#include "vulkan_image.h"
#include "utilities/errors_common.h"

rse_err_t create_render_pass(struct graphics_context_t* context)
{
    rse_err_t status = RSE_ERROR_NO_ERROR;
    VkAttachmentDescription attachments[3] = {0};
    VkAttachmentDescription color_attachment = {0};
    VkAttachmentReference color_attachment_ref = {0};
    VkAttachmentDescription color_attachment_resolve = {0};
    VkAttachmentReference color_attachment_resolve_ref = {0};
    VkSubpassDescription subpass = {0};
    VkRenderPassCreateInfo renderpass_info = {0};
    VkAttachmentDescription depth_attachment = {0};
    VkAttachmentReference depth_attachment_ref = {0};
    VkSubpassDependency dependency = {0};

    STATUS_CHECK(find_depth_format(context, &depth_attachment.format));

    depth_attachment.samples = VK_SAMPLE_COUNT_8_BIT;
    depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
    depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    depth_attachment.finalLayout =
        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

    depth_attachment_ref.attachment = 1;
    depth_attachment_ref.layout =
        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

    color_attachment.flags = 0U;
    color_attachment.format = IMAGE_FORMAT;
    color_attachment.samples = VK_SAMPLE_COUNT_8_BIT;
    color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
    color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    color_attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    color_attachment_ref.attachment = 0;
    color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    color_attachment_resolve.format = IMAGE_FORMAT;
    color_attachment_resolve.samples = VK_SAMPLE_COUNT_1_BIT;
    color_attachment_resolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    color_attachment_resolve.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    color_attachment_resolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    color_attachment_resolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    color_attachment_resolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    color_attachment_resolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

    color_attachment_resolve_ref.attachment = 2;
    color_attachment_resolve_ref.layout =
        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
    subpass.colorAttachmentCount = 1;
    subpass.pColorAttachments = &color_attachment_ref;
    subpass.pDepthStencilAttachment = &depth_attachment_ref;
    subpass.pResolveAttachments = &color_attachment_resolve_ref;

    attachments[0] = color_attachment;
    attachments[1] = depth_attachment;
    attachments[2] = color_attachment_resolve;

    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_WRITE_BIT |
                               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;

    renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
    renderpass_info.attachmentCount = 3;
    renderpass_info.pAttachments = attachments;
    renderpass_info.subpassCount = 1;
    renderpass_info.pSubpasses = &subpass;
    renderpass_info.dependencyCount = 1;
    renderpass_info.pDependencies = &dependency;

    if (VK_SUCCESS != vkCreateRenderPass(context->vulkan_handles.device, &renderpass_info,
                                         NULL, &context->vulkan_handles.render_pass)) {
        SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create render pass");
        return RSE_ERROR_INTERNAL_ERROR;
    }

    return RSE_ERROR_NO_ERROR;
}

void destroy_render_pass(struct graphics_context_t* context)
{
    vkDestroyRenderPass(context->vulkan_handles.device, context->vulkan_handles.render_pass, NULL);
}
