use ::anyhow::{anyhow, Result}; use ::log::*; use ::nalgebra_glm as glm; use ::std::mem::size_of; use ::thiserror::Error; use ::vulkanalia::prelude::v1_0::*; use ::vulkanalia::vk::KhrSurfaceExtension; use super::AppData; // ---------------------------------------------------------------------------- // Error Wrapper // ---------------------------------------------------------------------------- /// Generic Error wrapper struct #[derive(Debug, Error)] #[error("Missing {0}.")] pub struct SuitabilityError(pub &'static str); // ---------------------------------------------------------------------------- // Queue Family // ---------------------------------------------------------------------------- #[derive(Copy, Clone, Debug)] pub(crate) struct QueueFamilyIndices { pub(crate) graphics: u32, pub(crate) present: u32, } impl QueueFamilyIndices { pub(crate) unsafe fn get( instance: &Instance, data: &AppData, physical_device: vk::PhysicalDevice, ) -> Result { let properties = instance.get_physical_device_queue_family_properties(physical_device); let graphics = properties .iter() .position(|p| p.queue_flags.contains(vk::QueueFlags::GRAPHICS)) .map(|i| i as u32); let mut present = None; for (index, _properties) in properties.iter().enumerate() { if instance.get_physical_device_surface_support_khr( physical_device, index as u32, data.surface, )? { present = Some(index as u32); break; } } if let (Some(graphics), Some(present)) = (graphics, present) { Ok(Self { graphics, present }) } else { Err(anyhow!(SuitabilityError( "Missing required queue families." ))) } } } // ---------------------------------------------------------------------------- // Swapchain // ---------------------------------------------------------------------------- #[derive(Clone, Debug)] pub(crate) struct SwapchainSupport { pub(crate) capabilities: vk::SurfaceCapabilitiesKHR, pub(crate) formats: Vec, pub(crate) present_modes: Vec, } impl SwapchainSupport { pub(crate) unsafe fn get( instance: &Instance, data: &AppData, physical_device: vk::PhysicalDevice, ) -> Result { Ok(Self { capabilities: instance .get_physical_device_surface_capabilities_khr(physical_device, data.surface)?, formats: instance .get_physical_device_surface_formats_khr(physical_device, data.surface)?, present_modes: instance .get_physical_device_surface_present_modes_khr(physical_device, data.surface)?, }) } } // ---------------------------------------------------------------------------- // Vertex // ---------------------------------------------------------------------------- #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct Vertex { pos: glm::Vec3, color: glm::Vec3, tex_coord: glm::Vec2, } impl Vertex { pub fn new(pos: glm::Vec3, color: glm::Vec3, tex_coord: glm::Vec2) -> Self { Self { pos, color, tex_coord, } } pub fn binding_description() -> vk::VertexInputBindingDescription { vk::VertexInputBindingDescription::builder() .binding(0) .stride(size_of::() as u32) .input_rate(vk::VertexInputRate::VERTEX) .build() } pub fn attribute_descriptions() -> [vk::VertexInputAttributeDescription; 3] { let pos = vk::VertexInputAttributeDescription::builder() .binding(0) .location(0) .format(vk::Format::R32G32B32_SFLOAT) .offset(0) .build(); let color = vk::VertexInputAttributeDescription::builder() .binding(0) .location(1) .format(vk::Format::R32G32B32_SFLOAT) .offset(size_of::() as u32) .build(); let tex_coord = vk::VertexInputAttributeDescription::builder() .binding(0) .location(2) .format(vk::Format::R32G32_SFLOAT) .offset((size_of::() + size_of::()) as u32) .build(); [pos, color, tex_coord] } } // ---------------------------------------------------------------------------- // Resource Descriptors // ---------------------------------------------------------------------------- #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct UniformBufferObject { pub(crate) model: glm::Mat4, pub(crate) view: glm::Mat4, pub(crate) proj: glm::Mat4, }