Add fix-function pipeline steps, and set up the render pass

This commit is contained in:
Timothy Warren 2023-04-07 10:03:59 -04:00
parent 6f9d56d370
commit 2ea377d91f
2 changed files with 155 additions and 40 deletions

View File

@ -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<vk::Image>,
swapchain_image_views: Vec<vk::ImageView>,
render_pass: vk::RenderPass,
pipeline_layout: vk::PipelineLayout,
}
impl AppData {}

View File

@ -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);