1
2#![allow(dead_code)]
3#![allow(clippy::too_many_arguments)]
4
5pub mod common;
7
8pub mod init;
10
11pub mod basics;
13
14pub mod device;
16
17pub mod surface;
19
20pub mod renderpass;
22
23pub mod framebuffer;
25
26pub mod rendertarget;
28
29pub mod swapchain;
31
32pub mod cmdpool;
34
35pub mod shader;
37
38pub mod descpool;
40
41pub mod context;
43
44pub mod buffer;
46
47pub mod buffervec;
49
50pub mod texture;
52
53pub mod material;
55
56pub mod mesh;
58
59pub mod descprops;
61
62pub mod pipeline;
64
65extern crate nalgebra_glm as glm;
66
67pub 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}