use anyhow::Result; use vulkanalia::prelude::v1_0::*; use vulkanalia::Device; use crate::app::AppData; use crate::shader::create_shader_module; use crate::vertex::{InstanceData, Vertex}; pub(crate) unsafe fn create_pipeline(device: &Device, data: &mut AppData) -> Result<()> { let vert_push_constant_range = vk::PushConstantRange::builder() .stage_flags(vk::ShaderStageFlags::VERTEX) .offset(0) .size(64 /* 16 × 4 byte floats */); let frag_push_constant_range = vk::PushConstantRange::builder() .stage_flags(vk::ShaderStageFlags::FRAGMENT) .offset(64) .size(4); let set_layouts = &[data.descriptor_set_layout]; let push_constant_ranges = &[vert_push_constant_range, frag_push_constant_range]; let layout_info = vk::PipelineLayoutCreateInfo::builder() .set_layouts(set_layouts) .push_constant_ranges(push_constant_ranges); data.pipeline_layout = device.create_pipeline_layout(&layout_info, None)?; let vert_shader_module = create_shader_module(device, "vert".to_owned())?; let frag_shader_module = create_shader_module(device, "frag".to_owned())?; let vert_stage = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::VERTEX) .module(vert_shader_module) .name(b"main\0"); let frag_stage = vk::PipelineShaderStageCreateInfo::builder() .stage(vk::ShaderStageFlags::FRAGMENT) .module(frag_shader_module) .name(b"main\0"); let binding_descriptions = &[ Vertex::binding_description(), InstanceData::binding_description(), ]; let mut attribute_descriptions: Vec = Vec::new(); attribute_descriptions.extend(&Vertex::attribute_descriptions()); attribute_descriptions.extend(&InstanceData::attribute_descriptions()); let vertex_input_state = vk::PipelineVertexInputStateCreateInfo::builder() .vertex_binding_descriptions(binding_descriptions) .vertex_attribute_descriptions(&attribute_descriptions); 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::COUNTER_CLOCKWISE) .depth_bias_enable(false); let multisample_state = vk::PipelineMultisampleStateCreateInfo::builder() .sample_shading_enable(data.setting_sample_shading) .rasterization_samples(data.msaa_samples); let attachment = vk::PipelineColorBlendAttachmentState::builder() .color_write_mask(vk::ColorComponentFlags::all()) .blend_enable(true) .src_color_blend_factor(vk::BlendFactor::SRC_ALPHA) .dst_color_blend_factor(vk::BlendFactor::ONE_MINUS_SRC_ALPHA) .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); // for transparency we need to change the blend factors to SRC_ALPHA and ONE_MINUS_SRC_ALPHA 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 depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::builder() .depth_test_enable(true) .depth_write_enable(true) .depth_compare_op(vk::CompareOp::LESS) .depth_bounds_test_enable(false) .stencil_test_enable(false); let stages = &[vert_stage, frag_stage]; let info = vk::GraphicsPipelineCreateInfo::builder() .stages(stages) .vertex_input_state(&vertex_input_state) .input_assembly_state(&input_assembly_state) .viewport_state(&viewport_state) .rasterization_state(&rasterization_state) .multisample_state(&multisample_state) .depth_stencil_state(&depth_stencil_state) .color_blend_state(&color_blend_state) .layout(data.pipeline_layout) .render_pass(data.render_pass) .subpass(0); data.pipeline = device .create_graphics_pipelines(vk::PipelineCache::null(), &[info], None)? .0; device.destroy_shader_module(vert_shader_module, None); device.destroy_shader_module(frag_shader_module, None); Ok(()) }