2023-04-12 14:53:59 -04:00
|
|
|
use ::anyhow::{anyhow, Result};
|
|
|
|
use ::log::*;
|
|
|
|
use ::nalgebra_glm as glm;
|
2023-04-20 11:06:52 -04:00
|
|
|
use ::std::hash::{Hash, Hasher};
|
2023-04-12 14:53:59 -04:00
|
|
|
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 {
|
2023-04-19 10:55:49 -04:00
|
|
|
pos: glm::Vec3,
|
2023-04-12 14:53:59 -04:00
|
|
|
color: glm::Vec3,
|
2023-04-19 10:17:19 -04:00
|
|
|
tex_coord: glm::Vec2,
|
2023-04-12 14:53:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Vertex {
|
2023-04-19 10:55:49 -04:00
|
|
|
pub fn new(pos: glm::Vec3, color: glm::Vec3, tex_coord: glm::Vec2) -> Self {
|
2023-04-19 10:17:19 -04:00
|
|
|
Self {
|
|
|
|
pos,
|
|
|
|
color,
|
|
|
|
tex_coord,
|
|
|
|
}
|
2023-04-12 14:53:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn binding_description() -> vk::VertexInputBindingDescription {
|
|
|
|
vk::VertexInputBindingDescription::builder()
|
|
|
|
.binding(0)
|
|
|
|
.stride(size_of::<Vertex>() as u32)
|
|
|
|
.input_rate(vk::VertexInputRate::VERTEX)
|
|
|
|
.build()
|
|
|
|
}
|
|
|
|
|
2023-04-19 10:17:19 -04:00
|
|
|
pub fn attribute_descriptions() -> [vk::VertexInputAttributeDescription; 3] {
|
2023-04-12 14:53:59 -04:00
|
|
|
let pos = vk::VertexInputAttributeDescription::builder()
|
|
|
|
.binding(0)
|
|
|
|
.location(0)
|
2023-04-19 10:55:49 -04:00
|
|
|
.format(vk::Format::R32G32B32_SFLOAT)
|
2023-04-12 14:53:59 -04:00
|
|
|
.offset(0)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let color = vk::VertexInputAttributeDescription::builder()
|
|
|
|
.binding(0)
|
|
|
|
.location(1)
|
|
|
|
.format(vk::Format::R32G32B32_SFLOAT)
|
2023-04-19 10:55:49 -04:00
|
|
|
.offset(size_of::<glm::Vec3>() as u32)
|
2023-04-12 14:53:59 -04:00
|
|
|
.build();
|
|
|
|
|
2023-04-19 10:17:19 -04:00
|
|
|
let tex_coord = vk::VertexInputAttributeDescription::builder()
|
|
|
|
.binding(0)
|
|
|
|
.location(2)
|
|
|
|
.format(vk::Format::R32G32_SFLOAT)
|
2023-04-19 10:55:49 -04:00
|
|
|
.offset((size_of::<glm::Vec3>() + size_of::<glm::Vec3>()) as u32)
|
2023-04-19 10:17:19 -04:00
|
|
|
.build();
|
|
|
|
|
|
|
|
[pos, color, tex_coord]
|
2023-04-12 14:53:59 -04:00
|
|
|
}
|
|
|
|
}
|
2023-04-13 10:14:10 -04:00
|
|
|
|
2023-04-20 11:06:52 -04:00
|
|
|
impl PartialEq for Vertex {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.pos == other.pos && self.color == other.color && self.tex_coord == other.tex_coord
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for Vertex {}
|
|
|
|
|
|
|
|
impl Hash for Vertex {
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
self.pos[0].to_bits().hash(state);
|
|
|
|
self.pos[1].to_bits().hash(state);
|
|
|
|
self.pos[2].to_bits().hash(state);
|
|
|
|
self.color[0].to_bits().hash(state);
|
|
|
|
self.color[1].to_bits().hash(state);
|
|
|
|
self.color[2].to_bits().hash(state);
|
|
|
|
self.tex_coord[0].to_bits().hash(state);
|
|
|
|
self.tex_coord[1].to_bits().hash(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-13 10:14:10 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// 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,
|
|
|
|
}
|