style: rustfmt run

This commit is contained in:
alphafetus committed 2026-05-08 16:51:18 -04:00
1 parent e7659ba387
commit 0661494b0f
17 files changed
+232 -200

No files matched your search

+3 -1
View File
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" /> <component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise">
<file url="file://$PROJECT_DIR$/src/math/mod.rs" charset="US-ASCII" />
</component>
</project> </project>
+127 -102
View File
@@ -1,36 +1,45 @@
use std::error::Error; use crate::common::mesh::MeshRegistry;
use crate::gpu::vertex3::Vertex3;
use crate::triangle;
use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer}; use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
use vulkano::command_buffer::allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo}; use vulkano::command_buffer::allocator::{
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, RenderPassBeginInfo, SubpassBeginInfo, SubpassContents, SubpassEndInfo}; StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo,
};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, RenderPassBeginInfo,
SubpassBeginInfo, SubpassContents, SubpassEndInfo,
};
use vulkano::descriptor_set::allocator::{DescriptorSetAllocator, StandardDescriptorSetAllocator}; use vulkano::descriptor_set::allocator::{DescriptorSetAllocator, StandardDescriptorSetAllocator};
use vulkano::device::{Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags};
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType}; use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
use vulkano::image::{Image, ImageUsage}; use vulkano::device::{
Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags,
};
use vulkano::image::view::ImageView; use vulkano::image::view::ImageView;
use vulkano::image::{Image, ImageUsage};
use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions}; use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions};
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator}; use vulkano::memory::allocator::{
use vulkano::pipeline::{GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo}; AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator,
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState}; };
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo; use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState; use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
use vulkano::pipeline::graphics::multisample::MultisampleState; use vulkano::pipeline::graphics::multisample::MultisampleState;
use vulkano::pipeline::graphics::rasterization::RasterizationState; use vulkano::pipeline::graphics::rasterization::RasterizationState;
use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition}; use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition};
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState}; use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::layout::PipelineDescriptorSetLayoutCreateInfo; use vulkano::pipeline::layout::PipelineDescriptorSetLayoutCreateInfo;
use vulkano::pipeline::{GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo};
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass}; use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
use vulkano::{swapchain, sync, Validated, VulkanError, VulkanLibrary};
use vulkano::shader::ShaderModule; use vulkano::shader::ShaderModule;
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
use vulkano::sync::GpuFuture; use vulkano::sync::GpuFuture;
use vulkano::{Validated, VulkanError, VulkanLibrary, swapchain, sync};
use winit::application::ApplicationHandler; use winit::application::ApplicationHandler;
use winit::event::WindowEvent; use winit::event::WindowEvent;
use winit::event_loop::ActiveEventLoop; use winit::event_loop::ActiveEventLoop;
use winit::window::{Window, WindowAttributes, WindowId}; use winit::window::{Window, WindowAttributes, WindowId};
use crate::common::mesh::MeshRegistry;
use crate::gpu::vertex3::Vertex3;
use crate::triangle;
struct VulkanContext { struct VulkanContext {
window: Arc<Window>, window: Arc<Window>,
@@ -54,7 +63,10 @@ impl VulkanContext {
/// Initializes and returns a new `VulkanContext`. It may fail in all cases where a Vulkan object /// Initializes and returns a new `VulkanContext`. It may fail in all cases where a Vulkan object
/// may fail, specifically during initialization of shaders, devices, buffers, or any other such /// may fail, specifically during initialization of shaders, devices, buffers, or any other such
/// structures. /// structures.
pub fn init(instance: Arc<Instance>, event_loop: &ActiveEventLoop) -> Result<Self, Box<dyn Error>> { pub fn init(
instance: Arc<Instance>,
event_loop: &ActiveEventLoop,
) -> Result<Self, Box<dyn Error>> {
let attributes = WindowAttributes::default() let attributes = WindowAttributes::default()
.with_title("Vulkano Example") .with_title("Vulkano Example")
.with_resizable(true); .with_resizable(true);
@@ -70,41 +82,29 @@ impl VulkanContext {
// Get a physical device. Fails if there is no suitable device found. The device must have a // Get a physical device. Fails if there is no suitable device found. The device must have a
// graphics queue and swapchain capabilities. // graphics queue and swapchain capabilities.
let (physical_device, queue_family_idx) = Self::get_physical_device( let (physical_device, queue_family_idx) =
instance.clone(), Self::get_physical_device(instance.clone(), surface.clone(), &dev_extensions)?;
surface.clone(),
&dev_extensions
)?;
// Create a Vulkan device. This is a handle to the connection between the program and the // Create a Vulkan device. This is a handle to the connection between the program and the
// chosen physical device. // chosen physical device.
let (device, mut queues) = Self::create_device( let (device, mut queues) = Self::create_device(
physical_device.clone(), physical_device.clone(),
&dev_extensions, &dev_extensions,
queue_family_idx as usize queue_family_idx as usize,
)?; )?;
// Get the first queue. This is what we'll use for drawing. // Get the first queue. This is what we'll use for drawing.
let queue = queues.next() let queue = queues.next().ok_or("Queues list was empty.")?;
.ok_or("Queues list was empty.")?;
let capabilities = physical_device let capabilities = physical_device.surface_capabilities(&surface, Default::default())?;
.surface_capabilities(
&surface,
Default::default()
)?;
let dimensions = window let dimensions = window.inner_size();
.inner_size();
let composite_alpha = capabilities let composite_alpha = capabilities
.supported_composite_alpha .supported_composite_alpha
.into_iter() .into_iter()
.next() .next()
.ok_or("No composite alpha supported")?; .ok_or("No composite alpha supported")?;
let image_format = physical_device let image_format = physical_device.surface_formats(&surface, Default::default())?[0].0;
.surface_formats(&surface, Default::default())?
[0]
.0;
// Swapchain needs to be easily changeable, since resizing the window creates a whole new // Swapchain needs to be easily changeable, since resizing the window creates a whole new
// set of information. Putting this into a function would be good, but also the new // set of information. Putting this into a function would be good, but also the new
@@ -119,7 +119,7 @@ impl VulkanContext {
image_usage: ImageUsage::COLOR_ATTACHMENT, image_usage: ImageUsage::COLOR_ATTACHMENT,
composite_alpha, composite_alpha,
..Default::default() ..Default::default()
} },
)?; )?;
let mem_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone())); let mem_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
@@ -127,7 +127,10 @@ impl VulkanContext {
device.clone(), device.clone(),
StandardCommandBufferAllocatorCreateInfo::default(), StandardCommandBufferAllocatorCreateInfo::default(),
)); ));
let desc_allocator = Arc::new(StandardDescriptorSetAllocator::new(device.clone(), Default::default())); let desc_allocator = Arc::new(StandardDescriptorSetAllocator::new(
device.clone(),
Default::default(),
));
let render_pass = vulkano::single_pass_renderpass!( let render_pass = vulkano::single_pass_renderpass!(
device.clone(), device.clone(),
@@ -158,7 +161,7 @@ impl VulkanContext {
&vert_shader, &vert_shader,
&frag_shader, &frag_shader,
&render_pass, &render_pass,
[image_extents[0] as f32, image_extents[1] as f32] [image_extents[0] as f32, image_extents[1] as f32],
)?; )?;
let vertex_buffer = Arc::new(Buffer::from_iter( let vertex_buffer = Arc::new(Buffer::from_iter(
@@ -173,11 +176,19 @@ impl VulkanContext {
..Default::default() ..Default::default()
}, },
vec![ vec![
Vertex3 { position: [0.5, 0.5, 0.0] }, Vertex3 {
Vertex3 { position: [-0.5, 0.5, 0.0] }, position: [0.5, 0.5, 0.0],
Vertex3 { position: [-0.5, -0.5, 0.0] }, },
Vertex3 { position: [0.5, -0.5, 0.0] }, Vertex3 {
] position: [-0.5, 0.5, 0.0],
},
Vertex3 {
position: [-0.5, -0.5, 0.0],
},
Vertex3 {
position: [0.5, -0.5, 0.0],
},
],
)?); )?);
let index_buffer = Arc::new(Buffer::from_iter( let index_buffer = Arc::new(Buffer::from_iter(
@@ -191,10 +202,7 @@ impl VulkanContext {
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE, | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default() ..Default::default()
}, },
vec![ vec![0, 1, 2, 0, 2, 3],
0, 1, 2,
0, 2, 3,
]
)?); )?);
let cmd_buffers = Self::get_command_buffers( let cmd_buffers = Self::get_command_buffers(
@@ -203,12 +211,10 @@ impl VulkanContext {
&pipeline, &pipeline,
&framebuffers, &framebuffers,
&vertex_buffer, &vertex_buffer,
&index_buffer &index_buffer,
)?; )?;
let mesh_registry = Arc::new(MeshRegistry::new( let mesh_registry = Arc::new(MeshRegistry::new(mem_allocator.clone())?);
mem_allocator.clone(),
)?);
Ok(Self { Ok(Self {
window, window,
@@ -233,7 +239,8 @@ impl VulkanContext {
pub fn draw_frame(&mut self) -> Result<(), Box<dyn Error>> { pub fn draw_frame(&mut self) -> Result<(), Box<dyn Error>> {
let (image_idx, suboptimal, acquire_future) = let (image_idx, suboptimal, acquire_future) =
match swapchain::acquire_next_image(self.swapchain.clone(), None) match swapchain::acquire_next_image(self.swapchain.clone(), None)
.map_err(Validated::unwrap){ .map_err(Validated::unwrap)
{
Ok(r) => r, Ok(r) => r,
Err(VulkanError::OutOfDate) => { Err(VulkanError::OutOfDate) => {
println!("Swapchain is out of date!"); println!("Swapchain is out of date!");
@@ -252,7 +259,10 @@ impl VulkanContext {
let execution = sync::now(self.device.clone()) let execution = sync::now(self.device.clone())
.join(acquire_future) .join(acquire_future)
.then_execute(self.queue.clone(), self.cmd_buffers[image_idx as usize].clone())? .then_execute(
self.queue.clone(),
self.cmd_buffers[image_idx as usize].clone(),
)?
.then_swapchain_present( .then_swapchain_present(
self.queue.clone(), self.queue.clone(),
SwapchainPresentInfo::swapchain_image_index(self.swapchain.clone(), image_idx), SwapchainPresentInfo::swapchain_image_index(self.swapchain.clone(), image_idx),
@@ -269,7 +279,7 @@ impl VulkanContext {
fn get_physical_device( fn get_physical_device(
instance: Arc<Instance>, instance: Arc<Instance>,
surface: Arc<Surface>, surface: Arc<Surface>,
extensions: &DeviceExtensions extensions: &DeviceExtensions,
) -> Result<(Arc<PhysicalDevice>, u32), String> { ) -> Result<(Arc<PhysicalDevice>, u32), String> {
instance instance
.enumerate_physical_devices() .enumerate_physical_devices()
@@ -285,12 +295,10 @@ impl VulkanContext {
}) })
.map(|q| (dev, q as u32)) .map(|q| (dev, q as u32))
}) })
.min_by_key(|(dev, _)| { .min_by_key(|(dev, _)| match dev.properties().device_type {
match dev.properties().device_type {
PhysicalDeviceType::DiscreteGpu => 0, PhysicalDeviceType::DiscreteGpu => 0,
PhysicalDeviceType::Cpu => 1, PhysicalDeviceType::Cpu => 1,
_ => 2 _ => 2,
}
}) })
.ok_or_else(|| "No physical devices found".to_string()) .ok_or_else(|| "No physical devices found".to_string())
} }
@@ -299,7 +307,7 @@ impl VulkanContext {
fn create_device( fn create_device(
physical_device: Arc<PhysicalDevice>, physical_device: Arc<PhysicalDevice>,
device_extensions: &DeviceExtensions, device_extensions: &DeviceExtensions,
graphics_index: usize graphics_index: usize,
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), String> { ) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), String> {
Device::new( Device::new(
physical_device.clone(), physical_device.clone(),
@@ -310,7 +318,7 @@ impl VulkanContext {
}], }],
enabled_extensions: device_extensions.clone(), enabled_extensions: device_extensions.clone(),
..Default::default() ..Default::default()
} },
) )
.map_err(|e| format!("Failed to create device: {e}")) .map_err(|e| format!("Failed to create device: {e}"))
} }
@@ -318,9 +326,10 @@ impl VulkanContext {
/// Creates a new [`Framebuffer`] for each swapchain image. /// Creates a new [`Framebuffer`] for each swapchain image.
fn create_framebuffers( fn create_framebuffers(
images: &Vec<Arc<Image>>, images: &Vec<Arc<Image>>,
render_pass: &Arc<RenderPass> render_pass: &Arc<RenderPass>,
) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> { ) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> {
let framebuffers = images.iter() let framebuffers = images
.iter()
.map(|image| { .map(|image| {
let view = ImageView::new_default(image.clone()).unwrap(); let view = ImageView::new_default(image.clone()).unwrap();
@@ -329,7 +338,7 @@ impl VulkanContext {
FramebufferCreateInfo { FramebufferCreateInfo {
attachments: vec![view], attachments: vec![view],
..Default::default() ..Default::default()
} },
) )
.unwrap() .unwrap()
}) })
@@ -348,26 +357,27 @@ impl VulkanContext {
extents: [f32; 2], extents: [f32; 2],
) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> { ) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> {
// Get shader stages // Get shader stages
let vs = vert_shader.entry_point("main") let vs = vert_shader
.entry_point("main")
.ok_or("Failed to find vertex shader entry point")?; .ok_or("Failed to find vertex shader entry point")?;
let fs = frag_shader.entry_point("main") let fs = frag_shader
.entry_point("main")
.ok_or("Failed to find fragment shader entry point")?; .ok_or("Failed to find fragment shader entry point")?;
let vertex_input_state = Vertex3::per_vertex() let vertex_input_state = Vertex3::per_vertex().definition(&vs)?;
.definition(&vs)?;
let stages = vec![ let stages = vec![
PipelineShaderStageCreateInfo::new(vs), PipelineShaderStageCreateInfo::new(vs),
PipelineShaderStageCreateInfo::new(fs), PipelineShaderStageCreateInfo::new(fs),
]; ];
let subpass = Subpass::from(render_pass.clone(), 0) let subpass =
.ok_or("Failed to create pipeline subpass")?; Subpass::from(render_pass.clone(), 0).ok_or("Failed to create pipeline subpass")?;
let layout = PipelineLayout::new( let layout = PipelineLayout::new(
device.clone(), device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages) PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages)
.into_pipeline_layout_create_info(device.clone())? .into_pipeline_layout_create_info(device.clone())?,
)?; )?;
let viewport = Viewport { let viewport = Viewport {
@@ -392,12 +402,12 @@ impl VulkanContext {
multisample_state: Some(MultisampleState::default()), multisample_state: Some(MultisampleState::default()),
color_blend_state: Some(ColorBlendState::with_attachment_states( color_blend_state: Some(ColorBlendState::with_attachment_states(
subpass.num_color_attachments(), subpass.num_color_attachments(),
ColorBlendAttachmentState::default() ColorBlendAttachmentState::default(),
)), )),
dynamic_state: Default::default(), dynamic_state: Default::default(),
subpass: Some(subpass.into()), subpass: Some(subpass.into()),
..GraphicsPipelineCreateInfo::layout(layout) ..GraphicsPipelineCreateInfo::layout(layout)
} },
)?) )?)
} }
@@ -408,15 +418,17 @@ impl VulkanContext {
pipeline: &Arc<GraphicsPipeline>, pipeline: &Arc<GraphicsPipeline>,
framebuffers: &Vec<Arc<Framebuffer>>, framebuffers: &Vec<Arc<Framebuffer>>,
vertex_buffer: &Arc<Subbuffer<[Vertex3]>>, vertex_buffer: &Arc<Subbuffer<[Vertex3]>>,
index_buffer: &Subbuffer<[u32]> index_buffer: &Subbuffer<[u32]>,
) -> Result<Vec<Arc<PrimaryAutoCommandBuffer>>, Box<dyn Error>> { ) -> Result<Vec<Arc<PrimaryAutoCommandBuffer>>, Box<dyn Error>> {
let buffers = framebuffers.iter() let buffers = framebuffers
.iter()
.filter_map(|framebuffer| { .filter_map(|framebuffer| {
let mut builder = AutoCommandBufferBuilder::primary( let mut builder = AutoCommandBufferBuilder::primary(
cmd_allocator.clone(), cmd_allocator.clone(),
queue.queue_family_index(), queue.queue_family_index(),
CommandBufferUsage::MultipleSubmit CommandBufferUsage::MultipleSubmit,
).ok()?; )
.ok()?;
unsafe { unsafe {
builder builder
@@ -428,14 +440,20 @@ impl VulkanContext {
SubpassBeginInfo { SubpassBeginInfo {
contents: SubpassContents::Inline, contents: SubpassContents::Inline,
..Default::default() ..Default::default()
} },
).ok()? )
.bind_pipeline_graphics(pipeline.clone()).ok()? .ok()?
.bind_vertex_buffers(0, vertex_buffer.as_ref().clone()).ok()? .bind_pipeline_graphics(pipeline.clone())
.bind_index_buffer(index_buffer.clone()).ok()? .ok()?
.bind_vertex_buffers(0, vertex_buffer.as_ref().clone())
.ok()?
.bind_index_buffer(index_buffer.clone())
.ok()?
// .draw(vertex_buffer.len() as u32, 1, 0, 0).ok()? // .draw(vertex_buffer.len() as u32, 1, 0, 0).ok()?
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0).ok()? .draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
.end_render_pass(SubpassEndInfo::default()).ok()?; .ok()?
.end_render_pass(SubpassEndInfo::default())
.ok()?;
} }
builder.build().ok() builder.build().ok()
@@ -450,10 +468,11 @@ impl VulkanContext {
/// specifically the [`GraphicsPipeline`] and [`PrimaryAutoCommandBuffer`]. All information is /// specifically the [`GraphicsPipeline`] and [`PrimaryAutoCommandBuffer`]. All information is
/// automatically set within the `VulkanContext`. /// automatically set within the `VulkanContext`.
pub fn recreate_swapchain(&mut self, resized: bool) -> Result<(), Box<dyn Error>> { pub fn recreate_swapchain(&mut self, resized: bool) -> Result<(), Box<dyn Error>> {
unsafe { self.device.wait_idle()?; }; unsafe {
self.device.wait_idle()?;
};
let (new_swapchain, new_images) = self.swapchain let (new_swapchain, new_images) = self.swapchain.recreate(SwapchainCreateInfo {
.recreate(SwapchainCreateInfo {
image_extent: self.window.inner_size().into(), image_extent: self.window.inner_size().into(),
..self.swapchain.create_info() ..self.swapchain.create_info()
})?; })?;
@@ -462,7 +481,8 @@ impl VulkanContext {
self.swapchain_images = new_images; self.swapchain_images = new_images;
// Recreate the framebuffers, which depend on the swapchain. // Recreate the framebuffers, which depend on the swapchain.
let new_framebuffers = Self::create_framebuffers(&self.swapchain_images, &self.render_pass)?; let new_framebuffers =
Self::create_framebuffers(&self.swapchain_images, &self.render_pass)?;
self.framebuffers = new_framebuffers; self.framebuffers = new_framebuffers;
@@ -482,7 +502,7 @@ impl VulkanContext {
&new_pipeline, &new_pipeline,
&self.framebuffers, &self.framebuffers,
&self.mesh_registry.vertex_buffer, &self.mesh_registry.vertex_buffer,
&self.mesh_registry.index_buffer &self.mesh_registry.index_buffer,
)?; )?;
self.pipeline = new_pipeline; self.pipeline = new_pipeline;
@@ -517,11 +537,9 @@ impl MainApplication {
} }
/// Gets the Vulkan instance. /// Gets the Vulkan instance.
fn get_instance( fn get_instance(required_extensions: InstanceExtensions) -> Result<Arc<Instance>, String> {
required_extensions: InstanceExtensions, let library =
) -> Result<Arc<Instance>, String> { VulkanLibrary::new().map_err(|e| format!("Failed to find Vulkan library: {e}"))?;
let library = VulkanLibrary::new()
.map_err(|e| format!("Failed to find Vulkan library: {e}"))?;
Instance::new( Instance::new(
library, library,
@@ -529,7 +547,7 @@ impl MainApplication {
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY, flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
enabled_extensions: required_extensions, enabled_extensions: required_extensions,
..Default::default() ..Default::default()
} },
) )
.map_err(|e| format!("Failed to create instance: {e}")) .map_err(|e| format!("Failed to create instance: {e}"))
} }
@@ -537,28 +555,35 @@ impl MainApplication {
impl ApplicationHandler for MainApplication { impl ApplicationHandler for MainApplication {
fn resumed(&mut self, event_loop: &ActiveEventLoop) { fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.context.is_none() self.context.is_none().then(|| {
.then(|| {
// Initialization logic // Initialization logic
let context = VulkanContext::init( let context = VulkanContext::init(self.instance.clone(), event_loop)
self.instance.clone(), .expect("Couldn't initialize VulkanContext");
event_loop
).expect("Couldn't initialize VulkanContext");
self.context = Some(context); self.context = Some(context);
}); });
} }
fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) { fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: WindowId,
event: WindowEvent,
) {
match event { match event {
WindowEvent::CloseRequested => { WindowEvent::CloseRequested => {
println!("Closing window."); println!("Closing window.");
event_loop.exit(); event_loop.exit();
} }
WindowEvent::Resized(dimensions) => { WindowEvent::Resized(dimensions) => {
println!("Window was resized, recreating swapchain. New dimensions: {:?}", dimensions); println!(
"Window was resized, recreating swapchain. New dimensions: {:?}",
dimensions
);
if let Some(context) = self.context.as_mut() { if let Some(context) = self.context.as_mut() {
context.recreate_swapchain(true).expect("Failed to recreate swapchain"); context
.recreate_swapchain(true)
.expect("Failed to recreate swapchain");
} }
} }
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
@@ -569,7 +594,7 @@ impl ApplicationHandler for MainApplication {
// Queue the next frame for drawing. // Queue the next frame for drawing.
self.context.as_ref().unwrap().window.request_redraw(); self.context.as_ref().unwrap().window.request_redraw();
} }
_ => () _ => (),
} }
} }
} }
+1 -1
View File
@@ -1,5 +1,5 @@
use nalgebra::{Matrix4, Vector3, Vector4};
use crate::common::scene::SceneInstance; use crate::common::scene::SceneInstance;
use nalgebra::{Matrix4, Vector3, Vector4};
/// Contains all information about an instance of a mesh, specifically its translation, rotation, /// Contains all information about an instance of a mesh, specifically its translation, rotation,
/// and scale. Note that the rotation is a [`Vector4`], and not a `Quaternion`. /// and scale. Note that the rotation is a [`Vector4`], and not a `Quaternion`.
+1 -1
View File
@@ -1,3 +1,3 @@
pub mod instance;
pub mod mesh; pub mod mesh;
pub mod scene; pub mod scene;
pub mod instance;
+8 -7
View File
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Read; use std::io::Read;
use std::path::Path; use std::path::Path;
use serde::{Deserialize, Serialize};
/// A scene, which holds all information required to render a world. /// A scene, which holds all information required to render a world.
/// ///
@@ -26,8 +26,7 @@ pub struct Scene {
impl Scene { impl Scene {
/// Converts this `Scene` into its byte representation. /// Converts this `Scene` into its byte representation.
pub fn bytes(&self) -> Vec<u8> { pub fn bytes(&self) -> Vec<u8> {
postcard::to_allocvec(self) postcard::to_allocvec(self).expect("Couldn't serialize scene")
.expect("Couldn't serialize scene")
} }
/// Reads a `scene` from the given path. Automatically resolves all paths for the meshes that /// Reads a `scene` from the given path. Automatically resolves all paths for the meshes that
@@ -43,18 +42,20 @@ impl Scene {
let mut contents = Vec::new(); let mut contents = Vec::new();
let _ = file.read_to_end(&mut contents).unwrap(); let _ = file.read_to_end(&mut contents).unwrap();
let mut scene: Self = postcard::from_bytes(contents.as_slice()) let mut scene: Self =
.expect("Couldn't deserialize scene"); postcard::from_bytes(contents.as_slice()).expect("Couldn't deserialize scene");
let base = path.parent().unwrap_or(&Path::new(".")); let base = path.parent().unwrap_or(&Path::new("."));
scene.mesh_paths = scene.mesh_paths scene.mesh_paths = scene
.mesh_paths
.into_iter() .into_iter()
.map(|(id, mesh_path)| { .map(|(id, mesh_path)| {
let res = base.join(mesh_path); let res = base.join(mesh_path);
let str = res.to_str().unwrap_or_default(); let str = res.to_str().unwrap_or_default();
(id, str.to_string()) (id, str.to_string())
}).collect::<HashMap<String, String>>(); })
.collect::<HashMap<String, String>>();
scene scene
} }
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::common::instance::MeshInstance;
use vulkano::buffer::BufferContents; use vulkano::buffer::BufferContents;
use vulkano::pipeline::graphics::vertex_input::Vertex; use vulkano::pipeline::graphics::vertex_input::Vertex;
use crate::common::instance::MeshInstance;
/// A transformation matrix for a mesh that can be passed into the shaders. /// A transformation matrix for a mesh that can be passed into the shaders.
#[derive(BufferContents, Vertex)] #[derive(BufferContents, Vertex)]
+1 -1
View File
@@ -1,2 +1,2 @@
pub mod vertex3;
pub mod instance; pub mod instance;
pub mod vertex3;
+6 -4
View File
@@ -1,15 +1,17 @@
use vulkano::buffer::BufferContents; use vulkano::buffer::BufferContents;
use vulkano::pipeline::graphics::vertex_input::Vertex; use vulkano::pipeline::graphics::vertex_input::Vertex;
#[derive(Debug, BufferContents, Vertex)] #[derive(Debug, Clone, BufferContents, Vertex)]
#[repr(C)] #[repr(C)]
pub struct Vertex3 { pub struct Vertex3 {
#[format(R32G32B32_SFLOAT)] #[format(R32G32B32_SFLOAT)]
pub(crate) position: [f32; 3], pub(crate) position: [f32; 3],
} }
impl From<&[f32; 3]> for Vertex3 { impl From<[f32; 3]> for Vertex3 {
fn from(v: &[f32; 3]) -> Self { fn from(v: [f32; 3]) -> Self {
Self { position: v.clone() } Self {
position: v.clone(),
}
} }
} }
+2 -2
View File
@@ -1,12 +1,12 @@
mod app; mod app;
pub mod math;
mod common; mod common;
pub mod gpu; pub mod gpu;
// pub mod math;
use crate::app::MainApplication;
use std::error::Error; use std::error::Error;
use vulkano::swapchain::Surface; use vulkano::swapchain::Surface;
use winit::event_loop::{ControlFlow, EventLoop}; use winit::event_loop::{ControlFlow, EventLoop};
use crate::app::MainApplication;
// Compute shader compilation. Happens at runtime, but file contents are included during compilation. // Compute shader compilation. Happens at runtime, but file contents are included during compilation.
mod cs { mod cs {
+4 -10
View File
@@ -1,6 +1,6 @@
use std::ops::{Add, Index, IndexMut, Mul, Sub}; use crate::math::Vector2;
use crate::math::traits::{Matrix, Vector}; use crate::math::traits::{Matrix, Vector};
use crate::math::{Vector2}; use std::ops::{Add, Index, IndexMut, Mul, Sub};
#[derive(Clone, Debug, PartialEq, PartialOrd, Copy, Default)] #[derive(Clone, Debug, PartialEq, PartialOrd, Copy, Default)]
pub struct Matrix2 { pub struct Matrix2 {
@@ -14,17 +14,11 @@ impl Matrix2 {
} }
pub fn row_vector(&self, row: usize) -> Vector2 { pub fn row_vector(&self, row: usize) -> Vector2 {
Vector2::from([ Vector2::from([self[row][0], self[row][1]])
self[row][0],
self[row][1],
])
} }
pub fn column_vector(&self, col: usize) -> Vector2 { pub fn column_vector(&self, col: usize) -> Vector2 {
Vector2::from([ Vector2::from([self[0][col], self[1][col]])
self[0][col],
self[1][col],
])
} }
} }
+1
View File
@@ -0,0 +1 @@
+31 -8
View File
@@ -1,6 +1,6 @@
use std::ops::{Add, Div, Mul, Sub};
use crate::math::traits::{Matrix, Vector};
use crate::math::Vector4; use crate::math::Vector4;
use crate::math::traits::{Matrix, Vector};
use std::ops::{Add, Div, Mul, Sub};
#[derive(Debug, Clone, Default, Copy, PartialEq)] #[derive(Debug, Clone, Default, Copy, PartialEq)]
pub struct Matrix4 { pub struct Matrix4 {
@@ -10,8 +10,7 @@ pub struct Matrix4 {
row4: Vector4, row4: Vector4,
} }
impl Matrix4 { impl Matrix4 {}
}
impl Add for Matrix4 { impl Add for Matrix4 {
type Output = Self; type Output = Self;
@@ -68,10 +67,34 @@ impl Mul for Matrix4 {
fn mul(self, rhs: Self) -> Self { fn mul(self, rhs: Self) -> Self {
let rhs = rhs.transpose(); let rhs = rhs.transpose();
Self { Self {
row1: [self.row1.dot(rhs.row1), self.row1.dot(rhs.row2), self.row1.dot(rhs.row3), self.row1.dot(rhs.row4)].into(), row1: [
row2: [self.row2.dot(rhs.row1), self.row2.dot(rhs.row2), self.row2.dot(rhs.row3), self.row2.dot(rhs.row4)].into(), self.row1.dot(rhs.row1),
row3: [self.row3.dot(rhs.row1), self.row3.dot(rhs.row2), self.row3.dot(rhs.row3), self.row3.dot(rhs.row4)].into(), self.row1.dot(rhs.row2),
row4: [self.row4.dot(rhs.row1), self.row4.dot(rhs.row2), self.row4.dot(rhs.row3), self.row4.dot(rhs.row4)].into(), self.row1.dot(rhs.row3),
self.row1.dot(rhs.row4),
]
.into(),
row2: [
self.row2.dot(rhs.row1),
self.row2.dot(rhs.row2),
self.row2.dot(rhs.row3),
self.row2.dot(rhs.row4),
]
.into(),
row3: [
self.row3.dot(rhs.row1),
self.row3.dot(rhs.row2),
self.row3.dot(rhs.row3),
self.row3.dot(rhs.row4),
]
.into(),
row4: [
self.row4.dot(rhs.row1),
self.row4.dot(rhs.row2),
self.row4.dot(rhs.row3),
self.row4.dot(rhs.row4),
]
.into(),
} }
} }
} }
+9 -9
View File
@@ -1,14 +1,14 @@
mod matrix4;
mod vector3;
mod vector2;
mod traits;
mod matrix3;
mod matrix2; mod matrix2;
mod matrix3;
mod matrix4;
mod traits;
mod vector2;
mod vector3;
mod vector4; mod vector4;
pub use matrix4::*;
pub use matrix3::*;
pub use matrix2::*; pub use matrix2::*;
pub use vector4::*; pub use matrix3::*;
pub use vector3::*; pub use matrix4::*;
pub use vector2::*; pub use vector2::*;
pub use vector3::*;
pub use vector4::*;
+23 -6
View File
@@ -1,8 +1,17 @@
use std::ops::{Add, Div, Mul, Sub};
use crate::math::Vector4; use crate::math::Vector4;
use std::ops::{Add, Div, Mul, Sub};
pub trait Vector: Clone + Copy + Default + PartialEq + Add + Sub + PartialOrd pub trait Vector:
+ Div<f32, Output = Self> + Mul<f32, Output = Self> { Clone
+ Copy
+ Default
+ PartialEq
+ Add
+ Sub
+ PartialOrd
+ Div<f32, Output = Self>
+ Mul<f32, Output = Self>
{
/// Gets the dot product of the two vectors. /// Gets the dot product of the two vectors.
fn dot(self, other: Self) -> f32; fn dot(self, other: Self) -> f32;
@@ -36,10 +45,18 @@ pub trait Vector: Clone + Copy + Default + PartialEq + Add + Sub + PartialOrd
/// Note that this trait does not require implementation of the `Div` trait at all - this is because /// Note that this trait does not require implementation of the `Div` trait at all - this is because
/// matrices do not have division, only multiplication by a scalar value. This doesn't mean that the /// matrices do not have division, only multiplication by a scalar value. This doesn't mean that the
/// scalar cannot be a decimal value, however. /// scalar cannot be a decimal value, however.
pub trait Matrix<TVec>: Clone + Copy + Default + PartialEq + Add + Sub pub trait Matrix<TVec>:
+ Mul<f32, Output = Self> + Mul<TVec, Output = TVec> Clone
+ Copy
+ Default
+ PartialEq
+ Add
+ Sub
+ Mul<f32, Output = Self>
+ Mul<TVec, Output = TVec>
+ Mul<Output = Self> + Mul<Output = Self>
where TVec: Vector where
TVec: Vector,
{ {
/// Creates an identity matrix. /// Creates an identity matrix.
fn identity() -> Self; fn identity() -> Self;
+3 -9
View File
@@ -1,5 +1,5 @@
use std::ops::{Add, Div, Mul, Sub, Index, IndexMut};
use crate::math::traits::Vector; use crate::math::traits::Vector;
use std::ops::{Add, Div, Index, IndexMut, Mul, Sub};
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)] #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Vector2 { pub struct Vector2 {
@@ -118,18 +118,12 @@ impl Vector for Vector2 {
impl From<[f32; 2]> for Vector2 { impl From<[f32; 2]> for Vector2 {
fn from(v: [f32; 2]) -> Self { fn from(v: [f32; 2]) -> Self {
Self { Self { x: v[0], y: v[1] }
x: v[0],
y: v[1],
}
} }
} }
impl From<f32> for Vector2 { impl From<f32> for Vector2 {
fn from(v: f32) -> Self { fn from(v: f32) -> Self {
Self { Self { x: v, y: 0.0 }
x: v,
y: 0.0,
}
} }
} }
+5 -17
View File
@@ -1,6 +1,6 @@
use std::ops::{Add, Div, Mul, Sub};
use crate::math::traits::Vector; use crate::math::traits::Vector;
use crate::math::vector2::Vector2; use crate::math::vector2::Vector2;
use std::ops::{Add, Div, Mul, Sub};
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)] #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Vector3 { pub struct Vector3 {
@@ -15,24 +15,15 @@ impl Vector3 {
} }
pub fn xy(&self) -> Vector2 { pub fn xy(&self) -> Vector2 {
Vector2::from([ Vector2::from([self.x, self.y])
self.x,
self.y
])
} }
pub fn yz(&self) -> Vector2 { pub fn yz(&self) -> Vector2 {
Vector2::from([ Vector2::from([self.y, self.z])
self.y,
self.z
])
} }
pub fn xz(&self) -> Vector2 { pub fn xz(&self) -> Vector2 {
Vector2::from([ Vector2::from([self.x, self.z])
self.x,
self.z
])
} }
pub fn xyz(&self) -> (f32, f32, f32) { pub fn xyz(&self) -> (f32, f32, f32) {
@@ -144,9 +135,6 @@ impl From<[f32; 3]> for Vector3 {
impl From<Vector2> for Vector3 { impl From<Vector2> for Vector3 {
fn from(v: Vector2) -> Self { fn from(v: Vector2) -> Self {
Self { Self { z: 0.0, ..v.into() }
z: 0.0,
..v.into()
}
} }
} }
+6 -21
View File
@@ -1,6 +1,6 @@
use std::ops::{Add, Div, Mul, Sub};
use crate::math::traits::Vector; use crate::math::traits::Vector;
use crate::math::{Vector2, Vector3}; use crate::math::{Vector2, Vector3};
use std::ops::{Add, Div, Mul, Sub};
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)] #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
pub struct Vector4 { pub struct Vector4 {
@@ -11,15 +11,8 @@ pub struct Vector4 {
} }
impl Vector4 { impl Vector4 {
pub fn new( pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
x: f32, Self { x, y, z, w }
y: f32,
z: f32,
w: f32,
) -> Self {
Self {
x, y, z, w
}
} }
pub fn one() -> Self { pub fn one() -> Self {
@@ -150,28 +143,20 @@ impl Vector for Vector4 {
impl From<[f32; 4]> for Vector4 { impl From<[f32; 4]> for Vector4 {
fn from([x, y, z, w]: [f32; 4]) -> Self { fn from([x, y, z, w]: [f32; 4]) -> Self {
Self { Self { x, y, z, w }
x, y, z, w,
}
} }
} }
impl From<[f32; 3]> for Vector4 { impl From<[f32; 3]> for Vector4 {
/// Creates a homogenous `Vector4` from a 3D positional vector. /// Creates a homogenous `Vector4` from a 3D positional vector.
fn from([x, y, z]: [f32; 3]) -> Self { fn from([x, y, z]: [f32; 3]) -> Self {
Self { Self { x, y, z, w: 1.0 }
x, y, z,
w: 1.0,
}
} }
} }
impl From<Vector3> for Vector4 { impl From<Vector3> for Vector4 {
fn from(Vector3 { x, y, z }: Vector3) -> Self { fn from(Vector3 { x, y, z }: Vector3) -> Self {
Self { Self { x, y, z, w: 1.0 }
x, y, z,
w: 1.0
}
} }
} }