vkobject_rs/
lib.rs

1
2#![allow(dead_code)]
3#![allow(clippy::too_many_arguments)]
4
5/// The common helper library
6pub mod common;
7
8/// The VkCore initializer
9pub mod init;
10
11/// The Vulkan basics
12pub mod basics;
13
14/// The Vulkan device
15pub mod device;
16
17/// The Vulkan surface
18pub mod surface;
19
20/// The Vulkan renderpass
21pub mod renderpass;
22
23/// The Vulkan framebuffer
24pub mod framebuffer;
25
26/// The render target
27pub mod rendertarget;
28
29/// The Vulkan swapchain
30pub mod swapchain;
31
32/// The Vulkan command pool
33pub mod cmdpool;
34
35/// The Vulkan shader
36pub mod shader;
37
38/// The Vulkan descriptor pool object
39pub mod descpool;
40
41/// The Vulkan context
42pub mod context;
43
44/// The buffer object
45pub mod buffer;
46
47/// The advanced buffer object that could be used as a vector
48pub mod buffervec;
49
50/// The texture object
51pub mod texture;
52
53/// The material object
54pub mod material;
55
56/// The mesh object
57pub mod mesh;
58
59/// The descriptor set properties
60pub mod descprops;
61
62/// The pipeline object to wiring up buffers from a mesh, shaders, rendertargets together.
63pub mod pipeline;
64
65extern crate nalgebra_glm as glm;
66
67/// The common things for you to use
68pub mod prelude {
69	pub use vkcore_rs::*;
70	pub use glm::*;
71	pub use half::f16;
72	pub use struct_iterable::Iterable;
73	pub use crate::common::*;
74	pub use crate::init::*;
75	pub use crate::basics::*;
76	pub use crate::device::*;
77	pub use crate::surface::*;
78	pub use crate::renderpass::*;
79	pub use crate::framebuffer::*;
80	pub use crate::rendertarget::*;
81	pub use crate::swapchain::*;
82	pub use crate::cmdpool::*;
83	pub use crate::shader::*;
84	pub use crate::descpool::*;
85	pub use crate::context::*;
86	pub use crate::buffer::*;
87	pub use crate::buffervec::*;
88	pub use crate::texture::*;
89	pub use crate::material::*;
90	pub use crate::mesh::*;
91	pub use crate::descprops::*;
92	pub use crate::pipeline::*;
93	pub use crate::derive_vertex_type;
94	pub use crate::derive_uniform_buffer_type;
95	pub use crate::derive_storage_buffer_type;
96}
97
98#[cfg(test)]
99mod tests {
100	use glfw::*;
101	use crate::prelude::*;
102	use std::{
103		collections::HashMap,
104		path::PathBuf,
105		slice::from_raw_parts_mut,
106		sync::{Arc, Mutex},
107	};
108
109	const TEST_TIME: f64 = 10.0;
110
111	#[derive(Debug)]
112	pub struct TestInstance {
113		pub ctx: VulkanContext,
114		pub window: PWindow,
115		pub events: GlfwReceiver<(f64, WindowEvent)>,
116		pub glfw: Glfw,
117		pub num_frames: u64,
118	}
119
120	derive_vertex_type! {
121		pub struct VertexType {
122			pub position: Vec2,
123		}
124	}
125
126	derive_uniform_buffer_type! {
127		pub struct UniformInput {
128			resolution: Vec3,
129			time: f32,
130		}
131	}
132
133	impl TestInstance {
134		pub fn new(width: u32, height: u32, title: &str, window_mode: glfw::WindowMode) -> Result<Self, VulkanError> {
135			let mut glfw = glfw::init(glfw::fail_on_errors).unwrap();
136			glfw.window_hint(WindowHint::ClientApi(ClientApiHint::NoApi));
137			let (mut window, events) = glfw.create_window(width, height, title, window_mode).expect("Failed to create GLFW window.");
138			window.set_key_polling(true);
139			let ctx = create_vulkan_context(&window, PresentInterval::VSync, 1, false)?;
140			Ok(Self {
141				glfw,
142				window,
143				events,
144				num_frames: 0,
145				ctx,
146			})
147		}
148
149		pub fn run(&mut self,
150			test_time: Option<f64>,
151			mut on_render: impl FnMut(&mut VulkanContext, f64) -> Result<(), VulkanError>
152		) -> Result<(), VulkanError> {
153			let start_time = self.glfw.get_time();
154			let mut time_in_sec: u64 = 0;
155			let mut num_frames_prev: u64 = 0;
156			while !self.window.should_close() {
157				let cur_frame_time = self.glfw.get_time();
158				let run_time = cur_frame_time - start_time;
159				on_render(&mut self.ctx, run_time)?;
160				self.num_frames += 1;
161
162				let new_time_in_sec = run_time.floor() as u64;
163				if new_time_in_sec > time_in_sec {
164					let fps = self.num_frames - num_frames_prev;
165					println!("FPS: {fps}\tat {new_time_in_sec}s");
166					time_in_sec = new_time_in_sec;
167					num_frames_prev = self.num_frames;
168				}
169
170				self.glfw.poll_events();
171				for (_, event) in glfw::flush_messages(&self.events) {
172					match event {
173						glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
174							self.window.set_should_close(true);
175						}
176						_ => {}
177					}
178				}
179				if let Some(test_time) = test_time {
180					if run_time >= test_time {
181						self.window.set_should_close(true);
182					}
183				}
184			}
185			println!("End of the test");
186			Ok(())
187		}
188	}
189
190	unsafe impl Send for TestInstance {}
191	unsafe impl Sync for TestInstance {}
192
193	#[test]
194	fn test() {
195		let mut inst = Box::new(TestInstance::new(1024, 768, "GLFW Window", glfw::WindowMode::Windowed).unwrap());
196
197		struct Resources {
198			uniform_input: Arc<dyn GenericUniformBuffer>,
199			pipeline: Pipeline,
200		}
201
202		impl Resources {
203			pub fn new(ctx: &mut VulkanContext) -> Result<Self, VulkanError> {
204				let device = ctx.device.clone();
205				let draw_shaders = Arc::new(DrawShaders::new(
206					Arc::new(VulkanShader::new_from_source_file_or_cache(device.clone(), ShaderSourcePath::VertexShader(PathBuf::from("shaders/test.vsh")), false, "main", OptimizationLevel::Performance, false)?),
207					None,
208					None,
209					None,
210					Arc::new(VulkanShader::new_from_source_file_or_cache(device.clone(), ShaderSourcePath::FragmentShader(PathBuf::from("shaders/test.fsh")), false, "main", OptimizationLevel::Performance, false)?),
211				));
212				let uniform_input: Arc<dyn GenericUniformBuffer> = Arc::new(UniformBuffer::<UniformInput>::new(device.clone())?);
213				let desc_prop = vec![uniform_input.clone()];
214				let desc_props: HashMap<u32, HashMap<u32, Arc<DescriptorProp>>> = [(0, [(0, Arc::new(DescriptorProp::UniformBuffers(desc_prop)))].into_iter().collect())].into_iter().collect();
215				let desc_props = Arc::new(DescriptorProps::new(desc_props));
216				let pool_in_use = ctx.cmdpools[0].use_pool(None)?;
217				let vertices_data = vec![
218					VertexType {
219						position: Vec2::new(-1.0, -1.0),
220					},
221					VertexType {
222						position: Vec2::new( 1.0, -1.0),
223					},
224					VertexType {
225						position: Vec2::new(-1.0,  1.0),
226					},
227					VertexType {
228						position: Vec2::new( 1.0,  1.0),
229					},
230				];
231				let vertices = BufferWithType::new(device.clone(), &vertices_data, pool_in_use.cmdbuf, VkBufferUsageFlagBits::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT as VkBufferUsageFlags)?;
232				let mesh = Arc::new(Mutex::new(GenericMeshWithMaterial::new(Box::new(Mesh::new(VkPrimitiveTopology::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices, buffer_unused(), buffer_unused(), buffer_unused())), None)));
233				mesh.lock().unwrap().mesh.flush(pool_in_use.cmdbuf)?;
234				drop(pool_in_use);
235				ctx.cmdpools[0].wait_for_submit(u64::MAX)?;
236				mesh.lock().unwrap().mesh.discard_staging_buffers();
237				let pipeline = ctx.create_pipeline_builder(mesh, draw_shaders, desc_props.clone())?
238				.set_cull_mode(VkCullModeFlagBits::VK_CULL_MODE_NONE as VkCullModeFlags)
239				.set_depth_test(false)
240				.set_depth_write(false)
241				.build()?;
242				Ok(Self {
243					uniform_input,
244					pipeline,
245				})
246			}
247
248			pub fn draw(&self, ctx: &mut VulkanContext, run_time: f64) -> Result<(), VulkanError> {
249				let scene = ctx.begin_scene(0, None)?;
250				let cmdbuf = scene.get_cmdbuf();
251				let extent = scene.get_rendertarget_extent();
252
253				let ui_data = unsafe {from_raw_parts_mut(self.uniform_input.get_staging_buffer_address() as *mut UniformInput, 1)};
254				ui_data[0] = UniformInput {
255					resolution: Vec3::new(extent.width as f32, extent.height as f32, 1.0),
256					time: run_time as f32,
257				};
258				self.uniform_input.flush(cmdbuf)?;
259
260				scene.set_viewport_swapchain(0.0, 1.0)?;
261				scene.set_scissor_swapchain()?;
262				scene.begin_renderpass(Vec4::new(0.0, 0.0, 0.2, 1.0), 1.0, 0)?;
263				self.pipeline.draw(cmdbuf)?;
264				scene.end_renderpass()?;
265				scene.finish();
266				Ok(())
267			}
268		}
269
270		let resources = Resources::new(&mut inst.ctx).unwrap();
271
272		inst.run(Some(TEST_TIME),
273		|ctx: &mut VulkanContext, run_time: f64| -> Result<(), VulkanError> {
274			resources.draw(ctx, run_time)
275		}).unwrap();
276	}
277}