Program Listing for File VulkanRenderer.ixx

Program Listing for File VulkanRenderer.ixx#

Return to documentation for file (Src/GraphicsEngineVulkan/renderer/VulkanRenderer.ixx)

module;
#include <algorithm>
#include <array>
#include <gsl/gsl>
#include <memory>
#include <vector>
#include <vulkan/vulkan.hpp>

export module kataglyphis.vulkan.renderer;

import kataglyphis.vulkan.allocator;
import kataglyphis.vulkan.as_manager;
import kataglyphis.vulkan.buffer_manager;
import kataglyphis.vulkan.buffer;
import kataglyphis.shared.scene.camera;
import kataglyphis.vulkan.command_buffer_manager;
import kataglyphis.vulkan.device;
import kataglyphis.vulkan.global_ubo;
import kataglyphis.vulkan.gui;
import kataglyphis.vulkan.instance;
import kataglyphis.vulkan.path_tracing;
import kataglyphis.vulkan.post_stage;
import kataglyphis.vulkan.rasterizer;
import kataglyphis.vulkan.raytracing;
import kataglyphis.vulkan.scene_ubo;
import kataglyphis.vulkan.swapchain;
import kataglyphis.vulkan.scene;
import kataglyphis.vulkan.texture;
import kataglyphis.vulkan.window;

export namespace Kataglyphis {
class VulkanRenderer
{
  public:
    VulkanRenderer(gsl::not_null<Kataglyphis::Frontend::Window *> window,
      gsl::not_null<Scene *> scene,
      gsl::not_null<Kataglyphis::Frontend::GUI *> gui,
      Camera *camera);

    void draw_frame();

    void update_uniforms(Scene *scene_data, Camera *camera_data, Kataglyphis::Frontend::Window *window_data);

    void update_state_due_to_user_input(Kataglyphis::Frontend::GUI *frontend_gui);
    void finish_all_render_commands();
    void update_raytracing_descriptor_set(uint32_t image_index);
    bool has_device_lost() const { return device_lost_detected; }

    void clean_up();

    ~VulkanRenderer();

  private:
    void shader_hot_reload();

    // helper class for managing our buffers
    VulkanBufferManager vulkan_buffer_manager;

    // Vulkan instance, stores all per-application states
    VulkanInstance instance;

    // surface defined on windows as WIN32 window system, Linux f.e. X11, MacOS
    // also their own
    vk::SurfaceKHR surface{};
    void create_surface();

    std::unique_ptr<VulkanDevice> device;

    VulkanSwapChain vulkan_swap_chain;

    Kataglyphis::Frontend::Window *window;
    Scene *scene;
    Kataglyphis::Frontend::GUI *gui;

    // -- pools
    bool record_commands(uint32_t image_index);
    void create_command_pool();
    void clean_up_command_pools();
    vk::CommandPool graphics_command_pool{};

    // uniform buffers
    VulkanRendererInternals::GlobalUBO global_ubo{};
    std::vector<VulkanBuffer> global_ubo_buffer;
    VulkanRendererInternals::SceneUBO scene_ubo{};
    std::vector<VulkanBuffer> scene_ubo_buffer;
    void create_uniform_buffers();
    void update_uniform_buffers(uint32_t image_index);
    void clean_up_ubos();

    std::vector<vk::CommandBuffer> command_buffers;
    Kataglyphis::VulkanRendererInternals::CommandBufferManager command_buffer_manager;
    void create_command_buffers();

    Kataglyphis::VulkanRendererInternals::Raytracing raytracing_stage;
    Kataglyphis::VulkanRendererInternals::Rasterizer rasterizer;
    Kataglyphis::VulkanRendererInternals::PathTracing path_tracing;
    Kataglyphis::VulkanRendererInternals::PostStage post_stage;

    // new era of memory management for my project
    // for now on integrate vma
    Allocator allocator;

    // -- synchronization
    uint32_t current_frame{ 0 };
    uint32_t frame_sync_count{ 1 };
    std::vector<vk::Semaphore> image_available;
    std::vector<vk::Semaphore> render_finished_by_image;
    std::vector<vk::Fence> in_flight_fences;
    std::vector<vk::Fence> images_in_flight_fences;
    void create_synchronization();
    void clean_up_sync();

    // -- draw_frame helper methods
    struct FrameSyncResult
    {
        bool success{ false };
        bool needs_swapchain_recreate{ false };
        vk::Result result{ vk::Result::eSuccess };
    };
    FrameSyncResult wait_for_frame_fence();
    struct AcquireResult
    {
        bool success{ false };
        vk::Result result{ vk::Result::eSuccess };
        uint32_t image_index{ 0 };
        bool needs_swapchain_recreate{ false };
    };
    AcquireResult acquire_next_image();
    FrameSyncResult wait_for_image_fence(uint32_t image_index);
    FrameSyncResult begin_command_buffer(uint32_t image_index);
    FrameSyncResult submit_commands(uint32_t image_index, vk::Semaphore wait_semaphore, vk::Semaphore signal_semaphore);
    FrameSyncResult present_frame(uint32_t image_index, vk::Semaphore signal_semaphore);

    void end_imgui_frame_if_needed();
    void abort_frame_with_fatal_error(const char *message, vk::Result error_code);
    bool validate_frame_state();

    Kataglyphis::VulkanRendererInternals::ASManager as_manager;
    VulkanBuffer object_description_buffer;
    void create_object_description_buffer();

    vk::DescriptorPool descriptor_pool_shared_render_stages{};
    void create_descriptor_pool_shared_render_stages();
    vk::DescriptorSetLayout shared_render_descriptor_set_layout{};
    void create_shared_render_descriptor_set_layouts();
    std::vector<vk::DescriptorSet> shared_render_descriptor_set;
    void create_shared_render_descriptor_set();
    void update_textures_in_shared_render_descriptor_set();

    vk::DescriptorPool post_descriptor_pool{};
    vk::DescriptorSetLayout post_descriptor_set_layout{};
    std::vector<vk::DescriptorSet> post_descriptor_set;
    void create_post_descriptor_layout();
    void update_post_descriptor_sets();

    vk::DescriptorPool raytracing_descriptor_pool{};
    std::vector<vk::DescriptorSet> raytracing_descriptor_set;
    vk::DescriptorSetLayout raytracing_descriptor_set_layout{};

    vk::PipelineCache pipeline_cache{};

    void create_raytracing_descriptor_set_layouts();
    void create_raytracing_descriptor_sets();
    void update_raytracing_descriptor_sets();
    void create_raytracing_descriptor_pool();

    bool check_changed_framebuffer_size();
    bool device_lost_detected{ false };
};
}// namespace Kataglyphis