You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
9.9KB

  1. #[macro_use]
  2. mod util;
  3. mod conf;
  4. mod hal;
  5. mod render;
  6. //mod vire;
  7. use crate::{
  8. render::*,
  9. util::{log, meta},
  10. };
  11. use ash::{version::DeviceV1_0, vk};
  12. use cgmath::{prelude::*, Matrix4, Point3, Rad, Vector2, Vector3};
  13. use std::rc::Rc;
  14. struct Pipelines {
  15. main: Rc<Pipeline>,
  16. }
  17. struct SwapchainData<'a> {
  18. swapchain: Rc<Swapchain>,
  19. image_f: Vec<Option<&'a Fence>>,
  20. descriptor_pool: Rc<DescriptorPool>,
  21. cmd_pool: Rc<CommandPool>,
  22. }
  23. impl Pipelines {
  24. fn create_from(mut pipelines: Vec<Rc<Pipeline>>) -> Self {
  25. let main = pipelines.pop().unwrap();
  26. Self { main }
  27. }
  28. }
  29. impl SwapchainData<'_> {
  30. pub fn create(
  31. device: Rc<Device>,
  32. phys_device: &PhysicalDevice,
  33. surface: Rc<Surface>,
  34. shader_vert: Rc<ShaderModule>,
  35. shader_frag: Rc<ShaderModule>,
  36. layout: Rc<PipelineLayout>,
  37. vertex_buffer: Rc<Buffer>,
  38. index_buffer: Rc<Buffer>,
  39. queue_graphics: &Queue,
  40. queue_surface: &Queue,
  41. conf: &render::Conf,
  42. ) -> Result<Self, ErrBufferCreate> {
  43. let swapchain = Swapchain::create(
  44. device.clone(),
  45. &phys_device,
  46. surface,
  47. conf,
  48. queue_graphics,
  49. queue_surface,
  50. )?;
  51. let images = Swapchain::get_images(swapchain.clone())?;
  52. let image_f = vec![None; images.len()];
  53. let image_views =
  54. ImageView::create_all(device.clone(), &images, swapchain.format)?;
  55. let render_pass = RenderPass::create(device.clone(), swapchain.format)?;
  56. let pipelines = Pipeline::create_all(
  57. device.clone(),
  58. &[
  59. PipelineCreateInfo::info_basic(
  60. shader_vert,
  61. shader_frag,
  62. layout.clone(),
  63. render_pass.clone(),
  64. swapchain.extent,
  65. ),
  66. ],
  67. )?;
  68. let pipelines = Pipelines::create_from(pipelines);
  69. let framebuffers = Framebuffer::create_all(
  70. device.clone(),
  71. render_pass.clone(),
  72. &image_views,
  73. swapchain.extent,
  74. )?;
  75. let uniform_buffers =
  76. framebuffers
  77. .iter()
  78. .map(|_| Buffer::create_uniform(device.clone(), phys_device))
  79. .collect::<Result<_, _>>()?;
  80. let descriptor_pool = DescriptorPool::create(
  81. device.clone(),
  82. uniform_buffers,
  83. layout.descriptor.clone(),
  84. )?;
  85. let cmd_pool = CommandPool::create_graphics(
  86. device,
  87. queue_graphics.index,
  88. &framebuffers,
  89. render_pass,
  90. swapchain.extent,
  91. |cmd, framebuffer_num| {
  92. cmd.bind_pipeline(pipelines.main.clone());
  93. cmd.bind_vertex_buffer(vertex_buffer.clone());
  94. cmd.bind_index_buffer(index_buffer.clone());
  95. cmd.bind_descriptor_pool(
  96. descriptor_pool.clone(),
  97. layout.clone(),
  98. framebuffer_num,
  99. );
  100. cmd.draw(INDICES.len());
  101. },
  102. )?;
  103. Ok(Self { swapchain, image_f, descriptor_pool, cmd_pool })
  104. }
  105. }
  106. fn draw_frame<'a>(
  107. sc_data: &mut SwapchainData<'a>,
  108. device: &Device,
  109. image_avail_s: &Semaphore,
  110. render_fini_s: &Semaphore,
  111. frame_f: &'a Fence,
  112. queue_graphics: &Queue,
  113. queue_surface: &Queue,
  114. time_ms: u128,
  115. ) -> Result<(), vk::Result> {
  116. let cmd_buffers = sc_data.cmd_pool.buf_handles();
  117. let fences = [**frame_f];
  118. unsafe {
  119. device.wait_for_fences(&fences, true, u64::max_value())?;
  120. }
  121. let image_index = unsafe {
  122. device
  123. .swapchain_ext
  124. .acquire_next_image(
  125. **sc_data.swapchain,
  126. u64::max_value(),
  127. **image_avail_s,
  128. vk::Fence::null(),
  129. )?
  130. .0 as usize
  131. };
  132. if let Some(fence) = sc_data.image_f[image_index] {
  133. let fences = [**fence];
  134. unsafe {
  135. device.wait_for_fences(&fences, true, u64::max_value())?;
  136. }
  137. }
  138. sc_data.image_f[image_index] = Some(frame_f);
  139. let uniforms = Uniforms {
  140. object:
  141. Matrix4::from_angle_z(Rad::full_turn() * time_ms as f32 / 10_000.0),
  142. camera: Matrix4::look_at(
  143. Point3::new(2.0, 2.0, 2.0),
  144. Point3::new(0.0, 0.0, 0.0),
  145. Vector3::new(0.0, 0.0, 1.0),
  146. ),
  147. projection:
  148. cgmath::perspective(
  149. Rad::turn_div_4(),
  150. sc_data.swapchain.extent.width as f32 /
  151. sc_data.swapchain.extent.height as f32,
  152. 0.01,
  153. 100_000.0,
  154. ) *
  155. Matrix4::new(
  156. 1.0, 0.0, 0.0, 0.0,
  157. 0.0, -1.0, 0.0, 0.0,
  158. 0.0, 0.0, 1.0, 0.0,
  159. 0.0, 0.0, 0.0, 1.0,
  160. ),
  161. };
  162. sc_data.descriptor_pool.buffers[image_index].write_data(&[uniforms])?;
  163. let wait_semaphores = [**image_avail_s];
  164. let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
  165. let signal_semaphores = [**render_fini_s];
  166. let submit_cmd_buffers = &cmd_buffers[image_index..=image_index];
  167. let submit_info = [
  168. vk::SubmitInfo {
  169. wait_semaphore_count: wait_semaphores.len() as u32,
  170. p_wait_semaphores: wait_semaphores.as_ptr(),
  171. p_wait_dst_stage_mask: wait_stages.as_ptr(),
  172. command_buffer_count: submit_cmd_buffers.len() as u32,
  173. p_command_buffers: submit_cmd_buffers.as_ptr(),
  174. signal_semaphore_count: signal_semaphores.len() as u32,
  175. p_signal_semaphores: signal_semaphores.as_ptr(),
  176. ..Default::default()
  177. }
  178. ];
  179. unsafe {
  180. device.reset_fences(&fences)?;
  181. device.queue_submit(**queue_graphics, &submit_info, **frame_f)?;
  182. }
  183. let swapchains = [**sc_data.swapchain];
  184. let image_indices = [image_index as u32];
  185. let present_info = vk::PresentInfoKHR {
  186. wait_semaphore_count: signal_semaphores.len() as u32,
  187. p_wait_semaphores: signal_semaphores.as_ptr(),
  188. swapchain_count: swapchains.len() as u32,
  189. p_swapchains: swapchains.as_ptr(),
  190. p_image_indices: image_indices.as_ptr(),
  191. ..Default::default()
  192. };
  193. unsafe {
  194. device.swapchain_ext.queue_present(**queue_surface, &present_info)?;
  195. device.queue_wait_idle(**queue_surface)?;
  196. }
  197. Ok(())
  198. }
  199. fn seize_device(lg: &log::Log, device: &Device) {
  200. let seize = unsafe { device.device_wait_idle() };
  201. if let Err(e) = seize {
  202. lg!(lg, log::Level::Error, "Error seizing renderer state: {}", e);
  203. }
  204. }
  205. fn fallback_main(
  206. conf: &conf::Conf,
  207. lg: &log::Log,
  208. ) -> Result<(), Box<dyn std::error::Error>> {
  209. let start_time = std::time::Instant::now();
  210. /*
  211. let main = {
  212. use std::io::prelude::*;
  213. let mut file = std::fs::File::open("main.vire")?;
  214. let mut data = String::new();
  215. file.read_to_string(&mut data)?;
  216. match vire::parser::datum::Datum::parse(&data) {
  217. Ok(datum) => datum,
  218. Err(res) => {
  219. lg!(
  220. lg, log::Level::Error, "`main.vire': {}",
  221. vire::parser::printable_error(&data, res),
  222. );
  223. Vec::new()
  224. }
  225. }
  226. };
  227. vire::interpreter::read_all(lg, &main);
  228. */
  229. let concur_frames = conf.render.concurrent_frames.into();
  230. let hal = hal::Context::new()?;
  231. let window = hal::Window::new(&hal, meta::ffi::name(), 640, 480)?;
  232. let entry = ash::Entry::new()?;
  233. let instance = Instance::create(&conf.render, entry, &window)?;
  234. let phys_device = PhysicalDevice::get(instance.clone(), &conf.render)?;
  235. let surface = Surface::create(instance.clone(), &window)?;
  236. let qf_info = QueueFamilyInfo::collect(&instance, &surface, &phys_device)?;
  237. let device = Device::create(instance, &phys_device, &qf_info)?;
  238. let queue_graphics = Queue::get(device.clone(), qf_info.gfx_index);
  239. let queue_surface = Queue::get(device.clone(), qf_info.srf_index);
  240. let vertex_buffer = Buffer::create_vertex(
  241. device.clone(),
  242. &phys_device,
  243. VERTICES,
  244. &queue_graphics,
  245. )?;
  246. let index_buffer = Buffer::create_index(
  247. device.clone(),
  248. &phys_device,
  249. INDICES,
  250. &queue_graphics,
  251. )?;
  252. let image_avail_s = Semaphore::create_all(device.clone(), concur_frames)?;
  253. let render_fini_s = Semaphore::create_all(device.clone(), concur_frames)?;
  254. let frame_f = Fence::create_all(device.clone(), concur_frames)?;
  255. let desc_layout = DescriptorSetLayout::create(device.clone())?;
  256. let layout = PipelineLayout::create(desc_layout)?;
  257. let spir_vert = Spir::read(MAIN_VERT);
  258. let spir_frag = Spir::read(MAIN_FRAG);
  259. let shader_vert = ShaderModule::create(device.clone(), &spir_vert)?;
  260. let shader_frag = ShaderModule::create(device.clone(), &spir_frag)?;
  261. let mut sc_data = SwapchainData::create(
  262. device.clone(),
  263. &phys_device,
  264. surface.clone(),
  265. shader_vert.clone(),
  266. shader_frag.clone(),
  267. layout.clone(),
  268. vertex_buffer.clone(),
  269. index_buffer.clone(),
  270. &queue_graphics,
  271. &queue_surface,
  272. &conf.render,
  273. )?;
  274. let mut cur_c_frame = 0;
  275. 'main_loop: loop {
  276. for event in hal::EventIterator {
  277. match event {
  278. hal::Event::Quit => break 'main_loop,
  279. }
  280. }
  281. let frame = draw_frame(
  282. &mut sc_data,
  283. &device,
  284. &image_avail_s[cur_c_frame],
  285. &render_fini_s[cur_c_frame],
  286. &frame_f[cur_c_frame],
  287. &queue_graphics,
  288. &queue_surface,
  289. start_time.elapsed().as_millis(),
  290. );
  291. match frame {
  292. Ok(()) => {}
  293. Err(vk::Result::ERROR_OUT_OF_DATE_KHR) => {
  294. seize_device(lg, &device);
  295. sc_data = SwapchainData::create(
  296. device.clone(),
  297. &phys_device,
  298. surface.clone(),
  299. shader_vert.clone(),
  300. shader_frag.clone(),
  301. layout.clone(),
  302. vertex_buffer.clone(),
  303. index_buffer.clone(),
  304. &queue_graphics,
  305. &queue_surface,
  306. &conf.render,
  307. )?;
  308. }
  309. Err(res) => {
  310. lg!(lg, log::Level::Error, "Error rendering frame: {}", res);
  311. }
  312. }
  313. cur_c_frame = (cur_c_frame + 1) % concur_frames;
  314. }
  315. seize_device(lg, &device);
  316. Ok(())
  317. }
  318. fn main() {
  319. let lg = log::Log::new();
  320. #[cfg(feature = "color-log")]
  321. let lg = lg.insert_mode("Color", log::Color).set_mode("Color").unwrap();
  322. let conf = conf::Conf::read("blonkus.yaml").unwrap_or_else(|err| {
  323. let level = match err {
  324. conf::ErrConfLoad::NoFile => log::Level::Notice,
  325. _ => log::Level::Error,
  326. };
  327. lg!(&lg, level, "{}", err);
  328. lg!(&lg, log::Level::Notice, "Using default configuration.");
  329. conf::Conf::default()
  330. });
  331. if let Err(e) = fallback_main(&conf, &lg) {
  332. lg!(&lg, log::Level::Critical, "Uncaught error: {}", e);
  333. }
  334. }
  335. const VERTICES: &[Vertex] = &[
  336. Vertex { pos: Vector2::new(-0.5, -0.5), color: Vector3::new(1.0, 0.0, 0.0) },
  337. Vertex { pos: Vector2::new( 0.5, -0.5), color: Vector3::new(0.0, 1.0, 0.0) },
  338. Vertex { pos: Vector2::new( 0.5, 0.5), color: Vector3::new(0.0, 0.0, 1.0) },
  339. Vertex { pos: Vector2::new(-0.5, 0.5), color: Vector3::new(1.0, 1.0, 1.0) },
  340. ];
  341. const INDICES: &[u16] = &[0, 1, 2, 2, 3, 0];
  342. const MAIN_VERT: &[u8] =
  343. include_bytes!(concat!(env!("OUT_DIR"), "/main.vert.o"));
  344. const MAIN_FRAG: &[u8] =
  345. include_bytes!(concat!(env!("OUT_DIR"), "/main.frag.o"));
  346. // EOF