vulkan-tutorial/src/app/structs.rs

158 lines
4.8 KiB
Rust

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<Self> {
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<vk::SurfaceFormatKHR>,
pub(crate) present_modes: Vec<vk::PresentModeKHR>,
}
impl SwapchainSupport {
pub(crate) unsafe fn get(
instance: &Instance,
data: &AppData,
physical_device: vk::PhysicalDevice,
) -> Result<Self> {
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::<Vertex>() 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::<glm::Vec3>() as u32)
.build();
let tex_coord = vk::VertexInputAttributeDescription::builder()
.binding(0)
.location(2)
.format(vk::Format::R32G32_SFLOAT)
.offset((size_of::<glm::Vec3>() + size_of::<glm::Vec3>()) 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,
}