diff --git a/shaders/frag.frag b/shaders/frag.frag index 7be9bb8..5110430 100644 --- a/shaders/frag.frag +++ b/shaders/frag.frag @@ -6,7 +6,7 @@ layout(location = 0) in vec4 normal; layout(location = 1) in vec4 pos_pre; layout(push_constant, std430) uniform pc { - layout(offset=32) vec4 data; + layout(offset=48) vec4 data; }; void main() { diff --git a/shaders/frag.spv b/shaders/frag.spv index f52d8db..caa5771 100644 Binary files a/shaders/frag.spv and b/shaders/frag.spv differ diff --git a/shaders/vert.spv b/shaders/vert.spv index afe0599..5aaa550 100644 Binary files a/shaders/vert.spv and b/shaders/vert.spv differ diff --git a/shaders/vert.vert b/shaders/vert.vert index 7a2a36b..5ed8c2c 100644 --- a/shaders/vert.vert +++ b/shaders/vert.vert @@ -8,6 +8,7 @@ layout(std430, set = 0, binding = 0) buffer positions_buffer { layout(push_constant, std430) uniform pc { layout(offset=0) vec4 cam_orig; layout(offset=16) vec4 cam_rot; + layout(offset=32) uvec2 screen_res; }; layout (location = 0) out vec4 normal; @@ -48,7 +49,7 @@ void main() { 0.0, 0.0, 0.0, 1.0 ); mat4 project_aspect = mat4( - (1080.0/1920.0), 0.0, 0.0, 0.0, + (float(screen_res.y)/float(screen_res.x)), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 diff --git a/src/main.rs b/src/main.rs index 9504522..43e289f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,8 @@ use std::ffi::CString; use raw_window_handle::HasDisplayHandle; use raw_window_handle::HasWindowHandle; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; use sdl2::video::Window; const APP_NAME: &str = "MineClone"; @@ -411,10 +413,10 @@ fn setup_pipe_layout(dev: &Device) -> vk::PipelineLayout { vk::PushConstantRange::default() .stage_flags(vk::ShaderStageFlags::VERTEX) .offset(0) - .size(32), // vec4 camera_orig, camera_rot + .size(48), // vec4 camera_orig, camera_rot vk::PushConstantRange::default() .stage_flags(vk::ShaderStageFlags::FRAGMENT) - .offset(32) + .offset(48) .size(16), // vec4 base_color ]; @@ -450,9 +452,9 @@ fn setup_pipeline( dev: &Device, vert_shader: &vk::ShaderModule, frag_shader: &vk::ShaderModule, + pass: &vk::RenderPass, + pipe_layout: &vk::PipelineLayout, ) -> vk::Pipeline { - let pipe_layout = setup_pipe_layout(&dev); - let pass = setup_render_pass(&dev); let shader_stages = setup_shader_stage(&dev, *vert_shader, *frag_shader); let vert_input = vk::PipelineVertexInputStateCreateInfo::default(); let input_assembly = vk::PipelineInputAssemblyStateCreateInfo::default() @@ -508,9 +510,9 @@ fn setup_pipeline( .multisample_state(&multisample) .depth_stencil_state(&depth_stencil) .color_blend_state(&color_blend) - .layout(pipe_layout) + .layout(*pipe_layout) .dynamic_state(&dynamic) - .render_pass(pass) + .render_pass(*pass) .subpass(0); let pipe = unsafe { @@ -633,6 +635,355 @@ fn make_swap_views( views } +fn make_depth_view(dev: &Device, depth_img: &vk::Image, format: vk::Format) -> vk::ImageView { + let view_info = vk::ImageViewCreateInfo::default() + .image(*depth_img) + .view_type(vk::ImageViewType::TYPE_2D) + .format(format) + .components(vk::ComponentMapping::default()) + .subresource_range( + vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::DEPTH) + .base_mip_level(0) + .level_count(1) + .base_array_layer(0) + .layer_count(1), + ); + let view = unsafe { + dev.create_image_view(&view_info, None) + .expect("Failed to create image view") + }; + view +} + +fn make_framebufs( + dev: &Device, + swap_views: &Vec, + depth_view: &vk::ImageView, + pass: &vk::RenderPass, + width: u32, + height: u32, +) -> Vec { + let mut framebufs = Vec::new(); + for view in swap_views.iter() { + let attachments = [*view, *depth_view]; + let framebuf_info = vk::FramebufferCreateInfo::default() + .render_pass(*pass) + .attachments(attachments.as_ref()) + .width(width) + .height(height) + .layers(1); + let framebuf = unsafe { + dev.create_framebuffer(&framebuf_info, None) + .expect("Failed to create framebuffer") + }; + framebufs.push(framebuf); + } + framebufs +} + +fn make_desc_sets(dev: &Device, desc_pool: &vk::DescriptorPool) -> Vec { + let layout = setup_desc_layout(&dev); + let layouts = [layout]; + let alloc_info = vk::DescriptorSetAllocateInfo::default() + .descriptor_pool(*desc_pool) + .set_layouts(&layouts); + let sets = unsafe { + dev.allocate_descriptor_sets(&alloc_info) + .expect("Failed to allocate descriptor sets") + }; + sets +} + +fn write_desc_sets(dev: &Device, desc_sets: &Vec, mesh_buf: &vk::Buffer) { + let buf_info = vk::DescriptorBufferInfo::default() + .buffer(*mesh_buf) + .offset(0) + .range(vk::WHOLE_SIZE); + let buf_infos = [buf_info]; + let buf_desc = vk::WriteDescriptorSet::default() + .dst_set(desc_sets[0]) + .dst_binding(0) + .dst_array_element(0) + .descriptor_type(vk::DescriptorType::STORAGE_BUFFER) + .buffer_info(&buf_infos); + unsafe { + dev.update_descriptor_sets(&[buf_desc], &[]); + } +} + +fn make_sem(dev: &Device) -> vk::Semaphore { + let sem_info = vk::SemaphoreCreateInfo::default(); + let sem = unsafe { + dev.create_semaphore(&sem_info, None) + .expect("Failed to create semaphore") + }; + sem +} + +fn make_fence(dev: &Device) -> vk::Fence { + let fence_info = vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED); + let fence = unsafe { + dev.create_fence(&fence_info, None) + .expect("Failed to create fence") + }; + fence +} + +fn wait_for_fence(dev: &Device, fence: &vk::Fence) { + unsafe { + let fence = [*fence]; + dev.wait_for_fences(&fence, true, u64::MAX) + .expect("Failed to wait for fence"); + } +} + +fn reset_fence(dev: &Device, fence: &vk::Fence) { + unsafe { + let fence = [*fence]; + dev.reset_fences(&fence).expect("Failed to reset fence"); + } +} + +fn ack_next_img( + dev: &Device, + swapchain_loader: &swapchain::Device, + swapchain: &vk::SwapchainKHR, + sem_avail: &vk::Semaphore, + fence: &vk::Fence, +) -> u32 { + unsafe { + let (img_inx, _) = swapchain_loader + .acquire_next_image(*swapchain, u64::MAX, *sem_avail, vk::Fence::null()) + .expect("Failed to acquire next image"); + img_inx + } +} + +fn record_commands( + dev: &Device, + cmd_buf: &vk::CommandBuffer, + framebuf: &vk::Framebuffer, + pass: &vk::RenderPass, + layout: &vk::PipelineLayout, + width: u32, + height: u32, + pipe: &vk::Pipeline, + desc_sets: &Vec, + camera: &Camera, +) { + let clear_vals = [ + vk::ClearValue { + color: vk::ClearColorValue { + float32: [0.0, 0.0, 0.0, 1.0], + }, + }, + vk::ClearValue { + depth_stencil: vk::ClearDepthStencilValue { + depth: 1.0, + stencil: 0, + }, + }, + ]; + + let render_pass_info = vk::RenderPassBeginInfo::default() + .render_pass(*pass) + .framebuffer(*framebuf) + .render_area( + vk::Rect2D::default() + .offset(vk::Offset2D::default()) + .extent(vk::Extent2D { width, height }), + ) + .clear_values(&clear_vals); + + unsafe { + dev.cmd_begin_render_pass(*cmd_buf, &render_pass_info, vk::SubpassContents::INLINE); + dev.cmd_bind_pipeline(*cmd_buf, vk::PipelineBindPoint::GRAPHICS, *pipe); + dev.cmd_bind_descriptor_sets( + *cmd_buf, + vk::PipelineBindPoint::GRAPHICS, + *layout, + 0, + desc_sets.as_ref(), + &[], + ); + dev.cmd_set_viewport_with_count( + *cmd_buf, + &[vk::Viewport::default() + .width(width as f32) + .height(height as f32)], + ); + dev.cmd_set_scissor_with_count( + *cmd_buf, + &[vk::Rect2D::default().extent(vk::Extent2D { width, height })], + ); + let cam_data: Vec = (Vec::::from([ + camera.origin.x, + camera.origin.y, + camera.origin.z, + 0.0, + camera.rotation.x, + camera.rotation.y, + camera.rotation.z, + ])) + .iter() + .map(|f| f.to_ne_bytes()) + .collect::>() + .into_flattened(); + + let screen_res: Vec = (Vec::::from([width, height])) + .iter() + .map(|f| f.to_ne_bytes()) + .collect::>() + .into_flattened(); + let base_color: Vec = (Vec::::from([0.0, 1.0, 1.0, 1.0])) + .iter() + .map(|f| f.to_ne_bytes()) + .collect::>() + .into_flattened(); + + dev.cmd_push_constants( + *cmd_buf, + *layout, + vk::ShaderStageFlags::VERTEX, + 0, + cam_data.as_ref(), + ); + dev.cmd_push_constants( + *cmd_buf, + *layout, + vk::ShaderStageFlags::VERTEX, + 32, + screen_res.as_ref(), + ); + dev.cmd_push_constants( + *cmd_buf, + *layout, + vk::ShaderStageFlags::FRAGMENT, + 48, + base_color.as_ref(), + ); + dev.cmd_draw(*cmd_buf, 36, 1, 0, 0); + dev.cmd_end_render_pass(*cmd_buf); + } +} + +fn start_cmd_buf(dev: &Device, cmd_buf: &vk::CommandBuffer) { + unsafe { + dev.reset_command_buffer(*cmd_buf, vk::CommandBufferResetFlags::empty()) + .expect("Failed to reset command buffer"); + let begin_info = + vk::CommandBufferBeginInfo::default().flags(vk::CommandBufferUsageFlags::empty()); + dev.begin_command_buffer(*cmd_buf, &begin_info) + .expect("Failed to begin command buffer"); + } +} + +fn end_cmd_buf(dev: &Device, cmd_buf: &vk::CommandBuffer) { + unsafe { + dev.end_command_buffer(*cmd_buf) + .expect("Failed to end command buffer"); + } +} + +fn submit_queue( + dev: &Device, + queue: &vk::Queue, + cmd_buf: &vk::CommandBuffer, + sem_avail: &vk::Semaphore, + sem_finish: &vk::Semaphore, + fence: &vk::Fence, +) { + let cmd_bufs = [*cmd_buf]; + let wait_sems = [*sem_avail]; + let signal_sems = [*sem_finish]; + let submit_info = vk::SubmitInfo::default() + .command_buffers(&cmd_bufs) + .wait_semaphores(&wait_sems) + .wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]) + .signal_semaphores(&signal_sems); + unsafe { + dev.queue_submit(*queue, &[submit_info], *fence) + .expect("Failed to submit queue"); + } +} + +fn queue_present( + swapchain_loader: &swapchain::Device, + queue: &vk::Queue, + swapchain: &vk::SwapchainKHR, + img_inx: u32, + sem_finish: &vk::Semaphore, +) { + let swapchains = [*swapchain]; + let img_inxs = [img_inx]; + let wait_sems = [*sem_finish]; + let present_info = vk::PresentInfoKHR::default() + .swapchains(&swapchains) + .image_indices(&img_inxs) + .wait_semaphores(&wait_sems); + unsafe { + swapchain_loader + .queue_present(*queue, &present_info) + .expect("Failed to present queue"); + } +} + +#[derive(Debug)] +struct Vector3 { + x: f32, + y: f32, + z: f32, +} + +#[derive(Debug)] +struct Camera { + origin: Vector3, + rotation: Vector3, +} + +fn handle_key(keycode: Keycode, camera: &mut Camera) { + let mov_scale = 0.01; + let rot_scale = 0.01; + match keycode { + Keycode::W => { + camera.origin.x -= -camera.rotation.y.sin() * mov_scale; + camera.origin.z -= camera.rotation.y.cos() * mov_scale; + } + Keycode::S => { + camera.origin.x += -camera.rotation.y.sin() * mov_scale; + camera.origin.z += camera.rotation.y.cos() * mov_scale; + } + Keycode::A => { + camera.origin.x += camera.rotation.y.cos() * mov_scale; + camera.origin.z += camera.rotation.y.sin() * mov_scale; + } + Keycode::D => { + camera.origin.z -= camera.rotation.y.sin() * mov_scale; + camera.origin.x -= camera.rotation.y.cos() * mov_scale; + } + Keycode::R => { + camera.rotation.x += rot_scale; + } + Keycode::F => { + camera.rotation.x -= rot_scale; + } + Keycode::Q => { + camera.rotation.y += rot_scale; + } + Keycode::E => { + camera.rotation.y -= rot_scale; + } + Keycode::Space => { + camera.origin.y += mov_scale; + } + Keycode::LShift => { + camera.origin.y -= mov_scale; + } + _ => {} + } +} + fn main() { let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); @@ -659,7 +1010,12 @@ fn main() { let rcs_queue_inx = find_rcs_queue_inx(&instance, &pdev).expect("No RCS queue found"); - let dev = make_dev(&instance, &pdev, rcs_queue_inx, vec![c"VK_KHR_swapchain", c"VK_EXT_extended_dynamic_state3"]); + let dev = make_dev( + &instance, + &pdev, + rcs_queue_inx, + vec![c"VK_KHR_swapchain", c"VK_EXT_extended_dynamic_state3"], + ); let queue = unsafe { dev.get_device_queue(rcs_queue_inx, 0) }; @@ -725,7 +1081,10 @@ fn main() { .expect("Failed to create fragment shader module") }; - let pipe = setup_pipeline(&dev, &vert_shader, &frag_shader); + let pass = setup_render_pass(&dev); + + let pipe_layout = setup_pipe_layout(&dev); + let pipe = setup_pipeline(&dev, &vert_shader, &frag_shader, &pass, &pipe_layout); let surface_loader = surface::Instance::new(&entry, &instance); let swapchain_loader = swapchain::Device::new(&instance, &dev); @@ -744,4 +1103,81 @@ fn main() { let swap_images = make_swap_images(&dev, &swapchain, &swapchain_loader); let swap_views = make_swap_views(&dev, &swap_images, vk::Format::B8G8R8A8_UNORM); + + let depth_view = make_depth_view(&dev, &depth_img, vk::Format::D32_SFLOAT); + + let framebufs = make_framebufs(&dev, &swap_views, &depth_view, &pass, width, height); + + let desc_sets = make_desc_sets(&dev, &desc_pool); + + write_desc_sets(&dev, &desc_sets, &mesh_buf); + + let sem_avail = make_sem(&dev); + let sem_finish = make_sem(&dev); + let fence_flight = make_fence(&dev); + + let mut event_pump = sdl_context.event_pump().expect("Failed to get event pump"); + let mut camera = Camera { + origin: Vector3 { + x: 0.0, + y: 0.0, + z: 0.0, + }, + rotation: Vector3 { + x: 0.0, + y: 0.0, + z: 0.0, + }, + }; + + let mut running = true; + while running { + for event in event_pump.poll_iter() { + match event { + Event::Quit { .. } => running = false, + Event::KeyDown { + keycode: Some(keycode), + .. + } => handle_key(keycode, &mut camera), + _ => {} + } + } + wait_for_fence(&dev, &fence_flight); + reset_fence(&dev, &fence_flight); + + let img_inx = ack_next_img( + &dev, + &swapchain_loader, + &swapchain, + &sem_avail, + &fence_flight, + ); + + start_cmd_buf(&dev, &cmd_buf); + + record_commands( + &dev, + &cmd_buf, + &framebufs[img_inx as usize], + &pass, + &pipe_layout, + width, + height, + &pipe, + &desc_sets, + &camera, + ); + end_cmd_buf(&dev, &cmd_buf); + + submit_queue( + &dev, + &queue, + &cmd_buf, + &sem_avail, + &sem_finish, + &fence_flight, + ); + + queue_present(&swapchain_loader, &queue, &swapchain, img_inx, &sem_finish); + } }