crystal-api 0.0.6

Crystal API is a unified GPU API's wrapper
Documentation
use std::sync::Arc;

use ash::vk;

use crate::{
    debug::error,
    errors::{GraphicsError, GraphicsResult},
    vulkan::API_VERSION_LATEST,
};

pub(crate) fn create_instance(
    addition_extension: &[*const i8],
) -> GraphicsResult<(
    Arc<ash::Entry>,
    Arc<ash::Instance>,
    Option<super::debug_callback::DebugUtilsMessanger>,
)> {
    let mut instance_extensions = vec![
        #[cfg(debug_assertions)]
        vk::EXT_DEBUG_UTILS_NAME.as_ptr(),
        #[cfg(target_vendor = "apple")]
        vk::KHR_PORTABILITY_ENUMERATION_NAME.as_ptr(),
    ];

    addition_extension
        .iter()
        .for_each(|ext| instance_extensions.push(*ext));

    let entry = match unsafe { ash::Entry::load() } {
        Ok(entry) => Arc::new(entry),
        Err(e) => {
            error!("cannot load vulkan entry: {}", e);
            return GraphicsResult::Err(GraphicsError::ConnotInitLibrary);
        }
    };

    let flags = if cfg!(target_vendor = "apple") {
        vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR
    } else {
        vk::InstanceCreateFlags::empty()
    };

    let app_info = vk::ApplicationInfo::default().api_version(API_VERSION_LATEST);
    #[cfg(not(debug_assertions))]
    let create_info = vk::InstanceCreateInfo::default()
        .flags(flags)
        .application_info(&app_info)
        .enabled_extension_names(&instance_extensions);

    #[cfg(debug_assertions)]
    let layers;
    #[cfg(debug_assertions)]
    let layers_pp: Vec<*const i8>;

    #[cfg(debug_assertions)]
    let create_info = {
        layers = super::validation::get_supported_validation_layers(&entry);

        if layers.is_empty() {
            error!(
                "No validation layers found!
                Vulkan SDK should be installed for proper debug.
                Visit https://vulkan.lunarg.com/"
            );

            vk::InstanceCreateInfo::default()
                .flags(flags)
                .application_info(&app_info)
                .enabled_extension_names(&instance_extensions)
        } else {
            layers_pp = layers.iter().map(|x| x.as_ptr()).collect();

            let mut create_info = vk::InstanceCreateInfo::default()
                .flags(flags)
                .application_info(&app_info)
                .enabled_extension_names(&instance_extensions);

            create_info.pp_enabled_layer_names = layers_pp.as_ptr();
            create_info.enabled_layer_count = layers_pp.len() as u32;

            create_info
        }
    };

    let instance = match unsafe { entry.create_instance(&create_info, None) } {
        Err(e) => {
            error!("cannot create vulkan instance: {}", e);
            return GraphicsResult::Err(GraphicsError::ConnotInitLibrary);
        }
        Ok(instance) => Arc::new(instance),
    };

    let debug_utils_messanger = {
        #[cfg(debug_assertions)]
        match super::debug_callback::create_debug_utils_messanger(&entry, &instance) {
            Ok(debug_utils_messanger) => {
                crate::debug::log!("debug_utils_messanger created");
                Some(debug_utils_messanger)
            }
            Err(e) => {
                error!("debug_utils_messanger creation error: {}", e);
                None
            }
        }

        #[cfg(not(debug_assertions))]
        None
    };

    Ok((entry, instance, debug_utils_messanger))
}