diff --git a/src/app.rs b/src/app.rs index 377a9df..ad448c3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,6 @@ mod functions; use functions::{ - create_instance, create_logical_device, create_pipeline, create_swapchain, + create_instance, create_logical_device, create_pipeline, create_render_pass, create_swapchain, create_swapchain_image_views, pick_physical_device, }; @@ -42,6 +42,7 @@ impl App { create_swapchain(window, &instance, &device, &mut data)?; create_swapchain_image_views(&device, &mut data)?; + create_render_pass(&instance, &device, &mut data)?; create_pipeline(&device, &mut data)?; Ok(Self { @@ -59,6 +60,9 @@ impl App { /// Destroys our Vulkan app. pub unsafe fn destroy(&mut self) { + self.device + .destroy_pipeline_layout(self.data.pipeline_layout, None); + self.device.destroy_render_pass(self.data.render_pass, None); self.data .swapchain_image_views .iter() @@ -93,6 +97,8 @@ pub struct AppData { swapchain: vk::SwapchainKHR, swapchain_images: Vec, swapchain_image_views: Vec, + render_pass: vk::RenderPass, + pipeline_layout: vk::PipelineLayout, } impl AppData {} diff --git a/src/app/functions.rs b/src/app/functions.rs index 370af08..6150c91 100644 --- a/src/app/functions.rs +++ b/src/app/functions.rs @@ -32,6 +32,10 @@ extern "system" fn debug_callback( vk::FALSE } +//================================================ +// Physical Device +//================================================ + pub(super) unsafe fn create_instance( window: &Window, entry: &Entry, @@ -168,6 +172,10 @@ unsafe fn check_physical_device_extensions( } } +//================================================ +// Logical Device +//================================================ + pub(super) unsafe fn create_logical_device( instance: &Instance, data: &mut AppData, @@ -230,45 +238,9 @@ pub(super) unsafe fn create_logical_device( Ok(device) } -fn get_swapchain_surface_format(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR { - formats - .iter() - .cloned() - .find(|f| { - f.format == vk::Format::B8G8R8A8_SRGB - && f.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR - }) - .unwrap_or_else(|| formats[0]) -} - -fn get_swapchain_present_mode(present_modes: &[vk::PresentModeKHR]) -> vk::PresentModeKHR { - present_modes - .iter() - .cloned() - .find(|m| *m == vk::PresentModeKHR::MAILBOX) - .unwrap_or(vk::PresentModeKHR::FIFO) -} - -fn get_swapchain_extent(window: &Window, capabilities: vk::SurfaceCapabilitiesKHR) -> vk::Extent2D { - if capabilities.current_extent.width != u32::MAX { - capabilities.current_extent - } else { - let size = window.inner_size(); - let clamp = |min: u32, max: u32, v: u32| min.max(max.min(v)); - vk::Extent2D::builder() - .width(clamp( - capabilities.min_image_extent.width, - capabilities.max_image_extent.width, - size.width, - )) - .height(clamp( - capabilities.min_image_extent.height, - capabilities.max_image_extent.height, - size.height, - )) - .build() - } -} +//================================================ +// Swapchain +//================================================ pub(super) unsafe fn create_swapchain( window: &Window, @@ -323,6 +295,46 @@ pub(super) unsafe fn create_swapchain( Ok(()) } +fn get_swapchain_surface_format(formats: &[vk::SurfaceFormatKHR]) -> vk::SurfaceFormatKHR { + formats + .iter() + .cloned() + .find(|f| { + f.format == vk::Format::B8G8R8A8_SRGB + && f.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR + }) + .unwrap_or_else(|| formats[0]) +} + +fn get_swapchain_present_mode(present_modes: &[vk::PresentModeKHR]) -> vk::PresentModeKHR { + present_modes + .iter() + .cloned() + .find(|m| *m == vk::PresentModeKHR::MAILBOX) + .unwrap_or(vk::PresentModeKHR::FIFO) +} + +fn get_swapchain_extent(window: &Window, capabilities: vk::SurfaceCapabilitiesKHR) -> vk::Extent2D { + if capabilities.current_extent.width != u32::MAX { + capabilities.current_extent + } else { + let size = window.inner_size(); + let clamp = |min: u32, max: u32, v: u32| min.max(max.min(v)); + vk::Extent2D::builder() + .width(clamp( + capabilities.min_image_extent.width, + capabilities.max_image_extent.width, + size.width, + )) + .height(clamp( + capabilities.min_image_extent.height, + capabilities.max_image_extent.height, + size.height, + )) + .build() + } +} + pub(super) unsafe fn create_swapchain_image_views( device: &Device, data: &mut AppData, @@ -358,6 +370,45 @@ pub(super) unsafe fn create_swapchain_image_views( Ok(()) } +//================================================ +// Pipeline +//================================================ + +pub(super) unsafe fn create_render_pass( + instance: &Instance, + device: &Device, + data: &mut AppData, +) -> Result<()> { + let color_attachment = vk::AttachmentDescription::builder() + .format(data.swapchain_format) + .samples(vk::SampleCountFlags::_1) + .load_op(vk::AttachmentLoadOp::CLEAR) + .store_op(vk::AttachmentStoreOp::STORE) + .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) + .stencil_store_op(vk::AttachmentStoreOp::DONT_CARE) + .initial_layout(vk::ImageLayout::UNDEFINED) + .final_layout(vk::ImageLayout::PRESENT_SRC_KHR); + + // Subpasses + let color_attachment_ref = vk::AttachmentReference::builder() + .attachment(0) + .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); + let color_attachments = &[color_attachment_ref]; + let subpass = vk::SubpassDescription::builder() + .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) + .color_attachments(color_attachments); + + let attachments = &[color_attachment]; + let subpasses = &[subpass]; + let info = vk::RenderPassCreateInfo::builder() + .attachments(attachments) + .subpasses(subpasses); + + data.render_pass = device.create_render_pass(&info, None)?; + + Ok(()) +} + pub(super) unsafe fn create_pipeline(device: &Device, data: &mut AppData) -> Result<()> { let vert = include_bytes!("../../shaders/vert.spv"); let frag = include_bytes!("../../shaders/frag.spv"); @@ -375,6 +426,64 @@ pub(super) unsafe fn create_pipeline(device: &Device, data: &mut AppData) -> Res .module(frag_shader_module) .name(b"main\0"); + let vertex_input_state = vk::PipelineVertexInputStateCreateInfo::builder(); + + let input_assembly_state = vk::PipelineInputAssemblyStateCreateInfo::builder() + .topology(vk::PrimitiveTopology::TRIANGLE_LIST) + .primitive_restart_enable(false); + + let viewport = vk::Viewport::builder() + .x(0.0) + .y(0.0) + .width(data.swapchain_extent.width as f32) + .height(data.swapchain_extent.height as f32) + .min_depth(0.0) + .max_depth(1.0); + + let scissor = vk::Rect2D::builder() + .offset(vk::Offset2D { x: 0, y: 0 }) + .extent(data.swapchain_extent); + + let viewports = &[viewport]; + let scissors = &[scissor]; + let viewport_state = vk::PipelineViewportStateCreateInfo::builder() + .viewports(viewports) + .scissors(scissors); + + let rasterization_state = vk::PipelineRasterizationStateCreateInfo::builder() + .depth_clamp_enable(false) + .rasterizer_discard_enable(false) + .polygon_mode(vk::PolygonMode::FILL) + .line_width(1.0) + .cull_mode(vk::CullModeFlags::BACK) + .front_face(vk::FrontFace::CLOCKWISE) + .depth_bias_enable(false); + + let multisample_state = vk::PipelineMultisampleStateCreateInfo::builder() + .sample_shading_enable(false) + .rasterization_samples(vk::SampleCountFlags::_1); + + let attachment = vk::PipelineColorBlendAttachmentState::builder() + .color_write_mask(vk::ColorComponentFlags::all()) + .blend_enable(false) + .src_color_blend_factor(vk::BlendFactor::ONE) + .dst_color_blend_factor(vk::BlendFactor::ZERO) + .color_blend_op(vk::BlendOp::ADD) + .src_alpha_blend_factor(vk::BlendFactor::ONE) + .dst_alpha_blend_factor(vk::BlendFactor::ZERO) + .alpha_blend_op(vk::BlendOp::ADD); + + let attachments = &[attachment]; + let color_blend_state = vk::PipelineColorBlendStateCreateInfo::builder() + .logic_op_enable(false) + .logic_op(vk::LogicOp::COPY) + .attachments(attachments) + .blend_constants([0.0, 0.0, 0.0, 0.0]); + + let layout_info = vk::PipelineLayoutCreateInfo::builder(); + data.pipeline_layout = device.create_pipeline_layout(&layout_info, None)?; + + // Cleanup device.destroy_shader_module(vert_shader_module, None); device.destroy_shader_module(frag_shader_module, None);