gravitron 0.1.2

A GameEngine based on an ECS and Vulkan
Documentation
use std::mem::ManuallyDrop;

use anyhow::Error;
use debug::Debugger;
use device::Device;
use gpu_allocator::vulkan;
use graphics::Renderer;
use instance::{InstanceDevice, InstanceDeviceConfig};
use surface::Surface;
use winit::window::Window;

use crate::config::{app::AppConfig, vulkan::VulkanConfig};

mod debug;
mod device;
pub mod error;
mod graphics;
mod instance;
mod surface;

pub(crate) struct Vulkan {
  #[allow(dead_code)]
  entry: ash::Entry,
  debugger: Option<Debugger>,
  instance: InstanceDevice,
  window: Window,
  surface: Surface,
  device: Device,
  renderer: Renderer,
  allocator: ManuallyDrop<vulkan::Allocator>,
}

impl Vulkan {
  pub(crate) fn init(mut config: VulkanConfig, app_config: &AppConfig, window: Window) -> Result<Self, Error> {
    let entry = unsafe { ash::Entry::load() }?;

    let debugger_info = if config.renderer.debug {
      Some(Debugger::init_info(&mut config.renderer))
    } else {
      None
    };

    let mut instance_config = InstanceDeviceConfig::default()
      .add_layers(config.renderer.layers.clone())
      .add_extensions(config.renderer.instance_extensions.clone())
      .add_instance_nexts(std::mem::take(&mut config.renderer.instance_next));

    let instance = InstanceDevice::init(&mut instance_config, &entry, app_config)?;

    let debugger = if config.renderer.debug {
      Some(Debugger::init(
        &entry,
        instance.get_instance(),
        debugger_info.unwrap(),
      )?)
    } else {
      None
    };

    let surface = Surface::init(&entry, instance.get_instance(), &window)?;
    let device = Device::init(
      instance.get_instance(),
      instance.get_physical_device(),
      &surface,
      &config.renderer,
    )?;

    let mut allocator = vulkan::Allocator::new(&vulkan::AllocatorCreateDesc {
      device: device.get_device().clone(),
      physical_device: instance.get_physical_device(),
      instance: instance.get_instance().clone(),
      debug_settings: Default::default(),
      buffer_device_address: false,
      allocation_sizes: Default::default(),
    })?;

    let renderer = Renderer::init(&instance, &device, &mut allocator, &surface, &mut config, app_config)?;

    Ok(Vulkan {
      entry,
      debugger,
      instance,
      window,
      surface,
      device,
      renderer,
      allocator: ManuallyDrop::new(allocator),
    })
  }

  pub(crate) fn request_redraw(&self) {
    self.window.request_redraw();
  }

  pub(crate) fn destroy(&mut self) {
    self.renderer.destroy(self.device.get_device(), &mut self.allocator);
    unsafe {
      ManuallyDrop::drop(&mut self.allocator);
    }
    self.device.destroy();
    self.surface.destroy();
    if let Some(debugger) = &mut self.debugger {
      debugger.destroy();
    }
    self.instance.destroy();
  }
}