rotex-vulkan 0.1.1

A Vulkan backend for rotex_core
Documentation
mod buffer;
mod command;
mod descriptor;
mod device;
mod framebuffer;
mod graphics_pipeline;
mod image;
mod pass;
mod swapchain;
mod sync;

pub use buffer::RotexBuffer;
pub use command::{CommandBuffer, CommandPool};
pub use descriptor::{DescriptorPool, DescriptorSet};
pub use device::{Adapter, Device, DeviceDescriptor, QueueAllocation, QueueCategory, QueueRequest};
pub use framebuffer::{Framebuffer, FramebufferBuilder};
pub use graphics_pipeline::{
    ColorBlendAttachmentState, ColorBlendState, DepthStencilState, DescriptorSetLayout,
    GraphicsPipeline, GraphicsPipelineBuilder, GraphicsPipelineLayout, RasterizationState,
    ShaderModule, ShaderStageDescriptor, Vertex, VertexInputDescriptor,
};
pub use image::{ImageDescriptor, RotexImage, RotexSampler, SamplerDescriptor};
pub use pass::{RenderPass, RenderPassBuilder, SubpassBlueprint};
pub use swapchain::{Surface, Swapchain};
pub use sync::{Fence, Semaphore};

use ash::vk;
use std::cmp::Reverse;

use crate::core::{DebugMessenger, Instance, InstanceOptions};
use crate::error::{Error, ErrorKind, Severity};

pub(crate) struct VulkanInstance {
    raw: Instance,
    debug: Option<DebugMessenger>,
}

impl VulkanInstance {
    pub(crate) fn new(options: &InstanceOptions, extensions: &[*const i8]) -> Result<Self, Error> {
        let (raw, debug) = Instance::new_with_options(options, extensions)?;
        Ok(Self { raw, debug })
    }

    pub(crate) fn request_device(&self, desc: DeviceDescriptor) -> Result<VulkanDevice, Error> {
        let mut adapters = self.raw.enumerate_adapters();
        if adapters.is_empty() {
            return Err(Error {
                kind: ErrorKind::NoCompatibleDevice,
                severity: Severity::Fatal,
            });
        }
        adapters.sort_by_key(|adapter| Reverse(adapter.selection_score()));

        let mut last_error = None;
        for adapter in adapters {
            if !adapter.supports_queue_requests(&self.raw, &desc.queues) {
                continue;
            }
            if desc.enable_swapchain && !adapter.has_swapchain_extension(&self.raw)? {
                continue;
            }
            match adapter.request_device(&self.raw, desc.clone()) {
                Ok(device) => {
                    eprintln!(
                        "[vulkan] selected adapter: {} ({:?})",
                        adapter.name(),
                        adapter.device_type()
                    );
                    return Ok(VulkanDevice { raw: device });
                }
                Err(err) => {
                    last_error = Some(err);
                }
            }
        }

        Err(last_error.unwrap_or(Error {
            kind: ErrorKind::NoCompatibleDevice,
            severity: Severity::Fatal,
        }))
    }

    pub(crate) fn create_surface_from_raw(&self, raw_surface: vk::SurfaceKHR) -> VulkanSurface {
        VulkanSurface {
            raw: Surface::new(&self.raw, raw_surface),
        }
    }

    pub(crate) fn raw_entry(&self) -> &ash::Entry {
        self.raw.entry()
    }

    pub(crate) fn raw_instance(&self) -> &ash::Instance {
        self.raw.instance()
    }

    pub(crate) fn raw(&self) -> &Instance {
        &self.raw
    }

    pub(crate) fn destroy(mut self) {
        if let Some(debug) = self.debug.take() {
            debug.destroy();
        }
        self.raw.destroy();
    }
}

pub(crate) struct VulkanDevice {
    raw: Device,
}

impl VulkanDevice {
    pub(crate) fn raw(&self) -> &Device {
        &self.raw
    }

    pub(crate) fn destroy(mut self) {
        self.raw.destroy();
    }
}

pub(crate) struct VulkanSurface {
    raw: Surface,
}

impl VulkanSurface {
    pub(crate) fn create_swapchain(
        &self,
        instance: &VulkanInstance,
        device: &VulkanDevice,
        extent_hint: vk::Extent2D,
    ) -> Result<VulkanSwapchain, Error> {
        let swapchain = Swapchain::new(&instance.raw, device.raw(), &self.raw, extent_hint)?;
        Ok(VulkanSwapchain { raw: swapchain })
    }

    pub(crate) fn create_swapchain_with_old(
        &self,
        instance: &VulkanInstance,
        device: &VulkanDevice,
        extent_hint: vk::Extent2D,
        old_swapchain: vk::SwapchainKHR,
    ) -> Result<VulkanSwapchain, Error> {
        let swapchain = Swapchain::new_with_old(
            instance.raw(),
            device.raw(),
            &self.raw,
            extent_hint,
            old_swapchain,
        )?;
        Ok(VulkanSwapchain { raw: swapchain })
    }

    pub(crate) fn destroy(mut self) {
        self.raw.destroy();
    }
}

pub(crate) struct VulkanSwapchain {
    raw: Swapchain,
}

impl VulkanSwapchain {
    pub(crate) fn raw(&self) -> &Swapchain {
        &self.raw
    }

    pub(crate) fn destroy(mut self, device: &VulkanDevice) {
        self.raw.destroy(device.raw());
    }

    pub(crate) fn destroy_in_place(&mut self, device: &VulkanDevice) {
        self.raw.destroy(device.raw());
    }

    pub(crate) fn handle(&self) -> vk::SwapchainKHR {
        self.raw.swapchain
    }
}