From 1f980e7c121afd3081bb32a5ef3a85a5044230fb Mon Sep 17 00:00:00 2001 From: Till Date: Tue, 23 Jul 2019 21:55:02 +0200 Subject: [PATCH] asdf --- shaders/triangle.frag | 4 +- shaders/triangle.vert | 3 ++ src/main.rs | 28 ++++++++++--- src/vulkan.rs | 94 +++++++++++++++++++++++++++++-------------- 4 files changed, 91 insertions(+), 38 deletions(-) diff --git a/shaders/triangle.frag b/shaders/triangle.frag index 68ba49e..447bbcd 100644 --- a/shaders/triangle.frag +++ b/shaders/triangle.frag @@ -1,7 +1,9 @@ #version 450 +layout(location = 0) in vec3 pos; + layout(location = 0) out vec4 f_color; void main() { - f_color = vec4(0.0, 1.0, 0.0, 1.0); + f_color = vec4(pos, 1.0); } \ No newline at end of file diff --git a/shaders/triangle.vert b/shaders/triangle.vert index 3671517..eebfee0 100644 --- a/shaders/triangle.vert +++ b/shaders/triangle.vert @@ -2,10 +2,13 @@ layout(location = 0) in vec3 position; +layout(location = 0) out vec3 pos; + layout(push_constant) uniform push_constants { float time; } push; void main() { gl_Position = vec4(position + vec3(sin(push.time / 10.), 0., 0.), 1.0); + pos = gl_Position.xyz; } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6ec0bf8..a5f35dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use crate::vulkan::{Vertex, GameData}; -use winit::{DeviceId, KeyboardInput, ElementState, VirtualKeyCode}; +use winit::{Event, WindowEvent}; use std::time::SystemTime; +use std::iter::FromIterator; mod vulkan; @@ -9,11 +10,26 @@ impl GameData<'_> { } - fn on_keyboard_event(self: &Self, _: DeviceId, input: KeyboardInput) { - if input.state == ElementState::Pressed && input.virtual_keycode == Some(VirtualKeyCode::F) { - println!("doot"); + /// Returns true if event should be ignored by the vulkan handler + fn on_window_event(self: &Self, event: &Event) -> bool { + match event { + Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => { + let mods = String::from_iter( + vec!["shift", "ctrl", "alt", "logo"].iter() + .zip(vec![input.modifiers.shift, input.modifiers.ctrl, input.modifiers.alt, input.modifiers.logo]) + .filter(|(&_name, state)| *state) + .map(|(&name, _state)| name)); + if mods.len() > 0 { + println!("Keyboard {:?} input {:?} {:?} + {:?}", device_id, input.state, &mods, input.scancode) + } else { + println!("Keyboard {:?} input {:?} {:?}", device_id, input.state, input.scancode) + } + } + _ => {} } + return false; } + fn update_push_constants(self: &mut Self) { self.push_constants.time = self.start_time.elapsed().unwrap().as_millis() as f32 / 1000.0; } @@ -36,8 +52,8 @@ fn main() { Vertex { position: [0.2, 0.2, 0.3] } ], line_vertices: vec![ - Vertex { position: [-1., 0., 0.] }, - Vertex { position: [1., 0., 0.] }, + Vertex { position: [-0.9, 1., 0.] }, + Vertex { position: [0.9, 0., 0.] }, ], push_constants: &mut pc, start_time: SystemTime::now() diff --git a/src/vulkan.rs b/src/vulkan.rs index 0f406c2..cb40ad9 100644 --- a/src/vulkan.rs +++ b/src/vulkan.rs @@ -3,7 +3,7 @@ use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState}; use vulkano::device::{Device, DeviceExtensions}; use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, Subpass, RenderPassAbstract}; use vulkano::image::SwapchainImage; -use vulkano::instance::{Instance, PhysicalDevice}; +use vulkano::instance::{Instance, PhysicalDevice, ApplicationInfo, Version, RawInstanceExtensions}; use vulkano::pipeline::{GraphicsPipeline}; use vulkano::pipeline::shader::{GraphicsShaderType, ShaderModule}; use vulkano::pipeline::viewport::Viewport; @@ -11,6 +11,8 @@ use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, use vulkano::swapchain; use vulkano::sync::{GpuFuture, FlushError}; use vulkano::sync; +use vulkano::pipeline::vertex::SingleBufferDefinition; +use vulkano::descriptor::PipelineLayoutAbstract; use vulkano_win::VkSurfaceBuild; @@ -19,15 +21,14 @@ use winit::{EventsLoop, Window, WindowBuilder, Event, WindowEvent}; use std::sync::Arc; use std::time::SystemTime; use std::path::PathBuf; -use std::ffi::CStr; +use std::ffi::{CStr, CString}; use shade_runner; use shade_runner::{CompiledShaders, Entry}; use shaderc; -use vulkano::pipeline::vertex::SingleBufferDefinition; -use vulkano::descriptor::PipelineLayoutAbstract; use crate::PushConstants; +use vulkano::instance::debug::{DebugCallback, MessageTypes}; const VALIDATION_LAYERS: &[&str] = &[ "VK_LAYER_LUNARG_standard_validation" @@ -52,15 +53,45 @@ pub struct GameData<'a> { } pub fn init(mut game: GameData) { + if ENABLE_VALIDATION_LAYERS { + println!("Enabling validation layers..."); + } + let instance = { - let extensions = vulkano_win::required_extensions(); +// let mut extensions = RawInstanceExtensions::from(&vulkano_win::required_extensions()); + let mut extensions = vulkano_win::required_extensions(); + + let app_info = ApplicationInfo { + application_name: Some("Asuro Editor".into()), + application_version: Some(Version { major: 0, minor: 1, patch: 0 }), + engine_name: Some("Asuro Rust Engine".into()), + engine_version: Some(Version { major: 0, minor: 1, patch: 0 }) + }; if ENABLE_VALIDATION_LAYERS { - Instance::new(None, &extensions, VALIDATION_LAYERS.iter().cloned()).expect("failed to create Vulkan instance") + let available_layers = vulkano::instance::layers_list().unwrap().map(|layer| String::from(layer.name())).collect::>(); + + VALIDATION_LAYERS.iter().for_each(|wanted_layer_name| { + if !available_layers.iter().any(|available_layer_name| available_layer_name == wanted_layer_name) { + panic!("Validation layer not found: {:?}. Available layers: {:?}", wanted_layer_name, &available_layers.join(", ")); + } + }); + + extensions.ext_debug_report = true; +// extensions.insert(CString::new("VK_EXT_debug_utils").unwrap()); + + Instance::new(Some(&app_info), &extensions, VALIDATION_LAYERS.iter().cloned()).expect("failed to create Vulkan instance") } else { - Instance::new(None, &extensions, None).expect("failed to create Vulkan instance") + Instance::new(Some(&app_info), &extensions, None).expect("failed to create Vulkan instance") } }; + + if ENABLE_VALIDATION_LAYERS { + let debug_callback = setup_debug_callback(&instance); + assert!(debug_callback.is_some()); + println!("Debug callback created."); + } + let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); println!("Using device: {} (type: {:?})", physical.name(), physical.ty()); @@ -155,24 +186,8 @@ pub fn init(mut game: GameData) { }; let mesh_vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), game.mesh_vertices.iter().cloned()).unwrap(); - let line_vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), game.mesh_vertices.iter().cloned()).unwrap(); + let line_vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), game.line_vertices.iter().cloned()).unwrap(); - // The next step is to create the shaders. - // - // The raw shader creation API provided by the vulkano library is unsafe, for various reasons. - // - // An overview of what the `vulkano_shaders::shader!` macro generates can be found in the - // `vulkano-shaders` crate docs. You can view them at https://docs.rs/vulkano-shaders/ - // - // TODO: explain this in details - - // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL - // implicitly does a lot of computation whenever you draw. In Vulkan, you have to do all this - // manually. - - // The next step is to create a *render pass*, which is an object that describes where the - // output of the graphics pipeline will go. It describes the layout of the images - // where the colors, depth and/or stencil information will be written. let render_pass = Arc::new(vulkano::single_pass_renderpass!( device.clone(), attachments: { @@ -394,13 +409,12 @@ pub fn init(mut game: GameData) { // it. let mut done = false; events_loop.poll_events(|ev| { - match ev { - Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => done = true, - Event::WindowEvent { event: WindowEvent::Resized(_), .. } => recreate_swapchain = true, - Event::WindowEvent { event: WindowEvent::KeyboardInput { device_id, input }, .. } => { - game.on_keyboard_event(device_id, input); + if !game.on_window_event(&ev) { + match ev { + Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => done = true, + Event::WindowEvent { event: WindowEvent::Resized(_), .. } => recreate_swapchain = true, + _ => {} } - _ => {} } }); if done { return; } @@ -499,4 +513,22 @@ fn read_shader(vert_path_relative: &str, frag_path_relative: &str) -> (CompiledS } Err(error) => panic!("Shader compilation error: {:?}", error) } -} \ No newline at end of file +} + +fn setup_debug_callback(instance: &Arc) -> Option { + if !ENABLE_VALIDATION_LAYERS { + return None; + } + + let msg_types = MessageTypes { + error: true, + warning: true, + performance_warning: true, + information: true, + debug: true, + }; + + DebugCallback::new(&instance, msg_types, |msg| { + println!("validation layer: {:?}", msg.description); + }).ok() +}