From 9ac0d69f7312e62b4e32d6fa36507e343a0f4d88 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 25 Apr 2023 09:39:50 -0400 Subject: [PATCH] Add multisample antialiasing --- src/app/data.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 8 deletions(-) diff --git a/src/app/data.rs b/src/app/data.rs index 7b6c594..01cde9f 100644 --- a/src/app/data.rs +++ b/src/app/data.rs @@ -47,6 +47,7 @@ pub(crate) struct AppData { pub(super) surface: vk::SurfaceKHR, // Physical Device / Logical Device physical_device: vk::PhysicalDevice, + msaa_samples: vk::SampleCountFlags, pub(super) graphics_queue: vk::Queue, pub(super) present_queue: vk::Queue, // Swapchain @@ -64,6 +65,10 @@ pub(crate) struct AppData { framebuffers: Vec, // Command Pool command_pool: vk::CommandPool, + // Color + color_image: vk::Image, + color_image_memory: vk::DeviceMemory, + color_image_view: vk::ImageView, // Depth depth_image: vk::Image, depth_image_memory: vk::DeviceMemory, @@ -117,6 +122,7 @@ impl AppData { self.create_descriptor_set_layout(&device)?; self.create_pipeline(&device)?; self.create_command_pool(&instance, &device)?; + self.create_color_objects(&instance, &device)?; self.create_depth_objects(&instance, &device)?; self.create_framebuffers(&device)?; self.create_texture_image(&instance, &device)?; @@ -256,6 +262,9 @@ impl AppData { /// # Safety /// Here be Dragons unsafe fn destroy_swapchain(&mut self, device: &Device) { + device.destroy_image_view(self.color_image_view, None); + device.free_memory(self.color_image_memory, None); + device.destroy_image(self.color_image, None); device.destroy_descriptor_pool(self.descriptor_pool, None); self.uniform_buffers .iter() @@ -296,6 +305,7 @@ impl AppData { } else { info!("Selected physical device (`{}`).", properties.device_name); self.physical_device = physical_device; + self.msaa_samples = self.get_max_msaa_samples(instance); return Ok(()); } } @@ -323,6 +333,25 @@ impl AppData { Ok(()) } + + unsafe fn get_max_msaa_samples(&self, instance: &Instance) -> vk::SampleCountFlags { + let properties = instance.get_physical_device_properties(self.physical_device); + let counts = properties.limits.framebuffer_color_sample_counts + & properties.limits.framebuffer_depth_sample_counts; + + [ + vk::SampleCountFlags::_64, + vk::SampleCountFlags::_32, + vk::SampleCountFlags::_16, + vk::SampleCountFlags::_8, + vk::SampleCountFlags::_4, + vk::SampleCountFlags::_2, + ] + .iter() + .cloned() + .find(|c| counts.contains(*c)) + .unwrap_or(vk::SampleCountFlags::_1) + } } unsafe fn check_physical_device_extensions( @@ -482,6 +511,7 @@ impl AppData { self.create_swapchain_image_views(device)?; self.create_render_pass(instance, device)?; self.create_pipeline(device)?; + self.create_color_objects(instance, device)?; self.create_depth_objects(instance, device)?; self.create_framebuffers(device)?; self.create_uniform_buffers(instance, device)?; @@ -561,17 +591,17 @@ impl AppData { unsafe fn create_render_pass(&mut self, instance: &Instance, device: &Device) -> Result<()> { let color_attachment = vk::AttachmentDescription::builder() .format(self.swapchain_format) - .samples(vk::SampleCountFlags::_1) + .samples(self.msaa_samples) .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); + .final_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); let depth_stencil_attachment = vk::AttachmentDescription::builder() .format(self.get_depth_format(instance)?) - .samples(vk::SampleCountFlags::_1) + .samples(self.msaa_samples) .load_op(vk::AttachmentLoadOp::CLEAR) .store_op(vk::AttachmentStoreOp::DONT_CARE) .stencil_load_op(vk::AttachmentLoadOp::DONT_CARE) @@ -579,6 +609,16 @@ impl AppData { .initial_layout(vk::ImageLayout::UNDEFINED) .final_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + let color_resolve_attachment = vk::AttachmentDescription::builder() + .format(self.swapchain_format) + .samples(vk::SampleCountFlags::_1) + .load_op(vk::AttachmentLoadOp::DONT_CARE) + .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) @@ -586,11 +626,16 @@ impl AppData { let depth_stencil_attachment_ref = vk::AttachmentReference::builder() .attachment(1) .layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + let color_resolve_attachment_ref = vk::AttachmentReference::builder() + .attachment(2) + .layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL); let color_attachments = &[color_attachment_ref]; + let resolve_attachments = &[color_resolve_attachment_ref]; let subpass = vk::SubpassDescription::builder() .pipeline_bind_point(vk::PipelineBindPoint::GRAPHICS) .color_attachments(color_attachments) - .depth_stencil_attachment(&depth_stencil_attachment_ref); + .depth_stencil_attachment(&depth_stencil_attachment_ref) + .resolve_attachments(resolve_attachments); let dependency = vk::SubpassDependency::builder() .src_subpass(vk::SUBPASS_EXTERNAL) .dst_subpass(0) @@ -608,7 +653,11 @@ impl AppData { | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, ); - let attachments = &[color_attachment, depth_stencil_attachment]; + let attachments = &[ + color_attachment, + depth_stencil_attachment, + color_resolve_attachment, + ]; let subpasses = &[subpass]; let dependencies = &[dependency]; let info = vk::RenderPassCreateInfo::builder() @@ -698,7 +747,7 @@ impl AppData { let multisample_state = vk::PipelineMultisampleStateCreateInfo::builder() .sample_shading_enable(false) - .rasterization_samples(vk::SampleCountFlags::_1); + .rasterization_samples(self.msaa_samples); let depth_stencil_state = vk::PipelineDepthStencilStateCreateInfo::builder() .depth_test_enable(true) @@ -777,7 +826,7 @@ impl AppData { .swapchain_image_views .iter() .map(|i| { - let attachments = &[*i, self.depth_image_view]; + let attachments = &[self.color_image_view, self.depth_image_view, *i]; let create_info = vk::FramebufferCreateInfo::builder() .render_pass(self.render_pass) .attachments(attachments) @@ -810,6 +859,40 @@ impl AppData { } } +//================================================ +// Color Objects +//================================================ + +impl AppData { + unsafe fn create_color_objects(&mut self, instance: &Instance, device: &Device) -> Result<()> { + let (color_image, color_image_memory) = self.create_image( + instance, + device, + self.swapchain_extent.width, + self.swapchain_extent.height, + 1, + self.msaa_samples, + self.swapchain_format, + vk::ImageTiling::OPTIMAL, + vk::ImageUsageFlags::COLOR_ATTACHMENT | vk::ImageUsageFlags::TRANSIENT_ATTACHMENT, + vk::MemoryPropertyFlags::DEVICE_LOCAL, + )?; + + self.color_image = color_image; + self.color_image_memory = color_image_memory; + + self.color_image_view = create_image_view( + device, + self.color_image, + self.swapchain_format, + vk::ImageAspectFlags::COLOR, + 1, + )?; + + Ok(()) + } +} + //================================================ // Depth Objects //================================================ @@ -823,6 +906,7 @@ impl AppData { self.swapchain_extent.width, self.swapchain_extent.height, 1, + self.msaa_samples, format, vk::ImageTiling::OPTIMAL, vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT, @@ -928,6 +1012,7 @@ impl AppData { width, height, self.mip_levels, + vk::SampleCountFlags::_1, vk::Format::R8G8B8A8_SRGB, vk::ImageTiling::OPTIMAL, vk::ImageUsageFlags::SAMPLED @@ -1530,6 +1615,7 @@ impl AppData { width: u32, height: u32, mip_levels: u32, + samples: vk::SampleCountFlags, format: vk::Format, tiling: vk::ImageTiling, usage: vk::ImageUsageFlags, @@ -1548,7 +1634,7 @@ impl AppData { .tiling(tiling) .initial_layout(vk::ImageLayout::UNDEFINED) .usage(usage) - .samples(vk::SampleCountFlags::_1) + .samples(samples) .sharing_mode(vk::SharingMode::EXCLUSIVE); let image = device.create_image(&info, None)?;